From d36ce782b757a2405e87061316fe054af889545c Mon Sep 17 00:00:00 2001 From: Will Date: Thu, 4 Sep 2025 18:32:51 +0800 Subject: [PATCH 01/52] fix: update account profile (#25150) --- api/services/account_service.py | 1 + 1 file changed, 1 insertion(+) diff --git a/api/services/account_service.py b/api/services/account_service.py index b12d4623bb..9a9dd04bbe 100644 --- a/api/services/account_service.py +++ b/api/services/account_service.py @@ -351,6 +351,7 @@ class AccountService: @staticmethod def update_account(account, **kwargs): """Update account fields""" + account = db.session.merge(account) for field, value in kwargs.items(): if hasattr(account, field): setattr(account, field, value) From de768af099c90d0c694dc67269e5da3c5d99bd0c Mon Sep 17 00:00:00 2001 From: Will Date: Thu, 4 Sep 2025 20:34:56 +0800 Subject: [PATCH 02/52] fix: reset password (#25172) --- api/services/account_service.py | 1 + 1 file changed, 1 insertion(+) diff --git a/api/services/account_service.py b/api/services/account_service.py index 9a9dd04bbe..660c80ebfc 100644 --- a/api/services/account_service.py +++ b/api/services/account_service.py @@ -214,6 +214,7 @@ class AccountService: base64_password_hashed = base64.b64encode(password_hashed).decode() account.password = base64_password_hashed account.password_salt = base64_salt + db.session.add(account) db.session.commit() return account From 334218a62ce2c9b61cecb5cc58c6b130af45cbea Mon Sep 17 00:00:00 2001 From: Yongtao Huang Date: Fri, 5 Sep 2025 00:22:38 +0800 Subject: [PATCH 03/52] Remove unused mypy script (#25177) --- api/mypy.ini | 25 ------------------------- dev/mypy-check | 10 ---------- 2 files changed, 35 deletions(-) delete mode 100644 api/mypy.ini delete mode 100755 dev/mypy-check diff --git a/api/mypy.ini b/api/mypy.ini deleted file mode 100644 index bd771a056f..0000000000 --- a/api/mypy.ini +++ /dev/null @@ -1,25 +0,0 @@ -[mypy] -warn_return_any = True -warn_unused_configs = True -check_untyped_defs = True -cache_fine_grained = True -sqlite_cache = True -exclude = (?x)( - tests/ - | migrations/ - ) - -[mypy-flask_login] -ignore_missing_imports=True - -[mypy-flask_restx] -ignore_missing_imports=True - -[mypy-flask_restx.api] -ignore_missing_imports=True - -[mypy-flask_restx.inputs] -ignore_missing_imports=True - -[mypy-google.cloud.storage] -ignore_missing_imports=True diff --git a/dev/mypy-check b/dev/mypy-check deleted file mode 100755 index 8a2342730c..0000000000 --- a/dev/mypy-check +++ /dev/null @@ -1,10 +0,0 @@ -#!/bin/bash - -set -x - -SCRIPT_DIR="$(dirname "$(realpath "$0")")" -cd "$SCRIPT_DIR/.." - -# run mypy checks -uv run --directory api --dev --with pip \ - python -m mypy --install-types --non-interactive --exclude venv ./ From 15b3443e9e03971689368d09c226e3528b145c2d Mon Sep 17 00:00:00 2001 From: -LAN- Date: Fri, 5 Sep 2025 01:52:19 +0800 Subject: [PATCH 04/52] fix(debug_logging_layer): remove access for variable pool --- .../workflow/graph_engine/layers/debug_logging.py | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/api/core/workflow/graph_engine/layers/debug_logging.py b/api/core/workflow/graph_engine/layers/debug_logging.py index ddfdfa0edd..f24c3fe33c 100644 --- a/api/core/workflow/graph_engine/layers/debug_logging.py +++ b/api/core/workflow/graph_engine/layers/debug_logging.py @@ -113,17 +113,6 @@ class DebugLoggingLayer(GraphEngineLayer): # Log initial state self.logger.info("Initial State:") - # Log inputs if available - if self.graph_runtime_state.variable_pool: - initial_vars: dict[str, Any] = {} - # Access the variable dictionary directly - for node_id, variables in self.graph_runtime_state.variable_pool.variable_dictionary.items(): - for var_key, var in variables.items(): - initial_vars[f"{node_id}.{var_key}"] = str(var.value) if hasattr(var, "value") else str(var) - - if initial_vars: - self.logger.info(" Initial variables: %s", self._format_dict(initial_vars)) - @override def on_event(self, event: GraphEngineEvent) -> None: """Log individual events based on their type.""" From 103a9a4e6730f7c82aaa26f8ac6263ad4b323445 Mon Sep 17 00:00:00 2001 From: -LAN- Date: Fri, 5 Sep 2025 01:59:11 +0800 Subject: [PATCH 05/52] fix(graph_engine): add type hint for workers_to_remove --- api/core/workflow/graph_engine/worker_management/worker_pool.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api/core/workflow/graph_engine/worker_management/worker_pool.py b/api/core/workflow/graph_engine/worker_management/worker_pool.py index 25671ce6ba..00328fbda1 100644 --- a/api/core/workflow/graph_engine/worker_management/worker_pool.py +++ b/api/core/workflow/graph_engine/worker_management/worker_pool.py @@ -217,7 +217,7 @@ class WorkerPool: return False # Find and remove idle workers that have been idle long enough - workers_to_remove = [] + workers_to_remove: list[tuple[Worker, int]] = [] for worker in self._workers: # Check if worker is idle and has exceeded idle time threshold From 2adf5d0eee4a69793a1f5202d94a0c59b7651a87 Mon Sep 17 00:00:00 2001 From: -LAN- Date: Fri, 5 Sep 2025 02:09:53 +0800 Subject: [PATCH 06/52] docs: remove outdated document --- api/core/workflow/docs/WORKER_POOL_CONFIG.md | 173 ------------------- 1 file changed, 173 deletions(-) delete mode 100644 api/core/workflow/docs/WORKER_POOL_CONFIG.md diff --git a/api/core/workflow/docs/WORKER_POOL_CONFIG.md b/api/core/workflow/docs/WORKER_POOL_CONFIG.md deleted file mode 100644 index db4cf3b6d6..0000000000 --- a/api/core/workflow/docs/WORKER_POOL_CONFIG.md +++ /dev/null @@ -1,173 +0,0 @@ -# GraphEngine Worker Pool Configuration - -## Overview - -The GraphEngine now supports **dynamic worker pool management** to optimize performance and resource usage. Instead of a fixed 10-worker pool, the engine can: - -1. **Start with optimal worker count** based on graph complexity -1. **Scale up** when workload increases -1. **Scale down** when workers are idle -1. **Respect configurable min/max limits** - -## Benefits - -- **Resource Efficiency**: Uses fewer workers for simple sequential workflows -- **Better Performance**: Scales up for parallel-heavy workflows -- **Gevent Optimization**: Works efficiently with Gevent's greenlet model -- **Memory Savings**: Reduces memory footprint for simple workflows - -## Configuration - -### Configuration Variables (via dify_config) - -| Variable | Default | Description | -|----------|---------|-------------| -| `GRAPH_ENGINE_MIN_WORKERS` | 1 | Minimum number of workers per engine | -| `GRAPH_ENGINE_MAX_WORKERS` | 10 | Maximum number of workers per engine | -| `GRAPH_ENGINE_SCALE_UP_THRESHOLD` | 3 | Queue depth that triggers scale up | -| `GRAPH_ENGINE_SCALE_DOWN_IDLE_TIME` | 5.0 | Seconds of idle time before scaling down | - -### Example Configurations - -#### Low-Resource Environment - -```bash -export GRAPH_ENGINE_MIN_WORKERS=1 -export GRAPH_ENGINE_MAX_WORKERS=3 -export GRAPH_ENGINE_SCALE_UP_THRESHOLD=2 -export GRAPH_ENGINE_SCALE_DOWN_IDLE_TIME=3.0 -``` - -#### High-Performance Environment - -```bash -export GRAPH_ENGINE_MIN_WORKERS=2 -export GRAPH_ENGINE_MAX_WORKERS=20 -export GRAPH_ENGINE_SCALE_UP_THRESHOLD=5 -export GRAPH_ENGINE_SCALE_DOWN_IDLE_TIME=10.0 -``` - -#### Default (Balanced) - -```bash -# Uses defaults: min=1, max=10, threshold=3, idle_time=5.0 -``` - -## How It Works - -### Initial Worker Calculation - -The engine analyzes the graph structure at startup: - -- **Sequential graphs** (no branches): 1 worker -- **Limited parallelism** (few branches): 2 workers -- **Moderate parallelism**: 3 workers -- **High parallelism** (many branches): 5 workers - -### Dynamic Scaling - -During execution: - -1. **Scale Up** triggers when: - - - Queue depth exceeds `SCALE_UP_THRESHOLD` - - All workers are busy and queue has items - - Not at `MAX_WORKERS` limit - -1. **Scale Down** triggers when: - - - Worker idle for more than `SCALE_DOWN_IDLE_TIME` seconds - - Above `MIN_WORKERS` limit - -### Gevent Compatibility - -Since Gevent patches threading to use greenlets: - -- Workers are lightweight coroutines, not OS threads -- Dynamic scaling has minimal overhead -- Can efficiently handle many concurrent workers - -## Migration Guide - -### Before (Fixed 10 Workers) - -```python -# Every GraphEngine instance created 10 workers -# Resource waste for simple workflows -# No adaptation to workload -``` - -### After (Dynamic Workers) - -```python -# GraphEngine creates 1-5 initial workers based on graph -# Scales up/down based on workload -# Configurable via environment variables -``` - -### Backward Compatibility - -The default configuration (`max=10`) maintains compatibility with existing deployments. To get the old behavior exactly: - -```bash -export GRAPH_ENGINE_MIN_WORKERS=10 -export GRAPH_ENGINE_MAX_WORKERS=10 -``` - -## Performance Impact - -### Memory Usage - -- **Simple workflows**: ~80% reduction (1 vs 10 workers) -- **Complex workflows**: Similar or slightly better - -### Execution Time - -- **Sequential workflows**: No change -- **Parallel workflows**: Improved with proper scaling -- **Bursty workloads**: Better adaptation - -### Example Metrics - -| Workflow Type | Old (10 workers) | New (Dynamic) | Improvement | -|--------------|------------------|---------------|-------------| -| Sequential | 10 workers idle | 1 worker active | 90% fewer workers | -| 3-way parallel | 7 workers idle | 3 workers active | 70% fewer workers | -| Heavy parallel | 10 workers busy | 10+ workers (scales up) | Better throughput | - -## Monitoring - -Log messages indicate scaling activity: - -```shell -INFO: GraphEngine initialized with 2 workers (min: 1, max: 10) -INFO: Scaled up workers: 2 -> 3 (queue_depth: 4) -INFO: Scaled down workers: 3 -> 2 (removed 1 idle workers) -``` - -## Best Practices - -1. **Start with defaults** - They work well for most cases -1. **Monitor queue depth** - Adjust `SCALE_UP_THRESHOLD` if queues back up -1. **Consider workload patterns**: - - Bursty: Lower `SCALE_DOWN_IDLE_TIME` - - Steady: Higher `SCALE_DOWN_IDLE_TIME` -1. **Test with your workloads** - Measure and tune - -## Troubleshooting - -### Workers not scaling up - -- Check `GRAPH_ENGINE_MAX_WORKERS` limit -- Verify queue depth exceeds threshold -- Check logs for scaling messages - -### Workers scaling down too quickly - -- Increase `GRAPH_ENGINE_SCALE_DOWN_IDLE_TIME` -- Consider workload patterns - -### Out of memory - -- Reduce `GRAPH_ENGINE_MAX_WORKERS` -- Check for memory leaks in nodes From a2e0f80c0186c2bc849342b970a1f624d1fc7fd4 Mon Sep 17 00:00:00 2001 From: -LAN- Date: Fri, 5 Sep 2025 08:34:18 +0800 Subject: [PATCH 07/52] [Chore/Refactor] Improve type checking configuration (#25185) Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com> --- .github/workflows/style.yml | 4 ++ api/app_factory.py | 3 + api/core/plugin/utils/chunk_merger.py | 4 +- api/core/tools/tool_manager.py | 2 +- api/pyproject.toml | 1 + api/pyrightconfig.json | 65 +++++++------------ api/services/dataset_service.py | 2 +- .../tools/builtin_tools_manage_service.py | 2 +- api/uv.lock | 37 +++++++++++ 9 files changed, 73 insertions(+), 47 deletions(-) diff --git a/.github/workflows/style.yml b/.github/workflows/style.yml index aaabec0cb5..73383ced13 100644 --- a/.github/workflows/style.yml +++ b/.github/workflows/style.yml @@ -48,6 +48,10 @@ jobs: if: steps.changed-files.outputs.any_changed == 'true' run: dev/basedpyright-check + - name: Run Mypy Type Checks + if: steps.changed-files.outputs.any_changed == 'true' + run: uv --directory api run mypy --exclude-gitignore --exclude 'tests/' --exclude 'migrations/' --check-untyped-defs --disable-error-code=import-untyped . + - name: Dotenv check if: steps.changed-files.outputs.any_changed == 'true' run: uv run --project api dotenv-linter ./api/.env.example ./web/.env.example diff --git a/api/app_factory.py b/api/app_factory.py index 8a0417dd72..17c376de77 100644 --- a/api/app_factory.py +++ b/api/app_factory.py @@ -25,6 +25,9 @@ def create_flask_app_with_configs() -> DifyApp: # add an unique identifier to each request RecyclableContextVar.increment_thread_recycles() + # Capture the decorator's return value to avoid pyright reportUnusedFunction + _ = before_request + return dify_app diff --git a/api/core/plugin/utils/chunk_merger.py b/api/core/plugin/utils/chunk_merger.py index 3fb4d5d9e2..21ca2d8d37 100644 --- a/api/core/plugin/utils/chunk_merger.py +++ b/api/core/plugin/utils/chunk_merger.py @@ -1,6 +1,6 @@ from collections.abc import Generator from dataclasses import dataclass, field -from typing import TypeVar, Union +from typing import TypeVar, Union, cast from core.agent.entities import AgentInvokeMessage from core.tools.entities.tool_entities import ToolInvokeMessage @@ -85,7 +85,7 @@ def merge_blob_chunks( message=ToolInvokeMessage.BlobMessage(blob=files[chunk_id].data[: files[chunk_id].bytes_written]), meta=resp.meta, ) - yield merged_message + yield cast(MessageType, merged_message) # Clean up the buffer del files[chunk_id] else: diff --git a/api/core/tools/tool_manager.py b/api/core/tools/tool_manager.py index 6dacaa0508..9897045d9b 100644 --- a/api/core/tools/tool_manager.py +++ b/api/core/tools/tool_manager.py @@ -642,7 +642,7 @@ class ToolManager: include_set=dify_config.POSITION_TOOL_INCLUDES_SET, exclude_set=dify_config.POSITION_TOOL_EXCLUDES_SET, data=provider, - name_func=lambda x: x.identity.name, + name_func=lambda x: x.entity.identity.name, ): continue user_provider = ToolTransformService.builtin_provider_to_user_provider( diff --git a/api/pyproject.toml b/api/pyproject.toml index 7416380fdb..8f5a6a44ac 100644 --- a/api/pyproject.toml +++ b/api/pyproject.toml @@ -166,6 +166,7 @@ dev = [ "types-python-http-client>=3.3.7.20240910", "types-redis>=4.6.0.20241004", "celery-types>=0.23.0", + "mypy~=1.17.1", ] ############################################################ diff --git a/api/pyrightconfig.json b/api/pyrightconfig.json index 80fd10558e..dfffdb8cff 100644 --- a/api/pyrightconfig.json +++ b/api/pyrightconfig.json @@ -1,47 +1,28 @@ { "include": ["."], - "exclude": ["tests/", "migrations/", ".venv/"], + "exclude": [ + "tests/", + "migrations/", + ".venv/", + "models/", + "core/", + "controllers/", + "tasks/", + "services/", + "schedule/", + "extensions/", + "utils/", + "repositories/", + "libs/", + "fields/", + "factories/", + "events/", + "contexts/", + "constants/", + "configs/", + "commands.py" + ], "typeCheckingMode": "strict", "pythonVersion": "3.11", - "pythonPlatform": "All", - "reportMissingTypeStubs": false, - "reportOptionalMemberAccess": "none", - "reportOptionalIterable": "none", - "reportOptionalOperand": "none", - "reportOptionalSubscript": "none", - "reportTypedDictNotRequiredAccess": "none", - "reportPrivateImportUsage": "none", - "reportUnsupportedDunderAll": "none", - "reportUnnecessaryTypeIgnoreComment": "none", - "reportMatchNotExhaustive": "none", - "reportImplicitOverride": "none", - "reportCallInDefaultInitializer": "none", - "reportUnnecessaryIsInstance": "none", - "reportUnnecessaryComparison": "none", - "reportUnknownParameterType": "none", - "reportMissingParameterType": "none", - "reportUnknownArgumentType": "none", - "reportUnknownVariableType": "none", - "reportUnknownMemberType": "none", - "reportMissingTypeArgument": "none", - "reportUntypedFunctionDecorator": "none", - "reportUnknownLambdaType": "none", - "reportPrivateUsage": "none", - "reportConstantRedefinition": "none", - "reportIncompatibleMethodOverride": "none", - "reportIncompatibleVariableOverride": "none", - "reportOverlappingOverload": "none", - "reportPossiblyUnboundVariable": "none", - "reportUnusedImport": "none", - "reportUnusedFunction": "none", - "reportArgumentType": "none", - "reportAssignmentType": "none", - "reportAttributeAccessIssue": "none", - "reportCallIssue": "none", - "reportIndexIssue": "none", - "reportRedeclaration": "none", - "reportReturnType": "none", - "reportOperatorIssue": "none", - "reportTypeCommentUsage": "none", - "reportDeprecated": "none" + "pythonPlatform": "All" } diff --git a/api/services/dataset_service.py b/api/services/dataset_service.py index a5550c7012..4b202001da 100644 --- a/api/services/dataset_service.py +++ b/api/services/dataset_service.py @@ -1198,7 +1198,7 @@ class DocumentService: "Invalid process rule mode: %s, can not find dataset process rule", process_rule.mode, ) - return + return [], "" db.session.add(dataset_process_rule) db.session.commit() lock_name = f"add_document_lock_dataset_id_{dataset.id}" diff --git a/api/services/tools/builtin_tools_manage_service.py b/api/services/tools/builtin_tools_manage_service.py index 71bc50017f..bce389b949 100644 --- a/api/services/tools/builtin_tools_manage_service.py +++ b/api/services/tools/builtin_tools_manage_service.py @@ -573,7 +573,7 @@ class BuiltinToolManageService: include_set=dify_config.POSITION_TOOL_INCLUDES_SET, # type: ignore exclude_set=dify_config.POSITION_TOOL_EXCLUDES_SET, # type: ignore data=provider_controller, - name_func=lambda x: x.identity.name, + name_func=lambda x: x.entity.identity.name, ): continue diff --git a/api/uv.lock b/api/uv.lock index 987dc7243d..1d872087c7 100644 --- a/api/uv.lock +++ b/api/uv.lock @@ -1357,6 +1357,7 @@ dev = [ { name = "faker" }, { name = "hypothesis" }, { name = "lxml-stubs" }, + { name = "mypy" }, { name = "pandas-stubs" }, { name = "pytest" }, { name = "pytest-benchmark" }, @@ -1547,6 +1548,7 @@ dev = [ { name = "faker", specifier = "~=32.1.0" }, { name = "hypothesis", specifier = ">=6.131.15" }, { name = "lxml-stubs", specifier = "~=0.5.1" }, + { name = "mypy", specifier = "~=1.17.1" }, { name = "pandas-stubs", specifier = "~=2.2.3" }, { name = "pytest", specifier = "~=8.3.2" }, { name = "pytest-benchmark", specifier = "~=4.0.0" }, @@ -3287,6 +3289,32 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/d8/30/9aec301e9772b098c1f5c0ca0279237c9766d94b97802e9888010c64b0ed/multidict-6.6.3-py3-none-any.whl", hash = "sha256:8db10f29c7541fc5da4defd8cd697e1ca429db743fa716325f236079b96f775a", size = 12313, upload-time = "2025-06-30T15:53:45.437Z" }, ] +[[package]] +name = "mypy" +version = "1.17.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "mypy-extensions" }, + { name = "pathspec" }, + { name = "typing-extensions" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/8e/22/ea637422dedf0bf36f3ef238eab4e455e2a0dcc3082b5cc067615347ab8e/mypy-1.17.1.tar.gz", hash = "sha256:25e01ec741ab5bb3eec8ba9cdb0f769230368a22c959c4937360efb89b7e9f01", size = 3352570, upload-time = "2025-07-31T07:54:19.204Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/46/cf/eadc80c4e0a70db1c08921dcc220357ba8ab2faecb4392e3cebeb10edbfa/mypy-1.17.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:ad37544be07c5d7fba814eb370e006df58fed8ad1ef33ed1649cb1889ba6ff58", size = 10921009, upload-time = "2025-07-31T07:53:23.037Z" }, + { url = "https://files.pythonhosted.org/packages/5d/c1/c869d8c067829ad30d9bdae051046561552516cfb3a14f7f0347b7d973ee/mypy-1.17.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:064e2ff508e5464b4bd807a7c1625bc5047c5022b85c70f030680e18f37273a5", size = 10047482, upload-time = "2025-07-31T07:53:26.151Z" }, + { url = "https://files.pythonhosted.org/packages/98/b9/803672bab3fe03cee2e14786ca056efda4bb511ea02dadcedde6176d06d0/mypy-1.17.1-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:70401bbabd2fa1aa7c43bb358f54037baf0586f41e83b0ae67dd0534fc64edfd", size = 11832883, upload-time = "2025-07-31T07:53:47.948Z" }, + { url = "https://files.pythonhosted.org/packages/88/fb/fcdac695beca66800918c18697b48833a9a6701de288452b6715a98cfee1/mypy-1.17.1-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:e92bdc656b7757c438660f775f872a669b8ff374edc4d18277d86b63edba6b8b", size = 12566215, upload-time = "2025-07-31T07:54:04.031Z" }, + { url = "https://files.pythonhosted.org/packages/7f/37/a932da3d3dace99ee8eb2043b6ab03b6768c36eb29a02f98f46c18c0da0e/mypy-1.17.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:c1fdf4abb29ed1cb091cf432979e162c208a5ac676ce35010373ff29247bcad5", size = 12751956, upload-time = "2025-07-31T07:53:36.263Z" }, + { url = "https://files.pythonhosted.org/packages/8c/cf/6438a429e0f2f5cab8bc83e53dbebfa666476f40ee322e13cac5e64b79e7/mypy-1.17.1-cp311-cp311-win_amd64.whl", hash = "sha256:ff2933428516ab63f961644bc49bc4cbe42bbffb2cd3b71cc7277c07d16b1a8b", size = 9507307, upload-time = "2025-07-31T07:53:59.734Z" }, + { url = "https://files.pythonhosted.org/packages/17/a2/7034d0d61af8098ec47902108553122baa0f438df8a713be860f7407c9e6/mypy-1.17.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:69e83ea6553a3ba79c08c6e15dbd9bfa912ec1e493bf75489ef93beb65209aeb", size = 11086295, upload-time = "2025-07-31T07:53:28.124Z" }, + { url = "https://files.pythonhosted.org/packages/14/1f/19e7e44b594d4b12f6ba8064dbe136505cec813549ca3e5191e40b1d3cc2/mypy-1.17.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:1b16708a66d38abb1e6b5702f5c2c87e133289da36f6a1d15f6a5221085c6403", size = 10112355, upload-time = "2025-07-31T07:53:21.121Z" }, + { url = "https://files.pythonhosted.org/packages/5b/69/baa33927e29e6b4c55d798a9d44db5d394072eef2bdc18c3e2048c9ed1e9/mypy-1.17.1-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:89e972c0035e9e05823907ad5398c5a73b9f47a002b22359b177d40bdaee7056", size = 11875285, upload-time = "2025-07-31T07:53:55.293Z" }, + { url = "https://files.pythonhosted.org/packages/90/13/f3a89c76b0a41e19490b01e7069713a30949d9a6c147289ee1521bcea245/mypy-1.17.1-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:03b6d0ed2b188e35ee6d5c36b5580cffd6da23319991c49ab5556c023ccf1341", size = 12737895, upload-time = "2025-07-31T07:53:43.623Z" }, + { url = "https://files.pythonhosted.org/packages/23/a1/c4ee79ac484241301564072e6476c5a5be2590bc2e7bfd28220033d2ef8f/mypy-1.17.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:c837b896b37cd103570d776bda106eabb8737aa6dd4f248451aecf53030cdbeb", size = 12931025, upload-time = "2025-07-31T07:54:17.125Z" }, + { url = "https://files.pythonhosted.org/packages/89/b8/7409477be7919a0608900e6320b155c72caab4fef46427c5cc75f85edadd/mypy-1.17.1-cp312-cp312-win_amd64.whl", hash = "sha256:665afab0963a4b39dff7c1fa563cc8b11ecff7910206db4b2e64dd1ba25aed19", size = 9584664, upload-time = "2025-07-31T07:54:12.842Z" }, + { url = "https://files.pythonhosted.org/packages/1d/f3/8fcd2af0f5b806f6cf463efaffd3c9548a28f84220493ecd38d127b6b66d/mypy-1.17.1-py3-none-any.whl", hash = "sha256:a9f52c0351c21fe24c21d8c0eb1f62967b262d6729393397b6f443c3b773c3b9", size = 2283411, upload-time = "2025-07-31T07:53:24.664Z" }, +] + [[package]] name = "mypy-boto3-bedrock-runtime" version = "1.39.0" @@ -4038,6 +4066,15 @@ dependencies = [ ] sdist = { url = "https://files.pythonhosted.org/packages/10/9a/e3186e760c57ee5f1c27ea5cea577a0ff9abfca51eefcb4d9a4cd39aff2e/pandoc-2.4.tar.gz", hash = "sha256:ecd1f8cbb7f4180c6b5db4a17a7c1a74df519995f5f186ef81ce72a9cbd0dd9a", size = 34635, upload-time = "2024-08-07T14:33:58.016Z" } +[[package]] +name = "pathspec" +version = "0.12.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/ca/bc/f35b8446f4531a7cb215605d100cd88b7ac6f44ab3fc94870c120ab3adbf/pathspec-0.12.1.tar.gz", hash = "sha256:a482d51503a1ab33b1c67a6c3813a26953dbdc71c31dacaef9a838c4e29f5712", size = 51043, upload-time = "2023-12-10T22:30:45Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/cc/20/ff623b09d963f88bfde16306a54e12ee5ea43e9b597108672ff3a408aad6/pathspec-0.12.1-py3-none-any.whl", hash = "sha256:a0d503e138a4c123b27490a4f7beda6a01c6f288df0e4a8b79c7eb0dc7b4cc08", size = 31191, upload-time = "2023-12-10T22:30:43.14Z" }, +] + [[package]] name = "pgvecto-rs" version = "0.2.2" From f721c778ad84440c634a66de942385cb712a80d9 Mon Sep 17 00:00:00 2001 From: Anubhav Singh Date: Fri, 5 Sep 2025 06:54:59 +0530 Subject: [PATCH 08/52] fix: Ensure the order of execution steps are correct when logging with Weave by W&B (#25183) --- api/core/ops/weave_trace/weave_trace.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/api/core/ops/weave_trace/weave_trace.py b/api/core/ops/weave_trace/weave_trace.py index 8089860481..8eb94cc679 100644 --- a/api/core/ops/weave_trace/weave_trace.py +++ b/api/core/ops/weave_trace/weave_trace.py @@ -120,7 +120,7 @@ class WeaveDataTrace(BaseTraceInstance): workflow_attributes["trace_id"] = trace_id workflow_attributes["start_time"] = trace_info.start_time workflow_attributes["end_time"] = trace_info.end_time - workflow_attributes["tags"] = ["workflow"] + workflow_attributes["tags"] = ["dify_workflow"] workflow_run = WeaveTraceModel( file_list=trace_info.file_list, @@ -156,6 +156,9 @@ class WeaveDataTrace(BaseTraceInstance): workflow_run_id=trace_info.workflow_run_id ) + # rearrange workflow_node_executions by starting time + workflow_node_executions = sorted(workflow_node_executions, key=lambda x: x.created_at) + for node_execution in workflow_node_executions: node_execution_id = node_execution.id tenant_id = trace_info.tenant_id # Use from trace_info instead From 19e1cbd0335bf217ee4082e7e74df3f784c69734 Mon Sep 17 00:00:00 2001 From: Asuka Minato Date: Fri, 5 Sep 2025 10:53:01 +0900 Subject: [PATCH 09/52] example regexp exec (#25200) --- .../app/(appDetailLayout)/[appId]/overview/tracing/panel.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web/app/(commonLayout)/app/(appDetailLayout)/[appId]/overview/tracing/panel.tsx b/web/app/(commonLayout)/app/(appDetailLayout)/[appId]/overview/tracing/panel.tsx index 7564a0f3c8..f79745c4dd 100644 --- a/web/app/(commonLayout)/app/(appDetailLayout)/[appId]/overview/tracing/panel.tsx +++ b/web/app/(commonLayout)/app/(appDetailLayout)/[appId]/overview/tracing/panel.tsx @@ -27,7 +27,7 @@ const I18N_PREFIX = 'app.tracing' const Panel: FC = () => { const { t } = useTranslation() const pathname = usePathname() - const matched = pathname.match(/\/app\/([^/]+)/) + const matched = /\/app\/([^/]+)/.exec(pathname) const appId = (matched?.length && matched[1]) ? matched[1] : '' const { isCurrentWorkspaceEditor } = useAppContext() const readOnly = !isCurrentWorkspaceEditor From 4966e4e1fbc87c1b1ca6845bec1de91d23511613 Mon Sep 17 00:00:00 2001 From: Yoshio Sugiyama Date: Fri, 5 Sep 2025 11:10:56 +0900 Subject: [PATCH 10/52] fix: Remove invalid key from firecrawl request payload. (#25190) Signed-off-by: SUGIYAMA Yoshio --- api/core/rag/extractor/firecrawl/firecrawl_app.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/api/core/rag/extractor/firecrawl/firecrawl_app.py b/api/core/rag/extractor/firecrawl/firecrawl_app.py index 83a4ac651f..fd60af0f1c 100644 --- a/api/core/rag/extractor/firecrawl/firecrawl_app.py +++ b/api/core/rag/extractor/firecrawl/firecrawl_app.py @@ -22,7 +22,6 @@ class FirecrawlApp: "formats": ["markdown"], "onlyMainContent": True, "timeout": 30000, - "integration": "dify", } if params: json_data.update(params) @@ -40,7 +39,7 @@ class FirecrawlApp: def crawl_url(self, url, params=None) -> str: # Documentation: https://docs.firecrawl.dev/api-reference/endpoint/crawl-post headers = self._prepare_headers() - json_data = {"url": url, "integration": "dify"} + json_data = {"url": url} if params: json_data.update(params) response = self._post_request(f"{self.base_url}/v1/crawl", json_data, headers) @@ -138,7 +137,6 @@ class FirecrawlApp: "timeout": 60000, "ignoreInvalidURLs": False, "scrapeOptions": {}, - "integration": "dify", } if params: json_data.update(params) From 64e338133ce6e230b8ba7b1e0d458cc011f2057e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=A2=A8=E7=BB=BF=E8=89=B2?= <48266410+lcedaw@users.noreply.github.com> Date: Fri, 5 Sep 2025 10:11:49 +0800 Subject: [PATCH 11/52] fix: chunk detail modal answer not wrap line (#25203) Co-authored-by: lijiezhao --- .../datasets/hit-testing/components/chunk-detail-modal.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web/app/components/datasets/hit-testing/components/chunk-detail-modal.tsx b/web/app/components/datasets/hit-testing/components/chunk-detail-modal.tsx index 33cff979c8..ab848a5871 100644 --- a/web/app/components/datasets/hit-testing/components/chunk-detail-modal.tsx +++ b/web/app/components/datasets/hit-testing/components/chunk-detail-modal.tsx @@ -66,7 +66,7 @@ const ChunkDetailModal: FC = ({ /> )} {answer && ( -
+
Q
From f0561c0c3bdccfb60b549aad6da81621cfea873e Mon Sep 17 00:00:00 2001 From: Asuka Minato Date: Fri, 5 Sep 2025 11:14:13 +0900 Subject: [PATCH 12/52] to RefObject (#25192) --- web/app/components/base/icons/IconBase.tsx | 2 +- web/app/components/base/icons/script.mjs | 2 +- web/app/components/base/icons/src/public/avatar/Robot.tsx | 2 +- web/app/components/base/icons/src/public/avatar/User.tsx | 2 +- web/app/components/base/icons/src/public/billing/ArCube1.tsx | 2 +- web/app/components/base/icons/src/public/billing/Asterisk.tsx | 2 +- .../base/icons/src/public/billing/AwsMarketplace.tsx | 2 +- web/app/components/base/icons/src/public/billing/Azure.tsx | 2 +- .../components/base/icons/src/public/billing/Buildings.tsx | 2 +- web/app/components/base/icons/src/public/billing/Diamond.tsx | 2 +- .../components/base/icons/src/public/billing/GoogleCloud.tsx | 2 +- web/app/components/base/icons/src/public/billing/Group2.tsx | 2 +- web/app/components/base/icons/src/public/billing/Keyframe.tsx | 2 +- web/app/components/base/icons/src/public/billing/Sparkles.tsx | 2 +- .../components/base/icons/src/public/billing/SparklesSoft.tsx | 2 +- web/app/components/base/icons/src/public/common/D.tsx | 2 +- .../base/icons/src/public/common/DiagonalDividingLine.tsx | 2 +- web/app/components/base/icons/src/public/common/Dify.tsx | 2 +- web/app/components/base/icons/src/public/common/Gdpr.tsx | 2 +- web/app/components/base/icons/src/public/common/Github.tsx | 2 +- web/app/components/base/icons/src/public/common/Highlight.tsx | 2 +- web/app/components/base/icons/src/public/common/Iso.tsx | 2 +- web/app/components/base/icons/src/public/common/Line3.tsx | 2 +- web/app/components/base/icons/src/public/common/Lock.tsx | 2 +- .../base/icons/src/public/common/MessageChatSquare.tsx | 2 +- .../base/icons/src/public/common/MultiPathRetrieval.tsx | 2 +- .../components/base/icons/src/public/common/NTo1Retrieval.tsx | 2 +- web/app/components/base/icons/src/public/common/Notion.tsx | 2 +- web/app/components/base/icons/src/public/common/Soc2.tsx | 2 +- .../components/base/icons/src/public/common/SparklesSoft.tsx | 2 +- .../base/icons/src/public/common/SparklesSoftAccent.tsx | 2 +- .../components/base/icons/src/public/education/Triangle.tsx | 2 +- web/app/components/base/icons/src/public/files/Csv.tsx | 2 +- web/app/components/base/icons/src/public/files/Doc.tsx | 2 +- web/app/components/base/icons/src/public/files/Docx.tsx | 2 +- web/app/components/base/icons/src/public/files/Html.tsx | 2 +- web/app/components/base/icons/src/public/files/Json.tsx | 2 +- web/app/components/base/icons/src/public/files/Md.tsx | 2 +- web/app/components/base/icons/src/public/files/Pdf.tsx | 2 +- web/app/components/base/icons/src/public/files/Txt.tsx | 2 +- web/app/components/base/icons/src/public/files/Unknown.tsx | 2 +- web/app/components/base/icons/src/public/files/Xlsx.tsx | 2 +- web/app/components/base/icons/src/public/files/Yaml.tsx | 2 +- web/app/components/base/icons/src/public/knowledge/Chunk.tsx | 2 +- .../components/base/icons/src/public/knowledge/Collapse.tsx | 2 +- .../base/icons/src/public/knowledge/GeneralType.tsx | 2 +- .../base/icons/src/public/knowledge/LayoutRight2LineMod.tsx | 2 +- .../base/icons/src/public/knowledge/ParentChildType.tsx | 2 +- .../base/icons/src/public/knowledge/SelectionMod.tsx | 2 +- web/app/components/base/icons/src/public/llm/Anthropic.tsx | 2 +- .../components/base/icons/src/public/llm/AnthropicDark.tsx | 2 +- .../components/base/icons/src/public/llm/AnthropicLight.tsx | 2 +- .../components/base/icons/src/public/llm/AnthropicText.tsx | 2 +- .../base/icons/src/public/llm/AzureOpenaiService.tsx | 2 +- .../base/icons/src/public/llm/AzureOpenaiServiceText.tsx | 2 +- web/app/components/base/icons/src/public/llm/Azureai.tsx | 2 +- web/app/components/base/icons/src/public/llm/AzureaiText.tsx | 2 +- web/app/components/base/icons/src/public/llm/Baichuan.tsx | 2 +- web/app/components/base/icons/src/public/llm/BaichuanText.tsx | 2 +- web/app/components/base/icons/src/public/llm/Chatglm.tsx | 2 +- web/app/components/base/icons/src/public/llm/ChatglmText.tsx | 2 +- web/app/components/base/icons/src/public/llm/Cohere.tsx | 2 +- web/app/components/base/icons/src/public/llm/CohereText.tsx | 2 +- web/app/components/base/icons/src/public/llm/Gpt3.tsx | 2 +- web/app/components/base/icons/src/public/llm/Gpt4.tsx | 2 +- web/app/components/base/icons/src/public/llm/Huggingface.tsx | 2 +- .../components/base/icons/src/public/llm/HuggingfaceText.tsx | 2 +- .../base/icons/src/public/llm/HuggingfaceTextHub.tsx | 2 +- web/app/components/base/icons/src/public/llm/IflytekSpark.tsx | 2 +- .../components/base/icons/src/public/llm/IflytekSparkText.tsx | 2 +- .../base/icons/src/public/llm/IflytekSparkTextCn.tsx | 2 +- web/app/components/base/icons/src/public/llm/Jina.tsx | 2 +- web/app/components/base/icons/src/public/llm/JinaText.tsx | 2 +- web/app/components/base/icons/src/public/llm/Localai.tsx | 2 +- web/app/components/base/icons/src/public/llm/LocalaiText.tsx | 2 +- web/app/components/base/icons/src/public/llm/Microsoft.tsx | 2 +- web/app/components/base/icons/src/public/llm/OpenaiBlack.tsx | 2 +- web/app/components/base/icons/src/public/llm/OpenaiBlue.tsx | 2 +- web/app/components/base/icons/src/public/llm/OpenaiGreen.tsx | 2 +- web/app/components/base/icons/src/public/llm/OpenaiTeal.tsx | 2 +- web/app/components/base/icons/src/public/llm/OpenaiText.tsx | 2 +- .../base/icons/src/public/llm/OpenaiTransparent.tsx | 2 +- web/app/components/base/icons/src/public/llm/OpenaiViolet.tsx | 2 +- web/app/components/base/icons/src/public/llm/OpenaiYellow.tsx | 2 +- web/app/components/base/icons/src/public/llm/Openllm.tsx | 2 +- web/app/components/base/icons/src/public/llm/OpenllmText.tsx | 2 +- web/app/components/base/icons/src/public/llm/Replicate.tsx | 2 +- .../components/base/icons/src/public/llm/ReplicateText.tsx | 2 +- .../components/base/icons/src/public/llm/XorbitsInference.tsx | 2 +- .../base/icons/src/public/llm/XorbitsInferenceText.tsx | 2 +- web/app/components/base/icons/src/public/llm/Zhipuai.tsx | 2 +- web/app/components/base/icons/src/public/llm/ZhipuaiText.tsx | 2 +- .../components/base/icons/src/public/llm/ZhipuaiTextCn.tsx | 2 +- web/app/components/base/icons/src/public/model/Checked.tsx | 2 +- .../base/icons/src/public/other/DefaultToolIcon.tsx | 2 +- web/app/components/base/icons/src/public/other/Icon3Dots.tsx | 2 +- .../components/base/icons/src/public/other/Message3Fill.tsx | 2 +- web/app/components/base/icons/src/public/other/RowStruct.tsx | 2 +- web/app/components/base/icons/src/public/plugins/Google.tsx | 2 +- .../components/base/icons/src/public/plugins/PartnerDark.tsx | 2 +- .../components/base/icons/src/public/plugins/PartnerLight.tsx | 2 +- .../components/base/icons/src/public/plugins/VerifiedDark.tsx | 2 +- .../base/icons/src/public/plugins/VerifiedLight.tsx | 2 +- .../components/base/icons/src/public/plugins/WebReader.tsx | 2 +- .../components/base/icons/src/public/plugins/Wikipedia.tsx | 2 +- web/app/components/base/icons/src/public/thought/DataSet.tsx | 2 +- web/app/components/base/icons/src/public/thought/Loading.tsx | 2 +- web/app/components/base/icons/src/public/thought/Search.tsx | 2 +- .../components/base/icons/src/public/thought/ThoughtList.tsx | 2 +- .../components/base/icons/src/public/thought/WebReader.tsx | 2 +- .../components/base/icons/src/public/tracing/AliyunIcon.tsx | 2 +- .../base/icons/src/public/tracing/AliyunIconBig.tsx | 2 +- .../components/base/icons/src/public/tracing/ArizeIcon.tsx | 2 +- .../components/base/icons/src/public/tracing/ArizeIconBig.tsx | 2 +- .../components/base/icons/src/public/tracing/LangfuseIcon.tsx | 2 +- .../base/icons/src/public/tracing/LangfuseIconBig.tsx | 2 +- .../base/icons/src/public/tracing/LangsmithIcon.tsx | 2 +- .../base/icons/src/public/tracing/LangsmithIconBig.tsx | 2 +- web/app/components/base/icons/src/public/tracing/OpikIcon.tsx | 2 +- .../components/base/icons/src/public/tracing/OpikIconBig.tsx | 2 +- .../components/base/icons/src/public/tracing/PhoenixIcon.tsx | 2 +- .../base/icons/src/public/tracing/PhoenixIconBig.tsx | 2 +- .../components/base/icons/src/public/tracing/TracingIcon.tsx | 2 +- .../components/base/icons/src/public/tracing/WeaveIcon.tsx | 2 +- .../components/base/icons/src/public/tracing/WeaveIconBig.tsx | 2 +- .../components/base/icons/src/vender/features/Citations.tsx | 2 +- .../base/icons/src/vender/features/ContentModeration.tsx | 2 +- .../components/base/icons/src/vender/features/Document.tsx | 2 +- .../base/icons/src/vender/features/FolderUpload.tsx | 2 +- .../components/base/icons/src/vender/features/LoveMessage.tsx | 2 +- .../components/base/icons/src/vender/features/MessageFast.tsx | 2 +- .../base/icons/src/vender/features/Microphone01.tsx | 2 +- .../components/base/icons/src/vender/features/TextToAudio.tsx | 2 +- .../base/icons/src/vender/features/VirtualAssistant.tsx | 2 +- web/app/components/base/icons/src/vender/features/Vision.tsx | 2 +- .../icons/src/vender/line/alertsAndFeedback/AlertTriangle.tsx | 2 +- .../icons/src/vender/line/alertsAndFeedback/ThumbsDown.tsx | 2 +- .../base/icons/src/vender/line/alertsAndFeedback/ThumbsUp.tsx | 2 +- .../base/icons/src/vender/line/arrows/ArrowNarrowLeft.tsx | 2 +- .../base/icons/src/vender/line/arrows/ArrowUpRight.tsx | 2 +- .../base/icons/src/vender/line/arrows/ChevronDownDouble.tsx | 2 +- .../base/icons/src/vender/line/arrows/ChevronRight.tsx | 2 +- .../icons/src/vender/line/arrows/ChevronSelectorVertical.tsx | 2 +- .../base/icons/src/vender/line/arrows/RefreshCcw01.tsx | 2 +- .../base/icons/src/vender/line/arrows/RefreshCw05.tsx | 2 +- .../base/icons/src/vender/line/arrows/ReverseLeft.tsx | 2 +- .../base/icons/src/vender/line/communication/AiText.tsx | 2 +- .../base/icons/src/vender/line/communication/ChatBot.tsx | 2 +- .../base/icons/src/vender/line/communication/ChatBotSlim.tsx | 2 +- .../base/icons/src/vender/line/communication/CuteRobot.tsx | 2 +- .../src/vender/line/communication/MessageCheckRemove.tsx | 2 +- .../icons/src/vender/line/communication/MessageFastPlus.tsx | 2 +- .../icons/src/vender/line/development/ArtificialBrain.tsx | 2 +- .../icons/src/vender/line/development/BarChartSquare02.tsx | 2 +- .../base/icons/src/vender/line/development/BracketsX.tsx | 2 +- .../base/icons/src/vender/line/development/CodeBrowser.tsx | 2 +- .../base/icons/src/vender/line/development/Container.tsx | 2 +- .../base/icons/src/vender/line/development/Database01.tsx | 2 +- .../base/icons/src/vender/line/development/Database03.tsx | 2 +- .../base/icons/src/vender/line/development/FileHeart02.tsx | 2 +- .../base/icons/src/vender/line/development/GitBranch01.tsx | 2 +- .../icons/src/vender/line/development/PromptEngineering.tsx | 2 +- .../base/icons/src/vender/line/development/PuzzlePiece01.tsx | 2 +- .../base/icons/src/vender/line/development/TerminalSquare.tsx | 2 +- .../base/icons/src/vender/line/development/Variable.tsx | 2 +- .../base/icons/src/vender/line/development/Webhooks.tsx | 2 +- .../base/icons/src/vender/line/editor/AlignLeft.tsx | 2 +- .../base/icons/src/vender/line/editor/BezierCurve03.tsx | 2 +- .../components/base/icons/src/vender/line/editor/Collapse.tsx | 2 +- .../components/base/icons/src/vender/line/editor/Colors.tsx | 2 +- .../base/icons/src/vender/line/editor/ImageIndentLeft.tsx | 2 +- .../base/icons/src/vender/line/editor/LeftIndent02.tsx | 2 +- .../base/icons/src/vender/line/editor/LetterSpacing01.tsx | 2 +- .../base/icons/src/vender/line/editor/TypeSquare.tsx | 2 +- .../base/icons/src/vender/line/education/BookOpen01.tsx | 2 +- web/app/components/base/icons/src/vender/line/files/Copy.tsx | 2 +- .../components/base/icons/src/vender/line/files/CopyCheck.tsx | 2 +- .../components/base/icons/src/vender/line/files/File02.tsx | 2 +- .../base/icons/src/vender/line/files/FileArrow01.tsx | 2 +- .../base/icons/src/vender/line/files/FileCheck02.tsx | 2 +- .../base/icons/src/vender/line/files/FileDownload02.tsx | 2 +- .../base/icons/src/vender/line/files/FilePlus01.tsx | 2 +- .../base/icons/src/vender/line/files/FilePlus02.tsx | 2 +- .../components/base/icons/src/vender/line/files/FileText.tsx | 2 +- .../base/icons/src/vender/line/files/FileUpload.tsx | 2 +- .../components/base/icons/src/vender/line/files/Folder.tsx | 2 +- .../icons/src/vender/line/financeAndECommerce/Balance.tsx | 2 +- .../src/vender/line/financeAndECommerce/CoinsStacked01.tsx | 2 +- .../icons/src/vender/line/financeAndECommerce/GoldCoin.tsx | 2 +- .../icons/src/vender/line/financeAndECommerce/ReceiptList.tsx | 2 +- .../base/icons/src/vender/line/financeAndECommerce/Tag01.tsx | 2 +- .../base/icons/src/vender/line/financeAndECommerce/Tag03.tsx | 2 +- .../components/base/icons/src/vender/line/general/AtSign.tsx | 2 +- .../base/icons/src/vender/line/general/Bookmark.tsx | 2 +- .../components/base/icons/src/vender/line/general/Check.tsx | 2 +- .../base/icons/src/vender/line/general/CheckDone01.tsx | 2 +- .../base/icons/src/vender/line/general/ChecklistSquare.tsx | 2 +- .../base/icons/src/vender/line/general/CodeAssistant.tsx | 2 +- .../base/icons/src/vender/line/general/DotsGrid.tsx | 2 +- .../components/base/icons/src/vender/line/general/Edit02.tsx | 2 +- .../components/base/icons/src/vender/line/general/Edit04.tsx | 2 +- .../components/base/icons/src/vender/line/general/Edit05.tsx | 2 +- .../components/base/icons/src/vender/line/general/Hash02.tsx | 2 +- .../base/icons/src/vender/line/general/InfoCircle.tsx | 2 +- .../components/base/icons/src/vender/line/general/Link03.tsx | 2 +- .../base/icons/src/vender/line/general/LinkExternal02.tsx | 2 +- .../components/base/icons/src/vender/line/general/LogIn04.tsx | 2 +- .../base/icons/src/vender/line/general/LogOut01.tsx | 2 +- .../base/icons/src/vender/line/general/LogOut04.tsx | 2 +- .../base/icons/src/vender/line/general/MagicEdit.tsx | 2 +- .../components/base/icons/src/vender/line/general/Menu01.tsx | 2 +- .../components/base/icons/src/vender/line/general/Pin01.tsx | 2 +- .../components/base/icons/src/vender/line/general/Pin02.tsx | 2 +- .../components/base/icons/src/vender/line/general/Plus02.tsx | 2 +- .../components/base/icons/src/vender/line/general/Refresh.tsx | 2 +- .../base/icons/src/vender/line/general/SearchMenu.tsx | 2 +- .../base/icons/src/vender/line/general/Settings01.tsx | 2 +- .../base/icons/src/vender/line/general/Settings04.tsx | 2 +- .../base/icons/src/vender/line/general/Target04.tsx | 2 +- .../base/icons/src/vender/line/general/Upload03.tsx | 2 +- .../base/icons/src/vender/line/general/UploadCloud01.tsx | 2 +- web/app/components/base/icons/src/vender/line/general/X.tsx | 2 +- .../base/icons/src/vender/line/images/ImagePlus.tsx | 2 +- .../base/icons/src/vender/line/layout/AlignLeft01.tsx | 2 +- .../base/icons/src/vender/line/layout/AlignRight01.tsx | 2 +- .../components/base/icons/src/vender/line/layout/Grid01.tsx | 2 +- .../base/icons/src/vender/line/layout/LayoutGrid02.tsx | 2 +- .../base/icons/src/vender/line/mapsAndTravel/Globe01.tsx | 2 +- .../base/icons/src/vender/line/mapsAndTravel/Route.tsx | 2 +- .../icons/src/vender/line/mediaAndDevices/Microphone01.tsx | 2 +- .../base/icons/src/vender/line/mediaAndDevices/PlayCircle.tsx | 2 +- .../base/icons/src/vender/line/mediaAndDevices/SlidersH.tsx | 2 +- .../base/icons/src/vender/line/mediaAndDevices/Speaker.tsx | 2 +- .../base/icons/src/vender/line/mediaAndDevices/Stop.tsx | 2 +- .../base/icons/src/vender/line/mediaAndDevices/StopCircle.tsx | 2 +- .../components/base/icons/src/vender/line/others/Apps02.tsx | 2 +- .../components/base/icons/src/vender/line/others/BubbleX.tsx | 2 +- .../components/base/icons/src/vender/line/others/Colors.tsx | 2 +- .../base/icons/src/vender/line/others/DragHandle.tsx | 2 +- web/app/components/base/icons/src/vender/line/others/Env.tsx | 2 +- .../base/icons/src/vender/line/others/Exchange02.tsx | 2 +- .../components/base/icons/src/vender/line/others/FileCode.tsx | 2 +- .../base/icons/src/vender/line/others/GlobalVariable.tsx | 2 +- .../base/icons/src/vender/line/others/Icon3Dots.tsx | 2 +- .../base/icons/src/vender/line/others/LongArrowLeft.tsx | 2 +- .../base/icons/src/vender/line/others/LongArrowRight.tsx | 2 +- .../base/icons/src/vender/line/others/SearchMenu.tsx | 2 +- .../components/base/icons/src/vender/line/others/Tools.tsx | 2 +- .../base/icons/src/vender/line/shapes/CubeOutline.tsx | 2 +- .../base/icons/src/vender/line/time/ClockFastForward.tsx | 2 +- .../components/base/icons/src/vender/line/time/ClockPlay.tsx | 2 +- .../base/icons/src/vender/line/time/ClockPlaySlim.tsx | 2 +- .../base/icons/src/vender/line/time/ClockRefresh.tsx | 2 +- .../components/base/icons/src/vender/line/users/User01.tsx | 2 +- .../components/base/icons/src/vender/line/users/Users01.tsx | 2 +- .../components/base/icons/src/vender/line/weather/Stars02.tsx | 2 +- .../components/base/icons/src/vender/other/AnthropicText.tsx | 2 +- web/app/components/base/icons/src/vender/other/Generator.tsx | 2 +- web/app/components/base/icons/src/vender/other/Group.tsx | 2 +- web/app/components/base/icons/src/vender/other/Mcp.tsx | 2 +- .../base/icons/src/vender/other/NoToolPlaceholder.tsx | 2 +- web/app/components/base/icons/src/vender/other/Openai.tsx | 2 +- web/app/components/base/icons/src/vender/other/ReplayLine.tsx | 2 +- .../base/icons/src/vender/plugin/BoxSparkleFill.tsx | 2 +- .../components/base/icons/src/vender/plugin/LeftCorner.tsx | 2 +- .../icons/src/vender/solid/FinanceAndECommerce/GoldCoin.tsx | 2 +- .../icons/src/vender/solid/FinanceAndECommerce/Scales02.tsx | 2 +- .../src/vender/solid/alertsAndFeedback/AlertTriangle.tsx | 2 +- .../base/icons/src/vender/solid/arrows/ChevronDown.tsx | 2 +- .../base/icons/src/vender/solid/arrows/HighPriority.tsx | 2 +- .../base/icons/src/vender/solid/communication/AiText.tsx | 2 +- .../icons/src/vender/solid/communication/BubbleTextMod.tsx | 2 +- .../base/icons/src/vender/solid/communication/ChatBot.tsx | 2 +- .../base/icons/src/vender/solid/communication/CuteRobot.tsx | 2 +- .../base/icons/src/vender/solid/communication/EditList.tsx | 2 +- .../base/icons/src/vender/solid/communication/ListSparkle.tsx | 2 +- .../base/icons/src/vender/solid/communication/Logic.tsx | 2 +- .../src/vender/solid/communication/MessageDotsCircle.tsx | 2 +- .../base/icons/src/vender/solid/communication/MessageFast.tsx | 2 +- .../src/vender/solid/communication/MessageHeartCircle.tsx | 2 +- .../src/vender/solid/communication/MessageSmileSquare.tsx | 2 +- .../base/icons/src/vender/solid/communication/Send03.tsx | 2 +- .../base/icons/src/vender/solid/development/ApiConnection.tsx | 2 +- .../icons/src/vender/solid/development/ApiConnectionMod.tsx | 2 +- .../icons/src/vender/solid/development/BarChartSquare02.tsx | 2 +- .../base/icons/src/vender/solid/development/Container.tsx | 2 +- .../base/icons/src/vender/solid/development/Database02.tsx | 2 +- .../base/icons/src/vender/solid/development/Database03.tsx | 2 +- .../base/icons/src/vender/solid/development/FileHeart02.tsx | 2 +- .../icons/src/vender/solid/development/PatternRecognition.tsx | 2 +- .../icons/src/vender/solid/development/PromptEngineering.tsx | 2 +- .../base/icons/src/vender/solid/development/PuzzlePiece01.tsx | 2 +- .../base/icons/src/vender/solid/development/Semantic.tsx | 2 +- .../icons/src/vender/solid/development/TerminalSquare.tsx | 2 +- .../base/icons/src/vender/solid/development/Variable02.tsx | 2 +- .../components/base/icons/src/vender/solid/editor/Brush01.tsx | 2 +- .../base/icons/src/vender/solid/editor/Citations.tsx | 2 +- .../components/base/icons/src/vender/solid/editor/Colors.tsx | 2 +- .../base/icons/src/vender/solid/editor/Paragraph.tsx | 2 +- .../base/icons/src/vender/solid/editor/TypeSquare.tsx | 2 +- .../base/icons/src/vender/solid/education/Beaker02.tsx | 2 +- .../base/icons/src/vender/solid/education/BubbleText.tsx | 2 +- .../base/icons/src/vender/solid/education/Heart02.tsx | 2 +- .../base/icons/src/vender/solid/education/Unblur.tsx | 2 +- .../components/base/icons/src/vender/solid/files/File05.tsx | 2 +- .../base/icons/src/vender/solid/files/FileSearch02.tsx | 2 +- .../components/base/icons/src/vender/solid/files/FileZip.tsx | 2 +- .../components/base/icons/src/vender/solid/files/Folder.tsx | 2 +- .../base/icons/src/vender/solid/general/AnswerTriangle.tsx | 2 +- .../icons/src/vender/solid/general/ArrowDownRoundFill.tsx | 2 +- .../base/icons/src/vender/solid/general/CheckCircle.tsx | 2 +- .../base/icons/src/vender/solid/general/CheckDone01.tsx | 2 +- .../base/icons/src/vender/solid/general/Download02.tsx | 2 +- .../components/base/icons/src/vender/solid/general/Edit03.tsx | 2 +- .../components/base/icons/src/vender/solid/general/Edit04.tsx | 2 +- .../components/base/icons/src/vender/solid/general/Eye.tsx | 2 +- .../components/base/icons/src/vender/solid/general/Github.tsx | 2 +- .../icons/src/vender/solid/general/MessageClockCircle.tsx | 2 +- .../base/icons/src/vender/solid/general/PlusCircle.tsx | 2 +- .../base/icons/src/vender/solid/general/QuestionTriangle.tsx | 2 +- .../base/icons/src/vender/solid/general/SearchMd.tsx | 2 +- .../base/icons/src/vender/solid/general/Target04.tsx | 2 +- .../components/base/icons/src/vender/solid/general/Tool03.tsx | 2 +- .../base/icons/src/vender/solid/general/XCircle.tsx | 2 +- .../base/icons/src/vender/solid/general/ZapFast.tsx | 2 +- .../base/icons/src/vender/solid/general/ZapNarrow.tsx | 2 +- .../components/base/icons/src/vender/solid/layout/Grid01.tsx | 2 +- .../base/icons/src/vender/solid/mapsAndTravel/Globe06.tsx | 2 +- .../base/icons/src/vender/solid/mapsAndTravel/Route.tsx | 2 +- .../src/vender/solid/mediaAndDevices/AudioSupportIcon.tsx | 2 +- .../src/vender/solid/mediaAndDevices/DocumentSupportIcon.tsx | 2 +- .../base/icons/src/vender/solid/mediaAndDevices/MagicBox.tsx | 2 +- .../base/icons/src/vender/solid/mediaAndDevices/MagicEyes.tsx | 2 +- .../base/icons/src/vender/solid/mediaAndDevices/MagicWand.tsx | 2 +- .../icons/src/vender/solid/mediaAndDevices/Microphone01.tsx | 2 +- .../base/icons/src/vender/solid/mediaAndDevices/Play.tsx | 2 +- .../base/icons/src/vender/solid/mediaAndDevices/Robot.tsx | 2 +- .../base/icons/src/vender/solid/mediaAndDevices/Sliders02.tsx | 2 +- .../base/icons/src/vender/solid/mediaAndDevices/Speaker.tsx | 2 +- .../icons/src/vender/solid/mediaAndDevices/StopCircle.tsx | 2 +- .../src/vender/solid/mediaAndDevices/VideoSupportIcon.tsx | 2 +- .../base/icons/src/vender/solid/security/Lock01.tsx | 2 +- .../components/base/icons/src/vender/solid/shapes/Corner.tsx | 2 +- .../components/base/icons/src/vender/solid/shapes/Star04.tsx | 2 +- .../components/base/icons/src/vender/solid/shapes/Star06.tsx | 2 +- .../components/base/icons/src/vender/solid/users/User01.tsx | 2 +- .../base/icons/src/vender/solid/users/UserEdit02.tsx | 2 +- .../components/base/icons/src/vender/solid/users/Users01.tsx | 2 +- .../base/icons/src/vender/solid/users/UsersPlus.tsx | 2 +- .../base/icons/src/vender/system/AutoUpdateLine.tsx | 2 +- web/app/components/base/icons/src/vender/workflow/Agent.tsx | 2 +- web/app/components/base/icons/src/vender/workflow/Answer.tsx | 2 +- .../components/base/icons/src/vender/workflow/Assigner.tsx | 2 +- web/app/components/base/icons/src/vender/workflow/Code.tsx | 2 +- .../base/icons/src/vender/workflow/DocsExtractor.tsx | 2 +- web/app/components/base/icons/src/vender/workflow/End.tsx | 2 +- web/app/components/base/icons/src/vender/workflow/Home.tsx | 2 +- web/app/components/base/icons/src/vender/workflow/Http.tsx | 2 +- web/app/components/base/icons/src/vender/workflow/IfElse.tsx | 2 +- .../components/base/icons/src/vender/workflow/Iteration.tsx | 2 +- .../base/icons/src/vender/workflow/IterationStart.tsx | 2 +- web/app/components/base/icons/src/vender/workflow/Jinja.tsx | 2 +- .../base/icons/src/vender/workflow/KnowledgeRetrieval.tsx | 2 +- .../components/base/icons/src/vender/workflow/ListFilter.tsx | 2 +- web/app/components/base/icons/src/vender/workflow/Llm.tsx | 2 +- web/app/components/base/icons/src/vender/workflow/Loop.tsx | 2 +- web/app/components/base/icons/src/vender/workflow/LoopEnd.tsx | 2 +- .../base/icons/src/vender/workflow/ParameterExtractor.tsx | 2 +- .../base/icons/src/vender/workflow/QuestionClassifier.tsx | 2 +- .../base/icons/src/vender/workflow/TemplatingTransform.tsx | 2 +- .../components/base/icons/src/vender/workflow/VariableX.tsx | 2 +- .../base/icons/src/vender/workflow/WindowCursor.tsx | 2 +- web/app/components/share/text-generation/run-once/index.tsx | 2 +- .../workflow/nodes/agent/use-single-run-form-params.ts | 4 ++-- .../workflow/nodes/assigner/use-single-run-form-params.ts | 4 ++-- .../workflow/nodes/code/use-single-run-form-params.ts | 4 ++-- .../nodes/document-extractor/use-single-run-form-params.ts | 4 ++-- .../workflow/nodes/http/use-single-run-form-params.ts | 4 ++-- .../workflow/nodes/if-else/use-single-run-form-params.ts | 4 ++-- .../workflow/nodes/iteration/use-single-run-form-params.ts | 4 ++-- .../nodes/knowledge-retrieval/use-single-run-form-params.ts | 4 ++-- .../workflow/nodes/llm/use-single-run-form-params.ts | 4 ++-- .../nodes/parameter-extractor/use-single-run-form-params.ts | 4 ++-- .../nodes/question-classifier/use-single-run-form-params.ts | 4 ++-- .../workflow/nodes/start/use-single-run-form-params.ts | 4 ++-- .../nodes/template-transform/use-single-run-form-params.ts | 4 ++-- .../workflow/nodes/tool/use-single-run-form-params.ts | 4 ++-- .../nodes/variable-assigner/use-single-run-form-params.ts | 4 ++-- web/types/workflow.ts | 4 ++-- 389 files changed, 405 insertions(+), 405 deletions(-) diff --git a/web/app/components/base/icons/IconBase.tsx b/web/app/components/base/icons/IconBase.tsx index 134c948b05..a20608c1c9 100644 --- a/web/app/components/base/icons/IconBase.tsx +++ b/web/app/components/base/icons/IconBase.tsx @@ -18,7 +18,7 @@ const IconBase = ( ref, ...props }: IconBaseProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => { const { data, className, onClick, style, ...restProps } = props diff --git a/web/app/components/base/icons/script.mjs b/web/app/components/base/icons/script.mjs index 1b5994edef..764bbf1987 100644 --- a/web/app/components/base/icons/script.mjs +++ b/web/app/components/base/icons/script.mjs @@ -66,7 +66,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/public/avatar/Robot.tsx b/web/app/components/base/icons/src/public/avatar/Robot.tsx index 8bee6e24cb..31dd7f3efd 100644 --- a/web/app/components/base/icons/src/public/avatar/Robot.tsx +++ b/web/app/components/base/icons/src/public/avatar/Robot.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/public/avatar/User.tsx b/web/app/components/base/icons/src/public/avatar/User.tsx index c7af42868f..d5210a2af4 100644 --- a/web/app/components/base/icons/src/public/avatar/User.tsx +++ b/web/app/components/base/icons/src/public/avatar/User.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/public/billing/ArCube1.tsx b/web/app/components/base/icons/src/public/billing/ArCube1.tsx index dfd3c41473..1a517ca750 100644 --- a/web/app/components/base/icons/src/public/billing/ArCube1.tsx +++ b/web/app/components/base/icons/src/public/billing/ArCube1.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/public/billing/Asterisk.tsx b/web/app/components/base/icons/src/public/billing/Asterisk.tsx index 71b778b0b2..916b90429c 100644 --- a/web/app/components/base/icons/src/public/billing/Asterisk.tsx +++ b/web/app/components/base/icons/src/public/billing/Asterisk.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/public/billing/AwsMarketplace.tsx b/web/app/components/base/icons/src/public/billing/AwsMarketplace.tsx index 7ea4e14be4..339ffc55b1 100644 --- a/web/app/components/base/icons/src/public/billing/AwsMarketplace.tsx +++ b/web/app/components/base/icons/src/public/billing/AwsMarketplace.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/public/billing/Azure.tsx b/web/app/components/base/icons/src/public/billing/Azure.tsx index fe47611cb1..5bd1831123 100644 --- a/web/app/components/base/icons/src/public/billing/Azure.tsx +++ b/web/app/components/base/icons/src/public/billing/Azure.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/public/billing/Buildings.tsx b/web/app/components/base/icons/src/public/billing/Buildings.tsx index eaed4e82cf..054317c9f0 100644 --- a/web/app/components/base/icons/src/public/billing/Buildings.tsx +++ b/web/app/components/base/icons/src/public/billing/Buildings.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/public/billing/Diamond.tsx b/web/app/components/base/icons/src/public/billing/Diamond.tsx index 18226e36b9..6312eec538 100644 --- a/web/app/components/base/icons/src/public/billing/Diamond.tsx +++ b/web/app/components/base/icons/src/public/billing/Diamond.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/public/billing/GoogleCloud.tsx b/web/app/components/base/icons/src/public/billing/GoogleCloud.tsx index 6750a7c9d7..951c205b28 100644 --- a/web/app/components/base/icons/src/public/billing/GoogleCloud.tsx +++ b/web/app/components/base/icons/src/public/billing/GoogleCloud.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/public/billing/Group2.tsx b/web/app/components/base/icons/src/public/billing/Group2.tsx index 792b45412d..1ab4976044 100644 --- a/web/app/components/base/icons/src/public/billing/Group2.tsx +++ b/web/app/components/base/icons/src/public/billing/Group2.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/public/billing/Keyframe.tsx b/web/app/components/base/icons/src/public/billing/Keyframe.tsx index a82aad9813..204ac4dd23 100644 --- a/web/app/components/base/icons/src/public/billing/Keyframe.tsx +++ b/web/app/components/base/icons/src/public/billing/Keyframe.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/public/billing/Sparkles.tsx b/web/app/components/base/icons/src/public/billing/Sparkles.tsx index 09fb779b5a..1aedb0c17f 100644 --- a/web/app/components/base/icons/src/public/billing/Sparkles.tsx +++ b/web/app/components/base/icons/src/public/billing/Sparkles.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/public/billing/SparklesSoft.tsx b/web/app/components/base/icons/src/public/billing/SparklesSoft.tsx index b3f94d0b4d..5827652f66 100644 --- a/web/app/components/base/icons/src/public/billing/SparklesSoft.tsx +++ b/web/app/components/base/icons/src/public/billing/SparklesSoft.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/public/common/D.tsx b/web/app/components/base/icons/src/public/common/D.tsx index 87aca80ee2..9b33f9ba53 100644 --- a/web/app/components/base/icons/src/public/common/D.tsx +++ b/web/app/components/base/icons/src/public/common/D.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/public/common/DiagonalDividingLine.tsx b/web/app/components/base/icons/src/public/common/DiagonalDividingLine.tsx index ce95c2f8f9..5e1156fc26 100644 --- a/web/app/components/base/icons/src/public/common/DiagonalDividingLine.tsx +++ b/web/app/components/base/icons/src/public/common/DiagonalDividingLine.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/public/common/Dify.tsx b/web/app/components/base/icons/src/public/common/Dify.tsx index f53f47f6d4..b77064650c 100644 --- a/web/app/components/base/icons/src/public/common/Dify.tsx +++ b/web/app/components/base/icons/src/public/common/Dify.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/public/common/Gdpr.tsx b/web/app/components/base/icons/src/public/common/Gdpr.tsx index 5141b5774a..8ae72c1346 100644 --- a/web/app/components/base/icons/src/public/common/Gdpr.tsx +++ b/web/app/components/base/icons/src/public/common/Gdpr.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/public/common/Github.tsx b/web/app/components/base/icons/src/public/common/Github.tsx index 9c6f41834f..26df0683da 100644 --- a/web/app/components/base/icons/src/public/common/Github.tsx +++ b/web/app/components/base/icons/src/public/common/Github.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/public/common/Highlight.tsx b/web/app/components/base/icons/src/public/common/Highlight.tsx index 261b5898ce..46bb4fd1bf 100644 --- a/web/app/components/base/icons/src/public/common/Highlight.tsx +++ b/web/app/components/base/icons/src/public/common/Highlight.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/public/common/Iso.tsx b/web/app/components/base/icons/src/public/common/Iso.tsx index db4b515742..0656a6957d 100644 --- a/web/app/components/base/icons/src/public/common/Iso.tsx +++ b/web/app/components/base/icons/src/public/common/Iso.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/public/common/Line3.tsx b/web/app/components/base/icons/src/public/common/Line3.tsx index a1fb899d6b..afaf47664f 100644 --- a/web/app/components/base/icons/src/public/common/Line3.tsx +++ b/web/app/components/base/icons/src/public/common/Line3.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/public/common/Lock.tsx b/web/app/components/base/icons/src/public/common/Lock.tsx index 1fce8bb4ce..b4bea5eeac 100644 --- a/web/app/components/base/icons/src/public/common/Lock.tsx +++ b/web/app/components/base/icons/src/public/common/Lock.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/public/common/MessageChatSquare.tsx b/web/app/components/base/icons/src/public/common/MessageChatSquare.tsx index 85ccc0b760..401e5c4b2f 100644 --- a/web/app/components/base/icons/src/public/common/MessageChatSquare.tsx +++ b/web/app/components/base/icons/src/public/common/MessageChatSquare.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/public/common/MultiPathRetrieval.tsx b/web/app/components/base/icons/src/public/common/MultiPathRetrieval.tsx index a325900bda..5d1c23743f 100644 --- a/web/app/components/base/icons/src/public/common/MultiPathRetrieval.tsx +++ b/web/app/components/base/icons/src/public/common/MultiPathRetrieval.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/public/common/NTo1Retrieval.tsx b/web/app/components/base/icons/src/public/common/NTo1Retrieval.tsx index 1afa979528..e42e588df4 100644 --- a/web/app/components/base/icons/src/public/common/NTo1Retrieval.tsx +++ b/web/app/components/base/icons/src/public/common/NTo1Retrieval.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/public/common/Notion.tsx b/web/app/components/base/icons/src/public/common/Notion.tsx index 33b7c31238..e451a3d80a 100644 --- a/web/app/components/base/icons/src/public/common/Notion.tsx +++ b/web/app/components/base/icons/src/public/common/Notion.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/public/common/Soc2.tsx b/web/app/components/base/icons/src/public/common/Soc2.tsx index b94d523801..9e041fcf27 100644 --- a/web/app/components/base/icons/src/public/common/Soc2.tsx +++ b/web/app/components/base/icons/src/public/common/Soc2.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/public/common/SparklesSoft.tsx b/web/app/components/base/icons/src/public/common/SparklesSoft.tsx index b3f94d0b4d..5827652f66 100644 --- a/web/app/components/base/icons/src/public/common/SparklesSoft.tsx +++ b/web/app/components/base/icons/src/public/common/SparklesSoft.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/public/common/SparklesSoftAccent.tsx b/web/app/components/base/icons/src/public/common/SparklesSoftAccent.tsx index a2bbc73b7d..be38813b06 100644 --- a/web/app/components/base/icons/src/public/common/SparklesSoftAccent.tsx +++ b/web/app/components/base/icons/src/public/common/SparklesSoftAccent.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/public/education/Triangle.tsx b/web/app/components/base/icons/src/public/education/Triangle.tsx index 85aa518ad2..ec1c96777a 100644 --- a/web/app/components/base/icons/src/public/education/Triangle.tsx +++ b/web/app/components/base/icons/src/public/education/Triangle.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/public/files/Csv.tsx b/web/app/components/base/icons/src/public/files/Csv.tsx index 03ce2fb74d..f5f22c3fee 100644 --- a/web/app/components/base/icons/src/public/files/Csv.tsx +++ b/web/app/components/base/icons/src/public/files/Csv.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/public/files/Doc.tsx b/web/app/components/base/icons/src/public/files/Doc.tsx index e71773fdff..1773d3e4f3 100644 --- a/web/app/components/base/icons/src/public/files/Doc.tsx +++ b/web/app/components/base/icons/src/public/files/Doc.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/public/files/Docx.tsx b/web/app/components/base/icons/src/public/files/Docx.tsx index 25d5d06459..1984050210 100644 --- a/web/app/components/base/icons/src/public/files/Docx.tsx +++ b/web/app/components/base/icons/src/public/files/Docx.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/public/files/Html.tsx b/web/app/components/base/icons/src/public/files/Html.tsx index 65b333d8b4..73b2faa627 100644 --- a/web/app/components/base/icons/src/public/files/Html.tsx +++ b/web/app/components/base/icons/src/public/files/Html.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/public/files/Json.tsx b/web/app/components/base/icons/src/public/files/Json.tsx index 90812bee5f..530ee52b7b 100644 --- a/web/app/components/base/icons/src/public/files/Json.tsx +++ b/web/app/components/base/icons/src/public/files/Json.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/public/files/Md.tsx b/web/app/components/base/icons/src/public/files/Md.tsx index 25d4205001..0c975043fd 100644 --- a/web/app/components/base/icons/src/public/files/Md.tsx +++ b/web/app/components/base/icons/src/public/files/Md.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/public/files/Pdf.tsx b/web/app/components/base/icons/src/public/files/Pdf.tsx index 15444df5b9..fe46fcfc3b 100644 --- a/web/app/components/base/icons/src/public/files/Pdf.tsx +++ b/web/app/components/base/icons/src/public/files/Pdf.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/public/files/Txt.tsx b/web/app/components/base/icons/src/public/files/Txt.tsx index 7b1f16ce62..f38b0e9c5c 100644 --- a/web/app/components/base/icons/src/public/files/Txt.tsx +++ b/web/app/components/base/icons/src/public/files/Txt.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/public/files/Unknown.tsx b/web/app/components/base/icons/src/public/files/Unknown.tsx index 1b7c658fb8..cd7686558f 100644 --- a/web/app/components/base/icons/src/public/files/Unknown.tsx +++ b/web/app/components/base/icons/src/public/files/Unknown.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/public/files/Xlsx.tsx b/web/app/components/base/icons/src/public/files/Xlsx.tsx index 399570bf15..e65f2ab4bc 100644 --- a/web/app/components/base/icons/src/public/files/Xlsx.tsx +++ b/web/app/components/base/icons/src/public/files/Xlsx.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/public/files/Yaml.tsx b/web/app/components/base/icons/src/public/files/Yaml.tsx index 5f95d27aad..6c20f412dd 100644 --- a/web/app/components/base/icons/src/public/files/Yaml.tsx +++ b/web/app/components/base/icons/src/public/files/Yaml.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/public/knowledge/Chunk.tsx b/web/app/components/base/icons/src/public/knowledge/Chunk.tsx index a01bd1eb3e..a16aef2b3d 100644 --- a/web/app/components/base/icons/src/public/knowledge/Chunk.tsx +++ b/web/app/components/base/icons/src/public/knowledge/Chunk.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/public/knowledge/Collapse.tsx b/web/app/components/base/icons/src/public/knowledge/Collapse.tsx index 6f43dde272..5b77a2eba5 100644 --- a/web/app/components/base/icons/src/public/knowledge/Collapse.tsx +++ b/web/app/components/base/icons/src/public/knowledge/Collapse.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/public/knowledge/GeneralType.tsx b/web/app/components/base/icons/src/public/knowledge/GeneralType.tsx index 29005b8d07..828dd823f6 100644 --- a/web/app/components/base/icons/src/public/knowledge/GeneralType.tsx +++ b/web/app/components/base/icons/src/public/knowledge/GeneralType.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/public/knowledge/LayoutRight2LineMod.tsx b/web/app/components/base/icons/src/public/knowledge/LayoutRight2LineMod.tsx index 18327cd649..6daef46784 100644 --- a/web/app/components/base/icons/src/public/knowledge/LayoutRight2LineMod.tsx +++ b/web/app/components/base/icons/src/public/knowledge/LayoutRight2LineMod.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/public/knowledge/ParentChildType.tsx b/web/app/components/base/icons/src/public/knowledge/ParentChildType.tsx index 107315002a..2bb75969d2 100644 --- a/web/app/components/base/icons/src/public/knowledge/ParentChildType.tsx +++ b/web/app/components/base/icons/src/public/knowledge/ParentChildType.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/public/knowledge/SelectionMod.tsx b/web/app/components/base/icons/src/public/knowledge/SelectionMod.tsx index a2d60fa9e5..dfd50736c0 100644 --- a/web/app/components/base/icons/src/public/knowledge/SelectionMod.tsx +++ b/web/app/components/base/icons/src/public/knowledge/SelectionMod.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/public/llm/Anthropic.tsx b/web/app/components/base/icons/src/public/llm/Anthropic.tsx index f5de0f5916..8ccf1f1c75 100644 --- a/web/app/components/base/icons/src/public/llm/Anthropic.tsx +++ b/web/app/components/base/icons/src/public/llm/Anthropic.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/public/llm/AnthropicDark.tsx b/web/app/components/base/icons/src/public/llm/AnthropicDark.tsx index d1744003d8..88374c33ae 100644 --- a/web/app/components/base/icons/src/public/llm/AnthropicDark.tsx +++ b/web/app/components/base/icons/src/public/llm/AnthropicDark.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/public/llm/AnthropicLight.tsx b/web/app/components/base/icons/src/public/llm/AnthropicLight.tsx index 0cacdf76ca..e2abff9c8f 100644 --- a/web/app/components/base/icons/src/public/llm/AnthropicLight.tsx +++ b/web/app/components/base/icons/src/public/llm/AnthropicLight.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/public/llm/AnthropicText.tsx b/web/app/components/base/icons/src/public/llm/AnthropicText.tsx index be9ebd3b64..62186fb1c3 100644 --- a/web/app/components/base/icons/src/public/llm/AnthropicText.tsx +++ b/web/app/components/base/icons/src/public/llm/AnthropicText.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/public/llm/AzureOpenaiService.tsx b/web/app/components/base/icons/src/public/llm/AzureOpenaiService.tsx index 9a82df1273..bb8e09a94f 100644 --- a/web/app/components/base/icons/src/public/llm/AzureOpenaiService.tsx +++ b/web/app/components/base/icons/src/public/llm/AzureOpenaiService.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/public/llm/AzureOpenaiServiceText.tsx b/web/app/components/base/icons/src/public/llm/AzureOpenaiServiceText.tsx index f91189a908..3f7fb68029 100644 --- a/web/app/components/base/icons/src/public/llm/AzureOpenaiServiceText.tsx +++ b/web/app/components/base/icons/src/public/llm/AzureOpenaiServiceText.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/public/llm/Azureai.tsx b/web/app/components/base/icons/src/public/llm/Azureai.tsx index bf7f2dac60..67109a7eff 100644 --- a/web/app/components/base/icons/src/public/llm/Azureai.tsx +++ b/web/app/components/base/icons/src/public/llm/Azureai.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/public/llm/AzureaiText.tsx b/web/app/components/base/icons/src/public/llm/AzureaiText.tsx index cd2376997b..21c5505699 100644 --- a/web/app/components/base/icons/src/public/llm/AzureaiText.tsx +++ b/web/app/components/base/icons/src/public/llm/AzureaiText.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/public/llm/Baichuan.tsx b/web/app/components/base/icons/src/public/llm/Baichuan.tsx index 363820b612..0f7c37b4b2 100644 --- a/web/app/components/base/icons/src/public/llm/Baichuan.tsx +++ b/web/app/components/base/icons/src/public/llm/Baichuan.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/public/llm/BaichuanText.tsx b/web/app/components/base/icons/src/public/llm/BaichuanText.tsx index 37d6242678..2e7269e508 100644 --- a/web/app/components/base/icons/src/public/llm/BaichuanText.tsx +++ b/web/app/components/base/icons/src/public/llm/BaichuanText.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/public/llm/Chatglm.tsx b/web/app/components/base/icons/src/public/llm/Chatglm.tsx index 742704fc77..6c2d36fe14 100644 --- a/web/app/components/base/icons/src/public/llm/Chatglm.tsx +++ b/web/app/components/base/icons/src/public/llm/Chatglm.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/public/llm/ChatglmText.tsx b/web/app/components/base/icons/src/public/llm/ChatglmText.tsx index e97f3fa912..868cc77fd0 100644 --- a/web/app/components/base/icons/src/public/llm/ChatglmText.tsx +++ b/web/app/components/base/icons/src/public/llm/ChatglmText.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/public/llm/Cohere.tsx b/web/app/components/base/icons/src/public/llm/Cohere.tsx index 1f16d1c010..68d4248a4f 100644 --- a/web/app/components/base/icons/src/public/llm/Cohere.tsx +++ b/web/app/components/base/icons/src/public/llm/Cohere.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/public/llm/CohereText.tsx b/web/app/components/base/icons/src/public/llm/CohereText.tsx index e6d5cebb51..1b89cc1f51 100644 --- a/web/app/components/base/icons/src/public/llm/CohereText.tsx +++ b/web/app/components/base/icons/src/public/llm/CohereText.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/public/llm/Gpt3.tsx b/web/app/components/base/icons/src/public/llm/Gpt3.tsx index 7926d50c7a..43565e3dbf 100644 --- a/web/app/components/base/icons/src/public/llm/Gpt3.tsx +++ b/web/app/components/base/icons/src/public/llm/Gpt3.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/public/llm/Gpt4.tsx b/web/app/components/base/icons/src/public/llm/Gpt4.tsx index 1fa170e054..ddcb97f600 100644 --- a/web/app/components/base/icons/src/public/llm/Gpt4.tsx +++ b/web/app/components/base/icons/src/public/llm/Gpt4.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/public/llm/Huggingface.tsx b/web/app/components/base/icons/src/public/llm/Huggingface.tsx index 1dcee1861a..5a8724050b 100644 --- a/web/app/components/base/icons/src/public/llm/Huggingface.tsx +++ b/web/app/components/base/icons/src/public/llm/Huggingface.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/public/llm/HuggingfaceText.tsx b/web/app/components/base/icons/src/public/llm/HuggingfaceText.tsx index 961d63e3db..81aa7e8ee8 100644 --- a/web/app/components/base/icons/src/public/llm/HuggingfaceText.tsx +++ b/web/app/components/base/icons/src/public/llm/HuggingfaceText.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/public/llm/HuggingfaceTextHub.tsx b/web/app/components/base/icons/src/public/llm/HuggingfaceTextHub.tsx index 47e3620e2b..b08d2c9300 100644 --- a/web/app/components/base/icons/src/public/llm/HuggingfaceTextHub.tsx +++ b/web/app/components/base/icons/src/public/llm/HuggingfaceTextHub.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/public/llm/IflytekSpark.tsx b/web/app/components/base/icons/src/public/llm/IflytekSpark.tsx index a2573a3e87..9eaf2eb68a 100644 --- a/web/app/components/base/icons/src/public/llm/IflytekSpark.tsx +++ b/web/app/components/base/icons/src/public/llm/IflytekSpark.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/public/llm/IflytekSparkText.tsx b/web/app/components/base/icons/src/public/llm/IflytekSparkText.tsx index 99abd56665..ca4df9f1aa 100644 --- a/web/app/components/base/icons/src/public/llm/IflytekSparkText.tsx +++ b/web/app/components/base/icons/src/public/llm/IflytekSparkText.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/public/llm/IflytekSparkTextCn.tsx b/web/app/components/base/icons/src/public/llm/IflytekSparkTextCn.tsx index 8f9d09e03e..f4c9524130 100644 --- a/web/app/components/base/icons/src/public/llm/IflytekSparkTextCn.tsx +++ b/web/app/components/base/icons/src/public/llm/IflytekSparkTextCn.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/public/llm/Jina.tsx b/web/app/components/base/icons/src/public/llm/Jina.tsx index 6fe24037de..103bd43ad3 100644 --- a/web/app/components/base/icons/src/public/llm/Jina.tsx +++ b/web/app/components/base/icons/src/public/llm/Jina.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/public/llm/JinaText.tsx b/web/app/components/base/icons/src/public/llm/JinaText.tsx index e5514a563b..c1fc15048f 100644 --- a/web/app/components/base/icons/src/public/llm/JinaText.tsx +++ b/web/app/components/base/icons/src/public/llm/JinaText.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/public/llm/Localai.tsx b/web/app/components/base/icons/src/public/llm/Localai.tsx index 731f00856d..cecca63d29 100644 --- a/web/app/components/base/icons/src/public/llm/Localai.tsx +++ b/web/app/components/base/icons/src/public/llm/Localai.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/public/llm/LocalaiText.tsx b/web/app/components/base/icons/src/public/llm/LocalaiText.tsx index aaea98adae..66d5ffea84 100644 --- a/web/app/components/base/icons/src/public/llm/LocalaiText.tsx +++ b/web/app/components/base/icons/src/public/llm/LocalaiText.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/public/llm/Microsoft.tsx b/web/app/components/base/icons/src/public/llm/Microsoft.tsx index 0b6e5dc4f2..675af132b5 100644 --- a/web/app/components/base/icons/src/public/llm/Microsoft.tsx +++ b/web/app/components/base/icons/src/public/llm/Microsoft.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/public/llm/OpenaiBlack.tsx b/web/app/components/base/icons/src/public/llm/OpenaiBlack.tsx index 1b9e3ec613..df5bb5f78b 100644 --- a/web/app/components/base/icons/src/public/llm/OpenaiBlack.tsx +++ b/web/app/components/base/icons/src/public/llm/OpenaiBlack.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/public/llm/OpenaiBlue.tsx b/web/app/components/base/icons/src/public/llm/OpenaiBlue.tsx index 3dc45a9695..15f557b067 100644 --- a/web/app/components/base/icons/src/public/llm/OpenaiBlue.tsx +++ b/web/app/components/base/icons/src/public/llm/OpenaiBlue.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/public/llm/OpenaiGreen.tsx b/web/app/components/base/icons/src/public/llm/OpenaiGreen.tsx index 36f967c255..d9e69b1f97 100644 --- a/web/app/components/base/icons/src/public/llm/OpenaiGreen.tsx +++ b/web/app/components/base/icons/src/public/llm/OpenaiGreen.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/public/llm/OpenaiTeal.tsx b/web/app/components/base/icons/src/public/llm/OpenaiTeal.tsx index ab50b42a1e..286c0446b2 100644 --- a/web/app/components/base/icons/src/public/llm/OpenaiTeal.tsx +++ b/web/app/components/base/icons/src/public/llm/OpenaiTeal.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/public/llm/OpenaiText.tsx b/web/app/components/base/icons/src/public/llm/OpenaiText.tsx index f07995d101..b5974ff068 100644 --- a/web/app/components/base/icons/src/public/llm/OpenaiText.tsx +++ b/web/app/components/base/icons/src/public/llm/OpenaiText.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/public/llm/OpenaiTransparent.tsx b/web/app/components/base/icons/src/public/llm/OpenaiTransparent.tsx index 0a90287cf2..fb98e27870 100644 --- a/web/app/components/base/icons/src/public/llm/OpenaiTransparent.tsx +++ b/web/app/components/base/icons/src/public/llm/OpenaiTransparent.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/public/llm/OpenaiViolet.tsx b/web/app/components/base/icons/src/public/llm/OpenaiViolet.tsx index 03e2864142..302cc91860 100644 --- a/web/app/components/base/icons/src/public/llm/OpenaiViolet.tsx +++ b/web/app/components/base/icons/src/public/llm/OpenaiViolet.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/public/llm/OpenaiYellow.tsx b/web/app/components/base/icons/src/public/llm/OpenaiYellow.tsx index 77dac7e322..9d3ec3088e 100644 --- a/web/app/components/base/icons/src/public/llm/OpenaiYellow.tsx +++ b/web/app/components/base/icons/src/public/llm/OpenaiYellow.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/public/llm/Openllm.tsx b/web/app/components/base/icons/src/public/llm/Openllm.tsx index 6497165f76..335fe9f9dd 100644 --- a/web/app/components/base/icons/src/public/llm/Openllm.tsx +++ b/web/app/components/base/icons/src/public/llm/Openllm.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/public/llm/OpenllmText.tsx b/web/app/components/base/icons/src/public/llm/OpenllmText.tsx index d1b6f6b22c..c9696a2cbb 100644 --- a/web/app/components/base/icons/src/public/llm/OpenllmText.tsx +++ b/web/app/components/base/icons/src/public/llm/OpenllmText.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/public/llm/Replicate.tsx b/web/app/components/base/icons/src/public/llm/Replicate.tsx index 237b68dbc8..11a76e0a9f 100644 --- a/web/app/components/base/icons/src/public/llm/Replicate.tsx +++ b/web/app/components/base/icons/src/public/llm/Replicate.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/public/llm/ReplicateText.tsx b/web/app/components/base/icons/src/public/llm/ReplicateText.tsx index 667b7d580c..1a2b13b527 100644 --- a/web/app/components/base/icons/src/public/llm/ReplicateText.tsx +++ b/web/app/components/base/icons/src/public/llm/ReplicateText.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/public/llm/XorbitsInference.tsx b/web/app/components/base/icons/src/public/llm/XorbitsInference.tsx index 8316ce3acb..c4663e7a6b 100644 --- a/web/app/components/base/icons/src/public/llm/XorbitsInference.tsx +++ b/web/app/components/base/icons/src/public/llm/XorbitsInference.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/public/llm/XorbitsInferenceText.tsx b/web/app/components/base/icons/src/public/llm/XorbitsInferenceText.tsx index fb834e709c..43539cd025 100644 --- a/web/app/components/base/icons/src/public/llm/XorbitsInferenceText.tsx +++ b/web/app/components/base/icons/src/public/llm/XorbitsInferenceText.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/public/llm/Zhipuai.tsx b/web/app/components/base/icons/src/public/llm/Zhipuai.tsx index d06244b8db..8d6493f8b3 100644 --- a/web/app/components/base/icons/src/public/llm/Zhipuai.tsx +++ b/web/app/components/base/icons/src/public/llm/Zhipuai.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/public/llm/ZhipuaiText.tsx b/web/app/components/base/icons/src/public/llm/ZhipuaiText.tsx index 600ca7c707..683bb7530d 100644 --- a/web/app/components/base/icons/src/public/llm/ZhipuaiText.tsx +++ b/web/app/components/base/icons/src/public/llm/ZhipuaiText.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/public/llm/ZhipuaiTextCn.tsx b/web/app/components/base/icons/src/public/llm/ZhipuaiTextCn.tsx index 53112419c3..2501b6e200 100644 --- a/web/app/components/base/icons/src/public/llm/ZhipuaiTextCn.tsx +++ b/web/app/components/base/icons/src/public/llm/ZhipuaiTextCn.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/public/model/Checked.tsx b/web/app/components/base/icons/src/public/model/Checked.tsx index ec8b54f7f8..7854479cd2 100644 --- a/web/app/components/base/icons/src/public/model/Checked.tsx +++ b/web/app/components/base/icons/src/public/model/Checked.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/public/other/DefaultToolIcon.tsx b/web/app/components/base/icons/src/public/other/DefaultToolIcon.tsx index dd28b8aa44..60c57606ac 100644 --- a/web/app/components/base/icons/src/public/other/DefaultToolIcon.tsx +++ b/web/app/components/base/icons/src/public/other/DefaultToolIcon.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/public/other/Icon3Dots.tsx b/web/app/components/base/icons/src/public/other/Icon3Dots.tsx index bcc2cee00e..7b2390f7c1 100644 --- a/web/app/components/base/icons/src/public/other/Icon3Dots.tsx +++ b/web/app/components/base/icons/src/public/other/Icon3Dots.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/public/other/Message3Fill.tsx b/web/app/components/base/icons/src/public/other/Message3Fill.tsx index 04113774f6..fc15d0375e 100644 --- a/web/app/components/base/icons/src/public/other/Message3Fill.tsx +++ b/web/app/components/base/icons/src/public/other/Message3Fill.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/public/other/RowStruct.tsx b/web/app/components/base/icons/src/public/other/RowStruct.tsx index 14487c8993..cb20dc973e 100644 --- a/web/app/components/base/icons/src/public/other/RowStruct.tsx +++ b/web/app/components/base/icons/src/public/other/RowStruct.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/public/plugins/Google.tsx b/web/app/components/base/icons/src/public/plugins/Google.tsx index 7d8d66730c..3e19ecd2f8 100644 --- a/web/app/components/base/icons/src/public/plugins/Google.tsx +++ b/web/app/components/base/icons/src/public/plugins/Google.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/public/plugins/PartnerDark.tsx b/web/app/components/base/icons/src/public/plugins/PartnerDark.tsx index 4277762921..c944657858 100644 --- a/web/app/components/base/icons/src/public/plugins/PartnerDark.tsx +++ b/web/app/components/base/icons/src/public/plugins/PartnerDark.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/public/plugins/PartnerLight.tsx b/web/app/components/base/icons/src/public/plugins/PartnerLight.tsx index 3591c963fc..072c6ed38c 100644 --- a/web/app/components/base/icons/src/public/plugins/PartnerLight.tsx +++ b/web/app/components/base/icons/src/public/plugins/PartnerLight.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/public/plugins/VerifiedDark.tsx b/web/app/components/base/icons/src/public/plugins/VerifiedDark.tsx index 03d045d158..783fc7f802 100644 --- a/web/app/components/base/icons/src/public/plugins/VerifiedDark.tsx +++ b/web/app/components/base/icons/src/public/plugins/VerifiedDark.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/public/plugins/VerifiedLight.tsx b/web/app/components/base/icons/src/public/plugins/VerifiedLight.tsx index 675a584605..65eb3a7d9f 100644 --- a/web/app/components/base/icons/src/public/plugins/VerifiedLight.tsx +++ b/web/app/components/base/icons/src/public/plugins/VerifiedLight.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/public/plugins/WebReader.tsx b/web/app/components/base/icons/src/public/plugins/WebReader.tsx index b23007d5ff..5606e32f88 100644 --- a/web/app/components/base/icons/src/public/plugins/WebReader.tsx +++ b/web/app/components/base/icons/src/public/plugins/WebReader.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/public/plugins/Wikipedia.tsx b/web/app/components/base/icons/src/public/plugins/Wikipedia.tsx index 0477e9cc96..c2fde5c1f8 100644 --- a/web/app/components/base/icons/src/public/plugins/Wikipedia.tsx +++ b/web/app/components/base/icons/src/public/plugins/Wikipedia.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/public/thought/DataSet.tsx b/web/app/components/base/icons/src/public/thought/DataSet.tsx index 28c38c302e..f35ff4efbc 100644 --- a/web/app/components/base/icons/src/public/thought/DataSet.tsx +++ b/web/app/components/base/icons/src/public/thought/DataSet.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/public/thought/Loading.tsx b/web/app/components/base/icons/src/public/thought/Loading.tsx index 11389b8231..af959fba40 100644 --- a/web/app/components/base/icons/src/public/thought/Loading.tsx +++ b/web/app/components/base/icons/src/public/thought/Loading.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/public/thought/Search.tsx b/web/app/components/base/icons/src/public/thought/Search.tsx index 2f469d20af..ecd98048d5 100644 --- a/web/app/components/base/icons/src/public/thought/Search.tsx +++ b/web/app/components/base/icons/src/public/thought/Search.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/public/thought/ThoughtList.tsx b/web/app/components/base/icons/src/public/thought/ThoughtList.tsx index 99b42aebee..e7f0e312ef 100644 --- a/web/app/components/base/icons/src/public/thought/ThoughtList.tsx +++ b/web/app/components/base/icons/src/public/thought/ThoughtList.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/public/thought/WebReader.tsx b/web/app/components/base/icons/src/public/thought/WebReader.tsx index b23007d5ff..5606e32f88 100644 --- a/web/app/components/base/icons/src/public/thought/WebReader.tsx +++ b/web/app/components/base/icons/src/public/thought/WebReader.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/public/tracing/AliyunIcon.tsx b/web/app/components/base/icons/src/public/tracing/AliyunIcon.tsx index c7f785d9fb..b233736472 100644 --- a/web/app/components/base/icons/src/public/tracing/AliyunIcon.tsx +++ b/web/app/components/base/icons/src/public/tracing/AliyunIcon.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/public/tracing/AliyunIconBig.tsx b/web/app/components/base/icons/src/public/tracing/AliyunIconBig.tsx index 703ea1d37f..3e9bc7f0ef 100644 --- a/web/app/components/base/icons/src/public/tracing/AliyunIconBig.tsx +++ b/web/app/components/base/icons/src/public/tracing/AliyunIconBig.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/public/tracing/ArizeIcon.tsx b/web/app/components/base/icons/src/public/tracing/ArizeIcon.tsx index dac1ec280e..77ca0d3194 100644 --- a/web/app/components/base/icons/src/public/tracing/ArizeIcon.tsx +++ b/web/app/components/base/icons/src/public/tracing/ArizeIcon.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/public/tracing/ArizeIconBig.tsx b/web/app/components/base/icons/src/public/tracing/ArizeIconBig.tsx index f817b481e3..ad3117b768 100644 --- a/web/app/components/base/icons/src/public/tracing/ArizeIconBig.tsx +++ b/web/app/components/base/icons/src/public/tracing/ArizeIconBig.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/public/tracing/LangfuseIcon.tsx b/web/app/components/base/icons/src/public/tracing/LangfuseIcon.tsx index 7f0f115fef..d71702c0bf 100644 --- a/web/app/components/base/icons/src/public/tracing/LangfuseIcon.tsx +++ b/web/app/components/base/icons/src/public/tracing/LangfuseIcon.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/public/tracing/LangfuseIconBig.tsx b/web/app/components/base/icons/src/public/tracing/LangfuseIconBig.tsx index 69ac5aaa45..ddf36fee6e 100644 --- a/web/app/components/base/icons/src/public/tracing/LangfuseIconBig.tsx +++ b/web/app/components/base/icons/src/public/tracing/LangfuseIconBig.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/public/tracing/LangsmithIcon.tsx b/web/app/components/base/icons/src/public/tracing/LangsmithIcon.tsx index 696442c7eb..b09f883125 100644 --- a/web/app/components/base/icons/src/public/tracing/LangsmithIcon.tsx +++ b/web/app/components/base/icons/src/public/tracing/LangsmithIcon.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/public/tracing/LangsmithIconBig.tsx b/web/app/components/base/icons/src/public/tracing/LangsmithIconBig.tsx index 2e652d53f5..fd6ce2ea7e 100644 --- a/web/app/components/base/icons/src/public/tracing/LangsmithIconBig.tsx +++ b/web/app/components/base/icons/src/public/tracing/LangsmithIconBig.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/public/tracing/OpikIcon.tsx b/web/app/components/base/icons/src/public/tracing/OpikIcon.tsx index 9f114fb56e..4125f25d4a 100644 --- a/web/app/components/base/icons/src/public/tracing/OpikIcon.tsx +++ b/web/app/components/base/icons/src/public/tracing/OpikIcon.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/public/tracing/OpikIconBig.tsx b/web/app/components/base/icons/src/public/tracing/OpikIconBig.tsx index 643312b407..298df57b37 100644 --- a/web/app/components/base/icons/src/public/tracing/OpikIconBig.tsx +++ b/web/app/components/base/icons/src/public/tracing/OpikIconBig.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/public/tracing/PhoenixIcon.tsx b/web/app/components/base/icons/src/public/tracing/PhoenixIcon.tsx index e0d36e065d..1812f86093 100644 --- a/web/app/components/base/icons/src/public/tracing/PhoenixIcon.tsx +++ b/web/app/components/base/icons/src/public/tracing/PhoenixIcon.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/public/tracing/PhoenixIconBig.tsx b/web/app/components/base/icons/src/public/tracing/PhoenixIconBig.tsx index 9131e6bea6..9d059e928e 100644 --- a/web/app/components/base/icons/src/public/tracing/PhoenixIconBig.tsx +++ b/web/app/components/base/icons/src/public/tracing/PhoenixIconBig.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/public/tracing/TracingIcon.tsx b/web/app/components/base/icons/src/public/tracing/TracingIcon.tsx index 1f1e8d337c..495829d395 100644 --- a/web/app/components/base/icons/src/public/tracing/TracingIcon.tsx +++ b/web/app/components/base/icons/src/public/tracing/TracingIcon.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/public/tracing/WeaveIcon.tsx b/web/app/components/base/icons/src/public/tracing/WeaveIcon.tsx index 9261604bfe..3c9a1acf0a 100644 --- a/web/app/components/base/icons/src/public/tracing/WeaveIcon.tsx +++ b/web/app/components/base/icons/src/public/tracing/WeaveIcon.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/public/tracing/WeaveIconBig.tsx b/web/app/components/base/icons/src/public/tracing/WeaveIconBig.tsx index 79267467db..ea2b4f11b4 100644 --- a/web/app/components/base/icons/src/public/tracing/WeaveIconBig.tsx +++ b/web/app/components/base/icons/src/public/tracing/WeaveIconBig.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/vender/features/Citations.tsx b/web/app/components/base/icons/src/vender/features/Citations.tsx index 439aab6584..08a73bf99a 100644 --- a/web/app/components/base/icons/src/vender/features/Citations.tsx +++ b/web/app/components/base/icons/src/vender/features/Citations.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/vender/features/ContentModeration.tsx b/web/app/components/base/icons/src/vender/features/ContentModeration.tsx index baf9629d3d..e08262ad94 100644 --- a/web/app/components/base/icons/src/vender/features/ContentModeration.tsx +++ b/web/app/components/base/icons/src/vender/features/ContentModeration.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/vender/features/Document.tsx b/web/app/components/base/icons/src/vender/features/Document.tsx index 05c0180bb1..448493bd5c 100644 --- a/web/app/components/base/icons/src/vender/features/Document.tsx +++ b/web/app/components/base/icons/src/vender/features/Document.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/vender/features/FolderUpload.tsx b/web/app/components/base/icons/src/vender/features/FolderUpload.tsx index 27b38aef5f..9e34c438a8 100644 --- a/web/app/components/base/icons/src/vender/features/FolderUpload.tsx +++ b/web/app/components/base/icons/src/vender/features/FolderUpload.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/vender/features/LoveMessage.tsx b/web/app/components/base/icons/src/vender/features/LoveMessage.tsx index c4cdcfdbd3..1a5b4b65a6 100644 --- a/web/app/components/base/icons/src/vender/features/LoveMessage.tsx +++ b/web/app/components/base/icons/src/vender/features/LoveMessage.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/vender/features/MessageFast.tsx b/web/app/components/base/icons/src/vender/features/MessageFast.tsx index 45a1e77b18..efa7b15821 100644 --- a/web/app/components/base/icons/src/vender/features/MessageFast.tsx +++ b/web/app/components/base/icons/src/vender/features/MessageFast.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/vender/features/Microphone01.tsx b/web/app/components/base/icons/src/vender/features/Microphone01.tsx index 37fb66a887..c76cc607e4 100644 --- a/web/app/components/base/icons/src/vender/features/Microphone01.tsx +++ b/web/app/components/base/icons/src/vender/features/Microphone01.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/vender/features/TextToAudio.tsx b/web/app/components/base/icons/src/vender/features/TextToAudio.tsx index 1f94c1056d..3394009594 100644 --- a/web/app/components/base/icons/src/vender/features/TextToAudio.tsx +++ b/web/app/components/base/icons/src/vender/features/TextToAudio.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/vender/features/VirtualAssistant.tsx b/web/app/components/base/icons/src/vender/features/VirtualAssistant.tsx index eeb64a1b67..532fe6d02e 100644 --- a/web/app/components/base/icons/src/vender/features/VirtualAssistant.tsx +++ b/web/app/components/base/icons/src/vender/features/VirtualAssistant.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/vender/features/Vision.tsx b/web/app/components/base/icons/src/vender/features/Vision.tsx index 7b6cbf6406..6532428973 100644 --- a/web/app/components/base/icons/src/vender/features/Vision.tsx +++ b/web/app/components/base/icons/src/vender/features/Vision.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/vender/line/alertsAndFeedback/AlertTriangle.tsx b/web/app/components/base/icons/src/vender/line/alertsAndFeedback/AlertTriangle.tsx index cceacb9f32..465c638547 100644 --- a/web/app/components/base/icons/src/vender/line/alertsAndFeedback/AlertTriangle.tsx +++ b/web/app/components/base/icons/src/vender/line/alertsAndFeedback/AlertTriangle.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/vender/line/alertsAndFeedback/ThumbsDown.tsx b/web/app/components/base/icons/src/vender/line/alertsAndFeedback/ThumbsDown.tsx index f2efee64cc..6f675fe9d7 100644 --- a/web/app/components/base/icons/src/vender/line/alertsAndFeedback/ThumbsDown.tsx +++ b/web/app/components/base/icons/src/vender/line/alertsAndFeedback/ThumbsDown.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/vender/line/alertsAndFeedback/ThumbsUp.tsx b/web/app/components/base/icons/src/vender/line/alertsAndFeedback/ThumbsUp.tsx index dadd80c64d..e4cb8ccb72 100644 --- a/web/app/components/base/icons/src/vender/line/alertsAndFeedback/ThumbsUp.tsx +++ b/web/app/components/base/icons/src/vender/line/alertsAndFeedback/ThumbsUp.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/vender/line/arrows/ArrowNarrowLeft.tsx b/web/app/components/base/icons/src/vender/line/arrows/ArrowNarrowLeft.tsx index 1c3b82edd9..9731f85581 100644 --- a/web/app/components/base/icons/src/vender/line/arrows/ArrowNarrowLeft.tsx +++ b/web/app/components/base/icons/src/vender/line/arrows/ArrowNarrowLeft.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/vender/line/arrows/ArrowUpRight.tsx b/web/app/components/base/icons/src/vender/line/arrows/ArrowUpRight.tsx index 6c3293fe6f..f100e54042 100644 --- a/web/app/components/base/icons/src/vender/line/arrows/ArrowUpRight.tsx +++ b/web/app/components/base/icons/src/vender/line/arrows/ArrowUpRight.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/vender/line/arrows/ChevronDownDouble.tsx b/web/app/components/base/icons/src/vender/line/arrows/ChevronDownDouble.tsx index aa134fa68b..a8ee02f1c0 100644 --- a/web/app/components/base/icons/src/vender/line/arrows/ChevronDownDouble.tsx +++ b/web/app/components/base/icons/src/vender/line/arrows/ChevronDownDouble.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/vender/line/arrows/ChevronRight.tsx b/web/app/components/base/icons/src/vender/line/arrows/ChevronRight.tsx index befecea5be..95233770c5 100644 --- a/web/app/components/base/icons/src/vender/line/arrows/ChevronRight.tsx +++ b/web/app/components/base/icons/src/vender/line/arrows/ChevronRight.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/vender/line/arrows/ChevronSelectorVertical.tsx b/web/app/components/base/icons/src/vender/line/arrows/ChevronSelectorVertical.tsx index 7c19420500..50538a81ac 100644 --- a/web/app/components/base/icons/src/vender/line/arrows/ChevronSelectorVertical.tsx +++ b/web/app/components/base/icons/src/vender/line/arrows/ChevronSelectorVertical.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/vender/line/arrows/RefreshCcw01.tsx b/web/app/components/base/icons/src/vender/line/arrows/RefreshCcw01.tsx index f0caf7359e..10bb8c8912 100644 --- a/web/app/components/base/icons/src/vender/line/arrows/RefreshCcw01.tsx +++ b/web/app/components/base/icons/src/vender/line/arrows/RefreshCcw01.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/vender/line/arrows/RefreshCw05.tsx b/web/app/components/base/icons/src/vender/line/arrows/RefreshCw05.tsx index b426871c18..49dbf58926 100644 --- a/web/app/components/base/icons/src/vender/line/arrows/RefreshCw05.tsx +++ b/web/app/components/base/icons/src/vender/line/arrows/RefreshCw05.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/vender/line/arrows/ReverseLeft.tsx b/web/app/components/base/icons/src/vender/line/arrows/ReverseLeft.tsx index 30a2e3ab58..5656eb5e7c 100644 --- a/web/app/components/base/icons/src/vender/line/arrows/ReverseLeft.tsx +++ b/web/app/components/base/icons/src/vender/line/arrows/ReverseLeft.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/vender/line/communication/AiText.tsx b/web/app/components/base/icons/src/vender/line/communication/AiText.tsx index c1a6a2495c..7d5a860038 100644 --- a/web/app/components/base/icons/src/vender/line/communication/AiText.tsx +++ b/web/app/components/base/icons/src/vender/line/communication/AiText.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/vender/line/communication/ChatBot.tsx b/web/app/components/base/icons/src/vender/line/communication/ChatBot.tsx index 867ae313b5..6f44bec6d1 100644 --- a/web/app/components/base/icons/src/vender/line/communication/ChatBot.tsx +++ b/web/app/components/base/icons/src/vender/line/communication/ChatBot.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/vender/line/communication/ChatBotSlim.tsx b/web/app/components/base/icons/src/vender/line/communication/ChatBotSlim.tsx index 1950a4295b..77adb96a74 100644 --- a/web/app/components/base/icons/src/vender/line/communication/ChatBotSlim.tsx +++ b/web/app/components/base/icons/src/vender/line/communication/ChatBotSlim.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/vender/line/communication/CuteRobot.tsx b/web/app/components/base/icons/src/vender/line/communication/CuteRobot.tsx index 526bb7734b..576c73a611 100644 --- a/web/app/components/base/icons/src/vender/line/communication/CuteRobot.tsx +++ b/web/app/components/base/icons/src/vender/line/communication/CuteRobot.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/vender/line/communication/MessageCheckRemove.tsx b/web/app/components/base/icons/src/vender/line/communication/MessageCheckRemove.tsx index fac727bae2..d68d14fd2b 100644 --- a/web/app/components/base/icons/src/vender/line/communication/MessageCheckRemove.tsx +++ b/web/app/components/base/icons/src/vender/line/communication/MessageCheckRemove.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/vender/line/communication/MessageFastPlus.tsx b/web/app/components/base/icons/src/vender/line/communication/MessageFastPlus.tsx index 444668797c..20a6612c5e 100644 --- a/web/app/components/base/icons/src/vender/line/communication/MessageFastPlus.tsx +++ b/web/app/components/base/icons/src/vender/line/communication/MessageFastPlus.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/vender/line/development/ArtificialBrain.tsx b/web/app/components/base/icons/src/vender/line/development/ArtificialBrain.tsx index cefb404ca2..8c11be610b 100644 --- a/web/app/components/base/icons/src/vender/line/development/ArtificialBrain.tsx +++ b/web/app/components/base/icons/src/vender/line/development/ArtificialBrain.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/vender/line/development/BarChartSquare02.tsx b/web/app/components/base/icons/src/vender/line/development/BarChartSquare02.tsx index c8a335785d..c19303e0e2 100644 --- a/web/app/components/base/icons/src/vender/line/development/BarChartSquare02.tsx +++ b/web/app/components/base/icons/src/vender/line/development/BarChartSquare02.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/vender/line/development/BracketsX.tsx b/web/app/components/base/icons/src/vender/line/development/BracketsX.tsx index 84cc1d2dac..5a608baa66 100644 --- a/web/app/components/base/icons/src/vender/line/development/BracketsX.tsx +++ b/web/app/components/base/icons/src/vender/line/development/BracketsX.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/vender/line/development/CodeBrowser.tsx b/web/app/components/base/icons/src/vender/line/development/CodeBrowser.tsx index fd402ed617..94c63a4dcb 100644 --- a/web/app/components/base/icons/src/vender/line/development/CodeBrowser.tsx +++ b/web/app/components/base/icons/src/vender/line/development/CodeBrowser.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/vender/line/development/Container.tsx b/web/app/components/base/icons/src/vender/line/development/Container.tsx index 2aa777a256..70e1397c71 100644 --- a/web/app/components/base/icons/src/vender/line/development/Container.tsx +++ b/web/app/components/base/icons/src/vender/line/development/Container.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/vender/line/development/Database01.tsx b/web/app/components/base/icons/src/vender/line/development/Database01.tsx index 55a67f8e32..6623a75927 100644 --- a/web/app/components/base/icons/src/vender/line/development/Database01.tsx +++ b/web/app/components/base/icons/src/vender/line/development/Database01.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/vender/line/development/Database03.tsx b/web/app/components/base/icons/src/vender/line/development/Database03.tsx index 012294ad7b..97e629337b 100644 --- a/web/app/components/base/icons/src/vender/line/development/Database03.tsx +++ b/web/app/components/base/icons/src/vender/line/development/Database03.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/vender/line/development/FileHeart02.tsx b/web/app/components/base/icons/src/vender/line/development/FileHeart02.tsx index e918e5e491..d829b4b85a 100644 --- a/web/app/components/base/icons/src/vender/line/development/FileHeart02.tsx +++ b/web/app/components/base/icons/src/vender/line/development/FileHeart02.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/vender/line/development/GitBranch01.tsx b/web/app/components/base/icons/src/vender/line/development/GitBranch01.tsx index 15343eb5d9..572d1b7689 100644 --- a/web/app/components/base/icons/src/vender/line/development/GitBranch01.tsx +++ b/web/app/components/base/icons/src/vender/line/development/GitBranch01.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/vender/line/development/PromptEngineering.tsx b/web/app/components/base/icons/src/vender/line/development/PromptEngineering.tsx index 506e9fe5ca..57729d4066 100644 --- a/web/app/components/base/icons/src/vender/line/development/PromptEngineering.tsx +++ b/web/app/components/base/icons/src/vender/line/development/PromptEngineering.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/vender/line/development/PuzzlePiece01.tsx b/web/app/components/base/icons/src/vender/line/development/PuzzlePiece01.tsx index b62d37d7c0..b78592690c 100644 --- a/web/app/components/base/icons/src/vender/line/development/PuzzlePiece01.tsx +++ b/web/app/components/base/icons/src/vender/line/development/PuzzlePiece01.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/vender/line/development/TerminalSquare.tsx b/web/app/components/base/icons/src/vender/line/development/TerminalSquare.tsx index 38575b9f9f..1add0ad7e4 100644 --- a/web/app/components/base/icons/src/vender/line/development/TerminalSquare.tsx +++ b/web/app/components/base/icons/src/vender/line/development/TerminalSquare.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/vender/line/development/Variable.tsx b/web/app/components/base/icons/src/vender/line/development/Variable.tsx index 3f2844a0aa..5ee57ce909 100644 --- a/web/app/components/base/icons/src/vender/line/development/Variable.tsx +++ b/web/app/components/base/icons/src/vender/line/development/Variable.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/vender/line/development/Webhooks.tsx b/web/app/components/base/icons/src/vender/line/development/Webhooks.tsx index 61dc2078a4..966a79a537 100644 --- a/web/app/components/base/icons/src/vender/line/development/Webhooks.tsx +++ b/web/app/components/base/icons/src/vender/line/development/Webhooks.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/vender/line/editor/AlignLeft.tsx b/web/app/components/base/icons/src/vender/line/editor/AlignLeft.tsx index 6d8c83f2fa..4c1d88eef9 100644 --- a/web/app/components/base/icons/src/vender/line/editor/AlignLeft.tsx +++ b/web/app/components/base/icons/src/vender/line/editor/AlignLeft.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/vender/line/editor/BezierCurve03.tsx b/web/app/components/base/icons/src/vender/line/editor/BezierCurve03.tsx index 5bea9013d0..7019495437 100644 --- a/web/app/components/base/icons/src/vender/line/editor/BezierCurve03.tsx +++ b/web/app/components/base/icons/src/vender/line/editor/BezierCurve03.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/vender/line/editor/Collapse.tsx b/web/app/components/base/icons/src/vender/line/editor/Collapse.tsx index 6f43dde272..5b77a2eba5 100644 --- a/web/app/components/base/icons/src/vender/line/editor/Collapse.tsx +++ b/web/app/components/base/icons/src/vender/line/editor/Collapse.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/vender/line/editor/Colors.tsx b/web/app/components/base/icons/src/vender/line/editor/Colors.tsx index bdfe6d1b90..ef04c1c5dc 100644 --- a/web/app/components/base/icons/src/vender/line/editor/Colors.tsx +++ b/web/app/components/base/icons/src/vender/line/editor/Colors.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/vender/line/editor/ImageIndentLeft.tsx b/web/app/components/base/icons/src/vender/line/editor/ImageIndentLeft.tsx index 957c12c4b0..63fce72d66 100644 --- a/web/app/components/base/icons/src/vender/line/editor/ImageIndentLeft.tsx +++ b/web/app/components/base/icons/src/vender/line/editor/ImageIndentLeft.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/vender/line/editor/LeftIndent02.tsx b/web/app/components/base/icons/src/vender/line/editor/LeftIndent02.tsx index 96ae01c9d4..de16320324 100644 --- a/web/app/components/base/icons/src/vender/line/editor/LeftIndent02.tsx +++ b/web/app/components/base/icons/src/vender/line/editor/LeftIndent02.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/vender/line/editor/LetterSpacing01.tsx b/web/app/components/base/icons/src/vender/line/editor/LetterSpacing01.tsx index e6bc4cea6b..777e056389 100644 --- a/web/app/components/base/icons/src/vender/line/editor/LetterSpacing01.tsx +++ b/web/app/components/base/icons/src/vender/line/editor/LetterSpacing01.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/vender/line/editor/TypeSquare.tsx b/web/app/components/base/icons/src/vender/line/editor/TypeSquare.tsx index 5149e12b85..a94ab1fe23 100644 --- a/web/app/components/base/icons/src/vender/line/editor/TypeSquare.tsx +++ b/web/app/components/base/icons/src/vender/line/editor/TypeSquare.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/vender/line/education/BookOpen01.tsx b/web/app/components/base/icons/src/vender/line/education/BookOpen01.tsx index b362119ac2..81d40fb689 100644 --- a/web/app/components/base/icons/src/vender/line/education/BookOpen01.tsx +++ b/web/app/components/base/icons/src/vender/line/education/BookOpen01.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/vender/line/files/Copy.tsx b/web/app/components/base/icons/src/vender/line/files/Copy.tsx index 155b825fa1..8d2a4d9f2d 100644 --- a/web/app/components/base/icons/src/vender/line/files/Copy.tsx +++ b/web/app/components/base/icons/src/vender/line/files/Copy.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/vender/line/files/CopyCheck.tsx b/web/app/components/base/icons/src/vender/line/files/CopyCheck.tsx index 90eca4c04d..7939d3f552 100644 --- a/web/app/components/base/icons/src/vender/line/files/CopyCheck.tsx +++ b/web/app/components/base/icons/src/vender/line/files/CopyCheck.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/vender/line/files/File02.tsx b/web/app/components/base/icons/src/vender/line/files/File02.tsx index 8c53308316..c51f1d4808 100644 --- a/web/app/components/base/icons/src/vender/line/files/File02.tsx +++ b/web/app/components/base/icons/src/vender/line/files/File02.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/vender/line/files/FileArrow01.tsx b/web/app/components/base/icons/src/vender/line/files/FileArrow01.tsx index c0f42071ad..562b165c9d 100644 --- a/web/app/components/base/icons/src/vender/line/files/FileArrow01.tsx +++ b/web/app/components/base/icons/src/vender/line/files/FileArrow01.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/vender/line/files/FileCheck02.tsx b/web/app/components/base/icons/src/vender/line/files/FileCheck02.tsx index 0bb51a3181..fa32b308e3 100644 --- a/web/app/components/base/icons/src/vender/line/files/FileCheck02.tsx +++ b/web/app/components/base/icons/src/vender/line/files/FileCheck02.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/vender/line/files/FileDownload02.tsx b/web/app/components/base/icons/src/vender/line/files/FileDownload02.tsx index 5dac794d95..7d6528694b 100644 --- a/web/app/components/base/icons/src/vender/line/files/FileDownload02.tsx +++ b/web/app/components/base/icons/src/vender/line/files/FileDownload02.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/vender/line/files/FilePlus01.tsx b/web/app/components/base/icons/src/vender/line/files/FilePlus01.tsx index d33f4b5637..bce1a388c5 100644 --- a/web/app/components/base/icons/src/vender/line/files/FilePlus01.tsx +++ b/web/app/components/base/icons/src/vender/line/files/FilePlus01.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/vender/line/files/FilePlus02.tsx b/web/app/components/base/icons/src/vender/line/files/FilePlus02.tsx index 5405325d99..5d4ba8e542 100644 --- a/web/app/components/base/icons/src/vender/line/files/FilePlus02.tsx +++ b/web/app/components/base/icons/src/vender/line/files/FilePlus02.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/vender/line/files/FileText.tsx b/web/app/components/base/icons/src/vender/line/files/FileText.tsx index 9c64082dbe..fa2d0f098c 100644 --- a/web/app/components/base/icons/src/vender/line/files/FileText.tsx +++ b/web/app/components/base/icons/src/vender/line/files/FileText.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/vender/line/files/FileUpload.tsx b/web/app/components/base/icons/src/vender/line/files/FileUpload.tsx index 2e3143d992..766f19dffb 100644 --- a/web/app/components/base/icons/src/vender/line/files/FileUpload.tsx +++ b/web/app/components/base/icons/src/vender/line/files/FileUpload.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/vender/line/files/Folder.tsx b/web/app/components/base/icons/src/vender/line/files/Folder.tsx index e7a3fdf167..c5c3ea5b72 100644 --- a/web/app/components/base/icons/src/vender/line/files/Folder.tsx +++ b/web/app/components/base/icons/src/vender/line/files/Folder.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/vender/line/financeAndECommerce/Balance.tsx b/web/app/components/base/icons/src/vender/line/financeAndECommerce/Balance.tsx index f2d4b1bd89..2ea9b0c7f1 100644 --- a/web/app/components/base/icons/src/vender/line/financeAndECommerce/Balance.tsx +++ b/web/app/components/base/icons/src/vender/line/financeAndECommerce/Balance.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/vender/line/financeAndECommerce/CoinsStacked01.tsx b/web/app/components/base/icons/src/vender/line/financeAndECommerce/CoinsStacked01.tsx index 7eb20edb90..ff094d5f9c 100644 --- a/web/app/components/base/icons/src/vender/line/financeAndECommerce/CoinsStacked01.tsx +++ b/web/app/components/base/icons/src/vender/line/financeAndECommerce/CoinsStacked01.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/vender/line/financeAndECommerce/GoldCoin.tsx b/web/app/components/base/icons/src/vender/line/financeAndECommerce/GoldCoin.tsx index d912a6b2b0..c4147aff78 100644 --- a/web/app/components/base/icons/src/vender/line/financeAndECommerce/GoldCoin.tsx +++ b/web/app/components/base/icons/src/vender/line/financeAndECommerce/GoldCoin.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/vender/line/financeAndECommerce/ReceiptList.tsx b/web/app/components/base/icons/src/vender/line/financeAndECommerce/ReceiptList.tsx index e96aced5f4..637c386911 100644 --- a/web/app/components/base/icons/src/vender/line/financeAndECommerce/ReceiptList.tsx +++ b/web/app/components/base/icons/src/vender/line/financeAndECommerce/ReceiptList.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/vender/line/financeAndECommerce/Tag01.tsx b/web/app/components/base/icons/src/vender/line/financeAndECommerce/Tag01.tsx index c8b1ce2890..cb58ca1e54 100644 --- a/web/app/components/base/icons/src/vender/line/financeAndECommerce/Tag01.tsx +++ b/web/app/components/base/icons/src/vender/line/financeAndECommerce/Tag01.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/vender/line/financeAndECommerce/Tag03.tsx b/web/app/components/base/icons/src/vender/line/financeAndECommerce/Tag03.tsx index c0ec1bbb08..c28f6c042f 100644 --- a/web/app/components/base/icons/src/vender/line/financeAndECommerce/Tag03.tsx +++ b/web/app/components/base/icons/src/vender/line/financeAndECommerce/Tag03.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/vender/line/general/AtSign.tsx b/web/app/components/base/icons/src/vender/line/general/AtSign.tsx index 44c972bae0..a66020fae9 100644 --- a/web/app/components/base/icons/src/vender/line/general/AtSign.tsx +++ b/web/app/components/base/icons/src/vender/line/general/AtSign.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/vender/line/general/Bookmark.tsx b/web/app/components/base/icons/src/vender/line/general/Bookmark.tsx index 6708376e54..bec0be814e 100644 --- a/web/app/components/base/icons/src/vender/line/general/Bookmark.tsx +++ b/web/app/components/base/icons/src/vender/line/general/Bookmark.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/vender/line/general/Check.tsx b/web/app/components/base/icons/src/vender/line/general/Check.tsx index babd2021c1..5992a006b5 100644 --- a/web/app/components/base/icons/src/vender/line/general/Check.tsx +++ b/web/app/components/base/icons/src/vender/line/general/Check.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/vender/line/general/CheckDone01.tsx b/web/app/components/base/icons/src/vender/line/general/CheckDone01.tsx index c7e7d80c6c..0119a7d0a2 100644 --- a/web/app/components/base/icons/src/vender/line/general/CheckDone01.tsx +++ b/web/app/components/base/icons/src/vender/line/general/CheckDone01.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/vender/line/general/ChecklistSquare.tsx b/web/app/components/base/icons/src/vender/line/general/ChecklistSquare.tsx index 8fb72f0ef0..1f65ce6aba 100644 --- a/web/app/components/base/icons/src/vender/line/general/ChecklistSquare.tsx +++ b/web/app/components/base/icons/src/vender/line/general/ChecklistSquare.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/vender/line/general/CodeAssistant.tsx b/web/app/components/base/icons/src/vender/line/general/CodeAssistant.tsx index 71adb145fb..0176131569 100644 --- a/web/app/components/base/icons/src/vender/line/general/CodeAssistant.tsx +++ b/web/app/components/base/icons/src/vender/line/general/CodeAssistant.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/vender/line/general/DotsGrid.tsx b/web/app/components/base/icons/src/vender/line/general/DotsGrid.tsx index fb272fda74..c5bb38b714 100644 --- a/web/app/components/base/icons/src/vender/line/general/DotsGrid.tsx +++ b/web/app/components/base/icons/src/vender/line/general/DotsGrid.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/vender/line/general/Edit02.tsx b/web/app/components/base/icons/src/vender/line/general/Edit02.tsx index 10ba0f58d4..7ab863787f 100644 --- a/web/app/components/base/icons/src/vender/line/general/Edit02.tsx +++ b/web/app/components/base/icons/src/vender/line/general/Edit02.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/vender/line/general/Edit04.tsx b/web/app/components/base/icons/src/vender/line/general/Edit04.tsx index 5e436c0e25..39b598d067 100644 --- a/web/app/components/base/icons/src/vender/line/general/Edit04.tsx +++ b/web/app/components/base/icons/src/vender/line/general/Edit04.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/vender/line/general/Edit05.tsx b/web/app/components/base/icons/src/vender/line/general/Edit05.tsx index f6904bb60a..ddf85758b4 100644 --- a/web/app/components/base/icons/src/vender/line/general/Edit05.tsx +++ b/web/app/components/base/icons/src/vender/line/general/Edit05.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/vender/line/general/Hash02.tsx b/web/app/components/base/icons/src/vender/line/general/Hash02.tsx index fa8bdfbcda..1455da0a2f 100644 --- a/web/app/components/base/icons/src/vender/line/general/Hash02.tsx +++ b/web/app/components/base/icons/src/vender/line/general/Hash02.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/vender/line/general/InfoCircle.tsx b/web/app/components/base/icons/src/vender/line/general/InfoCircle.tsx index 3f1d59a265..b7c9b61131 100644 --- a/web/app/components/base/icons/src/vender/line/general/InfoCircle.tsx +++ b/web/app/components/base/icons/src/vender/line/general/InfoCircle.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/vender/line/general/Link03.tsx b/web/app/components/base/icons/src/vender/line/general/Link03.tsx index 1a0c3e130d..98a61acdca 100644 --- a/web/app/components/base/icons/src/vender/line/general/Link03.tsx +++ b/web/app/components/base/icons/src/vender/line/general/Link03.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/vender/line/general/LinkExternal02.tsx b/web/app/components/base/icons/src/vender/line/general/LinkExternal02.tsx index 58d502d090..a8d5977a21 100644 --- a/web/app/components/base/icons/src/vender/line/general/LinkExternal02.tsx +++ b/web/app/components/base/icons/src/vender/line/general/LinkExternal02.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/vender/line/general/LogIn04.tsx b/web/app/components/base/icons/src/vender/line/general/LogIn04.tsx index 6d2fbfcdb5..234cbb6bf2 100644 --- a/web/app/components/base/icons/src/vender/line/general/LogIn04.tsx +++ b/web/app/components/base/icons/src/vender/line/general/LogIn04.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/vender/line/general/LogOut01.tsx b/web/app/components/base/icons/src/vender/line/general/LogOut01.tsx index 12b83b2ce1..8ee8abf076 100644 --- a/web/app/components/base/icons/src/vender/line/general/LogOut01.tsx +++ b/web/app/components/base/icons/src/vender/line/general/LogOut01.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/vender/line/general/LogOut04.tsx b/web/app/components/base/icons/src/vender/line/general/LogOut04.tsx index 2a73cb4439..9adf56d997 100644 --- a/web/app/components/base/icons/src/vender/line/general/LogOut04.tsx +++ b/web/app/components/base/icons/src/vender/line/general/LogOut04.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/vender/line/general/MagicEdit.tsx b/web/app/components/base/icons/src/vender/line/general/MagicEdit.tsx index 4e49c55277..1bf06a3f69 100644 --- a/web/app/components/base/icons/src/vender/line/general/MagicEdit.tsx +++ b/web/app/components/base/icons/src/vender/line/general/MagicEdit.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/vender/line/general/Menu01.tsx b/web/app/components/base/icons/src/vender/line/general/Menu01.tsx index 3ef0904075..acf84a6cac 100644 --- a/web/app/components/base/icons/src/vender/line/general/Menu01.tsx +++ b/web/app/components/base/icons/src/vender/line/general/Menu01.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/vender/line/general/Pin01.tsx b/web/app/components/base/icons/src/vender/line/general/Pin01.tsx index fc0aa4fe81..3fdabb4278 100644 --- a/web/app/components/base/icons/src/vender/line/general/Pin01.tsx +++ b/web/app/components/base/icons/src/vender/line/general/Pin01.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/vender/line/general/Pin02.tsx b/web/app/components/base/icons/src/vender/line/general/Pin02.tsx index e1b1853e01..2affb7ec53 100644 --- a/web/app/components/base/icons/src/vender/line/general/Pin02.tsx +++ b/web/app/components/base/icons/src/vender/line/general/Pin02.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/vender/line/general/Plus02.tsx b/web/app/components/base/icons/src/vender/line/general/Plus02.tsx index 6e7920f6ce..8242195f60 100644 --- a/web/app/components/base/icons/src/vender/line/general/Plus02.tsx +++ b/web/app/components/base/icons/src/vender/line/general/Plus02.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/vender/line/general/Refresh.tsx b/web/app/components/base/icons/src/vender/line/general/Refresh.tsx index 0d51f21c5d..d2b8892e4c 100644 --- a/web/app/components/base/icons/src/vender/line/general/Refresh.tsx +++ b/web/app/components/base/icons/src/vender/line/general/Refresh.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/vender/line/general/SearchMenu.tsx b/web/app/components/base/icons/src/vender/line/general/SearchMenu.tsx index 4826abb20f..497f24a984 100644 --- a/web/app/components/base/icons/src/vender/line/general/SearchMenu.tsx +++ b/web/app/components/base/icons/src/vender/line/general/SearchMenu.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/vender/line/general/Settings01.tsx b/web/app/components/base/icons/src/vender/line/general/Settings01.tsx index 77d4b7a315..98199c7540 100644 --- a/web/app/components/base/icons/src/vender/line/general/Settings01.tsx +++ b/web/app/components/base/icons/src/vender/line/general/Settings01.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/vender/line/general/Settings04.tsx b/web/app/components/base/icons/src/vender/line/general/Settings04.tsx index cb475fad85..0cddfb76f3 100644 --- a/web/app/components/base/icons/src/vender/line/general/Settings04.tsx +++ b/web/app/components/base/icons/src/vender/line/general/Settings04.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/vender/line/general/Target04.tsx b/web/app/components/base/icons/src/vender/line/general/Target04.tsx index d2d04f93ef..a5c340ff3a 100644 --- a/web/app/components/base/icons/src/vender/line/general/Target04.tsx +++ b/web/app/components/base/icons/src/vender/line/general/Target04.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/vender/line/general/Upload03.tsx b/web/app/components/base/icons/src/vender/line/general/Upload03.tsx index e62e5d74ed..ae03806ce0 100644 --- a/web/app/components/base/icons/src/vender/line/general/Upload03.tsx +++ b/web/app/components/base/icons/src/vender/line/general/Upload03.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/vender/line/general/UploadCloud01.tsx b/web/app/components/base/icons/src/vender/line/general/UploadCloud01.tsx index 413c36e7db..8e0e5e266c 100644 --- a/web/app/components/base/icons/src/vender/line/general/UploadCloud01.tsx +++ b/web/app/components/base/icons/src/vender/line/general/UploadCloud01.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/vender/line/general/X.tsx b/web/app/components/base/icons/src/vender/line/general/X.tsx index 779f4cd162..5160a92150 100644 --- a/web/app/components/base/icons/src/vender/line/general/X.tsx +++ b/web/app/components/base/icons/src/vender/line/general/X.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/vender/line/images/ImagePlus.tsx b/web/app/components/base/icons/src/vender/line/images/ImagePlus.tsx index bd5a9212d0..10b019adb6 100644 --- a/web/app/components/base/icons/src/vender/line/images/ImagePlus.tsx +++ b/web/app/components/base/icons/src/vender/line/images/ImagePlus.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/vender/line/layout/AlignLeft01.tsx b/web/app/components/base/icons/src/vender/line/layout/AlignLeft01.tsx index 0aad9be884..0761e89f56 100644 --- a/web/app/components/base/icons/src/vender/line/layout/AlignLeft01.tsx +++ b/web/app/components/base/icons/src/vender/line/layout/AlignLeft01.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/vender/line/layout/AlignRight01.tsx b/web/app/components/base/icons/src/vender/line/layout/AlignRight01.tsx index 486ba7b38d..ffe1889ff8 100644 --- a/web/app/components/base/icons/src/vender/line/layout/AlignRight01.tsx +++ b/web/app/components/base/icons/src/vender/line/layout/AlignRight01.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/vender/line/layout/Grid01.tsx b/web/app/components/base/icons/src/vender/line/layout/Grid01.tsx index 5638f3c081..bc9b6115be 100644 --- a/web/app/components/base/icons/src/vender/line/layout/Grid01.tsx +++ b/web/app/components/base/icons/src/vender/line/layout/Grid01.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/vender/line/layout/LayoutGrid02.tsx b/web/app/components/base/icons/src/vender/line/layout/LayoutGrid02.tsx index f718a66e98..2b23964d1f 100644 --- a/web/app/components/base/icons/src/vender/line/layout/LayoutGrid02.tsx +++ b/web/app/components/base/icons/src/vender/line/layout/LayoutGrid02.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/vender/line/mapsAndTravel/Globe01.tsx b/web/app/components/base/icons/src/vender/line/mapsAndTravel/Globe01.tsx index 445fde6304..0059dea57f 100644 --- a/web/app/components/base/icons/src/vender/line/mapsAndTravel/Globe01.tsx +++ b/web/app/components/base/icons/src/vender/line/mapsAndTravel/Globe01.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/vender/line/mapsAndTravel/Route.tsx b/web/app/components/base/icons/src/vender/line/mapsAndTravel/Route.tsx index f81fb619ce..9cbde4a15e 100644 --- a/web/app/components/base/icons/src/vender/line/mapsAndTravel/Route.tsx +++ b/web/app/components/base/icons/src/vender/line/mapsAndTravel/Route.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/vender/line/mediaAndDevices/Microphone01.tsx b/web/app/components/base/icons/src/vender/line/mediaAndDevices/Microphone01.tsx index 37fb66a887..c76cc607e4 100644 --- a/web/app/components/base/icons/src/vender/line/mediaAndDevices/Microphone01.tsx +++ b/web/app/components/base/icons/src/vender/line/mediaAndDevices/Microphone01.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/vender/line/mediaAndDevices/PlayCircle.tsx b/web/app/components/base/icons/src/vender/line/mediaAndDevices/PlayCircle.tsx index 3298fe3121..db2c1fc419 100644 --- a/web/app/components/base/icons/src/vender/line/mediaAndDevices/PlayCircle.tsx +++ b/web/app/components/base/icons/src/vender/line/mediaAndDevices/PlayCircle.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/vender/line/mediaAndDevices/SlidersH.tsx b/web/app/components/base/icons/src/vender/line/mediaAndDevices/SlidersH.tsx index f5649c461e..97851a57a0 100644 --- a/web/app/components/base/icons/src/vender/line/mediaAndDevices/SlidersH.tsx +++ b/web/app/components/base/icons/src/vender/line/mediaAndDevices/SlidersH.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/vender/line/mediaAndDevices/Speaker.tsx b/web/app/components/base/icons/src/vender/line/mediaAndDevices/Speaker.tsx index 0cf9364257..d17916c05b 100644 --- a/web/app/components/base/icons/src/vender/line/mediaAndDevices/Speaker.tsx +++ b/web/app/components/base/icons/src/vender/line/mediaAndDevices/Speaker.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/vender/line/mediaAndDevices/Stop.tsx b/web/app/components/base/icons/src/vender/line/mediaAndDevices/Stop.tsx index 3b5d84b64f..55e9d67506 100644 --- a/web/app/components/base/icons/src/vender/line/mediaAndDevices/Stop.tsx +++ b/web/app/components/base/icons/src/vender/line/mediaAndDevices/Stop.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/vender/line/mediaAndDevices/StopCircle.tsx b/web/app/components/base/icons/src/vender/line/mediaAndDevices/StopCircle.tsx index 84430c3d98..0e99a65359 100644 --- a/web/app/components/base/icons/src/vender/line/mediaAndDevices/StopCircle.tsx +++ b/web/app/components/base/icons/src/vender/line/mediaAndDevices/StopCircle.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/vender/line/others/Apps02.tsx b/web/app/components/base/icons/src/vender/line/others/Apps02.tsx index 070cc28ce0..3236059d8d 100644 --- a/web/app/components/base/icons/src/vender/line/others/Apps02.tsx +++ b/web/app/components/base/icons/src/vender/line/others/Apps02.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/vender/line/others/BubbleX.tsx b/web/app/components/base/icons/src/vender/line/others/BubbleX.tsx index 80d433178f..2d76dc87cb 100644 --- a/web/app/components/base/icons/src/vender/line/others/BubbleX.tsx +++ b/web/app/components/base/icons/src/vender/line/others/BubbleX.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/vender/line/others/Colors.tsx b/web/app/components/base/icons/src/vender/line/others/Colors.tsx index bdfe6d1b90..ef04c1c5dc 100644 --- a/web/app/components/base/icons/src/vender/line/others/Colors.tsx +++ b/web/app/components/base/icons/src/vender/line/others/Colors.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/vender/line/others/DragHandle.tsx b/web/app/components/base/icons/src/vender/line/others/DragHandle.tsx index 495c29cf09..798384ed18 100644 --- a/web/app/components/base/icons/src/vender/line/others/DragHandle.tsx +++ b/web/app/components/base/icons/src/vender/line/others/DragHandle.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/vender/line/others/Env.tsx b/web/app/components/base/icons/src/vender/line/others/Env.tsx index fbfc3a749e..23d0ce3df2 100644 --- a/web/app/components/base/icons/src/vender/line/others/Env.tsx +++ b/web/app/components/base/icons/src/vender/line/others/Env.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/vender/line/others/Exchange02.tsx b/web/app/components/base/icons/src/vender/line/others/Exchange02.tsx index 782a3fc6fc..4f58de3619 100644 --- a/web/app/components/base/icons/src/vender/line/others/Exchange02.tsx +++ b/web/app/components/base/icons/src/vender/line/others/Exchange02.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/vender/line/others/FileCode.tsx b/web/app/components/base/icons/src/vender/line/others/FileCode.tsx index 10df81bd22..3660aad794 100644 --- a/web/app/components/base/icons/src/vender/line/others/FileCode.tsx +++ b/web/app/components/base/icons/src/vender/line/others/FileCode.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/vender/line/others/GlobalVariable.tsx b/web/app/components/base/icons/src/vender/line/others/GlobalVariable.tsx index 77588635f5..3f28717a84 100644 --- a/web/app/components/base/icons/src/vender/line/others/GlobalVariable.tsx +++ b/web/app/components/base/icons/src/vender/line/others/GlobalVariable.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/vender/line/others/Icon3Dots.tsx b/web/app/components/base/icons/src/vender/line/others/Icon3Dots.tsx index bcc2cee00e..7b2390f7c1 100644 --- a/web/app/components/base/icons/src/vender/line/others/Icon3Dots.tsx +++ b/web/app/components/base/icons/src/vender/line/others/Icon3Dots.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/vender/line/others/LongArrowLeft.tsx b/web/app/components/base/icons/src/vender/line/others/LongArrowLeft.tsx index 997201b5ca..73e3fd6710 100644 --- a/web/app/components/base/icons/src/vender/line/others/LongArrowLeft.tsx +++ b/web/app/components/base/icons/src/vender/line/others/LongArrowLeft.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/vender/line/others/LongArrowRight.tsx b/web/app/components/base/icons/src/vender/line/others/LongArrowRight.tsx index 42732f95a5..e186b10654 100644 --- a/web/app/components/base/icons/src/vender/line/others/LongArrowRight.tsx +++ b/web/app/components/base/icons/src/vender/line/others/LongArrowRight.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/vender/line/others/SearchMenu.tsx b/web/app/components/base/icons/src/vender/line/others/SearchMenu.tsx index 4826abb20f..497f24a984 100644 --- a/web/app/components/base/icons/src/vender/line/others/SearchMenu.tsx +++ b/web/app/components/base/icons/src/vender/line/others/SearchMenu.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/vender/line/others/Tools.tsx b/web/app/components/base/icons/src/vender/line/others/Tools.tsx index 6d023291c5..018522f519 100644 --- a/web/app/components/base/icons/src/vender/line/others/Tools.tsx +++ b/web/app/components/base/icons/src/vender/line/others/Tools.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/vender/line/shapes/CubeOutline.tsx b/web/app/components/base/icons/src/vender/line/shapes/CubeOutline.tsx index 40e0df21d7..78f58e9564 100644 --- a/web/app/components/base/icons/src/vender/line/shapes/CubeOutline.tsx +++ b/web/app/components/base/icons/src/vender/line/shapes/CubeOutline.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/vender/line/time/ClockFastForward.tsx b/web/app/components/base/icons/src/vender/line/time/ClockFastForward.tsx index e520c5a10e..db4814bd8e 100644 --- a/web/app/components/base/icons/src/vender/line/time/ClockFastForward.tsx +++ b/web/app/components/base/icons/src/vender/line/time/ClockFastForward.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/vender/line/time/ClockPlay.tsx b/web/app/components/base/icons/src/vender/line/time/ClockPlay.tsx index a86756aaba..4b7d91c196 100644 --- a/web/app/components/base/icons/src/vender/line/time/ClockPlay.tsx +++ b/web/app/components/base/icons/src/vender/line/time/ClockPlay.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/vender/line/time/ClockPlaySlim.tsx b/web/app/components/base/icons/src/vender/line/time/ClockPlaySlim.tsx index 47e917b3b0..f84b357117 100644 --- a/web/app/components/base/icons/src/vender/line/time/ClockPlaySlim.tsx +++ b/web/app/components/base/icons/src/vender/line/time/ClockPlaySlim.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/vender/line/time/ClockRefresh.tsx b/web/app/components/base/icons/src/vender/line/time/ClockRefresh.tsx index 31e3a9c1fd..991d6a6708 100644 --- a/web/app/components/base/icons/src/vender/line/time/ClockRefresh.tsx +++ b/web/app/components/base/icons/src/vender/line/time/ClockRefresh.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/vender/line/users/User01.tsx b/web/app/components/base/icons/src/vender/line/users/User01.tsx index 24fd0df89b..42f2144b97 100644 --- a/web/app/components/base/icons/src/vender/line/users/User01.tsx +++ b/web/app/components/base/icons/src/vender/line/users/User01.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/vender/line/users/Users01.tsx b/web/app/components/base/icons/src/vender/line/users/Users01.tsx index f26ff03138..b63daf7242 100644 --- a/web/app/components/base/icons/src/vender/line/users/Users01.tsx +++ b/web/app/components/base/icons/src/vender/line/users/Users01.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/vender/line/weather/Stars02.tsx b/web/app/components/base/icons/src/vender/line/weather/Stars02.tsx index ad24f6c98f..8a42448c70 100644 --- a/web/app/components/base/icons/src/vender/line/weather/Stars02.tsx +++ b/web/app/components/base/icons/src/vender/line/weather/Stars02.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/vender/other/AnthropicText.tsx b/web/app/components/base/icons/src/vender/other/AnthropicText.tsx index be9ebd3b64..62186fb1c3 100644 --- a/web/app/components/base/icons/src/vender/other/AnthropicText.tsx +++ b/web/app/components/base/icons/src/vender/other/AnthropicText.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/vender/other/Generator.tsx b/web/app/components/base/icons/src/vender/other/Generator.tsx index cba390482d..9fdb4277d3 100644 --- a/web/app/components/base/icons/src/vender/other/Generator.tsx +++ b/web/app/components/base/icons/src/vender/other/Generator.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/vender/other/Group.tsx b/web/app/components/base/icons/src/vender/other/Group.tsx index 7b72300fdd..7fef1b3c4d 100644 --- a/web/app/components/base/icons/src/vender/other/Group.tsx +++ b/web/app/components/base/icons/src/vender/other/Group.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/vender/other/Mcp.tsx b/web/app/components/base/icons/src/vender/other/Mcp.tsx index 00ffa4a831..d16918c725 100644 --- a/web/app/components/base/icons/src/vender/other/Mcp.tsx +++ b/web/app/components/base/icons/src/vender/other/Mcp.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/vender/other/NoToolPlaceholder.tsx b/web/app/components/base/icons/src/vender/other/NoToolPlaceholder.tsx index da8fddee22..0eafd50bf3 100644 --- a/web/app/components/base/icons/src/vender/other/NoToolPlaceholder.tsx +++ b/web/app/components/base/icons/src/vender/other/NoToolPlaceholder.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/vender/other/Openai.tsx b/web/app/components/base/icons/src/vender/other/Openai.tsx index bcb7337060..af6185320c 100644 --- a/web/app/components/base/icons/src/vender/other/Openai.tsx +++ b/web/app/components/base/icons/src/vender/other/Openai.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/vender/other/ReplayLine.tsx b/web/app/components/base/icons/src/vender/other/ReplayLine.tsx index 29f7137bb9..1dae257a6d 100644 --- a/web/app/components/base/icons/src/vender/other/ReplayLine.tsx +++ b/web/app/components/base/icons/src/vender/other/ReplayLine.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/vender/plugin/BoxSparkleFill.tsx b/web/app/components/base/icons/src/vender/plugin/BoxSparkleFill.tsx index 500f3e7999..12002c2e24 100644 --- a/web/app/components/base/icons/src/vender/plugin/BoxSparkleFill.tsx +++ b/web/app/components/base/icons/src/vender/plugin/BoxSparkleFill.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/vender/plugin/LeftCorner.tsx b/web/app/components/base/icons/src/vender/plugin/LeftCorner.tsx index 93b68277a2..b25ad9f014 100644 --- a/web/app/components/base/icons/src/vender/plugin/LeftCorner.tsx +++ b/web/app/components/base/icons/src/vender/plugin/LeftCorner.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/vender/solid/FinanceAndECommerce/GoldCoin.tsx b/web/app/components/base/icons/src/vender/solid/FinanceAndECommerce/GoldCoin.tsx index d912a6b2b0..c4147aff78 100644 --- a/web/app/components/base/icons/src/vender/solid/FinanceAndECommerce/GoldCoin.tsx +++ b/web/app/components/base/icons/src/vender/solid/FinanceAndECommerce/GoldCoin.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/vender/solid/FinanceAndECommerce/Scales02.tsx b/web/app/components/base/icons/src/vender/solid/FinanceAndECommerce/Scales02.tsx index 5a4ad8b6c5..dc76432b84 100644 --- a/web/app/components/base/icons/src/vender/solid/FinanceAndECommerce/Scales02.tsx +++ b/web/app/components/base/icons/src/vender/solid/FinanceAndECommerce/Scales02.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/vender/solid/alertsAndFeedback/AlertTriangle.tsx b/web/app/components/base/icons/src/vender/solid/alertsAndFeedback/AlertTriangle.tsx index cceacb9f32..465c638547 100644 --- a/web/app/components/base/icons/src/vender/solid/alertsAndFeedback/AlertTriangle.tsx +++ b/web/app/components/base/icons/src/vender/solid/alertsAndFeedback/AlertTriangle.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/vender/solid/arrows/ChevronDown.tsx b/web/app/components/base/icons/src/vender/solid/arrows/ChevronDown.tsx index e08b7db110..643ddfbf79 100644 --- a/web/app/components/base/icons/src/vender/solid/arrows/ChevronDown.tsx +++ b/web/app/components/base/icons/src/vender/solid/arrows/ChevronDown.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/vender/solid/arrows/HighPriority.tsx b/web/app/components/base/icons/src/vender/solid/arrows/HighPriority.tsx index 4d25be2cb2..af6fa05e5c 100644 --- a/web/app/components/base/icons/src/vender/solid/arrows/HighPriority.tsx +++ b/web/app/components/base/icons/src/vender/solid/arrows/HighPriority.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/vender/solid/communication/AiText.tsx b/web/app/components/base/icons/src/vender/solid/communication/AiText.tsx index c1a6a2495c..7d5a860038 100644 --- a/web/app/components/base/icons/src/vender/solid/communication/AiText.tsx +++ b/web/app/components/base/icons/src/vender/solid/communication/AiText.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/vender/solid/communication/BubbleTextMod.tsx b/web/app/components/base/icons/src/vender/solid/communication/BubbleTextMod.tsx index da3ed73c05..62502b3598 100644 --- a/web/app/components/base/icons/src/vender/solid/communication/BubbleTextMod.tsx +++ b/web/app/components/base/icons/src/vender/solid/communication/BubbleTextMod.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/vender/solid/communication/ChatBot.tsx b/web/app/components/base/icons/src/vender/solid/communication/ChatBot.tsx index 867ae313b5..6f44bec6d1 100644 --- a/web/app/components/base/icons/src/vender/solid/communication/ChatBot.tsx +++ b/web/app/components/base/icons/src/vender/solid/communication/ChatBot.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/vender/solid/communication/CuteRobot.tsx b/web/app/components/base/icons/src/vender/solid/communication/CuteRobot.tsx index 526bb7734b..576c73a611 100644 --- a/web/app/components/base/icons/src/vender/solid/communication/CuteRobot.tsx +++ b/web/app/components/base/icons/src/vender/solid/communication/CuteRobot.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/vender/solid/communication/EditList.tsx b/web/app/components/base/icons/src/vender/solid/communication/EditList.tsx index 09fce2cae5..572d570a82 100644 --- a/web/app/components/base/icons/src/vender/solid/communication/EditList.tsx +++ b/web/app/components/base/icons/src/vender/solid/communication/EditList.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/vender/solid/communication/ListSparkle.tsx b/web/app/components/base/icons/src/vender/solid/communication/ListSparkle.tsx index b42b769d46..86876da056 100644 --- a/web/app/components/base/icons/src/vender/solid/communication/ListSparkle.tsx +++ b/web/app/components/base/icons/src/vender/solid/communication/ListSparkle.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/vender/solid/communication/Logic.tsx b/web/app/components/base/icons/src/vender/solid/communication/Logic.tsx index 695b3414eb..db7d418bf7 100644 --- a/web/app/components/base/icons/src/vender/solid/communication/Logic.tsx +++ b/web/app/components/base/icons/src/vender/solid/communication/Logic.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/vender/solid/communication/MessageDotsCircle.tsx b/web/app/components/base/icons/src/vender/solid/communication/MessageDotsCircle.tsx index 08431eadb7..43eca08463 100644 --- a/web/app/components/base/icons/src/vender/solid/communication/MessageDotsCircle.tsx +++ b/web/app/components/base/icons/src/vender/solid/communication/MessageDotsCircle.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/vender/solid/communication/MessageFast.tsx b/web/app/components/base/icons/src/vender/solid/communication/MessageFast.tsx index 45a1e77b18..efa7b15821 100644 --- a/web/app/components/base/icons/src/vender/solid/communication/MessageFast.tsx +++ b/web/app/components/base/icons/src/vender/solid/communication/MessageFast.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/vender/solid/communication/MessageHeartCircle.tsx b/web/app/components/base/icons/src/vender/solid/communication/MessageHeartCircle.tsx index 089458134a..547947ea39 100644 --- a/web/app/components/base/icons/src/vender/solid/communication/MessageHeartCircle.tsx +++ b/web/app/components/base/icons/src/vender/solid/communication/MessageHeartCircle.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/vender/solid/communication/MessageSmileSquare.tsx b/web/app/components/base/icons/src/vender/solid/communication/MessageSmileSquare.tsx index ece30804cb..ad3df7d9e5 100644 --- a/web/app/components/base/icons/src/vender/solid/communication/MessageSmileSquare.tsx +++ b/web/app/components/base/icons/src/vender/solid/communication/MessageSmileSquare.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/vender/solid/communication/Send03.tsx b/web/app/components/base/icons/src/vender/solid/communication/Send03.tsx index 7e23d70ee4..030013487f 100644 --- a/web/app/components/base/icons/src/vender/solid/communication/Send03.tsx +++ b/web/app/components/base/icons/src/vender/solid/communication/Send03.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/vender/solid/development/ApiConnection.tsx b/web/app/components/base/icons/src/vender/solid/development/ApiConnection.tsx index 70011637b8..9e8c9ab68d 100644 --- a/web/app/components/base/icons/src/vender/solid/development/ApiConnection.tsx +++ b/web/app/components/base/icons/src/vender/solid/development/ApiConnection.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/vender/solid/development/ApiConnectionMod.tsx b/web/app/components/base/icons/src/vender/solid/development/ApiConnectionMod.tsx index fb741f0657..be9628ee9f 100644 --- a/web/app/components/base/icons/src/vender/solid/development/ApiConnectionMod.tsx +++ b/web/app/components/base/icons/src/vender/solid/development/ApiConnectionMod.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/vender/solid/development/BarChartSquare02.tsx b/web/app/components/base/icons/src/vender/solid/development/BarChartSquare02.tsx index c8a335785d..c19303e0e2 100644 --- a/web/app/components/base/icons/src/vender/solid/development/BarChartSquare02.tsx +++ b/web/app/components/base/icons/src/vender/solid/development/BarChartSquare02.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/vender/solid/development/Container.tsx b/web/app/components/base/icons/src/vender/solid/development/Container.tsx index 2aa777a256..70e1397c71 100644 --- a/web/app/components/base/icons/src/vender/solid/development/Container.tsx +++ b/web/app/components/base/icons/src/vender/solid/development/Container.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/vender/solid/development/Database02.tsx b/web/app/components/base/icons/src/vender/solid/development/Database02.tsx index 088a3ae0c5..cd69b7dc34 100644 --- a/web/app/components/base/icons/src/vender/solid/development/Database02.tsx +++ b/web/app/components/base/icons/src/vender/solid/development/Database02.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/vender/solid/development/Database03.tsx b/web/app/components/base/icons/src/vender/solid/development/Database03.tsx index 012294ad7b..97e629337b 100644 --- a/web/app/components/base/icons/src/vender/solid/development/Database03.tsx +++ b/web/app/components/base/icons/src/vender/solid/development/Database03.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/vender/solid/development/FileHeart02.tsx b/web/app/components/base/icons/src/vender/solid/development/FileHeart02.tsx index e918e5e491..d829b4b85a 100644 --- a/web/app/components/base/icons/src/vender/solid/development/FileHeart02.tsx +++ b/web/app/components/base/icons/src/vender/solid/development/FileHeart02.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/vender/solid/development/PatternRecognition.tsx b/web/app/components/base/icons/src/vender/solid/development/PatternRecognition.tsx index c1eb6ad005..5c9a3f292b 100644 --- a/web/app/components/base/icons/src/vender/solid/development/PatternRecognition.tsx +++ b/web/app/components/base/icons/src/vender/solid/development/PatternRecognition.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/vender/solid/development/PromptEngineering.tsx b/web/app/components/base/icons/src/vender/solid/development/PromptEngineering.tsx index 506e9fe5ca..57729d4066 100644 --- a/web/app/components/base/icons/src/vender/solid/development/PromptEngineering.tsx +++ b/web/app/components/base/icons/src/vender/solid/development/PromptEngineering.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/vender/solid/development/PuzzlePiece01.tsx b/web/app/components/base/icons/src/vender/solid/development/PuzzlePiece01.tsx index b62d37d7c0..b78592690c 100644 --- a/web/app/components/base/icons/src/vender/solid/development/PuzzlePiece01.tsx +++ b/web/app/components/base/icons/src/vender/solid/development/PuzzlePiece01.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/vender/solid/development/Semantic.tsx b/web/app/components/base/icons/src/vender/solid/development/Semantic.tsx index df01994f8c..47eb464d86 100644 --- a/web/app/components/base/icons/src/vender/solid/development/Semantic.tsx +++ b/web/app/components/base/icons/src/vender/solid/development/Semantic.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/vender/solid/development/TerminalSquare.tsx b/web/app/components/base/icons/src/vender/solid/development/TerminalSquare.tsx index 38575b9f9f..1add0ad7e4 100644 --- a/web/app/components/base/icons/src/vender/solid/development/TerminalSquare.tsx +++ b/web/app/components/base/icons/src/vender/solid/development/TerminalSquare.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/vender/solid/development/Variable02.tsx b/web/app/components/base/icons/src/vender/solid/development/Variable02.tsx index 8ffaeaaa66..f2b8fb26d9 100644 --- a/web/app/components/base/icons/src/vender/solid/development/Variable02.tsx +++ b/web/app/components/base/icons/src/vender/solid/development/Variable02.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/vender/solid/editor/Brush01.tsx b/web/app/components/base/icons/src/vender/solid/editor/Brush01.tsx index d76c5f197f..4928176b7e 100644 --- a/web/app/components/base/icons/src/vender/solid/editor/Brush01.tsx +++ b/web/app/components/base/icons/src/vender/solid/editor/Brush01.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/vender/solid/editor/Citations.tsx b/web/app/components/base/icons/src/vender/solid/editor/Citations.tsx index 439aab6584..08a73bf99a 100644 --- a/web/app/components/base/icons/src/vender/solid/editor/Citations.tsx +++ b/web/app/components/base/icons/src/vender/solid/editor/Citations.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/vender/solid/editor/Colors.tsx b/web/app/components/base/icons/src/vender/solid/editor/Colors.tsx index bdfe6d1b90..ef04c1c5dc 100644 --- a/web/app/components/base/icons/src/vender/solid/editor/Colors.tsx +++ b/web/app/components/base/icons/src/vender/solid/editor/Colors.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/vender/solid/editor/Paragraph.tsx b/web/app/components/base/icons/src/vender/solid/editor/Paragraph.tsx index 548b38369a..2ad40771f6 100644 --- a/web/app/components/base/icons/src/vender/solid/editor/Paragraph.tsx +++ b/web/app/components/base/icons/src/vender/solid/editor/Paragraph.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/vender/solid/editor/TypeSquare.tsx b/web/app/components/base/icons/src/vender/solid/editor/TypeSquare.tsx index 5149e12b85..a94ab1fe23 100644 --- a/web/app/components/base/icons/src/vender/solid/editor/TypeSquare.tsx +++ b/web/app/components/base/icons/src/vender/solid/editor/TypeSquare.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/vender/solid/education/Beaker02.tsx b/web/app/components/base/icons/src/vender/solid/education/Beaker02.tsx index 6fd1a62002..45ccc843b8 100644 --- a/web/app/components/base/icons/src/vender/solid/education/Beaker02.tsx +++ b/web/app/components/base/icons/src/vender/solid/education/Beaker02.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/vender/solid/education/BubbleText.tsx b/web/app/components/base/icons/src/vender/solid/education/BubbleText.tsx index 9be36ec29b..6ce256babd 100644 --- a/web/app/components/base/icons/src/vender/solid/education/BubbleText.tsx +++ b/web/app/components/base/icons/src/vender/solid/education/BubbleText.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/vender/solid/education/Heart02.tsx b/web/app/components/base/icons/src/vender/solid/education/Heart02.tsx index ffe3a07df1..7eb509a3d8 100644 --- a/web/app/components/base/icons/src/vender/solid/education/Heart02.tsx +++ b/web/app/components/base/icons/src/vender/solid/education/Heart02.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/vender/solid/education/Unblur.tsx b/web/app/components/base/icons/src/vender/solid/education/Unblur.tsx index b994171e01..96b718fff9 100644 --- a/web/app/components/base/icons/src/vender/solid/education/Unblur.tsx +++ b/web/app/components/base/icons/src/vender/solid/education/Unblur.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/vender/solid/files/File05.tsx b/web/app/components/base/icons/src/vender/solid/files/File05.tsx index eda65c0e2c..0bdeb6f6af 100644 --- a/web/app/components/base/icons/src/vender/solid/files/File05.tsx +++ b/web/app/components/base/icons/src/vender/solid/files/File05.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/vender/solid/files/FileSearch02.tsx b/web/app/components/base/icons/src/vender/solid/files/FileSearch02.tsx index 154ad45bc1..d48d779ed4 100644 --- a/web/app/components/base/icons/src/vender/solid/files/FileSearch02.tsx +++ b/web/app/components/base/icons/src/vender/solid/files/FileSearch02.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/vender/solid/files/FileZip.tsx b/web/app/components/base/icons/src/vender/solid/files/FileZip.tsx index fc22a3ade3..c63b59e53d 100644 --- a/web/app/components/base/icons/src/vender/solid/files/FileZip.tsx +++ b/web/app/components/base/icons/src/vender/solid/files/FileZip.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/vender/solid/files/Folder.tsx b/web/app/components/base/icons/src/vender/solid/files/Folder.tsx index e7a3fdf167..c5c3ea5b72 100644 --- a/web/app/components/base/icons/src/vender/solid/files/Folder.tsx +++ b/web/app/components/base/icons/src/vender/solid/files/Folder.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/vender/solid/general/AnswerTriangle.tsx b/web/app/components/base/icons/src/vender/solid/general/AnswerTriangle.tsx index 956c328129..638d05e142 100644 --- a/web/app/components/base/icons/src/vender/solid/general/AnswerTriangle.tsx +++ b/web/app/components/base/icons/src/vender/solid/general/AnswerTriangle.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/vender/solid/general/ArrowDownRoundFill.tsx b/web/app/components/base/icons/src/vender/solid/general/ArrowDownRoundFill.tsx index c766a72b94..24a1ea53fd 100644 --- a/web/app/components/base/icons/src/vender/solid/general/ArrowDownRoundFill.tsx +++ b/web/app/components/base/icons/src/vender/solid/general/ArrowDownRoundFill.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/vender/solid/general/CheckCircle.tsx b/web/app/components/base/icons/src/vender/solid/general/CheckCircle.tsx index 2b34cd683e..9dc2a482cb 100644 --- a/web/app/components/base/icons/src/vender/solid/general/CheckCircle.tsx +++ b/web/app/components/base/icons/src/vender/solid/general/CheckCircle.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/vender/solid/general/CheckDone01.tsx b/web/app/components/base/icons/src/vender/solid/general/CheckDone01.tsx index c7e7d80c6c..0119a7d0a2 100644 --- a/web/app/components/base/icons/src/vender/solid/general/CheckDone01.tsx +++ b/web/app/components/base/icons/src/vender/solid/general/CheckDone01.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/vender/solid/general/Download02.tsx b/web/app/components/base/icons/src/vender/solid/general/Download02.tsx index aee29931f7..38581e6586 100644 --- a/web/app/components/base/icons/src/vender/solid/general/Download02.tsx +++ b/web/app/components/base/icons/src/vender/solid/general/Download02.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/vender/solid/general/Edit03.tsx b/web/app/components/base/icons/src/vender/solid/general/Edit03.tsx index 837e597f03..9570c9af74 100644 --- a/web/app/components/base/icons/src/vender/solid/general/Edit03.tsx +++ b/web/app/components/base/icons/src/vender/solid/general/Edit03.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/vender/solid/general/Edit04.tsx b/web/app/components/base/icons/src/vender/solid/general/Edit04.tsx index 5e436c0e25..39b598d067 100644 --- a/web/app/components/base/icons/src/vender/solid/general/Edit04.tsx +++ b/web/app/components/base/icons/src/vender/solid/general/Edit04.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/vender/solid/general/Eye.tsx b/web/app/components/base/icons/src/vender/solid/general/Eye.tsx index 29d1ea9fcb..4a0e28e145 100644 --- a/web/app/components/base/icons/src/vender/solid/general/Eye.tsx +++ b/web/app/components/base/icons/src/vender/solid/general/Eye.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/vender/solid/general/Github.tsx b/web/app/components/base/icons/src/vender/solid/general/Github.tsx index 9c6f41834f..26df0683da 100644 --- a/web/app/components/base/icons/src/vender/solid/general/Github.tsx +++ b/web/app/components/base/icons/src/vender/solid/general/Github.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/vender/solid/general/MessageClockCircle.tsx b/web/app/components/base/icons/src/vender/solid/general/MessageClockCircle.tsx index dc1f17eb76..6829b6c9ba 100644 --- a/web/app/components/base/icons/src/vender/solid/general/MessageClockCircle.tsx +++ b/web/app/components/base/icons/src/vender/solid/general/MessageClockCircle.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/vender/solid/general/PlusCircle.tsx b/web/app/components/base/icons/src/vender/solid/general/PlusCircle.tsx index 142ad91120..a70e1b4235 100644 --- a/web/app/components/base/icons/src/vender/solid/general/PlusCircle.tsx +++ b/web/app/components/base/icons/src/vender/solid/general/PlusCircle.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/vender/solid/general/QuestionTriangle.tsx b/web/app/components/base/icons/src/vender/solid/general/QuestionTriangle.tsx index 85cc44f8e4..8ced9c3063 100644 --- a/web/app/components/base/icons/src/vender/solid/general/QuestionTriangle.tsx +++ b/web/app/components/base/icons/src/vender/solid/general/QuestionTriangle.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/vender/solid/general/SearchMd.tsx b/web/app/components/base/icons/src/vender/solid/general/SearchMd.tsx index 295997cc0c..bc68734aa6 100644 --- a/web/app/components/base/icons/src/vender/solid/general/SearchMd.tsx +++ b/web/app/components/base/icons/src/vender/solid/general/SearchMd.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/vender/solid/general/Target04.tsx b/web/app/components/base/icons/src/vender/solid/general/Target04.tsx index d2d04f93ef..a5c340ff3a 100644 --- a/web/app/components/base/icons/src/vender/solid/general/Target04.tsx +++ b/web/app/components/base/icons/src/vender/solid/general/Target04.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/vender/solid/general/Tool03.tsx b/web/app/components/base/icons/src/vender/solid/general/Tool03.tsx index fd60b8e8a9..02807eaae3 100644 --- a/web/app/components/base/icons/src/vender/solid/general/Tool03.tsx +++ b/web/app/components/base/icons/src/vender/solid/general/Tool03.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/vender/solid/general/XCircle.tsx b/web/app/components/base/icons/src/vender/solid/general/XCircle.tsx index b278a98e21..0c9d6b4bdf 100644 --- a/web/app/components/base/icons/src/vender/solid/general/XCircle.tsx +++ b/web/app/components/base/icons/src/vender/solid/general/XCircle.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/vender/solid/general/ZapFast.tsx b/web/app/components/base/icons/src/vender/solid/general/ZapFast.tsx index af7e8bd33f..e1660f3c36 100644 --- a/web/app/components/base/icons/src/vender/solid/general/ZapFast.tsx +++ b/web/app/components/base/icons/src/vender/solid/general/ZapFast.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/vender/solid/general/ZapNarrow.tsx b/web/app/components/base/icons/src/vender/solid/general/ZapNarrow.tsx index 5f2aa62712..8f0960f45c 100644 --- a/web/app/components/base/icons/src/vender/solid/general/ZapNarrow.tsx +++ b/web/app/components/base/icons/src/vender/solid/general/ZapNarrow.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/vender/solid/layout/Grid01.tsx b/web/app/components/base/icons/src/vender/solid/layout/Grid01.tsx index 5638f3c081..bc9b6115be 100644 --- a/web/app/components/base/icons/src/vender/solid/layout/Grid01.tsx +++ b/web/app/components/base/icons/src/vender/solid/layout/Grid01.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/vender/solid/mapsAndTravel/Globe06.tsx b/web/app/components/base/icons/src/vender/solid/mapsAndTravel/Globe06.tsx index d961eed865..af5d2a8d52 100644 --- a/web/app/components/base/icons/src/vender/solid/mapsAndTravel/Globe06.tsx +++ b/web/app/components/base/icons/src/vender/solid/mapsAndTravel/Globe06.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/vender/solid/mapsAndTravel/Route.tsx b/web/app/components/base/icons/src/vender/solid/mapsAndTravel/Route.tsx index f81fb619ce..9cbde4a15e 100644 --- a/web/app/components/base/icons/src/vender/solid/mapsAndTravel/Route.tsx +++ b/web/app/components/base/icons/src/vender/solid/mapsAndTravel/Route.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/vender/solid/mediaAndDevices/AudioSupportIcon.tsx b/web/app/components/base/icons/src/vender/solid/mediaAndDevices/AudioSupportIcon.tsx index 663866ff88..607c2d1d52 100644 --- a/web/app/components/base/icons/src/vender/solid/mediaAndDevices/AudioSupportIcon.tsx +++ b/web/app/components/base/icons/src/vender/solid/mediaAndDevices/AudioSupportIcon.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/vender/solid/mediaAndDevices/DocumentSupportIcon.tsx b/web/app/components/base/icons/src/vender/solid/mediaAndDevices/DocumentSupportIcon.tsx index 5bad91edd1..a98abfacd2 100644 --- a/web/app/components/base/icons/src/vender/solid/mediaAndDevices/DocumentSupportIcon.tsx +++ b/web/app/components/base/icons/src/vender/solid/mediaAndDevices/DocumentSupportIcon.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/vender/solid/mediaAndDevices/MagicBox.tsx b/web/app/components/base/icons/src/vender/solid/mediaAndDevices/MagicBox.tsx index 0c38691c67..dfc2f9d46c 100644 --- a/web/app/components/base/icons/src/vender/solid/mediaAndDevices/MagicBox.tsx +++ b/web/app/components/base/icons/src/vender/solid/mediaAndDevices/MagicBox.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/vender/solid/mediaAndDevices/MagicEyes.tsx b/web/app/components/base/icons/src/vender/solid/mediaAndDevices/MagicEyes.tsx index e7f7335dde..1b13fa52be 100644 --- a/web/app/components/base/icons/src/vender/solid/mediaAndDevices/MagicEyes.tsx +++ b/web/app/components/base/icons/src/vender/solid/mediaAndDevices/MagicEyes.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/vender/solid/mediaAndDevices/MagicWand.tsx b/web/app/components/base/icons/src/vender/solid/mediaAndDevices/MagicWand.tsx index 3eb6130c52..09f9117a18 100644 --- a/web/app/components/base/icons/src/vender/solid/mediaAndDevices/MagicWand.tsx +++ b/web/app/components/base/icons/src/vender/solid/mediaAndDevices/MagicWand.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/vender/solid/mediaAndDevices/Microphone01.tsx b/web/app/components/base/icons/src/vender/solid/mediaAndDevices/Microphone01.tsx index 37fb66a887..c76cc607e4 100644 --- a/web/app/components/base/icons/src/vender/solid/mediaAndDevices/Microphone01.tsx +++ b/web/app/components/base/icons/src/vender/solid/mediaAndDevices/Microphone01.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/vender/solid/mediaAndDevices/Play.tsx b/web/app/components/base/icons/src/vender/solid/mediaAndDevices/Play.tsx index b9e07c57d6..4ac957cc35 100644 --- a/web/app/components/base/icons/src/vender/solid/mediaAndDevices/Play.tsx +++ b/web/app/components/base/icons/src/vender/solid/mediaAndDevices/Play.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/vender/solid/mediaAndDevices/Robot.tsx b/web/app/components/base/icons/src/vender/solid/mediaAndDevices/Robot.tsx index 8bee6e24cb..31dd7f3efd 100644 --- a/web/app/components/base/icons/src/vender/solid/mediaAndDevices/Robot.tsx +++ b/web/app/components/base/icons/src/vender/solid/mediaAndDevices/Robot.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/vender/solid/mediaAndDevices/Sliders02.tsx b/web/app/components/base/icons/src/vender/solid/mediaAndDevices/Sliders02.tsx index f1d05e7253..4a994b35aa 100644 --- a/web/app/components/base/icons/src/vender/solid/mediaAndDevices/Sliders02.tsx +++ b/web/app/components/base/icons/src/vender/solid/mediaAndDevices/Sliders02.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/vender/solid/mediaAndDevices/Speaker.tsx b/web/app/components/base/icons/src/vender/solid/mediaAndDevices/Speaker.tsx index 0cf9364257..d17916c05b 100644 --- a/web/app/components/base/icons/src/vender/solid/mediaAndDevices/Speaker.tsx +++ b/web/app/components/base/icons/src/vender/solid/mediaAndDevices/Speaker.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/vender/solid/mediaAndDevices/StopCircle.tsx b/web/app/components/base/icons/src/vender/solid/mediaAndDevices/StopCircle.tsx index 84430c3d98..0e99a65359 100644 --- a/web/app/components/base/icons/src/vender/solid/mediaAndDevices/StopCircle.tsx +++ b/web/app/components/base/icons/src/vender/solid/mediaAndDevices/StopCircle.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/vender/solid/mediaAndDevices/VideoSupportIcon.tsx b/web/app/components/base/icons/src/vender/solid/mediaAndDevices/VideoSupportIcon.tsx index 4822f837f3..9d0b9983eb 100644 --- a/web/app/components/base/icons/src/vender/solid/mediaAndDevices/VideoSupportIcon.tsx +++ b/web/app/components/base/icons/src/vender/solid/mediaAndDevices/VideoSupportIcon.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/vender/solid/security/Lock01.tsx b/web/app/components/base/icons/src/vender/solid/security/Lock01.tsx index ea192d8662..1519388e11 100644 --- a/web/app/components/base/icons/src/vender/solid/security/Lock01.tsx +++ b/web/app/components/base/icons/src/vender/solid/security/Lock01.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/vender/solid/shapes/Corner.tsx b/web/app/components/base/icons/src/vender/solid/shapes/Corner.tsx index 6b02e92d29..19fe74ae09 100644 --- a/web/app/components/base/icons/src/vender/solid/shapes/Corner.tsx +++ b/web/app/components/base/icons/src/vender/solid/shapes/Corner.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/vender/solid/shapes/Star04.tsx b/web/app/components/base/icons/src/vender/solid/shapes/Star04.tsx index eb699cdeec..32d3265c4a 100644 --- a/web/app/components/base/icons/src/vender/solid/shapes/Star04.tsx +++ b/web/app/components/base/icons/src/vender/solid/shapes/Star04.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/vender/solid/shapes/Star06.tsx b/web/app/components/base/icons/src/vender/solid/shapes/Star06.tsx index 9b320a611b..b959ad3818 100644 --- a/web/app/components/base/icons/src/vender/solid/shapes/Star06.tsx +++ b/web/app/components/base/icons/src/vender/solid/shapes/Star06.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/vender/solid/users/User01.tsx b/web/app/components/base/icons/src/vender/solid/users/User01.tsx index 24fd0df89b..42f2144b97 100644 --- a/web/app/components/base/icons/src/vender/solid/users/User01.tsx +++ b/web/app/components/base/icons/src/vender/solid/users/User01.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/vender/solid/users/UserEdit02.tsx b/web/app/components/base/icons/src/vender/solid/users/UserEdit02.tsx index 588b6aee6d..7c4f00316b 100644 --- a/web/app/components/base/icons/src/vender/solid/users/UserEdit02.tsx +++ b/web/app/components/base/icons/src/vender/solid/users/UserEdit02.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/vender/solid/users/Users01.tsx b/web/app/components/base/icons/src/vender/solid/users/Users01.tsx index f26ff03138..b63daf7242 100644 --- a/web/app/components/base/icons/src/vender/solid/users/Users01.tsx +++ b/web/app/components/base/icons/src/vender/solid/users/Users01.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/vender/solid/users/UsersPlus.tsx b/web/app/components/base/icons/src/vender/solid/users/UsersPlus.tsx index 3594435eaf..ab4ade9e27 100644 --- a/web/app/components/base/icons/src/vender/solid/users/UsersPlus.tsx +++ b/web/app/components/base/icons/src/vender/solid/users/UsersPlus.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/vender/system/AutoUpdateLine.tsx b/web/app/components/base/icons/src/vender/system/AutoUpdateLine.tsx index d162edaa5a..0f783511bb 100644 --- a/web/app/components/base/icons/src/vender/system/AutoUpdateLine.tsx +++ b/web/app/components/base/icons/src/vender/system/AutoUpdateLine.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/vender/workflow/Agent.tsx b/web/app/components/base/icons/src/vender/workflow/Agent.tsx index 58a2426d3c..c9a34c10f3 100644 --- a/web/app/components/base/icons/src/vender/workflow/Agent.tsx +++ b/web/app/components/base/icons/src/vender/workflow/Agent.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/vender/workflow/Answer.tsx b/web/app/components/base/icons/src/vender/workflow/Answer.tsx index 91bf7883d4..b38008aa02 100644 --- a/web/app/components/base/icons/src/vender/workflow/Answer.tsx +++ b/web/app/components/base/icons/src/vender/workflow/Answer.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/vender/workflow/Assigner.tsx b/web/app/components/base/icons/src/vender/workflow/Assigner.tsx index c4d1382c48..1af518fd18 100644 --- a/web/app/components/base/icons/src/vender/workflow/Assigner.tsx +++ b/web/app/components/base/icons/src/vender/workflow/Assigner.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/vender/workflow/Code.tsx b/web/app/components/base/icons/src/vender/workflow/Code.tsx index 1ec2e49fc1..9285cb0076 100644 --- a/web/app/components/base/icons/src/vender/workflow/Code.tsx +++ b/web/app/components/base/icons/src/vender/workflow/Code.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/vender/workflow/DocsExtractor.tsx b/web/app/components/base/icons/src/vender/workflow/DocsExtractor.tsx index 838fb8a75f..421da3902a 100644 --- a/web/app/components/base/icons/src/vender/workflow/DocsExtractor.tsx +++ b/web/app/components/base/icons/src/vender/workflow/DocsExtractor.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/vender/workflow/End.tsx b/web/app/components/base/icons/src/vender/workflow/End.tsx index 8d7f6936d3..4f098d45fb 100644 --- a/web/app/components/base/icons/src/vender/workflow/End.tsx +++ b/web/app/components/base/icons/src/vender/workflow/End.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/vender/workflow/Home.tsx b/web/app/components/base/icons/src/vender/workflow/Home.tsx index 6210e6b941..18cc292480 100644 --- a/web/app/components/base/icons/src/vender/workflow/Home.tsx +++ b/web/app/components/base/icons/src/vender/workflow/Home.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/vender/workflow/Http.tsx b/web/app/components/base/icons/src/vender/workflow/Http.tsx index 77f46bfc5c..c84a585918 100644 --- a/web/app/components/base/icons/src/vender/workflow/Http.tsx +++ b/web/app/components/base/icons/src/vender/workflow/Http.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/vender/workflow/IfElse.tsx b/web/app/components/base/icons/src/vender/workflow/IfElse.tsx index aed6635776..e3820b2268 100644 --- a/web/app/components/base/icons/src/vender/workflow/IfElse.tsx +++ b/web/app/components/base/icons/src/vender/workflow/IfElse.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/vender/workflow/Iteration.tsx b/web/app/components/base/icons/src/vender/workflow/Iteration.tsx index 5e2b2c9a02..0805dcdcf9 100644 --- a/web/app/components/base/icons/src/vender/workflow/Iteration.tsx +++ b/web/app/components/base/icons/src/vender/workflow/Iteration.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/vender/workflow/IterationStart.tsx b/web/app/components/base/icons/src/vender/workflow/IterationStart.tsx index 939d696834..13848fd17a 100644 --- a/web/app/components/base/icons/src/vender/workflow/IterationStart.tsx +++ b/web/app/components/base/icons/src/vender/workflow/IterationStart.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/vender/workflow/Jinja.tsx b/web/app/components/base/icons/src/vender/workflow/Jinja.tsx index 67422f647b..fc9b0a5fc9 100644 --- a/web/app/components/base/icons/src/vender/workflow/Jinja.tsx +++ b/web/app/components/base/icons/src/vender/workflow/Jinja.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/vender/workflow/KnowledgeRetrieval.tsx b/web/app/components/base/icons/src/vender/workflow/KnowledgeRetrieval.tsx index abe3f35bd3..23141fe53f 100644 --- a/web/app/components/base/icons/src/vender/workflow/KnowledgeRetrieval.tsx +++ b/web/app/components/base/icons/src/vender/workflow/KnowledgeRetrieval.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/vender/workflow/ListFilter.tsx b/web/app/components/base/icons/src/vender/workflow/ListFilter.tsx index 4eb992a6e4..831679eb04 100644 --- a/web/app/components/base/icons/src/vender/workflow/ListFilter.tsx +++ b/web/app/components/base/icons/src/vender/workflow/ListFilter.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/vender/workflow/Llm.tsx b/web/app/components/base/icons/src/vender/workflow/Llm.tsx index d72c5f24bb..c712d9ecea 100644 --- a/web/app/components/base/icons/src/vender/workflow/Llm.tsx +++ b/web/app/components/base/icons/src/vender/workflow/Llm.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/vender/workflow/Loop.tsx b/web/app/components/base/icons/src/vender/workflow/Loop.tsx index 3ac3ffd72a..234d1539f2 100644 --- a/web/app/components/base/icons/src/vender/workflow/Loop.tsx +++ b/web/app/components/base/icons/src/vender/workflow/Loop.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/vender/workflow/LoopEnd.tsx b/web/app/components/base/icons/src/vender/workflow/LoopEnd.tsx index 0b8f71d2d8..282a93fe6b 100644 --- a/web/app/components/base/icons/src/vender/workflow/LoopEnd.tsx +++ b/web/app/components/base/icons/src/vender/workflow/LoopEnd.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/vender/workflow/ParameterExtractor.tsx b/web/app/components/base/icons/src/vender/workflow/ParameterExtractor.tsx index 7066a74f87..248bb77fed 100644 --- a/web/app/components/base/icons/src/vender/workflow/ParameterExtractor.tsx +++ b/web/app/components/base/icons/src/vender/workflow/ParameterExtractor.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/vender/workflow/QuestionClassifier.tsx b/web/app/components/base/icons/src/vender/workflow/QuestionClassifier.tsx index 59b2bccff0..3a03d90a65 100644 --- a/web/app/components/base/icons/src/vender/workflow/QuestionClassifier.tsx +++ b/web/app/components/base/icons/src/vender/workflow/QuestionClassifier.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/vender/workflow/TemplatingTransform.tsx b/web/app/components/base/icons/src/vender/workflow/TemplatingTransform.tsx index a4d1e50c27..c425043e23 100644 --- a/web/app/components/base/icons/src/vender/workflow/TemplatingTransform.tsx +++ b/web/app/components/base/icons/src/vender/workflow/TemplatingTransform.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/vender/workflow/VariableX.tsx b/web/app/components/base/icons/src/vender/workflow/VariableX.tsx index 43ec10adab..17706d8e0e 100644 --- a/web/app/components/base/icons/src/vender/workflow/VariableX.tsx +++ b/web/app/components/base/icons/src/vender/workflow/VariableX.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/base/icons/src/vender/workflow/WindowCursor.tsx b/web/app/components/base/icons/src/vender/workflow/WindowCursor.tsx index 8f48dc0b14..686e625640 100644 --- a/web/app/components/base/icons/src/vender/workflow/WindowCursor.tsx +++ b/web/app/components/base/icons/src/vender/workflow/WindowCursor.tsx @@ -11,7 +11,7 @@ const Icon = ( ref, ...props }: React.SVGProps & { - ref?: React.RefObject>; + ref?: React.RefObject>; }, ) => diff --git a/web/app/components/share/text-generation/run-once/index.tsx b/web/app/components/share/text-generation/run-once/index.tsx index bae7a1d162..7896776f35 100644 --- a/web/app/components/share/text-generation/run-once/index.tsx +++ b/web/app/components/share/text-generation/run-once/index.tsx @@ -26,7 +26,7 @@ export type IRunOnceProps = { siteInfo: SiteInfo promptConfig: PromptConfig inputs: Record - inputsRef: React.MutableRefObject> + inputsRef: React.RefObject> onInputsChange: (inputs: Record) => void onSend: () => void visionConfig: VisionSettings diff --git a/web/app/components/workflow/nodes/agent/use-single-run-form-params.ts b/web/app/components/workflow/nodes/agent/use-single-run-form-params.ts index b2785c39ff..0b9a40aea4 100644 --- a/web/app/components/workflow/nodes/agent/use-single-run-form-params.ts +++ b/web/app/components/workflow/nodes/agent/use-single-run-form-params.ts @@ -1,4 +1,4 @@ -import type { MutableRefObject } from 'react' +import type { RefObject } from 'react' import type { InputVar, Variable } from '@/app/components/workflow/types' import { useMemo } from 'react' import useNodeCrud from '../_base/hooks/use-node-crud' @@ -13,7 +13,7 @@ type Params = { id: string, payload: AgentNodeType, runInputData: Record - runInputDataRef: MutableRefObject> + runInputDataRef: RefObject> getInputVars: (textList: string[]) => InputVar[] setRunInputData: (data: Record) => void toVarInputs: (variables: Variable[]) => InputVar[] diff --git a/web/app/components/workflow/nodes/assigner/use-single-run-form-params.ts b/web/app/components/workflow/nodes/assigner/use-single-run-form-params.ts index 7ff31d91c7..403157b132 100644 --- a/web/app/components/workflow/nodes/assigner/use-single-run-form-params.ts +++ b/web/app/components/workflow/nodes/assigner/use-single-run-form-params.ts @@ -1,4 +1,4 @@ -import type { MutableRefObject } from 'react' +import type { RefObject } from 'react' import type { InputVar, ValueSelector, Variable } from '@/app/components/workflow/types' import { useMemo } from 'react' import useNodeCrud from '../_base/hooks/use-node-crud' @@ -9,7 +9,7 @@ type Params = { id: string, payload: AssignerNodeType, runInputData: Record - runInputDataRef: MutableRefObject> + runInputDataRef: RefObject> getInputVars: (textList: string[]) => InputVar[] setRunInputData: (data: Record) => void toVarInputs: (variables: Variable[]) => InputVar[] diff --git a/web/app/components/workflow/nodes/code/use-single-run-form-params.ts b/web/app/components/workflow/nodes/code/use-single-run-form-params.ts index 9714e55fff..cda882ac89 100644 --- a/web/app/components/workflow/nodes/code/use-single-run-form-params.ts +++ b/web/app/components/workflow/nodes/code/use-single-run-form-params.ts @@ -1,4 +1,4 @@ -import type { MutableRefObject } from 'react' +import type { RefObject } from 'react' import type { InputVar, Variable } from '@/app/components/workflow/types' import { useCallback, useMemo } from 'react' import useNodeCrud from '../_base/hooks/use-node-crud' @@ -8,7 +8,7 @@ type Params = { id: string, payload: CodeNodeType, runInputData: Record - runInputDataRef: MutableRefObject> + runInputDataRef: RefObject> getInputVars: (textList: string[]) => InputVar[] setRunInputData: (data: Record) => void toVarInputs: (variables: Variable[]) => InputVar[] diff --git a/web/app/components/workflow/nodes/document-extractor/use-single-run-form-params.ts b/web/app/components/workflow/nodes/document-extractor/use-single-run-form-params.ts index 3b249cd210..f60f1cbd77 100644 --- a/web/app/components/workflow/nodes/document-extractor/use-single-run-form-params.ts +++ b/web/app/components/workflow/nodes/document-extractor/use-single-run-form-params.ts @@ -1,4 +1,4 @@ -import type { MutableRefObject } from 'react' +import type { RefObject } from 'react' import type { InputVar, Variable } from '@/app/components/workflow/types' import { useCallback, useMemo } from 'react' import type { DocExtractorNodeType } from './types' @@ -11,7 +11,7 @@ type Params = { id: string, payload: DocExtractorNodeType, runInputData: Record - runInputDataRef: MutableRefObject> + runInputDataRef: RefObject> getInputVars: (textList: string[]) => InputVar[] setRunInputData: (data: Record) => void toVarInputs: (variables: Variable[]) => InputVar[] diff --git a/web/app/components/workflow/nodes/http/use-single-run-form-params.ts b/web/app/components/workflow/nodes/http/use-single-run-form-params.ts index 42f39c4d32..06d4ac3a27 100644 --- a/web/app/components/workflow/nodes/http/use-single-run-form-params.ts +++ b/web/app/components/workflow/nodes/http/use-single-run-form-params.ts @@ -1,4 +1,4 @@ -import type { MutableRefObject } from 'react' +import type { RefObject } from 'react' import type { InputVar, Variable } from '@/app/components/workflow/types' import { useCallback, useMemo } from 'react' import useNodeCrud from '../_base/hooks/use-node-crud' @@ -8,7 +8,7 @@ type Params = { id: string, payload: HttpNodeType, runInputData: Record - runInputDataRef: MutableRefObject> + runInputDataRef: RefObject> getInputVars: (textList: string[]) => InputVar[] setRunInputData: (data: Record) => void toVarInputs: (variables: Variable[]) => InputVar[] diff --git a/web/app/components/workflow/nodes/if-else/use-single-run-form-params.ts b/web/app/components/workflow/nodes/if-else/use-single-run-form-params.ts index f61f2846c3..8bf667e0cc 100644 --- a/web/app/components/workflow/nodes/if-else/use-single-run-form-params.ts +++ b/web/app/components/workflow/nodes/if-else/use-single-run-form-params.ts @@ -1,4 +1,4 @@ -import type { MutableRefObject } from 'react' +import type { RefObject } from 'react' import type { InputVar, ValueSelector, Variable } from '@/app/components/workflow/types' import { useCallback } from 'react' import type { CaseItem, Condition, IfElseNodeType } from './types' @@ -7,7 +7,7 @@ type Params = { id: string, payload: IfElseNodeType, runInputData: Record - runInputDataRef: MutableRefObject> + runInputDataRef: RefObject> getInputVars: (textList: string[]) => InputVar[] setRunInputData: (data: Record) => void toVarInputs: (variables: Variable[]) => InputVar[] diff --git a/web/app/components/workflow/nodes/iteration/use-single-run-form-params.ts b/web/app/components/workflow/nodes/iteration/use-single-run-form-params.ts index b6c96bac48..ba840a472d 100644 --- a/web/app/components/workflow/nodes/iteration/use-single-run-form-params.ts +++ b/web/app/components/workflow/nodes/iteration/use-single-run-form-params.ts @@ -1,4 +1,4 @@ -import type { MutableRefObject } from 'react' +import type { RefObject } from 'react' import type { InputVar, ValueSelector, Variable } from '@/app/components/workflow/types' import { useCallback, useMemo } from 'react' import type { IterationNodeType } from './types' @@ -16,7 +16,7 @@ type Params = { id: string, payload: IterationNodeType, runInputData: Record - runInputDataRef: MutableRefObject> + runInputDataRef: RefObject> getInputVars: (textList: string[]) => InputVar[] setRunInputData: (data: Record) => void toVarInputs: (variables: Variable[]) => InputVar[] diff --git a/web/app/components/workflow/nodes/knowledge-retrieval/use-single-run-form-params.ts b/web/app/components/workflow/nodes/knowledge-retrieval/use-single-run-form-params.ts index 6655932790..24f2530c8c 100644 --- a/web/app/components/workflow/nodes/knowledge-retrieval/use-single-run-form-params.ts +++ b/web/app/components/workflow/nodes/knowledge-retrieval/use-single-run-form-params.ts @@ -1,4 +1,4 @@ -import type { MutableRefObject } from 'react' +import type { RefObject } from 'react' import { useTranslation } from 'react-i18next' import type { InputVar, Variable } from '@/app/components/workflow/types' import { InputVarType } from '@/app/components/workflow/types' @@ -11,7 +11,7 @@ type Params = { id: string, payload: KnowledgeRetrievalNodeType runInputData: Record - runInputDataRef: MutableRefObject> + runInputDataRef: RefObject> getInputVars: (textList: string[]) => InputVar[] setRunInputData: (data: Record) => void toVarInputs: (variables: Variable[]) => InputVar[] diff --git a/web/app/components/workflow/nodes/llm/use-single-run-form-params.ts b/web/app/components/workflow/nodes/llm/use-single-run-form-params.ts index 2480bbee31..aaa12be0c2 100644 --- a/web/app/components/workflow/nodes/llm/use-single-run-form-params.ts +++ b/web/app/components/workflow/nodes/llm/use-single-run-form-params.ts @@ -1,4 +1,4 @@ -import type { MutableRefObject } from 'react' +import type { RefObject } from 'react' import { useTranslation } from 'react-i18next' import type { Props as FormProps } from '@/app/components/workflow/nodes/_base/components/before-run-form/form' import type { InputVar, PromptItem, Var, Variable } from '@/app/components/workflow/types' @@ -18,7 +18,7 @@ type Params = { id: string, payload: LLMNodeType, runInputData: Record - runInputDataRef: MutableRefObject> + runInputDataRef: RefObject> getInputVars: (textList: string[]) => InputVar[] setRunInputData: (data: Record) => void toVarInputs: (variables: Variable[]) => InputVar[] diff --git a/web/app/components/workflow/nodes/parameter-extractor/use-single-run-form-params.ts b/web/app/components/workflow/nodes/parameter-extractor/use-single-run-form-params.ts index f920ff1555..68a6f4992b 100644 --- a/web/app/components/workflow/nodes/parameter-extractor/use-single-run-form-params.ts +++ b/web/app/components/workflow/nodes/parameter-extractor/use-single-run-form-params.ts @@ -1,4 +1,4 @@ -import type { MutableRefObject } from 'react' +import type { RefObject } from 'react' import { useTranslation } from 'react-i18next' import type { Props as FormProps } from '@/app/components/workflow/nodes/_base/components/before-run-form/form' import type { InputVar, Var, Variable } from '@/app/components/workflow/types' @@ -17,7 +17,7 @@ type Params = { id: string, payload: ParameterExtractorNodeType, runInputData: Record - runInputDataRef: MutableRefObject> + runInputDataRef: RefObject> getInputVars: (textList: string[]) => InputVar[] setRunInputData: (data: Record) => void toVarInputs: (variables: Variable[]) => InputVar[] diff --git a/web/app/components/workflow/nodes/question-classifier/use-single-run-form-params.ts b/web/app/components/workflow/nodes/question-classifier/use-single-run-form-params.ts index 9bbb3e1d5d..79c63cf1da 100644 --- a/web/app/components/workflow/nodes/question-classifier/use-single-run-form-params.ts +++ b/web/app/components/workflow/nodes/question-classifier/use-single-run-form-params.ts @@ -1,4 +1,4 @@ -import type { MutableRefObject } from 'react' +import type { RefObject } from 'react' import { useTranslation } from 'react-i18next' import type { Props as FormProps } from '@/app/components/workflow/nodes/_base/components/before-run-form/form' import type { InputVar, Var, Variable } from '@/app/components/workflow/types' @@ -17,7 +17,7 @@ type Params = { id: string, payload: QuestionClassifierNodeType, runInputData: Record - runInputDataRef: MutableRefObject> + runInputDataRef: RefObject> getInputVars: (textList: string[]) => InputVar[] setRunInputData: (data: Record) => void toVarInputs: (variables: Variable[]) => InputVar[] diff --git a/web/app/components/workflow/nodes/start/use-single-run-form-params.ts b/web/app/components/workflow/nodes/start/use-single-run-form-params.ts index 38abbf2a63..ed2b3900d2 100644 --- a/web/app/components/workflow/nodes/start/use-single-run-form-params.ts +++ b/web/app/components/workflow/nodes/start/use-single-run-form-params.ts @@ -1,4 +1,4 @@ -import type { MutableRefObject } from 'react' +import type { RefObject } from 'react' import { useTranslation } from 'react-i18next' import type { Props as FormProps } from '@/app/components/workflow/nodes/_base/components/before-run-form/form' import type { ValueSelector } from '@/app/components/workflow/types' @@ -10,7 +10,7 @@ type Params = { id: string, payload: StartNodeType, runInputData: Record - runInputDataRef: MutableRefObject> + runInputDataRef: RefObject> getInputVars: (textList: string[]) => InputVar[] setRunInputData: (data: Record) => void toVarInputs: (variables: Variable[]) => InputVar[] diff --git a/web/app/components/workflow/nodes/template-transform/use-single-run-form-params.ts b/web/app/components/workflow/nodes/template-transform/use-single-run-form-params.ts index ab1cfe731d..172ece6ce6 100644 --- a/web/app/components/workflow/nodes/template-transform/use-single-run-form-params.ts +++ b/web/app/components/workflow/nodes/template-transform/use-single-run-form-params.ts @@ -1,4 +1,4 @@ -import type { MutableRefObject } from 'react' +import type { RefObject } from 'react' import type { InputVar, Variable } from '@/app/components/workflow/types' import { useCallback, useMemo } from 'react' import useNodeCrud from '../_base/hooks/use-node-crud' @@ -8,7 +8,7 @@ type Params = { id: string, payload: TemplateTransformNodeType, runInputData: Record - runInputDataRef: MutableRefObject> + runInputDataRef: RefObject> getInputVars: (textList: string[]) => InputVar[] setRunInputData: (data: Record) => void toVarInputs: (variables: Variable[]) => InputVar[] diff --git a/web/app/components/workflow/nodes/tool/use-single-run-form-params.ts b/web/app/components/workflow/nodes/tool/use-single-run-form-params.ts index 535787697e..3ebb88b7c8 100644 --- a/web/app/components/workflow/nodes/tool/use-single-run-form-params.ts +++ b/web/app/components/workflow/nodes/tool/use-single-run-form-params.ts @@ -1,4 +1,4 @@ -import type { MutableRefObject } from 'react' +import type { RefObject } from 'react' import type { InputVar, Variable } from '@/app/components/workflow/types' import { useCallback, useMemo, useState } from 'react' import useNodeCrud from '../_base/hooks/use-node-crud' @@ -15,7 +15,7 @@ type Params = { id: string, payload: ToolNodeType, runInputData: Record - runInputDataRef: MutableRefObject> + runInputDataRef: RefObject> getInputVars: (textList: string[]) => InputVar[] setRunInputData: (data: Record) => void toVarInputs: (variables: Variable[]) => InputVar[] diff --git a/web/app/components/workflow/nodes/variable-assigner/use-single-run-form-params.ts b/web/app/components/workflow/nodes/variable-assigner/use-single-run-form-params.ts index 0d6d737c21..8e67675d3e 100644 --- a/web/app/components/workflow/nodes/variable-assigner/use-single-run-form-params.ts +++ b/web/app/components/workflow/nodes/variable-assigner/use-single-run-form-params.ts @@ -1,4 +1,4 @@ -import type { MutableRefObject } from 'react' +import type { RefObject } from 'react' import type { InputVar, ValueSelector, Variable } from '@/app/components/workflow/types' import { useCallback } from 'react' import type { VariableAssignerNodeType } from './types' @@ -7,7 +7,7 @@ type Params = { id: string, payload: VariableAssignerNodeType, runInputData: Record - runInputDataRef: MutableRefObject> + runInputDataRef: RefObject> getInputVars: (textList: string[]) => InputVar[] setRunInputData: (data: Record) => void toVarInputs: (variables: Variable[]) => InputVar[] diff --git a/web/types/workflow.ts b/web/types/workflow.ts index 1cbcc942a5..4e2b4355ca 100644 --- a/web/types/workflow.ts +++ b/web/types/workflow.ts @@ -4,7 +4,7 @@ import type { TransferMethod } from '@/types/app' import type { ErrorHandleTypeEnum } from '@/app/components/workflow/nodes/_base/components/error-handle/types' import type { BeforeRunFormProps } from '@/app/components/workflow/nodes/_base/components/before-run-form' import type { SpecialResultPanelProps } from '@/app/components/workflow/run/special-result-panel' -import type { MutableRefObject } from 'react' +import type { RefObject } from 'react' export type AgentLogItem = { node_execution_id: string, @@ -363,7 +363,7 @@ export type PanelProps = { getInputVars: (textList: string[]) => InputVar[] toVarInputs: (variables: Variable[]) => InputVar[] runInputData: Record - runInputDataRef: MutableRefObject> + runInputDataRef: RefObject> setRunInputData: (data: Record) => void runResult: any } From 432f89cf3320973f4fd6d4dc82a460c965ac03e8 Mon Sep 17 00:00:00 2001 From: Yongtao Huang Date: Fri, 5 Sep 2025 11:30:04 +0800 Subject: [PATCH 13/52] Chore: clean some # type: ignore (#25157) --- api/core/indexing_runner.py | 19 +++++++++++-------- .../processor/parent_child_index_processor.py | 2 +- 2 files changed, 12 insertions(+), 9 deletions(-) diff --git a/api/core/indexing_runner.py b/api/core/indexing_runner.py index 7479bb39b9..37eb3eab60 100644 --- a/api/core/indexing_runner.py +++ b/api/core/indexing_runner.py @@ -270,7 +270,9 @@ class IndexingRunner: tenant_id=tenant_id, model_type=ModelType.TEXT_EMBEDDING, ) - preview_texts = [] # type: ignore + # keep separate, avoid union-list ambiguity + preview_texts: list[PreviewDetail] = [] + qa_preview_texts: list[QAPreviewDetail] = [] total_segments = 0 index_type = doc_form @@ -293,14 +295,14 @@ class IndexingRunner: for document in documents: if len(preview_texts) < 10: if doc_form and doc_form == "qa_model": - preview_detail = QAPreviewDetail( + qa_detail = QAPreviewDetail( question=document.page_content, answer=document.metadata.get("answer") or "" ) - preview_texts.append(preview_detail) + qa_preview_texts.append(qa_detail) else: - preview_detail = PreviewDetail(content=document.page_content) # type: ignore + preview_detail = PreviewDetail(content=document.page_content) if document.children: - preview_detail.child_chunks = [child.page_content for child in document.children] # type: ignore + preview_detail.child_chunks = [child.page_content for child in document.children] preview_texts.append(preview_detail) # delete image files and related db records @@ -321,8 +323,8 @@ class IndexingRunner: db.session.delete(image_file) if doc_form and doc_form == "qa_model": - return IndexingEstimate(total_segments=total_segments * 20, qa_preview=preview_texts, preview=[]) - return IndexingEstimate(total_segments=total_segments, preview=preview_texts) # type: ignore + return IndexingEstimate(total_segments=total_segments * 20, qa_preview=qa_preview_texts, preview=[]) + return IndexingEstimate(total_segments=total_segments, preview=preview_texts) def _extract( self, index_processor: BaseIndexProcessor, dataset_document: DatasetDocument, process_rule: dict @@ -424,6 +426,7 @@ class IndexingRunner: """ Get the NodeParser object according to the processing rule. """ + character_splitter: TextSplitter if processing_rule_mode in ["custom", "hierarchical"]: # The user-defined segmentation rule max_segmentation_tokens_length = dify_config.INDEXING_MAX_SEGMENTATION_TOKENS_LENGTH @@ -450,7 +453,7 @@ class IndexingRunner: embedding_model_instance=embedding_model_instance, ) - return character_splitter # type: ignore + return character_splitter def _split_to_documents_for_estimate( self, text_docs: list[Document], splitter: TextSplitter, processing_rule: DatasetProcessRule diff --git a/api/core/rag/index_processor/processor/parent_child_index_processor.py b/api/core/rag/index_processor/processor/parent_child_index_processor.py index cb7f6ab57a..d1088af853 100644 --- a/api/core/rag/index_processor/processor/parent_child_index_processor.py +++ b/api/core/rag/index_processor/processor/parent_child_index_processor.py @@ -36,7 +36,7 @@ class ParentChildIndexProcessor(BaseIndexProcessor): if not process_rule.get("rules"): raise ValueError("No rules found in process rule.") rules = Rule(**process_rule.get("rules")) - all_documents = [] # type: ignore + all_documents: list[Document] = [] if rules.parent_mode == ParentMode.PARAGRAPH: # Split the text documents into nodes. if not rules.segmentation: From e78f1cdc6a4ffb33b0a88ff83ea21d42bae96294 Mon Sep 17 00:00:00 2001 From: -LAN- Date: Fri, 5 Sep 2025 12:39:48 +0800 Subject: [PATCH 14/52] refactor: improve plugin version validation to support full semantic versioning (#25161) Signed-off-by: -LAN- Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com> --- api/core/plugin/entities/plugin.py | 27 ++++++++++++++++--- api/pyproject.toml | 7 ++--- .../services/test_webapp_auth_service.py | 21 +++++++++++---- api/uv.lock | 8 +++--- 4 files changed, 49 insertions(+), 14 deletions(-) diff --git a/api/core/plugin/entities/plugin.py b/api/core/plugin/entities/plugin.py index a07b58d9ea..01e9e11e66 100644 --- a/api/core/plugin/entities/plugin.py +++ b/api/core/plugin/entities/plugin.py @@ -4,7 +4,8 @@ import re from collections.abc import Mapping from typing import Any, Optional -from pydantic import BaseModel, Field, model_validator +from packaging.version import InvalidVersion, Version +from pydantic import BaseModel, Field, field_validator, model_validator from werkzeug.exceptions import NotFound from core.agent.plugin_entities import AgentStrategyProviderEntity @@ -71,10 +72,21 @@ class PluginDeclaration(BaseModel): endpoints: Optional[list[str]] = Field(default_factory=list[str]) class Meta(BaseModel): - minimum_dify_version: Optional[str] = Field(default=None, pattern=r"^\d{1,4}(\.\d{1,4}){1,3}(-\w{1,16})?$") + minimum_dify_version: Optional[str] = Field(default=None) version: Optional[str] = Field(default=None) - version: str = Field(..., pattern=r"^\d{1,4}(\.\d{1,4}){1,3}(-\w{1,16})?$") + @field_validator("minimum_dify_version") + @classmethod + def validate_minimum_dify_version(cls, v: Optional[str]) -> Optional[str]: + if v is None: + return v + try: + Version(v) + return v + except InvalidVersion as e: + raise ValueError(f"Invalid version format: {v}") from e + + version: str = Field(...) author: Optional[str] = Field(..., pattern=r"^[a-zA-Z0-9_-]{1,64}$") name: str = Field(..., pattern=r"^[a-z0-9_-]{1,128}$") description: I18nObject @@ -94,6 +106,15 @@ class PluginDeclaration(BaseModel): agent_strategy: Optional[AgentStrategyProviderEntity] = None meta: Meta + @field_validator("version") + @classmethod + def validate_version(cls, v: str) -> str: + try: + Version(v) + return v + except InvalidVersion as e: + raise ValueError(f"Invalid version format: {v}") from e + @model_validator(mode="before") @classmethod def validate_category(cls, values: dict) -> dict: diff --git a/api/pyproject.toml b/api/pyproject.toml index 8f5a6a44ac..c59140e246 100644 --- a/api/pyproject.toml +++ b/api/pyproject.toml @@ -84,10 +84,11 @@ dependencies = [ "weave~=0.51.0", "yarl~=1.18.3", "webvtt-py~=0.5.1", - "sseclient-py>=1.8.0", - "httpx-sse>=0.4.0", + "sseclient-py~=1.8.0", + "httpx-sse~=0.4.0", "sendgrid~=6.12.3", - "flask-restx>=1.3.0", + "flask-restx~=1.3.0", + "packaging~=23.2", ] # Before adding new dependency, consider place it in # alphabet order (a-z) and suitable group. diff --git a/api/tests/test_containers_integration_tests/services/test_webapp_auth_service.py b/api/tests/test_containers_integration_tests/services/test_webapp_auth_service.py index 666b083ba6..429056f5e2 100644 --- a/api/tests/test_containers_integration_tests/services/test_webapp_auth_service.py +++ b/api/tests/test_containers_integration_tests/services/test_webapp_auth_service.py @@ -57,10 +57,12 @@ class TestWebAppAuthService: tuple: (account, tenant) - Created account and tenant instances """ fake = Faker() + import uuid - # Create account + # Create account with unique email to avoid collisions + unique_email = f"test_{uuid.uuid4().hex[:8]}@example.com" account = Account( - email=fake.email(), + email=unique_email, name=fake.name(), interface_language="en-US", status="active", @@ -109,8 +111,11 @@ class TestWebAppAuthService: password = fake.password(length=12) # Create account with password + import uuid + + unique_email = f"test_{uuid.uuid4().hex[:8]}@example.com" account = Account( - email=fake.email(), + email=unique_email, name=fake.name(), interface_language="en-US", status="active", @@ -322,9 +327,12 @@ class TestWebAppAuthService: """ # Arrange: Create account without password fake = Faker() + import uuid + + unique_email = f"test_{uuid.uuid4().hex[:8]}@example.com" account = Account( - email=fake.email(), + email=unique_email, name=fake.name(), interface_language="en-US", status="active", @@ -431,9 +439,12 @@ class TestWebAppAuthService: """ # Arrange: Create banned account fake = Faker() + import uuid + + unique_email = f"test_{uuid.uuid4().hex[:8]}@example.com" account = Account( - email=fake.email(), + email=unique_email, name=fake.name(), interface_language="en-US", status=AccountStatus.BANNED.value, diff --git a/api/uv.lock b/api/uv.lock index 1d872087c7..54c4083369 100644 --- a/api/uv.lock +++ b/api/uv.lock @@ -1318,6 +1318,7 @@ dependencies = [ { name = "opentelemetry-semantic-conventions" }, { name = "opentelemetry-util-http" }, { name = "opik" }, + { name = "packaging" }, { name = "pandas", extra = ["excel", "output-formatting", "performance"] }, { name = "pandoc" }, { name = "psycogreen" }, @@ -1469,7 +1470,7 @@ requires-dist = [ { name = "flask-login", specifier = "~=0.6.3" }, { name = "flask-migrate", specifier = "~=4.0.7" }, { name = "flask-orjson", specifier = "~=2.0.0" }, - { name = "flask-restx", specifier = ">=1.3.0" }, + { name = "flask-restx", specifier = "~=1.3.0" }, { name = "flask-sqlalchemy", specifier = "~=3.1.1" }, { name = "gevent", specifier = "~=24.11.1" }, { name = "gmpy2", specifier = "~=2.2.1" }, @@ -1481,7 +1482,7 @@ requires-dist = [ { name = "googleapis-common-protos", specifier = "==1.63.0" }, { name = "gunicorn", specifier = "~=23.0.0" }, { name = "httpx", extras = ["socks"], specifier = "~=0.27.0" }, - { name = "httpx-sse", specifier = ">=0.4.0" }, + { name = "httpx-sse", specifier = "~=0.4.0" }, { name = "jieba", specifier = "==0.42.1" }, { name = "json-repair", specifier = ">=0.41.1" }, { name = "langfuse", specifier = "~=2.51.3" }, @@ -1509,6 +1510,7 @@ requires-dist = [ { name = "opentelemetry-semantic-conventions", specifier = "==0.48b0" }, { name = "opentelemetry-util-http", specifier = "==0.48b0" }, { name = "opik", specifier = "~=1.7.25" }, + { name = "packaging", specifier = "~=23.2" }, { name = "pandas", extras = ["excel", "output-formatting", "performance"], specifier = "~=2.2.2" }, { name = "pandoc", specifier = "~=2.4" }, { name = "psycogreen", specifier = "~=1.0.2" }, @@ -1528,7 +1530,7 @@ requires-dist = [ { name = "sendgrid", specifier = "~=6.12.3" }, { name = "sentry-sdk", extras = ["flask"], specifier = "~=2.28.0" }, { name = "sqlalchemy", specifier = "~=2.0.29" }, - { name = "sseclient-py", specifier = ">=1.8.0" }, + { name = "sseclient-py", specifier = "~=1.8.0" }, { name = "starlette", specifier = "==0.47.2" }, { name = "tiktoken", specifier = "~=0.9.0" }, { name = "transformers", specifier = "~=4.53.0" }, From f84b9fd5ef048f0f90bbcf5d2d16af39304c8fd9 Mon Sep 17 00:00:00 2001 From: Asuka Minato Date: Fri, 5 Sep 2025 13:41:36 +0900 Subject: [PATCH 15/52] example of type button (#25224) --- web/app/components/apps/app-card.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web/app/components/apps/app-card.tsx b/web/app/components/apps/app-card.tsx index ee9230af12..d0d42dc32c 100644 --- a/web/app/components/apps/app-card.tsx +++ b/web/app/components/apps/app-card.tsx @@ -257,7 +257,7 @@ const AppCard = ({ app, onRefresh }: AppCardProps) => { } return (
- From 95eac7f7f0299f44c5304698c6986d8d0ee6c451 Mon Sep 17 00:00:00 2001 From: Asuka Minato Date: Fri, 5 Sep 2025 13:41:54 +0900 Subject: [PATCH 16/52] example of readonly (#25220) --- web/app/components/app/type-selector/index.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web/app/components/app/type-selector/index.tsx b/web/app/components/app/type-selector/index.tsx index 99a76d7ac7..f8432ceab6 100644 --- a/web/app/components/app/type-selector/index.tsx +++ b/web/app/components/app/type-selector/index.tsx @@ -103,7 +103,7 @@ export const AppTypeIcon = React.memo(({ type, className, wrapperClassName, styl return null }) -function AppTypeSelectTrigger({ values }: { values: AppSelectorProps['value'] }) { +function AppTypeSelectTrigger({ values }: { readonly values: AppSelectorProps['value'] }) { const { t } = useTranslation() if (!values || values.length === 0) { return
Date: Fri, 5 Sep 2025 14:00:28 +0800 Subject: [PATCH 17/52] fix: child chunk API 404 due to UUID type comparison (#25234) Signed-off-by: kenwoodjw --- api/controllers/service_api/dataset/segment.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/api/controllers/service_api/dataset/segment.py b/api/controllers/service_api/dataset/segment.py index f5e2010ca4..a22155b07a 100644 --- a/api/controllers/service_api/dataset/segment.py +++ b/api/controllers/service_api/dataset/segment.py @@ -440,7 +440,7 @@ class DatasetChildChunkApi(DatasetApiResource): raise NotFound("Segment not found.") # validate segment belongs to the specified document - if segment.document_id != document_id: + if str(segment.document_id) != str(document_id): raise NotFound("Document not found.") # check child chunk @@ -451,7 +451,7 @@ class DatasetChildChunkApi(DatasetApiResource): raise NotFound("Child chunk not found.") # validate child chunk belongs to the specified segment - if child_chunk.segment_id != segment.id: + if str(child_chunk.segment_id) != str(segment.id): raise NotFound("Child chunk not found.") try: @@ -500,7 +500,7 @@ class DatasetChildChunkApi(DatasetApiResource): raise NotFound("Segment not found.") # validate segment belongs to the specified document - if segment.document_id != document_id: + if str(segment.document_id) != str(document_id): raise NotFound("Segment not found.") # get child chunk @@ -511,7 +511,7 @@ class DatasetChildChunkApi(DatasetApiResource): raise NotFound("Child chunk not found.") # validate child chunk belongs to the specified segment - if child_chunk.segment_id != segment.id: + if str(child_chunk.segment_id) != str(segment.id): raise NotFound("Child chunk not found.") # validate args From cd95237ae4c61b6d90a9977957aed22a33a26b74 Mon Sep 17 00:00:00 2001 From: coolfinish Date: Fri, 5 Sep 2025 01:38:52 -0500 Subject: [PATCH 18/52] fix: loop node doesn't exit when it react the condition #24717 (#24844) Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com> --- api/core/workflow/nodes/loop/loop_node.py | 56 +++++++++++++---------- 1 file changed, 32 insertions(+), 24 deletions(-) diff --git a/api/core/workflow/nodes/loop/loop_node.py b/api/core/workflow/nodes/loop/loop_node.py index e4aea357c4..ae3927a89a 100644 --- a/api/core/workflow/nodes/loop/loop_node.py +++ b/api/core/workflow/nodes/loop/loop_node.py @@ -289,6 +289,8 @@ class LoopNode(BaseNode): Returns: dict: {'check_break_result': bool} """ + condition_selectors = self._extract_selectors_from_conditions(break_conditions) + extended_selectors = {**loop_variable_selectors, **condition_selectors} # Run workflow rst = graph_engine.run() current_index_variable = variable_pool.get([self.node_id, "index"]) @@ -314,31 +316,30 @@ class LoopNode(BaseNode): and event.node_type == NodeType.LOOP_END and not isinstance(event, NodeRunStreamChunkEvent) ): - # Check if variables in break conditions exist and process conditions - # Allow loop internal variables to be used in break conditions - available_conditions = [] - for condition in break_conditions: - variable = self.graph_runtime_state.variable_pool.get(condition.variable_selector) - if variable: - available_conditions.append(condition) - - # Process conditions if at least one variable is available - if available_conditions: - _, _, check_break_result = condition_processor.process_conditions( - variable_pool=self.graph_runtime_state.variable_pool, - conditions=available_conditions, - operator=logical_operator, - ) - if check_break_result: - break - else: - check_break_result = True + check_break_result = True yield self._handle_event_metadata(event=event, iter_run_index=current_index) break if isinstance(event, NodeRunSucceededEvent): yield self._handle_event_metadata(event=event, iter_run_index=current_index) + # Check if all variables in break conditions exist + exists_variable = False + for condition in break_conditions: + if not self.graph_runtime_state.variable_pool.get(condition.variable_selector): + exists_variable = False + break + else: + exists_variable = True + if exists_variable: + input_conditions, group_result, check_break_result = condition_processor.process_conditions( + variable_pool=self.graph_runtime_state.variable_pool, + conditions=break_conditions, + operator=logical_operator, + ) + if check_break_result: + break + elif isinstance(event, BaseGraphEvent): if isinstance(event, GraphRunFailedEvent): # Loop run failed @@ -400,12 +401,8 @@ class LoopNode(BaseNode): else: yield self._handle_event_metadata(event=cast(InNodeEvent, event), iter_run_index=current_index) - # Remove all nodes outputs from variable pool - for node_id in loop_graph.node_ids: - variable_pool.remove([node_id]) - _outputs: dict[str, Segment | int | None] = {} - for loop_variable_key, loop_variable_selector in loop_variable_selectors.items(): + for loop_variable_key, loop_variable_selector in extended_selectors.items(): _loop_variable_segment = variable_pool.get(loop_variable_selector) if _loop_variable_segment: _outputs[loop_variable_key] = _loop_variable_segment @@ -415,6 +412,10 @@ class LoopNode(BaseNode): _outputs["loop_round"] = current_index + 1 self._node_data.outputs = _outputs + # Remove all nodes outputs from variable pool + for node_id in loop_graph.node_ids: + variable_pool.remove([node_id]) + if check_break_result: return {"check_break_result": True} @@ -433,6 +434,13 @@ class LoopNode(BaseNode): return {"check_break_result": False} + def _extract_selectors_from_conditions(self, conditions: list) -> dict[str, list[str]]: + return { + condition.variable_selector[1]: condition.variable_selector + for condition in conditions + if condition.variable_selector and len(condition.variable_selector) >= 2 + } + def _handle_event_metadata( self, *, From d03d3518d74a00c22696abcaca267585d148f8c0 Mon Sep 17 00:00:00 2001 From: Asuka Minato Date: Fri, 5 Sep 2025 18:35:50 +0900 Subject: [PATCH 19/52] example of lazy (#25216) --- web/app/components/workflow/run/tracing-panel.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web/app/components/workflow/run/tracing-panel.tsx b/web/app/components/workflow/run/tracing-panel.tsx index a6e9bf9dd4..2346b08c9e 100644 --- a/web/app/components/workflow/run/tracing-panel.tsx +++ b/web/app/components/workflow/run/tracing-panel.tsx @@ -33,7 +33,7 @@ const TracingPanel: FC = ({ }) => { const { t } = useTranslation() const treeNodes = formatNodeList(list, t) - const [collapsedNodes, setCollapsedNodes] = useState>(new Set()) + const [collapsedNodes, setCollapsedNodes] = useState>(() => new Set()) const [hoveredParallel, setHoveredParallel] = useState(null) const toggleCollapse = (id: string) => { From a9da8edbde40c6fc9ad14818d0f75b109783d51e Mon Sep 17 00:00:00 2001 From: Asuka Minato Date: Fri, 5 Sep 2025 18:35:59 +0900 Subject: [PATCH 20/52] example of remove useEffect (#25212) --- .../variable-inspect/value-content.tsx | 26 ++++++++----------- 1 file changed, 11 insertions(+), 15 deletions(-) diff --git a/web/app/components/workflow/variable-inspect/value-content.tsx b/web/app/components/workflow/variable-inspect/value-content.tsx index a3ede311c4..2b28cd8ef4 100644 --- a/web/app/components/workflow/variable-inspect/value-content.tsx +++ b/web/app/components/workflow/variable-inspect/value-content.tsx @@ -60,22 +60,18 @@ const ValueContent = ({ const [fileValue, setFileValue] = useState(formatFileValue(currentVar)) const { run: debounceValueChange } = useDebounceFn(handleValueChange, { wait: 500 }) + if (showTextEditor) { + if (currentVar.value_type === 'number') + setValue(JSON.stringify(currentVar.value)) + if (!currentVar.value) + setValue('') + setValue(currentVar.value) + } + if (showJSONEditor) + setJson(currentVar.value ? JSON.stringify(currentVar.value, null, 2) : '') - // update default value when id changed - useEffect(() => { - if (showTextEditor) { - if (currentVar.value_type === 'number') - return setValue(JSON.stringify(currentVar.value)) - if (!currentVar.value) - return setValue('') - setValue(currentVar.value) - } - if (showJSONEditor) - setJson(currentVar.value ? JSON.stringify(currentVar.value, null, 2) : '') - - if (showFileEditor) - setFileValue(formatFileValue(currentVar)) - }, [currentVar.id, currentVar.value]) + if (showFileEditor) + setFileValue(formatFileValue(currentVar)) const handleTextChange = (value: string) => { if (currentVar.value_type === 'string') From 05cd7e2d8a24f9b9780401e8dc8621788209c7bc Mon Sep 17 00:00:00 2001 From: Timo <57227498+EchterTimo@users.noreply.github.com> Date: Fri, 5 Sep 2025 12:12:46 +0200 Subject: [PATCH 21/52] add type annotations for Python SDK ChatClient Class (#24018) Co-authored-by: EchterTimo --- sdks/python-client/dify_client/client.py | 39 +++++++++++++++--------- 1 file changed, 25 insertions(+), 14 deletions(-) diff --git a/sdks/python-client/dify_client/client.py b/sdks/python-client/dify_client/client.py index d885dc6fb7..abd0e7ae29 100644 --- a/sdks/python-client/dify_client/client.py +++ b/sdks/python-client/dify_client/client.py @@ -73,12 +73,12 @@ class CompletionClient(DifyClient): class ChatClient(DifyClient): def create_chat_message( self, - inputs, - query, - user, - response_mode="blocking", - conversation_id=None, - files=None, + inputs: dict, + query: str, + user: str, + response_mode: str = "blocking", + conversation_id: str | None = None, + files: dict | None = None, ): data = { "inputs": inputs, @@ -97,22 +97,33 @@ class ChatClient(DifyClient): stream=True if response_mode == "streaming" else False, ) - def get_suggested(self, message_id, user: str): + def get_suggested(self, message_id: str, user: str): params = {"user": user} return self._send_request( "GET", f"/messages/{message_id}/suggested", params=params ) - def stop_message(self, task_id, user): + def stop_message(self, task_id: str, user: str): data = {"user": user} return self._send_request("POST", f"/chat-messages/{task_id}/stop", data) - def get_conversations(self, user, last_id=None, limit=None, pinned=None): - params = {"user": user, "last_id": last_id, "limit": limit, "pinned": pinned} + def get_conversations( + self, + user: str, + last_id: str | None = None, + limit: int | None = None, + pinned: bool | None = None + ): + params = {"user": user, "last_id": last_id, + "limit": limit, "pinned": pinned} return self._send_request("GET", "/conversations", params=params) def get_conversation_messages( - self, user, conversation_id=None, first_id=None, limit=None + self, + user: str, + conversation_id: str | None = None, + first_id: str | None = None, + limit: int | None = None ): params = {"user": user} @@ -126,18 +137,18 @@ class ChatClient(DifyClient): return self._send_request("GET", "/messages", params=params) def rename_conversation( - self, conversation_id, name, auto_generate: bool, user: str + self, conversation_id: str, name: str, auto_generate: bool, user: str ): data = {"name": name, "auto_generate": auto_generate, "user": user} return self._send_request( "POST", f"/conversations/{conversation_id}/name", data ) - def delete_conversation(self, conversation_id, user): + def delete_conversation(self, conversation_id: str, user: str): data = {"user": user} return self._send_request("DELETE", f"/conversations/{conversation_id}", data) - def audio_to_text(self, audio_file, user): + def audio_to_text(self, audio_file: dict, user: str): data = {"user": user} files = {"audio_file": audio_file} return self._send_request_with_files("POST", "/audio-to-text", data, files) From edf4a1b652ab01a3a93e805b099e9cde6a70421e Mon Sep 17 00:00:00 2001 From: taewoong Kim <116135174+ultramancode@users.noreply.github.com> Date: Fri, 5 Sep 2025 19:15:35 +0900 Subject: [PATCH 22/52] feat: add reasoning format processing to LLMNode for tag handling (#23313) Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com> --- .../model_runtime/entities/llm_entities.py | 1 + api/core/workflow/nodes/event/event.py | 1 + api/core/workflow/nodes/llm/entities.py | 19 +++- api/core/workflow/nodes/llm/node.py | 102 +++++++++++++++++- .../core/workflow/nodes/llm/test_node.py | 64 +++++++++++ web/app/components/workflow/constants.ts | 4 + .../components/reasoning-format-config.tsx | 40 +++++++ .../components/workflow/nodes/llm/panel.tsx | 10 ++ .../components/workflow/nodes/llm/types.ts | 1 + .../workflow/nodes/llm/use-config.ts | 9 ++ web/i18n/de-DE/workflow.ts | 6 ++ web/i18n/en-US/workflow.ts | 6 ++ web/i18n/es-ES/workflow.ts | 6 ++ web/i18n/fa-IR/workflow.ts | 6 ++ web/i18n/fr-FR/workflow.ts | 6 ++ web/i18n/hi-IN/workflow.ts | 6 ++ web/i18n/it-IT/workflow.ts | 6 ++ web/i18n/ja-JP/workflow.ts | 6 ++ web/i18n/ko-KR/workflow.ts | 6 ++ web/i18n/pl-PL/workflow.ts | 6 ++ web/i18n/pt-BR/workflow.ts | 6 ++ web/i18n/ro-RO/workflow.ts | 6 ++ web/i18n/ru-RU/workflow.ts | 6 ++ web/i18n/sl-SI/workflow.ts | 6 ++ web/i18n/th-TH/workflow.ts | 6 ++ web/i18n/tr-TR/workflow.ts | 6 ++ web/i18n/uk-UA/workflow.ts | 6 ++ web/i18n/vi-VN/workflow.ts | 6 ++ web/i18n/zh-Hans/workflow.ts | 6 ++ web/i18n/zh-Hant/workflow.ts | 6 ++ 30 files changed, 366 insertions(+), 5 deletions(-) create mode 100644 web/app/components/workflow/nodes/llm/components/reasoning-format-config.tsx diff --git a/api/core/model_runtime/entities/llm_entities.py b/api/core/model_runtime/entities/llm_entities.py index dc6032e405..d5caddb7a3 100644 --- a/api/core/model_runtime/entities/llm_entities.py +++ b/api/core/model_runtime/entities/llm_entities.py @@ -156,6 +156,7 @@ class LLMResult(BaseModel): message: AssistantPromptMessage usage: LLMUsage system_fingerprint: Optional[str] = None + reasoning_content: Optional[str] = None class LLMStructuredOutput(BaseModel): diff --git a/api/core/workflow/nodes/event/event.py b/api/core/workflow/nodes/event/event.py index 3ebe80f245..e33efbe505 100644 --- a/api/core/workflow/nodes/event/event.py +++ b/api/core/workflow/nodes/event/event.py @@ -30,6 +30,7 @@ class ModelInvokeCompletedEvent(BaseModel): text: str usage: LLMUsage finish_reason: str | None = None + reasoning_content: str | None = None class RunRetryEvent(BaseModel): diff --git a/api/core/workflow/nodes/llm/entities.py b/api/core/workflow/nodes/llm/entities.py index e6f8abeba0..222914351e 100644 --- a/api/core/workflow/nodes/llm/entities.py +++ b/api/core/workflow/nodes/llm/entities.py @@ -1,5 +1,5 @@ from collections.abc import Mapping, Sequence -from typing import Any, Optional +from typing import Any, Literal, Optional from pydantic import BaseModel, Field, field_validator @@ -68,6 +68,23 @@ class LLMNodeData(BaseNodeData): structured_output: Mapping[str, Any] | None = None # We used 'structured_output_enabled' in the past, but it's not a good name. structured_output_switch_on: bool = Field(False, alias="structured_output_enabled") + reasoning_format: Literal["separated", "tagged"] = Field( + # Keep tagged as default for backward compatibility + default="tagged", + description=( + """ + Strategy for handling model reasoning output. + + separated: Return clean text (without tags) + reasoning_content field. + Recommended for new workflows. Enables safe downstream parsing and + workflow variable access: {{#node_id.reasoning_content#}} + + tagged : Return original text (with tags) + reasoning_content field. + Maintains full backward compatibility while still providing reasoning_content + for workflow automation. Frontend thinking panels work as before. + """ + ), + ) @field_validator("prompt_config", mode="before") @classmethod diff --git a/api/core/workflow/nodes/llm/node.py b/api/core/workflow/nodes/llm/node.py index 10059fdcb1..37c4ecfd6b 100644 --- a/api/core/workflow/nodes/llm/node.py +++ b/api/core/workflow/nodes/llm/node.py @@ -2,8 +2,9 @@ import base64 import io import json import logging +import re from collections.abc import Generator, Mapping, Sequence -from typing import TYPE_CHECKING, Any, Optional, Union +from typing import TYPE_CHECKING, Any, Literal, Optional, Union from core.app.entities.app_invoke_entities import ModelConfigWithCredentialsEntity from core.file import FileType, file_manager @@ -99,6 +100,9 @@ class LLMNode(BaseNode): _node_data: LLMNodeData + # Compiled regex for extracting blocks (with compatibility for attributes) + _THINK_PATTERN = re.compile(r"]*>(.*?)", re.IGNORECASE | re.DOTALL) + # Instance attributes specific to LLMNode. # Output variable for file _file_outputs: list["File"] @@ -167,6 +171,7 @@ class LLMNode(BaseNode): result_text = "" usage = LLMUsage.empty_usage() finish_reason = None + reasoning_content = None variable_pool = self.graph_runtime_state.variable_pool try: @@ -256,6 +261,7 @@ class LLMNode(BaseNode): file_saver=self._llm_file_saver, file_outputs=self._file_outputs, node_id=self.node_id, + reasoning_format=self._node_data.reasoning_format, ) structured_output: LLMStructuredOutput | None = None @@ -264,9 +270,20 @@ class LLMNode(BaseNode): if isinstance(event, RunStreamChunkEvent): yield event elif isinstance(event, ModelInvokeCompletedEvent): + # Raw text result_text = event.text usage = event.usage finish_reason = event.finish_reason + reasoning_content = event.reasoning_content or "" + + # For downstream nodes, determine clean text based on reasoning_format + if self._node_data.reasoning_format == "tagged": + # Keep tags for backward compatibility + clean_text = result_text + else: + # Extract clean text from tags + clean_text, _ = LLMNode._split_reasoning(result_text, self._node_data.reasoning_format) + # deduct quota llm_utils.deduct_llm_quota(tenant_id=self.tenant_id, model_instance=model_instance, usage=usage) break @@ -284,7 +301,12 @@ class LLMNode(BaseNode): "model_name": model_config.model, } - outputs = {"text": result_text, "usage": jsonable_encoder(usage), "finish_reason": finish_reason} + outputs = { + "text": clean_text, + "reasoning_content": reasoning_content, + "usage": jsonable_encoder(usage), + "finish_reason": finish_reason, + } if structured_output: outputs["structured_output"] = structured_output.structured_output if self._file_outputs is not None: @@ -338,6 +360,7 @@ class LLMNode(BaseNode): file_saver: LLMFileSaver, file_outputs: list["File"], node_id: str, + reasoning_format: Literal["separated", "tagged"] = "tagged", ) -> Generator[NodeEvent | LLMStructuredOutput, None, None]: model_schema = model_instance.model_type_instance.get_model_schema( node_data_model.name, model_instance.credentials @@ -374,6 +397,7 @@ class LLMNode(BaseNode): file_saver=file_saver, file_outputs=file_outputs, node_id=node_id, + reasoning_format=reasoning_format, ) @staticmethod @@ -383,6 +407,7 @@ class LLMNode(BaseNode): file_saver: LLMFileSaver, file_outputs: list["File"], node_id: str, + reasoning_format: Literal["separated", "tagged"] = "tagged", ) -> Generator[NodeEvent | LLMStructuredOutput, None, None]: # For blocking mode if isinstance(invoke_result, LLMResult): @@ -390,6 +415,7 @@ class LLMNode(BaseNode): invoke_result=invoke_result, saver=file_saver, file_outputs=file_outputs, + reasoning_format=reasoning_format, ) yield event return @@ -430,13 +456,66 @@ class LLMNode(BaseNode): except OutputParserError as e: raise LLMNodeError(f"Failed to parse structured output: {e}") - yield ModelInvokeCompletedEvent(text=full_text_buffer.getvalue(), usage=usage, finish_reason=finish_reason) + # Extract reasoning content from tags in the main text + full_text = full_text_buffer.getvalue() + + if reasoning_format == "tagged": + # Keep tags in text for backward compatibility + clean_text = full_text + reasoning_content = "" + else: + # Extract clean text and reasoning from tags + clean_text, reasoning_content = LLMNode._split_reasoning(full_text, reasoning_format) + + yield ModelInvokeCompletedEvent( + # Use clean_text for separated mode, full_text for tagged mode + text=clean_text if reasoning_format == "separated" else full_text, + usage=usage, + finish_reason=finish_reason, + # Reasoning content for workflow variables and downstream nodes + reasoning_content=reasoning_content, + ) @staticmethod def _image_file_to_markdown(file: "File", /): text_chunk = f"![]({file.generate_url()})" return text_chunk + @classmethod + def _split_reasoning( + cls, text: str, reasoning_format: Literal["separated", "tagged"] = "tagged" + ) -> tuple[str, str]: + """ + Split reasoning content from text based on reasoning_format strategy. + + Args: + text: Full text that may contain blocks + reasoning_format: Strategy for handling reasoning content + - "separated": Remove tags and return clean text + reasoning_content field + - "tagged": Keep tags in text, return empty reasoning_content + + Returns: + tuple of (clean_text, reasoning_content) + """ + + if reasoning_format == "tagged": + return text, "" + + # Find all ... blocks (case-insensitive) + matches = cls._THINK_PATTERN.findall(text) + + # Extract reasoning content from all blocks + reasoning_content = "\n".join(match.strip() for match in matches) if matches else "" + + # Remove all ... blocks from original text + clean_text = cls._THINK_PATTERN.sub("", text) + + # Clean up extra whitespace + clean_text = re.sub(r"\n\s*\n", "\n\n", clean_text).strip() + + # Separated mode: always return clean text and reasoning_content + return clean_text, reasoning_content or "" + def _transform_chat_messages( self, messages: Sequence[LLMNodeChatModelMessage] | LLMNodeCompletionModelPromptTemplate, / ) -> Sequence[LLMNodeChatModelMessage] | LLMNodeCompletionModelPromptTemplate: @@ -964,6 +1043,7 @@ class LLMNode(BaseNode): invoke_result: LLMResult, saver: LLMFileSaver, file_outputs: list["File"], + reasoning_format: Literal["separated", "tagged"] = "tagged", ) -> ModelInvokeCompletedEvent: buffer = io.StringIO() for text_part in LLMNode._save_multimodal_output_and_convert_result_to_markdown( @@ -973,10 +1053,24 @@ class LLMNode(BaseNode): ): buffer.write(text_part) + # Extract reasoning content from tags in the main text + full_text = buffer.getvalue() + + if reasoning_format == "tagged": + # Keep tags in text for backward compatibility + clean_text = full_text + reasoning_content = "" + else: + # Extract clean text and reasoning from tags + clean_text, reasoning_content = LLMNode._split_reasoning(full_text, reasoning_format) + return ModelInvokeCompletedEvent( - text=buffer.getvalue(), + # Use clean_text for separated mode, full_text for tagged mode + text=clean_text if reasoning_format == "separated" else full_text, usage=invoke_result.usage, finish_reason=None, + # Reasoning content for workflow variables and downstream nodes + reasoning_content=reasoning_content, ) @staticmethod diff --git a/api/tests/unit_tests/core/workflow/nodes/llm/test_node.py b/api/tests/unit_tests/core/workflow/nodes/llm/test_node.py index 23a7fab7cf..ea8a88692f 100644 --- a/api/tests/unit_tests/core/workflow/nodes/llm/test_node.py +++ b/api/tests/unit_tests/core/workflow/nodes/llm/test_node.py @@ -69,6 +69,7 @@ def llm_node_data() -> LLMNodeData: detail=ImagePromptMessageContent.DETAIL.HIGH, ), ), + reasoning_format="tagged", ) @@ -689,3 +690,66 @@ class TestSaveMultimodalOutputAndConvertResultToMarkdown: assert list(gen) == [] mock_file_saver.save_binary_string.assert_not_called() mock_file_saver.save_remote_url.assert_not_called() + + +class TestReasoningFormat: + """Test cases for reasoning_format functionality""" + + def test_split_reasoning_separated_mode(self): + """Test separated mode: tags are removed and content is extracted""" + + text_with_think = """ + I need to explain what Dify is. It's an open source AI platform. + Dify is an open source AI platform. + """ + + clean_text, reasoning_content = LLMNode._split_reasoning(text_with_think, "separated") + + assert clean_text == "Dify is an open source AI platform." + assert reasoning_content == "I need to explain what Dify is. It's an open source AI platform." + + def test_split_reasoning_tagged_mode(self): + """Test tagged mode: original text is preserved""" + + text_with_think = """ + I need to explain what Dify is. It's an open source AI platform. + Dify is an open source AI platform. + """ + + clean_text, reasoning_content = LLMNode._split_reasoning(text_with_think, "tagged") + + # Original text unchanged + assert clean_text == text_with_think + # Empty reasoning content in tagged mode + assert reasoning_content == "" + + def test_split_reasoning_no_think_blocks(self): + """Test behavior when no tags are present""" + + text_without_think = "This is a simple answer without any thinking blocks." + + clean_text, reasoning_content = LLMNode._split_reasoning(text_without_think, "separated") + + assert clean_text == text_without_think + assert reasoning_content == "" + + def test_reasoning_format_default_value(self): + """Test that reasoning_format defaults to 'tagged' for backward compatibility""" + + node_data = LLMNodeData( + title="Test LLM", + model=ModelConfig(provider="openai", name="gpt-3.5-turbo", mode="chat", completion_params={}), + prompt_template=[], + context=ContextConfig(enabled=False), + ) + + assert node_data.reasoning_format == "tagged" + + text_with_think = """ + I need to explain what Dify is. It's an open source AI platform. + Dify is an open source AI platform. + """ + clean_text, reasoning_content = LLMNode._split_reasoning(text_with_think, node_data.reasoning_format) + + assert clean_text == text_with_think + assert reasoning_content == "" diff --git a/web/app/components/workflow/constants.ts b/web/app/components/workflow/constants.ts index a17961620b..04c2b7c682 100644 --- a/web/app/components/workflow/constants.ts +++ b/web/app/components/workflow/constants.ts @@ -479,6 +479,10 @@ export const LLM_OUTPUT_STRUCT: Var[] = [ variable: 'text', type: VarType.string, }, + { + variable: 'reasoning_content', + type: VarType.string, + }, { variable: 'usage', type: VarType.object, diff --git a/web/app/components/workflow/nodes/llm/components/reasoning-format-config.tsx b/web/app/components/workflow/nodes/llm/components/reasoning-format-config.tsx new file mode 100644 index 0000000000..49425ff64c --- /dev/null +++ b/web/app/components/workflow/nodes/llm/components/reasoning-format-config.tsx @@ -0,0 +1,40 @@ +import type { FC } from 'react' +import React from 'react' +import { useTranslation } from 'react-i18next' +import Field from '@/app/components/workflow/nodes/_base/components/field' +import Switch from '@/app/components/base/switch' + +type ReasoningFormatConfigProps = { + value?: 'tagged' | 'separated' + onChange: (value: 'tagged' | 'separated') => void + readonly?: boolean +} + +const ReasoningFormatConfig: FC = ({ + value = 'tagged', + onChange, + readonly = false, +}) => { + const { t } = useTranslation() + + return ( + onChange(enabled ? 'separated' : 'tagged')} + size='md' + disabled={readonly} + key={value} + /> + } + > +
+ + ) +} + +export default ReasoningFormatConfig diff --git a/web/app/components/workflow/nodes/llm/panel.tsx b/web/app/components/workflow/nodes/llm/panel.tsx index 52bbf48b74..f5f5997ace 100644 --- a/web/app/components/workflow/nodes/llm/panel.tsx +++ b/web/app/components/workflow/nodes/llm/panel.tsx @@ -17,6 +17,7 @@ import type { NodePanelProps } from '@/app/components/workflow/types' import Tooltip from '@/app/components/base/tooltip' import Editor from '@/app/components/workflow/nodes/_base/components/prompt/editor' import StructureOutput from './components/structure-output' +import ReasoningFormatConfig from './components/reasoning-format-config' import Switch from '@/app/components/base/switch' import { RiAlertFill, RiQuestionLine } from '@remixicon/react' import { fetchAndMergeValidCompletionParams } from '@/utils/completion-params' @@ -61,6 +62,7 @@ const Panel: FC> = ({ handleStructureOutputEnableChange, handleStructureOutputChange, filterJinja2InputVar, + handleReasoningFormatChange, } = useConfig(id, data) const model = inputs.model @@ -239,6 +241,14 @@ const Panel: FC> = ({ config={inputs.vision?.configs} onConfigChange={handleVisionResolutionChange} /> + + {/* Reasoning Format */} +
{ return [VarType.arrayObject, VarType.array, VarType.number, VarType.string, VarType.secret, VarType.arrayString, VarType.arrayNumber, VarType.file, VarType.arrayFile].includes(varPayload.type) }, []) + // reasoning format + const handleReasoningFormatChange = useCallback((reasoningFormat: 'tagged' | 'separated') => { + const newInputs = produce(inputs, (draft) => { + draft.reasoning_format = reasoningFormat + }) + setInputs(newInputs) + }, [inputs, setInputs]) + const { availableVars, availableNodesWithParent, @@ -355,6 +363,7 @@ const useConfig = (id: string, payload: LLMNodeType) => { setStructuredOutputCollapsed, handleStructureOutputEnableChange, filterJinja2InputVar, + handleReasoningFormatChange, } } diff --git a/web/i18n/de-DE/workflow.ts b/web/i18n/de-DE/workflow.ts index 0050986d3e..576afc2af1 100644 --- a/web/i18n/de-DE/workflow.ts +++ b/web/i18n/de-DE/workflow.ts @@ -470,6 +470,12 @@ const translation = { instruction: 'Anleitung', regenerate: 'Regenerieren', }, + reasoningFormat: { + tooltip: 'Inhalte aus Denk-Tags extrahieren und im Feld reasoning_content speichern.', + separated: 'Separate Denk tags', + title: 'Aktivieren Sie die Trennung von Argumentations-Tags', + tagged: 'Behalte die Denk-Tags', + }, }, knowledgeRetrieval: { queryVariable: 'Abfragevariable', diff --git a/web/i18n/en-US/workflow.ts b/web/i18n/en-US/workflow.ts index 14bd3d1293..eae63e9c2f 100644 --- a/web/i18n/en-US/workflow.ts +++ b/web/i18n/en-US/workflow.ts @@ -449,6 +449,12 @@ const translation = { variable: 'Variable', }, sysQueryInUser: 'sys.query in user message is required', + reasoningFormat: { + title: 'Enable reasoning tag separation', + tagged: 'Keep think tags', + separated: 'Separate think tags', + tooltip: 'Extract content from think tags and store it in the reasoning_content field.', + }, jsonSchema: { title: 'Structured Output Schema', instruction: 'Instruction', diff --git a/web/i18n/es-ES/workflow.ts b/web/i18n/es-ES/workflow.ts index fcab9c2731..238eb016ad 100644 --- a/web/i18n/es-ES/workflow.ts +++ b/web/i18n/es-ES/workflow.ts @@ -470,6 +470,12 @@ const translation = { import: 'Importar desde JSON', resetDefaults: 'Restablecer', }, + reasoningFormat: { + tagged: 'Mantén las etiquetas de pensamiento', + separated: 'Separar etiquetas de pensamiento', + title: 'Habilitar la separación de etiquetas de razonamiento', + tooltip: 'Extraer contenido de las etiquetas de pensamiento y almacenarlo en el campo reasoning_content.', + }, }, knowledgeRetrieval: { queryVariable: 'Variable de consulta', diff --git a/web/i18n/fa-IR/workflow.ts b/web/i18n/fa-IR/workflow.ts index 567f70cd1f..1a2d9aa227 100644 --- a/web/i18n/fa-IR/workflow.ts +++ b/web/i18n/fa-IR/workflow.ts @@ -470,6 +470,12 @@ const translation = { fieldNamePlaceholder: 'نام میدان', generationTip: 'شما می‌توانید از زبان طبیعی برای ایجاد سریع یک طرح‌واره JSON استفاده کنید.', }, + reasoningFormat: { + separated: 'تگ‌های تفکر جداگانه', + title: 'فعال‌سازی جداسازی برچسب‌های استدلال', + tagged: 'به فکر برچسب‌ها باشید', + tooltip: 'محتوا را از تگ‌های تفکر استخراج کرده و در فیلد reasoning_content ذخیره کنید.', + }, }, knowledgeRetrieval: { queryVariable: 'متغیر جستجو', diff --git a/web/i18n/fr-FR/workflow.ts b/web/i18n/fr-FR/workflow.ts index 3874ff6748..c2eb056198 100644 --- a/web/i18n/fr-FR/workflow.ts +++ b/web/i18n/fr-FR/workflow.ts @@ -470,6 +470,12 @@ const translation = { generateJsonSchema: 'Générer un schéma JSON', resultTip: 'Voici le résultat généré. Si vous n\'êtes pas satisfait, vous pouvez revenir en arrière et modifier votre demande.', }, + reasoningFormat: { + title: 'Activer la séparation des balises de raisonnement', + tagged: 'Gardez les étiquettes de pensée', + separated: 'Séparer les balises de réflexion', + tooltip: 'Extraire le contenu des balises think et le stocker dans le champ reasoning_content.', + }, }, knowledgeRetrieval: { queryVariable: 'Variable de requête', diff --git a/web/i18n/hi-IN/workflow.ts b/web/i18n/hi-IN/workflow.ts index b04d232e30..8df3e4b745 100644 --- a/web/i18n/hi-IN/workflow.ts +++ b/web/i18n/hi-IN/workflow.ts @@ -483,6 +483,12 @@ const translation = { required: 'आवश्यक', addChildField: 'बच्चे का क्षेत्र जोड़ें', }, + reasoningFormat: { + title: 'कारण संबंध टैग विभाजन सक्षम करें', + separated: 'अलग सोच टैग', + tagged: 'टैग्स के बारे में सोचते रहें', + tooltip: 'थिंक टैग से सामग्री निकाले और इसे reasoning_content क्षेत्र में संग्रहित करें।', + }, }, knowledgeRetrieval: { queryVariable: 'प्रश्न वेरिएबल', diff --git a/web/i18n/it-IT/workflow.ts b/web/i18n/it-IT/workflow.ts index 80c695cc6f..821e7544c7 100644 --- a/web/i18n/it-IT/workflow.ts +++ b/web/i18n/it-IT/workflow.ts @@ -487,6 +487,12 @@ const translation = { generating: 'Generazione dello schema JSON...', generatedResult: 'Risultato generato', }, + reasoningFormat: { + title: 'Abilita la separazione dei tag di ragionamento', + tagged: 'Continua a pensare ai tag', + separated: 'Tag di pensiero separati', + tooltip: 'Estrai il contenuto dai tag think e conservalo nel campo reasoning_content.', + }, }, knowledgeRetrieval: { queryVariable: 'Variabile Query', diff --git a/web/i18n/ja-JP/workflow.ts b/web/i18n/ja-JP/workflow.ts index 06535a8523..2a3ee304f3 100644 --- a/web/i18n/ja-JP/workflow.ts +++ b/web/i18n/ja-JP/workflow.ts @@ -477,6 +477,12 @@ const translation = { saveSchema: '編集中のフィールドを確定してから保存してください。', }, }, + reasoningFormat: { + tagged: 'タグを考え続けてください', + separated: '思考タグを分ける', + title: '推論タグの分離を有効にする', + tooltip: 'thinkタグから内容を抽出し、それをreasoning_contentフィールドに保存します。', + }, }, knowledgeRetrieval: { queryVariable: '検索変数', diff --git a/web/i18n/ko-KR/workflow.ts b/web/i18n/ko-KR/workflow.ts index 7b2fb77981..bc73e67e6a 100644 --- a/web/i18n/ko-KR/workflow.ts +++ b/web/i18n/ko-KR/workflow.ts @@ -497,6 +497,12 @@ const translation = { doc: '구조화된 출력에 대해 더 알아보세요.', import: 'JSON 에서 가져오기', }, + reasoningFormat: { + title: '추론 태그 분리 활성화', + separated: '추론 태그 분리', + tooltip: '추론 태그에서 내용을 추출하고 이를 reasoning_content 필드에 저장합니다', + tagged: '추론 태그 유지', + }, }, knowledgeRetrieval: { queryVariable: '쿼리 변수', diff --git a/web/i18n/pl-PL/workflow.ts b/web/i18n/pl-PL/workflow.ts index 9560865e1c..b5cd95d245 100644 --- a/web/i18n/pl-PL/workflow.ts +++ b/web/i18n/pl-PL/workflow.ts @@ -470,6 +470,12 @@ const translation = { back: 'Tył', addField: 'Dodaj pole', }, + reasoningFormat: { + tooltip: 'Wyodrębnij treść z tagów think i przechowaj ją w polu reasoning_content.', + separated: 'Oddziel tagi myślenia', + tagged: 'Zachowaj myśl tagi', + title: 'Włącz separację tagów uzasadnienia', + }, }, knowledgeRetrieval: { queryVariable: 'Zmienna zapytania', diff --git a/web/i18n/pt-BR/workflow.ts b/web/i18n/pt-BR/workflow.ts index 9e4b2dd445..a7ece8417f 100644 --- a/web/i18n/pt-BR/workflow.ts +++ b/web/i18n/pt-BR/workflow.ts @@ -470,6 +470,12 @@ const translation = { apply: 'Aplicar', required: 'obrigatório', }, + reasoningFormat: { + tagged: 'Mantenha as tags de pensamento', + title: 'Ativar separação de tags de raciocínio', + separated: 'Separe as tags de pensamento', + tooltip: 'Extraia o conteúdo das tags de pensamento e armazene-o no campo reasoning_content.', + }, }, knowledgeRetrieval: { queryVariable: 'Variável de consulta', diff --git a/web/i18n/ro-RO/workflow.ts b/web/i18n/ro-RO/workflow.ts index 3bda159d44..ce393406d2 100644 --- a/web/i18n/ro-RO/workflow.ts +++ b/web/i18n/ro-RO/workflow.ts @@ -470,6 +470,12 @@ const translation = { back: 'Înapoi', promptPlaceholder: 'Descrie schema ta JSON...', }, + reasoningFormat: { + tagged: 'Ține minte etichetele', + separated: 'Etichete de gândire separate', + title: 'Activează separarea etichetelor de raționare', + tooltip: 'Extrage conținutul din etichetele think și stochează-l în câmpul reasoning_content.', + }, }, knowledgeRetrieval: { queryVariable: 'Variabilă de interogare', diff --git a/web/i18n/ru-RU/workflow.ts b/web/i18n/ru-RU/workflow.ts index bd86004cbe..1290f7e6b7 100644 --- a/web/i18n/ru-RU/workflow.ts +++ b/web/i18n/ru-RU/workflow.ts @@ -470,6 +470,12 @@ const translation = { generating: 'Генерация схемы JSON...', promptTooltip: 'Преобразуйте текстовое описание в стандартизированную структуру JSON Schema.', }, + reasoningFormat: { + tagged: 'Продолжайте думать о тегах', + title: 'Включите разделение тегов на основе логики', + tooltip: 'Извлечь содержимое из тегов think и сохранить его в поле reasoning_content.', + separated: 'Отдельные теги для мышления', + }, }, knowledgeRetrieval: { queryVariable: 'Переменная запроса', diff --git a/web/i18n/sl-SI/workflow.ts b/web/i18n/sl-SI/workflow.ts index 9d57db3344..57b9fa5ed8 100644 --- a/web/i18n/sl-SI/workflow.ts +++ b/web/i18n/sl-SI/workflow.ts @@ -477,6 +477,12 @@ const translation = { context: 'kontekst', addMessage: 'Dodaj sporočilo', vision: 'vizija', + reasoningFormat: { + tagged: 'Ohranite oznake za razmišljanje', + title: 'Omogoči ločevanje oznak za razsojanje', + tooltip: 'Izvleći vsebino iz miselnih oznak in jo shraniti v polje reasoning_content.', + separated: 'Ločite oznake za razmišljanje', + }, }, knowledgeRetrieval: { outputVars: { diff --git a/web/i18n/th-TH/workflow.ts b/web/i18n/th-TH/workflow.ts index 653adbe0b3..7d6e892178 100644 --- a/web/i18n/th-TH/workflow.ts +++ b/web/i18n/th-TH/workflow.ts @@ -470,6 +470,12 @@ const translation = { stringValidations: 'การตรวจสอบสตริง', required: 'จำเป็นต้องใช้', }, + reasoningFormat: { + tagged: 'รักษาความคิดเกี่ยวกับแท็ก', + separated: 'แยกแท็กความคิดเห็น', + tooltip: 'ดึงเนื้อหาจากแท็กคิดและเก็บไว้ในฟิลด์ reasoning_content.', + title: 'เปิดใช้งานการแยกแท็กการเหตุผล', + }, }, knowledgeRetrieval: { queryVariable: 'ตัวแปรแบบสอบถาม', diff --git a/web/i18n/tr-TR/workflow.ts b/web/i18n/tr-TR/workflow.ts index 903705a65a..cda742fb68 100644 --- a/web/i18n/tr-TR/workflow.ts +++ b/web/i18n/tr-TR/workflow.ts @@ -470,6 +470,12 @@ const translation = { addChildField: 'Çocuk Alanı Ekle', resultTip: 'İşte oluşturulan sonuç. Eğer memnun değilseniz, geri dönüp isteminizi değiştirebilirsiniz.', }, + reasoningFormat: { + separated: 'Ayrı düşünce etiketleri', + title: 'Akıl yürütme etiket ayrımını etkinleştir', + tagged: 'Etiketleri düşünmeye devam et', + tooltip: 'Düşünce etiketlerinden içeriği çıkarın ve bunu reasoning_content alanında saklayın.', + }, }, knowledgeRetrieval: { queryVariable: 'Sorgu Değişkeni', diff --git a/web/i18n/uk-UA/workflow.ts b/web/i18n/uk-UA/workflow.ts index f051ab990f..999d1bfb3d 100644 --- a/web/i18n/uk-UA/workflow.ts +++ b/web/i18n/uk-UA/workflow.ts @@ -470,6 +470,12 @@ const translation = { title: 'Структурована схема виходу', doc: 'Дізнайтеся більше про структурований вихід', }, + reasoningFormat: { + separated: 'Окремі теги для думок', + tagged: 'Продовжуйте думати про мітки', + title: 'Увімкніть розділення тегів для міркування', + tooltip: 'Витягніть вміст з тегів think і зберігайте його в полі reasoning_content.', + }, }, knowledgeRetrieval: { queryVariable: 'Змінна запиту', diff --git a/web/i18n/vi-VN/workflow.ts b/web/i18n/vi-VN/workflow.ts index 0b2e2e8755..2f8e20d08d 100644 --- a/web/i18n/vi-VN/workflow.ts +++ b/web/i18n/vi-VN/workflow.ts @@ -470,6 +470,12 @@ const translation = { addChildField: 'Thêm trường trẻ em', title: 'Sơ đồ đầu ra có cấu trúc', }, + reasoningFormat: { + tagged: 'Giữ lại thẻ suy nghĩ', + tooltip: 'Trích xuất nội dung từ các thẻ think và lưu nó vào trường reasoning_content.', + separated: 'Tách biệt các thẻ suy nghĩ', + title: 'Bật chế độ phân tách nhãn lý luận', + }, }, knowledgeRetrieval: { queryVariable: 'Biến truy vấn', diff --git a/web/i18n/zh-Hans/workflow.ts b/web/i18n/zh-Hans/workflow.ts index daaba921ff..4573fa7bda 100644 --- a/web/i18n/zh-Hans/workflow.ts +++ b/web/i18n/zh-Hans/workflow.ts @@ -477,6 +477,12 @@ const translation = { saveSchema: '请先完成当前字段的编辑', }, }, + reasoningFormat: { + tooltip: '从think标签中提取内容,并将其存储在reasoning_content字段中。', + title: '启用推理标签分离', + tagged: '保持思考标签', + separated: '分开思考标签', + }, }, knowledgeRetrieval: { queryVariable: '查询变量', diff --git a/web/i18n/zh-Hant/workflow.ts b/web/i18n/zh-Hant/workflow.ts index 1105800a76..6f79177d14 100644 --- a/web/i18n/zh-Hant/workflow.ts +++ b/web/i18n/zh-Hant/workflow.ts @@ -470,6 +470,12 @@ const translation = { required: '必需的', resultTip: '這是生成的結果。如果您不滿意,可以回去修改您的提示。', }, + reasoningFormat: { + title: '啟用推理標籤分離', + tooltip: '從 think 標籤中提取內容並將其存儲在 reasoning_content 欄位中。', + tagged: '保持思考標籤', + separated: '分開思考標籤', + }, }, knowledgeRetrieval: { queryVariable: '查詢變量', From 917d60a1cb029d1501ab40a32663433b57eb93ab Mon Sep 17 00:00:00 2001 From: NeatGuyCoding <15627489+NeatGuyCoding@users.noreply.github.com> Date: Fri, 5 Sep 2025 19:20:37 +0800 Subject: [PATCH 23/52] Feature add test containers add document to index (#25251) --- .../tasks/__init__.py | 0 .../tasks/test_add_document_to_index_task.py | 786 ++++++++++++++++++ 2 files changed, 786 insertions(+) create mode 100644 api/tests/test_containers_integration_tests/tasks/__init__.py create mode 100644 api/tests/test_containers_integration_tests/tasks/test_add_document_to_index_task.py diff --git a/api/tests/test_containers_integration_tests/tasks/__init__.py b/api/tests/test_containers_integration_tests/tasks/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/api/tests/test_containers_integration_tests/tasks/test_add_document_to_index_task.py b/api/tests/test_containers_integration_tests/tasks/test_add_document_to_index_task.py new file mode 100644 index 0000000000..4600f2addb --- /dev/null +++ b/api/tests/test_containers_integration_tests/tasks/test_add_document_to_index_task.py @@ -0,0 +1,786 @@ +from unittest.mock import MagicMock, patch + +import pytest +from faker import Faker + +from core.rag.index_processor.constant.index_type import IndexType +from extensions.ext_database import db +from extensions.ext_redis import redis_client +from models.account import Account, Tenant, TenantAccountJoin, TenantAccountRole +from models.dataset import Dataset, DatasetAutoDisableLog, Document, DocumentSegment +from tasks.add_document_to_index_task import add_document_to_index_task + + +class TestAddDocumentToIndexTask: + """Integration tests for add_document_to_index_task using testcontainers.""" + + @pytest.fixture + def mock_external_service_dependencies(self): + """Mock setup for external service dependencies.""" + with ( + patch("tasks.add_document_to_index_task.IndexProcessorFactory") as mock_index_processor_factory, + ): + # Setup mock index processor + mock_processor = MagicMock() + mock_index_processor_factory.return_value.init_index_processor.return_value = mock_processor + + yield { + "index_processor_factory": mock_index_processor_factory, + "index_processor": mock_processor, + } + + def _create_test_dataset_and_document(self, db_session_with_containers, mock_external_service_dependencies): + """ + Helper method to create a test dataset and document for testing. + + Args: + db_session_with_containers: Database session from testcontainers infrastructure + mock_external_service_dependencies: Mock dependencies + + Returns: + tuple: (dataset, document) - Created dataset and document instances + """ + fake = Faker() + + # Create account and tenant + account = Account( + email=fake.email(), + name=fake.name(), + interface_language="en-US", + status="active", + ) + db.session.add(account) + db.session.commit() + + tenant = Tenant( + name=fake.company(), + status="normal", + ) + db.session.add(tenant) + db.session.commit() + + # Create tenant-account join + join = TenantAccountJoin( + tenant_id=tenant.id, + account_id=account.id, + role=TenantAccountRole.OWNER.value, + current=True, + ) + db.session.add(join) + db.session.commit() + + # Create dataset + dataset = Dataset( + id=fake.uuid4(), + tenant_id=tenant.id, + name=fake.company(), + description=fake.text(max_nb_chars=100), + data_source_type="upload_file", + indexing_technique="high_quality", + created_by=account.id, + ) + db.session.add(dataset) + db.session.commit() + + # Create document + document = Document( + id=fake.uuid4(), + tenant_id=tenant.id, + dataset_id=dataset.id, + position=1, + data_source_type="upload_file", + batch="test_batch", + name=fake.file_name(), + created_from="upload_file", + created_by=account.id, + indexing_status="completed", + enabled=True, + doc_form=IndexType.PARAGRAPH_INDEX, + ) + db.session.add(document) + db.session.commit() + + # Refresh dataset to ensure doc_form property works correctly + db.session.refresh(dataset) + + return dataset, document + + def _create_test_segments(self, db_session_with_containers, document, dataset): + """ + Helper method to create test document segments. + + Args: + db_session_with_containers: Database session from testcontainers infrastructure + document: Document instance + dataset: Dataset instance + + Returns: + list: List of created DocumentSegment instances + """ + fake = Faker() + segments = [] + + for i in range(3): + segment = DocumentSegment( + id=fake.uuid4(), + tenant_id=document.tenant_id, + dataset_id=dataset.id, + document_id=document.id, + position=i, + content=fake.text(max_nb_chars=200), + word_count=len(fake.text(max_nb_chars=200).split()), + tokens=len(fake.text(max_nb_chars=200).split()) * 2, + index_node_id=f"node_{i}", + index_node_hash=f"hash_{i}", + enabled=False, + status="completed", + created_by=document.created_by, + ) + db.session.add(segment) + segments.append(segment) + + db.session.commit() + return segments + + def test_add_document_to_index_success(self, db_session_with_containers, mock_external_service_dependencies): + """ + Test successful document indexing with paragraph index type. + + This test verifies: + - Proper document retrieval from database + - Correct segment processing and document creation + - Index processor integration + - Database state updates + - Segment status changes + - Redis cache key deletion + """ + # Arrange: Create test data + dataset, document = self._create_test_dataset_and_document( + db_session_with_containers, mock_external_service_dependencies + ) + segments = self._create_test_segments(db_session_with_containers, document, dataset) + + # Set up Redis cache key to simulate indexing in progress + indexing_cache_key = f"document_{document.id}_indexing" + redis_client.set(indexing_cache_key, "processing", ex=300) # 5 minutes expiry + + # Verify cache key exists + assert redis_client.exists(indexing_cache_key) == 1 + + # Act: Execute the task + add_document_to_index_task(document.id) + + # Assert: Verify the expected outcomes + # Verify index processor was called correctly + mock_external_service_dependencies["index_processor_factory"].assert_called_once_with(IndexType.PARAGRAPH_INDEX) + mock_external_service_dependencies["index_processor"].load.assert_called_once() + + # Verify database state changes + db.session.refresh(document) + for segment in segments: + db.session.refresh(segment) + assert segment.enabled is True + assert segment.disabled_at is None + assert segment.disabled_by is None + + # Verify Redis cache key was deleted + assert redis_client.exists(indexing_cache_key) == 0 + + def test_add_document_to_index_with_different_index_type( + self, db_session_with_containers, mock_external_service_dependencies + ): + """ + Test document indexing with different index types. + + This test verifies: + - Proper handling of different index types + - Index processor factory integration + - Document processing with various configurations + - Redis cache key deletion + """ + # Arrange: Create test data with different index type + dataset, document = self._create_test_dataset_and_document( + db_session_with_containers, mock_external_service_dependencies + ) + + # Update document to use different index type + document.doc_form = IndexType.QA_INDEX + db.session.commit() + + # Refresh dataset to ensure doc_form property reflects the updated document + db.session.refresh(dataset) + + # Create segments + segments = self._create_test_segments(db_session_with_containers, document, dataset) + + # Set up Redis cache key + indexing_cache_key = f"document_{document.id}_indexing" + redis_client.set(indexing_cache_key, "processing", ex=300) + + # Act: Execute the task + add_document_to_index_task(document.id) + + # Assert: Verify different index type handling + mock_external_service_dependencies["index_processor_factory"].assert_called_once_with(IndexType.QA_INDEX) + mock_external_service_dependencies["index_processor"].load.assert_called_once() + + # Verify the load method was called with correct parameters + call_args = mock_external_service_dependencies["index_processor"].load.call_args + assert call_args is not None + documents = call_args[0][1] # Second argument should be documents list + assert len(documents) == 3 + + # Verify database state changes + db.session.refresh(document) + for segment in segments: + db.session.refresh(segment) + assert segment.enabled is True + assert segment.disabled_at is None + assert segment.disabled_by is None + + # Verify Redis cache key was deleted + assert redis_client.exists(indexing_cache_key) == 0 + + def test_add_document_to_index_document_not_found( + self, db_session_with_containers, mock_external_service_dependencies + ): + """ + Test handling of non-existent document. + + This test verifies: + - Proper error handling for missing documents + - Early return without processing + - Database session cleanup + - No unnecessary index processor calls + - Redis cache key not affected (since it was never created) + """ + # Arrange: Use non-existent document ID + fake = Faker() + non_existent_id = fake.uuid4() + + # Act: Execute the task with non-existent document + add_document_to_index_task(non_existent_id) + + # Assert: Verify no processing occurred + mock_external_service_dependencies["index_processor_factory"].assert_not_called() + mock_external_service_dependencies["index_processor"].load.assert_not_called() + + # Note: redis_client.delete is not called when document is not found + # because indexing_cache_key is not defined in that case + + def test_add_document_to_index_invalid_indexing_status( + self, db_session_with_containers, mock_external_service_dependencies + ): + """ + Test handling of document with invalid indexing status. + + This test verifies: + - Early return when indexing_status is not "completed" + - No index processing for documents not ready for indexing + - Proper database session cleanup + - No unnecessary external service calls + - Redis cache key not affected + """ + # Arrange: Create test data with invalid indexing status + dataset, document = self._create_test_dataset_and_document( + db_session_with_containers, mock_external_service_dependencies + ) + + # Set invalid indexing status + document.indexing_status = "processing" + db.session.commit() + + # Act: Execute the task + add_document_to_index_task(document.id) + + # Assert: Verify no processing occurred + mock_external_service_dependencies["index_processor_factory"].assert_not_called() + mock_external_service_dependencies["index_processor"].load.assert_not_called() + + def test_add_document_to_index_dataset_not_found( + self, db_session_with_containers, mock_external_service_dependencies + ): + """ + Test handling when document's dataset doesn't exist. + + This test verifies: + - Proper error handling when dataset is missing + - Document status is set to error + - Document is disabled + - Error information is recorded + - Redis cache is cleared despite error + """ + # Arrange: Create test data + dataset, document = self._create_test_dataset_and_document( + db_session_with_containers, mock_external_service_dependencies + ) + + # Set up Redis cache key + indexing_cache_key = f"document_{document.id}_indexing" + redis_client.set(indexing_cache_key, "processing", ex=300) + + # Delete the dataset to simulate dataset not found scenario + db.session.delete(dataset) + db.session.commit() + + # Act: Execute the task + add_document_to_index_task(document.id) + + # Assert: Verify error handling + db.session.refresh(document) + assert document.enabled is False + assert document.indexing_status == "error" + assert document.error is not None + assert "doesn't exist" in document.error + assert document.disabled_at is not None + + # Verify no index processing occurred + mock_external_service_dependencies["index_processor_factory"].assert_not_called() + mock_external_service_dependencies["index_processor"].load.assert_not_called() + + # Verify redis cache was cleared despite error + assert redis_client.exists(indexing_cache_key) == 0 + + def test_add_document_to_index_with_parent_child_structure( + self, db_session_with_containers, mock_external_service_dependencies + ): + """ + Test document indexing with parent-child structure. + + This test verifies: + - Proper handling of PARENT_CHILD_INDEX type + - Child document creation from segments + - Correct document structure for parent-child indexing + - Index processor receives properly structured documents + - Redis cache key deletion + """ + # Arrange: Create test data with parent-child index type + dataset, document = self._create_test_dataset_and_document( + db_session_with_containers, mock_external_service_dependencies + ) + + # Update document to use parent-child index type + document.doc_form = IndexType.PARENT_CHILD_INDEX + db.session.commit() + + # Refresh dataset to ensure doc_form property reflects the updated document + db.session.refresh(dataset) + + # Create segments with mock child chunks + segments = self._create_test_segments(db_session_with_containers, document, dataset) + + # Set up Redis cache key + indexing_cache_key = f"document_{document.id}_indexing" + redis_client.set(indexing_cache_key, "processing", ex=300) + + # Mock the get_child_chunks method for each segment + with patch.object(DocumentSegment, "get_child_chunks") as mock_get_child_chunks: + # Setup mock to return child chunks for each segment + mock_child_chunks = [] + for i in range(2): # Each segment has 2 child chunks + mock_child = MagicMock() + mock_child.content = f"child_content_{i}" + mock_child.index_node_id = f"child_node_{i}" + mock_child.index_node_hash = f"child_hash_{i}" + mock_child_chunks.append(mock_child) + + mock_get_child_chunks.return_value = mock_child_chunks + + # Act: Execute the task + add_document_to_index_task(document.id) + + # Assert: Verify parent-child index processing + mock_external_service_dependencies["index_processor_factory"].assert_called_once_with( + IndexType.PARENT_CHILD_INDEX + ) + mock_external_service_dependencies["index_processor"].load.assert_called_once() + + # Verify the load method was called with correct parameters + call_args = mock_external_service_dependencies["index_processor"].load.call_args + assert call_args is not None + documents = call_args[0][1] # Second argument should be documents list + assert len(documents) == 3 # 3 segments + + # Verify each document has children + for doc in documents: + assert hasattr(doc, "children") + assert len(doc.children) == 2 # Each document has 2 children + + # Verify database state changes + db.session.refresh(document) + for segment in segments: + db.session.refresh(segment) + assert segment.enabled is True + assert segment.disabled_at is None + assert segment.disabled_by is None + + # Verify redis cache was cleared + assert redis_client.exists(indexing_cache_key) == 0 + + def test_add_document_to_index_with_no_segments_to_process( + self, db_session_with_containers, mock_external_service_dependencies + ): + """ + Test document indexing when no segments need processing. + + This test verifies: + - Proper handling when all segments are already enabled + - Index processing still occurs but with empty documents list + - Auto disable log deletion still occurs + - Redis cache is cleared + """ + # Arrange: Create test data + dataset, document = self._create_test_dataset_and_document( + db_session_with_containers, mock_external_service_dependencies + ) + + # Create segments that are already enabled + fake = Faker() + segments = [] + for i in range(3): + segment = DocumentSegment( + id=fake.uuid4(), + tenant_id=document.tenant_id, + dataset_id=dataset.id, + document_id=document.id, + position=i, + content=fake.text(max_nb_chars=200), + word_count=len(fake.text(max_nb_chars=200).split()), + tokens=len(fake.text(max_nb_chars=200).split()) * 2, + index_node_id=f"node_{i}", + index_node_hash=f"hash_{i}", + enabled=True, # Already enabled + status="completed", + created_by=document.created_by, + ) + db.session.add(segment) + segments.append(segment) + + db.session.commit() + + # Set up Redis cache key + indexing_cache_key = f"document_{document.id}_indexing" + redis_client.set(indexing_cache_key, "processing", ex=300) + + # Act: Execute the task + add_document_to_index_task(document.id) + + # Assert: Verify index processing occurred but with empty documents list + mock_external_service_dependencies["index_processor_factory"].assert_called_once_with(IndexType.PARAGRAPH_INDEX) + mock_external_service_dependencies["index_processor"].load.assert_called_once() + + # Verify the load method was called with empty documents list + call_args = mock_external_service_dependencies["index_processor"].load.call_args + assert call_args is not None + documents = call_args[0][1] # Second argument should be documents list + assert len(documents) == 0 # No segments to process + + # Verify redis cache was cleared + assert redis_client.exists(indexing_cache_key) == 0 + + def test_add_document_to_index_auto_disable_log_deletion( + self, db_session_with_containers, mock_external_service_dependencies + ): + """ + Test that auto disable logs are properly deleted during indexing. + + This test verifies: + - Auto disable log entries are deleted for the document + - Database state is properly managed + - Index processing continues normally + - Redis cache key deletion + """ + # Arrange: Create test data + dataset, document = self._create_test_dataset_and_document( + db_session_with_containers, mock_external_service_dependencies + ) + segments = self._create_test_segments(db_session_with_containers, document, dataset) + + # Create some auto disable log entries + fake = Faker() + auto_disable_logs = [] + for i in range(2): + log_entry = DatasetAutoDisableLog( + id=fake.uuid4(), + tenant_id=document.tenant_id, + dataset_id=dataset.id, + document_id=document.id, + ) + db.session.add(log_entry) + auto_disable_logs.append(log_entry) + + db.session.commit() + + # Set up Redis cache key + indexing_cache_key = f"document_{document.id}_indexing" + redis_client.set(indexing_cache_key, "processing", ex=300) + + # Verify logs exist before processing + existing_logs = ( + db.session.query(DatasetAutoDisableLog).where(DatasetAutoDisableLog.document_id == document.id).all() + ) + assert len(existing_logs) == 2 + + # Act: Execute the task + add_document_to_index_task(document.id) + + # Assert: Verify auto disable logs were deleted + remaining_logs = ( + db.session.query(DatasetAutoDisableLog).where(DatasetAutoDisableLog.document_id == document.id).all() + ) + assert len(remaining_logs) == 0 + + # Verify index processing occurred normally + mock_external_service_dependencies["index_processor_factory"].assert_called_once_with(IndexType.PARAGRAPH_INDEX) + mock_external_service_dependencies["index_processor"].load.assert_called_once() + + # Verify segments were enabled + for segment in segments: + db.session.refresh(segment) + assert segment.enabled is True + + # Verify redis cache was cleared + assert redis_client.exists(indexing_cache_key) == 0 + + def test_add_document_to_index_general_exception_handling( + self, db_session_with_containers, mock_external_service_dependencies + ): + """ + Test general exception handling during indexing process. + + This test verifies: + - Exceptions are properly caught and handled + - Document status is set to error + - Document is disabled + - Error information is recorded + - Redis cache is still cleared + - Database session is properly closed + """ + # Arrange: Create test data + dataset, document = self._create_test_dataset_and_document( + db_session_with_containers, mock_external_service_dependencies + ) + segments = self._create_test_segments(db_session_with_containers, document, dataset) + + # Set up Redis cache key + indexing_cache_key = f"document_{document.id}_indexing" + redis_client.set(indexing_cache_key, "processing", ex=300) + + # Mock the index processor to raise an exception + mock_external_service_dependencies["index_processor"].load.side_effect = Exception("Index processing failed") + + # Act: Execute the task + add_document_to_index_task(document.id) + + # Assert: Verify error handling + db.session.refresh(document) + assert document.enabled is False + assert document.indexing_status == "error" + assert document.error is not None + assert "Index processing failed" in document.error + assert document.disabled_at is not None + + # Verify segments were not enabled due to error + for segment in segments: + db.session.refresh(segment) + assert segment.enabled is False # Should remain disabled due to error + + # Verify redis cache was still cleared despite error + assert redis_client.exists(indexing_cache_key) == 0 + + def test_add_document_to_index_segment_filtering_edge_cases( + self, db_session_with_containers, mock_external_service_dependencies + ): + """ + Test segment filtering with various edge cases. + + This test verifies: + - Only segments with enabled=False and status="completed" are processed + - Segments are ordered by position correctly + - Mixed segment states are handled properly + - Redis cache key deletion + """ + # Arrange: Create test data + dataset, document = self._create_test_dataset_and_document( + db_session_with_containers, mock_external_service_dependencies + ) + + # Create segments with mixed states + fake = Faker() + segments = [] + + # Segment 1: Should be processed (enabled=False, status="completed") + segment1 = DocumentSegment( + id=fake.uuid4(), + tenant_id=document.tenant_id, + dataset_id=dataset.id, + document_id=document.id, + position=0, + content=fake.text(max_nb_chars=200), + word_count=len(fake.text(max_nb_chars=200).split()), + tokens=len(fake.text(max_nb_chars=200).split()) * 2, + index_node_id="node_0", + index_node_hash="hash_0", + enabled=False, + status="completed", + created_by=document.created_by, + ) + db.session.add(segment1) + segments.append(segment1) + + # Segment 2: Should NOT be processed (enabled=True, status="completed") + segment2 = DocumentSegment( + id=fake.uuid4(), + tenant_id=document.tenant_id, + dataset_id=dataset.id, + document_id=document.id, + position=1, + content=fake.text(max_nb_chars=200), + word_count=len(fake.text(max_nb_chars=200).split()), + tokens=len(fake.text(max_nb_chars=200).split()) * 2, + index_node_id="node_1", + index_node_hash="hash_1", + enabled=True, # Already enabled + status="completed", + created_by=document.created_by, + ) + db.session.add(segment2) + segments.append(segment2) + + # Segment 3: Should NOT be processed (enabled=False, status="processing") + segment3 = DocumentSegment( + id=fake.uuid4(), + tenant_id=document.tenant_id, + dataset_id=dataset.id, + document_id=document.id, + position=2, + content=fake.text(max_nb_chars=200), + word_count=len(fake.text(max_nb_chars=200).split()), + tokens=len(fake.text(max_nb_chars=200).split()) * 2, + index_node_id="node_2", + index_node_hash="hash_2", + enabled=False, + status="processing", # Not completed + created_by=document.created_by, + ) + db.session.add(segment3) + segments.append(segment3) + + # Segment 4: Should be processed (enabled=False, status="completed") + segment4 = DocumentSegment( + id=fake.uuid4(), + tenant_id=document.tenant_id, + dataset_id=dataset.id, + document_id=document.id, + position=3, + content=fake.text(max_nb_chars=200), + word_count=len(fake.text(max_nb_chars=200).split()), + tokens=len(fake.text(max_nb_chars=200).split()) * 2, + index_node_id="node_3", + index_node_hash="hash_3", + enabled=False, + status="completed", + created_by=document.created_by, + ) + db.session.add(segment4) + segments.append(segment4) + + db.session.commit() + + # Set up Redis cache key + indexing_cache_key = f"document_{document.id}_indexing" + redis_client.set(indexing_cache_key, "processing", ex=300) + + # Act: Execute the task + add_document_to_index_task(document.id) + + # Assert: Verify only eligible segments were processed + mock_external_service_dependencies["index_processor_factory"].assert_called_once_with(IndexType.PARAGRAPH_INDEX) + mock_external_service_dependencies["index_processor"].load.assert_called_once() + + # Verify the load method was called with correct parameters + call_args = mock_external_service_dependencies["index_processor"].load.call_args + assert call_args is not None + documents = call_args[0][1] # Second argument should be documents list + assert len(documents) == 2 # Only 2 segments should be processed + + # Verify correct segments were processed (by position order) + assert documents[0].metadata["doc_id"] == "node_0" # position 0 + assert documents[1].metadata["doc_id"] == "node_3" # position 3 + + # Verify database state changes + db.session.refresh(document) + db.session.refresh(segment1) + db.session.refresh(segment2) + db.session.refresh(segment3) + db.session.refresh(segment4) + + # All segments should be enabled because the task updates ALL segments for the document + assert segment1.enabled is True + assert segment2.enabled is True # Was already enabled, now updated to True + assert segment3.enabled is True # Was not processed but still updated to True + assert segment4.enabled is True + + # Verify redis cache was cleared + assert redis_client.exists(indexing_cache_key) == 0 + + def test_add_document_to_index_comprehensive_error_scenarios( + self, db_session_with_containers, mock_external_service_dependencies + ): + """ + Test comprehensive error scenarios and recovery. + + This test verifies: + - Multiple types of exceptions are handled properly + - Error state is consistently managed + - Resource cleanup occurs in all error cases + - Database session management is robust + - Redis cache key deletion in all scenarios + """ + # Arrange: Create test data + dataset, document = self._create_test_dataset_and_document( + db_session_with_containers, mock_external_service_dependencies + ) + segments = self._create_test_segments(db_session_with_containers, document, dataset) + + # Test different exception types + test_exceptions = [ + ("Database connection error", Exception("Database connection failed")), + ("Index processor error", RuntimeError("Index processor initialization failed")), + ("Memory error", MemoryError("Out of memory")), + ("Value error", ValueError("Invalid index type")), + ] + + for error_name, exception in test_exceptions: + # Reset mocks for each test + mock_external_service_dependencies["index_processor"].load.side_effect = exception + + # Reset document state + document.enabled = True + document.indexing_status = "completed" + document.error = None + document.disabled_at = None + db.session.commit() + + # Set up Redis cache key + indexing_cache_key = f"document_{document.id}_indexing" + redis_client.set(indexing_cache_key, "processing", ex=300) + + # Act: Execute the task + add_document_to_index_task(document.id) + + # Assert: Verify consistent error handling + db.session.refresh(document) + assert document.enabled is False, f"Document should be disabled for {error_name}" + assert document.indexing_status == "error", f"Document status should be error for {error_name}" + assert document.error is not None, f"Error should be recorded for {error_name}" + assert str(exception) in document.error, f"Error message should contain exception for {error_name}" + assert document.disabled_at is not None, f"Disabled timestamp should be set for {error_name}" + + # Verify segments remain disabled due to error + for segment in segments: + db.session.refresh(segment) + assert segment.enabled is False, f"Segments should remain disabled for {error_name}" + + # Verify redis cache was still cleared despite error + assert redis_client.exists(indexing_cache_key) == 0, f"Redis cache should be cleared for {error_name}" From 7ba1f0a04607f9a8201fc514dea4951c3487ec88 Mon Sep 17 00:00:00 2001 From: -LAN- Date: Fri, 5 Sep 2025 20:57:11 +0800 Subject: [PATCH 24/52] chore: improve typing Signed-off-by: -LAN- --- .../workflow/entities/graph_runtime_state.py | 2 +- api/core/workflow/entities/variable_pool.py | 8 +- .../graph/graph_runtime_state_protocol.py | 6 +- .../workflow/graph/read_only_state_wrapper.py | 15 +- api/core/workflow/node_events/base.py | 7 +- .../workflow/utils/condition/processor.py | 143 +++++++++++++----- 6 files changed, 129 insertions(+), 52 deletions(-) diff --git a/api/core/workflow/entities/graph_runtime_state.py b/api/core/workflow/entities/graph_runtime_state.py index 36662a065e..c06a62d1e7 100644 --- a/api/core/workflow/entities/graph_runtime_state.py +++ b/api/core/workflow/entities/graph_runtime_state.py @@ -25,7 +25,7 @@ class GraphRuntimeState(BaseModel): llm_usage: LLMUsage | None = None, outputs: dict[str, Any] | None = None, node_run_steps: int = 0, - **kwargs, + **kwargs: object, ): """Initialize the GraphRuntimeState with validation.""" super().__init__(**kwargs) diff --git a/api/core/workflow/entities/variable_pool.py b/api/core/workflow/entities/variable_pool.py index fb0794844e..db5cbeca03 100644 --- a/api/core/workflow/entities/variable_pool.py +++ b/api/core/workflow/entities/variable_pool.py @@ -14,7 +14,7 @@ from core.workflow.constants import CONVERSATION_VARIABLE_NODE_ID, ENVIRONMENT_V from core.workflow.system_variable import SystemVariable from factories import variable_factory -VariableValue = Union[str, int, float, dict, list, File] +VariableValue = Union[str, int, float, dict[str, object], list[object], File] VARIABLE_PATTERN = re.compile(r"\{\{#([a-zA-Z0-9_]{1,50}(?:\.[a-zA-Z_][a-zA-Z0-9_]{0,29}){1,10})#\}\}") @@ -40,11 +40,11 @@ class VariablePool(BaseModel): ) environment_variables: Sequence[VariableUnion] = Field( description="Environment variables.", - default_factory=list, + default_factory=list[VariableUnion], ) conversation_variables: Sequence[VariableUnion] = Field( description="Conversation variables.", - default_factory=list, + default_factory=list[VariableUnion], ) def model_post_init(self, context: Any, /) -> None: @@ -191,7 +191,7 @@ class VariablePool(BaseModel): def convert_template(self, template: str, /): parts = VARIABLE_PATTERN.split(template) - segments = [] + segments: list[Segment] = [] for part in filter(lambda x: x, parts): if "." in part and (variable := self.get(part.split("."))): segments.append(variable) diff --git a/api/core/workflow/graph/graph_runtime_state_protocol.py b/api/core/workflow/graph/graph_runtime_state_protocol.py index a5c8db333a..d7961405ca 100644 --- a/api/core/workflow/graph/graph_runtime_state_protocol.py +++ b/api/core/workflow/graph/graph_runtime_state_protocol.py @@ -1,16 +1,18 @@ +from collections.abc import Mapping from typing import Any, Protocol from core.model_runtime.entities.llm_entities import LLMUsage +from core.variables.segments import Segment class ReadOnlyVariablePool(Protocol): """Read-only interface for VariablePool.""" - def get(self, node_id: str, variable_key: str) -> Any: + def get(self, node_id: str, variable_key: str) -> Segment | None: """Get a variable value (read-only).""" ... - def get_all_by_node(self, node_id: str) -> dict[str, Any]: + def get_all_by_node(self, node_id: str) -> Mapping[str, object]: """Get all variables for a node (read-only).""" ... diff --git a/api/core/workflow/graph/read_only_state_wrapper.py b/api/core/workflow/graph/read_only_state_wrapper.py index 3562106a4c..255bb5adee 100644 --- a/api/core/workflow/graph/read_only_state_wrapper.py +++ b/api/core/workflow/graph/read_only_state_wrapper.py @@ -1,7 +1,9 @@ +from collections.abc import Mapping from copy import deepcopy from typing import Any from core.model_runtime.entities.llm_entities import LLMUsage +from core.variables.segments import Segment from core.workflow.entities.graph_runtime_state import GraphRuntimeState from core.workflow.entities.variable_pool import VariablePool @@ -12,19 +14,18 @@ class ReadOnlyVariablePoolWrapper: def __init__(self, variable_pool: VariablePool): self._variable_pool = variable_pool - def get(self, node_id: str, variable_key: str) -> Any: + def get(self, node_id: str, variable_key: str) -> Segment | None: """Get a variable value (returns a defensive copy).""" - value = self._variable_pool.get(node_id, variable_key) + value = self._variable_pool.get([node_id, variable_key]) return deepcopy(value) if value is not None else None - def get_all_by_node(self, node_id: str) -> dict[str, Any]: + def get_all_by_node(self, node_id: str) -> Mapping[str, object]: """Get all variables for a node (returns defensive copies).""" - variables = {} + variables: dict[str, object] = {} if node_id in self._variable_pool.variable_dictionary: for key, var in self._variable_pool.variable_dictionary[node_id].items(): - # FIXME(-LAN-): Handle the actual Variable object structure - value = var.value if hasattr(var, "value") else var - variables[key] = deepcopy(value) + # Variables have a value property that contains the actual data + variables[key] = deepcopy(var.value) return variables diff --git a/api/core/workflow/node_events/base.py b/api/core/workflow/node_events/base.py index 3e9e239d30..7fec47e21f 100644 --- a/api/core/workflow/node_events/base.py +++ b/api/core/workflow/node_events/base.py @@ -13,6 +13,11 @@ class NodeEventBase(BaseModel): pass +def _default_metadata(): + v: Mapping[WorkflowNodeExecutionMetadataKey, Any] = {} + return v + + class NodeRunResult(BaseModel): """ Node Run Result. @@ -23,7 +28,7 @@ class NodeRunResult(BaseModel): inputs: Mapping[str, Any] = Field(default_factory=dict) process_data: Mapping[str, Any] = Field(default_factory=dict) outputs: Mapping[str, Any] = Field(default_factory=dict) - metadata: Mapping[WorkflowNodeExecutionMetadataKey, Any] = Field(default_factory=dict) + metadata: Mapping[WorkflowNodeExecutionMetadataKey, Any] = Field(default_factory=_default_metadata) llm_usage: LLMUsage = Field(default_factory=LLMUsage.empty_usage) edge_source_handle: str = "source" # source handle id of node with multiple branches diff --git a/api/core/workflow/utils/condition/processor.py b/api/core/workflow/utils/condition/processor.py index 8689aa987b..f4bbe9c3c3 100644 --- a/api/core/workflow/utils/condition/processor.py +++ b/api/core/workflow/utils/condition/processor.py @@ -1,6 +1,6 @@ import json from collections.abc import Mapping, Sequence -from typing import Any, Literal, NamedTuple, Union +from typing import Literal, NamedTuple from core.file import FileAttribute, file_manager from core.variables import ArrayFileSegment @@ -10,7 +10,7 @@ from core.workflow.entities import VariablePool from .entities import Condition, SubCondition, SupportedComparisonOperator -def _convert_to_bool(value: Any) -> bool: +def _convert_to_bool(value: object) -> bool: if isinstance(value, int): return bool(value) @@ -23,7 +23,7 @@ def _convert_to_bool(value: Any) -> bool: class ConditionCheckResult(NamedTuple): - inputs: Sequence[Mapping[str, Any]] + inputs: Sequence[Mapping[str, object]] group_results: Sequence[bool] final_result: bool @@ -36,7 +36,7 @@ class ConditionProcessor: conditions: Sequence[Condition], operator: Literal["and", "or"], ) -> ConditionCheckResult: - input_conditions: list[Mapping[str, Any]] = [] + input_conditions: list[Mapping[str, object]] = [] group_results: list[bool] = [] for condition in conditions: @@ -103,8 +103,8 @@ class ConditionProcessor: def _evaluate_condition( *, operator: SupportedComparisonOperator, - value: Any, - expected: Union[str, Sequence[str], bool | Sequence[bool], None], + value: object, + expected: str | Sequence[str] | bool | Sequence[bool] | None, ) -> bool: match operator: case "contains": @@ -144,7 +144,17 @@ def _evaluate_condition( case "not in": return _assert_not_in(value=value, expected=expected) case "all of" if isinstance(expected, list): - return _assert_all_of(value=value, expected=expected) + # Type narrowing: at this point expected is a list, could be list[str] or list[bool] + if all(isinstance(item, str) for item in expected): + # Create a new typed list to satisfy type checker + str_list: list[str] = [item for item in expected if isinstance(item, str)] + return _assert_all_of(value=value, expected=str_list) + elif all(isinstance(item, bool) for item in expected): + # Create a new typed list to satisfy type checker + bool_list: list[bool] = [item for item in expected if isinstance(item, bool)] + return _assert_all_of_bool(value=value, expected=bool_list) + else: + raise ValueError("all of operator expects homogeneous list of strings or booleans") case "exists": return _assert_exists(value=value) case "not exists": @@ -153,55 +163,73 @@ def _evaluate_condition( raise ValueError(f"Unsupported operator: {operator}") -def _assert_contains(*, value: Any, expected: Any) -> bool: +def _assert_contains(*, value: object, expected: object) -> bool: if not value: return False if not isinstance(value, (str, list)): raise ValueError("Invalid actual value type: string or array") - if expected not in value: - return False + # Type checking ensures value is str or list at this point + if isinstance(value, str): + if not isinstance(expected, str): + expected = str(expected) + if expected not in value: + return False + else: # value is list + if expected not in value: + return False return True -def _assert_not_contains(*, value: Any, expected: Any) -> bool: +def _assert_not_contains(*, value: object, expected: object) -> bool: if not value: return True if not isinstance(value, (str, list)): raise ValueError("Invalid actual value type: string or array") - if expected in value: - return False + # Type checking ensures value is str or list at this point + if isinstance(value, str): + if not isinstance(expected, str): + expected = str(expected) + if expected in value: + return False + else: # value is list + if expected in value: + return False return True -def _assert_start_with(*, value: Any, expected: Any) -> bool: +def _assert_start_with(*, value: object, expected: object) -> bool: if not value: return False if not isinstance(value, str): raise ValueError("Invalid actual value type: string") + if not isinstance(expected, str): + raise ValueError("Expected value must be a string for startswith") if not value.startswith(expected): return False return True -def _assert_end_with(*, value: Any, expected: Any) -> bool: +def _assert_end_with(*, value: object, expected: object) -> bool: if not value: return False if not isinstance(value, str): raise ValueError("Invalid actual value type: string") + if not isinstance(expected, str): + raise ValueError("Expected value must be a string for endswith") if not value.endswith(expected): return False return True -def _assert_is(*, value: Any, expected: Any) -> bool: +def _assert_is(*, value: object, expected: object) -> bool: if value is None: return False @@ -213,7 +241,7 @@ def _assert_is(*, value: Any, expected: Any) -> bool: return True -def _assert_is_not(*, value: Any, expected: Any) -> bool: +def _assert_is_not(*, value: object, expected: object) -> bool: if value is None: return False @@ -225,19 +253,19 @@ def _assert_is_not(*, value: Any, expected: Any) -> bool: return True -def _assert_empty(*, value: Any) -> bool: +def _assert_empty(*, value: object) -> bool: if not value: return True return False -def _assert_not_empty(*, value: Any) -> bool: +def _assert_not_empty(*, value: object) -> bool: if value: return True return False -def _assert_equal(*, value: Any, expected: Any) -> bool: +def _assert_equal(*, value: object, expected: object) -> bool: if value is None: return False @@ -246,10 +274,16 @@ def _assert_equal(*, value: Any, expected: Any) -> bool: # Handle boolean comparison if isinstance(value, bool): + if not isinstance(expected, (bool, int, str)): + raise ValueError(f"Cannot convert {type(expected)} to bool") expected = bool(expected) elif isinstance(value, int): + if not isinstance(expected, (int, float, str)): + raise ValueError(f"Cannot convert {type(expected)} to int") expected = int(expected) else: + if not isinstance(expected, (int, float, str)): + raise ValueError(f"Cannot convert {type(expected)} to float") expected = float(expected) if value != expected: @@ -257,7 +291,7 @@ def _assert_equal(*, value: Any, expected: Any) -> bool: return True -def _assert_not_equal(*, value: Any, expected: Any) -> bool: +def _assert_not_equal(*, value: object, expected: object) -> bool: if value is None: return False @@ -266,10 +300,16 @@ def _assert_not_equal(*, value: Any, expected: Any) -> bool: # Handle boolean comparison if isinstance(value, bool): + if not isinstance(expected, (bool, int, str)): + raise ValueError(f"Cannot convert {type(expected)} to bool") expected = bool(expected) elif isinstance(value, int): + if not isinstance(expected, (int, float, str)): + raise ValueError(f"Cannot convert {type(expected)} to int") expected = int(expected) else: + if not isinstance(expected, (int, float, str)): + raise ValueError(f"Cannot convert {type(expected)} to float") expected = float(expected) if value == expected: @@ -277,7 +317,7 @@ def _assert_not_equal(*, value: Any, expected: Any) -> bool: return True -def _assert_greater_than(*, value: Any, expected: Any) -> bool: +def _assert_greater_than(*, value: object, expected: object) -> bool: if value is None: return False @@ -285,8 +325,12 @@ def _assert_greater_than(*, value: Any, expected: Any) -> bool: raise ValueError("Invalid actual value type: number") if isinstance(value, int): + if not isinstance(expected, (int, float, str)): + raise ValueError(f"Cannot convert {type(expected)} to int") expected = int(expected) else: + if not isinstance(expected, (int, float, str)): + raise ValueError(f"Cannot convert {type(expected)} to float") expected = float(expected) if value <= expected: @@ -294,7 +338,7 @@ def _assert_greater_than(*, value: Any, expected: Any) -> bool: return True -def _assert_less_than(*, value: Any, expected: Any) -> bool: +def _assert_less_than(*, value: object, expected: object) -> bool: if value is None: return False @@ -302,8 +346,12 @@ def _assert_less_than(*, value: Any, expected: Any) -> bool: raise ValueError("Invalid actual value type: number") if isinstance(value, int): + if not isinstance(expected, (int, float, str)): + raise ValueError(f"Cannot convert {type(expected)} to int") expected = int(expected) else: + if not isinstance(expected, (int, float, str)): + raise ValueError(f"Cannot convert {type(expected)} to float") expected = float(expected) if value >= expected: @@ -311,7 +359,7 @@ def _assert_less_than(*, value: Any, expected: Any) -> bool: return True -def _assert_greater_than_or_equal(*, value: Any, expected: Any) -> bool: +def _assert_greater_than_or_equal(*, value: object, expected: object) -> bool: if value is None: return False @@ -319,8 +367,12 @@ def _assert_greater_than_or_equal(*, value: Any, expected: Any) -> bool: raise ValueError("Invalid actual value type: number") if isinstance(value, int): + if not isinstance(expected, (int, float, str)): + raise ValueError(f"Cannot convert {type(expected)} to int") expected = int(expected) else: + if not isinstance(expected, (int, float, str)): + raise ValueError(f"Cannot convert {type(expected)} to float") expected = float(expected) if value < expected: @@ -328,7 +380,7 @@ def _assert_greater_than_or_equal(*, value: Any, expected: Any) -> bool: return True -def _assert_less_than_or_equal(*, value: Any, expected: Any) -> bool: +def _assert_less_than_or_equal(*, value: object, expected: object) -> bool: if value is None: return False @@ -336,8 +388,12 @@ def _assert_less_than_or_equal(*, value: Any, expected: Any) -> bool: raise ValueError("Invalid actual value type: number") if isinstance(value, int): + if not isinstance(expected, (int, float, str)): + raise ValueError(f"Cannot convert {type(expected)} to int") expected = int(expected) else: + if not isinstance(expected, (int, float, str)): + raise ValueError(f"Cannot convert {type(expected)} to float") expected = float(expected) if value > expected: @@ -345,19 +401,19 @@ def _assert_less_than_or_equal(*, value: Any, expected: Any) -> bool: return True -def _assert_null(*, value: Any) -> bool: +def _assert_null(*, value: object) -> bool: if value is None: return True return False -def _assert_not_null(*, value: Any) -> bool: +def _assert_not_null(*, value: object) -> bool: if value is not None: return True return False -def _assert_in(*, value: Any, expected: Any) -> bool: +def _assert_in(*, value: object, expected: object) -> bool: if not value: return False @@ -369,7 +425,7 @@ def _assert_in(*, value: Any, expected: Any) -> bool: return True -def _assert_not_in(*, value: Any, expected: Any) -> bool: +def _assert_not_in(*, value: object, expected: object) -> bool: if not value: return True @@ -381,20 +437,33 @@ def _assert_not_in(*, value: Any, expected: Any) -> bool: return True -def _assert_all_of(*, value: Any, expected: Sequence[str]) -> bool: +def _assert_all_of(*, value: object, expected: Sequence[str]) -> bool: if not value: return False - if not all(item in value for item in expected): + # Ensure value is a container that supports 'in' operator + if not isinstance(value, (list, tuple, set, str)): return False - return True + + return all(item in value for item in expected) -def _assert_exists(*, value: Any) -> bool: +def _assert_all_of_bool(*, value: object, expected: Sequence[bool]) -> bool: + if not value: + return False + + # Ensure value is a container that supports 'in' operator + if not isinstance(value, (list, tuple, set)): + return False + + return all(item in value for item in expected) + + +def _assert_exists(*, value: object) -> bool: return value is not None -def _assert_not_exists(*, value: Any) -> bool: +def _assert_not_exists(*, value: object) -> bool: return value is None @@ -404,7 +473,7 @@ def _process_sub_conditions( operator: Literal["and", "or"], ) -> bool: files = variable.value - group_results = [] + group_results: list[bool] = [] for condition in sub_conditions: key = FileAttribute(condition.key) values = [file_manager.get_attr(file=file, attr=key) for file in files] @@ -415,14 +484,14 @@ def _process_sub_conditions( if expected_value and not expected_value.startswith("."): expected_value = "." + expected_value - normalized_values = [] + normalized_values: list[object] = [] for value in values: if value and isinstance(value, str): if not value.startswith("."): value = "." + value normalized_values.append(value) values = normalized_values - sub_group_results = [ + sub_group_results: list[bool] = [ _evaluate_condition( value=value, operator=condition.comparison_operator, From d9aa0ec046adaafc8ff0ce80b1111f5d917f62cd Mon Sep 17 00:00:00 2001 From: -LAN- Date: Fri, 5 Sep 2025 21:17:18 +0800 Subject: [PATCH 25/52] fix: resolve mypy type errors in http_request and list_operator nodes - Fix str | bytes union type handling in http_request executor - Add type guard for boolean filter value in list_operator node --- api/core/workflow/nodes/http_request/executor.py | 5 ++++- api/core/workflow/nodes/list_operator/node.py | 2 ++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/api/core/workflow/nodes/http_request/executor.py b/api/core/workflow/nodes/http_request/executor.py index a0319cfe5f..c47ffb5ab0 100644 --- a/api/core/workflow/nodes/http_request/executor.py +++ b/api/core/workflow/nodes/http_request/executor.py @@ -421,7 +421,10 @@ class Executor: body_string += f"--{boundary}--\r\n" elif self.node_data.body: if self.content: - body_string = self.content.decode("utf-8", errors="replace") + if isinstance(self.content, bytes): + body_string = self.content.decode("utf-8", errors="replace") + else: + body_string = self.content elif self.data and self.node_data.body.type == "x-www-form-urlencoded": body_string = urlencode(self.data) elif self.data and self.node_data.body.type == "form-data": diff --git a/api/core/workflow/nodes/list_operator/node.py b/api/core/workflow/nodes/list_operator/node.py index 96220b635b..db8de2fa05 100644 --- a/api/core/workflow/nodes/list_operator/node.py +++ b/api/core/workflow/nodes/list_operator/node.py @@ -171,6 +171,8 @@ class ListOperatorNode(Node): result = list(filter(filter_func, variable.value)) variable = variable.model_copy(update={"value": result}) else: + if not isinstance(condition.value, bool): + raise ValueError(f"Boolean filter expects a boolean value, got {type(condition.value)}") filter_func = _get_boolean_filter_func(condition=condition.comparison_operator, value=condition.value) result = list(filter(filter_func, variable.value)) variable = variable.model_copy(update={"value": result}) From 2b0695bddee8ceb5627ff5591356de9554b61197 Mon Sep 17 00:00:00 2001 From: Asuka Minato Date: Sat, 6 Sep 2025 04:20:13 +0900 Subject: [PATCH 26/52] add more dataclass (#25039) Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com> Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- api/core/tools/tool_file_manager.py | 2 +- api/models/tools.py | 16 +++++++-------- .../factories/test_storage_key_loader.py | 20 +++++++++---------- .../factories/test_storage_key_loader.py | 19 +++++++++--------- .../workflow/nodes/llm/test_file_saver.py | 10 +++++----- 5 files changed, 34 insertions(+), 33 deletions(-) diff --git a/api/core/tools/tool_file_manager.py b/api/core/tools/tool_file_manager.py index ff054041cf..ad650196ce 100644 --- a/api/core/tools/tool_file_manager.py +++ b/api/core/tools/tool_file_manager.py @@ -98,6 +98,7 @@ class ToolFileManager: mimetype=mimetype, name=present_filename, size=len(file_binary), + original_url=None, ) session.add(tool_file) @@ -131,7 +132,6 @@ class ToolFileManager: filename = f"{unique_name}{extension}" filepath = f"tools/{tenant_id}/{filename}" storage.save(filepath, blob) - with Session(self._engine, expire_on_commit=False) as session: tool_file = ToolFile( user_id=user_id, diff --git a/api/models/tools.py b/api/models/tools.py index 08219ebd2f..9c460e9bf1 100644 --- a/api/models/tools.py +++ b/api/models/tools.py @@ -1,6 +1,6 @@ import json from datetime import datetime -from typing import Any, cast +from typing import Any, Optional, cast from urllib.parse import urlparse import sqlalchemy as sa @@ -22,15 +22,15 @@ from .types import StringUUID # system level tool oauth client params (client_id, client_secret, etc.) -class ToolOAuthSystemClient(Base): +class ToolOAuthSystemClient(TypeBase): __tablename__ = "tool_oauth_system_clients" __table_args__ = ( sa.PrimaryKeyConstraint("id", name="tool_oauth_system_client_pkey"), sa.UniqueConstraint("plugin_id", "provider", name="tool_oauth_system_client_plugin_id_provider_idx"), ) - id: Mapped[str] = mapped_column(StringUUID, server_default=sa.text("uuid_generate_v4()")) - plugin_id = mapped_column(String(512), nullable=False) + id: Mapped[str] = mapped_column(StringUUID, server_default=sa.text("uuid_generate_v4()"), init=False) + plugin_id: Mapped[str] = mapped_column(String(512), nullable=False) provider: Mapped[str] = mapped_column(String(255), nullable=False) # oauth params of the tool provider encrypted_oauth_params: Mapped[str] = mapped_column(sa.Text, nullable=False) @@ -412,7 +412,7 @@ class ToolConversationVariables(Base): return json.loads(self.variables_str) -class ToolFile(Base): +class ToolFile(TypeBase): """This table stores file metadata generated in workflows, not only files created by agent. """ @@ -423,19 +423,19 @@ class ToolFile(Base): sa.Index("tool_file_conversation_id_idx", "conversation_id"), ) - id: Mapped[str] = mapped_column(StringUUID, server_default=sa.text("uuid_generate_v4()")) + id: Mapped[str] = mapped_column(StringUUID, server_default=sa.text("uuid_generate_v4()"), init=False) # conversation user id user_id: Mapped[str] = mapped_column(StringUUID) # tenant id tenant_id: Mapped[str] = mapped_column(StringUUID) # conversation id - conversation_id: Mapped[str] = mapped_column(StringUUID, nullable=True) + conversation_id: Mapped[Optional[str]] = mapped_column(StringUUID, nullable=True) # file key file_key: Mapped[str] = mapped_column(String(255), nullable=False) # mime type mimetype: Mapped[str] = mapped_column(String(255), nullable=False) # original url - original_url: Mapped[str] = mapped_column(String(2048), nullable=True) + original_url: Mapped[Optional[str]] = mapped_column(String(2048), nullable=True, default=None) # name name: Mapped[str] = mapped_column(default="") # size diff --git a/api/tests/integration_tests/factories/test_storage_key_loader.py b/api/tests/integration_tests/factories/test_storage_key_loader.py index fecb3f6d95..0fb7076c85 100644 --- a/api/tests/integration_tests/factories/test_storage_key_loader.py +++ b/api/tests/integration_tests/factories/test_storage_key_loader.py @@ -84,17 +84,17 @@ class TestStorageKeyLoader(unittest.TestCase): if tenant_id is None: tenant_id = self.tenant_id - tool_file = ToolFile() + tool_file = ToolFile( + user_id=self.user_id, + tenant_id=tenant_id, + conversation_id=self.conversation_id, + file_key=file_key, + mimetype="text/plain", + original_url="http://example.com/file.txt", + name="test_tool_file.txt", + size=2048, + ) tool_file.id = file_id - tool_file.user_id = self.user_id - tool_file.tenant_id = tenant_id - tool_file.conversation_id = self.conversation_id - tool_file.file_key = file_key - tool_file.mimetype = "text/plain" - tool_file.original_url = "http://example.com/file.txt" - tool_file.name = "test_tool_file.txt" - tool_file.size = 2048 - self.session.add(tool_file) self.session.flush() self.test_tool_files.append(tool_file) diff --git a/api/tests/test_containers_integration_tests/factories/test_storage_key_loader.py b/api/tests/test_containers_integration_tests/factories/test_storage_key_loader.py index d6e14f3f54..b6fe8b73a2 100644 --- a/api/tests/test_containers_integration_tests/factories/test_storage_key_loader.py +++ b/api/tests/test_containers_integration_tests/factories/test_storage_key_loader.py @@ -84,16 +84,17 @@ class TestStorageKeyLoader(unittest.TestCase): if tenant_id is None: tenant_id = self.tenant_id - tool_file = ToolFile() + tool_file = ToolFile( + user_id=self.user_id, + tenant_id=tenant_id, + conversation_id=self.conversation_id, + file_key=file_key, + mimetype="text/plain", + original_url="http://example.com/file.txt", + name="test_tool_file.txt", + size=2048, + ) tool_file.id = file_id - tool_file.user_id = self.user_id - tool_file.tenant_id = tenant_id - tool_file.conversation_id = self.conversation_id - tool_file.file_key = file_key - tool_file.mimetype = "text/plain" - tool_file.original_url = "http://example.com/file.txt" - tool_file.name = "test_tool_file.txt" - tool_file.size = 2048 self.session.add(tool_file) self.session.flush() diff --git a/api/tests/unit_tests/core/workflow/nodes/llm/test_file_saver.py b/api/tests/unit_tests/core/workflow/nodes/llm/test_file_saver.py index 7c722660bc..e8f257bf2f 100644 --- a/api/tests/unit_tests/core/workflow/nodes/llm/test_file_saver.py +++ b/api/tests/unit_tests/core/workflow/nodes/llm/test_file_saver.py @@ -26,14 +26,13 @@ def _gen_id(): class TestFileSaverImpl: - def test_save_binary_string(self, monkeypatch): + def test_save_binary_string(self, monkeypatch: pytest.MonkeyPatch): user_id = _gen_id() tenant_id = _gen_id() file_type = FileType.IMAGE mime_type = "image/png" mock_signed_url = "https://example.com/image.png" mock_tool_file = ToolFile( - id=_gen_id(), user_id=user_id, tenant_id=tenant_id, conversation_id=None, @@ -43,6 +42,7 @@ class TestFileSaverImpl: name=f"{_gen_id()}.png", size=len(_PNG_DATA), ) + mock_tool_file.id = _gen_id() mocked_tool_file_manager = mock.MagicMock(spec=ToolFileManager) mocked_engine = mock.MagicMock(spec=Engine) @@ -80,7 +80,7 @@ class TestFileSaverImpl: ) mocked_sign_file.assert_called_once_with(mock_tool_file.id, ".png") - def test_save_remote_url_request_failed(self, monkeypatch): + def test_save_remote_url_request_failed(self, monkeypatch: pytest.MonkeyPatch): _TEST_URL = "https://example.com/image.png" mock_request = httpx.Request("GET", _TEST_URL) mock_response = httpx.Response( @@ -99,7 +99,7 @@ class TestFileSaverImpl: mock_get.assert_called_once_with(_TEST_URL) assert exc.value.response.status_code == 401 - def test_save_remote_url_success(self, monkeypatch): + def test_save_remote_url_success(self, monkeypatch: pytest.MonkeyPatch): _TEST_URL = "https://example.com/image.png" mime_type = "image/png" user_id = _gen_id() @@ -115,7 +115,6 @@ class TestFileSaverImpl: file_saver = FileSaverImpl(user_id=user_id, tenant_id=tenant_id) mock_tool_file = ToolFile( - id=_gen_id(), user_id=user_id, tenant_id=tenant_id, conversation_id=None, @@ -125,6 +124,7 @@ class TestFileSaverImpl: name=f"{_gen_id()}.png", size=len(_PNG_DATA), ) + mock_tool_file.id = _gen_id() mock_get = mock.MagicMock(spec=ssrf_proxy.get, return_value=mock_response) monkeypatch.setattr(ssrf_proxy, "get", mock_get) mock_save_binary_string = mock.MagicMock(spec=file_saver.save_binary_string, return_value=mock_tool_file) From a78339a040d5074333c0187bca7c724fb8bb95e4 Mon Sep 17 00:00:00 2001 From: Asuka Minato Date: Sat, 6 Sep 2025 04:32:23 +0900 Subject: [PATCH 27/52] remove bare list, dict, Sequence, None, Any (#25058) Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com> Co-authored-by: -LAN- --- api/configs/remote_settings_sources/base.py | 2 +- .../remote_settings_sources/nacos/__init__.py | 2 +- api/controllers/console/app/generator.py | 2 +- .../console/app/workflow_draft_variable.py | 6 +-- api/controllers/mcp/mcp.py | 2 +- api/core/agent/base_agent_runner.py | 2 +- api/core/agent/cot_agent_runner.py | 2 +- api/core/agent/entities.py | 2 +- .../easy_ui_based_app/dataset/manager.py | 2 +- .../easy_ui_based_app/model_config/manager.py | 2 +- .../prompt_template/manager.py | 2 +- .../apps/advanced_chat/app_config_manager.py | 2 +- .../app/apps/advanced_chat/app_generator.py | 2 +- api/core/app/apps/advanced_chat/app_runner.py | 6 +-- .../advanced_chat/generate_task_pipeline.py | 6 +-- .../app/apps/agent_chat/app_config_manager.py | 2 +- api/core/app/apps/agent_chat/app_generator.py | 2 +- api/core/app/apps/agent_chat/app_runner.py | 2 +- .../agent_chat/generate_response_converter.py | 4 +- .../base_app_generate_response_converter.py | 2 +- api/core/app/apps/base_app_generator.py | 2 +- api/core/app/apps/base_app_queue_manager.py | 12 ++--- api/core/app/apps/base_app_runner.py | 10 ++-- api/core/app/apps/chat/app_config_manager.py | 2 +- api/core/app/apps/chat/app_generator.py | 2 +- api/core/app/apps/chat/app_runner.py | 2 +- .../apps/chat/generate_response_converter.py | 4 +- .../common/workflow_response_converter.py | 2 +- .../app/apps/completion/app_config_manager.py | 2 +- api/core/app/apps/completion/app_generator.py | 2 +- api/core/app/apps/completion/app_runner.py | 2 +- .../completion/generate_response_converter.py | 4 +- .../apps/message_based_app_queue_manager.py | 4 +- .../app/apps/workflow/app_config_manager.py | 2 +- api/core/app/apps/workflow/app_generator.py | 2 +- .../app/apps/workflow/app_queue_manager.py | 4 +- api/core/app/apps/workflow/app_runner.py | 4 +- .../workflow/generate_response_converter.py | 4 +- .../apps/workflow/generate_task_pipeline.py | 6 +-- api/core/app/apps/workflow_app_runner.py | 6 +-- .../based_generate_task_pipeline.py | 2 +- .../easy_ui_based_generate_task_pipeline.py | 6 +-- .../task_pipeline/message_cycle_manager.py | 4 +- .../agent_tool_callback_handler.py | 14 +++--- .../index_tool_callback_handler.py | 6 +-- api/core/entities/model_entities.py | 4 +- api/core/entities/provider_configuration.py | 34 +++++++------- api/core/errors/error.py | 2 +- .../api_based_extension_requestor.py | 4 +- api/core/extension/extensible.py | 2 +- api/core/external_data_tool/api/api.py | 2 +- api/core/external_data_tool/base.py | 4 +- api/core/external_data_tool/factory.py | 4 +- api/core/file/tool_file_parser.py | 2 +- .../code_executor/code_node_provider.py | 2 +- .../jinja2/jinja2_transformer.py | 2 +- .../python3/python3_code_provider.py | 2 +- api/core/helper/model_provider_cache.py | 4 +- api/core/helper/provider_cache.py | 8 ++-- api/core/helper/tool_parameter_cache.py | 4 +- api/core/helper/trace_id_helper.py | 2 +- api/core/hosting_configuration.py | 4 +- api/core/indexing_runner.py | 6 +-- api/core/llm_generator/llm_generator.py | 14 +++--- .../output_parser/rule_config_generator.py | 4 +- .../output_parser/structured_output.py | 10 ++-- .../suggested_questions_after_answer.py | 3 +- api/core/mcp/auth/auth_provider.py | 6 +-- api/core/mcp/client/sse_client.py | 16 +++---- api/core/mcp/client/streamable_client.py | 24 +++++----- api/core/mcp/session/base_session.py | 30 ++++++------ api/core/mcp/session/client_session.py | 22 ++++----- api/core/memory/token_buffer_memory.py | 2 +- api/core/model_manager.py | 14 +++--- .../model_runtime/callbacks/base_callback.py | 8 ++-- .../callbacks/logging_callback.py | 6 +-- api/core/model_runtime/errors/invoke.py | 2 +- .../model_providers/__base/ai_model.py | 2 +- .../__base/large_language_model.py | 8 ++-- .../__base/tokenizers/gpt2_tokenizer.py | 2 +- .../model_providers/__base/tts_model.py | 2 +- .../model_providers/model_provider_factory.py | 8 ++-- .../schema_validators/common_validator.py | 2 +- .../model_credential_schema_validator.py | 2 +- .../provider_credential_schema_validator.py | 2 +- api/core/model_runtime/utils/encoders.py | 4 +- api/core/moderation/api/api.py | 4 +- api/core/moderation/base.py | 6 +-- api/core/moderation/factory.py | 4 +- api/core/moderation/keywords/keywords.py | 2 +- .../openai_moderation/openai_moderation.py | 2 +- api/core/moderation/output_moderation.py | 2 +- .../plugin/backwards_invocation/encrypt.py | 2 +- api/core/plugin/backwards_invocation/node.py | 4 +- api/core/plugin/entities/plugin.py | 8 ++-- api/core/plugin/impl/agent.py | 4 +- api/core/plugin/impl/exc.py | 2 +- api/core/plugin/impl/model.py | 2 +- api/core/plugin/impl/tool.py | 4 +- api/core/plugin/utils/chunk_merger.py | 2 +- api/core/prompt/advanced_prompt_transform.py | 2 +- api/core/prompt/simple_prompt_transform.py | 4 +- api/core/prompt/utils/prompt_message_util.py | 2 +- .../prompt/utils/prompt_template_parser.py | 2 +- api/core/provider_manager.py | 2 +- .../rag/datasource/keyword/jieba/jieba.py | 10 ++-- .../rag/datasource/keyword/keyword_base.py | 4 +- .../rag/datasource/keyword/keyword_factory.py | 4 +- .../vdb/analyticdb/analyticdb_vector.py | 6 +-- .../analyticdb/analyticdb_vector_openapi.py | 14 +++--- .../vdb/analyticdb/analyticdb_vector_sql.py | 12 ++--- .../rag/datasource/vdb/baidu/baidu_vector.py | 12 ++--- .../datasource/vdb/chroma/chroma_vector.py | 2 +- .../vdb/clickzetta/clickzetta_vector.py | 26 +++++------ .../vdb/couchbase/couchbase_vector.py | 6 +-- .../vdb/elasticsearch/elasticsearch_vector.py | 8 ++-- .../vdb/huawei/huawei_cloud_vector.py | 8 ++-- .../datasource/vdb/lindorm/lindorm_vector.py | 12 ++--- .../vdb/matrixone/matrixone_vector.py | 8 ++-- .../datasource/vdb/milvus/milvus_vector.py | 8 ++-- .../datasource/vdb/myscale/myscale_vector.py | 6 +-- .../vdb/oceanbase/oceanbase_vector.py | 10 ++-- .../rag/datasource/vdb/opengauss/opengauss.py | 8 ++-- .../vdb/opensearch/opensearch_vector.py | 6 +-- .../rag/datasource/vdb/oracle/oraclevector.py | 8 ++-- .../datasource/vdb/pgvecto_rs/pgvecto_rs.py | 6 +-- .../rag/datasource/vdb/pgvector/pgvector.py | 8 ++-- .../vdb/pyvastbase/vastbase_vector.py | 8 ++-- .../datasource/vdb/qdrant/qdrant_vector.py | 4 +- .../rag/datasource/vdb/relyt/relyt_vector.py | 8 ++-- .../vdb/tablestore/tablestore_vector.py | 18 ++++---- .../datasource/vdb/tencent/tencent_vector.py | 10 ++-- .../tidb_on_qdrant/tidb_on_qdrant_vector.py | 4 +- .../datasource/vdb/tidb_vector/tidb_vector.py | 8 ++-- .../datasource/vdb/upstash/upstash_vector.py | 10 ++-- api/core/rag/datasource/vdb/vector_base.py | 6 +-- api/core/rag/datasource/vdb/vector_factory.py | 8 ++-- .../vdb/vikingdb/vikingdb_vector.py | 6 +-- .../vdb/weaviate/weaviate_vector.py | 10 ++-- api/core/rag/docstore/dataset_docstore.py | 10 ++-- api/core/rag/embedding/cached_embedding.py | 2 +- .../rag/extractor/entity/extract_setting.py | 4 +- .../rag/extractor/firecrawl/firecrawl_app.py | 2 +- api/core/rag/extractor/helpers.py | 2 +- api/core/rag/extractor/watercrawl/provider.py | 8 ++-- api/core/rag/extractor/word_extractor.py | 2 +- api/core/rag/rerank/rerank_model.py | 2 +- api/core/rag/rerank/weight_rerank.py | 2 +- api/core/rag/retrieval/dataset_retrieval.py | 4 +- api/core/rag/splitter/text_splitter.py | 6 +-- .../celery_workflow_execution_repository.py | 2 +- ...lery_workflow_node_execution_repository.py | 2 +- ...qlalchemy_workflow_execution_repository.py | 2 +- ...hemy_workflow_node_execution_repository.py | 8 ++-- api/core/tools/__base/tool.py | 2 +- api/core/tools/__base/tool_provider.py | 4 +- api/core/tools/builtin_tool/provider.py | 6 +-- .../builtin_tool/providers/audio/audio.py | 2 +- .../tools/builtin_tool/providers/code/code.py | 2 +- .../tools/builtin_tool/providers/time/time.py | 2 +- .../providers/webscraper/webscraper.py | 2 +- api/core/tools/custom_tool/provider.py | 2 +- api/core/tools/custom_tool/tool.py | 4 +- api/core/tools/entities/api_entities.py | 4 +- api/core/tools/entities/common_entities.py | 2 +- api/core/tools/entities/tool_entities.py | 4 +- api/core/tools/mcp_tool/provider.py | 4 +- api/core/tools/mcp_tool/tool.py | 2 +- api/core/tools/plugin_tool/provider.py | 4 +- api/core/tools/plugin_tool/tool.py | 2 +- api/core/tools/tool_manager.py | 6 +-- api/core/tools/utils/configuration.py | 2 +- .../tools/utils/dataset_retriever_tool.py | 2 +- api/core/tools/utils/encryption.py | 4 +- api/core/tools/utils/parser.py | 2 +- api/core/tools/utils/yaml_utils.py | 2 +- api/core/tools/workflow_as_tool/tool.py | 2 +- api/core/variables/segments.py | 2 +- api/core/variables/types.py | 2 +- api/core/variables/utils.py | 2 +- .../callbacks/base_workflow_callback.py | 2 +- .../callbacks/workflow_logging_callback.py | 32 ++++++------- .../workflow/conversation_variable_updater.py | 2 +- api/core/workflow/entities/variable_pool.py | 8 ++-- .../entities/workflow_node_execution.py | 2 +- .../workflow/graph_engine/entities/graph.py | 14 +++--- .../entities/runtime_route_state.py | 4 +- .../workflow/graph_engine/graph_engine.py | 8 ++-- api/core/workflow/nodes/agent/agent_node.py | 2 +- api/core/workflow/nodes/answer/answer_node.py | 2 +- .../answer/answer_stream_generate_router.py | 2 +- .../nodes/answer/answer_stream_processor.py | 4 +- .../nodes/answer/base_stream_processor.py | 6 +-- api/core/workflow/nodes/base/entities.py | 2 +- api/core/workflow/nodes/base/node.py | 6 +-- api/core/workflow/nodes/code/code_node.py | 4 +- .../workflow/nodes/document_extractor/node.py | 2 +- api/core/workflow/nodes/end/end_node.py | 2 +- .../nodes/end/end_stream_generate_router.py | 2 +- .../nodes/end/end_stream_processor.py | 4 +- api/core/workflow/nodes/http_request/node.py | 4 +- .../workflow/nodes/if_else/if_else_node.py | 2 +- .../nodes/iteration/iteration_node.py | 4 +- .../nodes/iteration/iteration_start_node.py | 2 +- .../knowledge_retrieval_node.py | 4 +- api/core/workflow/nodes/list_operator/node.py | 2 +- api/core/workflow/nodes/llm/exc.py | 2 +- api/core/workflow/nodes/llm/llm_utils.py | 2 +- api/core/workflow/nodes/llm/node.py | 6 +-- api/core/workflow/nodes/loop/loop_end_node.py | 2 +- api/core/workflow/nodes/loop/loop_node.py | 2 +- .../workflow/nodes/loop/loop_start_node.py | 2 +- .../nodes/parameter_extractor/entities.py | 2 +- .../workflow/nodes/parameter_extractor/exc.py | 2 +- .../parameter_extractor_node.py | 10 ++-- .../question_classifier_node.py | 6 +-- api/core/workflow/nodes/start/start_node.py | 2 +- .../template_transform_node.py | 4 +- api/core/workflow/nodes/tool/tool_node.py | 2 +- .../variable_aggregator_node.py | 2 +- .../nodes/variable_assigner/common/impl.py | 2 +- .../nodes/variable_assigner/v1/node.py | 4 +- .../nodes/variable_assigner/v2/exc.py | 2 +- .../nodes/variable_assigner/v2/node.py | 2 +- .../workflow_execution_repository.py | 2 +- .../workflow_node_execution_repository.py | 2 +- .../utils/variable_template_parser.py | 2 +- api/core/workflow/workflow_cycle_manager.py | 10 ++-- api/core/workflow/workflow_entry.py | 6 +-- api/core/workflow/workflow_type_encoder.py | 2 +- .../update_provider_when_message_created.py | 2 +- api/extensions/ext_database.py | 6 +-- api/extensions/ext_orjson.py | 2 +- .../clickzetta_volume_storage.py | 6 +-- .../clickzetta_volume/file_lifecycle.py | 2 +- .../clickzetta_volume/volume_permissions.py | 2 +- api/extensions/storage/opendal_storage.py | 2 +- api/factories/file_factory.py | 2 +- api/libs/email_i18n.py | 12 ++--- api/libs/external_api.py | 2 +- api/libs/json_in_md_parser.py | 4 +- api/libs/module_loading.py | 5 +- api/models/account.py | 2 +- api/models/model.py | 44 +++++++++--------- api/models/tools.py | 14 +++--- api/models/workflow.py | 10 ++-- .../sqlalchemy_api_workflow_run_repository.py | 2 +- api/services/account_service.py | 34 +++++++------- .../advanced_prompt_template_service.py | 10 ++-- api/services/agent_service.py | 2 +- api/services/annotation_service.py | 8 ++-- api/services/api_based_extension_service.py | 6 +-- api/services/app_dsl_service.py | 4 +- api/services/app_model_config_service.py | 2 +- api/services/app_service.py | 4 +- api/services/auth/api_key_auth_service.py | 2 +- .../clear_free_plan_tenant_expired_logs.py | 4 +- api/services/code_based_extension_service.py | 2 +- api/services/conversation_service.py | 2 +- api/services/dataset_service.py | 2 +- .../entities/model_provider_entities.py | 8 ++-- api/services/errors/llm.py | 2 +- api/services/external_knowledge_service.py | 2 +- api/services/hit_testing_service.py | 4 +- api/services/model_load_balancing_service.py | 14 +++--- api/services/model_provider_service.py | 30 ++++++------ api/services/plugin/data_migration.py | 8 ++-- api/services/plugin/plugin_migration.py | 10 ++-- .../buildin/buildin_retrieval.py | 6 +-- .../database/database_retrieval.py | 4 +- .../recommend_app/recommend_app_base.py | 2 +- .../recommend_app/remote/remote_retrieval.py | 4 +- api/services/recommended_app_service.py | 2 +- api/services/tag_service.py | 8 ++-- .../tools/workflow_tools_manage_service.py | 12 ++--- api/services/website_service.py | 2 +- api/services/workflow/workflow_converter.py | 12 ++--- api/services/workflow_app_service.py | 2 +- .../workflow_draft_variable_service.py | 6 +-- api/services/workflow_service.py | 2 +- api/tasks/delete_conversation_task.py | 2 +- api/tasks/mail_account_deletion_task.py | 4 +- api/tasks/mail_change_mail_task.py | 4 +- api/tasks/mail_email_code_login.py | 2 +- api/tasks/mail_invite_member_task.py | 2 +- api/tasks/mail_owner_transfer_task.py | 6 +-- api/tasks/mail_reset_password_task.py | 2 +- api/tasks/remove_app_and_related_data_task.py | 2 +- api/tasks/workflow_execution_tasks.py | 2 +- api/tasks/workflow_node_execution_tasks.py | 4 +- api/tests/integration_tests/conftest.py | 2 +- .../model_runtime/__mock/plugin_daemon.py | 2 +- .../vdb/__mock/tcvectordb.py | 4 +- .../vdb/test_vector_store.py | 4 +- .../workflow/nodes/__mock/code_executor.py | 2 +- .../workflow/nodes/test_code.py | 10 ++-- .../conftest.py | 4 +- .../test_workflow_response_converter.py | 2 +- .../core/mcp/client/test_session.py | 2 +- .../graph_engine/test_graph_engine.py | 2 +- .../workflow/nodes/test_continue_on_error.py | 4 +- .../core/workflow/nodes/test_if_else.py | 2 +- .../core/workflow/test_variable_pool.py | 2 +- api/tests/unit_tests/libs/test_email_i18n.py | 46 +++++++++---------- api/tests/unit_tests/libs/test_rsa.py | 2 +- api/tests/unit_tests/models/test_account.py | 2 +- 306 files changed, 787 insertions(+), 817 deletions(-) diff --git a/api/configs/remote_settings_sources/base.py b/api/configs/remote_settings_sources/base.py index a96ffdfb4b..44ac2acd06 100644 --- a/api/configs/remote_settings_sources/base.py +++ b/api/configs/remote_settings_sources/base.py @@ -11,5 +11,5 @@ class RemoteSettingsSource: def get_field_value(self, field: FieldInfo, field_name: str) -> tuple[Any, str, bool]: raise NotImplementedError - def prepare_field_value(self, field_name: str, field: FieldInfo, value: Any, value_is_complex: bool) -> Any: + def prepare_field_value(self, field_name: str, field: FieldInfo, value: Any, value_is_complex: bool): return value diff --git a/api/configs/remote_settings_sources/nacos/__init__.py b/api/configs/remote_settings_sources/nacos/__init__.py index d4fcd2c96d..c6efd6f3ac 100644 --- a/api/configs/remote_settings_sources/nacos/__init__.py +++ b/api/configs/remote_settings_sources/nacos/__init__.py @@ -33,7 +33,7 @@ class NacosSettingsSource(RemoteSettingsSource): logger.exception("[get-access-token] exception occurred") raise - def _parse_config(self, content: str) -> dict: + def _parse_config(self, content: str): if not content: return {} try: diff --git a/api/controllers/console/app/generator.py b/api/controllers/console/app/generator.py index 497fd53df7..a2cb226014 100644 --- a/api/controllers/console/app/generator.py +++ b/api/controllers/console/app/generator.py @@ -207,7 +207,7 @@ class InstructionGenerationTemplateApi(Resource): @setup_required @login_required @account_initialization_required - def post(self) -> dict: + def post(self): parser = reqparse.RequestParser() parser.add_argument("type", type=str, required=True, default=False, location="json") args = parser.parse_args() diff --git a/api/controllers/console/app/workflow_draft_variable.py b/api/controllers/console/app/workflow_draft_variable.py index a0b73f7e07..5fced3e90f 100644 --- a/api/controllers/console/app/workflow_draft_variable.py +++ b/api/controllers/console/app/workflow_draft_variable.py @@ -1,5 +1,5 @@ import logging -from typing import Any, NoReturn +from typing import NoReturn from flask import Response from flask_restx import Resource, fields, inputs, marshal, marshal_with, reqparse @@ -29,7 +29,7 @@ from services.workflow_service import WorkflowService logger = logging.getLogger(__name__) -def _convert_values_to_json_serializable_object(value: Segment) -> Any: +def _convert_values_to_json_serializable_object(value: Segment): if isinstance(value, FileSegment): return value.value.model_dump() elif isinstance(value, ArrayFileSegment): @@ -40,7 +40,7 @@ def _convert_values_to_json_serializable_object(value: Segment) -> Any: return value.value -def _serialize_var_value(variable: WorkflowDraftVariable) -> Any: +def _serialize_var_value(variable: WorkflowDraftVariable): value = variable.get_value() # create a copy of the value to avoid affecting the model cache. value = value.model_copy(deep=True) diff --git a/api/controllers/mcp/mcp.py b/api/controllers/mcp/mcp.py index eef9ddc76f..43b59d5334 100644 --- a/api/controllers/mcp/mcp.py +++ b/api/controllers/mcp/mcp.py @@ -99,7 +99,7 @@ class MCPAppApi(Resource): return mcp_server, app - def _validate_server_status(self, mcp_server: AppMCPServer) -> None: + def _validate_server_status(self, mcp_server: AppMCPServer): """Validate MCP server status""" if mcp_server.status != AppMCPServerStatus.ACTIVE: raise MCPRequestError(mcp_types.INVALID_REQUEST, "Server is not active") diff --git a/api/core/agent/base_agent_runner.py b/api/core/agent/base_agent_runner.py index f5e45bcb47..1bcf83de6a 100644 --- a/api/core/agent/base_agent_runner.py +++ b/api/core/agent/base_agent_runner.py @@ -62,7 +62,7 @@ class BaseAgentRunner(AppRunner): model_instance: ModelInstance, memory: Optional[TokenBufferMemory] = None, prompt_messages: Optional[list[PromptMessage]] = None, - ) -> None: + ): self.tenant_id = tenant_id self.application_generate_entity = application_generate_entity self.conversation = conversation diff --git a/api/core/agent/cot_agent_runner.py b/api/core/agent/cot_agent_runner.py index 6cb1077126..b94a60c40a 100644 --- a/api/core/agent/cot_agent_runner.py +++ b/api/core/agent/cot_agent_runner.py @@ -338,7 +338,7 @@ class CotAgentRunner(BaseAgentRunner, ABC): return instruction - def _init_react_state(self, query) -> None: + def _init_react_state(self, query): """ init agent scratchpad """ diff --git a/api/core/agent/entities.py b/api/core/agent/entities.py index a31c1050bd..816d2782f0 100644 --- a/api/core/agent/entities.py +++ b/api/core/agent/entities.py @@ -41,7 +41,7 @@ class AgentScratchpadUnit(BaseModel): action_name: str action_input: Union[dict, str] - def to_dict(self) -> dict: + def to_dict(self): """ Convert to dictionary. """ diff --git a/api/core/app/app_config/easy_ui_based_app/dataset/manager.py b/api/core/app/app_config/easy_ui_based_app/dataset/manager.py index a5492d70bd..fcbf479e2e 100644 --- a/api/core/app/app_config/easy_ui_based_app/dataset/manager.py +++ b/api/core/app/app_config/easy_ui_based_app/dataset/manager.py @@ -158,7 +158,7 @@ class DatasetConfigManager: return config, ["agent_mode", "dataset_configs", "dataset_query_variable"] @classmethod - def extract_dataset_config_for_legacy_compatibility(cls, tenant_id: str, app_mode: AppMode, config: dict) -> dict: + def extract_dataset_config_for_legacy_compatibility(cls, tenant_id: str, app_mode: AppMode, config: dict): """ Extract dataset config for legacy compatibility diff --git a/api/core/app/app_config/easy_ui_based_app/model_config/manager.py b/api/core/app/app_config/easy_ui_based_app/model_config/manager.py index 54bca10fc3..781a703a01 100644 --- a/api/core/app/app_config/easy_ui_based_app/model_config/manager.py +++ b/api/core/app/app_config/easy_ui_based_app/model_config/manager.py @@ -105,7 +105,7 @@ class ModelConfigManager: return dict(config), ["model"] @classmethod - def validate_model_completion_params(cls, cp: dict) -> dict: + def validate_model_completion_params(cls, cp: dict): # model.completion_params if not isinstance(cp, dict): raise ValueError("model.completion_params must be of object type") diff --git a/api/core/app/app_config/easy_ui_based_app/prompt_template/manager.py b/api/core/app/app_config/easy_ui_based_app/prompt_template/manager.py index fa30511f63..e6ab31e586 100644 --- a/api/core/app/app_config/easy_ui_based_app/prompt_template/manager.py +++ b/api/core/app/app_config/easy_ui_based_app/prompt_template/manager.py @@ -122,7 +122,7 @@ class PromptTemplateConfigManager: return config, ["prompt_type", "pre_prompt", "chat_prompt_config", "completion_prompt_config"] @classmethod - def validate_post_prompt_and_set_defaults(cls, config: dict) -> dict: + def validate_post_prompt_and_set_defaults(cls, config: dict): """ Validate post_prompt and set defaults for prompt feature diff --git a/api/core/app/apps/advanced_chat/app_config_manager.py b/api/core/app/apps/advanced_chat/app_config_manager.py index cb606953cd..e4b308a6f6 100644 --- a/api/core/app/apps/advanced_chat/app_config_manager.py +++ b/api/core/app/apps/advanced_chat/app_config_manager.py @@ -41,7 +41,7 @@ class AdvancedChatAppConfigManager(BaseAppConfigManager): return app_config @classmethod - def config_validate(cls, tenant_id: str, config: dict, only_structure_validate: bool = False) -> dict: + def config_validate(cls, tenant_id: str, config: dict, only_structure_validate: bool = False): """ Validate for advanced chat app model config diff --git a/api/core/app/apps/advanced_chat/app_generator.py b/api/core/app/apps/advanced_chat/app_generator.py index 561af7bacf..84b032d6ca 100644 --- a/api/core/app/apps/advanced_chat/app_generator.py +++ b/api/core/app/apps/advanced_chat/app_generator.py @@ -481,7 +481,7 @@ class AdvancedChatAppGenerator(MessageBasedAppGenerator): message_id: str, context: contextvars.Context, variable_loader: VariableLoader, - ) -> None: + ): """ Generate worker in a new thread. :param flask_app: Flask app diff --git a/api/core/app/apps/advanced_chat/app_runner.py b/api/core/app/apps/advanced_chat/app_runner.py index 5e20e80d11..635754a201 100644 --- a/api/core/app/apps/advanced_chat/app_runner.py +++ b/api/core/app/apps/advanced_chat/app_runner.py @@ -54,7 +54,7 @@ class AdvancedChatAppRunner(WorkflowBasedAppRunner): workflow: Workflow, system_user_id: str, app: App, - ) -> None: + ): super().__init__( queue_manager=queue_manager, variable_loader=variable_loader, @@ -68,7 +68,7 @@ class AdvancedChatAppRunner(WorkflowBasedAppRunner): self.system_user_id = system_user_id self._app = app - def run(self) -> None: + def run(self): app_config = self.application_generate_entity.app_config app_config = cast(AdvancedChatAppConfig, app_config) @@ -221,7 +221,7 @@ class AdvancedChatAppRunner(WorkflowBasedAppRunner): return False - def _complete_with_stream_output(self, text: str, stopped_by: QueueStopEvent.StopBy) -> None: + def _complete_with_stream_output(self, text: str, stopped_by: QueueStopEvent.StopBy): """ Direct output """ diff --git a/api/core/app/apps/advanced_chat/generate_task_pipeline.py b/api/core/app/apps/advanced_chat/generate_task_pipeline.py index 750e13c502..8207b70f9e 100644 --- a/api/core/app/apps/advanced_chat/generate_task_pipeline.py +++ b/api/core/app/apps/advanced_chat/generate_task_pipeline.py @@ -101,7 +101,7 @@ class AdvancedChatAppGenerateTaskPipeline: workflow_execution_repository: WorkflowExecutionRepository, workflow_node_execution_repository: WorkflowNodeExecutionRepository, draft_var_saver_factory: DraftVariableSaverFactory, - ) -> None: + ): self._base_task_pipeline = BasedGenerateTaskPipeline( application_generate_entity=application_generate_entity, queue_manager=queue_manager, @@ -289,7 +289,7 @@ class AdvancedChatAppGenerateTaskPipeline: session.rollback() raise - def _ensure_workflow_initialized(self) -> None: + def _ensure_workflow_initialized(self): """Fluent validation for workflow state.""" if not self._workflow_run_id: raise ValueError("workflow run not initialized.") @@ -888,7 +888,7 @@ class AdvancedChatAppGenerateTaskPipeline: if self._conversation_name_generate_thread: self._conversation_name_generate_thread.join() - def _save_message(self, *, session: Session, graph_runtime_state: Optional[GraphRuntimeState] = None) -> None: + def _save_message(self, *, session: Session, graph_runtime_state: Optional[GraphRuntimeState] = None): message = self._get_message(session=session) # If there are assistant files, remove markdown image links from answer diff --git a/api/core/app/apps/agent_chat/app_config_manager.py b/api/core/app/apps/agent_chat/app_config_manager.py index 55b6ee510f..349b583833 100644 --- a/api/core/app/apps/agent_chat/app_config_manager.py +++ b/api/core/app/apps/agent_chat/app_config_manager.py @@ -86,7 +86,7 @@ class AgentChatAppConfigManager(BaseAppConfigManager): return app_config @classmethod - def config_validate(cls, tenant_id: str, config: Mapping[str, Any]) -> dict: + def config_validate(cls, tenant_id: str, config: Mapping[str, Any]): """ Validate for agent chat app model config diff --git a/api/core/app/apps/agent_chat/app_generator.py b/api/core/app/apps/agent_chat/app_generator.py index 8665bc9d11..c6d98374c1 100644 --- a/api/core/app/apps/agent_chat/app_generator.py +++ b/api/core/app/apps/agent_chat/app_generator.py @@ -222,7 +222,7 @@ class AgentChatAppGenerator(MessageBasedAppGenerator): queue_manager: AppQueueManager, conversation_id: str, message_id: str, - ) -> None: + ): """ Generate worker in a new thread. :param flask_app: Flask app diff --git a/api/core/app/apps/agent_chat/app_runner.py b/api/core/app/apps/agent_chat/app_runner.py index d3207365f3..388bed5255 100644 --- a/api/core/app/apps/agent_chat/app_runner.py +++ b/api/core/app/apps/agent_chat/app_runner.py @@ -35,7 +35,7 @@ class AgentChatAppRunner(AppRunner): queue_manager: AppQueueManager, conversation: Conversation, message: Message, - ) -> None: + ): """ Run assistant application :param application_generate_entity: application generate entity diff --git a/api/core/app/apps/agent_chat/generate_response_converter.py b/api/core/app/apps/agent_chat/generate_response_converter.py index 0eea135167..89a5b8e3b5 100644 --- a/api/core/app/apps/agent_chat/generate_response_converter.py +++ b/api/core/app/apps/agent_chat/generate_response_converter.py @@ -16,7 +16,7 @@ class AgentChatAppGenerateResponseConverter(AppGenerateResponseConverter): _blocking_response_type = ChatbotAppBlockingResponse @classmethod - def convert_blocking_full_response(cls, blocking_response: ChatbotAppBlockingResponse) -> dict: # type: ignore[override] + def convert_blocking_full_response(cls, blocking_response: ChatbotAppBlockingResponse): # type: ignore[override] """ Convert blocking full response. :param blocking_response: blocking response @@ -37,7 +37,7 @@ class AgentChatAppGenerateResponseConverter(AppGenerateResponseConverter): return response @classmethod - def convert_blocking_simple_response(cls, blocking_response: ChatbotAppBlockingResponse) -> dict: # type: ignore[override] + def convert_blocking_simple_response(cls, blocking_response: ChatbotAppBlockingResponse): # type: ignore[override] """ Convert blocking simple response. :param blocking_response: blocking response diff --git a/api/core/app/apps/base_app_generate_response_converter.py b/api/core/app/apps/base_app_generate_response_converter.py index af3731bdc7..74c6d2eca6 100644 --- a/api/core/app/apps/base_app_generate_response_converter.py +++ b/api/core/app/apps/base_app_generate_response_converter.py @@ -94,7 +94,7 @@ class AppGenerateResponseConverter(ABC): return metadata @classmethod - def _error_to_stream_response(cls, e: Exception) -> dict: + def _error_to_stream_response(cls, e: Exception): """ Error to stream response. :param e: exception diff --git a/api/core/app/apps/base_app_generator.py b/api/core/app/apps/base_app_generator.py index b420ffb8bf..6681fc6e48 100644 --- a/api/core/app/apps/base_app_generator.py +++ b/api/core/app/apps/base_app_generator.py @@ -157,7 +157,7 @@ class BaseAppGenerator: return value - def _sanitize_value(self, value: Any) -> Any: + def _sanitize_value(self, value: Any): if isinstance(value, str): return value.replace("\x00", "") return value diff --git a/api/core/app/apps/base_app_queue_manager.py b/api/core/app/apps/base_app_queue_manager.py index 6bb5132275..795a7befff 100644 --- a/api/core/app/apps/base_app_queue_manager.py +++ b/api/core/app/apps/base_app_queue_manager.py @@ -25,7 +25,7 @@ class PublishFrom(IntEnum): class AppQueueManager: - def __init__(self, task_id: str, user_id: str, invoke_from: InvokeFrom) -> None: + def __init__(self, task_id: str, user_id: str, invoke_from: InvokeFrom): if not user_id: raise ValueError("user is required") @@ -73,14 +73,14 @@ class AppQueueManager: self.publish(QueuePingEvent(), PublishFrom.TASK_PIPELINE) last_ping_time = elapsed_time // 10 - def stop_listen(self) -> None: + def stop_listen(self): """ Stop listen to queue :return: """ self._q.put(None) - def publish_error(self, e, pub_from: PublishFrom) -> None: + def publish_error(self, e, pub_from: PublishFrom): """ Publish error :param e: error @@ -89,7 +89,7 @@ class AppQueueManager: """ self.publish(QueueErrorEvent(error=e), pub_from) - def publish(self, event: AppQueueEvent, pub_from: PublishFrom) -> None: + def publish(self, event: AppQueueEvent, pub_from: PublishFrom): """ Publish event to queue :param event: @@ -100,7 +100,7 @@ class AppQueueManager: self._publish(event, pub_from) @abstractmethod - def _publish(self, event: AppQueueEvent, pub_from: PublishFrom) -> None: + def _publish(self, event: AppQueueEvent, pub_from: PublishFrom): """ Publish event to queue :param event: @@ -110,7 +110,7 @@ class AppQueueManager: raise NotImplementedError @classmethod - def set_stop_flag(cls, task_id: str, invoke_from: InvokeFrom, user_id: str) -> None: + def set_stop_flag(cls, task_id: str, invoke_from: InvokeFrom, user_id: str): """ Set task stop flag :return: diff --git a/api/core/app/apps/base_app_runner.py b/api/core/app/apps/base_app_runner.py index 6e8c261a6a..dafdcdd429 100644 --- a/api/core/app/apps/base_app_runner.py +++ b/api/core/app/apps/base_app_runner.py @@ -162,7 +162,7 @@ class AppRunner: text: str, stream: bool, usage: Optional[LLMUsage] = None, - ) -> None: + ): """ Direct output :param queue_manager: application queue manager @@ -204,7 +204,7 @@ class AppRunner: queue_manager: AppQueueManager, stream: bool, agent: bool = False, - ) -> None: + ): """ Handle invoke result :param invoke_result: invoke result @@ -220,9 +220,7 @@ class AppRunner: else: raise NotImplementedError(f"unsupported invoke result type: {type(invoke_result)}") - def _handle_invoke_result_direct( - self, invoke_result: LLMResult, queue_manager: AppQueueManager, agent: bool - ) -> None: + def _handle_invoke_result_direct(self, invoke_result: LLMResult, queue_manager: AppQueueManager, agent: bool): """ Handle invoke result direct :param invoke_result: invoke result @@ -239,7 +237,7 @@ class AppRunner: def _handle_invoke_result_stream( self, invoke_result: Generator[LLMResultChunk, None, None], queue_manager: AppQueueManager, agent: bool - ) -> None: + ): """ Handle invoke result :param invoke_result: invoke result diff --git a/api/core/app/apps/chat/app_config_manager.py b/api/core/app/apps/chat/app_config_manager.py index 96dc7dda79..96a3db8502 100644 --- a/api/core/app/apps/chat/app_config_manager.py +++ b/api/core/app/apps/chat/app_config_manager.py @@ -81,7 +81,7 @@ class ChatAppConfigManager(BaseAppConfigManager): return app_config @classmethod - def config_validate(cls, tenant_id: str, config: dict) -> dict: + def config_validate(cls, tenant_id: str, config: dict): """ Validate for chat app model config diff --git a/api/core/app/apps/chat/app_generator.py b/api/core/app/apps/chat/app_generator.py index c273776eb1..8bd956b314 100644 --- a/api/core/app/apps/chat/app_generator.py +++ b/api/core/app/apps/chat/app_generator.py @@ -211,7 +211,7 @@ class ChatAppGenerator(MessageBasedAppGenerator): queue_manager: AppQueueManager, conversation_id: str, message_id: str, - ) -> None: + ): """ Generate worker in a new thread. :param flask_app: Flask app diff --git a/api/core/app/apps/chat/app_runner.py b/api/core/app/apps/chat/app_runner.py index 4385d0f08d..d082cf2d3f 100644 --- a/api/core/app/apps/chat/app_runner.py +++ b/api/core/app/apps/chat/app_runner.py @@ -33,7 +33,7 @@ class ChatAppRunner(AppRunner): queue_manager: AppQueueManager, conversation: Conversation, message: Message, - ) -> None: + ): """ Run application :param application_generate_entity: application generate entity diff --git a/api/core/app/apps/chat/generate_response_converter.py b/api/core/app/apps/chat/generate_response_converter.py index 13a6be167c..816d6d79a9 100644 --- a/api/core/app/apps/chat/generate_response_converter.py +++ b/api/core/app/apps/chat/generate_response_converter.py @@ -16,7 +16,7 @@ class ChatAppGenerateResponseConverter(AppGenerateResponseConverter): _blocking_response_type = ChatbotAppBlockingResponse @classmethod - def convert_blocking_full_response(cls, blocking_response: ChatbotAppBlockingResponse) -> dict: # type: ignore[override] + def convert_blocking_full_response(cls, blocking_response: ChatbotAppBlockingResponse): # type: ignore[override] """ Convert blocking full response. :param blocking_response: blocking response @@ -37,7 +37,7 @@ class ChatAppGenerateResponseConverter(AppGenerateResponseConverter): return response @classmethod - def convert_blocking_simple_response(cls, blocking_response: ChatbotAppBlockingResponse) -> dict: # type: ignore[override] + def convert_blocking_simple_response(cls, blocking_response: ChatbotAppBlockingResponse): # type: ignore[override] """ Convert blocking simple response. :param blocking_response: blocking response diff --git a/api/core/app/apps/common/workflow_response_converter.py b/api/core/app/apps/common/workflow_response_converter.py index c8760d3cf0..937b2a7dd7 100644 --- a/api/core/app/apps/common/workflow_response_converter.py +++ b/api/core/app/apps/common/workflow_response_converter.py @@ -62,7 +62,7 @@ class WorkflowResponseConverter: *, application_generate_entity: Union[AdvancedChatAppGenerateEntity, WorkflowAppGenerateEntity], user: Union[Account, EndUser], - ) -> None: + ): self._application_generate_entity = application_generate_entity self._user = user diff --git a/api/core/app/apps/completion/app_config_manager.py b/api/core/app/apps/completion/app_config_manager.py index 02e5d47568..3a1f29689d 100644 --- a/api/core/app/apps/completion/app_config_manager.py +++ b/api/core/app/apps/completion/app_config_manager.py @@ -66,7 +66,7 @@ class CompletionAppConfigManager(BaseAppConfigManager): return app_config @classmethod - def config_validate(cls, tenant_id: str, config: dict) -> dict: + def config_validate(cls, tenant_id: str, config: dict): """ Validate for completion app model config diff --git a/api/core/app/apps/completion/app_generator.py b/api/core/app/apps/completion/app_generator.py index 8d2f3d488b..6e43e5ec94 100644 --- a/api/core/app/apps/completion/app_generator.py +++ b/api/core/app/apps/completion/app_generator.py @@ -192,7 +192,7 @@ class CompletionAppGenerator(MessageBasedAppGenerator): application_generate_entity: CompletionAppGenerateEntity, queue_manager: AppQueueManager, message_id: str, - ) -> None: + ): """ Generate worker in a new thread. :param flask_app: Flask app diff --git a/api/core/app/apps/completion/app_runner.py b/api/core/app/apps/completion/app_runner.py index d384bff255..6c4bf4139e 100644 --- a/api/core/app/apps/completion/app_runner.py +++ b/api/core/app/apps/completion/app_runner.py @@ -27,7 +27,7 @@ class CompletionAppRunner(AppRunner): def run( self, application_generate_entity: CompletionAppGenerateEntity, queue_manager: AppQueueManager, message: Message - ) -> None: + ): """ Run application :param application_generate_entity: application generate entity diff --git a/api/core/app/apps/completion/generate_response_converter.py b/api/core/app/apps/completion/generate_response_converter.py index c2b78e8176..4d45c61145 100644 --- a/api/core/app/apps/completion/generate_response_converter.py +++ b/api/core/app/apps/completion/generate_response_converter.py @@ -16,7 +16,7 @@ class CompletionAppGenerateResponseConverter(AppGenerateResponseConverter): _blocking_response_type = CompletionAppBlockingResponse @classmethod - def convert_blocking_full_response(cls, blocking_response: CompletionAppBlockingResponse) -> dict: # type: ignore[override] + def convert_blocking_full_response(cls, blocking_response: CompletionAppBlockingResponse): # type: ignore[override] """ Convert blocking full response. :param blocking_response: blocking response @@ -36,7 +36,7 @@ class CompletionAppGenerateResponseConverter(AppGenerateResponseConverter): return response @classmethod - def convert_blocking_simple_response(cls, blocking_response: CompletionAppBlockingResponse) -> dict: # type: ignore[override] + def convert_blocking_simple_response(cls, blocking_response: CompletionAppBlockingResponse): # type: ignore[override] """ Convert blocking simple response. :param blocking_response: blocking response diff --git a/api/core/app/apps/message_based_app_queue_manager.py b/api/core/app/apps/message_based_app_queue_manager.py index 4100a0d5a9..67fc016cba 100644 --- a/api/core/app/apps/message_based_app_queue_manager.py +++ b/api/core/app/apps/message_based_app_queue_manager.py @@ -14,14 +14,14 @@ from core.app.entities.queue_entities import ( class MessageBasedAppQueueManager(AppQueueManager): def __init__( self, task_id: str, user_id: str, invoke_from: InvokeFrom, conversation_id: str, app_mode: str, message_id: str - ) -> None: + ): super().__init__(task_id, user_id, invoke_from) self._conversation_id = str(conversation_id) self._app_mode = app_mode self._message_id = str(message_id) - def _publish(self, event: AppQueueEvent, pub_from: PublishFrom) -> None: + def _publish(self, event: AppQueueEvent, pub_from: PublishFrom): """ Publish event to queue :param event: diff --git a/api/core/app/apps/workflow/app_config_manager.py b/api/core/app/apps/workflow/app_config_manager.py index b0aa21c731..e72da91c21 100644 --- a/api/core/app/apps/workflow/app_config_manager.py +++ b/api/core/app/apps/workflow/app_config_manager.py @@ -35,7 +35,7 @@ class WorkflowAppConfigManager(BaseAppConfigManager): return app_config @classmethod - def config_validate(cls, tenant_id: str, config: dict, only_structure_validate: bool = False) -> dict: + def config_validate(cls, tenant_id: str, config: dict, only_structure_validate: bool = False): """ Validate for workflow app model config diff --git a/api/core/app/apps/workflow/app_generator.py b/api/core/app/apps/workflow/app_generator.py index 22b0234604..60395f0416 100644 --- a/api/core/app/apps/workflow/app_generator.py +++ b/api/core/app/apps/workflow/app_generator.py @@ -435,7 +435,7 @@ class WorkflowAppGenerator(BaseAppGenerator): context: contextvars.Context, variable_loader: VariableLoader, workflow_thread_pool_id: Optional[str] = None, - ) -> None: + ): """ Generate worker in a new thread. :param flask_app: Flask app diff --git a/api/core/app/apps/workflow/app_queue_manager.py b/api/core/app/apps/workflow/app_queue_manager.py index 40fc03afb7..9985e2d275 100644 --- a/api/core/app/apps/workflow/app_queue_manager.py +++ b/api/core/app/apps/workflow/app_queue_manager.py @@ -14,12 +14,12 @@ from core.app.entities.queue_entities import ( class WorkflowAppQueueManager(AppQueueManager): - def __init__(self, task_id: str, user_id: str, invoke_from: InvokeFrom, app_mode: str) -> None: + def __init__(self, task_id: str, user_id: str, invoke_from: InvokeFrom, app_mode: str): super().__init__(task_id, user_id, invoke_from) self._app_mode = app_mode - def _publish(self, event: AppQueueEvent, pub_from: PublishFrom) -> None: + def _publish(self, event: AppQueueEvent, pub_from: PublishFrom): """ Publish event to queue :param event: diff --git a/api/core/app/apps/workflow/app_runner.py b/api/core/app/apps/workflow/app_runner.py index 4f4c1460ae..42b3575807 100644 --- a/api/core/app/apps/workflow/app_runner.py +++ b/api/core/app/apps/workflow/app_runner.py @@ -34,7 +34,7 @@ class WorkflowAppRunner(WorkflowBasedAppRunner): workflow_thread_pool_id: Optional[str] = None, workflow: Workflow, system_user_id: str, - ) -> None: + ): super().__init__( queue_manager=queue_manager, variable_loader=variable_loader, @@ -45,7 +45,7 @@ class WorkflowAppRunner(WorkflowBasedAppRunner): self._workflow = workflow self._sys_user_id = system_user_id - def run(self) -> None: + def run(self): """ Run application """ diff --git a/api/core/app/apps/workflow/generate_response_converter.py b/api/core/app/apps/workflow/generate_response_converter.py index 917ede6173..210f6110b1 100644 --- a/api/core/app/apps/workflow/generate_response_converter.py +++ b/api/core/app/apps/workflow/generate_response_converter.py @@ -17,7 +17,7 @@ class WorkflowAppGenerateResponseConverter(AppGenerateResponseConverter): _blocking_response_type = WorkflowAppBlockingResponse @classmethod - def convert_blocking_full_response(cls, blocking_response: WorkflowAppBlockingResponse) -> dict: # type: ignore[override] + def convert_blocking_full_response(cls, blocking_response: WorkflowAppBlockingResponse): # type: ignore[override] """ Convert blocking full response. :param blocking_response: blocking response @@ -26,7 +26,7 @@ class WorkflowAppGenerateResponseConverter(AppGenerateResponseConverter): return dict(blocking_response.to_dict()) @classmethod - def convert_blocking_simple_response(cls, blocking_response: WorkflowAppBlockingResponse) -> dict: # type: ignore[override] + def convert_blocking_simple_response(cls, blocking_response: WorkflowAppBlockingResponse): # type: ignore[override] """ Convert blocking simple response. :param blocking_response: blocking response diff --git a/api/core/app/apps/workflow/generate_task_pipeline.py b/api/core/app/apps/workflow/generate_task_pipeline.py index c10f95475f..6ab89dbd61 100644 --- a/api/core/app/apps/workflow/generate_task_pipeline.py +++ b/api/core/app/apps/workflow/generate_task_pipeline.py @@ -92,7 +92,7 @@ class WorkflowAppGenerateTaskPipeline: workflow_execution_repository: WorkflowExecutionRepository, workflow_node_execution_repository: WorkflowNodeExecutionRepository, draft_var_saver_factory: DraftVariableSaverFactory, - ) -> None: + ): self._base_task_pipeline = BasedGenerateTaskPipeline( application_generate_entity=application_generate_entity, queue_manager=queue_manager, @@ -263,7 +263,7 @@ class WorkflowAppGenerateTaskPipeline: session.rollback() raise - def _ensure_workflow_initialized(self) -> None: + def _ensure_workflow_initialized(self): """Fluent validation for workflow state.""" if not self._workflow_run_id: raise ValueError("workflow run not initialized.") @@ -744,7 +744,7 @@ class WorkflowAppGenerateTaskPipeline: if tts_publisher: tts_publisher.publish(None) - def _save_workflow_app_log(self, *, session: Session, workflow_execution: WorkflowExecution) -> None: + def _save_workflow_app_log(self, *, session: Session, workflow_execution: WorkflowExecution): invoke_from = self._application_generate_entity.invoke_from if invoke_from == InvokeFrom.SERVICE_API: created_from = WorkflowAppLogCreatedFrom.SERVICE_API diff --git a/api/core/app/apps/workflow_app_runner.py b/api/core/app/apps/workflow_app_runner.py index 948ea95e63..b6cb88ea86 100644 --- a/api/core/app/apps/workflow_app_runner.py +++ b/api/core/app/apps/workflow_app_runner.py @@ -74,7 +74,7 @@ class WorkflowBasedAppRunner: queue_manager: AppQueueManager, variable_loader: VariableLoader = DUMMY_VARIABLE_LOADER, app_id: str, - ) -> None: + ): self._queue_manager = queue_manager self._variable_loader = variable_loader self._app_id = app_id @@ -292,7 +292,7 @@ class WorkflowBasedAppRunner: return graph, variable_pool - def _handle_event(self, workflow_entry: WorkflowEntry, event: GraphEngineEvent) -> None: + def _handle_event(self, workflow_entry: WorkflowEntry, event: GraphEngineEvent): """ Handle event :param workflow_entry: workflow entry @@ -694,5 +694,5 @@ class WorkflowBasedAppRunner: ) ) - def _publish_event(self, event: AppQueueEvent) -> None: + def _publish_event(self, event: AppQueueEvent): self._queue_manager.publish(event, PublishFrom.APPLICATION_MANAGER) diff --git a/api/core/app/task_pipeline/based_generate_task_pipeline.py b/api/core/app/task_pipeline/based_generate_task_pipeline.py index d04855e992..7d98cceb1a 100644 --- a/api/core/app/task_pipeline/based_generate_task_pipeline.py +++ b/api/core/app/task_pipeline/based_generate_task_pipeline.py @@ -35,7 +35,7 @@ class BasedGenerateTaskPipeline: application_generate_entity: AppGenerateEntity, queue_manager: AppQueueManager, stream: bool, - ) -> None: + ): self._application_generate_entity = application_generate_entity self.queue_manager = queue_manager self._start_at = time.perf_counter() diff --git a/api/core/app/task_pipeline/easy_ui_based_generate_task_pipeline.py b/api/core/app/task_pipeline/easy_ui_based_generate_task_pipeline.py index e3b917067f..0dad0a5a9d 100644 --- a/api/core/app/task_pipeline/easy_ui_based_generate_task_pipeline.py +++ b/api/core/app/task_pipeline/easy_ui_based_generate_task_pipeline.py @@ -80,7 +80,7 @@ class EasyUIBasedGenerateTaskPipeline(BasedGenerateTaskPipeline): conversation: Conversation, message: Message, stream: bool, - ) -> None: + ): super().__init__( application_generate_entity=application_generate_entity, queue_manager=queue_manager, @@ -362,7 +362,7 @@ class EasyUIBasedGenerateTaskPipeline(BasedGenerateTaskPipeline): if self._conversation_name_generate_thread: self._conversation_name_generate_thread.join() - def _save_message(self, *, session: Session, trace_manager: Optional[TraceQueueManager] = None) -> None: + def _save_message(self, *, session: Session, trace_manager: Optional[TraceQueueManager] = None): """ Save message. :return: @@ -412,7 +412,7 @@ class EasyUIBasedGenerateTaskPipeline(BasedGenerateTaskPipeline): application_generate_entity=self._application_generate_entity, ) - def _handle_stop(self, event: QueueStopEvent) -> None: + def _handle_stop(self, event: QueueStopEvent): """ Handle stop. :return: diff --git a/api/core/app/task_pipeline/message_cycle_manager.py b/api/core/app/task_pipeline/message_cycle_manager.py index 8ea4a4ec38..e865ba9d60 100644 --- a/api/core/app/task_pipeline/message_cycle_manager.py +++ b/api/core/app/task_pipeline/message_cycle_manager.py @@ -48,7 +48,7 @@ class MessageCycleManager: AdvancedChatAppGenerateEntity, ], task_state: Union[EasyUITaskState, WorkflowTaskState], - ) -> None: + ): self._application_generate_entity = application_generate_entity self._task_state = task_state @@ -132,7 +132,7 @@ class MessageCycleManager: return None - def handle_retriever_resources(self, event: QueueRetrieverResourcesEvent) -> None: + def handle_retriever_resources(self, event: QueueRetrieverResourcesEvent): """ Handle retriever resources. :param event: event diff --git a/api/core/callback_handler/agent_tool_callback_handler.py b/api/core/callback_handler/agent_tool_callback_handler.py index 65d899a002..30cdab26dc 100644 --- a/api/core/callback_handler/agent_tool_callback_handler.py +++ b/api/core/callback_handler/agent_tool_callback_handler.py @@ -23,7 +23,7 @@ def get_colored_text(text: str, color: str) -> str: return f"\u001b[{color_str}m\033[1;3m{text}\u001b[0m" -def print_text(text: str, color: Optional[str] = None, end: str = "", file: Optional[TextIO] = None) -> None: +def print_text(text: str, color: Optional[str] = None, end: str = "", file: Optional[TextIO] = None): """Print text with highlighting and no end characters.""" text_to_print = get_colored_text(text, color) if color else text print(text_to_print, end=end, file=file) @@ -37,7 +37,7 @@ class DifyAgentCallbackHandler(BaseModel): color: Optional[str] = "" current_loop: int = 1 - def __init__(self, color: Optional[str] = None) -> None: + def __init__(self, color: Optional[str] = None): super().__init__() """Initialize callback handler.""" # use a specific color is not specified @@ -48,7 +48,7 @@ class DifyAgentCallbackHandler(BaseModel): self, tool_name: str, tool_inputs: Mapping[str, Any], - ) -> None: + ): """Do nothing.""" if dify_config.DEBUG: print_text("\n[on_tool_start] ToolCall:" + tool_name + "\n" + str(tool_inputs) + "\n", color=self.color) @@ -61,7 +61,7 @@ class DifyAgentCallbackHandler(BaseModel): message_id: Optional[str] = None, timer: Optional[Any] = None, trace_manager: Optional[TraceQueueManager] = None, - ) -> None: + ): """If not the final action, print out observation.""" if dify_config.DEBUG: print_text("\n[on_tool_end]\n", color=self.color) @@ -82,12 +82,12 @@ class DifyAgentCallbackHandler(BaseModel): ) ) - def on_tool_error(self, error: Union[Exception, KeyboardInterrupt], **kwargs: Any) -> None: + def on_tool_error(self, error: Union[Exception, KeyboardInterrupt], **kwargs: Any): """Do nothing.""" if dify_config.DEBUG: print_text("\n[on_tool_error] Error: " + str(error) + "\n", color="red") - def on_agent_start(self, thought: str) -> None: + def on_agent_start(self, thought: str): """Run on agent start.""" if dify_config.DEBUG: if thought: @@ -98,7 +98,7 @@ class DifyAgentCallbackHandler(BaseModel): else: print_text("\n[on_agent_start] \nCurrent Loop: " + str(self.current_loop) + "\n", color=self.color) - def on_agent_finish(self, color: Optional[str] = None, **kwargs: Any) -> None: + def on_agent_finish(self, color: Optional[str] = None, **kwargs: Any): """Run on agent end.""" if dify_config.DEBUG: print_text("\n[on_agent_finish]\n Loop: " + str(self.current_loop) + "\n", color=self.color) diff --git a/api/core/callback_handler/index_tool_callback_handler.py b/api/core/callback_handler/index_tool_callback_handler.py index c85d2d5995..14d5f38dcd 100644 --- a/api/core/callback_handler/index_tool_callback_handler.py +++ b/api/core/callback_handler/index_tool_callback_handler.py @@ -21,14 +21,14 @@ class DatasetIndexToolCallbackHandler: def __init__( self, queue_manager: AppQueueManager, app_id: str, message_id: str, user_id: str, invoke_from: InvokeFrom - ) -> None: + ): self._queue_manager = queue_manager self._app_id = app_id self._message_id = message_id self._user_id = user_id self._invoke_from = invoke_from - def on_query(self, query: str, dataset_id: str) -> None: + def on_query(self, query: str, dataset_id: str): """ Handle query. """ @@ -46,7 +46,7 @@ class DatasetIndexToolCallbackHandler: db.session.add(dataset_query) db.session.commit() - def on_tool_end(self, documents: list[Document]) -> None: + def on_tool_end(self, documents: list[Document]): """Handle tool end.""" for document in documents: if document.metadata is not None: diff --git a/api/core/entities/model_entities.py b/api/core/entities/model_entities.py index ac64a8e3a0..0fd49b059c 100644 --- a/api/core/entities/model_entities.py +++ b/api/core/entities/model_entities.py @@ -33,7 +33,7 @@ class SimpleModelProviderEntity(BaseModel): icon_large: Optional[I18nObject] = None supported_model_types: list[ModelType] - def __init__(self, provider_entity: ProviderEntity) -> None: + def __init__(self, provider_entity: ProviderEntity): """ Init simple provider. @@ -57,7 +57,7 @@ class ProviderModelWithStatusEntity(ProviderModel): load_balancing_enabled: bool = False has_invalid_load_balancing_configs: bool = False - def raise_for_status(self) -> None: + def raise_for_status(self): """ Check model status and raise ValueError if not active. diff --git a/api/core/entities/provider_configuration.py b/api/core/entities/provider_configuration.py index 9119462aca..61a960c3d4 100644 --- a/api/core/entities/provider_configuration.py +++ b/api/core/entities/provider_configuration.py @@ -280,9 +280,7 @@ class ProviderConfiguration(BaseModel): else [], ) - def validate_provider_credentials( - self, credentials: dict, credential_id: str = "", session: Session | None = None - ) -> dict: + def validate_provider_credentials(self, credentials: dict, credential_id: str = "", session: Session | None = None): """ Validate custom credentials. :param credentials: provider credentials @@ -291,7 +289,7 @@ class ProviderConfiguration(BaseModel): :return: """ - def _validate(s: Session) -> dict: + def _validate(s: Session): # Get provider credential secret variables provider_credential_secret_variables = self.extract_secret_variables( self.provider.provider_credential_schema.credential_form_schemas @@ -402,7 +400,7 @@ class ProviderConfiguration(BaseModel): logger.warning("Error generating next credential name: %s", str(e)) return "API KEY 1" - def create_provider_credential(self, credentials: dict, credential_name: str | None) -> None: + def create_provider_credential(self, credentials: dict, credential_name: str | None): """ Add custom provider credentials. :param credentials: provider credentials @@ -458,7 +456,7 @@ class ProviderConfiguration(BaseModel): credentials: dict, credential_id: str, credential_name: str | None, - ) -> None: + ): """ update a saved provider credential (by credential_id). @@ -519,7 +517,7 @@ class ProviderConfiguration(BaseModel): credential_record: ProviderCredential | ProviderModelCredential, credential_source: str, session: Session, - ) -> None: + ): """ Update load balancing configurations that reference the given credential_id. @@ -559,7 +557,7 @@ class ProviderConfiguration(BaseModel): session.commit() - def delete_provider_credential(self, credential_id: str) -> None: + def delete_provider_credential(self, credential_id: str): """ Delete a saved provider credential (by credential_id). @@ -636,7 +634,7 @@ class ProviderConfiguration(BaseModel): session.rollback() raise - def switch_active_provider_credential(self, credential_id: str) -> None: + def switch_active_provider_credential(self, credential_id: str): """ Switch active provider credential (copy the selected one into current active snapshot). @@ -814,7 +812,7 @@ class ProviderConfiguration(BaseModel): credentials: dict, credential_id: str = "", session: Session | None = None, - ) -> dict: + ): """ Validate custom model credentials. @@ -825,7 +823,7 @@ class ProviderConfiguration(BaseModel): :return: """ - def _validate(s: Session) -> dict: + def _validate(s: Session): # Get provider credential secret variables provider_credential_secret_variables = self.extract_secret_variables( self.provider.model_credential_schema.credential_form_schemas @@ -1009,7 +1007,7 @@ class ProviderConfiguration(BaseModel): session.rollback() raise - def delete_custom_model_credential(self, model_type: ModelType, model: str, credential_id: str) -> None: + def delete_custom_model_credential(self, model_type: ModelType, model: str, credential_id: str): """ Delete a saved provider credential (by credential_id). @@ -1079,7 +1077,7 @@ class ProviderConfiguration(BaseModel): session.rollback() raise - def add_model_credential_to_model(self, model_type: ModelType, model: str, credential_id: str) -> None: + def add_model_credential_to_model(self, model_type: ModelType, model: str, credential_id: str): """ if model list exist this custom model, switch the custom model credential. if model list not exist this custom model, use the credential to add a new custom model record. @@ -1122,7 +1120,7 @@ class ProviderConfiguration(BaseModel): session.add(provider_model_record) session.commit() - def switch_custom_model_credential(self, model_type: ModelType, model: str, credential_id: str) -> None: + def switch_custom_model_credential(self, model_type: ModelType, model: str, credential_id: str): """ switch the custom model credential. @@ -1152,7 +1150,7 @@ class ProviderConfiguration(BaseModel): session.add(provider_model_record) session.commit() - def delete_custom_model(self, model_type: ModelType, model: str) -> None: + def delete_custom_model(self, model_type: ModelType, model: str): """ Delete custom model. :param model_type: model type @@ -1347,7 +1345,7 @@ class ProviderConfiguration(BaseModel): provider=self.provider.provider, model_type=model_type, model=model, credentials=credentials ) - def switch_preferred_provider_type(self, provider_type: ProviderType, session: Session | None = None) -> None: + def switch_preferred_provider_type(self, provider_type: ProviderType, session: Session | None = None): """ Switch preferred provider type. :param provider_type: @@ -1359,7 +1357,7 @@ class ProviderConfiguration(BaseModel): if provider_type == ProviderType.SYSTEM and not self.system_configuration.enabled: return - def _switch(s: Session) -> None: + def _switch(s: Session): # get preferred provider model_provider_id = ModelProviderID(self.provider.provider) provider_names = [self.provider.provider] @@ -1403,7 +1401,7 @@ class ProviderConfiguration(BaseModel): return secret_input_form_variables - def obfuscated_credentials(self, credentials: dict, credential_form_schemas: list[CredentialFormSchema]) -> dict: + def obfuscated_credentials(self, credentials: dict, credential_form_schemas: list[CredentialFormSchema]): """ Obfuscated credentials. diff --git a/api/core/errors/error.py b/api/core/errors/error.py index ad921bc255..642f24a411 100644 --- a/api/core/errors/error.py +++ b/api/core/errors/error.py @@ -6,7 +6,7 @@ class LLMError(ValueError): description: Optional[str] = None - def __init__(self, description: Optional[str] = None) -> None: + def __init__(self, description: Optional[str] = None): self.description = description diff --git a/api/core/extension/api_based_extension_requestor.py b/api/core/extension/api_based_extension_requestor.py index 4423299f70..fab9ae44e9 100644 --- a/api/core/extension/api_based_extension_requestor.py +++ b/api/core/extension/api_based_extension_requestor.py @@ -10,11 +10,11 @@ class APIBasedExtensionRequestor: timeout: tuple[int, int] = (5, 60) """timeout for request connect and read""" - def __init__(self, api_endpoint: str, api_key: str) -> None: + def __init__(self, api_endpoint: str, api_key: str): self.api_endpoint = api_endpoint self.api_key = api_key - def request(self, point: APIBasedExtensionPoint, params: dict) -> dict: + def request(self, point: APIBasedExtensionPoint, params: dict): """ Request the api. diff --git a/api/core/extension/extensible.py b/api/core/extension/extensible.py index 1c4fa60ab4..eee914a529 100644 --- a/api/core/extension/extensible.py +++ b/api/core/extension/extensible.py @@ -34,7 +34,7 @@ class Extensible: tenant_id: str config: Optional[dict] = None - def __init__(self, tenant_id: str, config: Optional[dict] = None) -> None: + def __init__(self, tenant_id: str, config: Optional[dict] = None): self.tenant_id = tenant_id self.config = config diff --git a/api/core/external_data_tool/api/api.py b/api/core/external_data_tool/api/api.py index 2100e7fadc..45878e763f 100644 --- a/api/core/external_data_tool/api/api.py +++ b/api/core/external_data_tool/api/api.py @@ -18,7 +18,7 @@ class ApiExternalDataTool(ExternalDataTool): """the unique name of external data tool""" @classmethod - def validate_config(cls, tenant_id: str, config: dict) -> None: + def validate_config(cls, tenant_id: str, config: dict): """ Validate the incoming form config data. diff --git a/api/core/external_data_tool/base.py b/api/core/external_data_tool/base.py index 0db736f096..81f1aaf174 100644 --- a/api/core/external_data_tool/base.py +++ b/api/core/external_data_tool/base.py @@ -16,14 +16,14 @@ class ExternalDataTool(Extensible, ABC): variable: str """the tool variable name of app tool""" - def __init__(self, tenant_id: str, app_id: str, variable: str, config: Optional[dict] = None) -> None: + def __init__(self, tenant_id: str, app_id: str, variable: str, config: Optional[dict] = None): super().__init__(tenant_id, config) self.app_id = app_id self.variable = variable @classmethod @abstractmethod - def validate_config(cls, tenant_id: str, config: dict) -> None: + def validate_config(cls, tenant_id: str, config: dict): """ Validate the incoming form config data. diff --git a/api/core/external_data_tool/factory.py b/api/core/external_data_tool/factory.py index 75a638acb1..538bc3f525 100644 --- a/api/core/external_data_tool/factory.py +++ b/api/core/external_data_tool/factory.py @@ -6,14 +6,14 @@ from extensions.ext_code_based_extension import code_based_extension class ExternalDataToolFactory: - def __init__(self, name: str, tenant_id: str, app_id: str, variable: str, config: dict) -> None: + def __init__(self, name: str, tenant_id: str, app_id: str, variable: str, config: dict): extension_class = code_based_extension.extension_class(ExtensionModule.EXTERNAL_DATA_TOOL, name) self.__extension_instance = extension_class( tenant_id=tenant_id, app_id=app_id, variable=variable, config=config ) @classmethod - def validate_config(cls, name: str, tenant_id: str, config: dict) -> None: + def validate_config(cls, name: str, tenant_id: str, config: dict): """ Validate the incoming form config data. diff --git a/api/core/file/tool_file_parser.py b/api/core/file/tool_file_parser.py index fac68beb0f..4c8e7282b8 100644 --- a/api/core/file/tool_file_parser.py +++ b/api/core/file/tool_file_parser.py @@ -7,6 +7,6 @@ if TYPE_CHECKING: _tool_file_manager_factory: Callable[[], "ToolFileManager"] | None = None -def set_tool_file_manager_factory(factory: Callable[[], "ToolFileManager"]) -> None: +def set_tool_file_manager_factory(factory: Callable[[], "ToolFileManager"]): global _tool_file_manager_factory _tool_file_manager_factory = factory diff --git a/api/core/helper/code_executor/code_node_provider.py b/api/core/helper/code_executor/code_node_provider.py index e233a596b9..701208080c 100644 --- a/api/core/helper/code_executor/code_node_provider.py +++ b/api/core/helper/code_executor/code_node_provider.py @@ -22,7 +22,7 @@ class CodeNodeProvider(BaseModel): pass @classmethod - def get_default_config(cls) -> dict: + def get_default_config(cls): return { "type": "code", "config": { diff --git a/api/core/helper/code_executor/jinja2/jinja2_transformer.py b/api/core/helper/code_executor/jinja2/jinja2_transformer.py index 54c78cdf92..969125d2f7 100644 --- a/api/core/helper/code_executor/jinja2/jinja2_transformer.py +++ b/api/core/helper/code_executor/jinja2/jinja2_transformer.py @@ -5,7 +5,7 @@ from core.helper.code_executor.template_transformer import TemplateTransformer class Jinja2TemplateTransformer(TemplateTransformer): @classmethod - def transform_response(cls, response: str) -> dict: + def transform_response(cls, response: str): """ Transform response to dict :param response: response diff --git a/api/core/helper/code_executor/python3/python3_code_provider.py b/api/core/helper/code_executor/python3/python3_code_provider.py index 9cca8af7c6..151bf0e201 100644 --- a/api/core/helper/code_executor/python3/python3_code_provider.py +++ b/api/core/helper/code_executor/python3/python3_code_provider.py @@ -13,7 +13,7 @@ class Python3CodeProvider(CodeNodeProvider): def get_default_code(cls) -> str: return dedent( """ - def main(arg1: str, arg2: str) -> dict: + def main(arg1: str, arg2: str): return { "result": arg1 + arg2, } diff --git a/api/core/helper/model_provider_cache.py b/api/core/helper/model_provider_cache.py index 35349210bd..1c112007cb 100644 --- a/api/core/helper/model_provider_cache.py +++ b/api/core/helper/model_provider_cache.py @@ -34,7 +34,7 @@ class ProviderCredentialsCache: else: return None - def set(self, credentials: dict) -> None: + def set(self, credentials: dict): """ Cache model provider credentials. @@ -43,7 +43,7 @@ class ProviderCredentialsCache: """ redis_client.setex(self.cache_key, 86400, json.dumps(credentials)) - def delete(self) -> None: + def delete(self): """ Delete cached model provider credentials. diff --git a/api/core/helper/provider_cache.py b/api/core/helper/provider_cache.py index 48ec3be5c8..26e738fced 100644 --- a/api/core/helper/provider_cache.py +++ b/api/core/helper/provider_cache.py @@ -28,11 +28,11 @@ class ProviderCredentialsCache(ABC): return None return None - def set(self, config: dict[str, Any]) -> None: + def set(self, config: dict[str, Any]): """Cache provider credentials""" redis_client.setex(self.cache_key, 86400, json.dumps(config)) - def delete(self) -> None: + def delete(self): """Delete cached provider credentials""" redis_client.delete(self.cache_key) @@ -75,10 +75,10 @@ class NoOpProviderCredentialCache: """Get cached provider credentials""" return None - def set(self, config: dict[str, Any]) -> None: + def set(self, config: dict[str, Any]): """Cache provider credentials""" pass - def delete(self) -> None: + def delete(self): """Delete cached provider credentials""" pass diff --git a/api/core/helper/tool_parameter_cache.py b/api/core/helper/tool_parameter_cache.py index 918b3e9eee..95a1086ca8 100644 --- a/api/core/helper/tool_parameter_cache.py +++ b/api/core/helper/tool_parameter_cache.py @@ -37,11 +37,11 @@ class ToolParameterCache: else: return None - def set(self, parameters: dict) -> None: + def set(self, parameters: dict): """Cache model provider credentials.""" redis_client.setex(self.cache_key, 86400, json.dumps(parameters)) - def delete(self) -> None: + def delete(self): """ Delete cached model provider credentials. diff --git a/api/core/helper/trace_id_helper.py b/api/core/helper/trace_id_helper.py index 5cd0ea5c66..35e6e292d1 100644 --- a/api/core/helper/trace_id_helper.py +++ b/api/core/helper/trace_id_helper.py @@ -49,7 +49,7 @@ def get_external_trace_id(request: Any) -> Optional[str]: return None -def extract_external_trace_id_from_args(args: Mapping[str, Any]) -> dict: +def extract_external_trace_id_from_args(args: Mapping[str, Any]): """ Extract 'external_trace_id' from args. diff --git a/api/core/hosting_configuration.py b/api/core/hosting_configuration.py index 20d98562de..a5d7f7aac7 100644 --- a/api/core/hosting_configuration.py +++ b/api/core/hosting_configuration.py @@ -44,11 +44,11 @@ class HostingConfiguration: provider_map: dict[str, HostingProvider] moderation_config: Optional[HostedModerationConfig] = None - def __init__(self) -> None: + def __init__(self): self.provider_map = {} self.moderation_config = None - def init_app(self, app: Flask) -> None: + def init_app(self, app: Flask): if dify_config.EDITION != "CLOUD": return diff --git a/api/core/indexing_runner.py b/api/core/indexing_runner.py index 37eb3eab60..89a05e02c8 100644 --- a/api/core/indexing_runner.py +++ b/api/core/indexing_runner.py @@ -512,7 +512,7 @@ class IndexingRunner: dataset: Dataset, dataset_document: DatasetDocument, documents: list[Document], - ) -> None: + ): """ insert index and update document/segment status to completed """ @@ -651,7 +651,7 @@ class IndexingRunner: @staticmethod def _update_document_index_status( document_id: str, after_indexing_status: str, extra_update_params: Optional[dict] = None - ) -> None: + ): """ Update the document indexing status. """ @@ -670,7 +670,7 @@ class IndexingRunner: db.session.commit() @staticmethod - def _update_segments_by_document(dataset_document_id: str, update_params: dict) -> None: + def _update_segments_by_document(dataset_document_id: str, update_params: dict): """ Update the document segment by document id. """ diff --git a/api/core/llm_generator/llm_generator.py b/api/core/llm_generator/llm_generator.py index 894f090c1b..94b8258e9c 100644 --- a/api/core/llm_generator/llm_generator.py +++ b/api/core/llm_generator/llm_generator.py @@ -127,7 +127,7 @@ class LLMGenerator: return questions @classmethod - def generate_rule_config(cls, tenant_id: str, instruction: str, model_config: dict, no_variable: bool) -> dict: + def generate_rule_config(cls, tenant_id: str, instruction: str, model_config: dict, no_variable: bool): output_parser = RuleConfigGeneratorOutputParser() error = "" @@ -262,9 +262,7 @@ class LLMGenerator: return rule_config @classmethod - def generate_code( - cls, tenant_id: str, instruction: str, model_config: dict, code_language: str = "javascript" - ) -> dict: + def generate_code(cls, tenant_id: str, instruction: str, model_config: dict, code_language: str = "javascript"): if code_language == "python": prompt_template = PromptTemplateParser(PYTHON_CODE_GENERATOR_PROMPT_TEMPLATE) else: @@ -373,7 +371,7 @@ class LLMGenerator: @staticmethod def instruction_modify_legacy( tenant_id: str, flow_id: str, current: str, instruction: str, model_config: dict, ideal_output: str | None - ) -> dict: + ): last_run: Message | None = ( db.session.query(Message).where(Message.app_id == flow_id).order_by(Message.created_at.desc()).first() ) @@ -413,7 +411,7 @@ class LLMGenerator: instruction: str, model_config: dict, ideal_output: str | None, - ) -> dict: + ): from services.workflow_service import WorkflowService app: App | None = db.session.query(App).where(App.id == flow_id).first() @@ -451,7 +449,7 @@ class LLMGenerator: return [] parsed: Sequence[AgentLogEvent] = json.loads(raw_agent_log) - def dict_of_event(event: AgentLogEvent) -> dict: + def dict_of_event(event: AgentLogEvent): return { "status": event.status, "error": event.error, @@ -488,7 +486,7 @@ class LLMGenerator: instruction: str, node_type: str, ideal_output: str | None, - ) -> dict: + ): LAST_RUN = "{{#last_run#}}" CURRENT = "{{#current#}}" ERROR_MESSAGE = "{{#error_message#}}" diff --git a/api/core/llm_generator/output_parser/rule_config_generator.py b/api/core/llm_generator/output_parser/rule_config_generator.py index 0c7683b16d..95fc6dbec6 100644 --- a/api/core/llm_generator/output_parser/rule_config_generator.py +++ b/api/core/llm_generator/output_parser/rule_config_generator.py @@ -1,5 +1,3 @@ -from typing import Any - from core.llm_generator.output_parser.errors import OutputParserError from core.llm_generator.prompts import ( RULE_CONFIG_PARAMETER_GENERATE_TEMPLATE, @@ -17,7 +15,7 @@ class RuleConfigGeneratorOutputParser: RULE_CONFIG_STATEMENT_GENERATE_TEMPLATE, ) - def parse(self, text: str) -> Any: + def parse(self, text: str): try: expected_keys = ["prompt", "variables", "opening_statement"] parsed = parse_and_check_json_markdown(text, expected_keys) diff --git a/api/core/llm_generator/output_parser/structured_output.py b/api/core/llm_generator/output_parser/structured_output.py index 151cef1bc3..28833fe8e8 100644 --- a/api/core/llm_generator/output_parser/structured_output.py +++ b/api/core/llm_generator/output_parser/structured_output.py @@ -210,7 +210,7 @@ def _handle_native_json_schema( structured_output_schema: Mapping, model_parameters: dict, rules: list[ParameterRule], -) -> dict: +): """ Handle structured output for models with native JSON schema support. @@ -232,7 +232,7 @@ def _handle_native_json_schema( return model_parameters -def _set_response_format(model_parameters: dict, rules: list) -> None: +def _set_response_format(model_parameters: dict, rules: list): """ Set the appropriate response format parameter based on model rules. @@ -306,7 +306,7 @@ def _parse_structured_output(result_text: str) -> Mapping[str, Any]: return structured_output -def _prepare_schema_for_model(provider: str, model_schema: AIModelEntity, schema: Mapping) -> dict: +def _prepare_schema_for_model(provider: str, model_schema: AIModelEntity, schema: Mapping): """ Prepare JSON schema based on model requirements. @@ -334,7 +334,7 @@ def _prepare_schema_for_model(provider: str, model_schema: AIModelEntity, schema return {"schema": processed_schema, "name": "llm_response"} -def remove_additional_properties(schema: dict) -> None: +def remove_additional_properties(schema: dict): """ Remove additionalProperties fields from JSON schema. Used for models like Gemini that don't support this property. @@ -357,7 +357,7 @@ def remove_additional_properties(schema: dict) -> None: remove_additional_properties(item) -def convert_boolean_to_string(schema: dict) -> None: +def convert_boolean_to_string(schema: dict): """ Convert boolean type specifications to string in JSON schema. diff --git a/api/core/llm_generator/output_parser/suggested_questions_after_answer.py b/api/core/llm_generator/output_parser/suggested_questions_after_answer.py index 98cdc4c8b7..e78859cc1a 100644 --- a/api/core/llm_generator/output_parser/suggested_questions_after_answer.py +++ b/api/core/llm_generator/output_parser/suggested_questions_after_answer.py @@ -1,6 +1,5 @@ import json import re -from typing import Any from core.llm_generator.prompts import SUGGESTED_QUESTIONS_AFTER_ANSWER_INSTRUCTION_PROMPT @@ -9,7 +8,7 @@ class SuggestedQuestionsAfterAnswerOutputParser: def get_format_instructions(self) -> str: return SUGGESTED_QUESTIONS_AFTER_ANSWER_INSTRUCTION_PROMPT - def parse(self, text: str) -> Any: + def parse(self, text: str): action_match = re.search(r"\[.*?\]", text.strip(), re.DOTALL) if action_match is not None: json_obj = json.loads(action_match.group(0).strip()) diff --git a/api/core/mcp/auth/auth_provider.py b/api/core/mcp/auth/auth_provider.py index bad99fc092..bf1820f744 100644 --- a/api/core/mcp/auth/auth_provider.py +++ b/api/core/mcp/auth/auth_provider.py @@ -44,7 +44,7 @@ class OAuthClientProvider: return None return OAuthClientInformation.model_validate(client_information) - def save_client_information(self, client_information: OAuthClientInformationFull) -> None: + def save_client_information(self, client_information: OAuthClientInformationFull): """Saves client information after dynamic registration.""" MCPToolManageService.update_mcp_provider_credentials( self.mcp_provider, @@ -63,13 +63,13 @@ class OAuthClientProvider: refresh_token=credentials.get("refresh_token", ""), ) - def save_tokens(self, tokens: OAuthTokens) -> None: + def save_tokens(self, tokens: OAuthTokens): """Stores new OAuth tokens for the current session.""" # update mcp provider credentials token_dict = tokens.model_dump() MCPToolManageService.update_mcp_provider_credentials(self.mcp_provider, token_dict, authed=True) - def save_code_verifier(self, code_verifier: str) -> None: + def save_code_verifier(self, code_verifier: str): """Saves a PKCE code verifier for the current session.""" MCPToolManageService.update_mcp_provider_credentials(self.mcp_provider, {"code_verifier": code_verifier}) diff --git a/api/core/mcp/client/sse_client.py b/api/core/mcp/client/sse_client.py index cc38954eca..cc4263c0aa 100644 --- a/api/core/mcp/client/sse_client.py +++ b/api/core/mcp/client/sse_client.py @@ -47,7 +47,7 @@ class SSETransport: headers: dict[str, Any] | None = None, timeout: float = 5.0, sse_read_timeout: float = 5 * 60, - ) -> None: + ): """Initialize the SSE transport. Args: @@ -76,7 +76,7 @@ class SSETransport: return url_parsed.netloc == endpoint_parsed.netloc and url_parsed.scheme == endpoint_parsed.scheme - def _handle_endpoint_event(self, sse_data: str, status_queue: StatusQueue) -> None: + def _handle_endpoint_event(self, sse_data: str, status_queue: StatusQueue): """Handle an 'endpoint' SSE event. Args: @@ -94,7 +94,7 @@ class SSETransport: status_queue.put(_StatusReady(endpoint_url)) - def _handle_message_event(self, sse_data: str, read_queue: ReadQueue) -> None: + def _handle_message_event(self, sse_data: str, read_queue: ReadQueue): """Handle a 'message' SSE event. Args: @@ -110,7 +110,7 @@ class SSETransport: logger.exception("Error parsing server message") read_queue.put(exc) - def _handle_sse_event(self, sse: ServerSentEvent, read_queue: ReadQueue, status_queue: StatusQueue) -> None: + def _handle_sse_event(self, sse: ServerSentEvent, read_queue: ReadQueue, status_queue: StatusQueue): """Handle a single SSE event. Args: @@ -126,7 +126,7 @@ class SSETransport: case _: logger.warning("Unknown SSE event: %s", sse.event) - def sse_reader(self, event_source: EventSource, read_queue: ReadQueue, status_queue: StatusQueue) -> None: + def sse_reader(self, event_source: EventSource, read_queue: ReadQueue, status_queue: StatusQueue): """Read and process SSE events. Args: @@ -144,7 +144,7 @@ class SSETransport: finally: read_queue.put(None) - def _send_message(self, client: httpx.Client, endpoint_url: str, message: SessionMessage) -> None: + def _send_message(self, client: httpx.Client, endpoint_url: str, message: SessionMessage): """Send a single message to the server. Args: @@ -163,7 +163,7 @@ class SSETransport: response.raise_for_status() logger.debug("Client message sent successfully: %s", response.status_code) - def post_writer(self, client: httpx.Client, endpoint_url: str, write_queue: WriteQueue) -> None: + def post_writer(self, client: httpx.Client, endpoint_url: str, write_queue: WriteQueue): """Handle writing messages to the server. Args: @@ -303,7 +303,7 @@ def sse_client( write_queue.put(None) -def send_message(http_client: httpx.Client, endpoint_url: str, session_message: SessionMessage) -> None: +def send_message(http_client: httpx.Client, endpoint_url: str, session_message: SessionMessage): """ Send a message to the server using the provided HTTP client. diff --git a/api/core/mcp/client/streamable_client.py b/api/core/mcp/client/streamable_client.py index a2b003e717..7eafa79837 100644 --- a/api/core/mcp/client/streamable_client.py +++ b/api/core/mcp/client/streamable_client.py @@ -82,7 +82,7 @@ class StreamableHTTPTransport: headers: dict[str, Any] | None = None, timeout: float | timedelta = 30, sse_read_timeout: float | timedelta = 60 * 5, - ) -> None: + ): """Initialize the StreamableHTTP transport. Args: @@ -122,7 +122,7 @@ class StreamableHTTPTransport: def _maybe_extract_session_id_from_response( self, response: httpx.Response, - ) -> None: + ): """Extract and store session ID from response headers.""" new_session_id = response.headers.get(MCP_SESSION_ID) if new_session_id: @@ -173,7 +173,7 @@ class StreamableHTTPTransport: self, client: httpx.Client, server_to_client_queue: ServerToClientQueue, - ) -> None: + ): """Handle GET stream for server-initiated messages.""" try: if not self.session_id: @@ -197,7 +197,7 @@ class StreamableHTTPTransport: except Exception as exc: logger.debug("GET stream error (non-fatal): %s", exc) - def _handle_resumption_request(self, ctx: RequestContext) -> None: + def _handle_resumption_request(self, ctx: RequestContext): """Handle a resumption request using GET with SSE.""" headers = self._update_headers_with_session(ctx.headers) if ctx.metadata and ctx.metadata.resumption_token: @@ -230,7 +230,7 @@ class StreamableHTTPTransport: if is_complete: break - def _handle_post_request(self, ctx: RequestContext) -> None: + def _handle_post_request(self, ctx: RequestContext): """Handle a POST request with response processing.""" headers = self._update_headers_with_session(ctx.headers) message = ctx.session_message.message @@ -278,7 +278,7 @@ class StreamableHTTPTransport: self, response: httpx.Response, server_to_client_queue: ServerToClientQueue, - ) -> None: + ): """Handle JSON response from the server.""" try: content = response.read() @@ -288,7 +288,7 @@ class StreamableHTTPTransport: except Exception as exc: server_to_client_queue.put(exc) - def _handle_sse_response(self, response: httpx.Response, ctx: RequestContext) -> None: + def _handle_sse_response(self, response: httpx.Response, ctx: RequestContext): """Handle SSE response from the server.""" try: event_source = EventSource(response) @@ -307,7 +307,7 @@ class StreamableHTTPTransport: self, content_type: str, server_to_client_queue: ServerToClientQueue, - ) -> None: + ): """Handle unexpected content type in response.""" error_msg = f"Unexpected content type: {content_type}" logger.error(error_msg) @@ -317,7 +317,7 @@ class StreamableHTTPTransport: self, server_to_client_queue: ServerToClientQueue, request_id: RequestId, - ) -> None: + ): """Send a session terminated error response.""" jsonrpc_error = JSONRPCError( jsonrpc="2.0", @@ -333,7 +333,7 @@ class StreamableHTTPTransport: client_to_server_queue: ClientToServerQueue, server_to_client_queue: ServerToClientQueue, start_get_stream: Callable[[], None], - ) -> None: + ): """Handle writing requests to the server. This method processes messages from the client_to_server_queue and sends them to the server. @@ -379,7 +379,7 @@ class StreamableHTTPTransport: except Exception as exc: server_to_client_queue.put(exc) - def terminate_session(self, client: httpx.Client) -> None: + def terminate_session(self, client: httpx.Client): """Terminate the session by sending a DELETE request.""" if not self.session_id: return @@ -441,7 +441,7 @@ def streamablehttp_client( timeout=httpx.Timeout(transport.timeout, read=transport.sse_read_timeout), ) as client: # Define callbacks that need access to thread pool - def start_get_stream() -> None: + def start_get_stream(): """Start a worker thread to handle server-initiated messages.""" executor.submit(transport.handle_get_stream, client, server_to_client_queue) diff --git a/api/core/mcp/session/base_session.py b/api/core/mcp/session/base_session.py index 1bd533581d..96c48034c7 100644 --- a/api/core/mcp/session/base_session.py +++ b/api/core/mcp/session/base_session.py @@ -76,7 +76,7 @@ class RequestResponder(Generic[ReceiveRequestT, SendResultT]): ReceiveNotificationT ]""", on_complete: Callable[["RequestResponder[ReceiveRequestT, SendResultT]"], Any], - ) -> None: + ): self.request_id = request_id self.request_meta = request_meta self.request = request @@ -95,7 +95,7 @@ class RequestResponder(Generic[ReceiveRequestT, SendResultT]): exc_type: type[BaseException] | None, exc_val: BaseException | None, exc_tb: TracebackType | None, - ) -> None: + ): """Exit the context manager, performing cleanup and notifying completion.""" try: if self._completed: @@ -103,7 +103,7 @@ class RequestResponder(Generic[ReceiveRequestT, SendResultT]): finally: self._entered = False - def respond(self, response: SendResultT | ErrorData) -> None: + def respond(self, response: SendResultT | ErrorData): """Send a response for this request. Must be called within a context manager block. @@ -119,7 +119,7 @@ class RequestResponder(Generic[ReceiveRequestT, SendResultT]): self._session._send_response(request_id=self.request_id, response=response) - def cancel(self) -> None: + def cancel(self): """Cancel this request and mark it as completed.""" if not self._entered: raise RuntimeError("RequestResponder must be used as a context manager") @@ -163,7 +163,7 @@ class BaseSession( receive_notification_type: type[ReceiveNotificationT], # If none, reading will never time out read_timeout_seconds: timedelta | None = None, - ) -> None: + ): self._read_stream = read_stream self._write_stream = write_stream self._response_streams = {} @@ -183,7 +183,7 @@ class BaseSession( self._receiver_future = self._executor.submit(self._receive_loop) return self - def check_receiver_status(self) -> None: + def check_receiver_status(self): """`check_receiver_status` ensures that any exceptions raised during the execution of `_receive_loop` are retrieved and propagated.""" if self._receiver_future and self._receiver_future.done(): @@ -191,7 +191,7 @@ class BaseSession( def __exit__( self, exc_type: type[BaseException] | None, exc_val: BaseException | None, exc_tb: TracebackType | None - ) -> None: + ): self._read_stream.put(None) self._write_stream.put(None) @@ -277,7 +277,7 @@ class BaseSession( self, notification: SendNotificationT, related_request_id: RequestId | None = None, - ) -> None: + ): """ Emits a notification, which is a one-way message that does not expect a response. @@ -296,7 +296,7 @@ class BaseSession( ) self._write_stream.put(session_message) - def _send_response(self, request_id: RequestId, response: SendResultT | ErrorData) -> None: + def _send_response(self, request_id: RequestId, response: SendResultT | ErrorData): if isinstance(response, ErrorData): jsonrpc_error = JSONRPCError(jsonrpc="2.0", id=request_id, error=response) session_message = SessionMessage(message=JSONRPCMessage(jsonrpc_error)) @@ -310,7 +310,7 @@ class BaseSession( session_message = SessionMessage(message=JSONRPCMessage(jsonrpc_response)) self._write_stream.put(session_message) - def _receive_loop(self) -> None: + def _receive_loop(self): """ Main message processing loop. In a real synchronous implementation, this would likely run in a separate thread. @@ -382,7 +382,7 @@ class BaseSession( logger.exception("Error in message processing loop") raise - def _received_request(self, responder: RequestResponder[ReceiveRequestT, SendResultT]) -> None: + def _received_request(self, responder: RequestResponder[ReceiveRequestT, SendResultT]): """ Can be overridden by subclasses to handle a request without needing to listen on the message stream. @@ -391,15 +391,13 @@ class BaseSession( forwarded on to the message stream. """ - def _received_notification(self, notification: ReceiveNotificationT) -> None: + def _received_notification(self, notification: ReceiveNotificationT): """ Can be overridden by subclasses to handle a notification without needing to listen on the message stream. """ - def send_progress_notification( - self, progress_token: str | int, progress: float, total: float | None = None - ) -> None: + def send_progress_notification(self, progress_token: str | int, progress: float, total: float | None = None): """ Sends a progress notification for a request that is currently being processed. @@ -408,5 +406,5 @@ class BaseSession( def _handle_incoming( self, req: RequestResponder[ReceiveRequestT, SendResultT] | ReceiveNotificationT | Exception, - ) -> None: + ): """A generic handler for incoming messages. Overwritten by subclasses.""" diff --git a/api/core/mcp/session/client_session.py b/api/core/mcp/session/client_session.py index 1bccf1d031..5817416ba4 100644 --- a/api/core/mcp/session/client_session.py +++ b/api/core/mcp/session/client_session.py @@ -28,19 +28,19 @@ class LoggingFnT(Protocol): def __call__( self, params: types.LoggingMessageNotificationParams, - ) -> None: ... + ): ... class MessageHandlerFnT(Protocol): def __call__( self, message: RequestResponder[types.ServerRequest, types.ClientResult] | types.ServerNotification | Exception, - ) -> None: ... + ): ... def _default_message_handler( message: RequestResponder[types.ServerRequest, types.ClientResult] | types.ServerNotification | Exception, -) -> None: +): if isinstance(message, Exception): raise ValueError(str(message)) elif isinstance(message, (types.ServerNotification | RequestResponder)): @@ -68,7 +68,7 @@ def _default_list_roots_callback( def _default_logging_callback( params: types.LoggingMessageNotificationParams, -) -> None: +): pass @@ -94,7 +94,7 @@ class ClientSession( logging_callback: LoggingFnT | None = None, message_handler: MessageHandlerFnT | None = None, client_info: types.Implementation | None = None, - ) -> None: + ): super().__init__( read_stream, write_stream, @@ -155,9 +155,7 @@ class ClientSession( types.EmptyResult, ) - def send_progress_notification( - self, progress_token: str | int, progress: float, total: float | None = None - ) -> None: + def send_progress_notification(self, progress_token: str | int, progress: float, total: float | None = None): """Send a progress notification.""" self.send_notification( types.ClientNotification( @@ -314,7 +312,7 @@ class ClientSession( types.ListToolsResult, ) - def send_roots_list_changed(self) -> None: + def send_roots_list_changed(self): """Send a roots/list_changed notification.""" self.send_notification( types.ClientNotification( @@ -324,7 +322,7 @@ class ClientSession( ) ) - def _received_request(self, responder: RequestResponder[types.ServerRequest, types.ClientResult]) -> None: + def _received_request(self, responder: RequestResponder[types.ServerRequest, types.ClientResult]): ctx = RequestContext[ClientSession, Any]( request_id=responder.request_id, meta=responder.request_meta, @@ -352,11 +350,11 @@ class ClientSession( def _handle_incoming( self, req: RequestResponder[types.ServerRequest, types.ClientResult] | types.ServerNotification | Exception, - ) -> None: + ): """Handle incoming messages by forwarding to the message handler.""" self._message_handler(req) - def _received_notification(self, notification: types.ServerNotification) -> None: + def _received_notification(self, notification: types.ServerNotification): """Handle notifications from the server.""" # Process specific notification types match notification.root: diff --git a/api/core/memory/token_buffer_memory.py b/api/core/memory/token_buffer_memory.py index 17050fcadf..f2178b0270 100644 --- a/api/core/memory/token_buffer_memory.py +++ b/api/core/memory/token_buffer_memory.py @@ -27,7 +27,7 @@ class TokenBufferMemory: self, conversation: Conversation, model_instance: ModelInstance, - ) -> None: + ): self.conversation = conversation self.model_instance = model_instance diff --git a/api/core/model_manager.py b/api/core/model_manager.py index e567565548..a59b0ae826 100644 --- a/api/core/model_manager.py +++ b/api/core/model_manager.py @@ -32,7 +32,7 @@ class ModelInstance: Model instance class """ - def __init__(self, provider_model_bundle: ProviderModelBundle, model: str) -> None: + def __init__(self, provider_model_bundle: ProviderModelBundle, model: str): self.provider_model_bundle = provider_model_bundle self.model = model self.provider = provider_model_bundle.configuration.provider.provider @@ -46,7 +46,7 @@ class ModelInstance: ) @staticmethod - def _fetch_credentials_from_bundle(provider_model_bundle: ProviderModelBundle, model: str) -> dict: + def _fetch_credentials_from_bundle(provider_model_bundle: ProviderModelBundle, model: str): """ Fetch credentials from provider model bundle :param provider_model_bundle: provider model bundle @@ -342,7 +342,7 @@ class ModelInstance: ), ) - def _round_robin_invoke(self, function: Callable[..., Any], *args, **kwargs) -> Any: + def _round_robin_invoke(self, function: Callable[..., Any], *args, **kwargs): """ Round-robin invoke :param function: function to invoke @@ -379,7 +379,7 @@ class ModelInstance: except Exception as e: raise e - def get_tts_voices(self, language: Optional[str] = None) -> list: + def get_tts_voices(self, language: Optional[str] = None): """ Invoke large language tts model voices @@ -394,7 +394,7 @@ class ModelInstance: class ModelManager: - def __init__(self) -> None: + def __init__(self): self._provider_manager = ProviderManager() def get_model_instance(self, tenant_id: str, provider: str, model_type: ModelType, model: str) -> ModelInstance: @@ -453,7 +453,7 @@ class LBModelManager: model: str, load_balancing_configs: list[ModelLoadBalancingConfiguration], managed_credentials: Optional[dict] = None, - ) -> None: + ): """ Load balancing model manager :param tenant_id: tenant_id @@ -534,7 +534,7 @@ model: %s""", return config - def cooldown(self, config: ModelLoadBalancingConfiguration, expire: int = 60) -> None: + def cooldown(self, config: ModelLoadBalancingConfiguration, expire: int = 60): """ Cooldown model load balancing config :param config: model load balancing config diff --git a/api/core/model_runtime/callbacks/base_callback.py b/api/core/model_runtime/callbacks/base_callback.py index 57cad17285..5ce4c23dbb 100644 --- a/api/core/model_runtime/callbacks/base_callback.py +++ b/api/core/model_runtime/callbacks/base_callback.py @@ -35,7 +35,7 @@ class Callback(ABC): stop: Optional[Sequence[str]] = None, stream: bool = True, user: Optional[str] = None, - ) -> None: + ): """ Before invoke callback @@ -94,7 +94,7 @@ class Callback(ABC): stop: Optional[Sequence[str]] = None, stream: bool = True, user: Optional[str] = None, - ) -> None: + ): """ After invoke callback @@ -124,7 +124,7 @@ class Callback(ABC): stop: Optional[Sequence[str]] = None, stream: bool = True, user: Optional[str] = None, - ) -> None: + ): """ Invoke error callback @@ -141,7 +141,7 @@ class Callback(ABC): """ raise NotImplementedError() - def print_text(self, text: str, color: Optional[str] = None, end: str = "") -> None: + def print_text(self, text: str, color: Optional[str] = None, end: str = ""): """Print text with highlighting and no end characters.""" text_to_print = self._get_colored_text(text, color) if color else text print(text_to_print, end=end) diff --git a/api/core/model_runtime/callbacks/logging_callback.py b/api/core/model_runtime/callbacks/logging_callback.py index 899f08195d..8411afca92 100644 --- a/api/core/model_runtime/callbacks/logging_callback.py +++ b/api/core/model_runtime/callbacks/logging_callback.py @@ -24,7 +24,7 @@ class LoggingCallback(Callback): stop: Optional[Sequence[str]] = None, stream: bool = True, user: Optional[str] = None, - ) -> None: + ): """ Before invoke callback @@ -110,7 +110,7 @@ class LoggingCallback(Callback): stop: Optional[Sequence[str]] = None, stream: bool = True, user: Optional[str] = None, - ) -> None: + ): """ After invoke callback @@ -151,7 +151,7 @@ class LoggingCallback(Callback): stop: Optional[Sequence[str]] = None, stream: bool = True, user: Optional[str] = None, - ) -> None: + ): """ Invoke error callback diff --git a/api/core/model_runtime/errors/invoke.py b/api/core/model_runtime/errors/invoke.py index 7675425361..6bcb707684 100644 --- a/api/core/model_runtime/errors/invoke.py +++ b/api/core/model_runtime/errors/invoke.py @@ -6,7 +6,7 @@ class InvokeError(ValueError): description: Optional[str] = None - def __init__(self, description: Optional[str] = None) -> None: + def __init__(self, description: Optional[str] = None): self.description = description def __str__(self): diff --git a/api/core/model_runtime/model_providers/__base/ai_model.py b/api/core/model_runtime/model_providers/__base/ai_model.py index 7d5ce1e47e..f41818e270 100644 --- a/api/core/model_runtime/model_providers/__base/ai_model.py +++ b/api/core/model_runtime/model_providers/__base/ai_model.py @@ -239,7 +239,7 @@ class AIModel(BaseModel): """ return None - def _get_default_parameter_rule_variable_map(self, name: DefaultParameterName) -> dict: + def _get_default_parameter_rule_variable_map(self, name: DefaultParameterName): """ Get default parameter rule for given name diff --git a/api/core/model_runtime/model_providers/__base/large_language_model.py b/api/core/model_runtime/model_providers/__base/large_language_model.py index ce378b443d..24b206fdbe 100644 --- a/api/core/model_runtime/model_providers/__base/large_language_model.py +++ b/api/core/model_runtime/model_providers/__base/large_language_model.py @@ -408,7 +408,7 @@ class LargeLanguageModel(AIModel): stream: bool = True, user: Optional[str] = None, callbacks: Optional[list[Callback]] = None, - ) -> None: + ): """ Trigger before invoke callbacks @@ -456,7 +456,7 @@ class LargeLanguageModel(AIModel): stream: bool = True, user: Optional[str] = None, callbacks: Optional[list[Callback]] = None, - ) -> None: + ): """ Trigger new chunk callbacks @@ -503,7 +503,7 @@ class LargeLanguageModel(AIModel): stream: bool = True, user: Optional[str] = None, callbacks: Optional[list[Callback]] = None, - ) -> None: + ): """ Trigger after invoke callbacks @@ -553,7 +553,7 @@ class LargeLanguageModel(AIModel): stream: bool = True, user: Optional[str] = None, callbacks: Optional[list[Callback]] = None, - ) -> None: + ): """ Trigger invoke error callbacks diff --git a/api/core/model_runtime/model_providers/__base/tokenizers/gpt2_tokenizer.py b/api/core/model_runtime/model_providers/__base/tokenizers/gpt2_tokenizer.py index cb740c1fd4..8f8a638af6 100644 --- a/api/core/model_runtime/model_providers/__base/tokenizers/gpt2_tokenizer.py +++ b/api/core/model_runtime/model_providers/__base/tokenizers/gpt2_tokenizer.py @@ -28,7 +28,7 @@ class GPT2Tokenizer: return GPT2Tokenizer._get_num_tokens_by_gpt2(text) @staticmethod - def get_encoder() -> Any: + def get_encoder(): global _tokenizer, _lock if _tokenizer is not None: return _tokenizer diff --git a/api/core/model_runtime/model_providers/__base/tts_model.py b/api/core/model_runtime/model_providers/__base/tts_model.py index d51831900c..9ee29f2f2f 100644 --- a/api/core/model_runtime/model_providers/__base/tts_model.py +++ b/api/core/model_runtime/model_providers/__base/tts_model.py @@ -56,7 +56,7 @@ class TTSModel(AIModel): except Exception as e: raise self._transform_invoke_error(e) - def get_tts_model_voices(self, model: str, credentials: dict, language: Optional[str] = None) -> list[dict]: + def get_tts_model_voices(self, model: str, credentials: dict, language: Optional[str] = None): """ Retrieves the list of voices supported by a given text-to-speech (TTS) model. diff --git a/api/core/model_runtime/model_providers/model_provider_factory.py b/api/core/model_runtime/model_providers/model_provider_factory.py index 24cf69a50b..6502b920f5 100644 --- a/api/core/model_runtime/model_providers/model_provider_factory.py +++ b/api/core/model_runtime/model_providers/model_provider_factory.py @@ -36,7 +36,7 @@ class ModelProviderExtension(BaseModel): class ModelProviderFactory: provider_position_map: dict[str, int] - def __init__(self, tenant_id: str) -> None: + def __init__(self, tenant_id: str): self.provider_position_map = {} self.tenant_id = tenant_id @@ -132,7 +132,7 @@ class ModelProviderFactory: return plugin_model_provider_entity - def provider_credentials_validate(self, *, provider: str, credentials: dict) -> dict: + def provider_credentials_validate(self, *, provider: str, credentials: dict): """ Validate provider credentials @@ -163,9 +163,7 @@ class ModelProviderFactory: return filtered_credentials - def model_credentials_validate( - self, *, provider: str, model_type: ModelType, model: str, credentials: dict - ) -> dict: + def model_credentials_validate(self, *, provider: str, model_type: ModelType, model: str, credentials: dict): """ Validate model credentials diff --git a/api/core/model_runtime/schema_validators/common_validator.py b/api/core/model_runtime/schema_validators/common_validator.py index b689007401..2caedeaf48 100644 --- a/api/core/model_runtime/schema_validators/common_validator.py +++ b/api/core/model_runtime/schema_validators/common_validator.py @@ -6,7 +6,7 @@ from core.model_runtime.entities.provider_entities import CredentialFormSchema, class CommonValidator: def _validate_and_filter_credential_form_schemas( self, credential_form_schemas: list[CredentialFormSchema], credentials: dict - ) -> dict: + ): need_validate_credential_form_schema_map = {} for credential_form_schema in credential_form_schemas: if not credential_form_schema.show_on: diff --git a/api/core/model_runtime/schema_validators/model_credential_schema_validator.py b/api/core/model_runtime/schema_validators/model_credential_schema_validator.py index 7d1644d134..0ac935ca31 100644 --- a/api/core/model_runtime/schema_validators/model_credential_schema_validator.py +++ b/api/core/model_runtime/schema_validators/model_credential_schema_validator.py @@ -8,7 +8,7 @@ class ModelCredentialSchemaValidator(CommonValidator): self.model_type = model_type self.model_credential_schema = model_credential_schema - def validate_and_filter(self, credentials: dict) -> dict: + def validate_and_filter(self, credentials: dict): """ Validate model credentials diff --git a/api/core/model_runtime/schema_validators/provider_credential_schema_validator.py b/api/core/model_runtime/schema_validators/provider_credential_schema_validator.py index 6dff2428ca..06350f92a9 100644 --- a/api/core/model_runtime/schema_validators/provider_credential_schema_validator.py +++ b/api/core/model_runtime/schema_validators/provider_credential_schema_validator.py @@ -6,7 +6,7 @@ class ProviderCredentialSchemaValidator(CommonValidator): def __init__(self, provider_credential_schema: ProviderCredentialSchema): self.provider_credential_schema = provider_credential_schema - def validate_and_filter(self, credentials: dict) -> dict: + def validate_and_filter(self, credentials: dict): """ Validate provider credentials diff --git a/api/core/model_runtime/utils/encoders.py b/api/core/model_runtime/utils/encoders.py index f65339fbfc..962e417671 100644 --- a/api/core/model_runtime/utils/encoders.py +++ b/api/core/model_runtime/utils/encoders.py @@ -18,7 +18,7 @@ from pydantic_core import Url from pydantic_extra_types.color import Color -def _model_dump(model: BaseModel, mode: Literal["json", "python"] = "json", **kwargs: Any) -> Any: +def _model_dump(model: BaseModel, mode: Literal["json", "python"] = "json", **kwargs: Any): return model.model_dump(mode=mode, **kwargs) @@ -100,7 +100,7 @@ def jsonable_encoder( exclude_none: bool = False, custom_encoder: Optional[dict[Any, Callable[[Any], Any]]] = None, sqlalchemy_safe: bool = True, -) -> Any: +): custom_encoder = custom_encoder or {} if custom_encoder: if type(obj) in custom_encoder: diff --git a/api/core/moderation/api/api.py b/api/core/moderation/api/api.py index 06d5c02bb8..ce7bd21110 100644 --- a/api/core/moderation/api/api.py +++ b/api/core/moderation/api/api.py @@ -25,7 +25,7 @@ class ApiModeration(Moderation): name: str = "api" @classmethod - def validate_config(cls, tenant_id: str, config: dict) -> None: + def validate_config(cls, tenant_id: str, config: dict): """ Validate the incoming form config data. @@ -75,7 +75,7 @@ class ApiModeration(Moderation): flagged=flagged, action=ModerationAction.DIRECT_OUTPUT, preset_response=preset_response ) - def _get_config_by_requestor(self, extension_point: APIBasedExtensionPoint, params: dict) -> dict: + def _get_config_by_requestor(self, extension_point: APIBasedExtensionPoint, params: dict): if self.config is None: raise ValueError("The config is not set.") extension = self._get_api_based_extension(self.tenant_id, self.config.get("api_based_extension_id", "")) diff --git a/api/core/moderation/base.py b/api/core/moderation/base.py index f079478798..752617b654 100644 --- a/api/core/moderation/base.py +++ b/api/core/moderation/base.py @@ -34,13 +34,13 @@ class Moderation(Extensible, ABC): module: ExtensionModule = ExtensionModule.MODERATION - def __init__(self, app_id: str, tenant_id: str, config: Optional[dict] = None) -> None: + def __init__(self, app_id: str, tenant_id: str, config: Optional[dict] = None): super().__init__(tenant_id, config) self.app_id = app_id @classmethod @abstractmethod - def validate_config(cls, tenant_id: str, config: dict) -> None: + def validate_config(cls, tenant_id: str, config: dict): """ Validate the incoming form config data. @@ -76,7 +76,7 @@ class Moderation(Extensible, ABC): raise NotImplementedError @classmethod - def _validate_inputs_and_outputs_config(cls, config: dict, is_preset_response_required: bool) -> None: + def _validate_inputs_and_outputs_config(cls, config: dict, is_preset_response_required: bool): # inputs_config inputs_config = config.get("inputs_config") if not isinstance(inputs_config, dict): diff --git a/api/core/moderation/factory.py b/api/core/moderation/factory.py index 9cda24d7a8..c2c8be6d6d 100644 --- a/api/core/moderation/factory.py +++ b/api/core/moderation/factory.py @@ -6,12 +6,12 @@ from extensions.ext_code_based_extension import code_based_extension class ModerationFactory: __extension_instance: Moderation - def __init__(self, name: str, app_id: str, tenant_id: str, config: dict) -> None: + def __init__(self, name: str, app_id: str, tenant_id: str, config: dict): extension_class = code_based_extension.extension_class(ExtensionModule.MODERATION, name) self.__extension_instance = extension_class(app_id, tenant_id, config) @classmethod - def validate_config(cls, name: str, tenant_id: str, config: dict) -> None: + def validate_config(cls, name: str, tenant_id: str, config: dict): """ Validate the incoming form config data. diff --git a/api/core/moderation/keywords/keywords.py b/api/core/moderation/keywords/keywords.py index 9dd2665c3b..8d8d153743 100644 --- a/api/core/moderation/keywords/keywords.py +++ b/api/core/moderation/keywords/keywords.py @@ -8,7 +8,7 @@ class KeywordsModeration(Moderation): name: str = "keywords" @classmethod - def validate_config(cls, tenant_id: str, config: dict) -> None: + def validate_config(cls, tenant_id: str, config: dict): """ Validate the incoming form config data. diff --git a/api/core/moderation/openai_moderation/openai_moderation.py b/api/core/moderation/openai_moderation/openai_moderation.py index d64f17b383..74ef6f7ceb 100644 --- a/api/core/moderation/openai_moderation/openai_moderation.py +++ b/api/core/moderation/openai_moderation/openai_moderation.py @@ -7,7 +7,7 @@ class OpenAIModeration(Moderation): name: str = "openai_moderation" @classmethod - def validate_config(cls, tenant_id: str, config: dict) -> None: + def validate_config(cls, tenant_id: str, config: dict): """ Validate the incoming form config data. diff --git a/api/core/moderation/output_moderation.py b/api/core/moderation/output_moderation.py index f981737df9..6993ec8b0b 100644 --- a/api/core/moderation/output_moderation.py +++ b/api/core/moderation/output_moderation.py @@ -40,7 +40,7 @@ class OutputModeration(BaseModel): def get_final_output(self) -> str: return self.final_output or "" - def append_new_token(self, token: str) -> None: + def append_new_token(self, token: str): self.buffer += token if not self.thread: diff --git a/api/core/plugin/backwards_invocation/encrypt.py b/api/core/plugin/backwards_invocation/encrypt.py index 213f5c726a..fafc6e894d 100644 --- a/api/core/plugin/backwards_invocation/encrypt.py +++ b/api/core/plugin/backwards_invocation/encrypt.py @@ -6,7 +6,7 @@ from models.account import Tenant class PluginEncrypter: @classmethod - def invoke_encrypt(cls, tenant: Tenant, payload: RequestInvokeEncrypt) -> dict: + def invoke_encrypt(cls, tenant: Tenant, payload: RequestInvokeEncrypt): encrypter, cache = create_provider_encrypter( tenant_id=tenant.id, config=payload.config, diff --git a/api/core/plugin/backwards_invocation/node.py b/api/core/plugin/backwards_invocation/node.py index 7898795ce2..bed5927e19 100644 --- a/api/core/plugin/backwards_invocation/node.py +++ b/api/core/plugin/backwards_invocation/node.py @@ -27,7 +27,7 @@ class PluginNodeBackwardsInvocation(BaseBackwardsInvocation): model_config: ParameterExtractorModelConfig, instruction: str, query: str, - ) -> dict: + ): """ Invoke parameter extractor node. @@ -78,7 +78,7 @@ class PluginNodeBackwardsInvocation(BaseBackwardsInvocation): classes: list[ClassConfig], instruction: str, query: str, - ) -> dict: + ): """ Invoke question classifier node. diff --git a/api/core/plugin/entities/plugin.py b/api/core/plugin/entities/plugin.py index 01e9e11e66..a6369636e2 100644 --- a/api/core/plugin/entities/plugin.py +++ b/api/core/plugin/entities/plugin.py @@ -117,7 +117,7 @@ class PluginDeclaration(BaseModel): @model_validator(mode="before") @classmethod - def validate_category(cls, values: dict) -> dict: + def validate_category(cls, values: dict): # auto detect category if values.get("tool"): values["category"] = PluginCategory.Tool @@ -168,7 +168,7 @@ class GenericProviderID: def __str__(self) -> str: return f"{self.organization}/{self.plugin_name}/{self.provider_name}" - def __init__(self, value: str, is_hardcoded: bool = False) -> None: + def __init__(self, value: str, is_hardcoded: bool = False): if not value: raise NotFound("plugin not found, please add plugin") # check if the value is a valid plugin id with format: $organization/$plugin_name/$provider_name @@ -191,14 +191,14 @@ class GenericProviderID: class ModelProviderID(GenericProviderID): - def __init__(self, value: str, is_hardcoded: bool = False) -> None: + def __init__(self, value: str, is_hardcoded: bool = False): super().__init__(value, is_hardcoded) if self.organization == "langgenius" and self.provider_name == "google": self.plugin_name = "gemini" class ToolProviderID(GenericProviderID): - def __init__(self, value: str, is_hardcoded: bool = False) -> None: + def __init__(self, value: str, is_hardcoded: bool = False): super().__init__(value, is_hardcoded) if self.organization == "langgenius": if self.provider_name in ["jina", "siliconflow", "stepfun", "gitee_ai"]: diff --git a/api/core/plugin/impl/agent.py b/api/core/plugin/impl/agent.py index 3c994ce70a..526f6f2961 100644 --- a/api/core/plugin/impl/agent.py +++ b/api/core/plugin/impl/agent.py @@ -17,7 +17,7 @@ class PluginAgentClient(BasePluginClient): Fetch agent providers for the given tenant. """ - def transformer(json_response: dict[str, Any]) -> dict: + def transformer(json_response: dict[str, Any]): for provider in json_response.get("data", []): declaration = provider.get("declaration", {}) or {} provider_name = declaration.get("identity", {}).get("name") @@ -49,7 +49,7 @@ class PluginAgentClient(BasePluginClient): """ agent_provider_id = GenericProviderID(provider) - def transformer(json_response: dict[str, Any]) -> dict: + def transformer(json_response: dict[str, Any]): # skip if error occurs if json_response.get("data") is None or json_response.get("data", {}).get("declaration") is None: return json_response diff --git a/api/core/plugin/impl/exc.py b/api/core/plugin/impl/exc.py index 8ecc2e2147..23a69bd92f 100644 --- a/api/core/plugin/impl/exc.py +++ b/api/core/plugin/impl/exc.py @@ -8,7 +8,7 @@ from extensions.ext_logging import get_request_id class PluginDaemonError(Exception): """Base class for all plugin daemon errors.""" - def __init__(self, description: str) -> None: + def __init__(self, description: str): self.description = description def __str__(self) -> str: diff --git a/api/core/plugin/impl/model.py b/api/core/plugin/impl/model.py index f7607eef8d..85a72d9f82 100644 --- a/api/core/plugin/impl/model.py +++ b/api/core/plugin/impl/model.py @@ -415,7 +415,7 @@ class PluginModelClient(BasePluginClient): model: str, credentials: dict, language: Optional[str] = None, - ) -> list[dict]: + ): """ Get tts model voices """ diff --git a/api/core/plugin/impl/tool.py b/api/core/plugin/impl/tool.py index 4c1558efcc..7199c0d15a 100644 --- a/api/core/plugin/impl/tool.py +++ b/api/core/plugin/impl/tool.py @@ -16,7 +16,7 @@ class PluginToolManager(BasePluginClient): Fetch tool providers for the given tenant. """ - def transformer(json_response: dict[str, Any]) -> dict: + def transformer(json_response: dict[str, Any]): for provider in json_response.get("data", []): declaration = provider.get("declaration", {}) or {} provider_name = declaration.get("identity", {}).get("name") @@ -48,7 +48,7 @@ class PluginToolManager(BasePluginClient): """ tool_provider_id = ToolProviderID(provider) - def transformer(json_response: dict[str, Any]) -> dict: + def transformer(json_response: dict[str, Any]): data = json_response.get("data") if data: for tool in data.get("declaration", {}).get("tools", []): diff --git a/api/core/plugin/utils/chunk_merger.py b/api/core/plugin/utils/chunk_merger.py index 21ca2d8d37..ec66ba02ee 100644 --- a/api/core/plugin/utils/chunk_merger.py +++ b/api/core/plugin/utils/chunk_merger.py @@ -18,7 +18,7 @@ class FileChunk: bytes_written: int = field(default=0, init=False) data: bytearray = field(init=False) - def __post_init__(self) -> None: + def __post_init__(self): self.data = bytearray(self.total_length) diff --git a/api/core/prompt/advanced_prompt_transform.py b/api/core/prompt/advanced_prompt_transform.py index 16c145f936..11c6e5c23b 100644 --- a/api/core/prompt/advanced_prompt_transform.py +++ b/api/core/prompt/advanced_prompt_transform.py @@ -30,7 +30,7 @@ class AdvancedPromptTransform(PromptTransform): self, with_variable_tmpl: bool = False, image_detail_config: ImagePromptMessageContent.DETAIL = ImagePromptMessageContent.DETAIL.LOW, - ) -> None: + ): self.with_variable_tmpl = with_variable_tmpl self.image_detail_config = image_detail_config diff --git a/api/core/prompt/simple_prompt_transform.py b/api/core/prompt/simple_prompt_transform.py index 13f4163d80..d75a230d73 100644 --- a/api/core/prompt/simple_prompt_transform.py +++ b/api/core/prompt/simple_prompt_transform.py @@ -126,7 +126,7 @@ class SimplePromptTransform(PromptTransform): has_context: bool, query_in_prompt: bool, with_memory_prompt: bool = False, - ) -> dict: + ): prompt_rules = self._get_prompt_rule(app_mode=app_mode, provider=provider, model=model) custom_variable_keys = [] @@ -277,7 +277,7 @@ class SimplePromptTransform(PromptTransform): return prompt_message - def _get_prompt_rule(self, app_mode: AppMode, provider: str, model: str) -> dict: + def _get_prompt_rule(self, app_mode: AppMode, provider: str, model: str): """ Get simple prompt rule. :param app_mode: app mode diff --git a/api/core/prompt/utils/prompt_message_util.py b/api/core/prompt/utils/prompt_message_util.py index cdc6ccc821..0a7a467227 100644 --- a/api/core/prompt/utils/prompt_message_util.py +++ b/api/core/prompt/utils/prompt_message_util.py @@ -15,7 +15,7 @@ from core.prompt.simple_prompt_transform import ModelMode class PromptMessageUtil: @staticmethod - def prompt_messages_to_prompt_for_saving(model_mode: str, prompt_messages: Sequence[PromptMessage]) -> list[dict]: + def prompt_messages_to_prompt_for_saving(model_mode: str, prompt_messages: Sequence[PromptMessage]): """ Prompt messages to prompt for saving. :param model_mode: model mode diff --git a/api/core/prompt/utils/prompt_template_parser.py b/api/core/prompt/utils/prompt_template_parser.py index 8e40674bc1..1b936c0893 100644 --- a/api/core/prompt/utils/prompt_template_parser.py +++ b/api/core/prompt/utils/prompt_template_parser.py @@ -25,7 +25,7 @@ class PromptTemplateParser: self.regex = WITH_VARIABLE_TMPL_REGEX if with_variable_tmpl else REGEX self.variable_keys = self.extract() - def extract(self) -> list: + def extract(self): # Regular expression to match the template rules return re.findall(self.regex, self.template) diff --git a/api/core/provider_manager.py b/api/core/provider_manager.py index 4a3b8c9dde..13dcef1a1f 100644 --- a/api/core/provider_manager.py +++ b/api/core/provider_manager.py @@ -59,7 +59,7 @@ class ProviderManager: ProviderManager is a class that manages the model providers includes Hosting and Customize Model Providers. """ - def __init__(self) -> None: + def __init__(self): self.decoding_rsa_key = None self.decoding_cipher_rsa = None diff --git a/api/core/rag/datasource/keyword/jieba/jieba.py b/api/core/rag/datasource/keyword/jieba/jieba.py index 5fb6f9fcc8..096f40f707 100644 --- a/api/core/rag/datasource/keyword/jieba/jieba.py +++ b/api/core/rag/datasource/keyword/jieba/jieba.py @@ -76,7 +76,7 @@ class Jieba(BaseKeyword): return False return id in set.union(*keyword_table.values()) - def delete_by_ids(self, ids: list[str]) -> None: + def delete_by_ids(self, ids: list[str]): lock_name = f"keyword_indexing_lock_{self.dataset.id}" with redis_client.lock(lock_name, timeout=600): keyword_table = self._get_dataset_keyword_table() @@ -116,7 +116,7 @@ class Jieba(BaseKeyword): return documents - def delete(self) -> None: + def delete(self): lock_name = f"keyword_indexing_lock_{self.dataset.id}" with redis_client.lock(lock_name, timeout=600): dataset_keyword_table = self.dataset.dataset_keyword_table @@ -168,14 +168,14 @@ class Jieba(BaseKeyword): return {} - def _add_text_to_keyword_table(self, keyword_table: dict, id: str, keywords: list[str]) -> dict: + def _add_text_to_keyword_table(self, keyword_table: dict, id: str, keywords: list[str]): for keyword in keywords: if keyword not in keyword_table: keyword_table[keyword] = set() keyword_table[keyword].add(id) return keyword_table - def _delete_ids_from_keyword_table(self, keyword_table: dict, ids: list[str]) -> dict: + def _delete_ids_from_keyword_table(self, keyword_table: dict, ids: list[str]): # get set of ids that correspond to node node_idxs_to_delete = set(ids) @@ -251,7 +251,7 @@ class Jieba(BaseKeyword): self._save_dataset_keyword_table(keyword_table) -def set_orjson_default(obj: Any) -> Any: +def set_orjson_default(obj: Any): """Default function for orjson serialization of set types""" if isinstance(obj, set): return list(obj) diff --git a/api/core/rag/datasource/keyword/keyword_base.py b/api/core/rag/datasource/keyword/keyword_base.py index b261b40b72..0a59855306 100644 --- a/api/core/rag/datasource/keyword/keyword_base.py +++ b/api/core/rag/datasource/keyword/keyword_base.py @@ -24,11 +24,11 @@ class BaseKeyword(ABC): raise NotImplementedError @abstractmethod - def delete_by_ids(self, ids: list[str]) -> None: + def delete_by_ids(self, ids: list[str]): raise NotImplementedError @abstractmethod - def delete(self) -> None: + def delete(self): raise NotImplementedError @abstractmethod diff --git a/api/core/rag/datasource/keyword/keyword_factory.py b/api/core/rag/datasource/keyword/keyword_factory.py index f1a6ade91f..b2e1a55eec 100644 --- a/api/core/rag/datasource/keyword/keyword_factory.py +++ b/api/core/rag/datasource/keyword/keyword_factory.py @@ -36,10 +36,10 @@ class Keyword: def text_exists(self, id: str) -> bool: return self._keyword_processor.text_exists(id) - def delete_by_ids(self, ids: list[str]) -> None: + def delete_by_ids(self, ids: list[str]): self._keyword_processor.delete_by_ids(ids) - def delete(self) -> None: + def delete(self): self._keyword_processor.delete() def search(self, query: str, **kwargs: Any) -> list[Document]: diff --git a/api/core/rag/datasource/vdb/analyticdb/analyticdb_vector.py b/api/core/rag/datasource/vdb/analyticdb/analyticdb_vector.py index b9e488362e..ddb549ba9d 100644 --- a/api/core/rag/datasource/vdb/analyticdb/analyticdb_vector.py +++ b/api/core/rag/datasource/vdb/analyticdb/analyticdb_vector.py @@ -46,10 +46,10 @@ class AnalyticdbVector(BaseVector): def text_exists(self, id: str) -> bool: return self.analyticdb_vector.text_exists(id) - def delete_by_ids(self, ids: list[str]) -> None: + def delete_by_ids(self, ids: list[str]): self.analyticdb_vector.delete_by_ids(ids) - def delete_by_metadata_field(self, key: str, value: str) -> None: + def delete_by_metadata_field(self, key: str, value: str): self.analyticdb_vector.delete_by_metadata_field(key, value) def search_by_vector(self, query_vector: list[float], **kwargs: Any) -> list[Document]: @@ -58,7 +58,7 @@ class AnalyticdbVector(BaseVector): def search_by_full_text(self, query: str, **kwargs: Any) -> list[Document]: return self.analyticdb_vector.search_by_full_text(query, **kwargs) - def delete(self) -> None: + def delete(self): self.analyticdb_vector.delete() diff --git a/api/core/rag/datasource/vdb/analyticdb/analyticdb_vector_openapi.py b/api/core/rag/datasource/vdb/analyticdb/analyticdb_vector_openapi.py index 48e3f20e38..c3a6127e4a 100644 --- a/api/core/rag/datasource/vdb/analyticdb/analyticdb_vector_openapi.py +++ b/api/core/rag/datasource/vdb/analyticdb/analyticdb_vector_openapi.py @@ -26,7 +26,7 @@ class AnalyticdbVectorOpenAPIConfig(BaseModel): @model_validator(mode="before") @classmethod - def validate_config(cls, values: dict) -> dict: + def validate_config(cls, values: dict): if not values["access_key_id"]: raise ValueError("config ANALYTICDB_KEY_ID is required") if not values["access_key_secret"]: @@ -65,7 +65,7 @@ class AnalyticdbVectorOpenAPI: self._client = Client(self._client_config) self._initialize() - def _initialize(self) -> None: + def _initialize(self): cache_key = f"vector_initialize_{self.config.instance_id}" lock_name = f"{cache_key}_lock" with redis_client.lock(lock_name, timeout=20): @@ -76,7 +76,7 @@ class AnalyticdbVectorOpenAPI: self._create_namespace_if_not_exists() redis_client.set(database_exist_cache_key, 1, ex=3600) - def _initialize_vector_database(self) -> None: + def _initialize_vector_database(self): from alibabacloud_gpdb20160503 import models as gpdb_20160503_models # type: ignore request = gpdb_20160503_models.InitVectorDatabaseRequest( @@ -87,7 +87,7 @@ class AnalyticdbVectorOpenAPI: ) self._client.init_vector_database(request) - def _create_namespace_if_not_exists(self) -> None: + def _create_namespace_if_not_exists(self): from alibabacloud_gpdb20160503 import models as gpdb_20160503_models from Tea.exceptions import TeaException # type: ignore @@ -200,7 +200,7 @@ class AnalyticdbVectorOpenAPI: response = self._client.query_collection_data(request) return len(response.body.matches.match) > 0 - def delete_by_ids(self, ids: list[str]) -> None: + def delete_by_ids(self, ids: list[str]): from alibabacloud_gpdb20160503 import models as gpdb_20160503_models ids_str = ",".join(f"'{id}'" for id in ids) @@ -216,7 +216,7 @@ class AnalyticdbVectorOpenAPI: ) self._client.delete_collection_data(request) - def delete_by_metadata_field(self, key: str, value: str) -> None: + def delete_by_metadata_field(self, key: str, value: str): from alibabacloud_gpdb20160503 import models as gpdb_20160503_models request = gpdb_20160503_models.DeleteCollectionDataRequest( @@ -305,7 +305,7 @@ class AnalyticdbVectorOpenAPI: documents = sorted(documents, key=lambda x: x.metadata["score"] if x.metadata else 0, reverse=True) return documents - def delete(self) -> None: + def delete(self): try: from alibabacloud_gpdb20160503 import models as gpdb_20160503_models diff --git a/api/core/rag/datasource/vdb/analyticdb/analyticdb_vector_sql.py b/api/core/rag/datasource/vdb/analyticdb/analyticdb_vector_sql.py index d1de43c5ef..12126f32d6 100644 --- a/api/core/rag/datasource/vdb/analyticdb/analyticdb_vector_sql.py +++ b/api/core/rag/datasource/vdb/analyticdb/analyticdb_vector_sql.py @@ -23,7 +23,7 @@ class AnalyticdbVectorBySqlConfig(BaseModel): @model_validator(mode="before") @classmethod - def validate_config(cls, values: dict) -> dict: + def validate_config(cls, values: dict): if not values["host"]: raise ValueError("config ANALYTICDB_HOST is required") if not values["port"]: @@ -52,7 +52,7 @@ class AnalyticdbVectorBySql: if not self.pool: self.pool = self._create_connection_pool() - def _initialize(self) -> None: + def _initialize(self): cache_key = f"vector_initialize_{self.config.host}" lock_name = f"{cache_key}_lock" with redis_client.lock(lock_name, timeout=20): @@ -85,7 +85,7 @@ class AnalyticdbVectorBySql: conn.commit() self.pool.putconn(conn) - def _initialize_vector_database(self) -> None: + def _initialize_vector_database(self): conn = psycopg2.connect( host=self.config.host, port=self.config.port, @@ -188,7 +188,7 @@ class AnalyticdbVectorBySql: cur.execute(f"SELECT id FROM {self.table_name} WHERE ref_doc_id = %s", (id,)) return cur.fetchone() is not None - def delete_by_ids(self, ids: list[str]) -> None: + def delete_by_ids(self, ids: list[str]): if not ids: return with self._get_cursor() as cur: @@ -198,7 +198,7 @@ class AnalyticdbVectorBySql: if "does not exist" not in str(e): raise e - def delete_by_metadata_field(self, key: str, value: str) -> None: + def delete_by_metadata_field(self, key: str, value: str): with self._get_cursor() as cur: try: cur.execute(f"DELETE FROM {self.table_name} WHERE metadata_->>%s = %s", (key, value)) @@ -270,6 +270,6 @@ class AnalyticdbVectorBySql: documents.append(doc) return documents - def delete(self) -> None: + def delete(self): with self._get_cursor() as cur: cur.execute(f"DROP TABLE IF EXISTS {self.table_name}") diff --git a/api/core/rag/datasource/vdb/baidu/baidu_vector.py b/api/core/rag/datasource/vdb/baidu/baidu_vector.py index d30cf42601..aa980f3835 100644 --- a/api/core/rag/datasource/vdb/baidu/baidu_vector.py +++ b/api/core/rag/datasource/vdb/baidu/baidu_vector.py @@ -36,7 +36,7 @@ class BaiduConfig(BaseModel): @model_validator(mode="before") @classmethod - def validate_config(cls, values: dict) -> dict: + def validate_config(cls, values: dict): if not values["endpoint"]: raise ValueError("config BAIDU_VECTOR_DB_ENDPOINT is required") if not values["account"]: @@ -66,7 +66,7 @@ class BaiduVector(BaseVector): def get_type(self) -> str: return VectorType.BAIDU - def to_index_struct(self) -> dict: + def to_index_struct(self): return {"type": self.get_type(), "vector_store": {"class_prefix": self._collection_name}} def create(self, texts: list[Document], embeddings: list[list[float]], **kwargs): @@ -111,13 +111,13 @@ class BaiduVector(BaseVector): return True return False - def delete_by_ids(self, ids: list[str]) -> None: + def delete_by_ids(self, ids: list[str]): if not ids: return quoted_ids = [f"'{id}'" for id in ids] self._db.table(self._collection_name).delete(filter=f"id IN({', '.join(quoted_ids)})") - def delete_by_metadata_field(self, key: str, value: str) -> None: + def delete_by_metadata_field(self, key: str, value: str): self._db.table(self._collection_name).delete(filter=f"{key} = '{value}'") def search_by_vector(self, query_vector: list[float], **kwargs: Any) -> list[Document]: @@ -164,7 +164,7 @@ class BaiduVector(BaseVector): return docs - def delete(self) -> None: + def delete(self): try: self._db.drop_table(table_name=self._collection_name) except ServerError as e: @@ -201,7 +201,7 @@ class BaiduVector(BaseVector): tables = self._db.list_table() return any(table.table_name == self._collection_name for table in tables) - def _create_table(self, dimension: int) -> None: + def _create_table(self, dimension: int): # Try to grab distributed lock and create table lock_name = f"vector_indexing_lock_{self._collection_name}" with redis_client.lock(lock_name, timeout=60): diff --git a/api/core/rag/datasource/vdb/chroma/chroma_vector.py b/api/core/rag/datasource/vdb/chroma/chroma_vector.py index 88da86cf76..e7128b183e 100644 --- a/api/core/rag/datasource/vdb/chroma/chroma_vector.py +++ b/api/core/rag/datasource/vdb/chroma/chroma_vector.py @@ -82,7 +82,7 @@ class ChromaVector(BaseVector): def delete(self): self._client.delete_collection(self._collection_name) - def delete_by_ids(self, ids: list[str]) -> None: + def delete_by_ids(self, ids: list[str]): if not ids: return collection = self._client.get_or_create_collection(self._collection_name) diff --git a/api/core/rag/datasource/vdb/clickzetta/clickzetta_vector.py b/api/core/rag/datasource/vdb/clickzetta/clickzetta_vector.py index 505cfb4c10..eb4cbd2324 100644 --- a/api/core/rag/datasource/vdb/clickzetta/clickzetta_vector.py +++ b/api/core/rag/datasource/vdb/clickzetta/clickzetta_vector.py @@ -49,7 +49,7 @@ class ClickzettaConfig(BaseModel): @model_validator(mode="before") @classmethod - def validate_config(cls, values: dict) -> dict: + def validate_config(cls, values: dict): """ Validate the configuration values. """ @@ -134,7 +134,7 @@ class ClickzettaConnectionPool: raise RuntimeError(f"Failed to create ClickZetta connection after {max_retries} attempts") - def _configure_connection(self, connection: "Connection") -> None: + def _configure_connection(self, connection: "Connection"): """Configure connection session settings.""" try: with connection.cursor() as cursor: @@ -221,7 +221,7 @@ class ClickzettaConnectionPool: # No valid connection found, create new one return self._create_connection(config) - def return_connection(self, config: ClickzettaConfig, connection: "Connection") -> None: + def return_connection(self, config: ClickzettaConfig, connection: "Connection"): """Return a connection to the pool.""" config_key = self._get_config_key(config) @@ -243,7 +243,7 @@ class ClickzettaConnectionPool: with contextlib.suppress(Exception): connection.close() - def _cleanup_expired_connections(self) -> None: + def _cleanup_expired_connections(self): """Clean up expired connections from all pools.""" current_time = time.time() @@ -265,7 +265,7 @@ class ClickzettaConnectionPool: self._pools[config_key] = valid_connections - def _start_cleanup_thread(self) -> None: + def _start_cleanup_thread(self): """Start background thread for connection cleanup.""" def cleanup_worker(): @@ -280,7 +280,7 @@ class ClickzettaConnectionPool: self._cleanup_thread = threading.Thread(target=cleanup_worker, daemon=True) self._cleanup_thread.start() - def shutdown(self) -> None: + def shutdown(self): """Shutdown connection pool and close all connections.""" self._shutdown = True @@ -319,7 +319,7 @@ class ClickzettaVector(BaseVector): """Get a connection from the pool.""" return self._connection_pool.get_connection(self._config) - def _return_connection(self, connection: "Connection") -> None: + def _return_connection(self, connection: "Connection"): """Return a connection to the pool.""" self._connection_pool.return_connection(self._config, connection) @@ -342,7 +342,7 @@ class ClickzettaVector(BaseVector): """Get a connection context manager.""" return self.ConnectionContext(self) - def _parse_metadata(self, raw_metadata: str, row_id: str) -> dict: + def _parse_metadata(self, raw_metadata: str, row_id: str): """ Parse metadata from JSON string with proper error handling and fallback. @@ -723,7 +723,7 @@ class ClickzettaVector(BaseVector): result = cursor.fetchone() return result[0] > 0 if result else False - def delete_by_ids(self, ids: list[str]) -> None: + def delete_by_ids(self, ids: list[str]): """Delete documents by IDs.""" if not ids: return @@ -736,7 +736,7 @@ class ClickzettaVector(BaseVector): # Execute delete through write queue self._execute_write(self._delete_by_ids_impl, ids) - def _delete_by_ids_impl(self, ids: list[str]) -> None: + def _delete_by_ids_impl(self, ids: list[str]): """Implementation of delete by IDs (executed in write worker thread).""" safe_ids = [self._safe_doc_id(id) for id in ids] @@ -748,7 +748,7 @@ class ClickzettaVector(BaseVector): with connection.cursor() as cursor: cursor.execute(sql, binding_params=safe_ids) - def delete_by_metadata_field(self, key: str, value: str) -> None: + def delete_by_metadata_field(self, key: str, value: str): """Delete documents by metadata field.""" # Check if table exists before attempting delete if not self._table_exists(): @@ -758,7 +758,7 @@ class ClickzettaVector(BaseVector): # Execute delete through write queue self._execute_write(self._delete_by_metadata_field_impl, key, value) - def _delete_by_metadata_field_impl(self, key: str, value: str) -> None: + def _delete_by_metadata_field_impl(self, key: str, value: str): """Implementation of delete by metadata field (executed in write worker thread).""" with self.get_connection_context() as connection: with connection.cursor() as cursor: @@ -1027,7 +1027,7 @@ class ClickzettaVector(BaseVector): return documents - def delete(self) -> None: + def delete(self): """Delete the entire collection.""" with self.get_connection_context() as connection: with connection.cursor() as cursor: diff --git a/api/core/rag/datasource/vdb/couchbase/couchbase_vector.py b/api/core/rag/datasource/vdb/couchbase/couchbase_vector.py index 9c34f51c64..6df909ca94 100644 --- a/api/core/rag/datasource/vdb/couchbase/couchbase_vector.py +++ b/api/core/rag/datasource/vdb/couchbase/couchbase_vector.py @@ -36,7 +36,7 @@ class CouchbaseConfig(BaseModel): @model_validator(mode="before") @classmethod - def validate_config(cls, values: dict) -> dict: + def validate_config(cls, values: dict): if not values.get("connection_string"): raise ValueError("config COUCHBASE_CONNECTION_STRING is required") if not values.get("user"): @@ -234,7 +234,7 @@ class CouchbaseVector(BaseVector): return bool(row["count"] > 0) return False # Return False if no rows are returned - def delete_by_ids(self, ids: list[str]) -> None: + def delete_by_ids(self, ids: list[str]): query = f""" DELETE FROM `{self._bucket_name}`.{self._client_config.scope_name}.{self._collection_name} WHERE META().id IN $doc_ids; @@ -261,7 +261,7 @@ class CouchbaseVector(BaseVector): # result = self._cluster.query(query, named_parameters={'value':value}) # return [row['id'] for row in result.rows()] - def delete_by_metadata_field(self, key: str, value: str) -> None: + def delete_by_metadata_field(self, key: str, value: str): query = f""" DELETE FROM `{self._client_config.bucket_name}`.{self._client_config.scope_name}.{self._collection_name} WHERE metadata.{key} = $value; diff --git a/api/core/rag/datasource/vdb/elasticsearch/elasticsearch_vector.py b/api/core/rag/datasource/vdb/elasticsearch/elasticsearch_vector.py index 4e288ccc08..df1c747585 100644 --- a/api/core/rag/datasource/vdb/elasticsearch/elasticsearch_vector.py +++ b/api/core/rag/datasource/vdb/elasticsearch/elasticsearch_vector.py @@ -43,7 +43,7 @@ class ElasticSearchConfig(BaseModel): @model_validator(mode="before") @classmethod - def validate_config(cls, values: dict) -> dict: + def validate_config(cls, values: dict): use_cloud = values.get("use_cloud", False) cloud_url = values.get("cloud_url") @@ -174,20 +174,20 @@ class ElasticSearchVector(BaseVector): def text_exists(self, id: str) -> bool: return bool(self._client.exists(index=self._collection_name, id=id)) - def delete_by_ids(self, ids: list[str]) -> None: + def delete_by_ids(self, ids: list[str]): if not ids: return for id in ids: self._client.delete(index=self._collection_name, id=id) - def delete_by_metadata_field(self, key: str, value: str) -> None: + def delete_by_metadata_field(self, key: str, value: str): query_str = {"query": {"match": {f"metadata.{key}": f"{value}"}}} results = self._client.search(index=self._collection_name, body=query_str) ids = [hit["_id"] for hit in results["hits"]["hits"]] if ids: self.delete_by_ids(ids) - def delete(self) -> None: + def delete(self): self._client.indices.delete(index=self._collection_name) def search_by_vector(self, query_vector: list[float], **kwargs: Any) -> list[Document]: diff --git a/api/core/rag/datasource/vdb/huawei/huawei_cloud_vector.py b/api/core/rag/datasource/vdb/huawei/huawei_cloud_vector.py index f0d014b1ec..107ea75e6a 100644 --- a/api/core/rag/datasource/vdb/huawei/huawei_cloud_vector.py +++ b/api/core/rag/datasource/vdb/huawei/huawei_cloud_vector.py @@ -33,7 +33,7 @@ class HuaweiCloudVectorConfig(BaseModel): @model_validator(mode="before") @classmethod - def validate_config(cls, values: dict) -> dict: + def validate_config(cls, values: dict): if not values["hosts"]: raise ValueError("config HOSTS is required") return values @@ -78,20 +78,20 @@ class HuaweiCloudVector(BaseVector): def text_exists(self, id: str) -> bool: return bool(self._client.exists(index=self._collection_name, id=id)) - def delete_by_ids(self, ids: list[str]) -> None: + def delete_by_ids(self, ids: list[str]): if not ids: return for id in ids: self._client.delete(index=self._collection_name, id=id) - def delete_by_metadata_field(self, key: str, value: str) -> None: + def delete_by_metadata_field(self, key: str, value: str): query_str = {"query": {"match": {f"metadata.{key}": f"{value}"}}} results = self._client.search(index=self._collection_name, body=query_str) ids = [hit["_id"] for hit in results["hits"]["hits"]] if ids: self.delete_by_ids(ids) - def delete(self) -> None: + def delete(self): self._client.indices.delete(index=self._collection_name) def search_by_vector(self, query_vector: list[float], **kwargs: Any) -> list[Document]: diff --git a/api/core/rag/datasource/vdb/lindorm/lindorm_vector.py b/api/core/rag/datasource/vdb/lindorm/lindorm_vector.py index cba10b5aa5..5097412c2c 100644 --- a/api/core/rag/datasource/vdb/lindorm/lindorm_vector.py +++ b/api/core/rag/datasource/vdb/lindorm/lindorm_vector.py @@ -36,7 +36,7 @@ class LindormVectorStoreConfig(BaseModel): @model_validator(mode="before") @classmethod - def validate_config(cls, values: dict) -> dict: + def validate_config(cls, values: dict): if not values["hosts"]: raise ValueError("config URL is required") if not values["username"]: @@ -167,7 +167,7 @@ class LindormVectorStore(BaseVector): if ids: self.delete_by_ids(ids) - def delete_by_ids(self, ids: list[str]) -> None: + def delete_by_ids(self, ids: list[str]): """Delete documents by their IDs in batch. Args: @@ -213,7 +213,7 @@ class LindormVectorStore(BaseVector): else: logger.exception("Error deleting document: %s", error) - def delete(self) -> None: + def delete(self): if self._using_ugc: routing_filter_query = { "query": {"bool": {"must": [{"term": {f"{self._routing_field}.keyword": self._routing}}]}} @@ -372,7 +372,7 @@ class LindormVectorStore(BaseVector): # logger.info(f"create index success: {self._collection_name}") -def default_text_mapping(dimension: int, method_name: str, **kwargs: Any) -> dict: +def default_text_mapping(dimension: int, method_name: str, **kwargs: Any): excludes_from_source = kwargs.get("excludes_from_source", False) analyzer = kwargs.get("analyzer", "ik_max_word") text_field = kwargs.get("text_field", Field.CONTENT_KEY.value) @@ -456,7 +456,7 @@ def default_text_search_query( routing: Optional[str] = None, routing_field: Optional[str] = None, **kwargs, -) -> dict: +): query_clause: dict[str, Any] = {} if routing is not None: query_clause = { @@ -513,7 +513,7 @@ def default_vector_search_query( filters: Optional[list[dict]] = None, filter_type: Optional[str] = None, **kwargs, -) -> dict: +): if filters is not None: filter_type = "pre_filter" if filter_type is None else filter_type if not isinstance(filters, list): diff --git a/api/core/rag/datasource/vdb/matrixone/matrixone_vector.py b/api/core/rag/datasource/vdb/matrixone/matrixone_vector.py index 564f8fc201..1bf8da5daa 100644 --- a/api/core/rag/datasource/vdb/matrixone/matrixone_vector.py +++ b/api/core/rag/datasource/vdb/matrixone/matrixone_vector.py @@ -29,7 +29,7 @@ class MatrixoneConfig(BaseModel): @model_validator(mode="before") @classmethod - def validate_config(cls, values: dict) -> dict: + def validate_config(cls, values: dict): if not values["host"]: raise ValueError("config host is required") if not values["port"]: @@ -128,7 +128,7 @@ class MatrixoneVector(BaseVector): return len(result) > 0 @ensure_client - def delete_by_ids(self, ids: list[str]) -> None: + def delete_by_ids(self, ids: list[str]): assert self.client is not None if not ids: return @@ -141,7 +141,7 @@ class MatrixoneVector(BaseVector): return [result.id for result in results] @ensure_client - def delete_by_metadata_field(self, key: str, value: str) -> None: + def delete_by_metadata_field(self, key: str, value: str): assert self.client is not None self.client.delete(filter={key: value}) @@ -207,7 +207,7 @@ class MatrixoneVector(BaseVector): return docs @ensure_client - def delete(self) -> None: + def delete(self): assert self.client is not None self.client.delete() diff --git a/api/core/rag/datasource/vdb/milvus/milvus_vector.py b/api/core/rag/datasource/vdb/milvus/milvus_vector.py index 4ad0fada15..2ec48ae365 100644 --- a/api/core/rag/datasource/vdb/milvus/milvus_vector.py +++ b/api/core/rag/datasource/vdb/milvus/milvus_vector.py @@ -36,7 +36,7 @@ class MilvusConfig(BaseModel): @model_validator(mode="before") @classmethod - def validate_config(cls, values: dict) -> dict: + def validate_config(cls, values: dict): """ Validate the configuration values. Raises ValueError if required fields are missing. @@ -79,7 +79,7 @@ class MilvusVector(BaseVector): self._load_collection_fields() self._hybrid_search_enabled = self._check_hybrid_search_support() # Check if hybrid search is supported - def _load_collection_fields(self, fields: Optional[list[str]] = None) -> None: + def _load_collection_fields(self, fields: Optional[list[str]] = None): if fields is None: # Load collection fields from remote server collection_info = self._client.describe_collection(self._collection_name) @@ -171,7 +171,7 @@ class MilvusVector(BaseVector): if ids: self._client.delete(collection_name=self._collection_name, pks=ids) - def delete_by_ids(self, ids: list[str]) -> None: + def delete_by_ids(self, ids: list[str]): """ Delete documents by their IDs. """ @@ -183,7 +183,7 @@ class MilvusVector(BaseVector): ids = [item["id"] for item in result] self._client.delete(collection_name=self._collection_name, pks=ids) - def delete(self) -> None: + def delete(self): """ Delete the entire collection. """ diff --git a/api/core/rag/datasource/vdb/myscale/myscale_vector.py b/api/core/rag/datasource/vdb/myscale/myscale_vector.py index d048f3b34e..b590a4dfe4 100644 --- a/api/core/rag/datasource/vdb/myscale/myscale_vector.py +++ b/api/core/rag/datasource/vdb/myscale/myscale_vector.py @@ -101,7 +101,7 @@ class MyScaleVector(BaseVector): results = self._client.query(f"SELECT id FROM {self._config.database}.{self._collection_name} WHERE id='{id}'") return results.row_count > 0 - def delete_by_ids(self, ids: list[str]) -> None: + def delete_by_ids(self, ids: list[str]): if not ids: return self._client.command( @@ -114,7 +114,7 @@ class MyScaleVector(BaseVector): ).result_rows return [row[0] for row in rows] - def delete_by_metadata_field(self, key: str, value: str) -> None: + def delete_by_metadata_field(self, key: str, value: str): self._client.command( f"DELETE FROM {self._config.database}.{self._collection_name} WHERE metadata.{key}='{value}'" ) @@ -156,7 +156,7 @@ class MyScaleVector(BaseVector): logger.exception("Vector search operation failed") return [] - def delete(self) -> None: + def delete(self): self._client.command(f"DROP TABLE IF EXISTS {self._config.database}.{self._collection_name}") diff --git a/api/core/rag/datasource/vdb/oceanbase/oceanbase_vector.py b/api/core/rag/datasource/vdb/oceanbase/oceanbase_vector.py index 556d03940e..44adf22d0c 100644 --- a/api/core/rag/datasource/vdb/oceanbase/oceanbase_vector.py +++ b/api/core/rag/datasource/vdb/oceanbase/oceanbase_vector.py @@ -35,7 +35,7 @@ class OceanBaseVectorConfig(BaseModel): @model_validator(mode="before") @classmethod - def validate_config(cls, values: dict) -> dict: + def validate_config(cls, values: dict): if not values["host"]: raise ValueError("config OCEANBASE_VECTOR_HOST is required") if not values["port"]: @@ -68,7 +68,7 @@ class OceanBaseVector(BaseVector): self._create_collection() self.add_texts(texts, embeddings) - def _create_collection(self) -> None: + def _create_collection(self): lock_name = "vector_indexing_lock_" + self._collection_name with redis_client.lock(lock_name, timeout=20): collection_exist_cache_key = "vector_indexing_" + self._collection_name @@ -174,7 +174,7 @@ class OceanBaseVector(BaseVector): cur = self._client.get(table_name=self._collection_name, ids=id) return bool(cur.rowcount != 0) - def delete_by_ids(self, ids: list[str]) -> None: + def delete_by_ids(self, ids: list[str]): if not ids: return self._client.delete(table_name=self._collection_name, ids=ids) @@ -190,7 +190,7 @@ class OceanBaseVector(BaseVector): ) return [row[0] for row in cur] - def delete_by_metadata_field(self, key: str, value: str) -> None: + def delete_by_metadata_field(self, key: str, value: str): ids = self.get_ids_by_metadata_field(key, value) self.delete_by_ids(ids) @@ -278,7 +278,7 @@ class OceanBaseVector(BaseVector): ) return docs - def delete(self) -> None: + def delete(self): self._client.drop_table_if_exist(self._collection_name) diff --git a/api/core/rag/datasource/vdb/opengauss/opengauss.py b/api/core/rag/datasource/vdb/opengauss/opengauss.py index c448210d94..f9dbfbeeaf 100644 --- a/api/core/rag/datasource/vdb/opengauss/opengauss.py +++ b/api/core/rag/datasource/vdb/opengauss/opengauss.py @@ -29,7 +29,7 @@ class OpenGaussConfig(BaseModel): @model_validator(mode="before") @classmethod - def validate_config(cls, values: dict) -> dict: + def validate_config(cls, values: dict): if not values["host"]: raise ValueError("config OPENGAUSS_HOST is required") if not values["port"]: @@ -159,7 +159,7 @@ class OpenGauss(BaseVector): docs.append(Document(page_content=record[1], metadata=record[0])) return docs - def delete_by_ids(self, ids: list[str]) -> None: + def delete_by_ids(self, ids: list[str]): # Avoiding crashes caused by performing delete operations on empty lists in certain scenarios # Scenario 1: extract a document fails, resulting in a table not being created. # Then clicking the retry button triggers a delete operation on an empty list. @@ -168,7 +168,7 @@ class OpenGauss(BaseVector): with self._get_cursor() as cur: cur.execute(f"DELETE FROM {self.table_name} WHERE id IN %s", (tuple(ids),)) - def delete_by_metadata_field(self, key: str, value: str) -> None: + def delete_by_metadata_field(self, key: str, value: str): with self._get_cursor() as cur: cur.execute(f"DELETE FROM {self.table_name} WHERE meta->>%s = %s", (key, value)) @@ -222,7 +222,7 @@ class OpenGauss(BaseVector): return docs - def delete(self) -> None: + def delete(self): with self._get_cursor() as cur: cur.execute(f"DROP TABLE IF EXISTS {self.table_name}") diff --git a/api/core/rag/datasource/vdb/opensearch/opensearch_vector.py b/api/core/rag/datasource/vdb/opensearch/opensearch_vector.py index 917c27eabf..3f65a4a275 100644 --- a/api/core/rag/datasource/vdb/opensearch/opensearch_vector.py +++ b/api/core/rag/datasource/vdb/opensearch/opensearch_vector.py @@ -33,7 +33,7 @@ class OpenSearchConfig(BaseModel): @model_validator(mode="before") @classmethod - def validate_config(cls, values: dict) -> dict: + def validate_config(cls, values: dict): if not values.get("host"): raise ValueError("config OPENSEARCH_HOST is required") if not values.get("port"): @@ -128,7 +128,7 @@ class OpenSearchVector(BaseVector): if ids: self.delete_by_ids(ids) - def delete_by_ids(self, ids: list[str]) -> None: + def delete_by_ids(self, ids: list[str]): index_name = self._collection_name.lower() if not self._client.indices.exists(index=index_name): logger.warning("Index %s does not exist", index_name) @@ -159,7 +159,7 @@ class OpenSearchVector(BaseVector): else: logger.exception("Error deleting document: %s", error) - def delete(self) -> None: + def delete(self): self._client.indices.delete(index=self._collection_name.lower()) def text_exists(self, id: str) -> bool: diff --git a/api/core/rag/datasource/vdb/oracle/oraclevector.py b/api/core/rag/datasource/vdb/oracle/oraclevector.py index 1b99f649bf..23997d3d20 100644 --- a/api/core/rag/datasource/vdb/oracle/oraclevector.py +++ b/api/core/rag/datasource/vdb/oracle/oraclevector.py @@ -33,7 +33,7 @@ class OracleVectorConfig(BaseModel): @model_validator(mode="before") @classmethod - def validate_config(cls, values: dict) -> dict: + def validate_config(cls, values: dict): if not values["user"]: raise ValueError("config ORACLE_USER is required") if not values["password"]: @@ -206,7 +206,7 @@ class OracleVector(BaseVector): conn.close() return docs - def delete_by_ids(self, ids: list[str]) -> None: + def delete_by_ids(self, ids: list[str]): if not ids: return with self._get_connection() as conn: @@ -216,7 +216,7 @@ class OracleVector(BaseVector): conn.commit() conn.close() - def delete_by_metadata_field(self, key: str, value: str) -> None: + def delete_by_metadata_field(self, key: str, value: str): with self._get_connection() as conn: with conn.cursor() as cur: cur.execute(f"DELETE FROM {self.table_name} WHERE JSON_VALUE(meta, '$." + key + "') = :1", (value,)) @@ -336,7 +336,7 @@ class OracleVector(BaseVector): else: return [Document(page_content="", metadata={})] - def delete(self) -> None: + def delete(self): with self._get_connection() as conn: with conn.cursor() as cur: cur.execute(f"DROP TABLE IF EXISTS {self.table_name} cascade constraints") diff --git a/api/core/rag/datasource/vdb/pgvecto_rs/pgvecto_rs.py b/api/core/rag/datasource/vdb/pgvecto_rs/pgvecto_rs.py index 99cd4a22cb..b986c79e3a 100644 --- a/api/core/rag/datasource/vdb/pgvecto_rs/pgvecto_rs.py +++ b/api/core/rag/datasource/vdb/pgvecto_rs/pgvecto_rs.py @@ -33,7 +33,7 @@ class PgvectoRSConfig(BaseModel): @model_validator(mode="before") @classmethod - def validate_config(cls, values: dict) -> dict: + def validate_config(cls, values: dict): if not values["host"]: raise ValueError("config PGVECTO_RS_HOST is required") if not values["port"]: @@ -150,7 +150,7 @@ class PGVectoRS(BaseVector): session.execute(select_statement, {"ids": ids}) session.commit() - def delete_by_ids(self, ids: list[str]) -> None: + def delete_by_ids(self, ids: list[str]): with Session(self._client) as session: select_statement = sql_text( f"SELECT id FROM {self._collection_name} WHERE meta->>'doc_id' = ANY (:doc_ids); " @@ -164,7 +164,7 @@ class PGVectoRS(BaseVector): session.execute(select_statement, {"ids": ids}) session.commit() - def delete(self) -> None: + def delete(self): with Session(self._client) as session: session.execute(sql_text(f"DROP TABLE IF EXISTS {self._collection_name}")) session.commit() diff --git a/api/core/rag/datasource/vdb/pgvector/pgvector.py b/api/core/rag/datasource/vdb/pgvector/pgvector.py index 13be18f920..445a0a7f8b 100644 --- a/api/core/rag/datasource/vdb/pgvector/pgvector.py +++ b/api/core/rag/datasource/vdb/pgvector/pgvector.py @@ -34,7 +34,7 @@ class PGVectorConfig(BaseModel): @model_validator(mode="before") @classmethod - def validate_config(cls, values: dict) -> dict: + def validate_config(cls, values: dict): if not values["host"]: raise ValueError("config PGVECTOR_HOST is required") if not values["port"]: @@ -146,7 +146,7 @@ class PGVector(BaseVector): docs.append(Document(page_content=record[1], metadata=record[0])) return docs - def delete_by_ids(self, ids: list[str]) -> None: + def delete_by_ids(self, ids: list[str]): # Avoiding crashes caused by performing delete operations on empty lists in certain scenarios # Scenario 1: extract a document fails, resulting in a table not being created. # Then clicking the retry button triggers a delete operation on an empty list. @@ -162,7 +162,7 @@ class PGVector(BaseVector): except Exception as e: raise e - def delete_by_metadata_field(self, key: str, value: str) -> None: + def delete_by_metadata_field(self, key: str, value: str): with self._get_cursor() as cur: cur.execute(f"DELETE FROM {self.table_name} WHERE meta->>%s = %s", (key, value)) @@ -242,7 +242,7 @@ class PGVector(BaseVector): return docs - def delete(self) -> None: + def delete(self): with self._get_cursor() as cur: cur.execute(f"DROP TABLE IF EXISTS {self.table_name}") diff --git a/api/core/rag/datasource/vdb/pyvastbase/vastbase_vector.py b/api/core/rag/datasource/vdb/pyvastbase/vastbase_vector.py index c33e344bff..86b6ace3f6 100644 --- a/api/core/rag/datasource/vdb/pyvastbase/vastbase_vector.py +++ b/api/core/rag/datasource/vdb/pyvastbase/vastbase_vector.py @@ -28,7 +28,7 @@ class VastbaseVectorConfig(BaseModel): @model_validator(mode="before") @classmethod - def validate_config(cls, values: dict) -> dict: + def validate_config(cls, values: dict): if not values["host"]: raise ValueError("config VASTBASE_HOST is required") if not values["port"]: @@ -133,7 +133,7 @@ class VastbaseVector(BaseVector): docs.append(Document(page_content=record[1], metadata=record[0])) return docs - def delete_by_ids(self, ids: list[str]) -> None: + def delete_by_ids(self, ids: list[str]): # Avoiding crashes caused by performing delete operations on empty lists in certain scenarios # Scenario 1: extract a document fails, resulting in a table not being created. # Then clicking the retry button triggers a delete operation on an empty list. @@ -142,7 +142,7 @@ class VastbaseVector(BaseVector): with self._get_cursor() as cur: cur.execute(f"DELETE FROM {self.table_name} WHERE id IN %s", (tuple(ids),)) - def delete_by_metadata_field(self, key: str, value: str) -> None: + def delete_by_metadata_field(self, key: str, value: str): with self._get_cursor() as cur: cur.execute(f"DELETE FROM {self.table_name} WHERE meta->>%s = %s", (key, value)) @@ -199,7 +199,7 @@ class VastbaseVector(BaseVector): return docs - def delete(self) -> None: + def delete(self): with self._get_cursor() as cur: cur.execute(f"DROP TABLE IF EXISTS {self.table_name}") diff --git a/api/core/rag/datasource/vdb/qdrant/qdrant_vector.py b/api/core/rag/datasource/vdb/qdrant/qdrant_vector.py index e55c06e665..12d97c500f 100644 --- a/api/core/rag/datasource/vdb/qdrant/qdrant_vector.py +++ b/api/core/rag/datasource/vdb/qdrant/qdrant_vector.py @@ -81,7 +81,7 @@ class QdrantVector(BaseVector): def get_type(self) -> str: return VectorType.QDRANT - def to_index_struct(self) -> dict: + def to_index_struct(self): return {"type": self.get_type(), "vector_store": {"class_prefix": self._collection_name}} def create(self, texts: list[Document], embeddings: list[list[float]], **kwargs): @@ -292,7 +292,7 @@ class QdrantVector(BaseVector): else: raise e - def delete_by_ids(self, ids: list[str]) -> None: + def delete_by_ids(self, ids: list[str]): from qdrant_client.http import models from qdrant_client.http.exceptions import UnexpectedResponse diff --git a/api/core/rag/datasource/vdb/relyt/relyt_vector.py b/api/core/rag/datasource/vdb/relyt/relyt_vector.py index a200bacfb6..9d3dc7c622 100644 --- a/api/core/rag/datasource/vdb/relyt/relyt_vector.py +++ b/api/core/rag/datasource/vdb/relyt/relyt_vector.py @@ -35,7 +35,7 @@ class RelytConfig(BaseModel): @model_validator(mode="before") @classmethod - def validate_config(cls, values: dict) -> dict: + def validate_config(cls, values: dict): if not values["host"]: raise ValueError("config RELYT_HOST is required") if not values["port"]: @@ -64,7 +64,7 @@ class RelytVector(BaseVector): def get_type(self) -> str: return VectorType.RELYT - def create(self, texts: list[Document], embeddings: list[list[float]], **kwargs) -> None: + def create(self, texts: list[Document], embeddings: list[list[float]], **kwargs): self.create_collection(len(embeddings[0])) self.embedding_dimension = len(embeddings[0]) self.add_texts(texts, embeddings) @@ -196,7 +196,7 @@ class RelytVector(BaseVector): if ids: self.delete_by_uuids(ids) - def delete_by_ids(self, ids: list[str]) -> None: + def delete_by_ids(self, ids: list[str]): with Session(self.client) as session: ids_str = ",".join(f"'{doc_id}'" for doc_id in ids) select_statement = sql_text( @@ -207,7 +207,7 @@ class RelytVector(BaseVector): ids = [item[0] for item in result] self.delete_by_uuids(ids) - def delete(self) -> None: + def delete(self): with Session(self.client) as session: session.execute(sql_text(f"""DROP TABLE IF EXISTS "{self._collection_name}";""")) session.commit() diff --git a/api/core/rag/datasource/vdb/tablestore/tablestore_vector.py b/api/core/rag/datasource/vdb/tablestore/tablestore_vector.py index 9c55351522..27685b7ddf 100644 --- a/api/core/rag/datasource/vdb/tablestore/tablestore_vector.py +++ b/api/core/rag/datasource/vdb/tablestore/tablestore_vector.py @@ -30,7 +30,7 @@ class TableStoreConfig(BaseModel): @model_validator(mode="before") @classmethod - def validate_config(cls, values: dict) -> dict: + def validate_config(cls, values: dict): if not values["access_key_id"]: raise ValueError("config ACCESS_KEY_ID is required") if not values["access_key_secret"]: @@ -112,7 +112,7 @@ class TableStoreVector(BaseVector): return return_row is not None - def delete_by_ids(self, ids: list[str]) -> None: + def delete_by_ids(self, ids: list[str]): if not ids: return for id in ids: @@ -121,7 +121,7 @@ class TableStoreVector(BaseVector): def get_ids_by_metadata_field(self, key: str, value: str): return self._search_by_metadata(key, value) - def delete_by_metadata_field(self, key: str, value: str) -> None: + def delete_by_metadata_field(self, key: str, value: str): ids = self.get_ids_by_metadata_field(key, value) self.delete_by_ids(ids) @@ -143,7 +143,7 @@ class TableStoreVector(BaseVector): score_threshold = float(kwargs.get("score_threshold") or 0.0) return self._search_by_full_text(query, filtered_list, top_k, score_threshold) - def delete(self) -> None: + def delete(self): self._delete_table_if_exist() def _create_collection(self, dimension: int): @@ -158,7 +158,7 @@ class TableStoreVector(BaseVector): self._create_search_index_if_not_exist(dimension) redis_client.set(collection_exist_cache_key, 1, ex=3600) - def _create_table_if_not_exist(self) -> None: + def _create_table_if_not_exist(self): table_list = self._tablestore_client.list_table() if self._table_name in table_list: logger.info("Tablestore system table[%s] already exists", self._table_name) @@ -171,7 +171,7 @@ class TableStoreVector(BaseVector): self._tablestore_client.create_table(table_meta, table_options, reserved_throughput) logger.info("Tablestore create table[%s] successfully.", self._table_name) - def _create_search_index_if_not_exist(self, dimension: int) -> None: + def _create_search_index_if_not_exist(self, dimension: int): search_index_list = self._tablestore_client.list_search_index(table_name=self._table_name) assert isinstance(search_index_list, Iterable) if self._index_name in [t[1] for t in search_index_list]: @@ -225,11 +225,11 @@ class TableStoreVector(BaseVector): self._tablestore_client.delete_table(self._table_name) logger.info("Tablestore delete system table[%s] successfully.", self._index_name) - def _delete_search_index(self) -> None: + def _delete_search_index(self): self._tablestore_client.delete_search_index(self._table_name, self._index_name) logger.info("Tablestore delete index[%s] successfully.", self._index_name) - def _write_row(self, primary_key: str, attributes: dict[str, Any]) -> None: + def _write_row(self, primary_key: str, attributes: dict[str, Any]): pk = [("id", primary_key)] tags = [] @@ -248,7 +248,7 @@ class TableStoreVector(BaseVector): row = tablestore.Row(pk, attribute_columns) self._tablestore_client.put_row(self._table_name, row) - def _delete_row(self, id: str) -> None: + def _delete_row(self, id: str): primary_key = [("id", id)] row = tablestore.Row(primary_key) self._tablestore_client.delete_row(self._table_name, row, None) diff --git a/api/core/rag/datasource/vdb/tencent/tencent_vector.py b/api/core/rag/datasource/vdb/tencent/tencent_vector.py index 3df35d081f..4af34bbb2d 100644 --- a/api/core/rag/datasource/vdb/tencent/tencent_vector.py +++ b/api/core/rag/datasource/vdb/tencent/tencent_vector.py @@ -82,7 +82,7 @@ class TencentVector(BaseVector): def get_type(self) -> str: return VectorType.TENCENT - def to_index_struct(self) -> dict: + def to_index_struct(self): return {"type": self.get_type(), "vector_store": {"class_prefix": self._collection_name}} def _has_collection(self) -> bool: @@ -92,7 +92,7 @@ class TencentVector(BaseVector): ) ) - def _create_collection(self, dimension: int) -> None: + def _create_collection(self, dimension: int): self._dimension = dimension lock_name = f"vector_indexing_lock_{self._collection_name}" with redis_client.lock(lock_name, timeout=20): @@ -205,7 +205,7 @@ class TencentVector(BaseVector): return True return False - def delete_by_ids(self, ids: list[str]) -> None: + def delete_by_ids(self, ids: list[str]): if not ids: return @@ -222,7 +222,7 @@ class TencentVector(BaseVector): database_name=self._client_config.database, collection_name=self.collection_name, document_ids=batch_ids ) - def delete_by_metadata_field(self, key: str, value: str) -> None: + def delete_by_metadata_field(self, key: str, value: str): self._client.delete( database_name=self._client_config.database, collection_name=self.collection_name, @@ -299,7 +299,7 @@ class TencentVector(BaseVector): docs.append(doc) return docs - def delete(self) -> None: + def delete(self): if self._has_collection(): self._client.drop_collection( database_name=self._client_config.database, collection_name=self.collection_name diff --git a/api/core/rag/datasource/vdb/tidb_on_qdrant/tidb_on_qdrant_vector.py b/api/core/rag/datasource/vdb/tidb_on_qdrant/tidb_on_qdrant_vector.py index be24f5a561..7055581459 100644 --- a/api/core/rag/datasource/vdb/tidb_on_qdrant/tidb_on_qdrant_vector.py +++ b/api/core/rag/datasource/vdb/tidb_on_qdrant/tidb_on_qdrant_vector.py @@ -90,7 +90,7 @@ class TidbOnQdrantVector(BaseVector): def get_type(self) -> str: return VectorType.TIDB_ON_QDRANT - def to_index_struct(self) -> dict: + def to_index_struct(self): return {"type": self.get_type(), "vector_store": {"class_prefix": self._collection_name}} def create(self, texts: list[Document], embeddings: list[list[float]], **kwargs): @@ -284,7 +284,7 @@ class TidbOnQdrantVector(BaseVector): else: raise e - def delete_by_ids(self, ids: list[str]) -> None: + def delete_by_ids(self, ids: list[str]): from qdrant_client.http import models from qdrant_client.http.exceptions import UnexpectedResponse diff --git a/api/core/rag/datasource/vdb/tidb_vector/tidb_vector.py b/api/core/rag/datasource/vdb/tidb_vector/tidb_vector.py index e5492cb7f3..6efc04aa29 100644 --- a/api/core/rag/datasource/vdb/tidb_vector/tidb_vector.py +++ b/api/core/rag/datasource/vdb/tidb_vector/tidb_vector.py @@ -31,7 +31,7 @@ class TiDBVectorConfig(BaseModel): @model_validator(mode="before") @classmethod - def validate_config(cls, values: dict) -> dict: + def validate_config(cls, values: dict): if not values["host"]: raise ValueError("config TIDB_VECTOR_HOST is required") if not values["port"]: @@ -144,7 +144,7 @@ class TiDBVector(BaseVector): result = self.get_ids_by_metadata_field("doc_id", id) return bool(result) - def delete_by_ids(self, ids: list[str]) -> None: + def delete_by_ids(self, ids: list[str]): with Session(self._engine) as session: ids_str = ",".join(f"'{doc_id}'" for doc_id in ids) select_statement = sql_text( @@ -179,7 +179,7 @@ class TiDBVector(BaseVector): else: return None - def delete_by_metadata_field(self, key: str, value: str) -> None: + def delete_by_metadata_field(self, key: str, value: str): ids = self.get_ids_by_metadata_field(key, value) if ids: self._delete_by_ids(ids) @@ -237,7 +237,7 @@ class TiDBVector(BaseVector): # tidb doesn't support bm25 search return [] - def delete(self) -> None: + def delete(self): with Session(self._engine) as session: session.execute(sql_text(f"""DROP TABLE IF EXISTS {self._collection_name};""")) session.commit() diff --git a/api/core/rag/datasource/vdb/upstash/upstash_vector.py b/api/core/rag/datasource/vdb/upstash/upstash_vector.py index 9e99f14dc5..289d971853 100644 --- a/api/core/rag/datasource/vdb/upstash/upstash_vector.py +++ b/api/core/rag/datasource/vdb/upstash/upstash_vector.py @@ -20,7 +20,7 @@ class UpstashVectorConfig(BaseModel): @model_validator(mode="before") @classmethod - def validate_config(cls, values: dict) -> dict: + def validate_config(cls, values: dict): if not values["url"]: raise ValueError("Upstash URL is required") if not values["token"]: @@ -60,7 +60,7 @@ class UpstashVector(BaseVector): response = self.get_ids_by_metadata_field("doc_id", id) return len(response) > 0 - def delete_by_ids(self, ids: list[str]) -> None: + def delete_by_ids(self, ids: list[str]): item_ids = [] for doc_id in ids: ids = self.get_ids_by_metadata_field("doc_id", doc_id) @@ -68,7 +68,7 @@ class UpstashVector(BaseVector): item_ids += ids self._delete_by_ids(ids=item_ids) - def _delete_by_ids(self, ids: list[str]) -> None: + def _delete_by_ids(self, ids: list[str]): if ids: self.index.delete(ids=ids) @@ -81,7 +81,7 @@ class UpstashVector(BaseVector): ) return [result.id for result in query_result] - def delete_by_metadata_field(self, key: str, value: str) -> None: + def delete_by_metadata_field(self, key: str, value: str): ids = self.get_ids_by_metadata_field(key, value) if ids: self._delete_by_ids(ids) @@ -117,7 +117,7 @@ class UpstashVector(BaseVector): def search_by_full_text(self, query: str, **kwargs: Any) -> list[Document]: return [] - def delete(self) -> None: + def delete(self): self.index.reset() def get_type(self) -> str: diff --git a/api/core/rag/datasource/vdb/vector_base.py b/api/core/rag/datasource/vdb/vector_base.py index edfce2edd8..469978224a 100644 --- a/api/core/rag/datasource/vdb/vector_base.py +++ b/api/core/rag/datasource/vdb/vector_base.py @@ -27,14 +27,14 @@ class BaseVector(ABC): raise NotImplementedError @abstractmethod - def delete_by_ids(self, ids: list[str]) -> None: + def delete_by_ids(self, ids: list[str]): raise NotImplementedError def get_ids_by_metadata_field(self, key: str, value: str): raise NotImplementedError @abstractmethod - def delete_by_metadata_field(self, key: str, value: str) -> None: + def delete_by_metadata_field(self, key: str, value: str): raise NotImplementedError @abstractmethod @@ -46,7 +46,7 @@ class BaseVector(ABC): raise NotImplementedError @abstractmethod - def delete(self) -> None: + def delete(self): raise NotImplementedError def _filter_duplicate_texts(self, texts: list[Document]) -> list[Document]: diff --git a/api/core/rag/datasource/vdb/vector_factory.py b/api/core/rag/datasource/vdb/vector_factory.py index 661a8f37aa..b2cc51d034 100644 --- a/api/core/rag/datasource/vdb/vector_factory.py +++ b/api/core/rag/datasource/vdb/vector_factory.py @@ -26,7 +26,7 @@ class AbstractVectorFactory(ABC): raise NotImplementedError @staticmethod - def gen_index_struct_dict(vector_type: VectorType, collection_name: str) -> dict: + def gen_index_struct_dict(vector_type: VectorType, collection_name: str): index_struct_dict = {"type": vector_type, "vector_store": {"class_prefix": collection_name}} return index_struct_dict @@ -207,10 +207,10 @@ class Vector: def text_exists(self, id: str) -> bool: return self._vector_processor.text_exists(id) - def delete_by_ids(self, ids: list[str]) -> None: + def delete_by_ids(self, ids: list[str]): self._vector_processor.delete_by_ids(ids) - def delete_by_metadata_field(self, key: str, value: str) -> None: + def delete_by_metadata_field(self, key: str, value: str): self._vector_processor.delete_by_metadata_field(key, value) def search_by_vector(self, query: str, **kwargs: Any) -> list[Document]: @@ -220,7 +220,7 @@ class Vector: def search_by_full_text(self, query: str, **kwargs: Any) -> list[Document]: return self._vector_processor.search_by_full_text(query, **kwargs) - def delete(self) -> None: + def delete(self): self._vector_processor.delete() # delete collection redis cache if self._vector_processor.collection_name: diff --git a/api/core/rag/datasource/vdb/vikingdb/vikingdb_vector.py b/api/core/rag/datasource/vdb/vikingdb/vikingdb_vector.py index 33267741c2..d1bdd3baef 100644 --- a/api/core/rag/datasource/vdb/vikingdb/vikingdb_vector.py +++ b/api/core/rag/datasource/vdb/vikingdb/vikingdb_vector.py @@ -144,7 +144,7 @@ class VikingDBVector(BaseVector): return True return False - def delete_by_ids(self, ids: list[str]) -> None: + def delete_by_ids(self, ids: list[str]): self._client.get_collection(self._collection_name).delete_data(ids) def get_ids_by_metadata_field(self, key: str, value: str): @@ -168,7 +168,7 @@ class VikingDBVector(BaseVector): ids.append(result.id) return ids - def delete_by_metadata_field(self, key: str, value: str) -> None: + def delete_by_metadata_field(self, key: str, value: str): ids = self.get_ids_by_metadata_field(key, value) self.delete_by_ids(ids) @@ -202,7 +202,7 @@ class VikingDBVector(BaseVector): def search_by_full_text(self, query: str, **kwargs: Any) -> list[Document]: return [] - def delete(self) -> None: + def delete(self): if self._has_index(): self._client.drop_index(self._collection_name, self._index_name) if self._has_collection(): diff --git a/api/core/rag/datasource/vdb/weaviate/weaviate_vector.py b/api/core/rag/datasource/vdb/weaviate/weaviate_vector.py index bc237b591a..43dde37c7e 100644 --- a/api/core/rag/datasource/vdb/weaviate/weaviate_vector.py +++ b/api/core/rag/datasource/vdb/weaviate/weaviate_vector.py @@ -24,7 +24,7 @@ class WeaviateConfig(BaseModel): @model_validator(mode="before") @classmethod - def validate_config(cls, values: dict) -> dict: + def validate_config(cls, values: dict): if not values["endpoint"]: raise ValueError("config WEAVIATE_ENDPOINT is required") return values @@ -75,7 +75,7 @@ class WeaviateVector(BaseVector): dataset_id = dataset.id return Dataset.gen_collection_name_by_id(dataset_id) - def to_index_struct(self) -> dict: + def to_index_struct(self): return {"type": self.get_type(), "vector_store": {"class_prefix": self._collection_name}} def create(self, texts: list[Document], embeddings: list[list[float]], **kwargs): @@ -164,7 +164,7 @@ class WeaviateVector(BaseVector): return True - def delete_by_ids(self, ids: list[str]) -> None: + def delete_by_ids(self, ids: list[str]): # check whether the index already exists schema = self._default_schema(self._collection_name) if self._client.schema.contains(schema): @@ -256,7 +256,7 @@ class WeaviateVector(BaseVector): docs.append(Document(page_content=text, vector=additional["vector"], metadata=res)) return docs - def _default_schema(self, index_name: str) -> dict: + def _default_schema(self, index_name: str): return { "class": index_name, "properties": [ @@ -267,7 +267,7 @@ class WeaviateVector(BaseVector): ], } - def _json_serializable(self, value: Any) -> Any: + def _json_serializable(self, value: Any): if isinstance(value, datetime.datetime): return value.isoformat() return value diff --git a/api/core/rag/docstore/dataset_docstore.py b/api/core/rag/docstore/dataset_docstore.py index 717cfe8f53..63c6db8d06 100644 --- a/api/core/rag/docstore/dataset_docstore.py +++ b/api/core/rag/docstore/dataset_docstore.py @@ -32,11 +32,11 @@ class DatasetDocumentStore: } @property - def dataset_id(self) -> Any: + def dataset_id(self): return self._dataset.id @property - def user_id(self) -> Any: + def user_id(self): return self._user_id @property @@ -59,7 +59,7 @@ class DatasetDocumentStore: return output - def add_documents(self, docs: Sequence[Document], allow_update: bool = True, save_child: bool = False) -> None: + def add_documents(self, docs: Sequence[Document], allow_update: bool = True, save_child: bool = False): max_position = ( db.session.query(func.max(DocumentSegment.position)) .where(DocumentSegment.document_id == self._document_id) @@ -195,7 +195,7 @@ class DatasetDocumentStore: }, ) - def delete_document(self, doc_id: str, raise_error: bool = True) -> None: + def delete_document(self, doc_id: str, raise_error: bool = True): document_segment = self.get_document_segment(doc_id) if document_segment is None: @@ -207,7 +207,7 @@ class DatasetDocumentStore: db.session.delete(document_segment) db.session.commit() - def set_document_hash(self, doc_id: str, doc_hash: str) -> None: + def set_document_hash(self, doc_id: str, doc_hash: str): """Set the hash for a given doc_id.""" document_segment = self.get_document_segment(doc_id) diff --git a/api/core/rag/embedding/cached_embedding.py b/api/core/rag/embedding/cached_embedding.py index e27c1f0594..43be9cde69 100644 --- a/api/core/rag/embedding/cached_embedding.py +++ b/api/core/rag/embedding/cached_embedding.py @@ -20,7 +20,7 @@ logger = logging.getLogger(__name__) class CacheEmbedding(Embeddings): - def __init__(self, model_instance: ModelInstance, user: Optional[str] = None) -> None: + def __init__(self, model_instance: ModelInstance, user: Optional[str] = None): self._model_instance = model_instance self._user = user diff --git a/api/core/rag/extractor/entity/extract_setting.py b/api/core/rag/extractor/entity/extract_setting.py index 1593ad1475..52d64f591f 100644 --- a/api/core/rag/extractor/entity/extract_setting.py +++ b/api/core/rag/extractor/entity/extract_setting.py @@ -18,7 +18,7 @@ class NotionInfo(BaseModel): tenant_id: str model_config = ConfigDict(arbitrary_types_allowed=True) - def __init__(self, **data) -> None: + def __init__(self, **data): super().__init__(**data) @@ -49,5 +49,5 @@ class ExtractSetting(BaseModel): document_model: Optional[str] = None model_config = ConfigDict(arbitrary_types_allowed=True) - def __init__(self, **data) -> None: + def __init__(self, **data): super().__init__(**data) diff --git a/api/core/rag/extractor/firecrawl/firecrawl_app.py b/api/core/rag/extractor/firecrawl/firecrawl_app.py index fd60af0f1c..e1ba6ef243 100644 --- a/api/core/rag/extractor/firecrawl/firecrawl_app.py +++ b/api/core/rag/extractor/firecrawl/firecrawl_app.py @@ -122,7 +122,7 @@ class FirecrawlApp: return response return response - def _handle_error(self, response, action) -> None: + def _handle_error(self, response, action): error_message = response.json().get("error", "Unknown error occurred") raise Exception(f"Failed to {action}. Status code: {response.status_code}. Error: {error_message}") # type: ignore[return] diff --git a/api/core/rag/extractor/helpers.py b/api/core/rag/extractor/helpers.py index 3d2fb55d9a..17f7d8661f 100644 --- a/api/core/rag/extractor/helpers.py +++ b/api/core/rag/extractor/helpers.py @@ -29,7 +29,7 @@ def detect_file_encodings(file_path: str, timeout: int = 5, sample_size: int = 1 """ import chardet - def read_and_detect(file_path: str) -> list[dict]: + def read_and_detect(file_path: str): with open(file_path, "rb") as f: # Read only a sample of the file for encoding detection # This prevents timeout on large files while still providing accurate encoding detection diff --git a/api/core/rag/extractor/watercrawl/provider.py b/api/core/rag/extractor/watercrawl/provider.py index da03fc67a6..c59a70ea57 100644 --- a/api/core/rag/extractor/watercrawl/provider.py +++ b/api/core/rag/extractor/watercrawl/provider.py @@ -9,7 +9,7 @@ class WaterCrawlProvider: def __init__(self, api_key, base_url: str | None = None): self.client = WaterCrawlAPIClient(api_key, base_url) - def crawl_url(self, url, options: Optional[dict | Any] = None) -> dict: + def crawl_url(self, url, options: Optional[dict | Any] = None): options = options or {} spider_options = { "max_depth": 1, @@ -41,7 +41,7 @@ class WaterCrawlProvider: return {"status": "active", "job_id": result.get("uuid")} - def get_crawl_status(self, crawl_request_id) -> dict: + def get_crawl_status(self, crawl_request_id): response = self.client.get_crawl_request(crawl_request_id) data = [] if response["status"] in ["new", "running"]: @@ -82,11 +82,11 @@ class WaterCrawlProvider: return None - def scrape_url(self, url: str) -> dict: + def scrape_url(self, url: str): response = self.client.scrape_url(url=url, sync=True, prefetched=True) return self._structure_data(response) - def _structure_data(self, result_object: dict) -> dict: + def _structure_data(self, result_object: dict): if isinstance(result_object.get("result", {}), str): raise ValueError("Invalid result object. Expected a dictionary.") diff --git a/api/core/rag/extractor/word_extractor.py b/api/core/rag/extractor/word_extractor.py index f3b162e3d3..f25f92cf81 100644 --- a/api/core/rag/extractor/word_extractor.py +++ b/api/core/rag/extractor/word_extractor.py @@ -56,7 +56,7 @@ class WordExtractor(BaseExtractor): elif not os.path.isfile(self.file_path): raise ValueError(f"File path {self.file_path} is not a valid file or url") - def __del__(self) -> None: + def __del__(self): if hasattr(self, "temp_file"): self.temp_file.close() diff --git a/api/core/rag/rerank/rerank_model.py b/api/core/rag/rerank/rerank_model.py index 693535413a..7a6ebd1f39 100644 --- a/api/core/rag/rerank/rerank_model.py +++ b/api/core/rag/rerank/rerank_model.py @@ -6,7 +6,7 @@ from core.rag.rerank.rerank_base import BaseRerankRunner class RerankModelRunner(BaseRerankRunner): - def __init__(self, rerank_model_instance: ModelInstance) -> None: + def __init__(self, rerank_model_instance: ModelInstance): self.rerank_model_instance = rerank_model_instance def run( diff --git a/api/core/rag/rerank/weight_rerank.py b/api/core/rag/rerank/weight_rerank.py index 80de746e29..ab49e43b70 100644 --- a/api/core/rag/rerank/weight_rerank.py +++ b/api/core/rag/rerank/weight_rerank.py @@ -14,7 +14,7 @@ from core.rag.rerank.rerank_base import BaseRerankRunner class WeightRerankRunner(BaseRerankRunner): - def __init__(self, tenant_id: str, weights: Weights) -> None: + def __init__(self, tenant_id: str, weights: Weights): self.tenant_id = tenant_id self.weights = weights diff --git a/api/core/rag/retrieval/dataset_retrieval.py b/api/core/rag/retrieval/dataset_retrieval.py index 2e63ecfc59..93bad23f2b 100644 --- a/api/core/rag/retrieval/dataset_retrieval.py +++ b/api/core/rag/retrieval/dataset_retrieval.py @@ -507,7 +507,7 @@ class DatasetRetrieval: def _on_retrieval_end( self, documents: list[Document], message_id: Optional[str] = None, timer: Optional[dict] = None - ) -> None: + ): """Handle retrieval end.""" dify_documents = [document for document in documents if document.provider == "dify"] for document in dify_documents: @@ -560,7 +560,7 @@ class DatasetRetrieval: ) ) - def _on_query(self, query: str, dataset_ids: list[str], app_id: str, user_from: str, user_id: str) -> None: + def _on_query(self, query: str, dataset_ids: list[str], app_id: str, user_from: str, user_id: str): """ Handle query. """ diff --git a/api/core/rag/splitter/text_splitter.py b/api/core/rag/splitter/text_splitter.py index 1b60fb7784..c5b6ac4608 100644 --- a/api/core/rag/splitter/text_splitter.py +++ b/api/core/rag/splitter/text_splitter.py @@ -47,7 +47,7 @@ class TextSplitter(BaseDocumentTransformer, ABC): length_function: Callable[[list[str]], list[int]] = lambda x: [len(x) for x in x], keep_separator: bool = False, add_start_index: bool = False, - ) -> None: + ): """Create a new TextSplitter. Args: @@ -201,7 +201,7 @@ class TokenTextSplitter(TextSplitter): allowed_special: Union[Literal["all"], Set[str]] = set(), disallowed_special: Union[Literal["all"], Collection[str]] = "all", **kwargs: Any, - ) -> None: + ): """Create a new TextSplitter.""" super().__init__(**kwargs) try: @@ -251,7 +251,7 @@ class RecursiveCharacterTextSplitter(TextSplitter): separators: Optional[list[str]] = None, keep_separator: bool = True, **kwargs: Any, - ) -> None: + ): """Create a new TextSplitter.""" super().__init__(keep_separator=keep_separator, **kwargs) self._separators = separators or ["\n\n", "\n", " ", ""] diff --git a/api/core/repositories/celery_workflow_execution_repository.py b/api/core/repositories/celery_workflow_execution_repository.py index 3849044581..d6f40491b6 100644 --- a/api/core/repositories/celery_workflow_execution_repository.py +++ b/api/core/repositories/celery_workflow_execution_repository.py @@ -93,7 +93,7 @@ class CeleryWorkflowExecutionRepository(WorkflowExecutionRepository): self._triggered_from, ) - def save(self, execution: WorkflowExecution) -> None: + def save(self, execution: WorkflowExecution): """ Save or update a WorkflowExecution instance asynchronously using Celery. diff --git a/api/core/repositories/celery_workflow_node_execution_repository.py b/api/core/repositories/celery_workflow_node_execution_repository.py index 1c4e6dfe8b..b36252dba2 100644 --- a/api/core/repositories/celery_workflow_node_execution_repository.py +++ b/api/core/repositories/celery_workflow_node_execution_repository.py @@ -106,7 +106,7 @@ class CeleryWorkflowNodeExecutionRepository(WorkflowNodeExecutionRepository): self._triggered_from, ) - def save(self, execution: WorkflowNodeExecution) -> None: + def save(self, execution: WorkflowNodeExecution): """ Save or update a WorkflowNodeExecution instance to cache and asynchronously to database. diff --git a/api/core/repositories/sqlalchemy_workflow_execution_repository.py b/api/core/repositories/sqlalchemy_workflow_execution_repository.py index 74a49842f3..46b028b219 100644 --- a/api/core/repositories/sqlalchemy_workflow_execution_repository.py +++ b/api/core/repositories/sqlalchemy_workflow_execution_repository.py @@ -176,7 +176,7 @@ class SQLAlchemyWorkflowExecutionRepository(WorkflowExecutionRepository): return db_model - def save(self, execution: WorkflowExecution) -> None: + def save(self, execution: WorkflowExecution): """ Save or update a WorkflowExecution domain entity to the database. diff --git a/api/core/repositories/sqlalchemy_workflow_node_execution_repository.py b/api/core/repositories/sqlalchemy_workflow_node_execution_repository.py index 85754be149..8702af9f80 100644 --- a/api/core/repositories/sqlalchemy_workflow_node_execution_repository.py +++ b/api/core/repositories/sqlalchemy_workflow_node_execution_repository.py @@ -194,9 +194,7 @@ class SQLAlchemyWorkflowNodeExecutionRepository(WorkflowNodeExecutionRepository) """Check if the exception is a duplicate key constraint violation.""" return isinstance(exception, IntegrityError) and isinstance(exception.orig, psycopg2.errors.UniqueViolation) - def _regenerate_id_on_duplicate( - self, execution: WorkflowNodeExecution, db_model: WorkflowNodeExecutionModel - ) -> None: + def _regenerate_id_on_duplicate(self, execution: WorkflowNodeExecution, db_model: WorkflowNodeExecutionModel): """Regenerate UUID v7 for both domain and database models when duplicate key detected.""" new_id = str(uuidv7()) logger.warning( @@ -205,7 +203,7 @@ class SQLAlchemyWorkflowNodeExecutionRepository(WorkflowNodeExecutionRepository) db_model.id = new_id execution.id = new_id - def save(self, execution: WorkflowNodeExecution) -> None: + def save(self, execution: WorkflowNodeExecution): """ Save or update a NodeExecution domain entity to the database. @@ -254,7 +252,7 @@ class SQLAlchemyWorkflowNodeExecutionRepository(WorkflowNodeExecutionRepository) logger.exception("Failed to save workflow node execution after all retries") raise - def _persist_to_database(self, db_model: WorkflowNodeExecutionModel) -> None: + def _persist_to_database(self, db_model: WorkflowNodeExecutionModel): """ Persist the database model to the database. diff --git a/api/core/tools/__base/tool.py b/api/core/tools/__base/tool.py index d6961cdaa4..5a2b803932 100644 --- a/api/core/tools/__base/tool.py +++ b/api/core/tools/__base/tool.py @@ -20,7 +20,7 @@ class Tool(ABC): The base class of a tool """ - def __init__(self, entity: ToolEntity, runtime: ToolRuntime) -> None: + def __init__(self, entity: ToolEntity, runtime: ToolRuntime): self.entity = entity self.runtime = runtime diff --git a/api/core/tools/__base/tool_provider.py b/api/core/tools/__base/tool_provider.py index d1d7976cc3..49cbf70378 100644 --- a/api/core/tools/__base/tool_provider.py +++ b/api/core/tools/__base/tool_provider.py @@ -12,7 +12,7 @@ from core.tools.errors import ToolProviderCredentialValidationError class ToolProviderController(ABC): - def __init__(self, entity: ToolProviderEntity) -> None: + def __init__(self, entity: ToolProviderEntity): self.entity = entity def get_credentials_schema(self) -> list[ProviderConfig]: @@ -41,7 +41,7 @@ class ToolProviderController(ABC): """ return ToolProviderType.BUILT_IN - def validate_credentials_format(self, credentials: dict[str, Any]) -> None: + def validate_credentials_format(self, credentials: dict[str, Any]): """ validate the format of the credentials of the provider and set the default value if needed diff --git a/api/core/tools/builtin_tool/provider.py b/api/core/tools/builtin_tool/provider.py index 375a32f39d..68bfe5b4a5 100644 --- a/api/core/tools/builtin_tool/provider.py +++ b/api/core/tools/builtin_tool/provider.py @@ -24,7 +24,7 @@ from core.tools.utils.yaml_utils import load_yaml_file class BuiltinToolProviderController(ToolProviderController): tools: list[BuiltinTool] - def __init__(self, **data: Any) -> None: + def __init__(self, **data: Any): self.tools = [] # load provider yaml @@ -197,7 +197,7 @@ class BuiltinToolProviderController(ToolProviderController): """ return self.entity.identity.tags or [] - def validate_credentials(self, user_id: str, credentials: dict[str, Any]) -> None: + def validate_credentials(self, user_id: str, credentials: dict[str, Any]): """ validate the credentials of the provider @@ -211,7 +211,7 @@ class BuiltinToolProviderController(ToolProviderController): self._validate_credentials(user_id, credentials) @abstractmethod - def _validate_credentials(self, user_id: str, credentials: dict[str, Any]) -> None: + def _validate_credentials(self, user_id: str, credentials: dict[str, Any]): """ validate the credentials of the provider diff --git a/api/core/tools/builtin_tool/providers/audio/audio.py b/api/core/tools/builtin_tool/providers/audio/audio.py index d7d71161f1..abf23559ec 100644 --- a/api/core/tools/builtin_tool/providers/audio/audio.py +++ b/api/core/tools/builtin_tool/providers/audio/audio.py @@ -4,5 +4,5 @@ from core.tools.builtin_tool.provider import BuiltinToolProviderController class AudioToolProvider(BuiltinToolProviderController): - def _validate_credentials(self, user_id: str, credentials: dict[str, Any]) -> None: + def _validate_credentials(self, user_id: str, credentials: dict[str, Any]): pass diff --git a/api/core/tools/builtin_tool/providers/code/code.py b/api/core/tools/builtin_tool/providers/code/code.py index 18b7cd4c90..3e02a64e89 100644 --- a/api/core/tools/builtin_tool/providers/code/code.py +++ b/api/core/tools/builtin_tool/providers/code/code.py @@ -4,5 +4,5 @@ from core.tools.builtin_tool.provider import BuiltinToolProviderController class CodeToolProvider(BuiltinToolProviderController): - def _validate_credentials(self, user_id: str, credentials: dict[str, Any]) -> None: + def _validate_credentials(self, user_id: str, credentials: dict[str, Any]): pass diff --git a/api/core/tools/builtin_tool/providers/time/time.py b/api/core/tools/builtin_tool/providers/time/time.py index 323a7c41b8..c8f33ec56b 100644 --- a/api/core/tools/builtin_tool/providers/time/time.py +++ b/api/core/tools/builtin_tool/providers/time/time.py @@ -4,5 +4,5 @@ from core.tools.builtin_tool.provider import BuiltinToolProviderController class WikiPediaProvider(BuiltinToolProviderController): - def _validate_credentials(self, user_id: str, credentials: dict[str, Any]) -> None: + def _validate_credentials(self, user_id: str, credentials: dict[str, Any]): pass diff --git a/api/core/tools/builtin_tool/providers/webscraper/webscraper.py b/api/core/tools/builtin_tool/providers/webscraper/webscraper.py index 52c8370e0d..7d8942d420 100644 --- a/api/core/tools/builtin_tool/providers/webscraper/webscraper.py +++ b/api/core/tools/builtin_tool/providers/webscraper/webscraper.py @@ -4,7 +4,7 @@ from core.tools.builtin_tool.provider import BuiltinToolProviderController class WebscraperProvider(BuiltinToolProviderController): - def _validate_credentials(self, user_id: str, credentials: dict[str, Any]) -> None: + def _validate_credentials(self, user_id: str, credentials: dict[str, Any]): """ Validate credentials """ diff --git a/api/core/tools/custom_tool/provider.py b/api/core/tools/custom_tool/provider.py index e3dfa089dc..5790aea2b0 100644 --- a/api/core/tools/custom_tool/provider.py +++ b/api/core/tools/custom_tool/provider.py @@ -24,7 +24,7 @@ class ApiToolProviderController(ToolProviderController): tenant_id: str tools: list[ApiTool] = Field(default_factory=list) - def __init__(self, entity: ToolProviderEntity, provider_id: str, tenant_id: str) -> None: + def __init__(self, entity: ToolProviderEntity, provider_id: str, tenant_id: str): super().__init__(entity) self.provider_id = provider_id self.tenant_id = tenant_id diff --git a/api/core/tools/custom_tool/tool.py b/api/core/tools/custom_tool/tool.py index 97342640f5..190af999b1 100644 --- a/api/core/tools/custom_tool/tool.py +++ b/api/core/tools/custom_tool/tool.py @@ -302,7 +302,7 @@ class ApiTool(Tool): def _convert_body_property_any_of( self, property: dict[str, Any], value: Any, any_of: list[dict[str, Any]], max_recursive=10 - ) -> Any: + ): if max_recursive <= 0: raise Exception("Max recursion depth reached") for option in any_of or []: @@ -337,7 +337,7 @@ class ApiTool(Tool): # If no option succeeded, you might want to return the value as is or raise an error return value # or raise ValueError(f"Cannot convert value '{value}' to any specified type in anyOf") - def _convert_body_property_type(self, property: dict[str, Any], value: Any) -> Any: + def _convert_body_property_type(self, property: dict[str, Any], value: Any): try: if "type" in property: if property["type"] == "integer" or property["type"] == "int": diff --git a/api/core/tools/entities/api_entities.py b/api/core/tools/entities/api_entities.py index 48015c04ee..187406fc2d 100644 --- a/api/core/tools/entities/api_entities.py +++ b/api/core/tools/entities/api_entities.py @@ -49,7 +49,7 @@ class ToolProviderApiEntity(BaseModel): def convert_none_to_empty_list(cls, v): return v if v is not None else [] - def to_dict(self) -> dict: + def to_dict(self): # ------------- # overwrite tool parameter types for temp fix tools = jsonable_encoder(self.tools) @@ -84,7 +84,7 @@ class ToolProviderApiEntity(BaseModel): **optional_fields, } - def optional_field(self, key: str, value: Any) -> dict: + def optional_field(self, key: str, value: Any): """Return dict with key-value if value is truthy, empty dict otherwise.""" return {key: value} if value else {} diff --git a/api/core/tools/entities/common_entities.py b/api/core/tools/entities/common_entities.py index 924e6fc0cf..aadbbeb843 100644 --- a/api/core/tools/entities/common_entities.py +++ b/api/core/tools/entities/common_entities.py @@ -19,5 +19,5 @@ class I18nObject(BaseModel): self.pt_BR = self.pt_BR or self.en_US self.ja_JP = self.ja_JP or self.en_US - def to_dict(self) -> dict: + def to_dict(self): return {"zh_Hans": self.zh_Hans, "en_US": self.en_US, "pt_BR": self.pt_BR, "ja_JP": self.ja_JP} diff --git a/api/core/tools/entities/tool_entities.py b/api/core/tools/entities/tool_entities.py index df599a09a3..66304b30a5 100644 --- a/api/core/tools/entities/tool_entities.py +++ b/api/core/tools/entities/tool_entities.py @@ -150,7 +150,7 @@ class ToolInvokeMessage(BaseModel): @model_validator(mode="before") @classmethod - def transform_variable_value(cls, values) -> Any: + def transform_variable_value(cls, values): """ Only basic types and lists are allowed. """ @@ -428,7 +428,7 @@ class ToolInvokeMeta(BaseModel): """ return cls(time_cost=0.0, error=error, tool_config={}) - def to_dict(self) -> dict: + def to_dict(self): return { "time_cost": self.time_cost, "error": self.error, diff --git a/api/core/tools/mcp_tool/provider.py b/api/core/tools/mcp_tool/provider.py index 24ee981a1b..fa99cccb80 100644 --- a/api/core/tools/mcp_tool/provider.py +++ b/api/core/tools/mcp_tool/provider.py @@ -28,7 +28,7 @@ class MCPToolProviderController(ToolProviderController): headers: Optional[dict[str, str]] = None, timeout: Optional[float] = None, sse_read_timeout: Optional[float] = None, - ) -> None: + ): super().__init__(entity) self.entity: ToolProviderEntityWithPlugin = entity self.tenant_id = tenant_id @@ -99,7 +99,7 @@ class MCPToolProviderController(ToolProviderController): sse_read_timeout=db_provider.sse_read_timeout, ) - def _validate_credentials(self, user_id: str, credentials: dict[str, Any]) -> None: + def _validate_credentials(self, user_id: str, credentials: dict[str, Any]): """ validate the credentials of the provider """ diff --git a/api/core/tools/mcp_tool/tool.py b/api/core/tools/mcp_tool/tool.py index 26789b23ce..6810ac683d 100644 --- a/api/core/tools/mcp_tool/tool.py +++ b/api/core/tools/mcp_tool/tool.py @@ -23,7 +23,7 @@ class MCPTool(Tool): headers: Optional[dict[str, str]] = None, timeout: Optional[float] = None, sse_read_timeout: Optional[float] = None, - ) -> None: + ): super().__init__(entity, runtime) self.tenant_id = tenant_id self.icon = icon diff --git a/api/core/tools/plugin_tool/provider.py b/api/core/tools/plugin_tool/provider.py index 494b8e209c..3fbbd4c9e5 100644 --- a/api/core/tools/plugin_tool/provider.py +++ b/api/core/tools/plugin_tool/provider.py @@ -16,7 +16,7 @@ class PluginToolProviderController(BuiltinToolProviderController): def __init__( self, entity: ToolProviderEntityWithPlugin, plugin_id: str, plugin_unique_identifier: str, tenant_id: str - ) -> None: + ): self.entity = entity self.tenant_id = tenant_id self.plugin_id = plugin_id @@ -31,7 +31,7 @@ class PluginToolProviderController(BuiltinToolProviderController): """ return ToolProviderType.PLUGIN - def _validate_credentials(self, user_id: str, credentials: dict[str, Any]) -> None: + def _validate_credentials(self, user_id: str, credentials: dict[str, Any]): """ validate the credentials of the provider """ diff --git a/api/core/tools/plugin_tool/tool.py b/api/core/tools/plugin_tool/tool.py index db38c10e81..e649caec1d 100644 --- a/api/core/tools/plugin_tool/tool.py +++ b/api/core/tools/plugin_tool/tool.py @@ -11,7 +11,7 @@ from core.tools.entities.tool_entities import ToolEntity, ToolInvokeMessage, Too class PluginTool(Tool): def __init__( self, entity: ToolEntity, runtime: ToolRuntime, tenant_id: str, icon: str, plugin_unique_identifier: str - ) -> None: + ): super().__init__(entity, runtime) self.tenant_id = tenant_id self.icon = icon diff --git a/api/core/tools/tool_manager.py b/api/core/tools/tool_manager.py index 9897045d9b..834f58be66 100644 --- a/api/core/tools/tool_manager.py +++ b/api/core/tools/tool_manager.py @@ -778,7 +778,7 @@ class ToolManager: return controller @classmethod - def user_get_api_provider(cls, provider: str, tenant_id: str) -> dict: + def user_get_api_provider(cls, provider: str, tenant_id: str): """ get api provider """ @@ -873,7 +873,7 @@ class ToolManager: ) @classmethod - def generate_workflow_tool_icon_url(cls, tenant_id: str, provider_id: str) -> dict: + def generate_workflow_tool_icon_url(cls, tenant_id: str, provider_id: str): try: workflow_provider: WorkflowToolProvider | None = ( db.session.query(WorkflowToolProvider) @@ -890,7 +890,7 @@ class ToolManager: return {"background": "#252525", "content": "\ud83d\ude01"} @classmethod - def generate_api_tool_icon_url(cls, tenant_id: str, provider_id: str) -> dict: + def generate_api_tool_icon_url(cls, tenant_id: str, provider_id: str): try: api_provider: ApiToolProvider | None = ( db.session.query(ApiToolProvider) diff --git a/api/core/tools/utils/configuration.py b/api/core/tools/utils/configuration.py index 3a9391dbb1..3ac487a471 100644 --- a/api/core/tools/utils/configuration.py +++ b/api/core/tools/utils/configuration.py @@ -24,7 +24,7 @@ class ToolParameterConfigurationManager: def __init__( self, tenant_id: str, tool_runtime: Tool, provider_name: str, provider_type: ToolProviderType, identity_id: str - ) -> None: + ): self.tenant_id = tenant_id self.tool_runtime = tool_runtime self.provider_name = provider_name diff --git a/api/core/tools/utils/dataset_retriever_tool.py b/api/core/tools/utils/dataset_retriever_tool.py index d58807e29f..d5803e33e7 100644 --- a/api/core/tools/utils/dataset_retriever_tool.py +++ b/api/core/tools/utils/dataset_retriever_tool.py @@ -20,7 +20,7 @@ from core.tools.utils.dataset_retriever.dataset_retriever_base_tool import Datas class DatasetRetrieverTool(Tool): - def __init__(self, entity: ToolEntity, runtime: ToolRuntime, retrieval_tool: DatasetRetrieverBaseTool) -> None: + def __init__(self, entity: ToolEntity, runtime: ToolRuntime, retrieval_tool: DatasetRetrieverBaseTool): super().__init__(entity, runtime) self.retrieval_tool = retrieval_tool diff --git a/api/core/tools/utils/encryption.py b/api/core/tools/utils/encryption.py index d771293e11..5820be0ffb 100644 --- a/api/core/tools/utils/encryption.py +++ b/api/core/tools/utils/encryption.py @@ -17,11 +17,11 @@ class ProviderConfigCache(Protocol): """Get cached provider configuration""" ... - def set(self, config: dict[str, Any]) -> None: + def set(self, config: dict[str, Any]): """Cache provider configuration""" ... - def delete(self) -> None: + def delete(self): """Delete cached provider configuration""" ... diff --git a/api/core/tools/utils/parser.py b/api/core/tools/utils/parser.py index 78f1f339fa..cae21633fe 100644 --- a/api/core/tools/utils/parser.py +++ b/api/core/tools/utils/parser.py @@ -242,7 +242,7 @@ class ApiBasedToolSchemaParser: return ApiBasedToolSchemaParser.parse_openapi_to_tool_bundle(openapi, extra_info=extra_info, warning=warning) @staticmethod - def parse_swagger_to_openapi(swagger: dict, extra_info: dict | None = None, warning: dict | None = None) -> dict: + def parse_swagger_to_openapi(swagger: dict, extra_info: dict | None = None, warning: dict | None = None): warning = warning or {} """ parse swagger to openapi diff --git a/api/core/tools/utils/yaml_utils.py b/api/core/tools/utils/yaml_utils.py index ee7ca11e05..8a0a91a50c 100644 --- a/api/core/tools/utils/yaml_utils.py +++ b/api/core/tools/utils/yaml_utils.py @@ -8,7 +8,7 @@ from yaml import YAMLError logger = logging.getLogger(__name__) -def load_yaml_file(file_path: str, ignore_error: bool = True, default_value: Any = {}) -> Any: +def load_yaml_file(file_path: str, ignore_error: bool = True, default_value: Any = {}): """ Safe loading a YAML file :param file_path: the path of the YAML file diff --git a/api/core/tools/workflow_as_tool/tool.py b/api/core/tools/workflow_as_tool/tool.py index 9bcc639520..c9d62388f2 100644 --- a/api/core/tools/workflow_as_tool/tool.py +++ b/api/core/tools/workflow_as_tool/tool.py @@ -223,7 +223,7 @@ class WorkflowTool(Tool): return result, files - def _update_file_mapping(self, file_dict: dict) -> dict: + def _update_file_mapping(self, file_dict: dict): transfer_method = FileTransferMethod.value_of(file_dict.get("transfer_method")) if transfer_method == FileTransferMethod.TOOL_FILE: file_dict["tool_file_id"] = file_dict.get("related_id") diff --git a/api/core/variables/segments.py b/api/core/variables/segments.py index 9e7616874e..cfef193633 100644 --- a/api/core/variables/segments.py +++ b/api/core/variables/segments.py @@ -51,7 +51,7 @@ class Segment(BaseModel): """ return sys.getsizeof(self.value) - def to_object(self) -> Any: + def to_object(self): return self.value diff --git a/api/core/variables/types.py b/api/core/variables/types.py index 55f8ae3c72..a2e12e742b 100644 --- a/api/core/variables/types.py +++ b/api/core/variables/types.py @@ -159,7 +159,7 @@ class SegmentType(StrEnum): raise AssertionError("this statement should be unreachable.") @staticmethod - def cast_value(value: Any, type_: "SegmentType") -> Any: + def cast_value(value: Any, type_: "SegmentType"): # Cast Python's `bool` type to `int` when the runtime type requires # an integer or number. # diff --git a/api/core/variables/utils.py b/api/core/variables/utils.py index 7ebd29f865..8e738f8fd5 100644 --- a/api/core/variables/utils.py +++ b/api/core/variables/utils.py @@ -14,7 +14,7 @@ def to_selector(node_id: str, name: str, paths: Iterable[str] = ()) -> Sequence[ return selectors -def segment_orjson_default(o: Any) -> Any: +def segment_orjson_default(o: Any): """Default function for orjson serialization of Segment types""" if isinstance(o, ArrayFileSegment): return [v.model_dump() for v in o.value] diff --git a/api/core/workflow/callbacks/base_workflow_callback.py b/api/core/workflow/callbacks/base_workflow_callback.py index 83086d1afc..5f1372c659 100644 --- a/api/core/workflow/callbacks/base_workflow_callback.py +++ b/api/core/workflow/callbacks/base_workflow_callback.py @@ -5,7 +5,7 @@ from core.workflow.graph_engine.entities.event import GraphEngineEvent class WorkflowCallback(ABC): @abstractmethod - def on_event(self, event: GraphEngineEvent) -> None: + def on_event(self, event: GraphEngineEvent): """ Published event """ diff --git a/api/core/workflow/callbacks/workflow_logging_callback.py b/api/core/workflow/callbacks/workflow_logging_callback.py index 12b5203ca3..ec62be605f 100644 --- a/api/core/workflow/callbacks/workflow_logging_callback.py +++ b/api/core/workflow/callbacks/workflow_logging_callback.py @@ -36,10 +36,10 @@ _TEXT_COLOR_MAPPING = { class WorkflowLoggingCallback(WorkflowCallback): - def __init__(self) -> None: + def __init__(self): self.current_node_id: Optional[str] = None - def on_event(self, event: GraphEngineEvent) -> None: + def on_event(self, event: GraphEngineEvent): if isinstance(event, GraphRunStartedEvent): self.print_text("\n[GraphRunStartedEvent]", color="pink") elif isinstance(event, GraphRunSucceededEvent): @@ -75,7 +75,7 @@ class WorkflowLoggingCallback(WorkflowCallback): else: self.print_text(f"\n[{event.__class__.__name__}]", color="blue") - def on_workflow_node_execute_started(self, event: NodeRunStartedEvent) -> None: + def on_workflow_node_execute_started(self, event: NodeRunStartedEvent): """ Workflow node execute started """ @@ -84,7 +84,7 @@ class WorkflowLoggingCallback(WorkflowCallback): self.print_text(f"Node Title: {event.node_data.title}", color="yellow") self.print_text(f"Type: {event.node_type.value}", color="yellow") - def on_workflow_node_execute_succeeded(self, event: NodeRunSucceededEvent) -> None: + def on_workflow_node_execute_succeeded(self, event: NodeRunSucceededEvent): """ Workflow node execute succeeded """ @@ -115,7 +115,7 @@ class WorkflowLoggingCallback(WorkflowCallback): color="green", ) - def on_workflow_node_execute_failed(self, event: NodeRunFailedEvent) -> None: + def on_workflow_node_execute_failed(self, event: NodeRunFailedEvent): """ Workflow node execute failed """ @@ -143,7 +143,7 @@ class WorkflowLoggingCallback(WorkflowCallback): color="red", ) - def on_node_text_chunk(self, event: NodeRunStreamChunkEvent) -> None: + def on_node_text_chunk(self, event: NodeRunStreamChunkEvent): """ Publish text chunk """ @@ -161,7 +161,7 @@ class WorkflowLoggingCallback(WorkflowCallback): self.print_text(event.chunk_content, color="pink", end="") - def on_workflow_parallel_started(self, event: ParallelBranchRunStartedEvent) -> None: + def on_workflow_parallel_started(self, event: ParallelBranchRunStartedEvent): """ Publish parallel started """ @@ -173,9 +173,7 @@ class WorkflowLoggingCallback(WorkflowCallback): if event.in_loop_id: self.print_text(f"Loop ID: {event.in_loop_id}", color="blue") - def on_workflow_parallel_completed( - self, event: ParallelBranchRunSucceededEvent | ParallelBranchRunFailedEvent - ) -> None: + def on_workflow_parallel_completed(self, event: ParallelBranchRunSucceededEvent | ParallelBranchRunFailedEvent): """ Publish parallel completed """ @@ -200,14 +198,14 @@ class WorkflowLoggingCallback(WorkflowCallback): if isinstance(event, ParallelBranchRunFailedEvent): self.print_text(f"Error: {event.error}", color=color) - def on_workflow_iteration_started(self, event: IterationRunStartedEvent) -> None: + def on_workflow_iteration_started(self, event: IterationRunStartedEvent): """ Publish iteration started """ self.print_text("\n[IterationRunStartedEvent]", color="blue") self.print_text(f"Iteration Node ID: {event.iteration_id}", color="blue") - def on_workflow_iteration_next(self, event: IterationRunNextEvent) -> None: + def on_workflow_iteration_next(self, event: IterationRunNextEvent): """ Publish iteration next """ @@ -215,7 +213,7 @@ class WorkflowLoggingCallback(WorkflowCallback): self.print_text(f"Iteration Node ID: {event.iteration_id}", color="blue") self.print_text(f"Iteration Index: {event.index}", color="blue") - def on_workflow_iteration_completed(self, event: IterationRunSucceededEvent | IterationRunFailedEvent) -> None: + def on_workflow_iteration_completed(self, event: IterationRunSucceededEvent | IterationRunFailedEvent): """ Publish iteration completed """ @@ -227,14 +225,14 @@ class WorkflowLoggingCallback(WorkflowCallback): ) self.print_text(f"Node ID: {event.iteration_id}", color="blue") - def on_workflow_loop_started(self, event: LoopRunStartedEvent) -> None: + def on_workflow_loop_started(self, event: LoopRunStartedEvent): """ Publish loop started """ self.print_text("\n[LoopRunStartedEvent]", color="blue") self.print_text(f"Loop Node ID: {event.loop_node_id}", color="blue") - def on_workflow_loop_next(self, event: LoopRunNextEvent) -> None: + def on_workflow_loop_next(self, event: LoopRunNextEvent): """ Publish loop next """ @@ -242,7 +240,7 @@ class WorkflowLoggingCallback(WorkflowCallback): self.print_text(f"Loop Node ID: {event.loop_node_id}", color="blue") self.print_text(f"Loop Index: {event.index}", color="blue") - def on_workflow_loop_completed(self, event: LoopRunSucceededEvent | LoopRunFailedEvent) -> None: + def on_workflow_loop_completed(self, event: LoopRunSucceededEvent | LoopRunFailedEvent): """ Publish loop completed """ @@ -252,7 +250,7 @@ class WorkflowLoggingCallback(WorkflowCallback): ) self.print_text(f"Loop Node ID: {event.loop_node_id}", color="blue") - def print_text(self, text: str, color: Optional[str] = None, end: str = "\n") -> None: + def print_text(self, text: str, color: Optional[str] = None, end: str = "\n"): """Print text with highlighting and no end characters.""" text_to_print = self._get_colored_text(text, color) if color else text print(f"{text_to_print}", end=end) diff --git a/api/core/workflow/conversation_variable_updater.py b/api/core/workflow/conversation_variable_updater.py index 84e99bb582..fd78248c17 100644 --- a/api/core/workflow/conversation_variable_updater.py +++ b/api/core/workflow/conversation_variable_updater.py @@ -20,7 +20,7 @@ class ConversationVariableUpdater(Protocol): """ @abc.abstractmethod - def update(self, conversation_id: str, variable: "Variable") -> None: + def update(self, conversation_id: str, variable: "Variable"): """ Updates the value of the specified conversation variable in the underlying storage. diff --git a/api/core/workflow/entities/variable_pool.py b/api/core/workflow/entities/variable_pool.py index fb0794844e..a2c13fcbf4 100644 --- a/api/core/workflow/entities/variable_pool.py +++ b/api/core/workflow/entities/variable_pool.py @@ -47,7 +47,7 @@ class VariablePool(BaseModel): default_factory=list, ) - def model_post_init(self, context: Any, /) -> None: + def model_post_init(self, context: Any, /): # Create a mapping from field names to SystemVariableKey enum values self._add_system_variables(self.system_variables) # Add environment variables to the variable pool @@ -57,7 +57,7 @@ class VariablePool(BaseModel): for var in self.conversation_variables: self.add((CONVERSATION_VARIABLE_NODE_ID, var.name), var) - def add(self, selector: Sequence[str], value: Any, /) -> None: + def add(self, selector: Sequence[str], value: Any, /): """ Add a variable to the variable pool. @@ -161,11 +161,11 @@ class VariablePool(BaseModel): # Return result as Segment return result if isinstance(result, Segment) else variable_factory.build_segment(result) - def _extract_value(self, obj: Any) -> Any: + def _extract_value(self, obj: Any): """Extract the actual value from an ObjectSegment.""" return obj.value if isinstance(obj, ObjectSegment) else obj - def _get_nested_attribute(self, obj: Mapping[str, Any], attr: str) -> Any: + def _get_nested_attribute(self, obj: Mapping[str, Any], attr: str): """Get a nested attribute from a dictionary-like object.""" if not isinstance(obj, dict): return None diff --git a/api/core/workflow/entities/workflow_node_execution.py b/api/core/workflow/entities/workflow_node_execution.py index 09a408f4d7..ff72d7cbf3 100644 --- a/api/core/workflow/entities/workflow_node_execution.py +++ b/api/core/workflow/entities/workflow_node_execution.py @@ -112,7 +112,7 @@ class WorkflowNodeExecution(BaseModel): process_data: Optional[Mapping[str, Any]] = None, outputs: Optional[Mapping[str, Any]] = None, metadata: Optional[Mapping[WorkflowNodeExecutionMetadataKey, Any]] = None, - ) -> None: + ): """ Update the model from mappings. diff --git a/api/core/workflow/graph_engine/entities/graph.py b/api/core/workflow/graph_engine/entities/graph.py index 49984806c9..d8d1825d94 100644 --- a/api/core/workflow/graph_engine/entities/graph.py +++ b/api/core/workflow/graph_engine/entities/graph.py @@ -205,9 +205,7 @@ class Graph(BaseModel): return graph @classmethod - def _recursively_add_node_ids( - cls, node_ids: list[str], edge_mapping: dict[str, list[GraphEdge]], node_id: str - ) -> None: + def _recursively_add_node_ids(cls, node_ids: list[str], edge_mapping: dict[str, list[GraphEdge]], node_id: str): """ Recursively add node ids @@ -225,7 +223,7 @@ class Graph(BaseModel): ) @classmethod - def _check_connected_to_previous_node(cls, route: list[str], edge_mapping: dict[str, list[GraphEdge]]) -> None: + def _check_connected_to_previous_node(cls, route: list[str], edge_mapping: dict[str, list[GraphEdge]]): """ Check whether it is connected to the previous node """ @@ -256,7 +254,7 @@ class Graph(BaseModel): parallel_mapping: dict[str, GraphParallel], node_parallel_mapping: dict[str, str], parent_parallel: Optional[GraphParallel] = None, - ) -> None: + ): """ Recursively add parallel ids @@ -461,7 +459,7 @@ class Graph(BaseModel): level_limit: int, parent_parallel_id: str, current_level: int = 1, - ) -> None: + ): """ Check if it exceeds N layers of parallel """ @@ -488,7 +486,7 @@ class Graph(BaseModel): edge_mapping: dict[str, list[GraphEdge]], merge_node_id: str, start_node_id: str, - ) -> None: + ): """ Recursively add node ids @@ -614,7 +612,7 @@ class Graph(BaseModel): @classmethod def _recursively_fetch_routes( cls, edge_mapping: dict[str, list[GraphEdge]], start_node_id: str, routes_node_ids: list[str] - ) -> None: + ): """ Recursively fetch route """ diff --git a/api/core/workflow/graph_engine/entities/runtime_route_state.py b/api/core/workflow/graph_engine/entities/runtime_route_state.py index a4ddfafab5..54440df725 100644 --- a/api/core/workflow/graph_engine/entities/runtime_route_state.py +++ b/api/core/workflow/graph_engine/entities/runtime_route_state.py @@ -47,7 +47,7 @@ class RouteNodeState(BaseModel): index: int = 1 - def set_finished(self, run_result: NodeRunResult) -> None: + def set_finished(self, run_result: NodeRunResult): """ Node finished @@ -94,7 +94,7 @@ class RuntimeRouteState(BaseModel): self.node_state_mapping[state.id] = state return state - def add_route(self, source_node_state_id: str, target_node_state_id: str) -> None: + def add_route(self, source_node_state_id: str, target_node_state_id: str): """ Add route to the graph state diff --git a/api/core/workflow/graph_engine/graph_engine.py b/api/core/workflow/graph_engine/graph_engine.py index 188d0c475f..9b0b187a7c 100644 --- a/api/core/workflow/graph_engine/graph_engine.py +++ b/api/core/workflow/graph_engine/graph_engine.py @@ -66,7 +66,7 @@ class GraphEngineThreadPool(ThreadPoolExecutor): initializer=None, initargs=(), max_submit_count=dify_config.MAX_SUBMIT_COUNT, - ) -> None: + ): super().__init__(max_workers, thread_name_prefix, initializer, initargs) self.max_submit_count = max_submit_count self.submit_count = 0 @@ -80,7 +80,7 @@ class GraphEngineThreadPool(ThreadPoolExecutor): def task_done_callback(self, future): self.submit_count -= 1 - def check_is_full(self) -> None: + def check_is_full(self): if self.submit_count > self.max_submit_count: raise ValueError(f"Max submit count {self.max_submit_count} of workflow thread pool reached.") @@ -104,7 +104,7 @@ class GraphEngine: max_execution_steps: int, max_execution_time: int, thread_pool_id: Optional[str] = None, - ) -> None: + ): thread_pool_max_submit_count = dify_config.MAX_SUBMIT_COUNT thread_pool_max_workers = 10 @@ -537,7 +537,7 @@ class GraphEngine: parent_parallel_id: Optional[str] = None, parent_parallel_start_node_id: Optional[str] = None, handle_exceptions: list[str] = [], - ) -> None: + ): """ Run parallel nodes """ diff --git a/api/core/workflow/nodes/agent/agent_node.py b/api/core/workflow/nodes/agent/agent_node.py index 9e5d5e62b4..2e5912652c 100644 --- a/api/core/workflow/nodes/agent/agent_node.py +++ b/api/core/workflow/nodes/agent/agent_node.py @@ -66,7 +66,7 @@ class AgentNode(BaseNode): _node_type = NodeType.AGENT _node_data: AgentNodeData - def init_node_data(self, data: Mapping[str, Any]) -> None: + def init_node_data(self, data: Mapping[str, Any]): self._node_data = AgentNodeData.model_validate(data) def _get_error_strategy(self) -> Optional[ErrorStrategy]: diff --git a/api/core/workflow/nodes/answer/answer_node.py b/api/core/workflow/nodes/answer/answer_node.py index 84bbabca73..116250c5ca 100644 --- a/api/core/workflow/nodes/answer/answer_node.py +++ b/api/core/workflow/nodes/answer/answer_node.py @@ -22,7 +22,7 @@ class AnswerNode(BaseNode): _node_data: AnswerNodeData - def init_node_data(self, data: Mapping[str, Any]) -> None: + def init_node_data(self, data: Mapping[str, Any]): self._node_data = AnswerNodeData.model_validate(data) def _get_error_strategy(self) -> Optional[ErrorStrategy]: diff --git a/api/core/workflow/nodes/answer/answer_stream_generate_router.py b/api/core/workflow/nodes/answer/answer_stream_generate_router.py index 1d9c3e9b96..216fe9b676 100644 --- a/api/core/workflow/nodes/answer/answer_stream_generate_router.py +++ b/api/core/workflow/nodes/answer/answer_stream_generate_router.py @@ -134,7 +134,7 @@ class AnswerStreamGeneratorRouter: node_id_config_mapping: dict[str, dict], reverse_edge_mapping: dict[str, list["GraphEdge"]], # type: ignore[name-defined] answer_dependencies: dict[str, list[str]], - ) -> None: + ): """ Recursive fetch answer dependencies :param current_node_id: current node id diff --git a/api/core/workflow/nodes/answer/answer_stream_processor.py b/api/core/workflow/nodes/answer/answer_stream_processor.py index a30014299a..2b1070f5eb 100644 --- a/api/core/workflow/nodes/answer/answer_stream_processor.py +++ b/api/core/workflow/nodes/answer/answer_stream_processor.py @@ -18,7 +18,7 @@ logger = logging.getLogger(__name__) class AnswerStreamProcessor(StreamProcessor): - def __init__(self, graph: Graph, variable_pool: VariablePool) -> None: + def __init__(self, graph: Graph, variable_pool: VariablePool): super().__init__(graph, variable_pool) self.generate_routes = graph.answer_stream_generate_routes self.route_position = {} @@ -66,7 +66,7 @@ class AnswerStreamProcessor(StreamProcessor): else: yield event - def reset(self) -> None: + def reset(self): self.route_position = {} for answer_node_id, _ in self.generate_routes.answer_generate_route.items(): self.route_position[answer_node_id] = 0 diff --git a/api/core/workflow/nodes/answer/base_stream_processor.py b/api/core/workflow/nodes/answer/base_stream_processor.py index 7e84557a2d..9e8e1787e5 100644 --- a/api/core/workflow/nodes/answer/base_stream_processor.py +++ b/api/core/workflow/nodes/answer/base_stream_processor.py @@ -11,7 +11,7 @@ logger = logging.getLogger(__name__) class StreamProcessor(ABC): - def __init__(self, graph: Graph, variable_pool: VariablePool) -> None: + def __init__(self, graph: Graph, variable_pool: VariablePool): self.graph = graph self.variable_pool = variable_pool self.rest_node_ids = graph.node_ids.copy() @@ -20,7 +20,7 @@ class StreamProcessor(ABC): def process(self, generator: Generator[GraphEngineEvent, None, None]) -> Generator[GraphEngineEvent, None, None]: raise NotImplementedError - def _remove_unreachable_nodes(self, event: NodeRunSucceededEvent | NodeRunExceptionEvent) -> None: + def _remove_unreachable_nodes(self, event: NodeRunSucceededEvent | NodeRunExceptionEvent): finished_node_id = event.route_node_state.node_id if finished_node_id not in self.rest_node_ids: return @@ -89,7 +89,7 @@ class StreamProcessor(ABC): node_ids.extend(self._fetch_node_ids_in_reachable_branch(edge.target_node_id, branch_identify)) return node_ids - def _remove_node_ids_in_unreachable_branch(self, node_id: str, reachable_node_ids: list[str]) -> None: + def _remove_node_ids_in_unreachable_branch(self, node_id: str, reachable_node_ids: list[str]): """ remove target node ids until merge """ diff --git a/api/core/workflow/nodes/base/entities.py b/api/core/workflow/nodes/base/entities.py index dcfed5eed2..708da21177 100644 --- a/api/core/workflow/nodes/base/entities.py +++ b/api/core/workflow/nodes/base/entities.py @@ -28,7 +28,7 @@ class DefaultValue(BaseModel): key: str @staticmethod - def _parse_json(value: str) -> Any: + def _parse_json(value: str): """Unified JSON parsing handler""" try: return json.loads(value) diff --git a/api/core/workflow/nodes/base/node.py b/api/core/workflow/nodes/base/node.py index be4f79af19..3aee9b2cc2 100644 --- a/api/core/workflow/nodes/base/node.py +++ b/api/core/workflow/nodes/base/node.py @@ -28,7 +28,7 @@ class BaseNode: graph_runtime_state: "GraphRuntimeState", previous_node_id: Optional[str] = None, thread_pool_id: Optional[str] = None, - ) -> None: + ): self.id = id self.tenant_id = graph_init_params.tenant_id self.app_id = graph_init_params.app_id @@ -51,7 +51,7 @@ class BaseNode: self.node_id = node_id @abstractmethod - def init_node_data(self, data: Mapping[str, Any]) -> None: ... + def init_node_data(self, data: Mapping[str, Any]): ... @abstractmethod def _run(self) -> NodeRunResult | Generator[Union[NodeEvent, "InNodeEvent"], None, None]: @@ -141,7 +141,7 @@ class BaseNode: return {} @classmethod - def get_default_config(cls, filters: Optional[dict] = None) -> dict: + def get_default_config(cls, filters: Optional[dict] = None): return {} @property diff --git a/api/core/workflow/nodes/code/code_node.py b/api/core/workflow/nodes/code/code_node.py index 17bd841fc9..d32d868651 100644 --- a/api/core/workflow/nodes/code/code_node.py +++ b/api/core/workflow/nodes/code/code_node.py @@ -28,7 +28,7 @@ class CodeNode(BaseNode): _node_data: CodeNodeData - def init_node_data(self, data: Mapping[str, Any]) -> None: + def init_node_data(self, data: Mapping[str, Any]): self._node_data = CodeNodeData.model_validate(data) def _get_error_strategy(self) -> Optional[ErrorStrategy]: @@ -50,7 +50,7 @@ class CodeNode(BaseNode): return self._node_data @classmethod - def get_default_config(cls, filters: Optional[dict] = None) -> dict: + def get_default_config(cls, filters: Optional[dict] = None): """ Get default config of node. :param filters: filter by node config parameters. diff --git a/api/core/workflow/nodes/document_extractor/node.py b/api/core/workflow/nodes/document_extractor/node.py index 125b84501c..7848bab446 100644 --- a/api/core/workflow/nodes/document_extractor/node.py +++ b/api/core/workflow/nodes/document_extractor/node.py @@ -47,7 +47,7 @@ class DocumentExtractorNode(BaseNode): _node_data: DocumentExtractorNodeData - def init_node_data(self, data: Mapping[str, Any]) -> None: + def init_node_data(self, data: Mapping[str, Any]): self._node_data = DocumentExtractorNodeData.model_validate(data) def _get_error_strategy(self) -> Optional[ErrorStrategy]: diff --git a/api/core/workflow/nodes/end/end_node.py b/api/core/workflow/nodes/end/end_node.py index f86f2e8129..0aff039e92 100644 --- a/api/core/workflow/nodes/end/end_node.py +++ b/api/core/workflow/nodes/end/end_node.py @@ -14,7 +14,7 @@ class EndNode(BaseNode): _node_data: EndNodeData - def init_node_data(self, data: Mapping[str, Any]) -> None: + def init_node_data(self, data: Mapping[str, Any]): self._node_data = EndNodeData(**data) def _get_error_strategy(self) -> Optional[ErrorStrategy]: diff --git a/api/core/workflow/nodes/end/end_stream_generate_router.py b/api/core/workflow/nodes/end/end_stream_generate_router.py index b3678a82b7..495ed6ea20 100644 --- a/api/core/workflow/nodes/end/end_stream_generate_router.py +++ b/api/core/workflow/nodes/end/end_stream_generate_router.py @@ -121,7 +121,7 @@ class EndStreamGeneratorRouter: node_id_config_mapping: dict[str, dict], reverse_edge_mapping: dict[str, list["GraphEdge"]], # type: ignore[name-defined] end_dependencies: dict[str, list[str]], - ) -> None: + ): """ Recursive fetch end dependencies :param current_node_id: current node id diff --git a/api/core/workflow/nodes/end/end_stream_processor.py b/api/core/workflow/nodes/end/end_stream_processor.py index a6fb2ffc18..7e426fee79 100644 --- a/api/core/workflow/nodes/end/end_stream_processor.py +++ b/api/core/workflow/nodes/end/end_stream_processor.py @@ -15,7 +15,7 @@ logger = logging.getLogger(__name__) class EndStreamProcessor(StreamProcessor): - def __init__(self, graph: Graph, variable_pool: VariablePool) -> None: + def __init__(self, graph: Graph, variable_pool: VariablePool): super().__init__(graph, variable_pool) self.end_stream_param = graph.end_stream_param self.route_position = {} @@ -76,7 +76,7 @@ class EndStreamProcessor(StreamProcessor): else: yield event - def reset(self) -> None: + def reset(self): self.route_position = {} for end_node_id, _ in self.end_stream_param.end_stream_variable_selector_mapping.items(): self.route_position[end_node_id] = 0 diff --git a/api/core/workflow/nodes/http_request/node.py b/api/core/workflow/nodes/http_request/node.py index bc1d5c9b87..bb3c453d99 100644 --- a/api/core/workflow/nodes/http_request/node.py +++ b/api/core/workflow/nodes/http_request/node.py @@ -38,7 +38,7 @@ class HttpRequestNode(BaseNode): _node_data: HttpRequestNodeData - def init_node_data(self, data: Mapping[str, Any]) -> None: + def init_node_data(self, data: Mapping[str, Any]): self._node_data = HttpRequestNodeData.model_validate(data) def _get_error_strategy(self) -> Optional[ErrorStrategy]: @@ -60,7 +60,7 @@ class HttpRequestNode(BaseNode): return self._node_data @classmethod - def get_default_config(cls, filters: Optional[dict[str, Any]] = None) -> dict: + def get_default_config(cls, filters: Optional[dict[str, Any]] = None): return { "type": "http-request", "config": { diff --git a/api/core/workflow/nodes/if_else/if_else_node.py b/api/core/workflow/nodes/if_else/if_else_node.py index c2bed870b0..82dba59cbe 100644 --- a/api/core/workflow/nodes/if_else/if_else_node.py +++ b/api/core/workflow/nodes/if_else/if_else_node.py @@ -19,7 +19,7 @@ class IfElseNode(BaseNode): _node_data: IfElseNodeData - def init_node_data(self, data: Mapping[str, Any]) -> None: + def init_node_data(self, data: Mapping[str, Any]): self._node_data = IfElseNodeData.model_validate(data) def _get_error_strategy(self) -> Optional[ErrorStrategy]: diff --git a/api/core/workflow/nodes/iteration/iteration_node.py b/api/core/workflow/nodes/iteration/iteration_node.py index 9deac1748a..9037677df9 100644 --- a/api/core/workflow/nodes/iteration/iteration_node.py +++ b/api/core/workflow/nodes/iteration/iteration_node.py @@ -67,7 +67,7 @@ class IterationNode(BaseNode): _node_data: IterationNodeData - def init_node_data(self, data: Mapping[str, Any]) -> None: + def init_node_data(self, data: Mapping[str, Any]): self._node_data = IterationNodeData.model_validate(data) def _get_error_strategy(self) -> Optional[ErrorStrategy]: @@ -89,7 +89,7 @@ class IterationNode(BaseNode): return self._node_data @classmethod - def get_default_config(cls, filters: Optional[dict] = None) -> dict: + def get_default_config(cls, filters: Optional[dict] = None): return { "type": "iteration", "config": { diff --git a/api/core/workflow/nodes/iteration/iteration_start_node.py b/api/core/workflow/nodes/iteration/iteration_start_node.py index b82c29291a..8c4794cf37 100644 --- a/api/core/workflow/nodes/iteration/iteration_start_node.py +++ b/api/core/workflow/nodes/iteration/iteration_start_node.py @@ -18,7 +18,7 @@ class IterationStartNode(BaseNode): _node_data: IterationStartNodeData - def init_node_data(self, data: Mapping[str, Any]) -> None: + def init_node_data(self, data: Mapping[str, Any]): self._node_data = IterationStartNodeData(**data) def _get_error_strategy(self) -> Optional[ErrorStrategy]: diff --git a/api/core/workflow/nodes/knowledge_retrieval/knowledge_retrieval_node.py b/api/core/workflow/nodes/knowledge_retrieval/knowledge_retrieval_node.py index 949a05d052..d357fea7dd 100644 --- a/api/core/workflow/nodes/knowledge_retrieval/knowledge_retrieval_node.py +++ b/api/core/workflow/nodes/knowledge_retrieval/knowledge_retrieval_node.py @@ -105,7 +105,7 @@ class KnowledgeRetrievalNode(BaseNode): thread_pool_id: Optional[str] = None, *, llm_file_saver: LLMFileSaver | None = None, - ) -> None: + ): super().__init__( id=id, config=config, @@ -125,7 +125,7 @@ class KnowledgeRetrievalNode(BaseNode): ) self._llm_file_saver = llm_file_saver - def init_node_data(self, data: Mapping[str, Any]) -> None: + def init_node_data(self, data: Mapping[str, Any]): self._node_data = KnowledgeRetrievalNodeData.model_validate(data) def _get_error_strategy(self) -> Optional[ErrorStrategy]: diff --git a/api/core/workflow/nodes/list_operator/node.py b/api/core/workflow/nodes/list_operator/node.py index a727a826c6..eb7b9fc2c6 100644 --- a/api/core/workflow/nodes/list_operator/node.py +++ b/api/core/workflow/nodes/list_operator/node.py @@ -41,7 +41,7 @@ class ListOperatorNode(BaseNode): _node_data: ListOperatorNodeData - def init_node_data(self, data: Mapping[str, Any]) -> None: + def init_node_data(self, data: Mapping[str, Any]): self._node_data = ListOperatorNodeData(**data) def _get_error_strategy(self) -> Optional[ErrorStrategy]: diff --git a/api/core/workflow/nodes/llm/exc.py b/api/core/workflow/nodes/llm/exc.py index 42b8f4e6ce..4d16095296 100644 --- a/api/core/workflow/nodes/llm/exc.py +++ b/api/core/workflow/nodes/llm/exc.py @@ -41,5 +41,5 @@ class FileTypeNotSupportError(LLMNodeError): class UnsupportedPromptContentTypeError(LLMNodeError): - def __init__(self, *, type_name: str) -> None: + def __init__(self, *, type_name: str): super().__init__(f"Prompt content type {type_name} is not supported.") diff --git a/api/core/workflow/nodes/llm/llm_utils.py b/api/core/workflow/nodes/llm/llm_utils.py index 2441e30c87..fae127ab76 100644 --- a/api/core/workflow/nodes/llm/llm_utils.py +++ b/api/core/workflow/nodes/llm/llm_utils.py @@ -107,7 +107,7 @@ def fetch_memory( return memory -def deduct_llm_quota(tenant_id: str, model_instance: ModelInstance, usage: LLMUsage) -> None: +def deduct_llm_quota(tenant_id: str, model_instance: ModelInstance, usage: LLMUsage): provider_model_bundle = model_instance.provider_model_bundle provider_configuration = provider_model_bundle.configuration diff --git a/api/core/workflow/nodes/llm/node.py b/api/core/workflow/nodes/llm/node.py index 37c4ecfd6b..c34a06d981 100644 --- a/api/core/workflow/nodes/llm/node.py +++ b/api/core/workflow/nodes/llm/node.py @@ -120,7 +120,7 @@ class LLMNode(BaseNode): thread_pool_id: Optional[str] = None, *, llm_file_saver: LLMFileSaver | None = None, - ) -> None: + ): super().__init__( id=id, config=config, @@ -140,7 +140,7 @@ class LLMNode(BaseNode): ) self._llm_file_saver = llm_file_saver - def init_node_data(self, data: Mapping[str, Any]) -> None: + def init_node_data(self, data: Mapping[str, Any]): self._node_data = LLMNodeData.model_validate(data) def _get_error_strategy(self) -> Optional[ErrorStrategy]: @@ -951,7 +951,7 @@ class LLMNode(BaseNode): return variable_mapping @classmethod - def get_default_config(cls, filters: Optional[dict] = None) -> dict: + def get_default_config(cls, filters: Optional[dict] = None): return { "type": "llm", "config": { diff --git a/api/core/workflow/nodes/loop/loop_end_node.py b/api/core/workflow/nodes/loop/loop_end_node.py index 53cadc5251..892ae88b04 100644 --- a/api/core/workflow/nodes/loop/loop_end_node.py +++ b/api/core/workflow/nodes/loop/loop_end_node.py @@ -18,7 +18,7 @@ class LoopEndNode(BaseNode): _node_data: LoopEndNodeData - def init_node_data(self, data: Mapping[str, Any]) -> None: + def init_node_data(self, data: Mapping[str, Any]): self._node_data = LoopEndNodeData(**data) def _get_error_strategy(self) -> Optional[ErrorStrategy]: diff --git a/api/core/workflow/nodes/loop/loop_node.py b/api/core/workflow/nodes/loop/loop_node.py index ae3927a89a..2fe3fb5567 100644 --- a/api/core/workflow/nodes/loop/loop_node.py +++ b/api/core/workflow/nodes/loop/loop_node.py @@ -54,7 +54,7 @@ class LoopNode(BaseNode): _node_data: LoopNodeData - def init_node_data(self, data: Mapping[str, Any]) -> None: + def init_node_data(self, data: Mapping[str, Any]): self._node_data = LoopNodeData.model_validate(data) def _get_error_strategy(self) -> Optional[ErrorStrategy]: diff --git a/api/core/workflow/nodes/loop/loop_start_node.py b/api/core/workflow/nodes/loop/loop_start_node.py index 29b45ea0c3..f5a20fc009 100644 --- a/api/core/workflow/nodes/loop/loop_start_node.py +++ b/api/core/workflow/nodes/loop/loop_start_node.py @@ -18,7 +18,7 @@ class LoopStartNode(BaseNode): _node_data: LoopStartNodeData - def init_node_data(self, data: Mapping[str, Any]) -> None: + def init_node_data(self, data: Mapping[str, Any]): self._node_data = LoopStartNodeData(**data) def _get_error_strategy(self) -> Optional[ErrorStrategy]: diff --git a/api/core/workflow/nodes/parameter_extractor/entities.py b/api/core/workflow/nodes/parameter_extractor/entities.py index 4e93cd9688..2739140224 100644 --- a/api/core/workflow/nodes/parameter_extractor/entities.py +++ b/api/core/workflow/nodes/parameter_extractor/entities.py @@ -98,7 +98,7 @@ class ParameterExtractorNodeData(BaseNodeData): def set_reasoning_mode(cls, v) -> str: return v or "function_call" - def get_parameter_json_schema(self) -> dict: + def get_parameter_json_schema(self): """ Get parameter json schema. diff --git a/api/core/workflow/nodes/parameter_extractor/exc.py b/api/core/workflow/nodes/parameter_extractor/exc.py index 247518cf20..a1707a2461 100644 --- a/api/core/workflow/nodes/parameter_extractor/exc.py +++ b/api/core/workflow/nodes/parameter_extractor/exc.py @@ -63,7 +63,7 @@ class InvalidValueTypeError(ParameterExtractorNodeError): expected_type: SegmentType, actual_type: SegmentType | None, value: Any, - ) -> None: + ): message = ( f"Invalid value for parameter {parameter_name}, expected segment type: {expected_type}, " f"actual_type: {actual_type}, python_type: {type(value)}, value: {value}" diff --git a/api/core/workflow/nodes/parameter_extractor/parameter_extractor_node.py b/api/core/workflow/nodes/parameter_extractor/parameter_extractor_node.py index 43edf7eac6..a854c7e87e 100644 --- a/api/core/workflow/nodes/parameter_extractor/parameter_extractor_node.py +++ b/api/core/workflow/nodes/parameter_extractor/parameter_extractor_node.py @@ -94,7 +94,7 @@ class ParameterExtractorNode(BaseNode): _node_data: ParameterExtractorNodeData - def init_node_data(self, data: Mapping[str, Any]) -> None: + def init_node_data(self, data: Mapping[str, Any]): self._node_data = ParameterExtractorNodeData.model_validate(data) def _get_error_strategy(self) -> Optional[ErrorStrategy]: @@ -119,7 +119,7 @@ class ParameterExtractorNode(BaseNode): _model_config: Optional[ModelConfigWithCredentialsEntity] = None @classmethod - def get_default_config(cls, filters: Optional[dict] = None) -> dict: + def get_default_config(cls, filters: Optional[dict] = None): return { "model": { "prompt_templates": { @@ -545,7 +545,7 @@ class ParameterExtractorNode(BaseNode): return prompt_messages - def _validate_result(self, data: ParameterExtractorNodeData, result: dict) -> dict: + def _validate_result(self, data: ParameterExtractorNodeData, result: dict): if len(data.parameters) != len(result): raise InvalidNumberOfParametersError("Invalid number of parameters") @@ -597,7 +597,7 @@ class ParameterExtractorNode(BaseNode): except ValueError: return None - def _transform_result(self, data: ParameterExtractorNodeData, result: dict) -> dict: + def _transform_result(self, data: ParameterExtractorNodeData, result: dict): """ Transform result into standard format. """ @@ -690,7 +690,7 @@ class ParameterExtractorNode(BaseNode): logger.info("extra error: %s", result) return None - def _generate_default_result(self, data: ParameterExtractorNodeData) -> dict: + def _generate_default_result(self, data: ParameterExtractorNodeData): """ Generate default result. """ diff --git a/api/core/workflow/nodes/question_classifier/question_classifier_node.py b/api/core/workflow/nodes/question_classifier/question_classifier_node.py index ba4e55bb89..07fb658f24 100644 --- a/api/core/workflow/nodes/question_classifier/question_classifier_node.py +++ b/api/core/workflow/nodes/question_classifier/question_classifier_node.py @@ -63,7 +63,7 @@ class QuestionClassifierNode(BaseNode): thread_pool_id: Optional[str] = None, *, llm_file_saver: LLMFileSaver | None = None, - ) -> None: + ): super().__init__( id=id, config=config, @@ -83,7 +83,7 @@ class QuestionClassifierNode(BaseNode): ) self._llm_file_saver = llm_file_saver - def init_node_data(self, data: Mapping[str, Any]) -> None: + def init_node_data(self, data: Mapping[str, Any]): self._node_data = QuestionClassifierNodeData.model_validate(data) def _get_error_strategy(self) -> Optional[ErrorStrategy]: @@ -275,7 +275,7 @@ class QuestionClassifierNode(BaseNode): return variable_mapping @classmethod - def get_default_config(cls, filters: Optional[dict] = None) -> dict: + def get_default_config(cls, filters: Optional[dict] = None): """ Get default config of node. :param filters: filter by node config parameters. diff --git a/api/core/workflow/nodes/start/start_node.py b/api/core/workflow/nodes/start/start_node.py index 9e401e76bb..6052774e6c 100644 --- a/api/core/workflow/nodes/start/start_node.py +++ b/api/core/workflow/nodes/start/start_node.py @@ -15,7 +15,7 @@ class StartNode(BaseNode): _node_data: StartNodeData - def init_node_data(self, data: Mapping[str, Any]) -> None: + def init_node_data(self, data: Mapping[str, Any]): self._node_data = StartNodeData(**data) def _get_error_strategy(self) -> Optional[ErrorStrategy]: diff --git a/api/core/workflow/nodes/template_transform/template_transform_node.py b/api/core/workflow/nodes/template_transform/template_transform_node.py index 1962c82db1..5588463a36 100644 --- a/api/core/workflow/nodes/template_transform/template_transform_node.py +++ b/api/core/workflow/nodes/template_transform/template_transform_node.py @@ -18,7 +18,7 @@ class TemplateTransformNode(BaseNode): _node_data: TemplateTransformNodeData - def init_node_data(self, data: Mapping[str, Any]) -> None: + def init_node_data(self, data: Mapping[str, Any]): self._node_data = TemplateTransformNodeData.model_validate(data) def _get_error_strategy(self) -> Optional[ErrorStrategy]: @@ -40,7 +40,7 @@ class TemplateTransformNode(BaseNode): return self._node_data @classmethod - def get_default_config(cls, filters: Optional[dict] = None) -> dict: + def get_default_config(cls, filters: Optional[dict] = None): """ Get default config of node. :param filters: filter by node config parameters. diff --git a/api/core/workflow/nodes/tool/tool_node.py b/api/core/workflow/nodes/tool/tool_node.py index 1a85c08b5b..c4caf5d83b 100644 --- a/api/core/workflow/nodes/tool/tool_node.py +++ b/api/core/workflow/nodes/tool/tool_node.py @@ -45,7 +45,7 @@ class ToolNode(BaseNode): _node_data: ToolNodeData - def init_node_data(self, data: Mapping[str, Any]) -> None: + def init_node_data(self, data: Mapping[str, Any]): self._node_data = ToolNodeData.model_validate(data) @classmethod diff --git a/api/core/workflow/nodes/variable_aggregator/variable_aggregator_node.py b/api/core/workflow/nodes/variable_aggregator/variable_aggregator_node.py index 98127bbeb6..cc5092d0a9 100644 --- a/api/core/workflow/nodes/variable_aggregator/variable_aggregator_node.py +++ b/api/core/workflow/nodes/variable_aggregator/variable_aggregator_node.py @@ -15,7 +15,7 @@ class VariableAggregatorNode(BaseNode): _node_data: VariableAssignerNodeData - def init_node_data(self, data: Mapping[str, Any]) -> None: + def init_node_data(self, data: Mapping[str, Any]): self._node_data = VariableAssignerNodeData(**data) def _get_error_strategy(self) -> Optional[ErrorStrategy]: diff --git a/api/core/workflow/nodes/variable_assigner/common/impl.py b/api/core/workflow/nodes/variable_assigner/common/impl.py index 8f7a44bb62..5292a9e447 100644 --- a/api/core/workflow/nodes/variable_assigner/common/impl.py +++ b/api/core/workflow/nodes/variable_assigner/common/impl.py @@ -11,7 +11,7 @@ from .exc import VariableOperatorNodeError class ConversationVariableUpdaterImpl: _engine: Engine | None - def __init__(self, engine: Engine | None = None) -> None: + def __init__(self, engine: Engine | None = None): self._engine = engine def _get_engine(self) -> Engine: diff --git a/api/core/workflow/nodes/variable_assigner/v1/node.py b/api/core/workflow/nodes/variable_assigner/v1/node.py index 321d280b1f..263c5a3893 100644 --- a/api/core/workflow/nodes/variable_assigner/v1/node.py +++ b/api/core/workflow/nodes/variable_assigner/v1/node.py @@ -30,7 +30,7 @@ class VariableAssignerNode(BaseNode): _node_data: VariableAssignerData - def init_node_data(self, data: Mapping[str, Any]) -> None: + def init_node_data(self, data: Mapping[str, Any]): self._node_data = VariableAssignerData.model_validate(data) def _get_error_strategy(self) -> Optional[ErrorStrategy]: @@ -61,7 +61,7 @@ class VariableAssignerNode(BaseNode): previous_node_id: Optional[str] = None, thread_pool_id: Optional[str] = None, conv_var_updater_factory: _CONV_VAR_UPDATER_FACTORY = conversation_variable_updater_factory, - ) -> None: + ): super().__init__( id=id, config=config, diff --git a/api/core/workflow/nodes/variable_assigner/v2/exc.py b/api/core/workflow/nodes/variable_assigner/v2/exc.py index fd6c304a9a..05173b3ca1 100644 --- a/api/core/workflow/nodes/variable_assigner/v2/exc.py +++ b/api/core/workflow/nodes/variable_assigner/v2/exc.py @@ -32,5 +32,5 @@ class ConversationIDNotFoundError(VariableOperatorNodeError): class InvalidDataError(VariableOperatorNodeError): - def __init__(self, message: str) -> None: + def __init__(self, message: str): super().__init__(message) diff --git a/api/core/workflow/nodes/variable_assigner/v2/node.py b/api/core/workflow/nodes/variable_assigner/v2/node.py index 00ee921cee..fdd155adf9 100644 --- a/api/core/workflow/nodes/variable_assigner/v2/node.py +++ b/api/core/workflow/nodes/variable_assigner/v2/node.py @@ -58,7 +58,7 @@ class VariableAssignerNode(BaseNode): _node_data: VariableAssignerNodeData - def init_node_data(self, data: Mapping[str, Any]) -> None: + def init_node_data(self, data: Mapping[str, Any]): self._node_data = VariableAssignerNodeData.model_validate(data) def _get_error_strategy(self) -> Optional[ErrorStrategy]: diff --git a/api/core/workflow/repositories/workflow_execution_repository.py b/api/core/workflow/repositories/workflow_execution_repository.py index bcbd253392..1e2bd79c74 100644 --- a/api/core/workflow/repositories/workflow_execution_repository.py +++ b/api/core/workflow/repositories/workflow_execution_repository.py @@ -16,7 +16,7 @@ class WorkflowExecutionRepository(Protocol): application domains or deployment scenarios. """ - def save(self, execution: WorkflowExecution) -> None: + def save(self, execution: WorkflowExecution): """ Save or update a WorkflowExecution instance. diff --git a/api/core/workflow/repositories/workflow_node_execution_repository.py b/api/core/workflow/repositories/workflow_node_execution_repository.py index 8bf81f5442..f4668c05c5 100644 --- a/api/core/workflow/repositories/workflow_node_execution_repository.py +++ b/api/core/workflow/repositories/workflow_node_execution_repository.py @@ -26,7 +26,7 @@ class WorkflowNodeExecutionRepository(Protocol): application domains or deployment scenarios. """ - def save(self, execution: WorkflowNodeExecution) -> None: + def save(self, execution: WorkflowNodeExecution): """ Save or update a NodeExecution instance. diff --git a/api/core/workflow/utils/variable_template_parser.py b/api/core/workflow/utils/variable_template_parser.py index f86c54c50a..a6dd98db5f 100644 --- a/api/core/workflow/utils/variable_template_parser.py +++ b/api/core/workflow/utils/variable_template_parser.py @@ -57,7 +57,7 @@ class VariableTemplateParser: self.template = template self.variable_keys = self.extract() - def extract(self) -> list: + def extract(self): """ Extracts all the template variable keys from the template string. diff --git a/api/core/workflow/workflow_cycle_manager.py b/api/core/workflow/workflow_cycle_manager.py index 3c264e782d..4f259b64a2 100644 --- a/api/core/workflow/workflow_cycle_manager.py +++ b/api/core/workflow/workflow_cycle_manager.py @@ -48,7 +48,7 @@ class WorkflowCycleManager: workflow_info: CycleManagerWorkflowInfo, workflow_execution_repository: WorkflowExecutionRepository, workflow_node_execution_repository: WorkflowNodeExecutionRepository, - ) -> None: + ): self._application_generate_entity = application_generate_entity self._workflow_system_variables = workflow_system_variables self._workflow_info = workflow_info @@ -299,7 +299,7 @@ class WorkflowCycleManager: error_message: Optional[str] = None, exceptions_count: int = 0, finished_at: Optional[datetime] = None, - ) -> None: + ): """Update workflow execution with completion data.""" execution.status = status execution.outputs = outputs or {} @@ -316,7 +316,7 @@ class WorkflowCycleManager: workflow_execution: WorkflowExecution, conversation_id: Optional[str], external_trace_id: Optional[str], - ) -> None: + ): """Add trace task if trace manager is provided.""" if trace_manager: trace_manager.add_trace_task( @@ -334,7 +334,7 @@ class WorkflowCycleManager: workflow_execution_id: str, error_message: str, now: datetime, - ) -> None: + ): """Fail all running node executions for a workflow.""" running_node_executions = [ node_exec @@ -406,7 +406,7 @@ class WorkflowCycleManager: status: WorkflowNodeExecutionStatus, error: Optional[str] = None, handle_special_values: bool = False, - ) -> None: + ): """Update node execution with completion data.""" finished_at = naive_utc_now() elapsed_time = (finished_at - event.start_at).total_seconds() diff --git a/api/core/workflow/workflow_entry.py b/api/core/workflow/workflow_entry.py index e9b73df0f3..b69a9971b5 100644 --- a/api/core/workflow/workflow_entry.py +++ b/api/core/workflow/workflow_entry.py @@ -48,7 +48,7 @@ class WorkflowEntry: call_depth: int, variable_pool: VariablePool, thread_pool_id: Optional[str] = None, - ) -> None: + ): """ Init workflow entry :param tenant_id: tenant id @@ -320,7 +320,7 @@ class WorkflowEntry: return result if isinstance(result, Mapping) or result is None else dict(result) @staticmethod - def _handle_special_values(value: Any) -> Any: + def _handle_special_values(value: Any): if value is None: return value if isinstance(value, dict): @@ -345,7 +345,7 @@ class WorkflowEntry: user_inputs: Mapping[str, Any], variable_pool: VariablePool, tenant_id: str, - ) -> None: + ): # NOTE(QuantumGhost): This logic should remain synchronized with # the implementation of `load_into_variable_pool`, specifically the logic about # variable existence checking. diff --git a/api/core/workflow/workflow_type_encoder.py b/api/core/workflow/workflow_type_encoder.py index 08e12e2681..6eac2dd6b4 100644 --- a/api/core/workflow/workflow_type_encoder.py +++ b/api/core/workflow/workflow_type_encoder.py @@ -13,7 +13,7 @@ class WorkflowRuntimeTypeConverter: result = self._to_json_encodable_recursive(value) return result if isinstance(result, Mapping) or result is None else dict(result) - def _to_json_encodable_recursive(self, value: Any) -> Any: + def _to_json_encodable_recursive(self, value: Any): if value is None: return value if isinstance(value, (bool, int, str, float)): diff --git a/api/events/event_handlers/update_provider_when_message_created.py b/api/events/event_handlers/update_provider_when_message_created.py index 5b6c1511c8..21fd0b9c5b 100644 --- a/api/events/event_handlers/update_provider_when_message_created.py +++ b/api/events/event_handlers/update_provider_when_message_created.py @@ -42,7 +42,7 @@ def _get_last_update_timestamp(cache_key: str) -> Optional[datetime]: @redis_fallback() -def _set_last_update_timestamp(cache_key: str, timestamp: datetime) -> None: +def _set_last_update_timestamp(cache_key: str, timestamp: datetime): """Set last update timestamp in Redis cache with TTL.""" redis_client.setex(cache_key, _CACHE_TTL_SECONDS, str(timestamp.timestamp())) diff --git a/api/extensions/ext_database.py b/api/extensions/ext_database.py index b32616b172..db16b60963 100644 --- a/api/extensions/ext_database.py +++ b/api/extensions/ext_database.py @@ -13,7 +13,7 @@ logger = logging.getLogger(__name__) _GEVENT_COMPATIBILITY_SETUP: bool = False -def _safe_rollback(connection) -> None: +def _safe_rollback(connection): """Safely rollback database connection. Args: @@ -25,7 +25,7 @@ def _safe_rollback(connection) -> None: logger.exception("Failed to rollback connection") -def _setup_gevent_compatibility() -> None: +def _setup_gevent_compatibility(): global _GEVENT_COMPATIBILITY_SETUP # pylint: disable=global-statement # Avoid duplicate registration @@ -33,7 +33,7 @@ def _setup_gevent_compatibility() -> None: return @event.listens_for(Pool, "reset") - def _safe_reset(dbapi_connection, connection_record, reset_state) -> None: # pylint: disable=unused-argument + def _safe_reset(dbapi_connection, connection_record, reset_state): # pylint: disable=unused-argument if reset_state.terminate_only: return diff --git a/api/extensions/ext_orjson.py b/api/extensions/ext_orjson.py index 659784a585..efa1386a67 100644 --- a/api/extensions/ext_orjson.py +++ b/api/extensions/ext_orjson.py @@ -3,6 +3,6 @@ from flask_orjson import OrjsonProvider from dify_app import DifyApp -def init_app(app: DifyApp) -> None: +def init_app(app: DifyApp): """Initialize Flask-Orjson extension for faster JSON serialization""" app.json = OrjsonProvider(app) diff --git a/api/extensions/storage/clickzetta_volume/clickzetta_volume_storage.py b/api/extensions/storage/clickzetta_volume/clickzetta_volume_storage.py index adf2944c90..33fa7d0a8d 100644 --- a/api/extensions/storage/clickzetta_volume/clickzetta_volume_storage.py +++ b/api/extensions/storage/clickzetta_volume/clickzetta_volume_storage.py @@ -40,7 +40,7 @@ class ClickZettaVolumeConfig(BaseModel): @model_validator(mode="before") @classmethod - def validate_config(cls, values: dict) -> dict: + def validate_config(cls, values: dict): """Validate the configuration values. This method will first try to use CLICKZETTA_VOLUME_* environment variables, @@ -217,7 +217,7 @@ class ClickZettaVolumeStorage(BaseStorage): logger.exception("SQL execution failed: %s", sql) raise - def _ensure_table_volume_exists(self, dataset_id: str) -> None: + def _ensure_table_volume_exists(self, dataset_id: str): """Ensure table volume exists for the given dataset_id.""" if self._config.volume_type != "table" or not dataset_id: return @@ -252,7 +252,7 @@ class ClickZettaVolumeStorage(BaseStorage): # Don't raise exception, let the operation continue # The table might exist but not be visible due to permissions - def save(self, filename: str, data: bytes) -> None: + def save(self, filename: str, data: bytes): """Save data to ClickZetta Volume. Args: diff --git a/api/extensions/storage/clickzetta_volume/file_lifecycle.py b/api/extensions/storage/clickzetta_volume/file_lifecycle.py index c41344774f..ef6b12fd59 100644 --- a/api/extensions/storage/clickzetta_volume/file_lifecycle.py +++ b/api/extensions/storage/clickzetta_volume/file_lifecycle.py @@ -38,7 +38,7 @@ class FileMetadata: tags: Optional[dict[str, str]] = None parent_version: Optional[int] = None - def to_dict(self) -> dict: + def to_dict(self): """Convert to dictionary format""" data = asdict(self) data["created_at"] = self.created_at.isoformat() diff --git a/api/extensions/storage/clickzetta_volume/volume_permissions.py b/api/extensions/storage/clickzetta_volume/volume_permissions.py index d216790f17..243df92efe 100644 --- a/api/extensions/storage/clickzetta_volume/volume_permissions.py +++ b/api/extensions/storage/clickzetta_volume/volume_permissions.py @@ -623,7 +623,7 @@ class VolumePermissionError(Exception): def check_volume_permission( permission_manager: VolumePermissionManager, operation: str, dataset_id: Optional[str] = None -) -> None: +): """Permission check decorator function Args: diff --git a/api/extensions/storage/opendal_storage.py b/api/extensions/storage/opendal_storage.py index 0ba35506d3..21b82d79e3 100644 --- a/api/extensions/storage/opendal_storage.py +++ b/api/extensions/storage/opendal_storage.py @@ -40,7 +40,7 @@ class OpenDALStorage(BaseStorage): self.op = self.op.layer(retry_layer) logger.debug("added retry layer to opendal operator") - def save(self, filename: str, data: bytes) -> None: + def save(self, filename: str, data: bytes): self.op.write(path=filename, bs=data) logger.debug("file %s saved", filename) diff --git a/api/factories/file_factory.py b/api/factories/file_factory.py index 62e3bfa3ba..9433b312cf 100644 --- a/api/factories/file_factory.py +++ b/api/factories/file_factory.py @@ -403,7 +403,7 @@ class StorageKeyLoader: This loader is batched, the database query count is constant regardless of the input size. """ - def __init__(self, session: Session, tenant_id: str) -> None: + def __init__(self, session: Session, tenant_id: str): self._session = session self._tenant_id = tenant_id diff --git a/api/libs/email_i18n.py b/api/libs/email_i18n.py index b7c9f3ec6c..3c039dff53 100644 --- a/api/libs/email_i18n.py +++ b/api/libs/email_i18n.py @@ -128,7 +128,7 @@ class FeatureBrandingService: class EmailSender(Protocol): """Protocol for email sending abstraction.""" - def send_email(self, to: str, subject: str, html_content: str) -> None: + def send_email(self, to: str, subject: str, html_content: str): """Send email with given parameters.""" ... @@ -136,7 +136,7 @@ class EmailSender(Protocol): class FlaskMailSender: """Flask-Mail based email sender.""" - def send_email(self, to: str, subject: str, html_content: str) -> None: + def send_email(self, to: str, subject: str, html_content: str): """Send email using Flask-Mail.""" if mail.is_inited(): mail.send(to=to, subject=subject, html=html_content) @@ -156,7 +156,7 @@ class EmailI18nService: renderer: EmailRenderer, branding_service: BrandingService, sender: EmailSender, - ) -> None: + ): self._config = config self._renderer = renderer self._branding_service = branding_service @@ -168,7 +168,7 @@ class EmailI18nService: language_code: str, to: str, template_context: Optional[dict[str, Any]] = None, - ) -> None: + ): """ Send internationalized email with branding support. @@ -192,7 +192,7 @@ class EmailI18nService: to: str, code: str, phase: str, - ) -> None: + ): """ Send change email notification with phase-specific handling. @@ -224,7 +224,7 @@ class EmailI18nService: to: str | list[str], subject: str, html_content: str, - ) -> None: + ): """ Send a raw email directly without template processing. diff --git a/api/libs/external_api.py b/api/libs/external_api.py index d5409c4b4c..cee80f7f24 100644 --- a/api/libs/external_api.py +++ b/api/libs/external_api.py @@ -16,7 +16,7 @@ def http_status_message(code): return HTTP_STATUS_CODES.get(code, "") -def register_external_error_handlers(api: Api) -> None: +def register_external_error_handlers(api: Api): @api.errorhandler(HTTPException) def handle_http_exception(e: HTTPException): got_request_exception.send(current_app, exception=e) diff --git a/api/libs/json_in_md_parser.py b/api/libs/json_in_md_parser.py index 9ab53b6294..0c642041bf 100644 --- a/api/libs/json_in_md_parser.py +++ b/api/libs/json_in_md_parser.py @@ -3,7 +3,7 @@ import json from core.llm_generator.output_parser.errors import OutputParserError -def parse_json_markdown(json_string: str) -> dict: +def parse_json_markdown(json_string: str): # Get json from the backticks/braces json_string = json_string.strip() starts = ["```json", "```", "``", "`", "{"] @@ -33,7 +33,7 @@ def parse_json_markdown(json_string: str) -> dict: return parsed -def parse_and_check_json_markdown(text: str, expected_keys: list[str]) -> dict: +def parse_and_check_json_markdown(text: str, expected_keys: list[str]): try: json_obj = parse_json_markdown(text) except json.JSONDecodeError as e: diff --git a/api/libs/module_loading.py b/api/libs/module_loading.py index 616d072a1b..9f74943433 100644 --- a/api/libs/module_loading.py +++ b/api/libs/module_loading.py @@ -7,10 +7,9 @@ https://github.com/django/django/blob/main/django/utils/module_loading.py import sys from importlib import import_module -from typing import Any -def cached_import(module_path: str, class_name: str) -> Any: +def cached_import(module_path: str, class_name: str): """ Import a module and return the named attribute/class from it, with caching. @@ -30,7 +29,7 @@ def cached_import(module_path: str, class_name: str) -> Any: return getattr(module, class_name) -def import_string(dotted_path: str) -> Any: +def import_string(dotted_path: str): """ Import a dotted module path and return the attribute/class designated by the last name in the path. Raise ImportError if the import failed. diff --git a/api/models/account.py b/api/models/account.py index 6db1381df7..4fec41c4e7 100644 --- a/api/models/account.py +++ b/api/models/account.py @@ -225,7 +225,7 @@ class Tenant(Base): ) @property - def custom_config_dict(self) -> dict: + def custom_config_dict(self): return json.loads(self.custom_config) if self.custom_config else {} @custom_config_dict.setter diff --git a/api/models/model.py b/api/models/model.py index aa1a87e3bf..fbebdc817c 100644 --- a/api/models/model.py +++ b/api/models/model.py @@ -162,7 +162,7 @@ class App(Base): return str(self.mode) @property - def deleted_tools(self) -> list: + def deleted_tools(self): from core.tools.tool_manager import ToolManager from services.plugin.plugin_service import PluginService @@ -339,15 +339,15 @@ class AppModelConfig(Base): return app @property - def model_dict(self) -> dict: + def model_dict(self): return json.loads(self.model) if self.model else {} @property - def suggested_questions_list(self) -> list: + def suggested_questions_list(self): return json.loads(self.suggested_questions) if self.suggested_questions else [] @property - def suggested_questions_after_answer_dict(self) -> dict: + def suggested_questions_after_answer_dict(self): return ( json.loads(self.suggested_questions_after_answer) if self.suggested_questions_after_answer @@ -355,19 +355,19 @@ class AppModelConfig(Base): ) @property - def speech_to_text_dict(self) -> dict: + def speech_to_text_dict(self): return json.loads(self.speech_to_text) if self.speech_to_text else {"enabled": False} @property - def text_to_speech_dict(self) -> dict: + def text_to_speech_dict(self): return json.loads(self.text_to_speech) if self.text_to_speech else {"enabled": False} @property - def retriever_resource_dict(self) -> dict: + def retriever_resource_dict(self): return json.loads(self.retriever_resource) if self.retriever_resource else {"enabled": True} @property - def annotation_reply_dict(self) -> dict: + def annotation_reply_dict(self): annotation_setting = ( db.session.query(AppAnnotationSetting).where(AppAnnotationSetting.app_id == self.app_id).first() ) @@ -390,11 +390,11 @@ class AppModelConfig(Base): return {"enabled": False} @property - def more_like_this_dict(self) -> dict: + def more_like_this_dict(self): return json.loads(self.more_like_this) if self.more_like_this else {"enabled": False} @property - def sensitive_word_avoidance_dict(self) -> dict: + def sensitive_word_avoidance_dict(self): return ( json.loads(self.sensitive_word_avoidance) if self.sensitive_word_avoidance @@ -410,7 +410,7 @@ class AppModelConfig(Base): return json.loads(self.user_input_form) if self.user_input_form else [] @property - def agent_mode_dict(self) -> dict: + def agent_mode_dict(self): return ( json.loads(self.agent_mode) if self.agent_mode @@ -418,15 +418,15 @@ class AppModelConfig(Base): ) @property - def chat_prompt_config_dict(self) -> dict: + def chat_prompt_config_dict(self): return json.loads(self.chat_prompt_config) if self.chat_prompt_config else {} @property - def completion_prompt_config_dict(self) -> dict: + def completion_prompt_config_dict(self): return json.loads(self.completion_prompt_config) if self.completion_prompt_config else {} @property - def dataset_configs_dict(self) -> dict: + def dataset_configs_dict(self): if self.dataset_configs: dataset_configs: dict = json.loads(self.dataset_configs) if "retrieval_model" not in dataset_configs: @@ -438,7 +438,7 @@ class AppModelConfig(Base): } @property - def file_upload_dict(self) -> dict: + def file_upload_dict(self): return ( json.loads(self.file_upload) if self.file_upload @@ -452,7 +452,7 @@ class AppModelConfig(Base): } ) - def to_dict(self) -> dict: + def to_dict(self): return { "opening_statement": self.opening_statement, "suggested_questions": self.suggested_questions_list, @@ -1087,7 +1087,7 @@ class Message(Base): return self.override_model_configs is not None @property - def message_metadata_dict(self) -> dict: + def message_metadata_dict(self): return json.loads(self.message_metadata) if self.message_metadata else {} @property @@ -1176,7 +1176,7 @@ class Message(Base): return None - def to_dict(self) -> dict: + def to_dict(self): return { "id": self.id, "app_id": self.app_id, @@ -1689,7 +1689,7 @@ class MessageAgentThought(Base): created_at = mapped_column(sa.DateTime, nullable=False, server_default=db.func.current_timestamp()) @property - def files(self) -> list: + def files(self): if self.message_files: return cast(list[Any], json.loads(self.message_files)) else: @@ -1700,7 +1700,7 @@ class MessageAgentThought(Base): return self.tool.split(";") if self.tool else [] @property - def tool_labels(self) -> dict: + def tool_labels(self): try: if self.tool_labels_str: return cast(dict, json.loads(self.tool_labels_str)) @@ -1710,7 +1710,7 @@ class MessageAgentThought(Base): return {} @property - def tool_meta(self) -> dict: + def tool_meta(self): try: if self.tool_meta_str: return cast(dict, json.loads(self.tool_meta_str)) @@ -1720,7 +1720,7 @@ class MessageAgentThought(Base): return {} @property - def tool_inputs_dict(self) -> dict: + def tool_inputs_dict(self): tools = self.tools try: if self.tool_input: diff --git a/api/models/tools.py b/api/models/tools.py index 9c460e9bf1..8755570ee1 100644 --- a/api/models/tools.py +++ b/api/models/tools.py @@ -1,6 +1,6 @@ import json from datetime import datetime -from typing import Any, Optional, cast +from typing import Optional, cast from urllib.parse import urlparse import sqlalchemy as sa @@ -54,7 +54,7 @@ class ToolOAuthTenantClient(Base): encrypted_oauth_params: Mapped[str] = mapped_column(sa.Text, nullable=False) @property - def oauth_params(self) -> dict: + def oauth_params(self): return cast(dict, json.loads(self.encrypted_oauth_params or "{}")) @@ -96,7 +96,7 @@ class BuiltinToolProvider(Base): expires_at: Mapped[int] = mapped_column(sa.BigInteger, nullable=False, server_default=sa.text("-1")) @property - def credentials(self) -> dict: + def credentials(self): return cast(dict, json.loads(self.encrypted_credentials)) @@ -146,7 +146,7 @@ class ApiToolProvider(Base): return [ApiToolBundle(**tool) for tool in json.loads(self.tools_str)] @property - def credentials(self) -> dict: + def credentials(self): return dict(json.loads(self.credentials_str)) @property @@ -289,7 +289,7 @@ class MCPToolProvider(Base): return db.session.query(Tenant).where(Tenant.id == self.tenant_id).first() @property - def credentials(self) -> dict: + def credentials(self): try: return cast(dict, json.loads(self.encrypted_credentials)) or {} except Exception: @@ -327,7 +327,7 @@ class MCPToolProvider(Base): return mask_url(self.decrypted_server_url) @property - def decrypted_credentials(self) -> dict: + def decrypted_credentials(self): from core.helper.provider_cache import NoOpProviderCredentialCache from core.tools.mcp_tool.provider import MCPToolProviderController from core.tools.utils.encryption import create_provider_encrypter @@ -408,7 +408,7 @@ class ToolConversationVariables(Base): updated_at = mapped_column(sa.DateTime, nullable=False, server_default=func.current_timestamp()) @property - def variables(self) -> Any: + def variables(self): return json.loads(self.variables_str) diff --git a/api/models/workflow.py b/api/models/workflow.py index 28bf683fb8..23f18929d4 100644 --- a/api/models/workflow.py +++ b/api/models/workflow.py @@ -282,14 +282,14 @@ class Workflow(Base): return self._features @features.setter - def features(self, value: str) -> None: + def features(self, value: str): self._features = value @property def features_dict(self) -> dict[str, Any]: return json.loads(self.features) if self.features else {} - def user_input_form(self, to_old_structure: bool = False) -> list: + def user_input_form(self, to_old_structure: bool = False): # get start node from graph if not self.graph: return [] @@ -439,7 +439,7 @@ class Workflow(Base): return results @conversation_variables.setter - def conversation_variables(self, value: Sequence[Variable]) -> None: + def conversation_variables(self, value: Sequence[Variable]): self._conversation_variables = json.dumps( {var.name: var.model_dump() for var in value}, ensure_ascii=False, @@ -892,7 +892,7 @@ class ConversationVariable(Base): DateTime, nullable=False, server_default=func.current_timestamp(), onupdate=func.current_timestamp() ) - def __init__(self, *, id: str, app_id: str, conversation_id: str, data: str) -> None: + def __init__(self, *, id: str, app_id: str, conversation_id: str, data: str): self.id = id self.app_id = app_id self.conversation_id = conversation_id @@ -1073,7 +1073,7 @@ class WorkflowDraftVariable(Base): return self.build_segment_with_type(self.value_type, value) @staticmethod - def rebuild_file_types(value: Any) -> Any: + def rebuild_file_types(value: Any): # NOTE(QuantumGhost): Temporary workaround for structured data handling. # By this point, `output` has been converted to dict by # `WorkflowEntry.handle_special_values`, so we need to diff --git a/api/repositories/sqlalchemy_api_workflow_run_repository.py b/api/repositories/sqlalchemy_api_workflow_run_repository.py index e69ea9b7ce..6294846f5e 100644 --- a/api/repositories/sqlalchemy_api_workflow_run_repository.py +++ b/api/repositories/sqlalchemy_api_workflow_run_repository.py @@ -46,7 +46,7 @@ class DifyAPISQLAlchemyWorkflowRunRepository(APIWorkflowRunRepository): session_maker: SQLAlchemy sessionmaker instance for database connections """ - def __init__(self, session_maker: sessionmaker[Session]) -> None: + def __init__(self, session_maker: sessionmaker[Session]): """ Initialize the repository with a sessionmaker. diff --git a/api/services/account_service.py b/api/services/account_service.py index 660c80ebfc..a76792f88e 100644 --- a/api/services/account_service.py +++ b/api/services/account_service.py @@ -105,14 +105,14 @@ class AccountService: return f"{ACCOUNT_REFRESH_TOKEN_PREFIX}{account_id}" @staticmethod - def _store_refresh_token(refresh_token: str, account_id: str) -> None: + def _store_refresh_token(refresh_token: str, account_id: str): redis_client.setex(AccountService._get_refresh_token_key(refresh_token), REFRESH_TOKEN_EXPIRY, account_id) redis_client.setex( AccountService._get_account_refresh_token_key(account_id), REFRESH_TOKEN_EXPIRY, refresh_token ) @staticmethod - def _delete_refresh_token(refresh_token: str, account_id: str) -> None: + def _delete_refresh_token(refresh_token: str, account_id: str): redis_client.delete(AccountService._get_refresh_token_key(refresh_token)) redis_client.delete(AccountService._get_account_refresh_token_key(account_id)) @@ -312,12 +312,12 @@ class AccountService: return True @staticmethod - def delete_account(account: Account) -> None: + def delete_account(account: Account): """Delete account. This method only adds a task to the queue for deletion.""" delete_account_task.delay(account.id) @staticmethod - def link_account_integrate(provider: str, open_id: str, account: Account) -> None: + def link_account_integrate(provider: str, open_id: str, account: Account): """Link account integrate""" try: # Query whether there is an existing binding record for the same provider @@ -344,7 +344,7 @@ class AccountService: raise LinkAccountIntegrateError("Failed to link account.") from e @staticmethod - def close_account(account: Account) -> None: + def close_account(account: Account): """Close account""" account.status = AccountStatus.CLOSED.value db.session.commit() @@ -374,7 +374,7 @@ class AccountService: return account @staticmethod - def update_login_info(account: Account, *, ip_address: str) -> None: + def update_login_info(account: Account, *, ip_address: str): """Update last login time and ip""" account.last_login_at = naive_utc_now() account.last_login_ip = ip_address @@ -398,7 +398,7 @@ class AccountService: return TokenPair(access_token=access_token, refresh_token=refresh_token) @staticmethod - def logout(*, account: Account) -> None: + def logout(*, account: Account): refresh_token = redis_client.get(AccountService._get_account_refresh_token_key(account.id)) if refresh_token: AccountService._delete_refresh_token(refresh_token.decode("utf-8"), account.id) @@ -705,7 +705,7 @@ class AccountService: @staticmethod @redis_fallback(default_return=None) - def add_login_error_rate_limit(email: str) -> None: + def add_login_error_rate_limit(email: str): key = f"login_error_rate_limit:{email}" count = redis_client.get(key) if count is None: @@ -734,7 +734,7 @@ class AccountService: @staticmethod @redis_fallback(default_return=None) - def add_forgot_password_error_rate_limit(email: str) -> None: + def add_forgot_password_error_rate_limit(email: str): key = f"forgot_password_error_rate_limit:{email}" count = redis_client.get(key) if count is None: @@ -763,7 +763,7 @@ class AccountService: @staticmethod @redis_fallback(default_return=None) - def add_change_email_error_rate_limit(email: str) -> None: + def add_change_email_error_rate_limit(email: str): key = f"change_email_error_rate_limit:{email}" count = redis_client.get(key) if count is None: @@ -791,7 +791,7 @@ class AccountService: @staticmethod @redis_fallback(default_return=None) - def add_owner_transfer_error_rate_limit(email: str) -> None: + def add_owner_transfer_error_rate_limit(email: str): key = f"owner_transfer_error_rate_limit:{email}" count = redis_client.get(key) if count is None: @@ -970,7 +970,7 @@ class TenantService: return tenant @staticmethod - def switch_tenant(account: Account, tenant_id: Optional[str] = None) -> None: + def switch_tenant(account: Account, tenant_id: Optional[str] = None): """Switch the current workspace for the account""" # Ensure tenant_id is provided @@ -1067,7 +1067,7 @@ class TenantService: return cast(int, db.session.query(func.count(Tenant.id)).scalar()) @staticmethod - def check_member_permission(tenant: Tenant, operator: Account, member: Account | None, action: str) -> None: + def check_member_permission(tenant: Tenant, operator: Account, member: Account | None, action: str): """Check member permission""" perms = { "add": [TenantAccountRole.OWNER, TenantAccountRole.ADMIN], @@ -1087,7 +1087,7 @@ class TenantService: raise NoPermissionError(f"No permission to {action} member.") @staticmethod - def remove_member_from_tenant(tenant: Tenant, account: Account, operator: Account) -> None: + def remove_member_from_tenant(tenant: Tenant, account: Account, operator: Account): """Remove member from tenant""" if operator.id == account.id: raise CannotOperateSelfError("Cannot operate self.") @@ -1102,7 +1102,7 @@ class TenantService: db.session.commit() @staticmethod - def update_member_role(tenant: Tenant, member: Account, new_role: str, operator: Account) -> None: + def update_member_role(tenant: Tenant, member: Account, new_role: str, operator: Account): """Update member role""" TenantService.check_member_permission(tenant, operator, member, "update") @@ -1129,7 +1129,7 @@ class TenantService: db.session.commit() @staticmethod - def get_custom_config(tenant_id: str) -> dict: + def get_custom_config(tenant_id: str): tenant = db.get_or_404(Tenant, tenant_id) return tenant.custom_config_dict @@ -1150,7 +1150,7 @@ class RegisterService: return f"member_invite:token:{token}" @classmethod - def setup(cls, email: str, name: str, password: str, ip_address: str) -> None: + def setup(cls, email: str, name: str, password: str, ip_address: str): """ Setup dify diff --git a/api/services/advanced_prompt_template_service.py b/api/services/advanced_prompt_template_service.py index 6dc1affa11..6f0ab2546a 100644 --- a/api/services/advanced_prompt_template_service.py +++ b/api/services/advanced_prompt_template_service.py @@ -17,7 +17,7 @@ from models.model import AppMode class AdvancedPromptTemplateService: @classmethod - def get_prompt(cls, args: dict) -> dict: + def get_prompt(cls, args: dict): app_mode = args["app_mode"] model_mode = args["model_mode"] model_name = args["model_name"] @@ -29,7 +29,7 @@ class AdvancedPromptTemplateService: return cls.get_common_prompt(app_mode, model_mode, has_context) @classmethod - def get_common_prompt(cls, app_mode: str, model_mode: str, has_context: str) -> dict: + def get_common_prompt(cls, app_mode: str, model_mode: str, has_context: str): context_prompt = copy.deepcopy(CONTEXT) if app_mode == AppMode.CHAT.value: @@ -52,7 +52,7 @@ class AdvancedPromptTemplateService: return {} @classmethod - def get_completion_prompt(cls, prompt_template: dict, has_context: str, context: str) -> dict: + def get_completion_prompt(cls, prompt_template: dict, has_context: str, context: str): if has_context == "true": prompt_template["completion_prompt_config"]["prompt"]["text"] = ( context + prompt_template["completion_prompt_config"]["prompt"]["text"] @@ -61,7 +61,7 @@ class AdvancedPromptTemplateService: return prompt_template @classmethod - def get_chat_prompt(cls, prompt_template: dict, has_context: str, context: str) -> dict: + def get_chat_prompt(cls, prompt_template: dict, has_context: str, context: str): if has_context == "true": prompt_template["chat_prompt_config"]["prompt"][0]["text"] = ( context + prompt_template["chat_prompt_config"]["prompt"][0]["text"] @@ -70,7 +70,7 @@ class AdvancedPromptTemplateService: return prompt_template @classmethod - def get_baichuan_prompt(cls, app_mode: str, model_mode: str, has_context: str) -> dict: + def get_baichuan_prompt(cls, app_mode: str, model_mode: str, has_context: str): baichuan_context_prompt = copy.deepcopy(BAICHUAN_CONTEXT) if app_mode == AppMode.CHAT.value: diff --git a/api/services/agent_service.py b/api/services/agent_service.py index 7c6df2428f..72833b9d69 100644 --- a/api/services/agent_service.py +++ b/api/services/agent_service.py @@ -16,7 +16,7 @@ from models.model import App, Conversation, EndUser, Message, MessageAgentThough class AgentService: @classmethod - def get_agent_logs(cls, app_model: App, conversation_id: str, message_id: str) -> dict: + def get_agent_logs(cls, app_model: App, conversation_id: str, message_id: str): """ Service to get agent logs """ diff --git a/api/services/annotation_service.py b/api/services/annotation_service.py index 45656e790d..24567cc34c 100644 --- a/api/services/annotation_service.py +++ b/api/services/annotation_service.py @@ -73,7 +73,7 @@ class AppAnnotationService: return annotation @classmethod - def enable_app_annotation(cls, args: dict, app_id: str) -> dict: + def enable_app_annotation(cls, args: dict, app_id: str): enable_app_annotation_key = f"enable_app_annotation_{str(app_id)}" cache_result = redis_client.get(enable_app_annotation_key) if cache_result is not None: @@ -96,7 +96,7 @@ class AppAnnotationService: return {"job_id": job_id, "job_status": "waiting"} @classmethod - def disable_app_annotation(cls, app_id: str) -> dict: + def disable_app_annotation(cls, app_id: str): disable_app_annotation_key = f"disable_app_annotation_{str(app_id)}" cache_result = redis_client.get(disable_app_annotation_key) if cache_result is not None: @@ -315,7 +315,7 @@ class AppAnnotationService: return {"deleted_count": deleted_count} @classmethod - def batch_import_app_annotations(cls, app_id, file: FileStorage) -> dict: + def batch_import_app_annotations(cls, app_id, file: FileStorage): # get app info app = ( db.session.query(App) @@ -490,7 +490,7 @@ class AppAnnotationService: } @classmethod - def clear_all_annotations(cls, app_id: str) -> dict: + def clear_all_annotations(cls, app_id: str): app = ( db.session.query(App) .where(App.id == app_id, App.tenant_id == current_user.current_tenant_id, App.status == "normal") diff --git a/api/services/api_based_extension_service.py b/api/services/api_based_extension_service.py index 2f28eff165..3a0ed41be0 100644 --- a/api/services/api_based_extension_service.py +++ b/api/services/api_based_extension_service.py @@ -30,7 +30,7 @@ class APIBasedExtensionService: return extension_data @staticmethod - def delete(extension_data: APIBasedExtension) -> None: + def delete(extension_data: APIBasedExtension): db.session.delete(extension_data) db.session.commit() @@ -51,7 +51,7 @@ class APIBasedExtensionService: return extension @classmethod - def _validation(cls, extension_data: APIBasedExtension) -> None: + def _validation(cls, extension_data: APIBasedExtension): # name if not extension_data.name: raise ValueError("name must not be empty") @@ -95,7 +95,7 @@ class APIBasedExtensionService: cls._ping_connection(extension_data) @staticmethod - def _ping_connection(extension_data: APIBasedExtension) -> None: + def _ping_connection(extension_data: APIBasedExtension): try: client = APIBasedExtensionRequestor(extension_data.api_endpoint, extension_data.api_key) resp = client.request(point=APIBasedExtensionPoint.PING, params={}) diff --git a/api/services/app_dsl_service.py b/api/services/app_dsl_service.py index 2663cb3805..2344be0aaf 100644 --- a/api/services/app_dsl_service.py +++ b/api/services/app_dsl_service.py @@ -566,7 +566,7 @@ class AppDslService: @classmethod def _append_workflow_export_data( cls, *, export_data: dict, app_model: App, include_secret: bool, workflow_id: Optional[str] = None - ) -> None: + ): """ Append workflow export data :param export_data: export data @@ -608,7 +608,7 @@ class AppDslService: ] @classmethod - def _append_model_config_export_data(cls, export_data: dict, app_model: App) -> None: + def _append_model_config_export_data(cls, export_data: dict, app_model: App): """ Append model config export data :param export_data: export data diff --git a/api/services/app_model_config_service.py b/api/services/app_model_config_service.py index a1ad271053..6f54f90734 100644 --- a/api/services/app_model_config_service.py +++ b/api/services/app_model_config_service.py @@ -6,7 +6,7 @@ from models.model import AppMode class AppModelConfigService: @classmethod - def validate_configuration(cls, tenant_id: str, config: dict, app_mode: AppMode) -> dict: + def validate_configuration(cls, tenant_id: str, config: dict, app_mode: AppMode): if app_mode == AppMode.CHAT: return ChatAppConfigManager.config_validate(tenant_id, config) elif app_mode == AppMode.AGENT_CHAT: diff --git a/api/services/app_service.py b/api/services/app_service.py index 1df926cc21..4502fa9296 100644 --- a/api/services/app_service.py +++ b/api/services/app_service.py @@ -316,7 +316,7 @@ class AppService: return app - def delete_app(self, app: App) -> None: + def delete_app(self, app: App): """ Delete app :param app: App instance @@ -331,7 +331,7 @@ class AppService: # Trigger asynchronous deletion of app and related data remove_app_and_related_data_task.delay(tenant_id=app.tenant_id, app_id=app.id) - def get_app_meta(self, app_model: App) -> dict: + def get_app_meta(self, app_model: App): """ Get app meta info :param app_model: app model diff --git a/api/services/auth/api_key_auth_service.py b/api/services/auth/api_key_auth_service.py index 996e9187f3..f6e960b413 100644 --- a/api/services/auth/api_key_auth_service.py +++ b/api/services/auth/api_key_auth_service.py @@ -8,7 +8,7 @@ from services.auth.api_key_auth_factory import ApiKeyAuthFactory class ApiKeyAuthService: @staticmethod - def get_provider_auth_list(tenant_id: str) -> list: + def get_provider_auth_list(tenant_id: str): data_source_api_key_bindings = ( db.session.query(DataSourceApiKeyAuthBinding) .where(DataSourceApiKeyAuthBinding.tenant_id == tenant_id, DataSourceApiKeyAuthBinding.disabled.is_(False)) diff --git a/api/services/clear_free_plan_tenant_expired_logs.py b/api/services/clear_free_plan_tenant_expired_logs.py index de00e74637..2f1b63664f 100644 --- a/api/services/clear_free_plan_tenant_expired_logs.py +++ b/api/services/clear_free_plan_tenant_expired_logs.py @@ -34,7 +34,7 @@ logger = logging.getLogger(__name__) class ClearFreePlanTenantExpiredLogs: @classmethod - def _clear_message_related_tables(cls, session: Session, tenant_id: str, batch_message_ids: list[str]) -> None: + def _clear_message_related_tables(cls, session: Session, tenant_id: str, batch_message_ids: list[str]): """ Clean up message-related tables to avoid data redundancy. This method cleans up tables that have foreign key relationships with Message. @@ -353,7 +353,7 @@ class ClearFreePlanTenantExpiredLogs: thread_pool = ThreadPoolExecutor(max_workers=10) - def process_tenant(flask_app: Flask, tenant_id: str) -> None: + def process_tenant(flask_app: Flask, tenant_id: str): try: if ( not dify_config.BILLING_ENABLED diff --git a/api/services/code_based_extension_service.py b/api/services/code_based_extension_service.py index f7597b7f1f..7c893463db 100644 --- a/api/services/code_based_extension_service.py +++ b/api/services/code_based_extension_service.py @@ -3,7 +3,7 @@ from extensions.ext_code_based_extension import code_based_extension class CodeBasedExtensionService: @staticmethod - def get_code_based_extension(module: str) -> list[dict]: + def get_code_based_extension(module: str): module_extensions = code_based_extension.module_extensions(module) return [ { diff --git a/api/services/conversation_service.py b/api/services/conversation_service.py index ac603d3cc9..d017ce54ab 100644 --- a/api/services/conversation_service.py +++ b/api/services/conversation_service.py @@ -250,7 +250,7 @@ class ConversationService: variable_id: str, user: Optional[Union[Account, EndUser]], new_value: Any, - ) -> dict: + ): """ Update a conversation variable's value. diff --git a/api/services/dataset_service.py b/api/services/dataset_service.py index 4b202001da..e0885f3257 100644 --- a/api/services/dataset_service.py +++ b/api/services/dataset_service.py @@ -719,7 +719,7 @@ class DatasetService: ) @staticmethod - def get_dataset_auto_disable_logs(dataset_id: str) -> dict: + def get_dataset_auto_disable_logs(dataset_id: str): features = FeatureService.get_features(current_user.current_tenant_id) if not features.billing.enabled or features.billing.subscription.plan == "sandbox": return { diff --git a/api/services/entities/model_provider_entities.py b/api/services/entities/model_provider_entities.py index 1fe259dd46..647052d739 100644 --- a/api/services/entities/model_provider_entities.py +++ b/api/services/entities/model_provider_entities.py @@ -83,7 +83,7 @@ class ProviderResponse(BaseModel): # pydantic configs model_config = ConfigDict(protected_namespaces=()) - def __init__(self, **data) -> None: + def __init__(self, **data): super().__init__(**data) url_prefix = ( @@ -113,7 +113,7 @@ class ProviderWithModelsResponse(BaseModel): status: CustomConfigurationStatus models: list[ProviderModelWithStatusEntity] - def __init__(self, **data) -> None: + def __init__(self, **data): super().__init__(**data) url_prefix = ( @@ -137,7 +137,7 @@ class SimpleProviderEntityResponse(SimpleProviderEntity): tenant_id: str - def __init__(self, **data) -> None: + def __init__(self, **data): super().__init__(**data) url_prefix = ( @@ -174,7 +174,7 @@ class ModelWithProviderEntityResponse(ProviderModelWithStatusEntity): provider: SimpleProviderEntityResponse - def __init__(self, tenant_id: str, model: ModelWithProviderEntity) -> None: + def __init__(self, tenant_id: str, model: ModelWithProviderEntity): dump_model = model.model_dump() dump_model["provider"]["tenant_id"] = tenant_id super().__init__(**dump_model) diff --git a/api/services/errors/llm.py b/api/services/errors/llm.py index e4fac6f745..ca4c9a611d 100644 --- a/api/services/errors/llm.py +++ b/api/services/errors/llm.py @@ -6,7 +6,7 @@ class InvokeError(Exception): description: Optional[str] = None - def __init__(self, description: Optional[str] = None) -> None: + def __init__(self, description: Optional[str] = None): self.description = description def __str__(self): diff --git a/api/services/external_knowledge_service.py b/api/services/external_knowledge_service.py index 077571ffb8..783d6c2428 100644 --- a/api/services/external_knowledge_service.py +++ b/api/services/external_knowledge_service.py @@ -277,7 +277,7 @@ class ExternalDatasetService: query: str, external_retrieval_parameters: dict, metadata_condition: Optional[MetadataCondition] = None, - ) -> list: + ): external_knowledge_binding = ( db.session.query(ExternalKnowledgeBindings).filter_by(dataset_id=dataset_id, tenant_id=tenant_id).first() ) diff --git a/api/services/hit_testing_service.py b/api/services/hit_testing_service.py index bce28da032..00ec3babf3 100644 --- a/api/services/hit_testing_service.py +++ b/api/services/hit_testing_service.py @@ -33,7 +33,7 @@ class HitTestingService: retrieval_model: Any, # FIXME drop this any external_retrieval_model: dict, limit: int = 10, - ) -> dict: + ): start = time.perf_counter() # get retrieval model , if the model is not setting , using default @@ -98,7 +98,7 @@ class HitTestingService: account: Account, external_retrieval_model: dict, metadata_filtering_conditions: dict, - ) -> dict: + ): if dataset.provider != "external": return { "query": {"content": query}, diff --git a/api/services/model_load_balancing_service.py b/api/services/model_load_balancing_service.py index 17696f5cd8..c638087f63 100644 --- a/api/services/model_load_balancing_service.py +++ b/api/services/model_load_balancing_service.py @@ -25,10 +25,10 @@ logger = logging.getLogger(__name__) class ModelLoadBalancingService: - def __init__(self) -> None: + def __init__(self): self.provider_manager = ProviderManager() - def enable_model_load_balancing(self, tenant_id: str, provider: str, model: str, model_type: str) -> None: + def enable_model_load_balancing(self, tenant_id: str, provider: str, model: str, model_type: str): """ enable model load balancing. @@ -49,7 +49,7 @@ class ModelLoadBalancingService: # Enable model load balancing provider_configuration.enable_model_load_balancing(model=model, model_type=ModelType.value_of(model_type)) - def disable_model_load_balancing(self, tenant_id: str, provider: str, model: str, model_type: str) -> None: + def disable_model_load_balancing(self, tenant_id: str, provider: str, model: str, model_type: str): """ disable model load balancing. @@ -295,7 +295,7 @@ class ModelLoadBalancingService: def update_load_balancing_configs( self, tenant_id: str, provider: str, model: str, model_type: str, configs: list[dict], config_from: str - ) -> None: + ): """ Update load balancing configurations. :param tenant_id: workspace id @@ -478,7 +478,7 @@ class ModelLoadBalancingService: model_type: str, credentials: dict, config_id: Optional[str] = None, - ) -> None: + ): """ Validate load balancing credentials. :param tenant_id: workspace id @@ -537,7 +537,7 @@ class ModelLoadBalancingService: credentials: dict, load_balancing_model_config: Optional[LoadBalancingModelConfig] = None, validate: bool = True, - ) -> dict: + ): """ Validate custom credentials. :param tenant_id: workspace id @@ -605,7 +605,7 @@ class ModelLoadBalancingService: else: raise ValueError("No credential schema found") - def _clear_credentials_cache(self, tenant_id: str, config_id: str) -> None: + def _clear_credentials_cache(self, tenant_id: str, config_id: str): """ Clear credentials cache. :param tenant_id: workspace id diff --git a/api/services/model_provider_service.py b/api/services/model_provider_service.py index 69c7e4cf58..510b1f1fe6 100644 --- a/api/services/model_provider_service.py +++ b/api/services/model_provider_service.py @@ -26,7 +26,7 @@ class ModelProviderService: Model Provider Service """ - def __init__(self) -> None: + def __init__(self): self.provider_manager = ProviderManager() def _get_provider_configuration(self, tenant_id: str, provider: str): @@ -142,7 +142,7 @@ class ModelProviderService: provider_configuration = self._get_provider_configuration(tenant_id, provider) return provider_configuration.get_provider_credential(credential_id=credential_id) # type: ignore - def validate_provider_credentials(self, tenant_id: str, provider: str, credentials: dict) -> None: + def validate_provider_credentials(self, tenant_id: str, provider: str, credentials: dict): """ validate provider credentials before saving. @@ -193,7 +193,7 @@ class ModelProviderService: credential_name=credential_name, ) - def remove_provider_credential(self, tenant_id: str, provider: str, credential_id: str) -> None: + def remove_provider_credential(self, tenant_id: str, provider: str, credential_id: str): """ remove a saved provider credential (by credential_id). :param tenant_id: workspace id @@ -204,7 +204,7 @@ class ModelProviderService: provider_configuration = self._get_provider_configuration(tenant_id, provider) provider_configuration.delete_provider_credential(credential_id=credential_id) - def switch_active_provider_credential(self, tenant_id: str, provider: str, credential_id: str) -> None: + def switch_active_provider_credential(self, tenant_id: str, provider: str, credential_id: str): """ :param tenant_id: workspace id :param provider: provider name @@ -232,9 +232,7 @@ class ModelProviderService: model_type=ModelType.value_of(model_type), model=model, credential_id=credential_id ) - def validate_model_credentials( - self, tenant_id: str, provider: str, model_type: str, model: str, credentials: dict - ) -> None: + def validate_model_credentials(self, tenant_id: str, provider: str, model_type: str, model: str, credentials: dict): """ validate model credentials. @@ -303,9 +301,7 @@ class ModelProviderService: credential_name=credential_name, ) - def remove_model_credential( - self, tenant_id: str, provider: str, model_type: str, model: str, credential_id: str - ) -> None: + def remove_model_credential(self, tenant_id: str, provider: str, model_type: str, model: str, credential_id: str): """ remove model credentials. @@ -323,7 +319,7 @@ class ModelProviderService: def switch_active_custom_model_credential( self, tenant_id: str, provider: str, model_type: str, model: str, credential_id: str - ) -> None: + ): """ switch model credentials. @@ -341,7 +337,7 @@ class ModelProviderService: def add_model_credential_to_model_list( self, tenant_id: str, provider: str, model_type: str, model: str, credential_id: str - ) -> None: + ): """ add model credentials to model list. @@ -357,7 +353,7 @@ class ModelProviderService: model_type=ModelType.value_of(model_type), model=model, credential_id=credential_id ) - def remove_model(self, tenant_id: str, provider: str, model_type: str, model: str) -> None: + def remove_model(self, tenant_id: str, provider: str, model_type: str, model: str): """ remove model credentials. @@ -485,7 +481,7 @@ class ModelProviderService: logger.debug("get_default_model_of_model_type error: %s", e) return None - def update_default_model_of_model_type(self, tenant_id: str, model_type: str, provider: str, model: str) -> None: + def update_default_model_of_model_type(self, tenant_id: str, model_type: str, provider: str, model: str): """ update default model of model type. @@ -517,7 +513,7 @@ class ModelProviderService: return byte_data, mime_type - def switch_preferred_provider(self, tenant_id: str, provider: str, preferred_provider_type: str) -> None: + def switch_preferred_provider(self, tenant_id: str, provider: str, preferred_provider_type: str): """ switch preferred provider. @@ -534,7 +530,7 @@ class ModelProviderService: # Switch preferred provider type provider_configuration.switch_preferred_provider_type(preferred_provider_type_enum) - def enable_model(self, tenant_id: str, provider: str, model: str, model_type: str) -> None: + def enable_model(self, tenant_id: str, provider: str, model: str, model_type: str): """ enable model. @@ -547,7 +543,7 @@ class ModelProviderService: provider_configuration = self._get_provider_configuration(tenant_id, provider) provider_configuration.enable_model(model=model, model_type=ModelType.value_of(model_type)) - def disable_model(self, tenant_id: str, provider: str, model: str, model_type: str) -> None: + def disable_model(self, tenant_id: str, provider: str, model: str, model_type: str): """ disable model. diff --git a/api/services/plugin/data_migration.py b/api/services/plugin/data_migration.py index 39585d7838..71a7b34a76 100644 --- a/api/services/plugin/data_migration.py +++ b/api/services/plugin/data_migration.py @@ -12,7 +12,7 @@ logger = logging.getLogger(__name__) class PluginDataMigration: @classmethod - def migrate(cls) -> None: + def migrate(cls): cls.migrate_db_records("providers", "provider_name", ModelProviderID) # large table cls.migrate_db_records("provider_models", "provider_name", ModelProviderID) cls.migrate_db_records("provider_orders", "provider_name", ModelProviderID) @@ -26,7 +26,7 @@ class PluginDataMigration: cls.migrate_db_records("tool_builtin_providers", "provider", ToolProviderID) @classmethod - def migrate_datasets(cls) -> None: + def migrate_datasets(cls): table_name = "datasets" provider_column_name = "embedding_model_provider" @@ -126,9 +126,7 @@ limit 1000""" ) @classmethod - def migrate_db_records( - cls, table_name: str, provider_column_name: str, provider_cls: type[GenericProviderID] - ) -> None: + def migrate_db_records(cls, table_name: str, provider_column_name: str, provider_cls: type[GenericProviderID]): click.echo(click.style(f"Migrating [{table_name}] data for plugin", fg="white")) processed_count = 0 diff --git a/api/services/plugin/plugin_migration.py b/api/services/plugin/plugin_migration.py index 221069b2b3..8dbf117fd3 100644 --- a/api/services/plugin/plugin_migration.py +++ b/api/services/plugin/plugin_migration.py @@ -33,7 +33,7 @@ excluded_providers = ["time", "audio", "code", "webscraper"] class PluginMigration: @classmethod - def extract_plugins(cls, filepath: str, workers: int) -> None: + def extract_plugins(cls, filepath: str, workers: int): """ Migrate plugin. """ @@ -55,7 +55,7 @@ class PluginMigration: thread_pool = ThreadPoolExecutor(max_workers=workers) - def process_tenant(flask_app: Flask, tenant_id: str) -> None: + def process_tenant(flask_app: Flask, tenant_id: str): with flask_app.app_context(): nonlocal handled_tenant_count try: @@ -291,7 +291,7 @@ class PluginMigration: return plugin_manifest[0].latest_package_identifier @classmethod - def extract_unique_plugins_to_file(cls, extracted_plugins: str, output_file: str) -> None: + def extract_unique_plugins_to_file(cls, extracted_plugins: str, output_file: str): """ Extract unique plugins. """ @@ -328,7 +328,7 @@ class PluginMigration: return {"plugins": plugins, "plugin_not_exist": plugin_not_exist} @classmethod - def install_plugins(cls, extracted_plugins: str, output_file: str, workers: int = 100) -> None: + def install_plugins(cls, extracted_plugins: str, output_file: str, workers: int = 100): """ Install plugins. """ @@ -348,7 +348,7 @@ class PluginMigration: if response.get("failed"): plugin_install_failed.extend(response.get("failed", [])) - def install(tenant_id: str, plugin_ids: list[str]) -> None: + def install(tenant_id: str, plugin_ids: list[str]): logger.info("Installing %s plugins for tenant %s", len(plugin_ids), tenant_id) # fetch plugin already installed installed_plugins = manager.list_plugins(tenant_id) diff --git a/api/services/recommend_app/buildin/buildin_retrieval.py b/api/services/recommend_app/buildin/buildin_retrieval.py index 523aebeed5..df9e01e273 100644 --- a/api/services/recommend_app/buildin/buildin_retrieval.py +++ b/api/services/recommend_app/buildin/buildin_retrieval.py @@ -19,7 +19,7 @@ class BuildInRecommendAppRetrieval(RecommendAppRetrievalBase): def get_type(self) -> str: return RecommendAppType.BUILDIN - def get_recommended_apps_and_categories(self, language: str) -> dict: + def get_recommended_apps_and_categories(self, language: str): result = self.fetch_recommended_apps_from_builtin(language) return result @@ -28,7 +28,7 @@ class BuildInRecommendAppRetrieval(RecommendAppRetrievalBase): return result @classmethod - def _get_builtin_data(cls) -> dict: + def _get_builtin_data(cls): """ Get builtin data. :return: @@ -44,7 +44,7 @@ class BuildInRecommendAppRetrieval(RecommendAppRetrievalBase): return cls.builtin_data or {} @classmethod - def fetch_recommended_apps_from_builtin(cls, language: str) -> dict: + def fetch_recommended_apps_from_builtin(cls, language: str): """ Fetch recommended apps from builtin. :param language: language diff --git a/api/services/recommend_app/database/database_retrieval.py b/api/services/recommend_app/database/database_retrieval.py index b97d13d012..e19f53f120 100644 --- a/api/services/recommend_app/database/database_retrieval.py +++ b/api/services/recommend_app/database/database_retrieval.py @@ -13,7 +13,7 @@ class DatabaseRecommendAppRetrieval(RecommendAppRetrievalBase): Retrieval recommended app from database """ - def get_recommended_apps_and_categories(self, language: str) -> dict: + def get_recommended_apps_and_categories(self, language: str): result = self.fetch_recommended_apps_from_db(language) return result @@ -25,7 +25,7 @@ class DatabaseRecommendAppRetrieval(RecommendAppRetrievalBase): return RecommendAppType.DATABASE @classmethod - def fetch_recommended_apps_from_db(cls, language: str) -> dict: + def fetch_recommended_apps_from_db(cls, language: str): """ Fetch recommended apps from db. :param language: language diff --git a/api/services/recommend_app/recommend_app_base.py b/api/services/recommend_app/recommend_app_base.py index 00c037710e..1f62fbf9d5 100644 --- a/api/services/recommend_app/recommend_app_base.py +++ b/api/services/recommend_app/recommend_app_base.py @@ -5,7 +5,7 @@ class RecommendAppRetrievalBase(ABC): """Interface for recommend app retrieval.""" @abstractmethod - def get_recommended_apps_and_categories(self, language: str) -> dict: + def get_recommended_apps_and_categories(self, language: str): raise NotImplementedError @abstractmethod diff --git a/api/services/recommend_app/remote/remote_retrieval.py b/api/services/recommend_app/remote/remote_retrieval.py index 85f3a02825..1e59287429 100644 --- a/api/services/recommend_app/remote/remote_retrieval.py +++ b/api/services/recommend_app/remote/remote_retrieval.py @@ -24,7 +24,7 @@ class RemoteRecommendAppRetrieval(RecommendAppRetrievalBase): result = BuildInRecommendAppRetrieval.fetch_recommended_app_detail_from_builtin(app_id) return result - def get_recommended_apps_and_categories(self, language: str) -> dict: + def get_recommended_apps_and_categories(self, language: str): try: result = self.fetch_recommended_apps_from_dify_official(language) except Exception as e: @@ -51,7 +51,7 @@ class RemoteRecommendAppRetrieval(RecommendAppRetrievalBase): return data @classmethod - def fetch_recommended_apps_from_dify_official(cls, language: str) -> dict: + def fetch_recommended_apps_from_dify_official(cls, language: str): """ Fetch recommended apps from dify official. :param language: language diff --git a/api/services/recommended_app_service.py b/api/services/recommended_app_service.py index 2aebe6b6b9..d9c1b51fa1 100644 --- a/api/services/recommended_app_service.py +++ b/api/services/recommended_app_service.py @@ -6,7 +6,7 @@ from services.recommend_app.recommend_app_factory import RecommendAppRetrievalFa class RecommendedAppService: @classmethod - def get_recommended_apps_and_categories(cls, language: str) -> dict: + def get_recommended_apps_and_categories(cls, language: str): """ Get recommended apps and categories. :param language: language diff --git a/api/services/tag_service.py b/api/services/tag_service.py index 2e5e96214b..a16bdb46cd 100644 --- a/api/services/tag_service.py +++ b/api/services/tag_service.py @@ -12,7 +12,7 @@ from models.model import App, Tag, TagBinding class TagService: @staticmethod - def get_tags(tag_type: str, current_tenant_id: str, keyword: Optional[str] = None) -> list: + def get_tags(tag_type: str, current_tenant_id: str, keyword: Optional[str] = None): query = ( db.session.query(Tag.id, Tag.type, Tag.name, func.count(TagBinding.id).label("binding_count")) .outerjoin(TagBinding, Tag.id == TagBinding.tag_id) @@ -25,7 +25,7 @@ class TagService: return results @staticmethod - def get_target_ids_by_tag_ids(tag_type: str, current_tenant_id: str, tag_ids: list) -> list: + def get_target_ids_by_tag_ids(tag_type: str, current_tenant_id: str, tag_ids: list): # Check if tag_ids is not empty to avoid WHERE false condition if not tag_ids or len(tag_ids) == 0: return [] @@ -51,7 +51,7 @@ class TagService: return results @staticmethod - def get_tag_by_tag_name(tag_type: str, current_tenant_id: str, tag_name: str) -> list: + def get_tag_by_tag_name(tag_type: str, current_tenant_id: str, tag_name: str): if not tag_type or not tag_name: return [] tags = ( @@ -64,7 +64,7 @@ class TagService: return tags @staticmethod - def get_tags_by_target_id(tag_type: str, current_tenant_id: str, target_id: str) -> list: + def get_tags_by_target_id(tag_type: str, current_tenant_id: str, target_id: str): tags = ( db.session.query(Tag) .join(TagBinding, Tag.id == TagBinding.tag_id) diff --git a/api/services/tools/workflow_tools_manage_service.py b/api/services/tools/workflow_tools_manage_service.py index 75da5e5eaa..2f8a91ed82 100644 --- a/api/services/tools/workflow_tools_manage_service.py +++ b/api/services/tools/workflow_tools_manage_service.py @@ -37,7 +37,7 @@ class WorkflowToolManageService: parameters: list[Mapping[str, Any]], privacy_policy: str = "", labels: list[str] | None = None, - ) -> dict: + ): WorkflowToolConfigurationUtils.check_parameter_configurations(parameters) # check if the name is unique @@ -103,7 +103,7 @@ class WorkflowToolManageService: parameters: list[Mapping[str, Any]], privacy_policy: str = "", labels: list[str] | None = None, - ) -> dict: + ): """ Update a workflow tool. :param user_id: the user id @@ -217,7 +217,7 @@ class WorkflowToolManageService: return result @classmethod - def delete_workflow_tool(cls, user_id: str, tenant_id: str, workflow_tool_id: str) -> dict: + def delete_workflow_tool(cls, user_id: str, tenant_id: str, workflow_tool_id: str): """ Delete a workflow tool. :param user_id: the user id @@ -233,7 +233,7 @@ class WorkflowToolManageService: return {"result": "success"} @classmethod - def get_workflow_tool_by_tool_id(cls, user_id: str, tenant_id: str, workflow_tool_id: str) -> dict: + def get_workflow_tool_by_tool_id(cls, user_id: str, tenant_id: str, workflow_tool_id: str): """ Get a workflow tool. :param user_id: the user id @@ -249,7 +249,7 @@ class WorkflowToolManageService: return cls._get_workflow_tool(tenant_id, db_tool) @classmethod - def get_workflow_tool_by_app_id(cls, user_id: str, tenant_id: str, workflow_app_id: str) -> dict: + def get_workflow_tool_by_app_id(cls, user_id: str, tenant_id: str, workflow_app_id: str): """ Get a workflow tool. :param user_id: the user id @@ -265,7 +265,7 @@ class WorkflowToolManageService: return cls._get_workflow_tool(tenant_id, db_tool) @classmethod - def _get_workflow_tool(cls, tenant_id: str, db_tool: WorkflowToolProvider | None) -> dict: + def _get_workflow_tool(cls, tenant_id: str, db_tool: WorkflowToolProvider | None): """ Get a workflow tool. :db_tool: the database tool diff --git a/api/services/website_service.py b/api/services/website_service.py index 991b669737..131b96db13 100644 --- a/api/services/website_service.py +++ b/api/services/website_service.py @@ -132,7 +132,7 @@ class WebsiteService: return encrypter.decrypt_token(tenant_id=tenant_id, token=api_key) @classmethod - def document_create_args_validate(cls, args: dict) -> None: + def document_create_args_validate(cls, args: dict): """Validate arguments for document creation.""" try: WebsiteCrawlApiRequest.from_args(args) diff --git a/api/services/workflow/workflow_converter.py b/api/services/workflow/workflow_converter.py index 00b02f8091..2994856b54 100644 --- a/api/services/workflow/workflow_converter.py +++ b/api/services/workflow/workflow_converter.py @@ -217,7 +217,7 @@ class WorkflowConverter: return app_config - def _convert_to_start_node(self, variables: list[VariableEntity]) -> dict: + def _convert_to_start_node(self, variables: list[VariableEntity]): """ Convert to Start Node :param variables: list of variables @@ -384,7 +384,7 @@ class WorkflowConverter: prompt_template: PromptTemplateEntity, file_upload: Optional[FileUploadConfig] = None, external_data_variable_node_mapping: dict[str, str] | None = None, - ) -> dict: + ): """ Convert to LLM Node :param original_app_mode: original app mode @@ -550,7 +550,7 @@ class WorkflowConverter: return template - def _convert_to_end_node(self) -> dict: + def _convert_to_end_node(self): """ Convert to End Node :return: @@ -566,7 +566,7 @@ class WorkflowConverter: }, } - def _convert_to_answer_node(self) -> dict: + def _convert_to_answer_node(self): """ Convert to Answer Node :return: @@ -578,7 +578,7 @@ class WorkflowConverter: "data": {"title": "ANSWER", "type": NodeType.ANSWER.value, "answer": "{{#llm.text#}}"}, } - def _create_edge(self, source: str, target: str) -> dict: + def _create_edge(self, source: str, target: str): """ Create Edge :param source: source node id @@ -587,7 +587,7 @@ class WorkflowConverter: """ return {"id": f"{source}-{target}", "source": source, "target": target} - def _append_node(self, graph: dict, node: dict) -> dict: + def _append_node(self, graph: dict, node: dict): """ Append Node to Graph diff --git a/api/services/workflow_app_service.py b/api/services/workflow_app_service.py index 6eabf03018..eda55d31d4 100644 --- a/api/services/workflow_app_service.py +++ b/api/services/workflow_app_service.py @@ -23,7 +23,7 @@ class WorkflowAppService: limit: int = 20, created_by_end_user_session_id: str | None = None, created_by_account: str | None = None, - ) -> dict: + ): """ Get paginate workflow app logs using SQLAlchemy 2.0 style :param session: SQLAlchemy session diff --git a/api/services/workflow_draft_variable_service.py b/api/services/workflow_draft_variable_service.py index b3b581093e..ae5f0a998f 100644 --- a/api/services/workflow_draft_variable_service.py +++ b/api/services/workflow_draft_variable_service.py @@ -67,7 +67,7 @@ class DraftVarLoader(VariableLoader): app_id: str, tenant_id: str, fallback_variables: Sequence[Variable] | None = None, - ) -> None: + ): self._engine = engine self._app_id = app_id self._tenant_id = tenant_id @@ -117,7 +117,7 @@ class DraftVarLoader(VariableLoader): class WorkflowDraftVariableService: _session: Session - def __init__(self, session: Session) -> None: + def __init__(self, session: Session): """ Initialize the WorkflowDraftVariableService with a SQLAlchemy session. @@ -438,7 +438,7 @@ def _batch_upsert_draft_variable( session: Session, draft_vars: Sequence[WorkflowDraftVariable], policy: _UpsertPolicy = _UpsertPolicy.OVERWRITE, -) -> None: +): if not draft_vars: return None # Although we could use SQLAlchemy ORM operations here, we choose not to for several reasons: diff --git a/api/services/workflow_service.py b/api/services/workflow_service.py index 3f54f6624f..350e52e438 100644 --- a/api/services/workflow_service.py +++ b/api/services/workflow_service.py @@ -591,7 +591,7 @@ class WorkflowService: return new_app - def validate_features_structure(self, app_model: App, features: dict) -> dict: + def validate_features_structure(self, app_model: App, features: dict): if app_model.mode == AppMode.ADVANCED_CHAT.value: return AdvancedChatAppConfigManager.config_validate( tenant_id=app_model.tenant_id, config=features, only_structure_validate=True diff --git a/api/tasks/delete_conversation_task.py b/api/tasks/delete_conversation_task.py index dc2751a650..756b67c93e 100644 --- a/api/tasks/delete_conversation_task.py +++ b/api/tasks/delete_conversation_task.py @@ -14,7 +14,7 @@ logger = logging.getLogger(__name__) @shared_task(queue="conversation") -def delete_conversation_related_data(conversation_id: str) -> None: +def delete_conversation_related_data(conversation_id: str): """ Delete related data conversation in correct order from datatbase to respect foreign key constraints diff --git a/api/tasks/mail_account_deletion_task.py b/api/tasks/mail_account_deletion_task.py index 41e8bc9320..ae42dff907 100644 --- a/api/tasks/mail_account_deletion_task.py +++ b/api/tasks/mail_account_deletion_task.py @@ -11,7 +11,7 @@ logger = logging.getLogger(__name__) @shared_task(queue="mail") -def send_deletion_success_task(to: str, language: str = "en-US") -> None: +def send_deletion_success_task(to: str, language: str = "en-US"): """ Send account deletion success email with internationalization support. @@ -46,7 +46,7 @@ def send_deletion_success_task(to: str, language: str = "en-US") -> None: @shared_task(queue="mail") -def send_account_deletion_verification_code(to: str, code: str, language: str = "en-US") -> None: +def send_account_deletion_verification_code(to: str, code: str, language: str = "en-US"): """ Send account deletion verification code email with internationalization support. diff --git a/api/tasks/mail_change_mail_task.py b/api/tasks/mail_change_mail_task.py index c090a84923..a974e807b6 100644 --- a/api/tasks/mail_change_mail_task.py +++ b/api/tasks/mail_change_mail_task.py @@ -11,7 +11,7 @@ logger = logging.getLogger(__name__) @shared_task(queue="mail") -def send_change_mail_task(language: str, to: str, code: str, phase: str) -> None: +def send_change_mail_task(language: str, to: str, code: str, phase: str): """ Send change email notification with internationalization support. @@ -43,7 +43,7 @@ def send_change_mail_task(language: str, to: str, code: str, phase: str) -> None @shared_task(queue="mail") -def send_change_mail_completed_notification_task(language: str, to: str) -> None: +def send_change_mail_completed_notification_task(language: str, to: str): """ Send change email completed notification with internationalization support. diff --git a/api/tasks/mail_email_code_login.py b/api/tasks/mail_email_code_login.py index 126c169d04..e97eae92d8 100644 --- a/api/tasks/mail_email_code_login.py +++ b/api/tasks/mail_email_code_login.py @@ -11,7 +11,7 @@ logger = logging.getLogger(__name__) @shared_task(queue="mail") -def send_email_code_login_mail_task(language: str, to: str, code: str) -> None: +def send_email_code_login_mail_task(language: str, to: str, code: str): """ Send email code login email with internationalization support. diff --git a/api/tasks/mail_invite_member_task.py b/api/tasks/mail_invite_member_task.py index a5d59d7452..8b091fe0b0 100644 --- a/api/tasks/mail_invite_member_task.py +++ b/api/tasks/mail_invite_member_task.py @@ -12,7 +12,7 @@ logger = logging.getLogger(__name__) @shared_task(queue="mail") -def send_invite_member_mail_task(language: str, to: str, token: str, inviter_name: str, workspace_name: str) -> None: +def send_invite_member_mail_task(language: str, to: str, token: str, inviter_name: str, workspace_name: str): """ Send invite member email with internationalization support. diff --git a/api/tasks/mail_owner_transfer_task.py b/api/tasks/mail_owner_transfer_task.py index 33a8e17436..6a72dde2f4 100644 --- a/api/tasks/mail_owner_transfer_task.py +++ b/api/tasks/mail_owner_transfer_task.py @@ -11,7 +11,7 @@ logger = logging.getLogger(__name__) @shared_task(queue="mail") -def send_owner_transfer_confirm_task(language: str, to: str, code: str, workspace: str) -> None: +def send_owner_transfer_confirm_task(language: str, to: str, code: str, workspace: str): """ Send owner transfer confirmation email with internationalization support. @@ -52,7 +52,7 @@ def send_owner_transfer_confirm_task(language: str, to: str, code: str, workspac @shared_task(queue="mail") -def send_old_owner_transfer_notify_email_task(language: str, to: str, workspace: str, new_owner_email: str) -> None: +def send_old_owner_transfer_notify_email_task(language: str, to: str, workspace: str, new_owner_email: str): """ Send old owner transfer notification email with internationalization support. @@ -93,7 +93,7 @@ def send_old_owner_transfer_notify_email_task(language: str, to: str, workspace: @shared_task(queue="mail") -def send_new_owner_transfer_notify_email_task(language: str, to: str, workspace: str) -> None: +def send_new_owner_transfer_notify_email_task(language: str, to: str, workspace: str): """ Send new owner transfer notification email with internationalization support. diff --git a/api/tasks/mail_reset_password_task.py b/api/tasks/mail_reset_password_task.py index 1fcc2bfbaa..545db84fde 100644 --- a/api/tasks/mail_reset_password_task.py +++ b/api/tasks/mail_reset_password_task.py @@ -11,7 +11,7 @@ logger = logging.getLogger(__name__) @shared_task(queue="mail") -def send_reset_password_mail_task(language: str, to: str, code: str) -> None: +def send_reset_password_mail_task(language: str, to: str, code: str): """ Send reset password email with internationalization support. diff --git a/api/tasks/remove_app_and_related_data_task.py b/api/tasks/remove_app_and_related_data_task.py index 7bfda3d740..241e04e4d2 100644 --- a/api/tasks/remove_app_and_related_data_task.py +++ b/api/tasks/remove_app_and_related_data_task.py @@ -395,7 +395,7 @@ def delete_draft_variables_batch(app_id: str, batch_size: int = 1000) -> int: return total_deleted -def _delete_records(query_sql: str, params: dict, delete_func: Callable, name: str) -> None: +def _delete_records(query_sql: str, params: dict, delete_func: Callable, name: str): while True: with db.engine.begin() as conn: rs = conn.execute(sa.text(query_sql), params) diff --git a/api/tasks/workflow_execution_tasks.py b/api/tasks/workflow_execution_tasks.py index 77ddf83023..7d145fb50c 100644 --- a/api/tasks/workflow_execution_tasks.py +++ b/api/tasks/workflow_execution_tasks.py @@ -120,7 +120,7 @@ def _create_workflow_run_from_execution( return workflow_run -def _update_workflow_run_from_execution(workflow_run: WorkflowRun, execution: WorkflowExecution) -> None: +def _update_workflow_run_from_execution(workflow_run: WorkflowRun, execution: WorkflowExecution): """ Update a WorkflowRun database model from a WorkflowExecution domain entity. """ diff --git a/api/tasks/workflow_node_execution_tasks.py b/api/tasks/workflow_node_execution_tasks.py index 16356086cf..8f5127670f 100644 --- a/api/tasks/workflow_node_execution_tasks.py +++ b/api/tasks/workflow_node_execution_tasks.py @@ -140,9 +140,7 @@ def _create_node_execution_from_domain( return node_execution -def _update_node_execution_from_domain( - node_execution: WorkflowNodeExecutionModel, execution: WorkflowNodeExecution -) -> None: +def _update_node_execution_from_domain(node_execution: WorkflowNodeExecutionModel, execution: WorkflowNodeExecution): """ Update a WorkflowNodeExecutionModel database model from a WorkflowNodeExecution domain entity. """ diff --git a/api/tests/integration_tests/conftest.py b/api/tests/integration_tests/conftest.py index d9f90f992e..597e7330b7 100644 --- a/api/tests/integration_tests/conftest.py +++ b/api/tests/integration_tests/conftest.py @@ -14,7 +14,7 @@ from services.account_service import AccountService, RegisterService # Loading the .env file if it exists -def _load_env() -> None: +def _load_env(): current_file_path = pathlib.Path(__file__).absolute() # Items later in the list have higher precedence. files_to_load = [".env", "vdb.env"] diff --git a/api/tests/integration_tests/model_runtime/__mock/plugin_daemon.py b/api/tests/integration_tests/model_runtime/__mock/plugin_daemon.py index c8cb7528e1..d4cd5df553 100644 --- a/api/tests/integration_tests/model_runtime/__mock/plugin_daemon.py +++ b/api/tests/integration_tests/model_runtime/__mock/plugin_daemon.py @@ -17,7 +17,7 @@ def mock_plugin_daemon( :return: unpatch function """ - def unpatch() -> None: + def unpatch(): monkeypatch.undo() monkeypatch.setattr(PluginModelClient, "invoke_llm", MockModelClass.invoke_llm) diff --git a/api/tests/integration_tests/vdb/__mock/tcvectordb.py b/api/tests/integration_tests/vdb/__mock/tcvectordb.py index 02f658aad6..fd7ab0a22b 100644 --- a/api/tests/integration_tests/vdb/__mock/tcvectordb.py +++ b/api/tests/integration_tests/vdb/__mock/tcvectordb.py @@ -150,7 +150,7 @@ class MockTcvectordbClass: filter: Optional[Filter] = None, output_fields: Optional[list[str]] = None, timeout: Optional[float] = None, - ) -> list[dict]: + ): return [{"metadata": '{"doc_id":"foo1"}', "text": "text", "doc_id": "foo1", "score": 0.1}] def collection_delete( @@ -163,7 +163,7 @@ class MockTcvectordbClass: ): return {"code": 0, "msg": "operation success"} - def drop_collection(self, database_name: str, collection_name: str, timeout: Optional[float] = None) -> dict: + def drop_collection(self, database_name: str, collection_name: str, timeout: Optional[float] = None): return {"code": 0, "msg": "operation success"} diff --git a/api/tests/integration_tests/vdb/test_vector_store.py b/api/tests/integration_tests/vdb/test_vector_store.py index 50519e2052..a033443cf8 100644 --- a/api/tests/integration_tests/vdb/test_vector_store.py +++ b/api/tests/integration_tests/vdb/test_vector_store.py @@ -26,7 +26,7 @@ def get_example_document(doc_id: str) -> Document: @pytest.fixture -def setup_mock_redis() -> None: +def setup_mock_redis(): # get ext_redis.redis_client.get = MagicMock(return_value=None) @@ -48,7 +48,7 @@ class AbstractVectorTest: self.example_doc_id = str(uuid.uuid4()) self.example_embedding = [1.001 * i for i in range(128)] - def create_vector(self) -> None: + def create_vector(self): self.vector.create( texts=[get_example_document(doc_id=self.example_doc_id)], embeddings=[self.example_embedding], diff --git a/api/tests/integration_tests/workflow/nodes/__mock/code_executor.py b/api/tests/integration_tests/workflow/nodes/__mock/code_executor.py index 30414811ea..bdd2f5afda 100644 --- a/api/tests/integration_tests/workflow/nodes/__mock/code_executor.py +++ b/api/tests/integration_tests/workflow/nodes/__mock/code_executor.py @@ -12,7 +12,7 @@ MOCK = os.getenv("MOCK_SWITCH", "false") == "true" class MockedCodeExecutor: @classmethod - def invoke(cls, language: Literal["python3", "javascript", "jinja2"], code: str, inputs: dict) -> dict: + def invoke(cls, language: Literal["python3", "javascript", "jinja2"], code: str, inputs: dict): # invoke directly match language: case CodeLanguage.PYTHON3: diff --git a/api/tests/integration_tests/workflow/nodes/test_code.py b/api/tests/integration_tests/workflow/nodes/test_code.py index eb85d6118e..7c6e528996 100644 --- a/api/tests/integration_tests/workflow/nodes/test_code.py +++ b/api/tests/integration_tests/workflow/nodes/test_code.py @@ -74,7 +74,7 @@ def init_code_node(code_config: dict): @pytest.mark.parametrize("setup_code_executor_mock", [["none"]], indirect=True) def test_execute_code(setup_code_executor_mock): code = """ - def main(args1: int, args2: int) -> dict: + def main(args1: int, args2: int): return { "result": args1 + args2, } @@ -120,7 +120,7 @@ def test_execute_code(setup_code_executor_mock): @pytest.mark.parametrize("setup_code_executor_mock", [["none"]], indirect=True) def test_execute_code_output_validator(setup_code_executor_mock): code = """ - def main(args1: int, args2: int) -> dict: + def main(args1: int, args2: int): return { "result": args1 + args2, } @@ -163,7 +163,7 @@ def test_execute_code_output_validator(setup_code_executor_mock): def test_execute_code_output_validator_depth(): code = """ - def main(args1: int, args2: int) -> dict: + def main(args1: int, args2: int): return { "result": { "result": args1 + args2, @@ -281,7 +281,7 @@ def test_execute_code_output_validator_depth(): def test_execute_code_output_object_list(): code = """ - def main(args1: int, args2: int) -> dict: + def main(args1: int, args2: int): return { "result": { "result": args1 + args2, @@ -356,7 +356,7 @@ def test_execute_code_output_object_list(): def test_execute_code_scientific_notation(): code = """ - def main() -> dict: + def main(): return { "result": -8.0E-5 } diff --git a/api/tests/test_containers_integration_tests/conftest.py b/api/tests/test_containers_integration_tests/conftest.py index 66ddc0ba4c..f28437f6c1 100644 --- a/api/tests/test_containers_integration_tests/conftest.py +++ b/api/tests/test_containers_integration_tests/conftest.py @@ -49,7 +49,7 @@ class DifyTestContainers: self._containers_started = False logger.info("DifyTestContainers initialized - ready to manage test containers") - def start_containers_with_env(self) -> None: + def start_containers_with_env(self): """ Start all required containers for integration testing. @@ -230,7 +230,7 @@ class DifyTestContainers: self._containers_started = True logger.info("All test containers started successfully") - def stop_containers(self) -> None: + def stop_containers(self): """ Stop and clean up all test containers. diff --git a/api/tests/unit_tests/core/app/apps/common/test_workflow_response_converter.py b/api/tests/unit_tests/core/app/apps/common/test_workflow_response_converter.py index b88a57bfd4..5895f63f94 100644 --- a/api/tests/unit_tests/core/app/apps/common/test_workflow_response_converter.py +++ b/api/tests/unit_tests/core/app/apps/common/test_workflow_response_converter.py @@ -23,7 +23,7 @@ class TestWorkflowResponseConverterFetchFilesFromVariableValue: storage_key="storage_key_123", ) - def create_file_dict(self, file_id: str = "test_file_dict") -> dict: + def create_file_dict(self, file_id: str = "test_file_dict"): """Create a file dictionary with correct dify_model_identity""" return { "dify_model_identity": FILE_MODEL_IDENTITY, diff --git a/api/tests/unit_tests/core/mcp/client/test_session.py b/api/tests/unit_tests/core/mcp/client/test_session.py index c84169bf15..08d5b7d21c 100644 --- a/api/tests/unit_tests/core/mcp/client/test_session.py +++ b/api/tests/unit_tests/core/mcp/client/test_session.py @@ -83,7 +83,7 @@ def test_client_session_initialize(): # Create message handler def message_handler( message: RequestResponder[types.ServerRequest, types.ClientResult] | types.ServerNotification | Exception, - ) -> None: + ): if isinstance(message, Exception): raise message diff --git a/api/tests/unit_tests/core/workflow/graph_engine/test_graph_engine.py b/api/tests/unit_tests/core/workflow/graph_engine/test_graph_engine.py index ed4e42425e..0bf4fa7ee1 100644 --- a/api/tests/unit_tests/core/workflow/graph_engine/test_graph_engine.py +++ b/api/tests/unit_tests/core/workflow/graph_engine/test_graph_engine.py @@ -777,7 +777,7 @@ def test_condition_parallel_correct_output(mock_close, mock_remove, app): }, { "data": { - "code": '\ndef main(arg1: str, arg2: str) -> dict:\n return {\n "result": arg1 + arg2,\n }\n', # noqa: E501 + "code": '\ndef main(arg1: str, arg2: str):\n return {\n "result": arg1 + arg2,\n }\n', "code_language": "python3", "desc": "", "outputs": {"result": {"children": None, "type": "string"}}, diff --git a/api/tests/unit_tests/core/workflow/nodes/test_continue_on_error.py b/api/tests/unit_tests/core/workflow/nodes/test_continue_on_error.py index 3f83428834..d045ac5e44 100644 --- a/api/tests/unit_tests/core/workflow/nodes/test_continue_on_error.py +++ b/api/tests/unit_tests/core/workflow/nodes/test_continue_on_error.py @@ -233,7 +233,7 @@ FAIL_BRANCH_EDGES = [ def test_code_default_value_continue_on_error(): error_code = """ - def main() -> dict: + def main(): return { "result": 1 / 0, } @@ -259,7 +259,7 @@ def test_code_default_value_continue_on_error(): def test_code_fail_branch_continue_on_error(): error_code = """ - def main() -> dict: + def main(): return { "result": 1 / 0, } diff --git a/api/tests/unit_tests/core/workflow/nodes/test_if_else.py b/api/tests/unit_tests/core/workflow/nodes/test_if_else.py index 36a6fbb53e..dc0524f439 100644 --- a/api/tests/unit_tests/core/workflow/nodes/test_if_else.py +++ b/api/tests/unit_tests/core/workflow/nodes/test_if_else.py @@ -276,7 +276,7 @@ def test_array_file_contains_file_name(): assert result.outputs["result"] is True -def _get_test_conditions() -> list: +def _get_test_conditions(): conditions = [ # Test boolean "is" operator {"comparison_operator": "is", "variable_selector": ["start", "bool_true"], "value": "true"}, diff --git a/api/tests/unit_tests/core/workflow/test_variable_pool.py b/api/tests/unit_tests/core/workflow/test_variable_pool.py index c0330b9441..0be85abfab 100644 --- a/api/tests/unit_tests/core/workflow/test_variable_pool.py +++ b/api/tests/unit_tests/core/workflow/test_variable_pool.py @@ -379,7 +379,7 @@ class TestVariablePoolSerialization: self._assert_pools_equal(reconstructed_dict, reconstructed_json) # TODO: assert the data for file object... - def _assert_pools_equal(self, pool1: VariablePool, pool2: VariablePool) -> None: + def _assert_pools_equal(self, pool1: VariablePool, pool2: VariablePool): """Assert that two VariablePools contain equivalent data""" # Compare system variables diff --git a/api/tests/unit_tests/libs/test_email_i18n.py b/api/tests/unit_tests/libs/test_email_i18n.py index aeb30438e0..b80c711cac 100644 --- a/api/tests/unit_tests/libs/test_email_i18n.py +++ b/api/tests/unit_tests/libs/test_email_i18n.py @@ -27,7 +27,7 @@ from services.feature_service import BrandingModel class MockEmailRenderer: """Mock implementation of EmailRenderer protocol""" - def __init__(self) -> None: + def __init__(self): self.rendered_templates: list[tuple[str, dict[str, Any]]] = [] def render_template(self, template_path: str, **context: Any) -> str: @@ -39,7 +39,7 @@ class MockEmailRenderer: class MockBrandingService: """Mock implementation of BrandingService protocol""" - def __init__(self, enabled: bool = False, application_title: str = "Dify") -> None: + def __init__(self, enabled: bool = False, application_title: str = "Dify"): self.enabled = enabled self.application_title = application_title @@ -54,10 +54,10 @@ class MockBrandingService: class MockEmailSender: """Mock implementation of EmailSender protocol""" - def __init__(self) -> None: + def __init__(self): self.sent_emails: list[dict[str, str]] = [] - def send_email(self, to: str, subject: str, html_content: str) -> None: + def send_email(self, to: str, subject: str, html_content: str): """Mock send_email that records sent emails""" self.sent_emails.append( { @@ -134,7 +134,7 @@ class TestEmailI18nService: email_service: EmailI18nService, mock_renderer: MockEmailRenderer, mock_sender: MockEmailSender, - ) -> None: + ): """Test sending email with English language""" email_service.send_email( email_type=EmailType.RESET_PASSWORD, @@ -162,7 +162,7 @@ class TestEmailI18nService: self, email_service: EmailI18nService, mock_sender: MockEmailSender, - ) -> None: + ): """Test sending email with Chinese language""" email_service.send_email( email_type=EmailType.RESET_PASSWORD, @@ -181,7 +181,7 @@ class TestEmailI18nService: email_config: EmailI18nConfig, mock_renderer: MockEmailRenderer, mock_sender: MockEmailSender, - ) -> None: + ): """Test sending email with branding enabled""" # Create branding service with branding enabled branding_service = MockBrandingService(enabled=True, application_title="MyApp") @@ -215,7 +215,7 @@ class TestEmailI18nService: self, email_service: EmailI18nService, mock_sender: MockEmailSender, - ) -> None: + ): """Test language fallback to English when requested language not available""" # Request invite member in Chinese (not configured) email_service.send_email( @@ -233,7 +233,7 @@ class TestEmailI18nService: self, email_service: EmailI18nService, mock_sender: MockEmailSender, - ) -> None: + ): """Test unknown language code falls back to English""" email_service.send_email( email_type=EmailType.RESET_PASSWORD, @@ -252,7 +252,7 @@ class TestEmailI18nService: mock_renderer: MockEmailRenderer, mock_sender: MockEmailSender, mock_branding_service: MockBrandingService, - ) -> None: + ): """Test sending change email for old email verification""" # Add change email templates to config email_config.templates[EmailType.CHANGE_EMAIL_OLD] = { @@ -290,7 +290,7 @@ class TestEmailI18nService: mock_renderer: MockEmailRenderer, mock_sender: MockEmailSender, mock_branding_service: MockBrandingService, - ) -> None: + ): """Test sending change email for new email verification""" # Add change email templates to config email_config.templates[EmailType.CHANGE_EMAIL_NEW] = { @@ -325,7 +325,7 @@ class TestEmailI18nService: def test_send_change_email_invalid_phase( self, email_service: EmailI18nService, - ) -> None: + ): """Test sending change email with invalid phase raises error""" with pytest.raises(ValueError, match="Invalid phase: invalid_phase"): email_service.send_change_email( @@ -339,7 +339,7 @@ class TestEmailI18nService: self, email_service: EmailI18nService, mock_sender: MockEmailSender, - ) -> None: + ): """Test sending raw email to single recipient""" email_service.send_raw_email( to="test@example.com", @@ -357,7 +357,7 @@ class TestEmailI18nService: self, email_service: EmailI18nService, mock_sender: MockEmailSender, - ) -> None: + ): """Test sending raw email to multiple recipients""" recipients = ["user1@example.com", "user2@example.com", "user3@example.com"] @@ -378,7 +378,7 @@ class TestEmailI18nService: def test_get_template_missing_email_type( self, email_config: EmailI18nConfig, - ) -> None: + ): """Test getting template for missing email type raises error""" with pytest.raises(ValueError, match="No templates configured for email type"): email_config.get_template(EmailType.EMAIL_CODE_LOGIN, EmailLanguage.EN_US) @@ -386,7 +386,7 @@ class TestEmailI18nService: def test_get_template_missing_language_and_english( self, email_config: EmailI18nConfig, - ) -> None: + ): """Test error when neither requested language nor English fallback exists""" # Add template without English fallback email_config.templates[EmailType.EMAIL_CODE_LOGIN] = { @@ -407,7 +407,7 @@ class TestEmailI18nService: mock_renderer: MockEmailRenderer, mock_sender: MockEmailSender, mock_branding_service: MockBrandingService, - ) -> None: + ): """Test subject templating with custom variables""" # Add template with variable in subject email_config.templates[EmailType.OWNER_TRANSFER_NEW_NOTIFY] = { @@ -437,7 +437,7 @@ class TestEmailI18nService: sent_email = mock_sender.sent_emails[0] assert sent_email["subject"] == "You are now the owner of My Workspace" - def test_email_language_from_language_code(self) -> None: + def test_email_language_from_language_code(self): """Test EmailLanguage.from_language_code method""" assert EmailLanguage.from_language_code("zh-Hans") == EmailLanguage.ZH_HANS assert EmailLanguage.from_language_code("en-US") == EmailLanguage.EN_US @@ -448,7 +448,7 @@ class TestEmailI18nService: class TestEmailI18nIntegration: """Integration tests for email i18n components""" - def test_create_default_email_config(self) -> None: + def test_create_default_email_config(self): """Test creating default email configuration""" config = create_default_email_config() @@ -476,7 +476,7 @@ class TestEmailI18nIntegration: assert EmailLanguage.ZH_HANS in config.templates[EmailType.RESET_PASSWORD] assert EmailLanguage.ZH_HANS in config.templates[EmailType.INVITE_MEMBER] - def test_get_email_i18n_service(self) -> None: + def test_get_email_i18n_service(self): """Test getting global email i18n service instance""" service1 = get_email_i18n_service() service2 = get_email_i18n_service() @@ -484,7 +484,7 @@ class TestEmailI18nIntegration: # Should return the same instance assert service1 is service2 - def test_flask_email_renderer(self) -> None: + def test_flask_email_renderer(self): """Test FlaskEmailRenderer implementation""" renderer = FlaskEmailRenderer() @@ -494,7 +494,7 @@ class TestEmailI18nIntegration: with pytest.raises(TemplateNotFound): renderer.render_template("test.html", foo="bar") - def test_flask_mail_sender_not_initialized(self) -> None: + def test_flask_mail_sender_not_initialized(self): """Test FlaskMailSender when mail is not initialized""" sender = FlaskMailSender() @@ -514,7 +514,7 @@ class TestEmailI18nIntegration: # Restore original mail libs.email_i18n.mail = original_mail - def test_flask_mail_sender_initialized(self) -> None: + def test_flask_mail_sender_initialized(self): """Test FlaskMailSender when mail is initialized""" sender = FlaskMailSender() diff --git a/api/tests/unit_tests/libs/test_rsa.py b/api/tests/unit_tests/libs/test_rsa.py index 2dc51252f0..6a448d4f1f 100644 --- a/api/tests/unit_tests/libs/test_rsa.py +++ b/api/tests/unit_tests/libs/test_rsa.py @@ -4,7 +4,7 @@ from Crypto.PublicKey import RSA from libs import gmpy2_pkcs10aep_cipher -def test_gmpy2_pkcs10aep_cipher() -> None: +def test_gmpy2_pkcs10aep_cipher(): rsa_key_pair = pyrsa.newkeys(2048) public_key = rsa_key_pair[0].save_pkcs1() private_key = rsa_key_pair[1].save_pkcs1() diff --git a/api/tests/unit_tests/models/test_account.py b/api/tests/unit_tests/models/test_account.py index 026912ffbe..f555fc58d7 100644 --- a/api/tests/unit_tests/models/test_account.py +++ b/api/tests/unit_tests/models/test_account.py @@ -1,7 +1,7 @@ from models.account import TenantAccountRole -def test_account_is_privileged_role() -> None: +def test_account_is_privileged_role(): assert TenantAccountRole.ADMIN == "admin" assert TenantAccountRole.OWNER == "owner" assert TenantAccountRole.EDITOR == "editor" From 52b1ac5f54c9648e11a939484808fad7c512858b Mon Sep 17 00:00:00 2001 From: -LAN- Date: Sat, 6 Sep 2025 16:04:24 +0800 Subject: [PATCH 28/52] feat(web): add Progressive Web App (PWA) support (#25274) --- web/app/layout.tsx | 9 +- web/next.config.js | 69 +- web/package.json | 4 + web/pnpm-lock.yaml | 1811 +++++++++++++----- web/public/_offline.html | 129 ++ web/public/apple-touch-icon.png | Bin 0 -> 3264 bytes web/public/browserconfig.xml | 11 + web/public/fallback-hxi5kegOl0PxtKhvDL_OX.js | 1 + web/public/icon-128x128.png | Bin 0 -> 2279 bytes web/public/icon-144x144.png | Bin 0 -> 2541 bytes web/public/icon-152x152.png | Bin 0 -> 2709 bytes web/public/icon-192x192.png | Bin 0 -> 3464 bytes web/public/icon-256x256.png | Bin 0 -> 4941 bytes web/public/icon-384x384.png | Bin 0 -> 7937 bytes web/public/icon-512x512.png | Bin 0 -> 11364 bytes web/public/icon-72x72.png | Bin 0 -> 1309 bytes web/public/icon-96x96.png | Bin 0 -> 1694 bytes web/public/manifest.json | 58 + web/public/sw.js | 1 + web/public/workbox-c05e7c83.js | 1 + web/scripts/generate-icons.js | 51 + 21 files changed, 1643 insertions(+), 502 deletions(-) create mode 100644 web/public/_offline.html create mode 100644 web/public/apple-touch-icon.png create mode 100644 web/public/browserconfig.xml create mode 100644 web/public/fallback-hxi5kegOl0PxtKhvDL_OX.js create mode 100644 web/public/icon-128x128.png create mode 100644 web/public/icon-144x144.png create mode 100644 web/public/icon-152x152.png create mode 100644 web/public/icon-192x192.png create mode 100644 web/public/icon-256x256.png create mode 100644 web/public/icon-384x384.png create mode 100644 web/public/icon-512x512.png create mode 100644 web/public/icon-72x72.png create mode 100644 web/public/icon-96x96.png create mode 100644 web/public/manifest.json create mode 100644 web/public/sw.js create mode 100644 web/public/workbox-c05e7c83.js create mode 100644 web/scripts/generate-icons.js diff --git a/web/app/layout.tsx b/web/app/layout.tsx index 46afd95b97..1c6b1cccc8 100644 --- a/web/app/layout.tsx +++ b/web/app/layout.tsx @@ -53,10 +53,17 @@ const LocaleLayout = async ({ return ( - + + + + + + + + =10'} + peerDependencies: + ajv: '>=8' + '@babel/code-frame@7.27.1': resolution: {integrity: sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==} engines: {node: '>=6.9.0'} @@ -657,14 +675,18 @@ packages: resolution: {integrity: sha512-60X7qkglvrap8mn1lh2ebxXdZYtUcpd7gsmy9kLaBJ4i/WdY8PqTSdxyA8qraikqKQK5C1KRBKXqznrVapyNaw==} engines: {node: '>=6.9.0'} - '@babel/core@7.28.0': - resolution: {integrity: sha512-UlLAnTPrFdNGoFtbSXwcGFQBtQZJCNjaN6hQNP3UPvuNXT1i82N26KL3dZeIpNalWywr9IuQuncaAfUaS1g6sQ==} + '@babel/core@7.28.3': + resolution: {integrity: sha512-yDBHV9kQNcr2/sUr9jghVyz9C3Y5G2zUM2H2lo+9mKv4sFgbA8s8Z9t8D1jiTkGoO/NoIfKMyKWr4s6CN23ZwQ==} engines: {node: '>=6.9.0'} '@babel/generator@7.28.0': resolution: {integrity: sha512-lJjzvrbEeWrhB4P3QBsH7tey117PjLZnDbLiQEKjQ/fNJTjuq4HSqgFA+UNSwZT8D7dxxbnuSBMsa1lrWzKlQg==} engines: {node: '>=6.9.0'} + '@babel/generator@7.28.3': + resolution: {integrity: sha512-3lSpxGgvnmZznmBkCRnVREPUFJv2wrv9iAoFDvADJc0ypmdOxdUtcLeBgBJ6zE0PMeTKnxeQzyk0xTBq4Ep7zw==} + engines: {node: '>=6.9.0'} + '@babel/helper-annotate-as-pure@7.27.3': resolution: {integrity: sha512-fXSwMQqitTGeHLBC08Eq5yXz2m37E4pJX1qAU1+2cNedz/ifv/bVXft90VeSav5nFO61EcNgwr0aJxbyPaWBPg==} engines: {node: '>=6.9.0'} @@ -679,6 +701,12 @@ packages: peerDependencies: '@babel/core': ^7.0.0 + '@babel/helper-create-class-features-plugin@7.28.3': + resolution: {integrity: sha512-V9f6ZFIYSLNEbuGA/92uOvYsGCJNsuA8ESZ4ldc09bWk/j8H8TKiPw8Mk1eG6olpnO0ALHJmYfZvF4MEE4gajg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + '@babel/helper-create-regexp-features-plugin@7.27.1': resolution: {integrity: sha512-uVDC72XVf8UbrH5qQTc18Agb8emwjTiZrQE11Nv3CuBEZmVvTwwE9CBUEvHku06gQCAyYf8Nv6ja1IN+6LMbxQ==} engines: {node: '>=6.9.0'} @@ -708,6 +736,12 @@ packages: peerDependencies: '@babel/core': ^7.0.0 + '@babel/helper-module-transforms@7.28.3': + resolution: {integrity: sha512-gytXUbs8k2sXS9PnQptz5o0QnpLL51SwASIORY6XaBKF88nsOT0Zw9szLqlSGQDP/4TljBAD5y98p2U1fqkdsw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + '@babel/helper-optimise-call-expression@7.27.1': resolution: {integrity: sha512-URMGH08NzYFhubNSGJrpUEphGKQwMQYBySzat5cAByY1/YgIRkULnIy3tAMeszlL/so2HbeilYloUmSpd7GdVw==} engines: {node: '>=6.9.0'} @@ -748,8 +782,8 @@ packages: resolution: {integrity: sha512-NFJK2sHUvrjo8wAU/nQTWU890/zB2jj0qBcCbZbbf+005cAsv6tMjXz31fBign6M5ov1o0Bllu+9nbqkfsjjJQ==} engines: {node: '>=6.9.0'} - '@babel/helpers@7.27.6': - resolution: {integrity: sha512-muE8Tt8M22638HU31A3CgfSUciwz1fhATfoVai05aPXGor//CdWDCbnlY1yvBPo07njuVOCNGCSp/GTt12lIug==} + '@babel/helpers@7.28.3': + resolution: {integrity: sha512-PTNtvUQihsAsDHMOP5pfobP8C6CM4JWXmP8DrEIt46c3r2bf87Ua1zoqevsMo9g+tWDwgWrFP5EIxuBx5RudAw==} engines: {node: '>=6.9.0'} '@babel/parser@7.28.0': @@ -757,6 +791,11 @@ packages: engines: {node: '>=6.0.0'} hasBin: true + '@babel/parser@7.28.3': + resolution: {integrity: sha512-7+Ey1mAgYqFAx2h0RuoxcQT5+MlG3GTV0TQrgr7/ZliKsm/MNDxVVutlWaziMq7wJNAz8MTqz55XLpWvva6StA==} + engines: {node: '>=6.0.0'} + hasBin: true + '@babel/plugin-bugfix-firefox-class-in-computed-class-key@7.27.1': resolution: {integrity: sha512-QPG3C9cCVRQLxAVwmefEmwdTanECuUBMQZ/ym5kiw3XKCGA7qkuQLcjWWHcrD/GKbn/WmJwaezfuuAOcyKlRPA==} engines: {node: '>=6.9.0'} @@ -781,8 +820,8 @@ packages: peerDependencies: '@babel/core': ^7.13.0 - '@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly@7.27.1': - resolution: {integrity: sha512-6BpaYGDavZqkI6yT+KSPdpZFfpnd68UKXbcjI9pJ13pvHhPrCKWOOLp+ysvMeA+DxnhuPpgIaRpxRxo5A9t5jw==} + '@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly@7.28.3': + resolution: {integrity: sha512-b6YTX108evsvE4YgWyQ921ZAFFQm3Bn+CA3+ZXlNVnPhx+UfsVURoPjfGAPCjBgrqo30yX/C2nZGX96DxvR9Iw==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0 @@ -937,14 +976,14 @@ packages: peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-class-static-block@7.27.1': - resolution: {integrity: sha512-s734HmYU78MVzZ++joYM+NkJusItbdRcbm+AGRgJCt3iA+yux0QpD9cBVdz3tKyrjVYWRl7j0mHSmv4lhV0aoA==} + '@babel/plugin-transform-class-static-block@7.28.3': + resolution: {integrity: sha512-LtPXlBbRoc4Njl/oh1CeD/3jC+atytbnf/UqLoqTDcEYGUPj022+rvfkbDYieUrSj3CaV4yHDByPE+T2HwfsJg==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.12.0 - '@babel/plugin-transform-classes@7.28.0': - resolution: {integrity: sha512-IjM1IoJNw72AZFlj33Cu8X0q2XK/6AaVC3jQu+cgQ5lThWD5ajnuUAml80dqRmOhmPkTH8uAwnpMu9Rvj0LTRA==} + '@babel/plugin-transform-classes@7.28.3': + resolution: {integrity: sha512-DoEWC5SuxuARF2KdKmGUq3ghfPMO6ZzR12Dnp5gubwbeWJo4dbNWXJPVlwvh4Zlq6Z7YVvL8VFxeSOJgjsx4Sg==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 @@ -1159,8 +1198,8 @@ packages: peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-regenerator@7.28.1': - resolution: {integrity: sha512-P0QiV/taaa3kXpLY+sXla5zec4E+4t4Aqc9ggHlfZ7a2cp8/x/Gv08jfwEtn9gnnYIMvHx6aoOZ8XJL8eU71Dg==} + '@babel/plugin-transform-regenerator@7.28.3': + resolution: {integrity: sha512-K3/M/a4+ESb5LEldjQb+XSrpY0nF+ZBFlTCbSnKaYAMfD8v33O6PMs4uYnOk19HlcsI8WMu3McdFPTiQHF/1/A==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 @@ -1243,8 +1282,8 @@ packages: peerDependencies: '@babel/core': ^7.0.0 - '@babel/preset-env@7.28.0': - resolution: {integrity: sha512-VmaxeGOwuDqzLl5JUkIRM1X2Qu2uKGxHEQWh+cvvbl7JuJRgKGJSfsEF/bUaxFhJl/XAyxBe7q7qSuTbKFuCyg==} + '@babel/preset-env@7.28.3': + resolution: {integrity: sha512-ROiDcM+GbYVPYBOeCR6uBXKkQpBExLl8k9HO1ygXEyds39j+vCCsjmj7S8GOniZQlEs81QlkdJZe76IpLSiqpg==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 @@ -1278,10 +1317,18 @@ packages: resolution: {integrity: sha512-mGe7UK5wWyh0bKRfupsUchrQGqvDbZDbKJw+kcRGSmdHVYrv+ltd0pnpDTVpiTqnaBru9iEvA8pz8W46v0Amwg==} engines: {node: '>=6.9.0'} + '@babel/traverse@7.28.3': + resolution: {integrity: sha512-7w4kZYHneL3A6NP2nxzHvT3HCZ7puDZZjFMqDpBPECub79sTtSO5CGXDkKrTQq8ksAwfD/XI2MRFX23njdDaIQ==} + engines: {node: '>=6.9.0'} + '@babel/types@7.28.1': resolution: {integrity: sha512-x0LvFTekgSX+83TI28Y9wYPUfzrnl2aT5+5QLnO6v7mSJYtEEevuDRN0F0uSHRk1G1IWZC43o00Y0xDDrpBGPQ==} engines: {node: '>=6.9.0'} + '@babel/types@7.28.2': + resolution: {integrity: sha512-ruv7Ae4J5dUYULmeXw1gmb7rYRz57OWCPM57pHojnLq/3Z1CK2lNSLTCVjxVk1F/TZHwOZZrOWi0ur95BbLxNQ==} + engines: {node: '>=6.9.0'} + '@bcoe/v8-coverage@0.2.3': resolution: {integrity: sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==} @@ -1721,170 +1768,144 @@ packages: resolution: {integrity: sha512-9B+taZ8DlyyqzZQnoeIvDVR/2F4EbMepXMc/NdVbkzsJbzkUjhXv/70GQJ7tdLA4YJgNP25zukcxpX2/SueNrA==} cpu: [arm64] os: [linux] - libc: [glibc] '@img/sharp-libvips-linux-arm64@1.2.0': resolution: {integrity: sha512-RXwd0CgG+uPRX5YYrkzKyalt2OJYRiJQ8ED/fi1tq9WQW2jsQIn0tqrlR5l5dr/rjqq6AHAxURhj2DVjyQWSOA==} cpu: [arm64] os: [linux] - libc: [glibc] '@img/sharp-libvips-linux-arm@1.0.5': resolution: {integrity: sha512-gvcC4ACAOPRNATg/ov8/MnbxFDJqf/pDePbBnuBDcjsI8PssmjoKMAz4LtLaVi+OnSb5FK/yIOamqDwGmXW32g==} cpu: [arm] os: [linux] - libc: [glibc] '@img/sharp-libvips-linux-arm@1.2.0': resolution: {integrity: sha512-mWd2uWvDtL/nvIzThLq3fr2nnGfyr/XMXlq8ZJ9WMR6PXijHlC3ksp0IpuhK6bougvQrchUAfzRLnbsen0Cqvw==} cpu: [arm] os: [linux] - libc: [glibc] '@img/sharp-libvips-linux-ppc64@1.2.0': resolution: {integrity: sha512-Xod/7KaDDHkYu2phxxfeEPXfVXFKx70EAFZ0qyUdOjCcxbjqyJOEUpDe6RIyaunGxT34Anf9ue/wuWOqBW2WcQ==} cpu: [ppc64] os: [linux] - libc: [glibc] '@img/sharp-libvips-linux-s390x@1.0.4': resolution: {integrity: sha512-u7Wz6ntiSSgGSGcjZ55im6uvTrOxSIS8/dgoVMoiGE9I6JAfU50yH5BoDlYA1tcuGS7g/QNtetJnxA6QEsCVTA==} cpu: [s390x] os: [linux] - libc: [glibc] '@img/sharp-libvips-linux-s390x@1.2.0': resolution: {integrity: sha512-eMKfzDxLGT8mnmPJTNMcjfO33fLiTDsrMlUVcp6b96ETbnJmd4uvZxVJSKPQfS+odwfVaGifhsB07J1LynFehw==} cpu: [s390x] os: [linux] - libc: [glibc] '@img/sharp-libvips-linux-x64@1.0.4': resolution: {integrity: sha512-MmWmQ3iPFZr0Iev+BAgVMb3ZyC4KeFc3jFxnNbEPas60e1cIfevbtuyf9nDGIzOaW9PdnDciJm+wFFaTlj5xYw==} cpu: [x64] os: [linux] - libc: [glibc] '@img/sharp-libvips-linux-x64@1.2.0': resolution: {integrity: sha512-ZW3FPWIc7K1sH9E3nxIGB3y3dZkpJlMnkk7z5tu1nSkBoCgw2nSRTFHI5pB/3CQaJM0pdzMF3paf9ckKMSE9Tg==} cpu: [x64] os: [linux] - libc: [glibc] '@img/sharp-libvips-linuxmusl-arm64@1.0.4': resolution: {integrity: sha512-9Ti+BbTYDcsbp4wfYib8Ctm1ilkugkA/uscUn6UXK1ldpC1JjiXbLfFZtRlBhjPZ5o1NCLiDbg8fhUPKStHoTA==} cpu: [arm64] os: [linux] - libc: [musl] '@img/sharp-libvips-linuxmusl-arm64@1.2.0': resolution: {integrity: sha512-UG+LqQJbf5VJ8NWJ5Z3tdIe/HXjuIdo4JeVNADXBFuG7z9zjoegpzzGIyV5zQKi4zaJjnAd2+g2nna8TZvuW9Q==} cpu: [arm64] os: [linux] - libc: [musl] '@img/sharp-libvips-linuxmusl-x64@1.0.4': resolution: {integrity: sha512-viYN1KX9m+/hGkJtvYYp+CCLgnJXwiQB39damAO7WMdKWlIhmYTfHjwSbQeUK/20vY154mwezd9HflVFM1wVSw==} cpu: [x64] os: [linux] - libc: [musl] '@img/sharp-libvips-linuxmusl-x64@1.2.0': resolution: {integrity: sha512-SRYOLR7CXPgNze8akZwjoGBoN1ThNZoqpOgfnOxmWsklTGVfJiGJoC/Lod7aNMGA1jSsKWM1+HRX43OP6p9+6Q==} cpu: [x64] os: [linux] - libc: [musl] '@img/sharp-linux-arm64@0.33.5': resolution: {integrity: sha512-JMVv+AMRyGOHtO1RFBiJy/MBsgz0x4AWrT6QoEVVTyh1E39TrCUpTRI7mx9VksGX4awWASxqCYLCV4wBZHAYxA==} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} cpu: [arm64] os: [linux] - libc: [glibc] '@img/sharp-linux-arm64@0.34.3': resolution: {integrity: sha512-QdrKe3EvQrqwkDrtuTIjI0bu6YEJHTgEeqdzI3uWJOH6G1O8Nl1iEeVYRGdj1h5I21CqxSvQp1Yv7xeU3ZewbA==} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} cpu: [arm64] os: [linux] - libc: [glibc] '@img/sharp-linux-arm@0.33.5': resolution: {integrity: sha512-JTS1eldqZbJxjvKaAkxhZmBqPRGmxgu+qFKSInv8moZ2AmT5Yib3EQ1c6gp493HvrvV8QgdOXdyaIBrhvFhBMQ==} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} cpu: [arm] os: [linux] - libc: [glibc] '@img/sharp-linux-arm@0.34.3': resolution: {integrity: sha512-oBK9l+h6KBN0i3dC8rYntLiVfW8D8wH+NPNT3O/WBHeW0OQWCjfWksLUaPidsrDKpJgXp3G3/hkmhptAW0I3+A==} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} cpu: [arm] os: [linux] - libc: [glibc] '@img/sharp-linux-ppc64@0.34.3': resolution: {integrity: sha512-GLtbLQMCNC5nxuImPR2+RgrviwKwVql28FWZIW1zWruy6zLgA5/x2ZXk3mxj58X/tszVF69KK0Is83V8YgWhLA==} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} cpu: [ppc64] os: [linux] - libc: [glibc] '@img/sharp-linux-s390x@0.33.5': resolution: {integrity: sha512-y/5PCd+mP4CA/sPDKl2961b+C9d+vPAveS33s6Z3zfASk2j5upL6fXVPZi7ztePZ5CuH+1kW8JtvxgbuXHRa4Q==} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} cpu: [s390x] os: [linux] - libc: [glibc] '@img/sharp-linux-s390x@0.34.3': resolution: {integrity: sha512-3gahT+A6c4cdc2edhsLHmIOXMb17ltffJlxR0aC2VPZfwKoTGZec6u5GrFgdR7ciJSsHT27BD3TIuGcuRT0KmQ==} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} cpu: [s390x] os: [linux] - libc: [glibc] '@img/sharp-linux-x64@0.33.5': resolution: {integrity: sha512-opC+Ok5pRNAzuvq1AG0ar+1owsu842/Ab+4qvU879ippJBHvyY5n2mxF1izXqkPYlGuP/M556uh53jRLJmzTWA==} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} cpu: [x64] os: [linux] - libc: [glibc] '@img/sharp-linux-x64@0.34.3': resolution: {integrity: sha512-8kYso8d806ypnSq3/Ly0QEw90V5ZoHh10yH0HnrzOCr6DKAPI6QVHvwleqMkVQ0m+fc7EH8ah0BB0QPuWY6zJQ==} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} cpu: [x64] os: [linux] - libc: [glibc] '@img/sharp-linuxmusl-arm64@0.33.5': resolution: {integrity: sha512-XrHMZwGQGvJg2V/oRSUfSAfjfPxO+4DkiRh6p2AFjLQztWUuY/o8Mq0eMQVIY7HJ1CDQUJlxGGZRw1a5bqmd1g==} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} cpu: [arm64] os: [linux] - libc: [musl] '@img/sharp-linuxmusl-arm64@0.34.3': resolution: {integrity: sha512-vAjbHDlr4izEiXM1OTggpCcPg9tn4YriK5vAjowJsHwdBIdx0fYRsURkxLG2RLm9gyBq66gwtWI8Gx0/ov+JKQ==} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} cpu: [arm64] os: [linux] - libc: [musl] '@img/sharp-linuxmusl-x64@0.33.5': resolution: {integrity: sha512-WT+d/cgqKkkKySYmqoZ8y3pxx7lx9vVejxW/W4DOFMYVSkErR+w7mf2u8m/y4+xHe7yY9DAXQMWQhpnMuFfScw==} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} cpu: [x64] os: [linux] - libc: [musl] '@img/sharp-linuxmusl-x64@0.34.3': resolution: {integrity: sha512-gCWUn9547K5bwvOn9l5XGAEjVTTRji4aPTqLzGXHvIr6bIDZKNTA34seMPgM0WmSf+RYBH411VavCejp3PkOeQ==} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} cpu: [x64] os: [linux] - libc: [musl] '@img/sharp-wasm32@0.33.5': resolution: {integrity: sha512-ykUW4LVGaMcU9lu9thv85CbRMAwfeadCJHRsg2GmeRa/cJxsVY9Rbd57JcMxBkKHag5U/x7TSBpScF4U8ElVzg==} @@ -2168,28 +2189,24 @@ packages: engines: {node: '>= 10'} cpu: [arm64] os: [linux] - libc: [glibc] '@next/swc-linux-arm64-musl@15.5.0': resolution: {integrity: sha512-biWqIOE17OW/6S34t1X8K/3vb1+svp5ji5QQT/IKR+VfM3B7GvlCwmz5XtlEan2ukOUf9tj2vJJBffaGH4fGRw==} engines: {node: '>= 10'} cpu: [arm64] os: [linux] - libc: [musl] '@next/swc-linux-x64-gnu@15.5.0': resolution: {integrity: sha512-zPisT+obYypM/l6EZ0yRkK3LEuoZqHaSoYKj+5jiD9ESHwdr6QhnabnNxYkdy34uCigNlWIaCbjFmQ8FY5AlxA==} engines: {node: '>= 10'} cpu: [x64] os: [linux] - libc: [glibc] '@next/swc-linux-x64-musl@15.5.0': resolution: {integrity: sha512-+t3+7GoU9IYmk+N+FHKBNFdahaReoAktdOpXHFIPOU1ixxtdge26NgQEEkJkCw2dHT9UwwK5zw4mAsURw4E8jA==} engines: {node: '>= 10'} cpu: [x64] os: [linux] - libc: [musl] '@next/swc-win32-arm64-msvc@15.5.0': resolution: {integrity: sha512-d8MrXKh0A+c9DLiy1BUFwtg3Hu90Lucj3k6iKTUdPOv42Ve2UiIG8HYi3UAb8kFVluXxEfdpCoPPCSODk5fDcw==} @@ -2411,42 +2428,36 @@ packages: engines: {node: '>= 10.0.0'} cpu: [arm] os: [linux] - libc: [glibc] '@parcel/watcher-linux-arm-musl@2.5.1': resolution: {integrity: sha512-6E+m/Mm1t1yhB8X412stiKFG3XykmgdIOqhjWj+VL8oHkKABfu/gjFj8DvLrYVHSBNC+/u5PeNrujiSQ1zwd1Q==} engines: {node: '>= 10.0.0'} cpu: [arm] os: [linux] - libc: [musl] '@parcel/watcher-linux-arm64-glibc@2.5.1': resolution: {integrity: sha512-LrGp+f02yU3BN9A+DGuY3v3bmnFUggAITBGriZHUREfNEzZh/GO06FF5u2kx8x+GBEUYfyTGamol4j3m9ANe8w==} engines: {node: '>= 10.0.0'} cpu: [arm64] os: [linux] - libc: [glibc] '@parcel/watcher-linux-arm64-musl@2.5.1': resolution: {integrity: sha512-cFOjABi92pMYRXS7AcQv9/M1YuKRw8SZniCDw0ssQb/noPkRzA+HBDkwmyOJYp5wXcsTrhxO0zq1U11cK9jsFg==} engines: {node: '>= 10.0.0'} cpu: [arm64] os: [linux] - libc: [musl] '@parcel/watcher-linux-x64-glibc@2.5.1': resolution: {integrity: sha512-GcESn8NZySmfwlTsIur+49yDqSny2IhPeZfXunQi48DMugKeZ7uy1FX83pO0X22sHntJ4Ub+9k34XQCX+oHt2A==} engines: {node: '>= 10.0.0'} cpu: [x64] os: [linux] - libc: [glibc] '@parcel/watcher-linux-x64-musl@2.5.1': resolution: {integrity: sha512-n0E2EQbatQ3bXhcH2D1XIAANAcTZkQICBPVaxMeaCVBtOpBZpWJuf7LwyWPSBDITb7In8mqQgJ7gH8CILCURXg==} engines: {node: '>= 10.0.0'} cpu: [x64] os: [linux] - libc: [musl] '@parcel/watcher-win32-arm64@2.5.1': resolution: {integrity: sha512-RFzklRvmc3PkjKjry3hLF9wD7ppR4AKcWNzH7kXR7GUe0Igb3Nz8fyPwtZCSquGrhU5HhUNDr/mKBqj7tqA2Vw==} @@ -2760,6 +2771,34 @@ packages: resolution: {integrity: sha512-UuBOt7BOsKVOkFXRe4Ypd/lADuNIfqJXv8GvHqtXaTYXPPKkj2nS2zPllVsrtRjcomDhIJVBnZwfmlI222WH8g==} engines: {node: '>=14.0.0'} + '@rollup/plugin-babel@5.3.1': + resolution: {integrity: sha512-WFfdLWU/xVWKeRQnKmIAQULUI7Il0gZnBIH/ZFO069wYIfPu+8zrfp/KMW0atmELoRDq8FbiP3VCss9MhCut7Q==} + engines: {node: '>= 10.0.0'} + peerDependencies: + '@babel/core': ^7.0.0 + '@types/babel__core': ^7.1.9 + rollup: ^1.20.0||^2.0.0 + peerDependenciesMeta: + '@types/babel__core': + optional: true + + '@rollup/plugin-node-resolve@11.2.1': + resolution: {integrity: sha512-yc2n43jcqVyGE2sqV5/YCmocy9ArjVAP/BeXyTtADTBBX6V0e5UMqwO8CdQ0kzjb6zu5P1qMzsScCMRvE9OlVg==} + engines: {node: '>= 10.0.0'} + peerDependencies: + rollup: ^1.20.0||^2.0.0 + + '@rollup/plugin-replace@2.4.2': + resolution: {integrity: sha512-IGcu+cydlUMZ5En85jxHH4qj2hta/11BHq95iHEyb2sbgiN0eCdzvUcHw5gt9pBL5lTi4JDYJ1acCoMGpTvEZg==} + peerDependencies: + rollup: ^1.20.0 || ^2.0.0 + + '@rollup/pluginutils@3.1.0': + resolution: {integrity: sha512-GksZ6pr6TpIjHm8h9lSQ8pi8BE9VeubNT0OMJ3B5uZJ8pz73NPiqOtCog/x2/QzM1ENChPKxMDhiQuRHsqc+lg==} + engines: {node: '>= 8.0.0'} + peerDependencies: + rollup: ^1.20.0||^2.0.0 + '@rtsao/scc@1.1.0': resolution: {integrity: sha512-zt6OdqaDoOnJ1ZYsCYGt9YmWzDXl4vQdKTyJev62gFhRGKdx7mcT54V9KIjg+d2wi9EXsPvAPKe7i7WjfVWB8g==} @@ -3031,6 +3070,9 @@ packages: peerDependencies: eslint: '>=9.0.0' + '@surma/rollup-plugin-off-main-thread@2.2.3': + resolution: {integrity: sha512-lR8q/9W7hZpMWweNiAKU7NQerBnzQQLvi8qnTDU/fxItPhtZVMbPV3lbCwjhIlNBe9Bbr5V+KHshvWmVSG9cxQ==} + '@svgdotjs/svg.js@3.2.4': resolution: {integrity: sha512-BjJ/7vWNowlX3Z8O4ywT58DqbNRyYlkk6Yz/D13aB7hGmfQTvGX4Tkgtm/ApYlu9M7lCQi15xUEidqMUmdMYwg==} @@ -3279,12 +3321,18 @@ packages: '@types/estree-jsx@1.0.5': resolution: {integrity: sha512-52CcUVNFyfb1A2ALocQw/Dd1BQFNmSdkuC3BkZ6iqhdMfQz7JWOFRuJFloOzjk+6WijU56m9oKXFAXc7o3Towg==} + '@types/estree@0.0.39': + resolution: {integrity: sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw==} + '@types/estree@1.0.8': resolution: {integrity: sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==} '@types/geojson@7946.0.16': resolution: {integrity: sha512-6C8nqWur3j98U6+lXDfTUWIfgvZU+EumvpHKcYjujKH7woYyLj2sUmff0tRhrqM7BohUw7Pz3ZB1jj2gW9Fvmg==} + '@types/glob@7.2.0': + resolution: {integrity: sha512-ZUxbzKl0IfJILTS6t7ip5fQQM/J3TJYubDm3nMbgubNNYS62eXeUpoLUC8/7fJNiFYHTrGPQn7hspDUzIHX3UA==} + '@types/graceful-fs@4.1.9': resolution: {integrity: sha512-olP3sd1qOEe5dXTSaFvQG+02VdRXcdytWLAZsAq1PecU8uqQAhkrnbli7DagjtXKW/Bl7YJbUsa8MPcuc8LHEQ==} @@ -3339,6 +3387,10 @@ packages: '@types/mdx@2.0.13': resolution: {integrity: sha512-+OWZQfAYyio6YkJb3HLxDrvnx6SWWDbC0zVPfBRzUk0/nqoDyf6dNxQi3eArPe8rJ473nobTMQ/8Zk+LxJ+Yuw==} + '@types/minimatch@6.0.0': + resolution: {integrity: sha512-zmPitbQ8+6zNutpwgcQuLcsEpn/Cj54Kbn7L5pX0Os5kdWplB7xPgEh/g+SWOB/qmows2gpuCaPyduq8ZZRnxA==} + deprecated: This is a stub types definition. minimatch provides its own type definitions, so you do not need this installed. + '@types/ms@2.1.0': resolution: {integrity: sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA==} @@ -3380,6 +3432,9 @@ packages: '@types/recordrtc@5.6.14': resolution: {integrity: sha512-Reiy1sl11xP0r6w8DW3iQjc1BgXFyNC7aDuutysIjpFoqyftbQps9xPA2FoBkfVXpJM61betgYPNt+v65zvMhA==} + '@types/resolve@1.17.1': + resolution: {integrity: sha512-yy7HuzQhj0dhGpD8RLXSZWEkLsV9ibvxvi6EiJ3bkqLAO1RGo0WbkWQiwpRlSFymTJRz0d3k5LM3kkx8ArDbLw==} + '@types/resolve@1.20.6': resolution: {integrity: sha512-A4STmOXPhMUtHH+S6ymgE2GiBSMqf4oTvcQZMcHzokuTLVYzXTB8ttjcgxOVaAp2lGwEdzZ0J+cRbbeevQj1UQ==} @@ -3561,49 +3616,41 @@ packages: resolution: {integrity: sha512-34gw7PjDGB9JgePJEmhEqBhWvCiiWCuXsL9hYphDF7crW7UgI05gyBAi6MF58uGcMOiOqSJ2ybEeCvHcq0BCmQ==} cpu: [arm64] os: [linux] - libc: [glibc] '@unrs/resolver-binding-linux-arm64-musl@1.11.1': resolution: {integrity: sha512-RyMIx6Uf53hhOtJDIamSbTskA99sPHS96wxVE/bJtePJJtpdKGXO1wY90oRdXuYOGOTuqjT8ACccMc4K6QmT3w==} cpu: [arm64] os: [linux] - libc: [musl] '@unrs/resolver-binding-linux-ppc64-gnu@1.11.1': resolution: {integrity: sha512-D8Vae74A4/a+mZH0FbOkFJL9DSK2R6TFPC9M+jCWYia/q2einCubX10pecpDiTmkJVUH+y8K3BZClycD8nCShA==} cpu: [ppc64] os: [linux] - libc: [glibc] '@unrs/resolver-binding-linux-riscv64-gnu@1.11.1': resolution: {integrity: sha512-frxL4OrzOWVVsOc96+V3aqTIQl1O2TjgExV4EKgRY09AJ9leZpEg8Ak9phadbuX0BA4k8U5qtvMSQQGGmaJqcQ==} cpu: [riscv64] os: [linux] - libc: [glibc] '@unrs/resolver-binding-linux-riscv64-musl@1.11.1': resolution: {integrity: sha512-mJ5vuDaIZ+l/acv01sHoXfpnyrNKOk/3aDoEdLO/Xtn9HuZlDD6jKxHlkN8ZhWyLJsRBxfv9GYM2utQ1SChKew==} cpu: [riscv64] os: [linux] - libc: [musl] '@unrs/resolver-binding-linux-s390x-gnu@1.11.1': resolution: {integrity: sha512-kELo8ebBVtb9sA7rMe1Cph4QHreByhaZ2QEADd9NzIQsYNQpt9UkM9iqr2lhGr5afh885d/cB5QeTXSbZHTYPg==} cpu: [s390x] os: [linux] - libc: [glibc] '@unrs/resolver-binding-linux-x64-gnu@1.11.1': resolution: {integrity: sha512-C3ZAHugKgovV5YvAMsxhq0gtXuwESUKc5MhEtjBpLoHPLYM+iuwSj3lflFwK3DPm68660rZ7G8BMcwSro7hD5w==} cpu: [x64] os: [linux] - libc: [glibc] '@unrs/resolver-binding-linux-x64-musl@1.11.1': resolution: {integrity: sha512-rV0YSoyhK2nZ4vEswT/QwqzqQXw5I6CjoaYMOX0TqBlWhojUf8P94mvI7nuJTeaCkkds3QE4+zS8Ko+GdXuZtA==} cpu: [x64] os: [linux] - libc: [musl] '@unrs/resolver-binding-wasm32-wasi@1.11.1': resolution: {integrity: sha512-5u4RkfxJm+Ng7IWgkzi3qrFOvLvQYnPBmjmZQ8+szTK/b31fQCnleNl1GgEt7nIsZRIf5PLhPwT0WM+q45x/UQ==} @@ -3874,6 +3921,18 @@ packages: resolution: {integrity: sha512-COROpnaoap1E2F000S62r6A60uHZnmlvomhfyT2DlTcrY1OrBKn2UhH7qn5wTC9zMvD0AY7csdPSNwKP+7WiQw==} engines: {node: '>= 0.4'} + array-union@1.0.2: + resolution: {integrity: sha512-Dxr6QJj/RdU/hCaBjOfxW+q6lyuVE6JFWIrAUpuOOhoJJoQ99cUn3igRaHVB5P9WrgFVN0FfArM3x0cueOU8ng==} + engines: {node: '>=0.10.0'} + + array-union@2.1.0: + resolution: {integrity: sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==} + engines: {node: '>=8'} + + array-uniq@1.0.3: + resolution: {integrity: sha512-MNha4BWQ6JbwhFhj03YK552f7cb3AzoE8SzeljgChvL1dl3IcvggXVz1DilzySZkCja+CXuZbdW7yATchWn8/Q==} + engines: {node: '>=0.10.0'} + asn1.js@4.10.1: resolution: {integrity: sha512-p32cOF5q0Zqs9uBiONKYLm6BClCoBCM5O9JfeUSlnQLBTxYdTK+pW+nXflm8UkKd2UYlEbYz5qEi0JuZR9ckSw==} @@ -3895,6 +3954,10 @@ packages: async@3.2.6: resolution: {integrity: sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==} + at-least-node@1.0.0: + resolution: {integrity: sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==} + engines: {node: '>= 4.0.0'} + autoprefixer@10.4.21: resolution: {integrity: sha512-O+A6LWV5LDHSJD3LjHYoNi4VLsj/Whi7k6zG12xTYaU4cQ8oxQGckXNX8cRHK5yOZ/ppVHe0ZBXGzSV9jXdVbQ==} engines: {node: ^10 || ^12 || >=14} @@ -3916,6 +3979,20 @@ packages: peerDependencies: '@babel/core': ^7.8.0 + babel-loader@10.0.0: + resolution: {integrity: sha512-z8jt+EdS61AMw22nSfoNJAZ0vrtmhPRVi6ghL3rCeRZI8cdNYFiV5xeV3HbE7rlZZNmGH8BVccwWt8/ED0QOHA==} + engines: {node: ^18.20.0 || ^20.10.0 || >=22.0.0} + peerDependencies: + '@babel/core': ^7.12.0 + webpack: '>=5.61.0' + + babel-loader@8.4.1: + resolution: {integrity: sha512-nXzRChX+Z1GoE6yWavBQg6jDslyFF3SDjl2paADuoQtQW10JqShJt62R6eJQ5m/pjJFDT8xgKIWSP85OY8eXeA==} + engines: {node: '>= 8.9'} + peerDependencies: + '@babel/core': ^7.0.0 + webpack: '>=2' + babel-loader@9.2.1: resolution: {integrity: sha512-fqe8naHt46e0yIdkjUZYqddSXfej3AHajX+CSO5X7oy0EmPc6o5Xh+RClNoHjnieWz9AW4kZxW9yyFMhVB1QLA==} engines: {node: '>= 14.15.0'} @@ -4228,6 +4305,12 @@ packages: resolution: {integrity: sha512-GfisEZEJvzKrmGWkvfhgzcz/BllN1USeqD2V6tg14OAOgaCD2Z/PUEuxnAZ/nPvmaHRG7a8y77p1T/IRQ4D1Hw==} engines: {node: '>=4'} + clean-webpack-plugin@4.0.0: + resolution: {integrity: sha512-WuWE1nyTNAyW5T7oNyys2EN0cfP2fdRxhxnIQWiAp0bMabPdHhoGxM8A6YL2GhqwgrPnnaemVE7nv5XJ2Fhh2w==} + engines: {node: '>=10.0.0'} + peerDependencies: + webpack: '>=4.0.0 <6.0.0' + cli-cursor@5.0.0: resolution: {integrity: sha512-aCj4O5wKyszjMmDT4tZj93kxyydN/K5zPWSCe6/0AV/AA1pqe5ZBIw0a2ZfPQV7lL5/yb5HsUreJ6UFAF1tEQw==} engines: {node: '>=18'} @@ -4329,6 +4412,10 @@ packages: common-path-prefix@3.0.0: resolution: {integrity: sha512-QE33hToZseCH3jS0qN96O/bSh3kaw/h+Tq7ngyY9eWDUnTlTNUyqfqvCXioLe5Na5jFsL78ra/wuBU4iuEgd4w==} + common-tags@1.8.2: + resolution: {integrity: sha512-gk/Z852D2Wtb//0I+kRFNKKE9dIIVirjoqPoA1wJU+XePVXZfGeBpk45+A1rKO4Q43prqWBNY/MiIeRLbPWUaA==} + engines: {node: '>=4.0.0'} + commondir@1.0.1: resolution: {integrity: sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg==} @@ -4423,6 +4510,10 @@ packages: crypto-js@4.2.0: resolution: {integrity: sha512-KALDyEYgpY+Rlob/iriUtjV6d5Eq+Y191A5g4UqLAi8CyGP9N1+FdVbkc1SxKc2r4YAYqG8JzO2KGL+AizD70Q==} + crypto-random-string@2.0.0: + resolution: {integrity: sha512-v1plID3y9r/lPhviJ1wrXpLeyUIGAZ2SHNYTEapm7/8A9nLPoyvVp3RK/EPFqn5kEznyWgYZNsRtYYIWbuG8KA==} + engines: {node: '>=8'} + css-loader@6.11.0: resolution: {integrity: sha512-CTJ+AEQJjq5NzLga5pE39qdiSV56F8ywCIsqNIRF0r7BDgWsN25aazToqAFg7ZrtA/U016xudB3ffgweORxX7g==} engines: {node: '>= 12.13.0'} @@ -4682,6 +4773,10 @@ packages: resolution: {integrity: sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og==} engines: {node: '>=8'} + del@4.1.1: + resolution: {integrity: sha512-QwGuEUouP2kVwQenAsOof5Fv8K9t3D8Ca8NxcXKrIpEHjTXK5J2nXLdP+ALI1cgv8wj7KuwBhTwBkOZSJKM5XQ==} + engines: {node: '>=6'} + delaunator@5.0.1: resolution: {integrity: sha512-8nvh+XBe96aCESrGOqMp/84b13H9cdKbG5P2ejQCh4d4sK9RL4371qou9drQjMhvnPmhWl5hnmqbEE0fXr9Xnw==} @@ -4731,6 +4826,10 @@ packages: diffie-hellman@5.0.3: resolution: {integrity: sha512-kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg==} + dir-glob@3.0.1: + resolution: {integrity: sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==} + engines: {node: '>=8'} + dlv@1.1.3: resolution: {integrity: sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==} @@ -4790,6 +4889,11 @@ packages: echarts@5.6.0: resolution: {integrity: sha512-oTbVTsXfKuEhxftHqL5xprgLoc0k7uScAwtryCgWF6hPYFLRwOUHiFmHGCBKP5NPFNkDVopOieyUqYGH8Fa3kA==} + ejs@3.1.10: + resolution: {integrity: sha512-UeJmFfOrAQS8OJWPZ4qtgHyWExa088/MtK5UEyoJGFH67cDEXkZSviOiKRCZ4Xij0zxI3JECgYs3oKx+AizQBA==} + engines: {node: '>=0.10.0'} + hasBin: true + electron-to-chromium@1.5.186: resolution: {integrity: sha512-lur7L4BFklgepaJxj4DqPk7vKbTEl0pajNlg2QjE5shefmlmBLm2HvQ7PMf1R/GvlevT/581cop33/quQcfX3A==} @@ -5273,6 +5377,9 @@ packages: estree-util-visit@2.0.0: resolution: {integrity: sha512-m5KgiH85xAhhW8Wta0vShLcUvOsh3LLPI2YVwcbio1l7E09NTLL1EyMZFM1OyWowoH0skScNbhOPl4kcBgzTww==} + estree-walker@1.0.1: + resolution: {integrity: sha512-1fMXF3YP4pZZVozF8j/ZLfvnR8NSIljt56UhbZ5PeeDmmGHpgpdwQt7ITlGvYaQukCvuBRMLEiKiYC+oeIg4cg==} + estree-walker@2.0.2: resolution: {integrity: sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==} @@ -5369,6 +5476,9 @@ packages: resolution: {integrity: sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==} engines: {node: '>=16.0.0'} + filelist@1.0.4: + resolution: {integrity: sha512-w1cEuf3S+DrLCQL7ET6kz+gmlJdbq9J7yXCSjK/OZCPA+qEN1WyF4ZAf0YYJa4/shHJra2t/d/r8SV4Ji+x+8Q==} + filesize@10.1.6: resolution: {integrity: sha512-sJslQKU2uM33qH5nqewAwVB2QgR6w1aMNsYUp3aN5rMRyXEwJGmZvaWzeJFNTOXWlHQyBFCWrdj3fV/fsTOX8w==} engines: {node: '>= 10.4.0'} @@ -5438,6 +5548,10 @@ packages: resolution: {integrity: sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==} engines: {node: '>=12'} + fs-extra@9.1.0: + resolution: {integrity: sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==} + engines: {node: '>=10'} + fs-minipass@2.1.0: resolution: {integrity: sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==} engines: {node: '>= 8'} @@ -5477,6 +5591,9 @@ packages: resolution: {integrity: sha512-FJhYRoDaiatfEkUK8HKlicmu/3SGFD51q3itKDGoSTysQJBnfOcxU5GxnhE1E6soB76MbT0MBtnKJuXyAx+96Q==} engines: {node: '>=6'} + get-own-enumerable-property-symbols@3.0.2: + resolution: {integrity: sha512-I0UBV/XOz1XkIJHEUDMZAbzCThU/H8DxmSfmdGcKPnVhu2VfFqr34jr9777IyaTYvxjedWhqVIilEDsCdP5G6g==} + get-package-type@0.1.0: resolution: {integrity: sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==} engines: {node: '>=8.0.0'} @@ -5530,6 +5647,14 @@ packages: resolution: {integrity: sha512-bqWEnJ1Nt3neqx2q5SFfGS8r/ahumIakg3HcwtNlrVlwXIeNumWn/c7Pn/wKzGhf6SaW6H6uWXLqC30STCMchQ==} engines: {node: '>=18'} + globby@11.1.0: + resolution: {integrity: sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==} + engines: {node: '>=10'} + + globby@6.1.0: + resolution: {integrity: sha512-KVbFv2TQtbzCoxAnfD6JcHZTYCzyliEaaeM/gH8qQdkKr5s0OP9scEgvdcngyk7AVdY6YVW/TJHd+lQ/Df3Daw==} + engines: {node: '>=0.10.0'} + got@11.8.6: resolution: {integrity: sha512-6tfZ91bOr7bOXnK7PRDCGBLa1H4U080YHNaAQ2KsMGlLEzRbk44nsZF2E1IeRc3vtJHPVbKCYgdFbaGO2ljd8g==} engines: {node: '>=10.19.0'} @@ -5710,6 +5835,9 @@ packages: peerDependencies: postcss: ^8.1.0 + idb@7.1.1: + resolution: {integrity: sha512-gchesWBzyvGHRO9W8tzUWFDycow5gwjvFKfyV9FF32Y7F50yZMp7mP+T2mJIWFx49zicqyC4uefHM17o6xKIVQ==} + ieee754@1.2.1: resolution: {integrity: sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==} @@ -5849,10 +5977,29 @@ packages: eslint: '*' typescript: '>=4.7.4' + is-module@1.0.0: + resolution: {integrity: sha512-51ypPSPCoTEIN9dy5Oy+h4pShgJmPCygKfyRCISBI+JoWT/2oJvK8QPxmwv7b/p239jXrm9M1mlQbyKJ5A152g==} + is-number@7.0.0: resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} engines: {node: '>=0.12.0'} + is-obj@1.0.1: + resolution: {integrity: sha512-l4RyHgRqGN4Y3+9JHVrNqO+tN0rV5My76uW5/nuO4K1b6vw5G8d/cmFjP9tRfEsdhZNt0IFdZuK/c2Vr4Nb+Qg==} + engines: {node: '>=0.10.0'} + + is-path-cwd@2.2.0: + resolution: {integrity: sha512-w942bTcih8fdJPJmQHFzkS76NEP8Kzzvmw92cXsazb8intwLqPibPPdXf4ANdKV3rYMuuQYGIWtvz9JilB3NFQ==} + engines: {node: '>=6'} + + is-path-in-cwd@2.1.0: + resolution: {integrity: sha512-rNocXHgipO+rvnP6dk3zI20RpOtrAM/kzbB258Uw5BWr3TpXi861yzjo16Dn4hUox07iw5AyeMLHWsujkjzvRQ==} + engines: {node: '>=6'} + + is-path-inside@2.1.0: + resolution: {integrity: sha512-wiyhTzfDWsvwAW53OBWF5zuvaOGlZ6PwYxAbPVDhpm+gM09xKQGjBq/8uYN12aDvMxnAnq3dxTyoSoRNmg5YFg==} + engines: {node: '>=6'} + is-plain-obj@4.1.0: resolution: {integrity: sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg==} engines: {node: '>=12'} @@ -5861,6 +6008,10 @@ packages: resolution: {integrity: sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==} engines: {node: '>=0.10.0'} + is-regexp@1.0.0: + resolution: {integrity: sha512-7zjFAPO4/gwyQAAgRRmqeEeyIICSdmCqa3tsVHMdBzaXXRiqopZL4Cyghg/XulGWrtABTpbnYYzzIRffLkP4oA==} + engines: {node: '>=0.10.0'} + is-stream@2.0.1: resolution: {integrity: sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==} engines: {node: '>=8'} @@ -5906,6 +6057,11 @@ packages: jackspeak@3.4.3: resolution: {integrity: sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==} + jake@10.9.4: + resolution: {integrity: sha512-wpHYzhxiVQL+IV05BLE2Xn34zW1S223hvjtqk0+gsPrwd/8JNLXJgZZM/iPFsYc1xyphF+6M6EvdE5E9MBGkDA==} + engines: {node: '>=10'} + hasBin: true + jest-changed-files@29.7.0: resolution: {integrity: sha512-fEArFiwf1BpQ+4bXSprcDc3/x4HSzL4al2tozwVpDFpsxALjLYdyiIK4e5Vz66GQJIbXJ82+35PtysofptNX2w==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} @@ -6021,6 +6177,10 @@ packages: resolution: {integrity: sha512-49Fg7WXkU3Vl2h6LbLtMQ/HyB6rXSIX7SqvBLQmssRBGN9I0PNvPmAmCWSOY6SOvrjhI/F7/bGAv9RtnsPA03g==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + jest-worker@26.6.2: + resolution: {integrity: sha512-KWYVV1c4i+jbMpaBC+U++4Va0cp8OisU185o73T1vo99hqi7w8tSJfUXYswwqqrjzwxa6KpRK54WhPvwf5w6PQ==} + engines: {node: '>= 10.13.0'} + jest-worker@27.5.1: resolution: {integrity: sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==} engines: {node: '>= 10.13.0'} @@ -6087,6 +6247,9 @@ packages: json-schema-traverse@1.0.0: resolution: {integrity: sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==} + json-schema@0.4.0: + resolution: {integrity: sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==} + json-stable-stringify-without-jsonify@1.0.1: resolution: {integrity: sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==} @@ -6109,6 +6272,10 @@ packages: jsonfile@6.1.0: resolution: {integrity: sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==} + jsonpointer@5.0.1: + resolution: {integrity: sha512-p/nXbhSEcu3pZRdkW1OfJhpsVtW1gd4Wa1fnQc9YLiTfAjn0312eMKimbdIQzuZl9aa9xUGaRlP9T/CJE/ditQ==} + engines: {node: '>=0.10.0'} + jsonschema@1.5.0: resolution: {integrity: sha512-K+A9hhqbn0f3pJX17Q/7H6yQfD/5OXgdrR5UE12gMXCiN9D5Xq2o5mddV2QEcX/bjla99ASsAAQUyMCCRWAEhw==} @@ -6242,6 +6409,9 @@ packages: lodash.merge@4.6.2: resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==} + lodash.sortby@4.7.0: + resolution: {integrity: sha512-HDWXG8isMntAyRF5vZ7xKuEvOhT4AhlRt/3czTSjvGUxjYCBVRQY48ViDHyfYz9VIoBkW4TMGQNapx+l3RUwdA==} + lodash@4.17.21: resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==} @@ -6279,6 +6449,9 @@ packages: resolution: {integrity: sha512-h5bgJWpxJNswbU7qCrV0tIKQCaS3blPDrqKWx+QxzuzL1zGUzij9XCWLrSLsJPu5t+eWA/ycetzYAO5IOMcWAQ==} hasBin: true + magic-string@0.25.9: + resolution: {integrity: sha512-RmF0AsMzgt25qzqqLc1+MbHmhdx0ojF2Fvs4XnOqz2ZOBXzzkEwc/dJQZCYHAn7v1jbVOjAZfK8msRn4BxO4VQ==} + magic-string@0.30.17: resolution: {integrity: sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA==} @@ -6563,6 +6736,10 @@ packages: minimatch@3.1.2: resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==} + minimatch@5.1.6: + resolution: {integrity: sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==} + engines: {node: '>=10'} + minimatch@9.0.5: resolution: {integrity: sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==} engines: {node: '>=16 || 14 >=14.17'} @@ -6637,6 +6814,11 @@ packages: neo-async@2.6.2: resolution: {integrity: sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==} + next-pwa@5.6.0: + resolution: {integrity: sha512-XV8g8C6B7UmViXU8askMEYhWwQ4qc/XqJGnexbLV68hzKaGHZDMtHsm2TNxFcbR7+ypVuth/wwpiIlMwpRJJ5A==} + peerDependencies: + next: '>=9.0.0' + next-themes@0.4.6: resolution: {integrity: sha512-pZvgD5L0IEvX5/9GWyHMf3m8BKiVQwsCMHfoFosXtXBMnaS0ZnIJ9ST4b4NqLVKDEm8QBxoNNGNaBv2JNF6XNA==} peerDependencies: @@ -6798,6 +6980,10 @@ packages: resolution: {integrity: sha512-wPrq66Llhl7/4AGC6I+cqxT07LhXvWL08LNXz1fENOw0Ap4sRZZ/gZpTTJ5jpurzzzfS2W/Ge9BY3LgLjCShcw==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + p-map@2.1.0: + resolution: {integrity: sha512-y3b8Kpd8OAN444hxfBbFfj1FY/RjtTd8tzYwhUqNYXx0fXx2iX4maP4Qr6qhIKbQXI02wTLAda4fYUbDagTUFw==} + engines: {node: '>=6'} + p-try@2.2.0: resolution: {integrity: sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==} engines: {node: '>=6'} @@ -6869,6 +7055,9 @@ packages: resolution: {integrity: sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==} engines: {node: '>=0.10.0'} + path-is-inside@1.0.2: + resolution: {integrity: sha512-DUWJr3+ULp4zXmol/SZkFf3JGsS9/SIv+Y3Rt93/UjPpDpklB5f1er4O3POIbUuUJ3FXgqte2Q7SrU6zAqwk8w==} + path-key@3.1.1: resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} engines: {node: '>=8'} @@ -6927,6 +7116,18 @@ packages: resolution: {integrity: sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==} engines: {node: '>=0.10.0'} + pify@4.0.1: + resolution: {integrity: sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==} + engines: {node: '>=6'} + + pinkie-promise@2.0.1: + resolution: {integrity: sha512-0Gni6D4UcLTbv9c57DfxDGdr41XfgUjqWZu492f0cIGr16zDU06BWP/RAEvOuo7CQ0CNjHaLlM59YJJFm3NWlw==} + engines: {node: '>=0.10.0'} + + pinkie@2.0.4: + resolution: {integrity: sha512-MnUuEycAemtSaeFSjXKW/aroV7akBbY+Sv+RkyqFjgAe73F+MR0TBWKBRDkmfWq/HiFmdavfZ1G7h4SPZXaCSg==} + engines: {node: '>=0.10.0'} + pinyin-pro@3.26.0: resolution: {integrity: sha512-HcBZZb0pvm0/JkPhZHWA5Hqp2cWHXrrW/WrV+OtaYYM+kf35ffvZppIUuGmyuQ7gDr1JDJKMkbEE+GN0wfMoGg==} @@ -7067,6 +7268,10 @@ packages: resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==} engines: {node: '>= 0.8.0'} + pretty-bytes@5.6.0: + resolution: {integrity: sha512-FFw039TmrBqFK8ma/7OL3sDz/VytdtJr044/QUJtH0wK9lb9jLq9tJyIxUwtQJHwar2BqtiA4iCWSwo9JLkzFg==} + engines: {node: '>=6'} + pretty-error@4.0.0: resolution: {integrity: sha512-AoJ5YMAcXKYxKhuJGdcvse+Voc6v1RgnsR3nWcYU7q4t6z0Q6T86sv5Zq8VIRbOWWFpvdGE83LtdSMNd+6Y0xw==} @@ -7565,6 +7770,11 @@ packages: rfdc@1.4.1: resolution: {integrity: sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA==} + rimraf@2.7.1: + resolution: {integrity: sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==} + deprecated: Rimraf versions prior to v4 are no longer supported + hasBin: true + rimraf@3.0.2: resolution: {integrity: sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==} deprecated: Rimraf versions prior to v4 are no longer supported @@ -7579,6 +7789,17 @@ packages: robust-predicates@3.0.2: resolution: {integrity: sha512-IXgzBWvWQwE6PrDI05OvmXUIruQTcoMDzRsOd5CDvHCVLcLHMTSYvOK5Cm46kWqlV3yAbuSpBZdJ5oP5OUoStg==} + rollup-plugin-terser@7.0.2: + resolution: {integrity: sha512-w3iIaU4OxcF52UUXiZNsNeuXIMDvFrr+ZXK6bFZ0Q60qyVfq4uLptoS4bbq3paG3x216eQllFZX7zt6TIImguQ==} + deprecated: This package has been deprecated and is no longer maintained. Please use @rollup/plugin-terser + peerDependencies: + rollup: ^2.0.0 + + rollup@2.79.2: + resolution: {integrity: sha512-fS6iqSPZDs3dr/y7Od6y5nha8dW1YnbgtsyotCVvoFGKbERG++CVRFv1meyGDE1SNItQA8BrnCw7ScdAhRJ3XQ==} + engines: {node: '>=10.0.0'} + hasBin: true + roughjs@4.6.6: resolution: {integrity: sha512-ZUz/69+SYpFN/g/lUlo2FXcIjRkSu3nDarreVdGGndHEBJ6cXPdKguS8JGxwj5HA5xIbVKSmLgr5b3AWxtRfvQ==} @@ -7620,6 +7841,10 @@ packages: scheduler@0.26.0: resolution: {integrity: sha512-NlHwttCI/l5gCPR3D1nNXtWABUmBwvZpEQiD4IXSbIDq8BzLIK/7Ir5gTFSGZDUu37K5cMNp0hFtzO38sC7gWA==} + schema-utils@2.7.1: + resolution: {integrity: sha512-SHiNtMOUGWBQJwzISiVYKu82GiV4QYGePp3odlY1tuKO7gPtphAT5R/py0fA6xtbgLL/RvtJZnU9b8s0F1q0Xg==} + engines: {node: '>= 8.9.0'} + schema-utils@3.3.0: resolution: {integrity: sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==} engines: {node: '>= 10.13.0'} @@ -7645,6 +7870,9 @@ packages: engines: {node: '>=10'} hasBin: true + serialize-javascript@4.0.0: + resolution: {integrity: sha512-GaNA54380uFefWghODBWEGisLZFj00nS5ACs6yHa9nLqlLpVLO8ChDGeKRjZnV4Nh4n0Qi7nhYZD/9fCPzEqkw==} + serialize-javascript@6.0.2: resolution: {integrity: sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==} @@ -7722,6 +7950,9 @@ packages: sortablejs@1.15.6: resolution: {integrity: sha512-aNfiuwMEpfBM/CN6LY0ibyhxPfPbyFeBTYJKCvzkJ2GkUpazIt3H+QIPAMHwqQ7tMKaHz1Qj+rJJCqljnf4p3A==} + source-list-map@2.0.1: + resolution: {integrity: sha512-qnQ7gVMxGNxsiL4lEuJwe/To8UnK7fAnmbGEEH8RpLouuKbeEm0lhbQVFIrNSuB+G7tVrAlVsZgETT5nljf+Iw==} + source-map-js@1.2.1: resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==} engines: {node: '>=0.10.0'} @@ -7740,6 +7971,15 @@ packages: resolution: {integrity: sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==} engines: {node: '>= 8'} + source-map@0.8.0-beta.0: + resolution: {integrity: sha512-2ymg6oRBpebeZi9UUNsgQ89bhx01TcTkmNTGnNO88imTmbSgy4nfujrgVEFKWpMTEGA11EDkTt7mqObTPdigIA==} + engines: {node: '>= 8'} + deprecated: The work that was done in this beta branch won't be included in future versions + + sourcemap-codec@1.4.8: + resolution: {integrity: sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==} + deprecated: Please use @jridgewell/sourcemap-codec instead + space-separated-tokens@1.1.5: resolution: {integrity: sha512-q/JSVd1Lptzhf5bkYm4ob4iWPjx0KiRe3sRFBNrVqbJkFaBm5vbbowy1mymoPNLRa52+oadOhJ+K49wsSeSjTA==} @@ -7810,6 +8050,10 @@ packages: stringify-entities@4.0.4: resolution: {integrity: sha512-IwfBptatlO+QCJUo19AqvrPNqlVMpW9YEL2LIVY+Rpv2qsjCGxaDLNRgeGsQWJhfItebuJhsGSLjaBbNSQ+ieg==} + stringify-object@3.3.0: + resolution: {integrity: sha512-rHqiFh1elqCQ9WPLIC8I0Q/g/wj5J1eMkyoiD6eoQApWHP0FtlK7rqnhmabL5VUY9JQCcqwwvlOaSuutekgyrw==} + engines: {node: '>=4'} + strip-ansi@6.0.1: resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} engines: {node: '>=8'} @@ -7826,6 +8070,10 @@ packages: resolution: {integrity: sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==} engines: {node: '>=8'} + strip-comments@2.0.1: + resolution: {integrity: sha512-ZprKx+bBLXv067WTCALv8SSz5l2+XhpYCsVtSqlMnkAXMWDq+/ekVbl1ghqP9rUHTzv6sm/DwCOiYutU/yp1fw==} + engines: {node: '>=10'} + strip-final-newline@2.0.0: resolution: {integrity: sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==} engines: {node: '>=6'} @@ -7932,6 +8180,14 @@ packages: resolution: {integrity: sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==} engines: {node: '>=10'} + temp-dir@2.0.0: + resolution: {integrity: sha512-aoBAniQmmwtcKp/7BzsH8Cxzv8OL736p7v1ihGb5e9DJ9kTwGWHrQrVB5+lfVDzfGrdRzXch+ig7LHaY1JTOrg==} + engines: {node: '>=8'} + + tempy@0.6.0: + resolution: {integrity: sha512-G13vtMYPT/J8A4X2SjdtBTphZlrp1gKv6hZiOjw14RCWg6GbHuQBGtjlx75xLbYV/wEc0D7G5K4rxKP/cXk8Bw==} + engines: {node: '>=10'} + terser-webpack-plugin@5.3.14: resolution: {integrity: sha512-vkZjpUjb6OMS7dhV+tILUW6BhpDR7P2L/aQSAv+Uwk+m8KATX9EccViHTJR2qDtACKPIYndLGCyl3FMo+r2LMw==} engines: {node: '>= 10.13.0'} @@ -8025,6 +8281,9 @@ packages: tr46@0.0.3: resolution: {integrity: sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==} + tr46@1.0.1: + resolution: {integrity: sha512-dTpowEjclQ7Kgx5SdBkqRzVhERQXov8/l9Ft9dVM9fmg0W0KQSVaXX9T4i6twCPNtYiZM53lpSSUAwJbFPOHxA==} + trim-lines@3.0.1: resolution: {integrity: sha512-kRj8B+YHZCc9kQYdWfJB2/oUl9rA99qbowYYBtr4ui4mZyAQ2JpvVBd/6U2YloATfqBhBTSMhTpgBHtU0Mf3Rg==} @@ -8112,6 +8371,10 @@ packages: resolution: {integrity: sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==} engines: {node: '>=4'} + type-fest@0.16.0: + resolution: {integrity: sha512-eaBzG6MxNzEn9kiwvtre90cXaNLkmadMWa1zQMs3XORCXNbsH/OewwbxC5ia9dCxIxnTAsSxXJaa/p5y8DlvJg==} + engines: {node: '>=10'} + type-fest@0.21.3: resolution: {integrity: sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==} engines: {node: '>=10'} @@ -8159,6 +8422,10 @@ packages: unified@11.0.5: resolution: {integrity: sha512-xKvGhPWw3k84Qjh8bI3ZeJjqnyadK+GEFtazSfZv/rKeTkTjOJho6mFqh2SM96iIcZokxiOpg78GazTSg8+KHA==} + unique-string@2.0.0: + resolution: {integrity: sha512-uNaeirEPvpZWSgzwsPGtU2zVSTrn/8L5q/IexZmH0eH6SA73CmAA5U4GwORTxQAZs95TAXLNqeLoPPNO5gZfWg==} + engines: {node: '>=8'} + unist-util-find-after@5.0.0: resolution: {integrity: sha512-amQa0Ep2m6hE2g72AugUItjbuM8X8cGQnFoHk0pGfrFeT9GZhzN5SW8nRsiGKK7Aif4CrACPENkA6P/Lw6fHGQ==} @@ -8197,6 +8464,10 @@ packages: unrs-resolver@1.11.1: resolution: {integrity: sha512-bSjt9pjaEBnNiGgc9rUiHGKv5l4/TGzDmYw3RhnkJGtLhbnnA/5qJj7x3dNDCRx/PJxu774LlH8lCOlB4hEfKg==} + upath@1.2.0: + resolution: {integrity: sha512-aZwGpamFO61g3OlfT7OQCHqhGnW43ieH9WZeP7QxN/G/jS4jfqUkZxoryvJgVPEcrl5NL/ggHsSmLMHuH64Lhg==} + engines: {node: '>=4'} + update-browserslist-db@1.1.3: resolution: {integrity: sha512-UxhIZQ+QInVdunkDAaiazvvT/+fXL5Osr0JZlJulepYu6Jd7qJtDZjlur0emRlT71EN3ScPoE7gvsuIKKNavKw==} hasBin: true @@ -8353,6 +8624,9 @@ packages: webidl-conversions@3.0.1: resolution: {integrity: sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==} + webidl-conversions@4.0.2: + resolution: {integrity: sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg==} + webidl-conversions@7.0.0: resolution: {integrity: sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==} engines: {node: '>=12'} @@ -8377,6 +8651,9 @@ packages: webpack-hot-middleware@2.26.1: resolution: {integrity: sha512-khZGfAeJx6I8K9zKohEWWYN6KDlVw2DHownoe+6Vtwj1LP9WFgegXnVMSkZ/dBEBtXFwrkkydsaPFlB7f8wU2A==} + webpack-sources@1.4.3: + resolution: {integrity: sha512-lgTS3Xhv1lCOKo7SA5TjKXMjpSM4sBjNV5+q2bqesbSPs5FjGmU6jjtBSkX9b4qW87vDIsCIlUPOEhbZrMdjeQ==} + webpack-sources@3.3.3: resolution: {integrity: sha512-yd1RBzSGanHkitROoPFd6qsrxt+oFhg/129YzheDGqeustzX0vTZJZsSsQjVQC4yzBQ56K55XU8gaNCtIzOnTg==} engines: {node: '>=10.13.0'} @@ -8401,6 +8678,9 @@ packages: whatwg-url@5.0.0: resolution: {integrity: sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==} + whatwg-url@7.1.0: + resolution: {integrity: sha512-WUu7Rg1DroM7oQvGWfOiAK21n74Gg+T4elXEQYkOhtyLeWiJFoOGLXPKI/9gzIie9CtwVLm8wtw6YJdKyxSjeg==} + which@2.0.2: resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} engines: {node: '>= 8'} @@ -8413,6 +8693,63 @@ packages: resolution: {integrity: sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==} engines: {node: '>=0.10.0'} + workbox-background-sync@6.6.0: + resolution: {integrity: sha512-jkf4ZdgOJxC9u2vztxLuPT/UjlH7m/nWRQ/MgGL0v8BJHoZdVGJd18Kck+a0e55wGXdqyHO+4IQTk0685g4MUw==} + + workbox-broadcast-update@6.6.0: + resolution: {integrity: sha512-nm+v6QmrIFaB/yokJmQ/93qIJ7n72NICxIwQwe5xsZiV2aI93MGGyEyzOzDPVz5THEr5rC3FJSsO3346cId64Q==} + + workbox-build@6.6.0: + resolution: {integrity: sha512-Tjf+gBwOTuGyZwMz2Nk/B13Fuyeo0Q84W++bebbVsfr9iLkDSo6j6PST8tET9HYA58mlRXwlMGpyWO8ETJiXdQ==} + engines: {node: '>=10.0.0'} + + workbox-cacheable-response@6.6.0: + resolution: {integrity: sha512-JfhJUSQDwsF1Xv3EV1vWzSsCOZn4mQ38bWEBR3LdvOxSPgB65gAM6cS2CX8rkkKHRgiLrN7Wxoyu+TuH67kHrw==} + deprecated: workbox-background-sync@6.6.0 + + workbox-core@6.6.0: + resolution: {integrity: sha512-GDtFRF7Yg3DD859PMbPAYPeJyg5gJYXuBQAC+wyrWuuXgpfoOrIQIvFRZnQ7+czTIQjIr1DhLEGFzZanAT/3bQ==} + + workbox-expiration@6.6.0: + resolution: {integrity: sha512-baplYXcDHbe8vAo7GYvyAmlS4f6998Jff513L4XvlzAOxcl8F620O91guoJ5EOf5qeXG4cGdNZHkkVAPouFCpw==} + + workbox-google-analytics@6.6.0: + resolution: {integrity: sha512-p4DJa6OldXWd6M9zRl0H6vB9lkrmqYFkRQ2xEiNdBFp9U0LhsGO7hsBscVEyH9H2/3eZZt8c97NB2FD9U2NJ+Q==} + deprecated: It is not compatible with newer versions of GA starting with v4, as long as you are using GAv3 it should be ok, but the package is not longer being maintained + + workbox-navigation-preload@6.6.0: + resolution: {integrity: sha512-utNEWG+uOfXdaZmvhshrh7KzhDu/1iMHyQOV6Aqup8Mm78D286ugu5k9MFD9SzBT5TcwgwSORVvInaXWbvKz9Q==} + + workbox-precaching@6.6.0: + resolution: {integrity: sha512-eYu/7MqtRZN1IDttl/UQcSZFkHP7dnvr/X3Vn6Iw6OsPMruQHiVjjomDFCNtd8k2RdjLs0xiz9nq+t3YVBcWPw==} + + workbox-range-requests@6.6.0: + resolution: {integrity: sha512-V3aICz5fLGq5DpSYEU8LxeXvsT//mRWzKrfBOIxzIdQnV/Wj7R+LyJVTczi4CQ4NwKhAaBVaSujI1cEjXW+hTw==} + + workbox-recipes@6.6.0: + resolution: {integrity: sha512-TFi3kTgYw73t5tg73yPVqQC8QQjxJSeqjXRO4ouE/CeypmP2O/xqmB/ZFBBQazLTPxILUQ0b8aeh0IuxVn9a6A==} + + workbox-routing@6.6.0: + resolution: {integrity: sha512-x8gdN7VDBiLC03izAZRfU+WKUXJnbqt6PG9Uh0XuPRzJPpZGLKce/FkOX95dWHRpOHWLEq8RXzjW0O+POSkKvw==} + + workbox-strategies@6.6.0: + resolution: {integrity: sha512-eC07XGuINAKUWDnZeIPdRdVja4JQtTuc35TZ8SwMb1ztjp7Ddq2CJ4yqLvWzFWGlYI7CG/YGqaETntTxBGdKgQ==} + + workbox-streams@6.6.0: + resolution: {integrity: sha512-rfMJLVvwuED09CnH1RnIep7L9+mj4ufkTyDPVaXPKlhi9+0czCu+SJggWCIFbPpJaAZmp2iyVGLqS3RUmY3fxg==} + + workbox-sw@6.6.0: + resolution: {integrity: sha512-R2IkwDokbtHUE4Kus8pKO5+VkPHD2oqTgl+XJwh4zbF1HyjAbgNmK/FneZHVU7p03XUt9ICfuGDYISWG9qV/CQ==} + + workbox-webpack-plugin@6.6.0: + resolution: {integrity: sha512-xNZIZHalboZU66Wa7x1YkjIqEy1gTR+zPM+kjrYJzqN7iurYZBctBLISyScjhkJKYuRrZUP0iqViZTh8rS0+3A==} + engines: {node: '>=10.0.0'} + peerDependencies: + webpack: ^4.4.0 || ^5.9.0 + + workbox-window@6.6.0: + resolution: {integrity: sha512-L4N9+vka17d16geaJXXRjENLFldvkWy7JyGxElRD0JvBxvFEd8LOhr+uXCcar/NzAmIBRv9EZ+M+Qr4mOoBITw==} + wrap-ansi@7.0.0: resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==} engines: {node: '>=10'} @@ -8612,6 +8949,13 @@ snapshots: '@antfu/utils@8.1.1': {} + '@apideck/better-ajv-errors@0.3.6(ajv@8.17.1)': + dependencies: + ajv: 8.17.1 + json-schema: 0.4.0 + jsonpointer: 5.0.1 + leven: 3.1.0 + '@babel/code-frame@7.27.1': dependencies: '@babel/helper-validator-identifier': 7.27.1 @@ -8620,18 +8964,18 @@ snapshots: '@babel/compat-data@7.28.0': {} - '@babel/core@7.28.0': + '@babel/core@7.28.3': dependencies: '@ampproject/remapping': 2.3.0 '@babel/code-frame': 7.27.1 - '@babel/generator': 7.28.0 + '@babel/generator': 7.28.3 '@babel/helper-compilation-targets': 7.27.2 - '@babel/helper-module-transforms': 7.27.3(@babel/core@7.28.0) - '@babel/helpers': 7.27.6 - '@babel/parser': 7.28.0 + '@babel/helper-module-transforms': 7.28.3(@babel/core@7.28.3) + '@babel/helpers': 7.28.3 + '@babel/parser': 7.28.3 '@babel/template': 7.27.2 - '@babel/traverse': 7.28.0 - '@babel/types': 7.28.1 + '@babel/traverse': 7.28.3 + '@babel/types': 7.28.2 convert-source-map: 2.0.0 debug: 4.4.1 gensync: 1.0.0-beta.2 @@ -8648,6 +8992,14 @@ snapshots: '@jridgewell/trace-mapping': 0.3.29 jsesc: 3.1.0 + '@babel/generator@7.28.3': + dependencies: + '@babel/parser': 7.28.3 + '@babel/types': 7.28.2 + '@jridgewell/gen-mapping': 0.3.12 + '@jridgewell/trace-mapping': 0.3.29 + jsesc: 3.1.0 + '@babel/helper-annotate-as-pure@7.27.3': dependencies: '@babel/types': 7.28.1 @@ -8660,29 +9012,42 @@ snapshots: lru-cache: 5.1.1 semver: 6.3.1 - '@babel/helper-create-class-features-plugin@7.27.1(@babel/core@7.28.0)': + '@babel/helper-create-class-features-plugin@7.27.1(@babel/core@7.28.3)': dependencies: - '@babel/core': 7.28.0 + '@babel/core': 7.28.3 '@babel/helper-annotate-as-pure': 7.27.3 '@babel/helper-member-expression-to-functions': 7.27.1 '@babel/helper-optimise-call-expression': 7.27.1 - '@babel/helper-replace-supers': 7.27.1(@babel/core@7.28.0) + '@babel/helper-replace-supers': 7.27.1(@babel/core@7.28.3) '@babel/helper-skip-transparent-expression-wrappers': 7.27.1 '@babel/traverse': 7.28.0 semver: 6.3.1 transitivePeerDependencies: - supports-color - '@babel/helper-create-regexp-features-plugin@7.27.1(@babel/core@7.28.0)': + '@babel/helper-create-class-features-plugin@7.28.3(@babel/core@7.28.3)': dependencies: - '@babel/core': 7.28.0 + '@babel/core': 7.28.3 + '@babel/helper-annotate-as-pure': 7.27.3 + '@babel/helper-member-expression-to-functions': 7.27.1 + '@babel/helper-optimise-call-expression': 7.27.1 + '@babel/helper-replace-supers': 7.27.1(@babel/core@7.28.3) + '@babel/helper-skip-transparent-expression-wrappers': 7.27.1 + '@babel/traverse': 7.28.3 + semver: 6.3.1 + transitivePeerDependencies: + - supports-color + + '@babel/helper-create-regexp-features-plugin@7.27.1(@babel/core@7.28.3)': + dependencies: + '@babel/core': 7.28.3 '@babel/helper-annotate-as-pure': 7.27.3 regexpu-core: 6.2.0 semver: 6.3.1 - '@babel/helper-define-polyfill-provider@0.6.5(@babel/core@7.28.0)': + '@babel/helper-define-polyfill-provider@0.6.5(@babel/core@7.28.3)': dependencies: - '@babel/core': 7.28.0 + '@babel/core': 7.28.3 '@babel/helper-compilation-targets': 7.27.2 '@babel/helper-plugin-utils': 7.27.1 debug: 4.4.1 @@ -8707,33 +9072,42 @@ snapshots: transitivePeerDependencies: - supports-color - '@babel/helper-module-transforms@7.27.3(@babel/core@7.28.0)': + '@babel/helper-module-transforms@7.27.3(@babel/core@7.28.3)': dependencies: - '@babel/core': 7.28.0 + '@babel/core': 7.28.3 '@babel/helper-module-imports': 7.27.1 '@babel/helper-validator-identifier': 7.27.1 '@babel/traverse': 7.28.0 transitivePeerDependencies: - supports-color + '@babel/helper-module-transforms@7.28.3(@babel/core@7.28.3)': + dependencies: + '@babel/core': 7.28.3 + '@babel/helper-module-imports': 7.27.1 + '@babel/helper-validator-identifier': 7.27.1 + '@babel/traverse': 7.28.3 + transitivePeerDependencies: + - supports-color + '@babel/helper-optimise-call-expression@7.27.1': dependencies: '@babel/types': 7.28.1 '@babel/helper-plugin-utils@7.27.1': {} - '@babel/helper-remap-async-to-generator@7.27.1(@babel/core@7.28.0)': + '@babel/helper-remap-async-to-generator@7.27.1(@babel/core@7.28.3)': dependencies: - '@babel/core': 7.28.0 + '@babel/core': 7.28.3 '@babel/helper-annotate-as-pure': 7.27.3 '@babel/helper-wrap-function': 7.27.1 '@babel/traverse': 7.28.0 transitivePeerDependencies: - supports-color - '@babel/helper-replace-supers@7.27.1(@babel/core@7.28.0)': + '@babel/helper-replace-supers@7.27.1(@babel/core@7.28.3)': dependencies: - '@babel/core': 7.28.0 + '@babel/core': 7.28.3 '@babel/helper-member-expression-to-functions': 7.27.1 '@babel/helper-optimise-call-expression': 7.27.1 '@babel/traverse': 7.28.0 @@ -8761,643 +9135,647 @@ snapshots: transitivePeerDependencies: - supports-color - '@babel/helpers@7.27.6': + '@babel/helpers@7.28.3': dependencies: '@babel/template': 7.27.2 - '@babel/types': 7.28.1 + '@babel/types': 7.28.2 '@babel/parser@7.28.0': dependencies: '@babel/types': 7.28.1 - '@babel/plugin-bugfix-firefox-class-in-computed-class-key@7.27.1(@babel/core@7.28.0)': + '@babel/parser@7.28.3': dependencies: - '@babel/core': 7.28.0 + '@babel/types': 7.28.2 + + '@babel/plugin-bugfix-firefox-class-in-computed-class-key@7.27.1(@babel/core@7.28.3)': + dependencies: + '@babel/core': 7.28.3 '@babel/helper-plugin-utils': 7.27.1 '@babel/traverse': 7.28.0 transitivePeerDependencies: - supports-color - '@babel/plugin-bugfix-safari-class-field-initializer-scope@7.27.1(@babel/core@7.28.0)': + '@babel/plugin-bugfix-safari-class-field-initializer-scope@7.27.1(@babel/core@7.28.3)': dependencies: - '@babel/core': 7.28.0 + '@babel/core': 7.28.3 '@babel/helper-plugin-utils': 7.27.1 - '@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@7.27.1(@babel/core@7.28.0)': + '@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@7.27.1(@babel/core@7.28.3)': dependencies: - '@babel/core': 7.28.0 + '@babel/core': 7.28.3 '@babel/helper-plugin-utils': 7.27.1 - '@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@7.27.1(@babel/core@7.28.0)': + '@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@7.27.1(@babel/core@7.28.3)': dependencies: - '@babel/core': 7.28.0 + '@babel/core': 7.28.3 '@babel/helper-plugin-utils': 7.27.1 '@babel/helper-skip-transparent-expression-wrappers': 7.27.1 - '@babel/plugin-transform-optional-chaining': 7.27.1(@babel/core@7.28.0) + '@babel/plugin-transform-optional-chaining': 7.27.1(@babel/core@7.28.3) transitivePeerDependencies: - supports-color - '@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly@7.27.1(@babel/core@7.28.0)': + '@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly@7.28.3(@babel/core@7.28.3)': dependencies: - '@babel/core': 7.28.0 + '@babel/core': 7.28.3 '@babel/helper-plugin-utils': 7.27.1 + '@babel/traverse': 7.28.3 + transitivePeerDependencies: + - supports-color + + '@babel/plugin-proposal-private-property-in-object@7.21.0-placeholder-for-preset-env.2(@babel/core@7.28.3)': + dependencies: + '@babel/core': 7.28.3 + + '@babel/plugin-syntax-async-generators@7.8.4(@babel/core@7.28.3)': + dependencies: + '@babel/core': 7.28.3 + '@babel/helper-plugin-utils': 7.27.1 + + '@babel/plugin-syntax-bigint@7.8.3(@babel/core@7.28.3)': + dependencies: + '@babel/core': 7.28.3 + '@babel/helper-plugin-utils': 7.27.1 + + '@babel/plugin-syntax-class-properties@7.12.13(@babel/core@7.28.3)': + dependencies: + '@babel/core': 7.28.3 + '@babel/helper-plugin-utils': 7.27.1 + + '@babel/plugin-syntax-class-static-block@7.14.5(@babel/core@7.28.3)': + dependencies: + '@babel/core': 7.28.3 + '@babel/helper-plugin-utils': 7.27.1 + + '@babel/plugin-syntax-dynamic-import@7.8.3(@babel/core@7.28.3)': + dependencies: + '@babel/core': 7.28.3 + '@babel/helper-plugin-utils': 7.27.1 + + '@babel/plugin-syntax-import-assertions@7.27.1(@babel/core@7.28.3)': + dependencies: + '@babel/core': 7.28.3 + '@babel/helper-plugin-utils': 7.27.1 + + '@babel/plugin-syntax-import-attributes@7.27.1(@babel/core@7.28.3)': + dependencies: + '@babel/core': 7.28.3 + '@babel/helper-plugin-utils': 7.27.1 + + '@babel/plugin-syntax-import-meta@7.10.4(@babel/core@7.28.3)': + dependencies: + '@babel/core': 7.28.3 + '@babel/helper-plugin-utils': 7.27.1 + + '@babel/plugin-syntax-json-strings@7.8.3(@babel/core@7.28.3)': + dependencies: + '@babel/core': 7.28.3 + '@babel/helper-plugin-utils': 7.27.1 + + '@babel/plugin-syntax-jsx@7.27.1(@babel/core@7.28.3)': + dependencies: + '@babel/core': 7.28.3 + '@babel/helper-plugin-utils': 7.27.1 + + '@babel/plugin-syntax-logical-assignment-operators@7.10.4(@babel/core@7.28.3)': + dependencies: + '@babel/core': 7.28.3 + '@babel/helper-plugin-utils': 7.27.1 + + '@babel/plugin-syntax-nullish-coalescing-operator@7.8.3(@babel/core@7.28.3)': + dependencies: + '@babel/core': 7.28.3 + '@babel/helper-plugin-utils': 7.27.1 + + '@babel/plugin-syntax-numeric-separator@7.10.4(@babel/core@7.28.3)': + dependencies: + '@babel/core': 7.28.3 + '@babel/helper-plugin-utils': 7.27.1 + + '@babel/plugin-syntax-object-rest-spread@7.8.3(@babel/core@7.28.3)': + dependencies: + '@babel/core': 7.28.3 + '@babel/helper-plugin-utils': 7.27.1 + + '@babel/plugin-syntax-optional-catch-binding@7.8.3(@babel/core@7.28.3)': + dependencies: + '@babel/core': 7.28.3 + '@babel/helper-plugin-utils': 7.27.1 + + '@babel/plugin-syntax-optional-chaining@7.8.3(@babel/core@7.28.3)': + dependencies: + '@babel/core': 7.28.3 + '@babel/helper-plugin-utils': 7.27.1 + + '@babel/plugin-syntax-private-property-in-object@7.14.5(@babel/core@7.28.3)': + dependencies: + '@babel/core': 7.28.3 + '@babel/helper-plugin-utils': 7.27.1 + + '@babel/plugin-syntax-top-level-await@7.14.5(@babel/core@7.28.3)': + dependencies: + '@babel/core': 7.28.3 + '@babel/helper-plugin-utils': 7.27.1 + + '@babel/plugin-syntax-typescript@7.27.1(@babel/core@7.28.3)': + dependencies: + '@babel/core': 7.28.3 + '@babel/helper-plugin-utils': 7.27.1 + + '@babel/plugin-syntax-unicode-sets-regex@7.18.6(@babel/core@7.28.3)': + dependencies: + '@babel/core': 7.28.3 + '@babel/helper-create-regexp-features-plugin': 7.27.1(@babel/core@7.28.3) + '@babel/helper-plugin-utils': 7.27.1 + + '@babel/plugin-transform-arrow-functions@7.27.1(@babel/core@7.28.3)': + dependencies: + '@babel/core': 7.28.3 + '@babel/helper-plugin-utils': 7.27.1 + + '@babel/plugin-transform-async-generator-functions@7.28.0(@babel/core@7.28.3)': + dependencies: + '@babel/core': 7.28.3 + '@babel/helper-plugin-utils': 7.27.1 + '@babel/helper-remap-async-to-generator': 7.27.1(@babel/core@7.28.3) '@babel/traverse': 7.28.0 transitivePeerDependencies: - supports-color - '@babel/plugin-proposal-private-property-in-object@7.21.0-placeholder-for-preset-env.2(@babel/core@7.28.0)': + '@babel/plugin-transform-async-to-generator@7.27.1(@babel/core@7.28.3)': dependencies: - '@babel/core': 7.28.0 - - '@babel/plugin-syntax-async-generators@7.8.4(@babel/core@7.28.0)': - dependencies: - '@babel/core': 7.28.0 - '@babel/helper-plugin-utils': 7.27.1 - - '@babel/plugin-syntax-bigint@7.8.3(@babel/core@7.28.0)': - dependencies: - '@babel/core': 7.28.0 - '@babel/helper-plugin-utils': 7.27.1 - - '@babel/plugin-syntax-class-properties@7.12.13(@babel/core@7.28.0)': - dependencies: - '@babel/core': 7.28.0 - '@babel/helper-plugin-utils': 7.27.1 - - '@babel/plugin-syntax-class-static-block@7.14.5(@babel/core@7.28.0)': - dependencies: - '@babel/core': 7.28.0 - '@babel/helper-plugin-utils': 7.27.1 - - '@babel/plugin-syntax-dynamic-import@7.8.3(@babel/core@7.28.0)': - dependencies: - '@babel/core': 7.28.0 - '@babel/helper-plugin-utils': 7.27.1 - - '@babel/plugin-syntax-import-assertions@7.27.1(@babel/core@7.28.0)': - dependencies: - '@babel/core': 7.28.0 - '@babel/helper-plugin-utils': 7.27.1 - - '@babel/plugin-syntax-import-attributes@7.27.1(@babel/core@7.28.0)': - dependencies: - '@babel/core': 7.28.0 - '@babel/helper-plugin-utils': 7.27.1 - - '@babel/plugin-syntax-import-meta@7.10.4(@babel/core@7.28.0)': - dependencies: - '@babel/core': 7.28.0 - '@babel/helper-plugin-utils': 7.27.1 - - '@babel/plugin-syntax-json-strings@7.8.3(@babel/core@7.28.0)': - dependencies: - '@babel/core': 7.28.0 - '@babel/helper-plugin-utils': 7.27.1 - - '@babel/plugin-syntax-jsx@7.27.1(@babel/core@7.28.0)': - dependencies: - '@babel/core': 7.28.0 - '@babel/helper-plugin-utils': 7.27.1 - - '@babel/plugin-syntax-logical-assignment-operators@7.10.4(@babel/core@7.28.0)': - dependencies: - '@babel/core': 7.28.0 - '@babel/helper-plugin-utils': 7.27.1 - - '@babel/plugin-syntax-nullish-coalescing-operator@7.8.3(@babel/core@7.28.0)': - dependencies: - '@babel/core': 7.28.0 - '@babel/helper-plugin-utils': 7.27.1 - - '@babel/plugin-syntax-numeric-separator@7.10.4(@babel/core@7.28.0)': - dependencies: - '@babel/core': 7.28.0 - '@babel/helper-plugin-utils': 7.27.1 - - '@babel/plugin-syntax-object-rest-spread@7.8.3(@babel/core@7.28.0)': - dependencies: - '@babel/core': 7.28.0 - '@babel/helper-plugin-utils': 7.27.1 - - '@babel/plugin-syntax-optional-catch-binding@7.8.3(@babel/core@7.28.0)': - dependencies: - '@babel/core': 7.28.0 - '@babel/helper-plugin-utils': 7.27.1 - - '@babel/plugin-syntax-optional-chaining@7.8.3(@babel/core@7.28.0)': - dependencies: - '@babel/core': 7.28.0 - '@babel/helper-plugin-utils': 7.27.1 - - '@babel/plugin-syntax-private-property-in-object@7.14.5(@babel/core@7.28.0)': - dependencies: - '@babel/core': 7.28.0 - '@babel/helper-plugin-utils': 7.27.1 - - '@babel/plugin-syntax-top-level-await@7.14.5(@babel/core@7.28.0)': - dependencies: - '@babel/core': 7.28.0 - '@babel/helper-plugin-utils': 7.27.1 - - '@babel/plugin-syntax-typescript@7.27.1(@babel/core@7.28.0)': - dependencies: - '@babel/core': 7.28.0 - '@babel/helper-plugin-utils': 7.27.1 - - '@babel/plugin-syntax-unicode-sets-regex@7.18.6(@babel/core@7.28.0)': - dependencies: - '@babel/core': 7.28.0 - '@babel/helper-create-regexp-features-plugin': 7.27.1(@babel/core@7.28.0) - '@babel/helper-plugin-utils': 7.27.1 - - '@babel/plugin-transform-arrow-functions@7.27.1(@babel/core@7.28.0)': - dependencies: - '@babel/core': 7.28.0 - '@babel/helper-plugin-utils': 7.27.1 - - '@babel/plugin-transform-async-generator-functions@7.28.0(@babel/core@7.28.0)': - dependencies: - '@babel/core': 7.28.0 - '@babel/helper-plugin-utils': 7.27.1 - '@babel/helper-remap-async-to-generator': 7.27.1(@babel/core@7.28.0) - '@babel/traverse': 7.28.0 - transitivePeerDependencies: - - supports-color - - '@babel/plugin-transform-async-to-generator@7.27.1(@babel/core@7.28.0)': - dependencies: - '@babel/core': 7.28.0 + '@babel/core': 7.28.3 '@babel/helper-module-imports': 7.27.1 '@babel/helper-plugin-utils': 7.27.1 - '@babel/helper-remap-async-to-generator': 7.27.1(@babel/core@7.28.0) + '@babel/helper-remap-async-to-generator': 7.27.1(@babel/core@7.28.3) transitivePeerDependencies: - supports-color - '@babel/plugin-transform-block-scoped-functions@7.27.1(@babel/core@7.28.0)': + '@babel/plugin-transform-block-scoped-functions@7.27.1(@babel/core@7.28.3)': dependencies: - '@babel/core': 7.28.0 + '@babel/core': 7.28.3 '@babel/helper-plugin-utils': 7.27.1 - '@babel/plugin-transform-block-scoping@7.28.0(@babel/core@7.28.0)': + '@babel/plugin-transform-block-scoping@7.28.0(@babel/core@7.28.3)': dependencies: - '@babel/core': 7.28.0 + '@babel/core': 7.28.3 '@babel/helper-plugin-utils': 7.27.1 - '@babel/plugin-transform-class-properties@7.27.1(@babel/core@7.28.0)': + '@babel/plugin-transform-class-properties@7.27.1(@babel/core@7.28.3)': dependencies: - '@babel/core': 7.28.0 - '@babel/helper-create-class-features-plugin': 7.27.1(@babel/core@7.28.0) + '@babel/core': 7.28.3 + '@babel/helper-create-class-features-plugin': 7.27.1(@babel/core@7.28.3) '@babel/helper-plugin-utils': 7.27.1 transitivePeerDependencies: - supports-color - '@babel/plugin-transform-class-static-block@7.27.1(@babel/core@7.28.0)': + '@babel/plugin-transform-class-static-block@7.28.3(@babel/core@7.28.3)': dependencies: - '@babel/core': 7.28.0 - '@babel/helper-create-class-features-plugin': 7.27.1(@babel/core@7.28.0) + '@babel/core': 7.28.3 + '@babel/helper-create-class-features-plugin': 7.28.3(@babel/core@7.28.3) '@babel/helper-plugin-utils': 7.27.1 transitivePeerDependencies: - supports-color - '@babel/plugin-transform-classes@7.28.0(@babel/core@7.28.0)': + '@babel/plugin-transform-classes@7.28.3(@babel/core@7.28.3)': dependencies: - '@babel/core': 7.28.0 + '@babel/core': 7.28.3 '@babel/helper-annotate-as-pure': 7.27.3 '@babel/helper-compilation-targets': 7.27.2 '@babel/helper-globals': 7.28.0 '@babel/helper-plugin-utils': 7.27.1 - '@babel/helper-replace-supers': 7.27.1(@babel/core@7.28.0) - '@babel/traverse': 7.28.0 + '@babel/helper-replace-supers': 7.27.1(@babel/core@7.28.3) + '@babel/traverse': 7.28.3 transitivePeerDependencies: - supports-color - '@babel/plugin-transform-computed-properties@7.27.1(@babel/core@7.28.0)': + '@babel/plugin-transform-computed-properties@7.27.1(@babel/core@7.28.3)': dependencies: - '@babel/core': 7.28.0 + '@babel/core': 7.28.3 '@babel/helper-plugin-utils': 7.27.1 '@babel/template': 7.27.2 - '@babel/plugin-transform-destructuring@7.28.0(@babel/core@7.28.0)': + '@babel/plugin-transform-destructuring@7.28.0(@babel/core@7.28.3)': dependencies: - '@babel/core': 7.28.0 + '@babel/core': 7.28.3 '@babel/helper-plugin-utils': 7.27.1 '@babel/traverse': 7.28.0 transitivePeerDependencies: - supports-color - '@babel/plugin-transform-dotall-regex@7.27.1(@babel/core@7.28.0)': + '@babel/plugin-transform-dotall-regex@7.27.1(@babel/core@7.28.3)': dependencies: - '@babel/core': 7.28.0 - '@babel/helper-create-regexp-features-plugin': 7.27.1(@babel/core@7.28.0) + '@babel/core': 7.28.3 + '@babel/helper-create-regexp-features-plugin': 7.27.1(@babel/core@7.28.3) '@babel/helper-plugin-utils': 7.27.1 - '@babel/plugin-transform-duplicate-keys@7.27.1(@babel/core@7.28.0)': + '@babel/plugin-transform-duplicate-keys@7.27.1(@babel/core@7.28.3)': dependencies: - '@babel/core': 7.28.0 + '@babel/core': 7.28.3 '@babel/helper-plugin-utils': 7.27.1 - '@babel/plugin-transform-duplicate-named-capturing-groups-regex@7.27.1(@babel/core@7.28.0)': + '@babel/plugin-transform-duplicate-named-capturing-groups-regex@7.27.1(@babel/core@7.28.3)': dependencies: - '@babel/core': 7.28.0 - '@babel/helper-create-regexp-features-plugin': 7.27.1(@babel/core@7.28.0) + '@babel/core': 7.28.3 + '@babel/helper-create-regexp-features-plugin': 7.27.1(@babel/core@7.28.3) '@babel/helper-plugin-utils': 7.27.1 - '@babel/plugin-transform-dynamic-import@7.27.1(@babel/core@7.28.0)': + '@babel/plugin-transform-dynamic-import@7.27.1(@babel/core@7.28.3)': dependencies: - '@babel/core': 7.28.0 + '@babel/core': 7.28.3 '@babel/helper-plugin-utils': 7.27.1 - '@babel/plugin-transform-explicit-resource-management@7.28.0(@babel/core@7.28.0)': + '@babel/plugin-transform-explicit-resource-management@7.28.0(@babel/core@7.28.3)': dependencies: - '@babel/core': 7.28.0 + '@babel/core': 7.28.3 '@babel/helper-plugin-utils': 7.27.1 - '@babel/plugin-transform-destructuring': 7.28.0(@babel/core@7.28.0) + '@babel/plugin-transform-destructuring': 7.28.0(@babel/core@7.28.3) transitivePeerDependencies: - supports-color - '@babel/plugin-transform-exponentiation-operator@7.27.1(@babel/core@7.28.0)': + '@babel/plugin-transform-exponentiation-operator@7.27.1(@babel/core@7.28.3)': dependencies: - '@babel/core': 7.28.0 + '@babel/core': 7.28.3 '@babel/helper-plugin-utils': 7.27.1 - '@babel/plugin-transform-export-namespace-from@7.27.1(@babel/core@7.28.0)': + '@babel/plugin-transform-export-namespace-from@7.27.1(@babel/core@7.28.3)': dependencies: - '@babel/core': 7.28.0 + '@babel/core': 7.28.3 '@babel/helper-plugin-utils': 7.27.1 - '@babel/plugin-transform-for-of@7.27.1(@babel/core@7.28.0)': + '@babel/plugin-transform-for-of@7.27.1(@babel/core@7.28.3)': dependencies: - '@babel/core': 7.28.0 + '@babel/core': 7.28.3 '@babel/helper-plugin-utils': 7.27.1 '@babel/helper-skip-transparent-expression-wrappers': 7.27.1 transitivePeerDependencies: - supports-color - '@babel/plugin-transform-function-name@7.27.1(@babel/core@7.28.0)': + '@babel/plugin-transform-function-name@7.27.1(@babel/core@7.28.3)': dependencies: - '@babel/core': 7.28.0 + '@babel/core': 7.28.3 '@babel/helper-compilation-targets': 7.27.2 '@babel/helper-plugin-utils': 7.27.1 '@babel/traverse': 7.28.0 transitivePeerDependencies: - supports-color - '@babel/plugin-transform-json-strings@7.27.1(@babel/core@7.28.0)': + '@babel/plugin-transform-json-strings@7.27.1(@babel/core@7.28.3)': dependencies: - '@babel/core': 7.28.0 + '@babel/core': 7.28.3 '@babel/helper-plugin-utils': 7.27.1 - '@babel/plugin-transform-literals@7.27.1(@babel/core@7.28.0)': + '@babel/plugin-transform-literals@7.27.1(@babel/core@7.28.3)': dependencies: - '@babel/core': 7.28.0 + '@babel/core': 7.28.3 '@babel/helper-plugin-utils': 7.27.1 - '@babel/plugin-transform-logical-assignment-operators@7.27.1(@babel/core@7.28.0)': + '@babel/plugin-transform-logical-assignment-operators@7.27.1(@babel/core@7.28.3)': dependencies: - '@babel/core': 7.28.0 + '@babel/core': 7.28.3 '@babel/helper-plugin-utils': 7.27.1 - '@babel/plugin-transform-member-expression-literals@7.27.1(@babel/core@7.28.0)': + '@babel/plugin-transform-member-expression-literals@7.27.1(@babel/core@7.28.3)': dependencies: - '@babel/core': 7.28.0 + '@babel/core': 7.28.3 '@babel/helper-plugin-utils': 7.27.1 - '@babel/plugin-transform-modules-amd@7.27.1(@babel/core@7.28.0)': + '@babel/plugin-transform-modules-amd@7.27.1(@babel/core@7.28.3)': dependencies: - '@babel/core': 7.28.0 - '@babel/helper-module-transforms': 7.27.3(@babel/core@7.28.0) + '@babel/core': 7.28.3 + '@babel/helper-module-transforms': 7.27.3(@babel/core@7.28.3) '@babel/helper-plugin-utils': 7.27.1 transitivePeerDependencies: - supports-color - '@babel/plugin-transform-modules-commonjs@7.27.1(@babel/core@7.28.0)': + '@babel/plugin-transform-modules-commonjs@7.27.1(@babel/core@7.28.3)': dependencies: - '@babel/core': 7.28.0 - '@babel/helper-module-transforms': 7.27.3(@babel/core@7.28.0) + '@babel/core': 7.28.3 + '@babel/helper-module-transforms': 7.27.3(@babel/core@7.28.3) '@babel/helper-plugin-utils': 7.27.1 transitivePeerDependencies: - supports-color - '@babel/plugin-transform-modules-systemjs@7.27.1(@babel/core@7.28.0)': + '@babel/plugin-transform-modules-systemjs@7.27.1(@babel/core@7.28.3)': dependencies: - '@babel/core': 7.28.0 - '@babel/helper-module-transforms': 7.27.3(@babel/core@7.28.0) + '@babel/core': 7.28.3 + '@babel/helper-module-transforms': 7.27.3(@babel/core@7.28.3) '@babel/helper-plugin-utils': 7.27.1 '@babel/helper-validator-identifier': 7.27.1 '@babel/traverse': 7.28.0 transitivePeerDependencies: - supports-color - '@babel/plugin-transform-modules-umd@7.27.1(@babel/core@7.28.0)': + '@babel/plugin-transform-modules-umd@7.27.1(@babel/core@7.28.3)': dependencies: - '@babel/core': 7.28.0 - '@babel/helper-module-transforms': 7.27.3(@babel/core@7.28.0) + '@babel/core': 7.28.3 + '@babel/helper-module-transforms': 7.27.3(@babel/core@7.28.3) '@babel/helper-plugin-utils': 7.27.1 transitivePeerDependencies: - supports-color - '@babel/plugin-transform-named-capturing-groups-regex@7.27.1(@babel/core@7.28.0)': + '@babel/plugin-transform-named-capturing-groups-regex@7.27.1(@babel/core@7.28.3)': dependencies: - '@babel/core': 7.28.0 - '@babel/helper-create-regexp-features-plugin': 7.27.1(@babel/core@7.28.0) + '@babel/core': 7.28.3 + '@babel/helper-create-regexp-features-plugin': 7.27.1(@babel/core@7.28.3) '@babel/helper-plugin-utils': 7.27.1 - '@babel/plugin-transform-new-target@7.27.1(@babel/core@7.28.0)': + '@babel/plugin-transform-new-target@7.27.1(@babel/core@7.28.3)': dependencies: - '@babel/core': 7.28.0 + '@babel/core': 7.28.3 '@babel/helper-plugin-utils': 7.27.1 - '@babel/plugin-transform-nullish-coalescing-operator@7.27.1(@babel/core@7.28.0)': + '@babel/plugin-transform-nullish-coalescing-operator@7.27.1(@babel/core@7.28.3)': dependencies: - '@babel/core': 7.28.0 + '@babel/core': 7.28.3 '@babel/helper-plugin-utils': 7.27.1 - '@babel/plugin-transform-numeric-separator@7.27.1(@babel/core@7.28.0)': + '@babel/plugin-transform-numeric-separator@7.27.1(@babel/core@7.28.3)': dependencies: - '@babel/core': 7.28.0 + '@babel/core': 7.28.3 '@babel/helper-plugin-utils': 7.27.1 - '@babel/plugin-transform-object-rest-spread@7.28.0(@babel/core@7.28.0)': + '@babel/plugin-transform-object-rest-spread@7.28.0(@babel/core@7.28.3)': dependencies: - '@babel/core': 7.28.0 + '@babel/core': 7.28.3 '@babel/helper-compilation-targets': 7.27.2 '@babel/helper-plugin-utils': 7.27.1 - '@babel/plugin-transform-destructuring': 7.28.0(@babel/core@7.28.0) - '@babel/plugin-transform-parameters': 7.27.7(@babel/core@7.28.0) + '@babel/plugin-transform-destructuring': 7.28.0(@babel/core@7.28.3) + '@babel/plugin-transform-parameters': 7.27.7(@babel/core@7.28.3) '@babel/traverse': 7.28.0 transitivePeerDependencies: - supports-color - '@babel/plugin-transform-object-super@7.27.1(@babel/core@7.28.0)': + '@babel/plugin-transform-object-super@7.27.1(@babel/core@7.28.3)': dependencies: - '@babel/core': 7.28.0 + '@babel/core': 7.28.3 '@babel/helper-plugin-utils': 7.27.1 - '@babel/helper-replace-supers': 7.27.1(@babel/core@7.28.0) + '@babel/helper-replace-supers': 7.27.1(@babel/core@7.28.3) transitivePeerDependencies: - supports-color - '@babel/plugin-transform-optional-catch-binding@7.27.1(@babel/core@7.28.0)': + '@babel/plugin-transform-optional-catch-binding@7.27.1(@babel/core@7.28.3)': dependencies: - '@babel/core': 7.28.0 + '@babel/core': 7.28.3 '@babel/helper-plugin-utils': 7.27.1 - '@babel/plugin-transform-optional-chaining@7.27.1(@babel/core@7.28.0)': + '@babel/plugin-transform-optional-chaining@7.27.1(@babel/core@7.28.3)': dependencies: - '@babel/core': 7.28.0 + '@babel/core': 7.28.3 '@babel/helper-plugin-utils': 7.27.1 '@babel/helper-skip-transparent-expression-wrappers': 7.27.1 transitivePeerDependencies: - supports-color - '@babel/plugin-transform-parameters@7.27.7(@babel/core@7.28.0)': + '@babel/plugin-transform-parameters@7.27.7(@babel/core@7.28.3)': dependencies: - '@babel/core': 7.28.0 + '@babel/core': 7.28.3 '@babel/helper-plugin-utils': 7.27.1 - '@babel/plugin-transform-private-methods@7.27.1(@babel/core@7.28.0)': + '@babel/plugin-transform-private-methods@7.27.1(@babel/core@7.28.3)': dependencies: - '@babel/core': 7.28.0 - '@babel/helper-create-class-features-plugin': 7.27.1(@babel/core@7.28.0) + '@babel/core': 7.28.3 + '@babel/helper-create-class-features-plugin': 7.27.1(@babel/core@7.28.3) '@babel/helper-plugin-utils': 7.27.1 transitivePeerDependencies: - supports-color - '@babel/plugin-transform-private-property-in-object@7.27.1(@babel/core@7.28.0)': + '@babel/plugin-transform-private-property-in-object@7.27.1(@babel/core@7.28.3)': dependencies: - '@babel/core': 7.28.0 + '@babel/core': 7.28.3 '@babel/helper-annotate-as-pure': 7.27.3 - '@babel/helper-create-class-features-plugin': 7.27.1(@babel/core@7.28.0) + '@babel/helper-create-class-features-plugin': 7.27.1(@babel/core@7.28.3) '@babel/helper-plugin-utils': 7.27.1 transitivePeerDependencies: - supports-color - '@babel/plugin-transform-property-literals@7.27.1(@babel/core@7.28.0)': + '@babel/plugin-transform-property-literals@7.27.1(@babel/core@7.28.3)': dependencies: - '@babel/core': 7.28.0 + '@babel/core': 7.28.3 '@babel/helper-plugin-utils': 7.27.1 - '@babel/plugin-transform-react-display-name@7.28.0(@babel/core@7.28.0)': + '@babel/plugin-transform-react-display-name@7.28.0(@babel/core@7.28.3)': dependencies: - '@babel/core': 7.28.0 + '@babel/core': 7.28.3 '@babel/helper-plugin-utils': 7.27.1 - '@babel/plugin-transform-react-jsx-development@7.27.1(@babel/core@7.28.0)': + '@babel/plugin-transform-react-jsx-development@7.27.1(@babel/core@7.28.3)': dependencies: - '@babel/core': 7.28.0 - '@babel/plugin-transform-react-jsx': 7.27.1(@babel/core@7.28.0) + '@babel/core': 7.28.3 + '@babel/plugin-transform-react-jsx': 7.27.1(@babel/core@7.28.3) transitivePeerDependencies: - supports-color - '@babel/plugin-transform-react-jsx@7.27.1(@babel/core@7.28.0)': + '@babel/plugin-transform-react-jsx@7.27.1(@babel/core@7.28.3)': dependencies: - '@babel/core': 7.28.0 + '@babel/core': 7.28.3 '@babel/helper-annotate-as-pure': 7.27.3 '@babel/helper-module-imports': 7.27.1 '@babel/helper-plugin-utils': 7.27.1 - '@babel/plugin-syntax-jsx': 7.27.1(@babel/core@7.28.0) + '@babel/plugin-syntax-jsx': 7.27.1(@babel/core@7.28.3) '@babel/types': 7.28.1 transitivePeerDependencies: - supports-color - '@babel/plugin-transform-react-pure-annotations@7.27.1(@babel/core@7.28.0)': + '@babel/plugin-transform-react-pure-annotations@7.27.1(@babel/core@7.28.3)': dependencies: - '@babel/core': 7.28.0 + '@babel/core': 7.28.3 '@babel/helper-annotate-as-pure': 7.27.3 '@babel/helper-plugin-utils': 7.27.1 - '@babel/plugin-transform-regenerator@7.28.1(@babel/core@7.28.0)': + '@babel/plugin-transform-regenerator@7.28.3(@babel/core@7.28.3)': dependencies: - '@babel/core': 7.28.0 + '@babel/core': 7.28.3 '@babel/helper-plugin-utils': 7.27.1 - '@babel/plugin-transform-regexp-modifiers@7.27.1(@babel/core@7.28.0)': + '@babel/plugin-transform-regexp-modifiers@7.27.1(@babel/core@7.28.3)': dependencies: - '@babel/core': 7.28.0 - '@babel/helper-create-regexp-features-plugin': 7.27.1(@babel/core@7.28.0) + '@babel/core': 7.28.3 + '@babel/helper-create-regexp-features-plugin': 7.27.1(@babel/core@7.28.3) '@babel/helper-plugin-utils': 7.27.1 - '@babel/plugin-transform-reserved-words@7.27.1(@babel/core@7.28.0)': + '@babel/plugin-transform-reserved-words@7.27.1(@babel/core@7.28.3)': dependencies: - '@babel/core': 7.28.0 + '@babel/core': 7.28.3 '@babel/helper-plugin-utils': 7.27.1 - '@babel/plugin-transform-runtime@7.28.0(@babel/core@7.28.0)': + '@babel/plugin-transform-runtime@7.28.0(@babel/core@7.28.3)': dependencies: - '@babel/core': 7.28.0 + '@babel/core': 7.28.3 '@babel/helper-module-imports': 7.27.1 '@babel/helper-plugin-utils': 7.27.1 - babel-plugin-polyfill-corejs2: 0.4.14(@babel/core@7.28.0) - babel-plugin-polyfill-corejs3: 0.13.0(@babel/core@7.28.0) - babel-plugin-polyfill-regenerator: 0.6.5(@babel/core@7.28.0) + babel-plugin-polyfill-corejs2: 0.4.14(@babel/core@7.28.3) + babel-plugin-polyfill-corejs3: 0.13.0(@babel/core@7.28.3) + babel-plugin-polyfill-regenerator: 0.6.5(@babel/core@7.28.3) semver: 6.3.1 transitivePeerDependencies: - supports-color - '@babel/plugin-transform-shorthand-properties@7.27.1(@babel/core@7.28.0)': + '@babel/plugin-transform-shorthand-properties@7.27.1(@babel/core@7.28.3)': dependencies: - '@babel/core': 7.28.0 + '@babel/core': 7.28.3 '@babel/helper-plugin-utils': 7.27.1 - '@babel/plugin-transform-spread@7.27.1(@babel/core@7.28.0)': + '@babel/plugin-transform-spread@7.27.1(@babel/core@7.28.3)': dependencies: - '@babel/core': 7.28.0 + '@babel/core': 7.28.3 '@babel/helper-plugin-utils': 7.27.1 '@babel/helper-skip-transparent-expression-wrappers': 7.27.1 transitivePeerDependencies: - supports-color - '@babel/plugin-transform-sticky-regex@7.27.1(@babel/core@7.28.0)': + '@babel/plugin-transform-sticky-regex@7.27.1(@babel/core@7.28.3)': dependencies: - '@babel/core': 7.28.0 + '@babel/core': 7.28.3 '@babel/helper-plugin-utils': 7.27.1 - '@babel/plugin-transform-template-literals@7.27.1(@babel/core@7.28.0)': + '@babel/plugin-transform-template-literals@7.27.1(@babel/core@7.28.3)': dependencies: - '@babel/core': 7.28.0 + '@babel/core': 7.28.3 '@babel/helper-plugin-utils': 7.27.1 - '@babel/plugin-transform-typeof-symbol@7.27.1(@babel/core@7.28.0)': + '@babel/plugin-transform-typeof-symbol@7.27.1(@babel/core@7.28.3)': dependencies: - '@babel/core': 7.28.0 + '@babel/core': 7.28.3 '@babel/helper-plugin-utils': 7.27.1 - '@babel/plugin-transform-typescript@7.28.0(@babel/core@7.28.0)': + '@babel/plugin-transform-typescript@7.28.0(@babel/core@7.28.3)': dependencies: - '@babel/core': 7.28.0 + '@babel/core': 7.28.3 '@babel/helper-annotate-as-pure': 7.27.3 - '@babel/helper-create-class-features-plugin': 7.27.1(@babel/core@7.28.0) + '@babel/helper-create-class-features-plugin': 7.27.1(@babel/core@7.28.3) '@babel/helper-plugin-utils': 7.27.1 '@babel/helper-skip-transparent-expression-wrappers': 7.27.1 - '@babel/plugin-syntax-typescript': 7.27.1(@babel/core@7.28.0) + '@babel/plugin-syntax-typescript': 7.27.1(@babel/core@7.28.3) transitivePeerDependencies: - supports-color - '@babel/plugin-transform-unicode-escapes@7.27.1(@babel/core@7.28.0)': + '@babel/plugin-transform-unicode-escapes@7.27.1(@babel/core@7.28.3)': dependencies: - '@babel/core': 7.28.0 + '@babel/core': 7.28.3 '@babel/helper-plugin-utils': 7.27.1 - '@babel/plugin-transform-unicode-property-regex@7.27.1(@babel/core@7.28.0)': + '@babel/plugin-transform-unicode-property-regex@7.27.1(@babel/core@7.28.3)': dependencies: - '@babel/core': 7.28.0 - '@babel/helper-create-regexp-features-plugin': 7.27.1(@babel/core@7.28.0) + '@babel/core': 7.28.3 + '@babel/helper-create-regexp-features-plugin': 7.27.1(@babel/core@7.28.3) '@babel/helper-plugin-utils': 7.27.1 - '@babel/plugin-transform-unicode-regex@7.27.1(@babel/core@7.28.0)': + '@babel/plugin-transform-unicode-regex@7.27.1(@babel/core@7.28.3)': dependencies: - '@babel/core': 7.28.0 - '@babel/helper-create-regexp-features-plugin': 7.27.1(@babel/core@7.28.0) + '@babel/core': 7.28.3 + '@babel/helper-create-regexp-features-plugin': 7.27.1(@babel/core@7.28.3) '@babel/helper-plugin-utils': 7.27.1 - '@babel/plugin-transform-unicode-sets-regex@7.27.1(@babel/core@7.28.0)': + '@babel/plugin-transform-unicode-sets-regex@7.27.1(@babel/core@7.28.3)': dependencies: - '@babel/core': 7.28.0 - '@babel/helper-create-regexp-features-plugin': 7.27.1(@babel/core@7.28.0) + '@babel/core': 7.28.3 + '@babel/helper-create-regexp-features-plugin': 7.27.1(@babel/core@7.28.3) '@babel/helper-plugin-utils': 7.27.1 - '@babel/preset-env@7.28.0(@babel/core@7.28.0)': + '@babel/preset-env@7.28.3(@babel/core@7.28.3)': dependencies: '@babel/compat-data': 7.28.0 - '@babel/core': 7.28.0 + '@babel/core': 7.28.3 '@babel/helper-compilation-targets': 7.27.2 '@babel/helper-plugin-utils': 7.27.1 '@babel/helper-validator-option': 7.27.1 - '@babel/plugin-bugfix-firefox-class-in-computed-class-key': 7.27.1(@babel/core@7.28.0) - '@babel/plugin-bugfix-safari-class-field-initializer-scope': 7.27.1(@babel/core@7.28.0) - '@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression': 7.27.1(@babel/core@7.28.0) - '@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining': 7.27.1(@babel/core@7.28.0) - '@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly': 7.27.1(@babel/core@7.28.0) - '@babel/plugin-proposal-private-property-in-object': 7.21.0-placeholder-for-preset-env.2(@babel/core@7.28.0) - '@babel/plugin-syntax-import-assertions': 7.27.1(@babel/core@7.28.0) - '@babel/plugin-syntax-import-attributes': 7.27.1(@babel/core@7.28.0) - '@babel/plugin-syntax-unicode-sets-regex': 7.18.6(@babel/core@7.28.0) - '@babel/plugin-transform-arrow-functions': 7.27.1(@babel/core@7.28.0) - '@babel/plugin-transform-async-generator-functions': 7.28.0(@babel/core@7.28.0) - '@babel/plugin-transform-async-to-generator': 7.27.1(@babel/core@7.28.0) - '@babel/plugin-transform-block-scoped-functions': 7.27.1(@babel/core@7.28.0) - '@babel/plugin-transform-block-scoping': 7.28.0(@babel/core@7.28.0) - '@babel/plugin-transform-class-properties': 7.27.1(@babel/core@7.28.0) - '@babel/plugin-transform-class-static-block': 7.27.1(@babel/core@7.28.0) - '@babel/plugin-transform-classes': 7.28.0(@babel/core@7.28.0) - '@babel/plugin-transform-computed-properties': 7.27.1(@babel/core@7.28.0) - '@babel/plugin-transform-destructuring': 7.28.0(@babel/core@7.28.0) - '@babel/plugin-transform-dotall-regex': 7.27.1(@babel/core@7.28.0) - '@babel/plugin-transform-duplicate-keys': 7.27.1(@babel/core@7.28.0) - '@babel/plugin-transform-duplicate-named-capturing-groups-regex': 7.27.1(@babel/core@7.28.0) - '@babel/plugin-transform-dynamic-import': 7.27.1(@babel/core@7.28.0) - '@babel/plugin-transform-explicit-resource-management': 7.28.0(@babel/core@7.28.0) - '@babel/plugin-transform-exponentiation-operator': 7.27.1(@babel/core@7.28.0) - '@babel/plugin-transform-export-namespace-from': 7.27.1(@babel/core@7.28.0) - '@babel/plugin-transform-for-of': 7.27.1(@babel/core@7.28.0) - '@babel/plugin-transform-function-name': 7.27.1(@babel/core@7.28.0) - '@babel/plugin-transform-json-strings': 7.27.1(@babel/core@7.28.0) - '@babel/plugin-transform-literals': 7.27.1(@babel/core@7.28.0) - '@babel/plugin-transform-logical-assignment-operators': 7.27.1(@babel/core@7.28.0) - '@babel/plugin-transform-member-expression-literals': 7.27.1(@babel/core@7.28.0) - '@babel/plugin-transform-modules-amd': 7.27.1(@babel/core@7.28.0) - '@babel/plugin-transform-modules-commonjs': 7.27.1(@babel/core@7.28.0) - '@babel/plugin-transform-modules-systemjs': 7.27.1(@babel/core@7.28.0) - '@babel/plugin-transform-modules-umd': 7.27.1(@babel/core@7.28.0) - '@babel/plugin-transform-named-capturing-groups-regex': 7.27.1(@babel/core@7.28.0) - '@babel/plugin-transform-new-target': 7.27.1(@babel/core@7.28.0) - '@babel/plugin-transform-nullish-coalescing-operator': 7.27.1(@babel/core@7.28.0) - '@babel/plugin-transform-numeric-separator': 7.27.1(@babel/core@7.28.0) - '@babel/plugin-transform-object-rest-spread': 7.28.0(@babel/core@7.28.0) - '@babel/plugin-transform-object-super': 7.27.1(@babel/core@7.28.0) - '@babel/plugin-transform-optional-catch-binding': 7.27.1(@babel/core@7.28.0) - '@babel/plugin-transform-optional-chaining': 7.27.1(@babel/core@7.28.0) - '@babel/plugin-transform-parameters': 7.27.7(@babel/core@7.28.0) - '@babel/plugin-transform-private-methods': 7.27.1(@babel/core@7.28.0) - '@babel/plugin-transform-private-property-in-object': 7.27.1(@babel/core@7.28.0) - '@babel/plugin-transform-property-literals': 7.27.1(@babel/core@7.28.0) - '@babel/plugin-transform-regenerator': 7.28.1(@babel/core@7.28.0) - '@babel/plugin-transform-regexp-modifiers': 7.27.1(@babel/core@7.28.0) - '@babel/plugin-transform-reserved-words': 7.27.1(@babel/core@7.28.0) - '@babel/plugin-transform-shorthand-properties': 7.27.1(@babel/core@7.28.0) - '@babel/plugin-transform-spread': 7.27.1(@babel/core@7.28.0) - '@babel/plugin-transform-sticky-regex': 7.27.1(@babel/core@7.28.0) - '@babel/plugin-transform-template-literals': 7.27.1(@babel/core@7.28.0) - '@babel/plugin-transform-typeof-symbol': 7.27.1(@babel/core@7.28.0) - '@babel/plugin-transform-unicode-escapes': 7.27.1(@babel/core@7.28.0) - '@babel/plugin-transform-unicode-property-regex': 7.27.1(@babel/core@7.28.0) - '@babel/plugin-transform-unicode-regex': 7.27.1(@babel/core@7.28.0) - '@babel/plugin-transform-unicode-sets-regex': 7.27.1(@babel/core@7.28.0) - '@babel/preset-modules': 0.1.6-no-external-plugins(@babel/core@7.28.0) - babel-plugin-polyfill-corejs2: 0.4.14(@babel/core@7.28.0) - babel-plugin-polyfill-corejs3: 0.13.0(@babel/core@7.28.0) - babel-plugin-polyfill-regenerator: 0.6.5(@babel/core@7.28.0) + '@babel/plugin-bugfix-firefox-class-in-computed-class-key': 7.27.1(@babel/core@7.28.3) + '@babel/plugin-bugfix-safari-class-field-initializer-scope': 7.27.1(@babel/core@7.28.3) + '@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression': 7.27.1(@babel/core@7.28.3) + '@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining': 7.27.1(@babel/core@7.28.3) + '@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly': 7.28.3(@babel/core@7.28.3) + '@babel/plugin-proposal-private-property-in-object': 7.21.0-placeholder-for-preset-env.2(@babel/core@7.28.3) + '@babel/plugin-syntax-import-assertions': 7.27.1(@babel/core@7.28.3) + '@babel/plugin-syntax-import-attributes': 7.27.1(@babel/core@7.28.3) + '@babel/plugin-syntax-unicode-sets-regex': 7.18.6(@babel/core@7.28.3) + '@babel/plugin-transform-arrow-functions': 7.27.1(@babel/core@7.28.3) + '@babel/plugin-transform-async-generator-functions': 7.28.0(@babel/core@7.28.3) + '@babel/plugin-transform-async-to-generator': 7.27.1(@babel/core@7.28.3) + '@babel/plugin-transform-block-scoped-functions': 7.27.1(@babel/core@7.28.3) + '@babel/plugin-transform-block-scoping': 7.28.0(@babel/core@7.28.3) + '@babel/plugin-transform-class-properties': 7.27.1(@babel/core@7.28.3) + '@babel/plugin-transform-class-static-block': 7.28.3(@babel/core@7.28.3) + '@babel/plugin-transform-classes': 7.28.3(@babel/core@7.28.3) + '@babel/plugin-transform-computed-properties': 7.27.1(@babel/core@7.28.3) + '@babel/plugin-transform-destructuring': 7.28.0(@babel/core@7.28.3) + '@babel/plugin-transform-dotall-regex': 7.27.1(@babel/core@7.28.3) + '@babel/plugin-transform-duplicate-keys': 7.27.1(@babel/core@7.28.3) + '@babel/plugin-transform-duplicate-named-capturing-groups-regex': 7.27.1(@babel/core@7.28.3) + '@babel/plugin-transform-dynamic-import': 7.27.1(@babel/core@7.28.3) + '@babel/plugin-transform-explicit-resource-management': 7.28.0(@babel/core@7.28.3) + '@babel/plugin-transform-exponentiation-operator': 7.27.1(@babel/core@7.28.3) + '@babel/plugin-transform-export-namespace-from': 7.27.1(@babel/core@7.28.3) + '@babel/plugin-transform-for-of': 7.27.1(@babel/core@7.28.3) + '@babel/plugin-transform-function-name': 7.27.1(@babel/core@7.28.3) + '@babel/plugin-transform-json-strings': 7.27.1(@babel/core@7.28.3) + '@babel/plugin-transform-literals': 7.27.1(@babel/core@7.28.3) + '@babel/plugin-transform-logical-assignment-operators': 7.27.1(@babel/core@7.28.3) + '@babel/plugin-transform-member-expression-literals': 7.27.1(@babel/core@7.28.3) + '@babel/plugin-transform-modules-amd': 7.27.1(@babel/core@7.28.3) + '@babel/plugin-transform-modules-commonjs': 7.27.1(@babel/core@7.28.3) + '@babel/plugin-transform-modules-systemjs': 7.27.1(@babel/core@7.28.3) + '@babel/plugin-transform-modules-umd': 7.27.1(@babel/core@7.28.3) + '@babel/plugin-transform-named-capturing-groups-regex': 7.27.1(@babel/core@7.28.3) + '@babel/plugin-transform-new-target': 7.27.1(@babel/core@7.28.3) + '@babel/plugin-transform-nullish-coalescing-operator': 7.27.1(@babel/core@7.28.3) + '@babel/plugin-transform-numeric-separator': 7.27.1(@babel/core@7.28.3) + '@babel/plugin-transform-object-rest-spread': 7.28.0(@babel/core@7.28.3) + '@babel/plugin-transform-object-super': 7.27.1(@babel/core@7.28.3) + '@babel/plugin-transform-optional-catch-binding': 7.27.1(@babel/core@7.28.3) + '@babel/plugin-transform-optional-chaining': 7.27.1(@babel/core@7.28.3) + '@babel/plugin-transform-parameters': 7.27.7(@babel/core@7.28.3) + '@babel/plugin-transform-private-methods': 7.27.1(@babel/core@7.28.3) + '@babel/plugin-transform-private-property-in-object': 7.27.1(@babel/core@7.28.3) + '@babel/plugin-transform-property-literals': 7.27.1(@babel/core@7.28.3) + '@babel/plugin-transform-regenerator': 7.28.3(@babel/core@7.28.3) + '@babel/plugin-transform-regexp-modifiers': 7.27.1(@babel/core@7.28.3) + '@babel/plugin-transform-reserved-words': 7.27.1(@babel/core@7.28.3) + '@babel/plugin-transform-shorthand-properties': 7.27.1(@babel/core@7.28.3) + '@babel/plugin-transform-spread': 7.27.1(@babel/core@7.28.3) + '@babel/plugin-transform-sticky-regex': 7.27.1(@babel/core@7.28.3) + '@babel/plugin-transform-template-literals': 7.27.1(@babel/core@7.28.3) + '@babel/plugin-transform-typeof-symbol': 7.27.1(@babel/core@7.28.3) + '@babel/plugin-transform-unicode-escapes': 7.27.1(@babel/core@7.28.3) + '@babel/plugin-transform-unicode-property-regex': 7.27.1(@babel/core@7.28.3) + '@babel/plugin-transform-unicode-regex': 7.27.1(@babel/core@7.28.3) + '@babel/plugin-transform-unicode-sets-regex': 7.27.1(@babel/core@7.28.3) + '@babel/preset-modules': 0.1.6-no-external-plugins(@babel/core@7.28.3) + babel-plugin-polyfill-corejs2: 0.4.14(@babel/core@7.28.3) + babel-plugin-polyfill-corejs3: 0.13.0(@babel/core@7.28.3) + babel-plugin-polyfill-regenerator: 0.6.5(@babel/core@7.28.3) core-js-compat: 3.44.0 semver: 6.3.1 transitivePeerDependencies: - supports-color - '@babel/preset-modules@0.1.6-no-external-plugins(@babel/core@7.28.0)': + '@babel/preset-modules@0.1.6-no-external-plugins(@babel/core@7.28.3)': dependencies: - '@babel/core': 7.28.0 + '@babel/core': 7.28.3 '@babel/helper-plugin-utils': 7.27.1 '@babel/types': 7.28.1 esutils: 2.0.3 - '@babel/preset-react@7.27.1(@babel/core@7.28.0)': + '@babel/preset-react@7.27.1(@babel/core@7.28.3)': dependencies: - '@babel/core': 7.28.0 + '@babel/core': 7.28.3 '@babel/helper-plugin-utils': 7.27.1 '@babel/helper-validator-option': 7.27.1 - '@babel/plugin-transform-react-display-name': 7.28.0(@babel/core@7.28.0) - '@babel/plugin-transform-react-jsx': 7.27.1(@babel/core@7.28.0) - '@babel/plugin-transform-react-jsx-development': 7.27.1(@babel/core@7.28.0) - '@babel/plugin-transform-react-pure-annotations': 7.27.1(@babel/core@7.28.0) + '@babel/plugin-transform-react-display-name': 7.28.0(@babel/core@7.28.3) + '@babel/plugin-transform-react-jsx': 7.27.1(@babel/core@7.28.3) + '@babel/plugin-transform-react-jsx-development': 7.27.1(@babel/core@7.28.3) + '@babel/plugin-transform-react-pure-annotations': 7.27.1(@babel/core@7.28.3) transitivePeerDependencies: - supports-color - '@babel/preset-typescript@7.27.1(@babel/core@7.28.0)': + '@babel/preset-typescript@7.27.1(@babel/core@7.28.3)': dependencies: - '@babel/core': 7.28.0 + '@babel/core': 7.28.3 '@babel/helper-plugin-utils': 7.27.1 '@babel/helper-validator-option': 7.27.1 - '@babel/plugin-syntax-jsx': 7.27.1(@babel/core@7.28.0) - '@babel/plugin-transform-modules-commonjs': 7.27.1(@babel/core@7.28.0) - '@babel/plugin-transform-typescript': 7.28.0(@babel/core@7.28.0) + '@babel/plugin-syntax-jsx': 7.27.1(@babel/core@7.28.3) + '@babel/plugin-transform-modules-commonjs': 7.27.1(@babel/core@7.28.3) + '@babel/plugin-transform-typescript': 7.28.0(@babel/core@7.28.3) transitivePeerDependencies: - supports-color @@ -9406,8 +9784,8 @@ snapshots: '@babel/template@7.27.2': dependencies: '@babel/code-frame': 7.27.1 - '@babel/parser': 7.28.0 - '@babel/types': 7.28.1 + '@babel/parser': 7.28.3 + '@babel/types': 7.28.2 '@babel/traverse@7.28.0': dependencies: @@ -9421,11 +9799,28 @@ snapshots: transitivePeerDependencies: - supports-color + '@babel/traverse@7.28.3': + dependencies: + '@babel/code-frame': 7.27.1 + '@babel/generator': 7.28.3 + '@babel/helper-globals': 7.28.0 + '@babel/parser': 7.28.3 + '@babel/template': 7.27.2 + '@babel/types': 7.28.2 + debug: 4.4.1 + transitivePeerDependencies: + - supports-color + '@babel/types@7.28.1': dependencies: '@babel/helper-string-parser': 7.27.1 '@babel/helper-validator-identifier': 7.27.1 + '@babel/types@7.28.2': + dependencies: + '@babel/helper-string-parser': 7.27.1 + '@babel/helper-validator-identifier': 7.27.1 + '@bcoe/v8-coverage@0.2.3': {} '@braintree/sanitize-url@7.1.1': {} @@ -10157,7 +10552,7 @@ snapshots: '@jest/transform@29.7.0': dependencies: - '@babel/core': 7.28.0 + '@babel/core': 7.28.3 '@jest/types': 29.6.3 '@jridgewell/trace-mapping': 0.3.29 babel-plugin-istanbul: 6.1.1 @@ -11017,6 +11412,40 @@ snapshots: '@rgrove/parse-xml@4.2.0': {} + '@rollup/plugin-babel@5.3.1(@babel/core@7.28.3)(@types/babel__core@7.20.5)(rollup@2.79.2)': + dependencies: + '@babel/core': 7.28.3 + '@babel/helper-module-imports': 7.27.1 + '@rollup/pluginutils': 3.1.0(rollup@2.79.2) + rollup: 2.79.2 + optionalDependencies: + '@types/babel__core': 7.20.5 + transitivePeerDependencies: + - supports-color + + '@rollup/plugin-node-resolve@11.2.1(rollup@2.79.2)': + dependencies: + '@rollup/pluginutils': 3.1.0(rollup@2.79.2) + '@types/resolve': 1.17.1 + builtin-modules: 3.3.0 + deepmerge: 4.3.1 + is-module: 1.0.0 + resolve: 1.22.10 + rollup: 2.79.2 + + '@rollup/plugin-replace@2.4.2(rollup@2.79.2)': + dependencies: + '@rollup/pluginutils': 3.1.0(rollup@2.79.2) + magic-string: 0.25.9 + rollup: 2.79.2 + + '@rollup/pluginutils@3.1.0(rollup@2.79.2)': + dependencies: + '@types/estree': 0.0.39 + estree-walker: 1.0.1 + picomatch: 2.3.1 + rollup: 2.79.2 + '@rtsao/scc@1.1.0': {} '@rushstack/eslint-patch@1.12.0': {} @@ -11291,20 +11720,20 @@ snapshots: dependencies: storybook: 8.5.0 - '@storybook/nextjs@8.5.0(esbuild@0.25.0)(next@15.5.0(@babel/core@7.28.0)(react-dom@19.1.1(react@19.1.1))(react@19.1.1)(sass@1.89.2))(react-dom@19.1.1(react@19.1.1))(react@19.1.1)(sass@1.89.2)(storybook@8.5.0)(type-fest@2.19.0)(typescript@5.8.3)(uglify-js@3.19.3)(webpack-hot-middleware@2.26.1)(webpack@5.100.2(esbuild@0.25.0)(uglify-js@3.19.3))': + '@storybook/nextjs@8.5.0(esbuild@0.25.0)(next@15.5.0(@babel/core@7.28.3)(react-dom@19.1.1(react@19.1.1))(react@19.1.1)(sass@1.89.2))(react-dom@19.1.1(react@19.1.1))(react@19.1.1)(sass@1.89.2)(storybook@8.5.0)(type-fest@2.19.0)(typescript@5.8.3)(uglify-js@3.19.3)(webpack-hot-middleware@2.26.1)(webpack@5.100.2(esbuild@0.25.0)(uglify-js@3.19.3))': dependencies: - '@babel/core': 7.28.0 - '@babel/plugin-syntax-bigint': 7.8.3(@babel/core@7.28.0) - '@babel/plugin-syntax-dynamic-import': 7.8.3(@babel/core@7.28.0) - '@babel/plugin-syntax-import-assertions': 7.27.1(@babel/core@7.28.0) - '@babel/plugin-transform-class-properties': 7.27.1(@babel/core@7.28.0) - '@babel/plugin-transform-export-namespace-from': 7.27.1(@babel/core@7.28.0) - '@babel/plugin-transform-numeric-separator': 7.27.1(@babel/core@7.28.0) - '@babel/plugin-transform-object-rest-spread': 7.28.0(@babel/core@7.28.0) - '@babel/plugin-transform-runtime': 7.28.0(@babel/core@7.28.0) - '@babel/preset-env': 7.28.0(@babel/core@7.28.0) - '@babel/preset-react': 7.27.1(@babel/core@7.28.0) - '@babel/preset-typescript': 7.27.1(@babel/core@7.28.0) + '@babel/core': 7.28.3 + '@babel/plugin-syntax-bigint': 7.8.3(@babel/core@7.28.3) + '@babel/plugin-syntax-dynamic-import': 7.8.3(@babel/core@7.28.3) + '@babel/plugin-syntax-import-assertions': 7.27.1(@babel/core@7.28.3) + '@babel/plugin-transform-class-properties': 7.27.1(@babel/core@7.28.3) + '@babel/plugin-transform-export-namespace-from': 7.27.1(@babel/core@7.28.3) + '@babel/plugin-transform-numeric-separator': 7.27.1(@babel/core@7.28.3) + '@babel/plugin-transform-object-rest-spread': 7.28.0(@babel/core@7.28.3) + '@babel/plugin-transform-runtime': 7.28.0(@babel/core@7.28.3) + '@babel/preset-env': 7.28.3(@babel/core@7.28.3) + '@babel/preset-react': 7.27.1(@babel/core@7.28.3) + '@babel/preset-typescript': 7.27.1(@babel/core@7.28.3) '@babel/runtime': 7.27.6 '@pmmmwh/react-refresh-webpack-plugin': 0.5.17(react-refresh@0.14.2)(type-fest@2.19.0)(webpack-hot-middleware@2.26.1)(webpack@5.100.2(esbuild@0.25.0)(uglify-js@3.19.3)) '@storybook/builder-webpack5': 8.5.0(esbuild@0.25.0)(storybook@8.5.0)(typescript@5.8.3)(uglify-js@3.19.3) @@ -11312,12 +11741,12 @@ snapshots: '@storybook/react': 8.5.0(@storybook/test@8.5.0(storybook@8.5.0))(react-dom@19.1.1(react@19.1.1))(react@19.1.1)(storybook@8.5.0)(typescript@5.8.3) '@storybook/test': 8.5.0(storybook@8.5.0) '@types/semver': 7.7.0 - babel-loader: 9.2.1(@babel/core@7.28.0)(webpack@5.100.2(esbuild@0.25.0)(uglify-js@3.19.3)) + babel-loader: 9.2.1(@babel/core@7.28.3)(webpack@5.100.2(esbuild@0.25.0)(uglify-js@3.19.3)) css-loader: 6.11.0(webpack@5.100.2(esbuild@0.25.0)(uglify-js@3.19.3)) find-up: 5.0.0 image-size: 1.2.1 loader-utils: 3.3.1 - next: 15.5.0(@babel/core@7.28.0)(react-dom@19.1.1(react@19.1.1))(react@19.1.1)(sass@1.89.2) + next: 15.5.0(@babel/core@7.28.3)(react-dom@19.1.1(react@19.1.1))(react@19.1.1)(sass@1.89.2) node-polyfill-webpack-plugin: 2.0.1(webpack@5.100.2(esbuild@0.25.0)(uglify-js@3.19.3)) pnp-webpack-plugin: 1.7.0(typescript@5.8.3) postcss: 8.5.6 @@ -11330,7 +11759,7 @@ snapshots: semver: 7.7.2 storybook: 8.5.0 style-loader: 3.3.4(webpack@5.100.2(esbuild@0.25.0)(uglify-js@3.19.3)) - styled-jsx: 5.1.7(@babel/core@7.28.0)(react@19.1.1) + styled-jsx: 5.1.7(@babel/core@7.28.3)(react@19.1.1) ts-dedent: 2.2.0 tsconfig-paths: 4.2.0 tsconfig-paths-webpack-plugin: 4.2.0 @@ -11453,6 +11882,13 @@ snapshots: estraverse: 5.3.0 picomatch: 4.0.3 + '@surma/rollup-plugin-off-main-thread@2.2.3': + dependencies: + ejs: 3.1.10 + json5: 2.2.3 + magic-string: 0.25.9 + string.prototype.matchall: '@nolyfill/string.prototype.matchall@1.0.44' + '@svgdotjs/svg.js@3.2.4': {} '@swc/helpers@0.5.15': @@ -11750,10 +12186,17 @@ snapshots: dependencies: '@types/estree': 1.0.8 + '@types/estree@0.0.39': {} + '@types/estree@1.0.8': {} '@types/geojson@7946.0.16': {} + '@types/glob@7.2.0': + dependencies: + '@types/minimatch': 6.0.0 + '@types/node': 18.15.0 + '@types/graceful-fs@4.1.9': dependencies: '@types/node': 18.15.0 @@ -11809,6 +12252,10 @@ snapshots: '@types/mdx@2.0.13': {} + '@types/minimatch@6.0.0': + dependencies: + minimatch: 9.0.5 + '@types/ms@2.1.0': {} '@types/negotiator@0.6.4': {} @@ -11850,6 +12297,10 @@ snapshots: '@types/recordrtc@5.6.14': {} + '@types/resolve@1.17.1': + dependencies: + '@types/node': 18.15.0 + '@types/resolve@1.20.6': {} '@types/responselike@1.0.3': @@ -11862,8 +12313,7 @@ snapshots: '@types/stack-utils@2.0.3': {} - '@types/trusted-types@2.0.7': - optional: true + '@types/trusted-types@2.0.7': {} '@types/unist@2.0.11': {} @@ -12390,6 +12840,14 @@ snapshots: aria-query@5.3.2: {} + array-union@1.0.2: + dependencies: + array-uniq: 1.0.3 + + array-union@2.1.0: {} + + array-uniq@1.0.3: {} + asn1.js@4.10.1: dependencies: bn.js: 4.12.2 @@ -12408,6 +12866,8 @@ snapshots: async@3.2.6: {} + at-least-node@1.0.0: {} + autoprefixer@10.4.21(postcss@8.5.6): dependencies: browserslist: 4.25.1 @@ -12422,22 +12882,37 @@ snapshots: axobject-query@4.1.0: {} - babel-jest@29.7.0(@babel/core@7.28.0): + babel-jest@29.7.0(@babel/core@7.28.3): dependencies: - '@babel/core': 7.28.0 + '@babel/core': 7.28.3 '@jest/transform': 29.7.0 '@types/babel__core': 7.20.5 babel-plugin-istanbul: 6.1.1 - babel-preset-jest: 29.6.3(@babel/core@7.28.0) + babel-preset-jest: 29.6.3(@babel/core@7.28.3) chalk: 4.1.2 graceful-fs: 4.2.11 slash: 3.0.0 transitivePeerDependencies: - supports-color - babel-loader@9.2.1(@babel/core@7.28.0)(webpack@5.100.2(esbuild@0.25.0)(uglify-js@3.19.3)): + babel-loader@10.0.0(@babel/core@7.28.3)(webpack@5.100.2(esbuild@0.25.0)(uglify-js@3.19.3)): dependencies: - '@babel/core': 7.28.0 + '@babel/core': 7.28.3 + find-up: 5.0.0 + webpack: 5.100.2(esbuild@0.25.0)(uglify-js@3.19.3) + + babel-loader@8.4.1(@babel/core@7.28.3)(webpack@5.100.2(esbuild@0.25.0)(uglify-js@3.19.3)): + dependencies: + '@babel/core': 7.28.3 + find-cache-dir: 3.3.2 + loader-utils: 2.0.4 + make-dir: 3.1.0 + schema-utils: 2.7.1 + webpack: 5.100.2(esbuild@0.25.0)(uglify-js@3.19.3) + + babel-loader@9.2.1(@babel/core@7.28.3)(webpack@5.100.2(esbuild@0.25.0)(uglify-js@3.19.3)): + dependencies: + '@babel/core': 7.28.3 find-cache-dir: 4.0.0 schema-utils: 4.3.2 webpack: 5.100.2(esbuild@0.25.0)(uglify-js@3.19.3) @@ -12459,54 +12934,54 @@ snapshots: '@types/babel__core': 7.20.5 '@types/babel__traverse': 7.20.7 - babel-plugin-polyfill-corejs2@0.4.14(@babel/core@7.28.0): + babel-plugin-polyfill-corejs2@0.4.14(@babel/core@7.28.3): dependencies: '@babel/compat-data': 7.28.0 - '@babel/core': 7.28.0 - '@babel/helper-define-polyfill-provider': 0.6.5(@babel/core@7.28.0) + '@babel/core': 7.28.3 + '@babel/helper-define-polyfill-provider': 0.6.5(@babel/core@7.28.3) semver: 6.3.1 transitivePeerDependencies: - supports-color - babel-plugin-polyfill-corejs3@0.13.0(@babel/core@7.28.0): + babel-plugin-polyfill-corejs3@0.13.0(@babel/core@7.28.3): dependencies: - '@babel/core': 7.28.0 - '@babel/helper-define-polyfill-provider': 0.6.5(@babel/core@7.28.0) + '@babel/core': 7.28.3 + '@babel/helper-define-polyfill-provider': 0.6.5(@babel/core@7.28.3) core-js-compat: 3.44.0 transitivePeerDependencies: - supports-color - babel-plugin-polyfill-regenerator@0.6.5(@babel/core@7.28.0): + babel-plugin-polyfill-regenerator@0.6.5(@babel/core@7.28.3): dependencies: - '@babel/core': 7.28.0 - '@babel/helper-define-polyfill-provider': 0.6.5(@babel/core@7.28.0) + '@babel/core': 7.28.3 + '@babel/helper-define-polyfill-provider': 0.6.5(@babel/core@7.28.3) transitivePeerDependencies: - supports-color - babel-preset-current-node-syntax@1.1.0(@babel/core@7.28.0): + babel-preset-current-node-syntax@1.1.0(@babel/core@7.28.3): dependencies: - '@babel/core': 7.28.0 - '@babel/plugin-syntax-async-generators': 7.8.4(@babel/core@7.28.0) - '@babel/plugin-syntax-bigint': 7.8.3(@babel/core@7.28.0) - '@babel/plugin-syntax-class-properties': 7.12.13(@babel/core@7.28.0) - '@babel/plugin-syntax-class-static-block': 7.14.5(@babel/core@7.28.0) - '@babel/plugin-syntax-import-attributes': 7.27.1(@babel/core@7.28.0) - '@babel/plugin-syntax-import-meta': 7.10.4(@babel/core@7.28.0) - '@babel/plugin-syntax-json-strings': 7.8.3(@babel/core@7.28.0) - '@babel/plugin-syntax-logical-assignment-operators': 7.10.4(@babel/core@7.28.0) - '@babel/plugin-syntax-nullish-coalescing-operator': 7.8.3(@babel/core@7.28.0) - '@babel/plugin-syntax-numeric-separator': 7.10.4(@babel/core@7.28.0) - '@babel/plugin-syntax-object-rest-spread': 7.8.3(@babel/core@7.28.0) - '@babel/plugin-syntax-optional-catch-binding': 7.8.3(@babel/core@7.28.0) - '@babel/plugin-syntax-optional-chaining': 7.8.3(@babel/core@7.28.0) - '@babel/plugin-syntax-private-property-in-object': 7.14.5(@babel/core@7.28.0) - '@babel/plugin-syntax-top-level-await': 7.14.5(@babel/core@7.28.0) + '@babel/core': 7.28.3 + '@babel/plugin-syntax-async-generators': 7.8.4(@babel/core@7.28.3) + '@babel/plugin-syntax-bigint': 7.8.3(@babel/core@7.28.3) + '@babel/plugin-syntax-class-properties': 7.12.13(@babel/core@7.28.3) + '@babel/plugin-syntax-class-static-block': 7.14.5(@babel/core@7.28.3) + '@babel/plugin-syntax-import-attributes': 7.27.1(@babel/core@7.28.3) + '@babel/plugin-syntax-import-meta': 7.10.4(@babel/core@7.28.3) + '@babel/plugin-syntax-json-strings': 7.8.3(@babel/core@7.28.3) + '@babel/plugin-syntax-logical-assignment-operators': 7.10.4(@babel/core@7.28.3) + '@babel/plugin-syntax-nullish-coalescing-operator': 7.8.3(@babel/core@7.28.3) + '@babel/plugin-syntax-numeric-separator': 7.10.4(@babel/core@7.28.3) + '@babel/plugin-syntax-object-rest-spread': 7.8.3(@babel/core@7.28.3) + '@babel/plugin-syntax-optional-catch-binding': 7.8.3(@babel/core@7.28.3) + '@babel/plugin-syntax-optional-chaining': 7.8.3(@babel/core@7.28.3) + '@babel/plugin-syntax-private-property-in-object': 7.14.5(@babel/core@7.28.3) + '@babel/plugin-syntax-top-level-await': 7.14.5(@babel/core@7.28.3) - babel-preset-jest@29.6.3(@babel/core@7.28.0): + babel-preset-jest@29.6.3(@babel/core@7.28.3): dependencies: - '@babel/core': 7.28.0 + '@babel/core': 7.28.3 babel-plugin-jest-hoist: 29.6.3 - babel-preset-current-node-syntax: 1.1.0(@babel/core@7.28.0) + babel-preset-current-node-syntax: 1.1.0(@babel/core@7.28.3) bail@2.0.2: {} @@ -12775,6 +13250,11 @@ snapshots: dependencies: escape-string-regexp: 1.0.5 + clean-webpack-plugin@4.0.0(webpack@5.100.2(esbuild@0.25.0)(uglify-js@3.19.3)): + dependencies: + del: 4.1.1 + webpack: 5.100.2(esbuild@0.25.0)(uglify-js@3.19.3) + cli-cursor@5.0.0: dependencies: restore-cursor: 5.1.0 @@ -12878,6 +13358,8 @@ snapshots: common-path-prefix@3.0.0: {} + common-tags@1.8.2: {} + commondir@1.0.1: {} compare-versions@6.1.1: {} @@ -13007,6 +13489,8 @@ snapshots: crypto-js@4.2.0: {} + crypto-random-string@2.0.0: {} + css-loader@6.11.0(webpack@5.100.2(esbuild@0.25.0)(uglify-js@3.19.3)): dependencies: icss-utils: 5.1.0(postcss@8.5.6) @@ -13265,6 +13749,16 @@ snapshots: define-lazy-prop@2.0.0: {} + del@4.1.1: + dependencies: + '@types/glob': 7.2.0 + globby: 6.1.0 + is-path-cwd: 2.2.0 + is-path-in-cwd: 2.1.0 + p-map: 2.1.0 + pify: 4.0.1 + rimraf: 2.7.1 + delaunator@5.0.1: dependencies: robust-predicates: 3.0.2 @@ -13306,6 +13800,10 @@ snapshots: miller-rabin: 4.0.1 randombytes: 2.1.0 + dir-glob@3.0.1: + dependencies: + path-type: 4.0.0 + dlv@1.1.3: {} doctrine@2.1.0: @@ -13369,6 +13867,10 @@ snapshots: tslib: 2.3.0 zrender: 5.6.1 + ejs@3.1.10: + dependencies: + jake: 10.9.4 + electron-to-chromium@1.5.186: {} elkjs@0.9.3: {} @@ -14090,6 +14592,8 @@ snapshots: '@types/estree-jsx': 1.0.5 '@types/unist': 3.0.3 + estree-walker@1.0.1: {} + estree-walker@2.0.2: {} estree-walker@3.0.3: @@ -14199,6 +14703,10 @@ snapshots: dependencies: flat-cache: 4.0.1 + filelist@1.0.4: + dependencies: + minimatch: 5.1.6 + filesize@10.1.6: {} fill-range@7.1.1: @@ -14280,6 +14788,13 @@ snapshots: jsonfile: 6.1.0 universalify: 2.0.1 + fs-extra@9.1.0: + dependencies: + at-least-node: 1.0.0 + graceful-fs: 4.2.11 + jsonfile: 6.1.0 + universalify: 2.0.1 + fs-minipass@2.1.0: dependencies: minipass: 3.3.6 @@ -14315,6 +14830,8 @@ snapshots: get-nonce@1.0.1: {} + get-own-enumerable-property-symbols@3.0.2: {} + get-package-type@0.1.0: {} get-stream@5.2.0: @@ -14365,6 +14882,23 @@ snapshots: globals@16.3.0: {} + globby@11.1.0: + dependencies: + array-union: 2.1.0 + dir-glob: 3.0.1 + fast-glob: 3.3.3 + ignore: 5.3.2 + merge2: 1.4.1 + slash: 3.0.0 + + globby@6.1.0: + dependencies: + array-union: 1.0.2 + glob: 7.2.3 + object-assign: 4.1.1 + pify: 2.3.0 + pinkie-promise: 2.0.1 + got@11.8.6: dependencies: '@sindresorhus/is': 4.6.0 @@ -14646,6 +15180,8 @@ snapshots: dependencies: postcss: 8.5.6 + idb@7.1.1: {} + ieee754@1.2.1: {} ignore@5.3.2: {} @@ -14757,12 +15293,28 @@ snapshots: transitivePeerDependencies: - supports-color + is-module@1.0.0: {} + is-number@7.0.0: {} + is-obj@1.0.1: {} + + is-path-cwd@2.2.0: {} + + is-path-in-cwd@2.1.0: + dependencies: + is-path-inside: 2.1.0 + + is-path-inside@2.1.0: + dependencies: + path-is-inside: 1.0.2 + is-plain-obj@4.1.0: {} is-plain-object@5.0.0: {} + is-regexp@1.0.0: {} + is-stream@2.0.1: {} is-stream@3.0.0: {} @@ -14779,7 +15331,7 @@ snapshots: istanbul-lib-instrument@5.2.1: dependencies: - '@babel/core': 7.28.0 + '@babel/core': 7.28.3 '@babel/parser': 7.28.0 '@istanbuljs/schema': 0.1.3 istanbul-lib-coverage: 3.2.2 @@ -14789,7 +15341,7 @@ snapshots: istanbul-lib-instrument@6.0.3: dependencies: - '@babel/core': 7.28.0 + '@babel/core': 7.28.3 '@babel/parser': 7.28.0 '@istanbuljs/schema': 0.1.3 istanbul-lib-coverage: 3.2.2 @@ -14822,6 +15374,12 @@ snapshots: optionalDependencies: '@pkgjs/parseargs': 0.11.0 + jake@10.9.4: + dependencies: + async: 3.2.6 + filelist: 1.0.4 + picocolors: 1.1.1 + jest-changed-files@29.7.0: dependencies: execa: 5.1.1 @@ -14875,10 +15433,10 @@ snapshots: jest-config@29.7.0(@types/node@18.15.0)(ts-node@10.9.2(@types/node@18.15.0)(typescript@5.8.3)): dependencies: - '@babel/core': 7.28.0 + '@babel/core': 7.28.3 '@jest/test-sequencer': 29.7.0 '@jest/types': 29.6.3 - babel-jest: 29.7.0(@babel/core@7.28.0) + babel-jest: 29.7.0(@babel/core@7.28.3) chalk: 4.1.2 ci-info: 3.9.0 deepmerge: 4.3.1 @@ -15060,15 +15618,15 @@ snapshots: jest-snapshot@29.7.0: dependencies: - '@babel/core': 7.28.0 + '@babel/core': 7.28.3 '@babel/generator': 7.28.0 - '@babel/plugin-syntax-jsx': 7.27.1(@babel/core@7.28.0) - '@babel/plugin-syntax-typescript': 7.27.1(@babel/core@7.28.0) + '@babel/plugin-syntax-jsx': 7.27.1(@babel/core@7.28.3) + '@babel/plugin-syntax-typescript': 7.27.1(@babel/core@7.28.3) '@babel/types': 7.28.1 '@jest/expect-utils': 29.7.0 '@jest/transform': 29.7.0 '@jest/types': 29.6.3 - babel-preset-current-node-syntax: 1.1.0(@babel/core@7.28.0) + babel-preset-current-node-syntax: 1.1.0(@babel/core@7.28.3) chalk: 4.1.2 expect: 29.7.0 graceful-fs: 4.2.11 @@ -15112,6 +15670,12 @@ snapshots: jest-util: 29.7.0 string-length: 4.0.2 + jest-worker@26.6.2: + dependencies: + '@types/node': 18.15.0 + merge-stream: 2.0.0 + supports-color: 7.2.0 + jest-worker@27.5.1: dependencies: '@types/node': 18.15.0 @@ -15168,6 +15732,8 @@ snapshots: json-schema-traverse@1.0.0: {} + json-schema@0.4.0: {} + json-stable-stringify-without-jsonify@1.0.1: {} json5@1.0.2: @@ -15191,6 +15757,8 @@ snapshots: optionalDependencies: graceful-fs: 4.2.11 + jsonpointer@5.0.1: {} + jsonschema@1.5.0: {} jsx-ast-utils@3.3.5: @@ -15326,6 +15894,8 @@ snapshots: lodash.merge@4.6.2: {} + lodash.sortby@4.7.0: {} + lodash@4.17.21: {} log-update@6.1.0: @@ -15363,6 +15933,10 @@ snapshots: lz-string@1.5.0: {} + magic-string@0.25.9: + dependencies: + sourcemap-codec: 1.4.8 + magic-string@0.30.17: dependencies: '@jridgewell/sourcemap-codec': 1.5.4 @@ -15953,6 +16527,10 @@ snapshots: dependencies: brace-expansion: 2.0.2 + minimatch@5.1.6: + dependencies: + brace-expansion: 2.0.2 + minimatch@9.0.5: dependencies: brace-expansion: 2.0.2 @@ -16014,12 +16592,30 @@ snapshots: neo-async@2.6.2: {} + next-pwa@5.6.0(@babel/core@7.28.3)(@types/babel__core@7.20.5)(esbuild@0.25.0)(next@15.5.0(@babel/core@7.28.3)(react-dom@19.1.1(react@19.1.1))(react@19.1.1)(sass@1.89.2))(uglify-js@3.19.3)(webpack@5.100.2(esbuild@0.25.0)(uglify-js@3.19.3)): + dependencies: + babel-loader: 8.4.1(@babel/core@7.28.3)(webpack@5.100.2(esbuild@0.25.0)(uglify-js@3.19.3)) + clean-webpack-plugin: 4.0.0(webpack@5.100.2(esbuild@0.25.0)(uglify-js@3.19.3)) + globby: 11.1.0 + next: 15.5.0(@babel/core@7.28.3)(react-dom@19.1.1(react@19.1.1))(react@19.1.1)(sass@1.89.2) + terser-webpack-plugin: 5.3.14(esbuild@0.25.0)(uglify-js@3.19.3)(webpack@5.100.2(esbuild@0.25.0)(uglify-js@3.19.3)) + workbox-webpack-plugin: 6.6.0(@types/babel__core@7.20.5)(webpack@5.100.2(esbuild@0.25.0)(uglify-js@3.19.3)) + workbox-window: 6.6.0 + transitivePeerDependencies: + - '@babel/core' + - '@swc/core' + - '@types/babel__core' + - esbuild + - supports-color + - uglify-js + - webpack + next-themes@0.4.6(react-dom@19.1.1(react@19.1.1))(react@19.1.1): dependencies: react: 19.1.1 react-dom: 19.1.1(react@19.1.1) - next@15.5.0(@babel/core@7.28.0)(react-dom@19.1.1(react@19.1.1))(react@19.1.1)(sass@1.89.2): + next@15.5.0(@babel/core@7.28.3)(react-dom@19.1.1(react@19.1.1))(react@19.1.1)(sass@1.89.2): dependencies: '@next/env': 15.5.0 '@swc/helpers': 0.5.15 @@ -16027,7 +16623,7 @@ snapshots: postcss: 8.4.31 react: 19.1.1 react-dom: 19.1.1(react@19.1.1) - styled-jsx: 5.1.6(@babel/core@7.28.0)(react@19.1.1) + styled-jsx: 5.1.6(@babel/core@7.28.3)(react@19.1.1) optionalDependencies: '@next/swc-darwin-arm64': 15.5.0 '@next/swc-darwin-x64': 15.5.0 @@ -16191,6 +16787,8 @@ snapshots: dependencies: p-limit: 4.0.0 + p-map@2.1.0: {} + p-try@2.2.0: {} package-json-from-dist@1.0.1: {} @@ -16272,6 +16870,8 @@ snapshots: path-is-absolute@1.0.1: {} + path-is-inside@1.0.2: {} + path-key@3.1.1: {} path-key@4.0.0: {} @@ -16319,6 +16919,14 @@ snapshots: pify@2.3.0: {} + pify@4.0.1: {} + + pinkie-promise@2.0.1: + dependencies: + pinkie: 2.0.4 + + pinkie@2.0.4: {} + pinyin-pro@3.26.0: {} pirates@4.0.7: {} @@ -16461,6 +17069,8 @@ snapshots: prelude-ls@1.2.1: {} + pretty-bytes@5.6.0: {} + pretty-error@4.0.0: dependencies: lodash: 4.17.21 @@ -16575,7 +17185,7 @@ snapshots: react-docgen@7.1.1: dependencies: - '@babel/core': 7.28.0 + '@babel/core': 7.28.3 '@babel/traverse': 7.28.0 '@babel/types': 7.28.1 '@types/babel__core': 7.20.5 @@ -17070,6 +17680,10 @@ snapshots: rfdc@1.4.1: {} + rimraf@2.7.1: + dependencies: + glob: 7.2.3 + rimraf@3.0.2: dependencies: glob: 7.2.3 @@ -17086,6 +17700,18 @@ snapshots: robust-predicates@3.0.2: {} + rollup-plugin-terser@7.0.2(rollup@2.79.2): + dependencies: + '@babel/code-frame': 7.27.1 + jest-worker: 26.6.2 + rollup: 2.79.2 + serialize-javascript: 4.0.0 + terser: 5.43.1 + + rollup@2.79.2: + optionalDependencies: + fsevents: 2.3.3 + roughjs@4.6.6: dependencies: hachure-fill: 0.5.2 @@ -17120,6 +17746,12 @@ snapshots: scheduler@0.26.0: {} + schema-utils@2.7.1: + dependencies: + '@types/json-schema': 7.0.15 + ajv: 6.12.6 + ajv-keywords: 3.5.2(ajv@6.12.6) + schema-utils@3.3.0: dependencies: '@types/json-schema': 7.0.15 @@ -17145,6 +17777,10 @@ snapshots: semver@7.7.2: {} + serialize-javascript@4.0.0: + dependencies: + randombytes: 2.1.0 + serialize-javascript@6.0.2: dependencies: randombytes: 2.1.0 @@ -17268,6 +17904,8 @@ snapshots: sortablejs@1.15.6: {} + source-list-map@2.0.1: {} + source-map-js@1.2.1: {} source-map-support@0.5.13: @@ -17284,6 +17922,12 @@ snapshots: source-map@0.7.4: {} + source-map@0.8.0-beta.0: + dependencies: + whatwg-url: 7.1.0 + + sourcemap-codec@1.4.8: {} + space-separated-tokens@1.1.5: {} space-separated-tokens@2.0.2: {} @@ -17357,6 +18001,12 @@ snapshots: character-entities-html4: 2.1.0 character-entities-legacy: 3.0.0 + stringify-object@3.3.0: + dependencies: + get-own-enumerable-property-symbols: 3.0.2 + is-obj: 1.0.1 + is-regexp: 1.0.0 + strip-ansi@6.0.1: dependencies: ansi-regex: 5.0.1 @@ -17369,6 +18019,8 @@ snapshots: strip-bom@4.0.0: {} + strip-comments@2.0.1: {} + strip-final-newline@2.0.0: {} strip-final-newline@3.0.0: {} @@ -17395,19 +18047,19 @@ snapshots: dependencies: inline-style-parser: 0.2.4 - styled-jsx@5.1.6(@babel/core@7.28.0)(react@19.1.1): + styled-jsx@5.1.6(@babel/core@7.28.3)(react@19.1.1): dependencies: client-only: 0.0.1 react: 19.1.1 optionalDependencies: - '@babel/core': 7.28.0 + '@babel/core': 7.28.3 - styled-jsx@5.1.7(@babel/core@7.28.0)(react@19.1.1): + styled-jsx@5.1.7(@babel/core@7.28.3)(react@19.1.1): dependencies: client-only: 0.0.1 react: 19.1.1 optionalDependencies: - '@babel/core': 7.28.0 + '@babel/core': 7.28.3 stylis@4.3.6: {} @@ -17484,6 +18136,15 @@ snapshots: yallist: 4.0.0 optional: true + temp-dir@2.0.0: {} + + tempy@0.6.0: + dependencies: + is-stream: 2.0.1 + temp-dir: 2.0.0 + type-fest: 0.16.0 + unique-string: 2.0.0 + terser-webpack-plugin@5.3.14(esbuild@0.25.0)(uglify-js@3.19.3)(webpack@5.100.2(esbuild@0.25.0)(uglify-js@3.19.3)): dependencies: '@jridgewell/trace-mapping': 0.3.29 @@ -17567,6 +18228,10 @@ snapshots: tr46@0.0.3: optional: true + tr46@1.0.1: + dependencies: + punycode: 2.3.1 + trim-lines@3.0.1: {} trough@2.2.0: {} @@ -17646,6 +18311,8 @@ snapshots: type-detect@4.0.8: {} + type-fest@0.16.0: {} + type-fest@0.21.3: {} type-fest@2.19.0: {} @@ -17688,6 +18355,10 @@ snapshots: trough: 2.2.0 vfile: 6.0.3 + unique-string@2.0.0: + dependencies: + crypto-random-string: 2.0.0 + unist-util-find-after@5.0.0: dependencies: '@types/unist': 3.0.3 @@ -17758,6 +18429,8 @@ snapshots: '@unrs/resolver-binding-win32-ia32-msvc': 1.11.1 '@unrs/resolver-binding-win32-x64-msvc': 1.11.1 + upath@1.2.0: {} + update-browserslist-db@1.1.3(browserslist@4.25.1): dependencies: browserslist: 4.25.1 @@ -17910,6 +18583,8 @@ snapshots: webidl-conversions@3.0.1: optional: true + webidl-conversions@4.0.2: {} + webidl-conversions@7.0.0: {} webpack-bundle-analyzer@4.10.1: @@ -17953,6 +18628,11 @@ snapshots: html-entities: 2.6.0 strip-ansi: 6.0.1 + webpack-sources@1.4.3: + dependencies: + source-list-map: 2.0.1 + source-map: 0.6.1 + webpack-sources@3.3.3: {} webpack-virtual-modules@0.6.2: {} @@ -17997,6 +18677,12 @@ snapshots: webidl-conversions: 3.0.1 optional: true + whatwg-url@7.1.0: + dependencies: + lodash.sortby: 4.7.0 + tr46: 1.0.1 + webidl-conversions: 4.0.2 + which@2.0.2: dependencies: isexe: 2.0.0 @@ -18008,6 +18694,131 @@ snapshots: word-wrap@1.2.5: {} + workbox-background-sync@6.6.0: + dependencies: + idb: 7.1.1 + workbox-core: 6.6.0 + + workbox-broadcast-update@6.6.0: + dependencies: + workbox-core: 6.6.0 + + workbox-build@6.6.0(@types/babel__core@7.20.5): + dependencies: + '@apideck/better-ajv-errors': 0.3.6(ajv@8.17.1) + '@babel/core': 7.28.3 + '@babel/preset-env': 7.28.3(@babel/core@7.28.3) + '@babel/runtime': 7.27.6 + '@rollup/plugin-babel': 5.3.1(@babel/core@7.28.3)(@types/babel__core@7.20.5)(rollup@2.79.2) + '@rollup/plugin-node-resolve': 11.2.1(rollup@2.79.2) + '@rollup/plugin-replace': 2.4.2(rollup@2.79.2) + '@surma/rollup-plugin-off-main-thread': 2.2.3 + ajv: 8.17.1 + common-tags: 1.8.2 + fast-json-stable-stringify: 2.1.0 + fs-extra: 9.1.0 + glob: 7.2.3 + lodash: 4.17.21 + pretty-bytes: 5.6.0 + rollup: 2.79.2 + rollup-plugin-terser: 7.0.2(rollup@2.79.2) + source-map: 0.8.0-beta.0 + stringify-object: 3.3.0 + strip-comments: 2.0.1 + tempy: 0.6.0 + upath: 1.2.0 + workbox-background-sync: 6.6.0 + workbox-broadcast-update: 6.6.0 + workbox-cacheable-response: 6.6.0 + workbox-core: 6.6.0 + workbox-expiration: 6.6.0 + workbox-google-analytics: 6.6.0 + workbox-navigation-preload: 6.6.0 + workbox-precaching: 6.6.0 + workbox-range-requests: 6.6.0 + workbox-recipes: 6.6.0 + workbox-routing: 6.6.0 + workbox-strategies: 6.6.0 + workbox-streams: 6.6.0 + workbox-sw: 6.6.0 + workbox-window: 6.6.0 + transitivePeerDependencies: + - '@types/babel__core' + - supports-color + + workbox-cacheable-response@6.6.0: + dependencies: + workbox-core: 6.6.0 + + workbox-core@6.6.0: {} + + workbox-expiration@6.6.0: + dependencies: + idb: 7.1.1 + workbox-core: 6.6.0 + + workbox-google-analytics@6.6.0: + dependencies: + workbox-background-sync: 6.6.0 + workbox-core: 6.6.0 + workbox-routing: 6.6.0 + workbox-strategies: 6.6.0 + + workbox-navigation-preload@6.6.0: + dependencies: + workbox-core: 6.6.0 + + workbox-precaching@6.6.0: + dependencies: + workbox-core: 6.6.0 + workbox-routing: 6.6.0 + workbox-strategies: 6.6.0 + + workbox-range-requests@6.6.0: + dependencies: + workbox-core: 6.6.0 + + workbox-recipes@6.6.0: + dependencies: + workbox-cacheable-response: 6.6.0 + workbox-core: 6.6.0 + workbox-expiration: 6.6.0 + workbox-precaching: 6.6.0 + workbox-routing: 6.6.0 + workbox-strategies: 6.6.0 + + workbox-routing@6.6.0: + dependencies: + workbox-core: 6.6.0 + + workbox-strategies@6.6.0: + dependencies: + workbox-core: 6.6.0 + + workbox-streams@6.6.0: + dependencies: + workbox-core: 6.6.0 + workbox-routing: 6.6.0 + + workbox-sw@6.6.0: {} + + workbox-webpack-plugin@6.6.0(@types/babel__core@7.20.5)(webpack@5.100.2(esbuild@0.25.0)(uglify-js@3.19.3)): + dependencies: + fast-json-stable-stringify: 2.1.0 + pretty-bytes: 5.6.0 + upath: 1.2.0 + webpack: 5.100.2(esbuild@0.25.0)(uglify-js@3.19.3) + webpack-sources: 1.4.3 + workbox-build: 6.6.0(@types/babel__core@7.20.5) + transitivePeerDependencies: + - '@types/babel__core' + - supports-color + + workbox-window@6.6.0: + dependencies: + '@types/trusted-types': 2.0.7 + workbox-core: 6.6.0 + wrap-ansi@7.0.0: dependencies: ansi-styles: 4.3.0 diff --git a/web/public/_offline.html b/web/public/_offline.html new file mode 100644 index 0000000000..f68a694e3a --- /dev/null +++ b/web/public/_offline.html @@ -0,0 +1,129 @@ + + + + + + Dify - Offline + + + +
+
+ ⚡ +
+

You're Offline

+

+ It looks like you've lost your internet connection. + Some features may not be available until you're back online. +

+ +
+ + + + \ No newline at end of file diff --git a/web/public/apple-touch-icon.png b/web/public/apple-touch-icon.png new file mode 100644 index 0000000000000000000000000000000000000000..bf0850ca92841dcf463bb98c9586596db8332221 GIT binary patch literal 3264 zcmXX}c{~(c7akLuu@p1bYE0HC42sCEp}a$Q?J+bnWS4caO&GE-iBBS1gQQosP-Gih z_Ka*b)-0Jfd$!Q&i&ngZv5ZI`rI7nH~;_uH~KF+s^fJ#E}WkF^r+qwJ%(!LxC$ zk~`ef|FbqIiS<*OmRm}qDGy1UR7yIGxE9ryP2rn0nDtrpRRps9VyB)KI@@UIyH8>8 z?w;Bm6R~a=r)W`LQZxor&NjOOMFI!sqym!w4W}3ps&cbVco_xGI-QR?>Su1{0;VE- zDX}zXHVQjV%%>>8E{O}UN*azpkeu%)0*iz*&*l`vWE{s+_;n|ho|(dANUb{htG|TL zyl5geJbNu$s65RQ!vd?Bw+TpNLNU2R4bK(5+l5w#I7d(Z6@D+ z&Z8Z%vTfMo(7RPiz!3cJym$IHW+5x%9{L?6*$;Hqi~8&Ih}oTSv4c*SJ7%BxOul~e z?C1%K_cdd`cLo}yL+nV7QB*w`z4@$KqiNI8jWyEqm?j?2Td#mC-UXeX&f+8(JD}u1 zcNW5BlXdP~TINFQr3k;Bpj}ci;XB%FAB`Yd5G9gvzc6@c_T)&;fU}UgpSS3%ZBiAs zfv?>aPcV}pk;~^}Oyj?|-TP5L$%Xl(91xv;Z~19dk_@XHS~|v*d->78XaD{Fw~Q%; zx0M>*(Sm!s?n1Rb;gH#Pm)lEXThSoE)a21sCN%nS-rHW9zV*O92LG@VGHOs#?iGXQ z3m@vVRC>GbT*y077gm%?*fv{x<{*USf4lj9g01co!=c@kZ~Rx<{zdE5&kE->mwicR z$;g(k8=a?;GwNM#cYZv6f5t1EHSFj-eOhpLjScqr5yLpPke$Nc@<=!lm)%&*7k3=S z8lKD9?j3Dj5p`-XGSoPFA@iZFTHC}+C6yHk7Hfh=f}g$71a1UYxfDOjR;iE8+%k!D z_JB^RLyen(G+1_iV=rp{=cAw6Tb(efd64q`2(9+&(^U);+qLgx(PPb{ZJw2IXGcjZ zK3gGboST}e=<5x;5dYPPboH6WB~VOf1tpcih|i&eo218^;;L43f}L#`ts2{QzZ@FY z9w@1_*YzL=51XBg2~h&(ONqo5+{XK%zBm_2fyaTest06VTz#;V=*GFjX50p`t*gyQAj2WN z+1dl%(_=0=DZ(Z4K9D>r{ND4nQwLDduCqOe7tI-z{IL4nXJfj9_w5=&E{OVs36Kll zENT3^zSB2Zk9c$Z#Uwm-tnPL=M%BGp%c`uO*zmz|NL1Ku=et%?7X4Ml#QXP?ZbtOn zxBPV5=Z(p^o4r41{*Q=Qw*2sKuk!n>N00OaF{)AJaxJ>w_v3QH%kKC1eoAvvxku=O zO$$O@GO3mdMC+@8NJBSZk9aeYeY=scR1Nn-tgAro1`UKCmoo~%_H2HMUrUi>bA#@W zMjM|EG7s(g8rRJYF>7<#(dRkca>mn ztky4Wg?$a1c2$xhe82E-D29`v2*j4(-6#mdq?5fyK96GpdPZnJ(C3@{JRQ4k%<*1y zc_$FU$0EM}zLs5O@ZBMJbT9bJ9mbK==679d2R#omTnu-cUTLc)wo&*^0vk)ZLT-0= z%S2VUhNf9k!DuPM9VCp`GmJpwJ>UU$MV%>qiRVCGxQN;l^Ev4|S58In7X;*jVOECi z{2@<3nlY3=6m_T>3Dk_yY$g?7t7J!B=Oe#@UO!>uwx;Xfq`v}PfU3R8h>_Vw@g7+I zkN6u$QzOqr`TuFxt8Zq4y8XJC{+W7;bf49%n2wk@6ojY#8kN1Pogx-{vcf$aOibOO4Q>t5iFF3X2_*FqV&5k{7wO= zl?pH|63eEaQ}ORD zu=J{|djY6G|KQ?j=8N%qT~3`_z-OK4jnk{ZumHmc(Rt?oVQLO5g?OT3r_AihCS^8E z(|$9W$|ntZRGA-XOygeyD~#xsn12x4(ZL|3d5}lwE-mUz!%H<(3z$%XaYfXQbG(!y zd_j)#9?aP>H4PaJ;fFu!Pc#^uO=cJRjhL*_%^}_=D#xh3K1*i=L4Ecnyh-Im2TK-A zB-V4T7HPG1{UHD80wc>|<2+fRR?<^6R*z#x?=2Mu! zEIhMI$1ikOPs6WC{}p;^!#B^`DLpNjB8moe+|Bt2DsoLSA)&*{C*q!f(XN18k|a&s zkAX;x%#JVnyQz9a)Guli(^ee9mzM)sQ|Ar zk!#|2y#7jvncz{dAuc4%)*&uSd&$p<)5Kj_+mj{(yga`3UhE$eLF?x3w;B&RvC+9? zsUoJj$>H5cd~DP|Mr$6+lY8BJa;zfk nYd-ncx + + + + + + + #1C64F2 + + + \ No newline at end of file diff --git a/web/public/fallback-hxi5kegOl0PxtKhvDL_OX.js b/web/public/fallback-hxi5kegOl0PxtKhvDL_OX.js new file mode 100644 index 0000000000..b24fdf0702 --- /dev/null +++ b/web/public/fallback-hxi5kegOl0PxtKhvDL_OX.js @@ -0,0 +1 @@ +(()=>{"use strict";self.fallback=async e=>"document"===e.destination?caches.match("/_offline.html",{ignoreSearch:!0}):Response.error()})(); \ No newline at end of file diff --git a/web/public/icon-128x128.png b/web/public/icon-128x128.png new file mode 100644 index 0000000000000000000000000000000000000000..06c630ccdfc609448593d16608c0acf253649209 GIT binary patch literal 2279 zcmV_$nD+)1rZrF zD6);M2Aj2DOqXS@rGbKISet(sgR(@HY@$=Zu4N#vPC#f7uwe4K67kBlc)OqW-R}rL zZa;pn=RD_}=lOoNXJc@==XuWev*$VId)|^HV*p)%0l-M$9$+@G2>1)|Hn0yk1RUWs zN6g>tGe09g`<(f|@;h!fzq5<)=TkZXd1n3|etN=!7BeHVqeGKpx+2u`Ow2IIPU<9z9{IE_MjY-}Ct^!^pzbps7nB)zh zhe@&=_Z@)%I0noFx+i%6Xa;uruJr)f4m2ehPvA(G?xgRU4ww$$DS1OCSpv8k*zCJ@ zBVto#@&~~9P6IDWb$kfiox}=ouE~)rjWG*2Cy6k3zp%jvS5EW1w4st10D1yTi*8=A zLo3ib2^pZTNp~u4kZft6Bt(GAOkY-U%Ri*9laK%|HWMS1bl3rWG6@0sF6nFE3mbt8 zLTK$T^Yi=)g@&P@X=u_nH8W=wzbuxViw^-b$rBDU(+>Uw-%qUk-yqWHGzWIt&n#aF zfPVx1(iqZ}kt!ujRy&=J4$Sragi1wbxSYw8m1){prUMx2Vh*2VpOiS*V)avCCU7co zG2K@1KW}EPDsdq_wf;5)c$t7W`~m!O9^5zy`n15gL*Sw&82oLxZ!WxZ(9eCf{|6Q> zgYP{ALngw-&CvBaNCww-4g0>;+gfB}#ZEA+*ifk0auwM9dicXD>D|+NZ3Xdq-Bf$9 zQxHJ-S|e-q))EN++zY*LuC5Z#83M04UTD_Q0dp4?-aa-0?@)l1^$H*hHG^T|Piw14 z`6RgFzenLa57-U7Lji=F>JcEARk}xy6<+PNR_4}S_V1;w9lrWqH^Fx(z|wk>KEd$T zw)!gb8OzPrlP6*HRCmF5D1a~|+Lr&a)%8{8oM-Ib$4`FaHu#POSX|4tEJ3AwTi4ZB znNM0=nXqj)bo)xw0!T~;RwIBcRSpWN{CX;L@oV<(;jZcKgYQ@X;h{>w?*{BAFr>@X zx23j+R9~Ka0?8$qp@qk{kUX**)amMkx`J`|LfWWxO1AlvZu|d zu1vYd2pC>YfZq`)M?Qqljjb*a7Y>76vgxZOzA!FR0?aEn+b85r7&-VZv`i@#`uSUTe8w*{svD2Y>a-nbjquKEC%0ge=ChPxR{bwf< z0fgpK0?4kGN+*`C%A^3ZN(mr~4wX(UUz14zwv^g(U1=~06_EhKCB*`K)A!wkN^5on z7^~m^d<*bcu>f+?MruemO}?!zuX4SC4cp+k<<(t3d#ZW?B#YPReM_$+B~}!#^8FyS zVu49NuPv)r&n1&K&W3auU6-GPITq0QaEmS?z!jv73P1<~2>rd}|5X4&5nzM}@Pkx~ zQ~?M`fXQA~{ipzhBETbwIaD!KQ~*K|V4(=`*HnvC0SHKd*2Kp)?kWJG2(VEEusC(1 zI#d8c5nxYZ5(23*|HZ;0%380F549t}lGowhUsZRF|8ezYerZB|&sBWQ{(YK};80=? zCWwM7$Jh~|7Fx4A79g~X04In96~H+;(wo3#Nei2xPADt{|p8T2?2paM8rA`Xlr0#pF2 zj42l2QX)VFu*#Wd56gCZ1da+|jm@QY2noI&paNLq(NY53O5msf4iAx#Q>a6q9HIg^ z+$PRQFrR=?0j%(J$>19SZYN+=04sdGoB&;2trR-&Zedf$My?(=R3D5lf2(k8OrzJ8 zHAr{)sK%dB_9gbVS+tR0hKrJA@7`)FGSAmAw@br*Q8xHSfGb=a7@-2-TL6jafQkYb z30|^Yx(a}A0bZyo_(p&x+oh`j_!gkHqvL=#ZI-SA;8TFrH3i=YFxuuFr~vpB;I^6t zFcPe>bq6W{z64l%YUWQJ0$3X#Pyz5IKvP}8x7{O90q`Nfvke8mC@;`(V)gh5*ttiq zofWQq|FU&bQRrBEUr^8KJm)?e|GSM!rkhFm%@7 z>z%}aEIu^d6U7dH0?toj!sH2L9)V^I>qqMDVQ>9>8vxC+G_Zk6$a8N0wj>M4Acbs8 z=DS8CVvY2wk}P3X9zSR%EGTDxq2M!+U#GkF4i8~o7BT+KV}=FM1o z+mOxEI(>eC#v(Ee-Ttk6Gz83{+P)S-NjiXVhGnKXAvM3Nt=14%O zFoPtfgybKMP2-GXl6}l*fRIx&!pM$T+2j;fVo)t2uEWCQ2Z(*`3bv$%5Fnefi-PR# zuX)(R@JesH?|a{S?{m(*&u`}bv%|i7?sI1)8_z}xuG5nw$qA2?GxeuV@$1-Qn2RU9Q; zjsnfVEV(D`xaJ<<eKEq59tF|0q1D*(fPT+zlWPr~B|0#EO zMkYuW<@hK>fGdDEvx$>20EdAuMIix9bqzQCNn)E3g#d7M;7MM2n(e@&2mQA+^e~&ZsdbG8iQs_$;ekK$jB`7m!HwTVlJSEFstfidbKz*l z^T_A7L*os}N|S*=!n#`JnS{r@@DkKDR3Gqrev#c%XX(%5wb2uSsHr{?(2B==V`;pA zpF6d`bJL`!7jC>WU2!rJs3opEQjFVcE}R)Z=sR9cuU&n8F!%e}$diFULSr0(R^u_f zz3}cD2BVL(q}R6ZuEzm=AbDc4~#t-k#0uuV?wO6f^h*H9RN)(v!6n{2)h z7Ma>V@hm*>X#WcRvQ@D9N!Zt!{!=ijFN{Fq$f@N7l9T?77;M{KD1n5j7D;3Cgo7O;E zF$G#wD$rw^Etzm5)L)y;b^Z4SZ_l`S{p(tlULT!Yoj~$lD#?3#>?t%jv8)078$~`a zp}G#JPzAbO1iBw(OdvuPs7VA`gEA%%p$fD*@}bVN2}Gy@Z4!ZYpo|Gbr~^@`p)LT42E zv6Pa!nzTUG(pJpHRN+t*df8qRNR=KFC;{3EE|7hN)ks^xzrxf9(Y0U#snY4iG`<#0 zAXSb{<5SwNnGGh8Ds7QF_AppXAXPSsKq(b_%LWrjl}Eft=cok}NR=ip63S}91XAT# zLfISw#spI3SW4@q1dIu!O5^decEMr-sdC2gy=Krw+lD0Alq(q12H`TsD1R1jCrJh@7l`tFQ4m_RE0yZf=fy5=@}X zk9+E0{~AD|<~$1|=Zkf|k?i%zB~nVanxNZ-55*N`cys8k2}C{* z-OcLQZxe{n1iHH-d7MD!rM+j~1R^AX#D$MlERd7vw`sP>1R^AXepQt`PM}oh3MLRC z2{fi^ft*Ae(`u0kL?{Anh$W8`D776MCJ>5z}_-xGrIf))jx^*THz6*4JBJwza&IY=YY~8E-pktR^9SK}rhe(=(z=skO$Vqft z;>|RC<(5R{aRLnip3}ZFBXyn!>Jk^oNpw+Y`9eljNZ;0{B2S4#i>hmr5fFE#DvuMW z4tQGoPL0IbBB?y73*;mkk@T$0P^B9fnTb3l5~&~7Yb3_(Oywz&XjyXiU?}k;6?sb1 zUxThQU2s}co3d9Sk!%HeQ9BYw)$9b$ihKY#Uk=`={vHe^4rD%P9t_DF3H|7(f^bN( zO(P!xE(@_hLxDH~Opbg8xXPA0yhQrs$|wY+ejf0acEpT#JbA8;LIRj*Z>zl-^IRT< zh$J4m5x=3sYu*l+t6Vn=`c%X~>5$heQ67*NR=_6hh!*S(^ROsSxQs^2B}$(anWbfD z;LazL^Z_GTWWw_0s0aY(+9GVCJOg|pDiSWUaiP6*tO<$TUFs|9ngE{$o~;;xcg1^@s67{VYS00009a7bBm000XU z000XU0RWnu7ytkYM@d9MRCt{2oqLd0Wf{N^%f%E@bV4bb1TS0^GDissWMEheOcBs* zvK%83(wS;TO0ZG^!?ARxXb1xduY*bsiCmH_1P9re$rM7lgoT%ISaAWl7woTj;6=V! zc9-vR-t%70^P4&U?Ci(BmmlZ6-*evgd6Fc@09C-bKs7KL_!;mRun?#LHUb|4b--?p zvD^IYL-RW|<}>oydx4vQ!N584H(d8q$pD}wa1n4DFcVnSKpI=@0{&|L=B>czr7f<< zL#Ys;1@Hx60`Mo`Bm7|}@B%R2NZ-Qscqv5yv<8L(zXP@q4*vmW0Yjt@uE$Y1{!TT} zOpvUJLT8(KoDR@Cn?r!pfib{8h?kA#F?y!!@y-oES70izm;7)5cpT{IdinjF zlDq<(Y}O5mUF6BoF3A%>4`7|;fmM$22GA|Z1Hdp~M?vS6Y>?d~*Cmm^l%A6FNW5!g z>?cR}5*;`Rc+&OgDjzc!_(T!|z!|{H$NHvt!ZM(J5;C&Q1bE%`NGeUT7Wi}$B0xve z0mX0R+x%yfkdP=cu*vnvDMhm>n8-iS!NgsZu-G84?2-T$^s8Nulu|aYdAslj+5k(- z@0;QY%O$Loco;-|!u7}~sqvIo!B}(TUWto|i4Oq7_4QAb)C1SLmaCgN2Cu~Xg1m<- zx!UQLn_RFKIK_ova#UZ*2h&}wyOew}EX#L{x`#f0)Mk<+1Ngn`o+{3mV_UAP-1SX~ z`cWyThE1Y0CEvU)r|)eD_H)-gQ@r8cwB?d)$@>X}b^nGtr$O%3-IM!DHLX6;+>ok^9;l(AsK+_dDnG?aIZ*H0*I0y-*c_n?HrB zBK|XYDp-9g`N@DK1i+&U%A14%w`AYec}wB+LH5MTNHAexrE>Kn5PDu;{zTNQ$*!Ff zXF!Wf?aP&sU_#$Y1e2Vo-m`vlWfL*}*V(jl+%K~cD`UaRyNk(9A(XY(oEIvah{00e z#WKHmEL*uU6ighspd7&-ArO8wr?QFY^>w@LTmEWs-)sXFOnA7Q6WPJUy&im`vWe(^ zt-ZGG-4Evs%U-UG1(Uc~hf)N)gMgUzTxAo{ca*)h-7~|DTp0@{++NBFAvuH@4Dv0o zl8Ly*(vg*&yR!*Lcp}*PqD~^2!csx8|3GCEDPIz7FzuPr+Hu*pq59VJuKOP)Yx)-> zn3Tc`j&ef)@~%<@wLzboN^8q%DSZ_-zb&TTVvr^Ae2=K!%KGBvu#J|uYn>E zOm;fAYEG~#37Adq!g<4so6J^Ugqap!;Xk*mblD>iOt>Pt$7927FZa!c^G7s3iKh;L zZ~PeE{FmK!NE?!T3O1v;Z;w&!Slzq@UjF-$m&;3P;Pnkhw)AAd*eSUc?A@jWlLG2W zO5E_1+zKXK*qC5%f0u%#_lvZX-(cc=Fl^Smm@S5`e2MeL~W>ewleXhaHtAKjDl?t!M5T7Di|>e_I_fvRygP2p(DxQ zD!C+OX4-<)*F)XT(ywpbReD<%t*Cqq3a_p1&xh5CV0(##%SWd#Sh?tKio@&?!7@4q zVILLDI}WN~DwuV_^bu(R73|m}(u+lY8mM62QRhvVA`Mh9?>HQ$_$QH|f_cY!5v+zt zP{F)og$TBgNKnDNW4<@rb<#iu^N!ixY&c8<70f#hZ#W!HB&cBCG0K}mA8DY1dB?z` z#YUq*1@n%xj~=|;MFgl|UUB5$tvTHtMJ!AO^NJOPxhZB40VUt>QY8|=j-lBcRXg#Cu{nhP%tCen_0Bx zgYBhHf?oKVzG>aZ+jEK#>_=I&NChJ%!EP@~E+g2Pz<%2;Qo)EtuzkR%iWV%Z0`V#s zu?W_9A@~yr)?E_(*=&^xMht?9BRxtM%t*G_X3JDCVi0UWS#lY{zGSmyDi|>cc3Ihi z8Oi==t7R$}p$qnWMRFOzF0r*1Q^5#XFma-H#ex~hp0&|J6^xJtdny&Vj9^_%tRq!a zFhUhf^7@{gnqWq<`+O|EpcgI*F-%NVE+bew*{x`;$x0~5{*zNu7tBa@rR&})&bi8p zTm_Onqv8ljci+LfU`DcQT=i0Mg2cS8&P1-*GV&-zF)dTM zj9_hnH;QYY5-@9klQS30NY*umq$x_XSqi&5k*h$mVYc^;DNc|%9g+9|Fxkx*C>FUp z@dcCD;&Ge3RWfBx(Im1!O+=?8M1V7ZRjx-+X_8kndx33v;r~+8 zeN-Ir7w;GJ#R9a^IGI;SmE$%^OqgKoM18H~6dC)wy$hnIiEOzAw!0nYT(T1wndAYp z3uCS85zi58fb)|)A$yE~srtyYj;wv#CV2(;3b4igIOmSq%(ppv9xu}^*y%A>vQ)aB zSMLCZ0-IAD=)CbBFx>S#dX1bKHsK7(f1nhHjMe>e`rh^Y1q0C8-0Jm9K-0+BJPmx# z^?U^j&`U*Ylous;o9p?B2B5E0Qq8$&ha@K|(8u+BLYzGzr7TaWAF@JNck-p0HcqrLzf|P*n zAYhb9f$)eF7%)<-H*2E01~PtRezw*8&MW3K^4Uq|-x?^Hn4{j@R|NkDf1DkTQ6m#G P00000NkvXXu0mjftlbh@ literal 0 HcmV?d00001 diff --git a/web/public/icon-192x192.png b/web/public/icon-192x192.png new file mode 100644 index 0000000000000000000000000000000000000000..4ada284e1d61c369f0ae74e0ab15e615fb6c0858 GIT binary patch literal 3464 zcmX|Ec{r5a8-C|C!w{J<_I0vWmL{^5W%OA_wg}l`q_Pc$D3k3)mdcW*Mx<%6lq?}? z>_ft*#S&R#lr0iPmTbS#b$!1-&N=t9-1j-xInN)@xpvapjE_g02LJ#*bAquQdu8qp zBqw{e8zFJA7j81a`62-9!R!tgkewsSPCjaGY-AsvGk-s#%+W!JnVv3&^?;HeuiZUh z(IxgzWZo3V@x=t*Z<;2@`S!o=^=l0-XtmVf6tZV>J+R}t!e_NVS@0nTSp_G_z^uuY z-Tvha>U}NsWYiYy9a?RBD$0a0@vEoTC`A43iteZgOU^`ClJA(I91dE+8;UG0As-}I zBQqHFD_fd+@EN2Vryi{MQ4L}2LUmA5ROLeLBV?HpnS0T-^NFTOx%6Fb-twf`WOC7d z^?K)0saWaq9xLh<|MYa*k&gG5W7mf=gn=a}W2NpS4BCR`pw+6}gLqm^PzOgm*U2%=*~%gG?8eG>bSNta%CS>f7q8V0J#>`=Q&^fR5yt;T;K#^%&A_c6vx%VVLok z)kZM-2qww*Cz+b+oI}AV1$@lv&{)^`*gD<*w4{Nl^;1=5p9d0sD`pF%WbSbKfV6;! z1wI>}OQ(9yRC?vx0bDQ}|MXH@4VytfTWcUbHr=mrHBqS;Q0qy1(DhNI)j$1lh8V?t z_|!3a95@53%i0>1pf4U>6q;x7fGj<)w$wU4^y8f2|THZdYZVe82qDn7|8h+(!u97cT1Jy7BbGTRY2Y}fIwQdd4?qaazuFY<*J^$ zM0T-LfG{KX@UNdDCCuw|29u67NdPss$OYi!%&h}Cni(nj&F|8*; zURp-Sb67O>F~v&QNnniJMiDm^8=;0f)wJL`ChA(a@_<{Dza@AG3CutPBvELXSC!to zciW<`CQwwBx0`2M%`tOq@!UcCXa_%5|B${mZ`(iONvA{;ZI)G+oMd%{T5yp?hAx}I zR?I&8+dF|*oiDOFTv>N59&R{yZ5t0P3F?rrIqG0(qsX>6W831M=Maf;L4|h>78#5R zo#m*N;WuB{bg5x1m!7c=UA+8kHhX8;o3+?f#UD7P%(@dJz+2Scd^?LgL>QPHh~&`! zX$B0Me5xkECieH7D5q$Q;Ht}EftO`Br})F)Khq>H2@X8>&^3B6!-E}hnOJG<=v%7( zI!=mL`IuOJi$1we_KD@!j=h`4r=h9@$xir))f*=U@@UTOsD}|+O$9sSeE$8flRah- z(T|lOviE3H3_)m*%NE%!I$nQCw~kfMKi;mm#j*)S+;q~{v4JVtHdV*am%c1L@B4w? zluL;3{KUU$>;a6I>hTwpj*NK3DRegd(89kmyg_3=nx5r~`jQUV`Bz#?);`(d#KeL84h3!5l*sg^B2(gwEE}r z7@2=#m>y9@o6+yW9SyrMF$k3DIW*Bg==>~oou5(6ysiIRcS3RtZ?h@Pnp80pb)b#a z-(4UsTylH+Cn76_a?-FJvx7ig(UfJLJD8$ZHkF0Bxcp|)eW!*`RoQ09h<0@ zm(!e}K76ed_rsizKE2Jc-q}FHZJUhyN1P1?_a}XbvV@MW@LFU?(rmOk_W6&-On@o_ zwpkbD088i{DPjdj_FU=I>|ny%-x2TaaHVkH%qkDyUJUuqdBc?}hU-9T*4D*TbsS9n zh0!RbN|+T6jz3azaVM;F8Tg$mawDjZ!kJaVM7>xdc=e-QBSN&_1@h*GW3V~2KdQ{{pFqOaZ7dGf z>{~bnssz^WXp34xWS7}jz&*pyO1zRL_`AS(Wp5DdsrS*Px80-kZDM=5X^H| zaR(u)0H*B2{$(`+xhBv7_*HI{wZ)bQ%K*&^{*Qt?17FklkFrKZE-LPa`2TO5 zhC7|WPu$8zQytOHF^r;0yf+t0$Cq$n zuzsJCfw1r1&!iRcy(D#*C2&@RS%7C7r?3%7E!g8|JGym=jR_e>+>dfi5;cUzA&sI?_@y?)+IVf$v7K0{9-bX zK-9@N3mU)8FG1*}5q24wQdB>%rDHnXJWSx7!f{JzKjl#g^~(Zw7gkrP!qomEv0fU$ zh1#cxza0eC2FgKH?9&t76e4KcRusS)Q``wt#D|Vl$ie<##Mo$gFawx}`i$8RAtW$7 z|56#E5{1#8pz)g&Db7X=QS>it6o_{*(SK(U!9N5ovY-4%@}R*Ze+%I^0wK9@X5aK#MIDD?f2}FT0Id zD~Rkmn*_Xmfy5S~WqjQ0cN2aioGRXbYU7k=7`@<9#4}X;L|9L<*o-b`4WkcmmP>D-HM2tfucznD!MW`XK}Gg; z+Gpvjvvqve!4#DvYxjX#Sj?d!Ga0p{gd4>P16qNPE!{H)RNMe1qei>h3!=xKuUxuv zplR$xT+-zb+eBO8#)Fz{)<$b2gFenzvHyj~H}G7OtcDFqkoRv*_O6pkX>mahP>f zFaRZgTt|tSq6y_M4=EUMQWEgtWqW&Q#J zrOY2U-i%4)eyLO0qhg*+NaI`#nm^_Pe>z+;r9d(oxQ}5Sy6!K!zjn{Zt`d8#uJ%WuM6TqI*BC7i?}c-;0*(;9B=mf z(}35NU-NnxUfFrbOnr&9H%BOig;Fxzz;am8o2$1_!wDmsx5XrtR~Gw&5%+ zyWyQRZYcPy7nX5J5YaBcnhp`pSq-ApD&;65_gPYOvCg`ROIL%%E;65`Si!s#&A~^nu6%#r%Skb|42p_Q6XpoQw zzyIiX*?z>=9bu;?TvPcgTI;#?Ea%KY-}*q4b1$bq=BHW@{ZtDsD_Ysocvk&bUNcpV zt5x@aurhpOc+%G@&<2FJVOV=;}L^kmr2ow~_10c<@GCOi6vS^MR)0FF2+`ni6$rjt@ z3PpNFrS5q?c*e(bM71`*{g$Bijm76Y}`guHpu<9ie=9Ha=XZxeipX;>+ssz!5&H@v$5ns z#$(6>Uxo|A_3+ieL*RYz)3^^r5#nHX_0pUXd#Y;(XX6bgL}Ni_K^-H3dBXWXk0_dp z_jjgEBdt`1`Brqbfjr+~!B>2f#Cx>o?}&S`6xLez)q3MlR6X0=L_wZ^LSPTjlP*c? zo@cK5TO`9%&ZJ6SxIw!NgmPIjC^HEBq&5$Jfq{ADx`oNbHCe zqz7WLX4V4Ag6=}LXK)t8>YbSy=w3mG* zNp7PRpTCRc&>nX1d3?&pe%7JXSV2rDN2TL6!C`+L6e;)}KI@B}+kV8jBK0ocVD9#H4NRSjI+`<9R1$CKZh6}G|8Bj%dzZ!chd)#?v`#* zInP`l#ATDp>=Wvry;;8SQ~NyeEK!&CcE{5KzSw8cMb-y?tQ?vYWYc;7*Mqu6&oV*&#>>Z#3ogNVYGf;L3GTN`Elsa*@fzg)RHx*G^Ibso4 zzhb>`fVNn&mSWtxJy(w+vm3pB`Lfa33kz7vT>W0@1PgLrQ%&j~u(qoIGwHhT{TS$0 zI95$;MP^|qZMWt~0*5c!b<8RYH%T)5 zJ?=8*JdB%n^V*u3;^E`re+0(=qqi^%uNmSuNSHiY^lgkBHxQ6gR}xOYSN2|>T0R5+>Q=&~`fAY61nTkX(fcL2 zT4&KP?kd=JsSu9LJWko`z#nV=4vW&f+G>AkgmVz-Z1Thlv1P^ zX1pG>_}!3^!&{ZW``*zWg9%lp3>7&O4Kb? zZ;C8YHG9v&lxu@K&8?>ce~hE}P5r&&qPQU4?&vBTsY6tLn$GsD#}`vGAPX3+>P?pA z0}^x-xfOO5cCXI(7%I8&b6~aLZ&^>2L)TMtOI#N&JKO*xg_k8-q@DyO&BohM`R&bu z(D3Onc6H-#*|s_3HmcjodN1a?^XF|lpV#apLjFf;*_gfv?-iHGAg!Rwg%gtDrqAE#jRj70-v5 z#E%T$nH$cZ6AeG-vFm>M(@uXekAY2hwAap?|A%sN8f$kzl*?8fMb&!y`9 z0_vggQzi`N2x*JPr*P&r?x5HjHOmm}vlH>bUQNOvCwu>P!QU;$S$QfUm1Ct>3KOq? zzc@CItb$SD6?dh8l;**D27AZ&#tW9Hb*s&ZBtwtt-s1!cTYK-Rx}h zh#|z?F94WyrJEOCypaX?%LgX9j3Dh7gm3%S`r|cwRHMBV=uV&Gbu1ytx+fnufv~EW z%^ikY0@q)99^cm%&bTl4f|WKp`*zFE#pB-xTI4u*diU+{+SA$*R{eCLHj4m{jJ6n& z`)*79OQ~Ma$z9HaYpvTs%`PVM+mP&hkI`tG*>bI0{q7SLZ}jN9)*IvT5o6MwUMBZ} zWuP9&3nYKK+bZf+CmP3anPx-!8xI!uO}*Vjovd8=vTl&lU5Vbg3!t>yn|pgi>iP(+ z(&_W$N|1y@A8N6=2s5o+%TirFauVF7zb7Gxb2A)ItNfUOn=n=3)}|exiB{V*Ai;Kp zB$Im$cd_Xtqq{5W;6eTQ4nsZ&>B2lYRR)s&j`}2mGpvf)xp)eg&5-8!h&rUMJ3QR} ziicD4KO;8D25jOpJu|^?(s2L@DqNVhQ{^D(b@C7&QJdyzRU`x6DtvSYwy3l5Zj)_y zLS}=H8TOQKQ2y$>nfccR3r6)0kT`iZzWZi+aBOqbxgEMlkZL(zWIif765TpF-)sV^ z*HkV(>FwB!vH2Q`UiWb5fgXdp`IxF|J*@#Hd~qQ^@vYhk$eY4+L2Gsa%Tignu;o1Oj3w22ttabN)3=H5W+PQYIZT{egK&0xE?ZiLMX=yKM(JIydV3$mg z92NG#&*d6mmPg~E0;u^K5e6-2>@WR)5;=arpacV9^b}5lai$T;$wnW%z5-!1{$ulZ zfVO+0>VHxwfiVJTOZ$&q<^gW)g#RJ&gP%y&0*^8vJ{*?f6Wn|S?%g1QJLqfrhcX%D zWe*kNWWX{uy?Jy*47Xhic<%U5bgC9$-xRHK75SAzsx7`^4gC|bT?`k%m9;$!s z=|Z`vS9_x+c6%jjevb;G0rNVe4pwUYQP#k%wgW`=6ObAXKpmj!{^lbdqIs5ELZu*y z=!OJ^)iIeUJ{(LHRwxT(PjNBlgaDTBF%D)5Ne(&#GNS7LyLP5_a3@n<*m*_m)ElOZ zN8luQ(IBaw`jGgiFJq8;6aUkWhnYEB`hnDCnaRt7&({Jf&2;k=86b=kJUk1ds{D_E z0TQ&jFj3~hfX@_hydAW?{+B5xO$29C^)I<=4N(VNx-@_csP9yqRsT1BW~S65EYc|Q zAJ3^ym5I0TBQvMDB4Esqq$wt(Jx0*4dHN8CfUuv}i~88Db@YF+$FTxobO*HSsI<@d_5$Hqjle zdGWZkP%V(?`mZ-p4+(an|Fyb@-NEc%O8A+7I5mI1<_`*l@D1NR z&XGIL{KHeRs|y%V2oaShc^bm$%dpbI@Og*(+|nZm0>o}jew+mUTUAUxj2CVy(#i`D zX{4VQ=1~C~Z3m#?PlQ~Jf5LzFaz7Ya#14{CS}{*c-l%ErW?ljfQrDk1H_?vV1T{_c z;Msp_;ZDi{2H-*+{nD#{w6(cS){a8dV^j^AXTL3Xq6J_6)|2g#;GW-@hx~ZuFs->@ z4}JqZH1n_%&sKF8i?|pDRwVPzlGj{#6Nrzj^5~t1n>IpogohB@OJq3&C6q#R$TIyMeE%JX32E0uyw%(r9=A=$Y1Vu zuUhZ6i{0$W#Wk=Zop}m8&i)X%$WI(Nk072Prka^SrA~fNdKJK+``lFn5G&|zZzcl* z&$qZ0LE2S!xr=0Yb7YC7I(WZd0+%*-Z;f(7&=w^v44PlTsgn+=6ak|D`n_{cPlLzj zRX~@u1lR&g-^AU>Zhg?gmTVcWc%5YK7SWsr-#uKpLR~DW-2D0c#0Mjf*e#m?a+3iU z{0P!69pMcov;v2Cx#YQof}K>jONn1vn+r&UhFi6`b@BG+V7FQFhKG44KN%qKaVMyD zlR6jS2Vp!tQhNrD9TgGG;0{;@@|;(TIpdz&xLa{h9drjdtlJ&+-i7DZ;Jh@DD3s%J zdyW%Ba7&PL1Oy>&s~?s8xVv|(>PD2!==;9|2A!oJoHAF(rGr{@iBzU-Cp7DN9U&it zbu!z(SdG$+bJI@gzhREjBL{s9wZNsrp>D!aHKB`SJ0{APh@myAaZj)*!%*?YPc>JKP9&z-7q_&Nr$DCzw z1&nNIjSrUGU!0Vy$eiozM8drX2>1I+*Q8g)dbX0nWe#|&)(x<%Q<{AK3aty@C~rDJ z3{Kl4eNC+3+g=3>O7d%JfjRq`X0XX9!7~e?EZ#Z(#W(f(vbViG?U0q?!ana7Mz-9C zKAjK7qt2m3I`KX2SUi3SB(_)$}5$7if!H^T9H|mOze6I{TL9ufeMwuIT~;@|eRI&AIM!4LEt=?NqHok-?|0E{{k5NOvw^ta% zxNxsIuELj@C884@qLa-vRk&(?6@D%Fa$|Q0>LHx4QvE9QEi0i~j@8Am5C7K3VkN!L zj*%Xs3@iTV`Sxi2%7e9Cx^GPI-*RT?7qM*fgsGOI<<#4WtoFH8_Unis(poo#mfqV% zj&i2`+AU4X@hd^FAbm&zgyCjLj`TGu>#_-E+kzNn>^13|om#HFs1d$#{e;Ey^@yKd zARRQWpL>{#MgO3jrCf=Bae&=Z9keu`v%+CYaT?=h6!;+eH`54qfe$iHMt6;0f=Zd0QN? zH;?~sFB=n<=haB0VERqYz>M8F`$N_DWE{SAj@{14h^X-0u|>C}eK#F~IX;tC=y-sR~ zHFJ1v4{u^%qG4ipqDA5j|4(F&%;o{Z)~E;U`&a@lshasIdaBQ#BWsgc$c4#TtMMHQ zFW<4XYMKxDh0)@(G0i|QwR^v*NXhBKo79Tq%V$HUrdLLD`ol{E613B;VGEq#BdC1lVkYS%bnnAGwCK|JnB+P%WqjN2Jx7?CQ$x9#x`C>;4my zIUl=8=dIC*<`v;QE5Zhh7J3+$jKn6&6SWdu(GBg)mM3fisd z17*&V$`$)Ds!m5&ow9Qry9rwLhB);qUMOzJ(m)T3@CZKwuci6V8F^Mw#^7*Rm)>}5 z`StF!22+fdMa><_AKCBVhTy(v!Yt!peZv#YO{b>>8kI8U2rokBrV+*~QmN8@EtS{8 zT_^oWZPgexp|UHF(_%V}qxg{ngY&eu4zisLV^R}?;w+Y~a?iQHd|iowka z_|H1K_2d>?31E-3|`dd!H=Ta$)Ni+vh2Qjer+ z)z$@6Yqa!gb$13xeT6?L)Ub-;|CMps7x~w^ZJL%bEQ02_P!@597MnHod8PZRJ&ud2 za*deQ+I0mGNHa|Vu9i;#}-psd+F^o)KA|tf7Ez5YgiQ;9ZXx#F^4o_oi6rOuVAS^ zMEzaLck6jzAIX27fz4gc)o5<(lJBBiRp4WFl31Cbe39<8bBUnMk`|q&ED)r~(9FJ? z5ZLvrk88~u!)c9qh^7+8Pm1&5;~y%!22%@1x}KyGR^ue{?J`8WD-$VKl_MHnPYhDN z9IS3h8kWZ>f`+R%P>3Z-!$155^*zBgqWf?P+!wZ1Hc!oW z_!Q?8?qS0NID|ye(%;9}JQr@6Q(EQ`c^(G4 zqSR2n-H_g9zL8XD*7L9vc=PZC_^)7Uz3i%4b`EwruG`5F609J}o{1q1vNj&C_wc=m ztWF$BuWy%`s{;-J`#YNKg z-`(=FK7x=lw9Esz+>A78LOJ_Bu{c&Uzw%$ilHxT_1xN#^G?Id3xy;&o(kb!%M~Od( z-J}@zETjR8s|mf;0epr?-W(pwqCIXMi*>2J#?cfcR@W;dFW86e>oB3ed&BZEZTNMT zMzWMK{hbMmzSd`le9YNc&3X?_Zv3Ut>hoD)S{%{A;UfWE#v`U^`V;A;ZwoZ5EXt;{ zKe6TFf()$mzDI-iCxB!~G;zrIf)Z0Y$%SQE;&PboM-}_bImKs3VV1`PqCLWkI`-fn)7LEg zYHuVSFJ23bL@uJ~x1{aK9?XFQ@^xANR8~$36ulNCg0w_Vpy|od_LLKzVI>_%EYhNM zaBH?5E->>#cz%+icL0{iKlLIy*Lq}H0oPFo`8@lAFXS98FCW8O(B~`Y=|>aE$J~m= zbh8snTVLbo_}DK4QZ(TjFL{TclgBrK$ayh^sWzVZ`2nG zR@ZVYOdzZ0e_A&oWdOCbJS2nbm9*BY>K1Aq$8JhS3&qoKDy@dDt$$Y>~DaKii^d+tM3w8Ss8gnIM27( z#CD*CN97gG|6A?cE2=56h2EkS3iUiY+4(qKH-ck5c4iJYcv4LwV?{@?W@G+H(CYVj z6=jBFilciHk4h3MmOpPux!G3&D8&Q=yenhGIrC$^n8Qf*I@kKE&i`GqHclAuu8)w7 z{ekgYMni1s^>mIm&n|xcS%XTxKy6I2M8AhM4s(!QP`4k|{Zj5{^fz`6Nr1S9y1bes zmbE3udEwsmZsUQQDUG96<@Y{dYbTXgf)fNsa`=#4u}^JZ6E^1*gJZ7T(WjU9zbmk^ zAEcYn9G(I0I>IT=q8?DRGhjvjAL7j+9_b?mk@+Z7oxVYld#DXAVdc*VMAf^1A zl))z3(>2kBwGQy)L;M3BAj@*BY(RPMxchv#q&`BO;80SqzsdL~eY8DX=7_vqCxl=7^~fjQS`i9lNX`$tURyH^hiAngzVC9%@y z%Y!^uhh?L$r6om0d?dX7soOGF%pXw2Wh;>1Qj{>m>+>ZG*|n}%FV0w(=yTm4 zld!HK{w0u4*@tybu;fL(s#%R@B%q2~(7m}@#=#FxVh((m)i|%*I|`z;ANWp=v#*?` z<(&)e8V&GLTvUCkv)n*(l|%hV=s%y3l=o7&Dn5!Pa&FE__eeYo%3i_RmmYyk&{m0;8h2L`K#m(ea08A? zVp)EV_)A12SM|!nsVa?Re?S|5ZpDubL`YPIJ)<*j6%ogJZ;2>NhxJ|ON!Tz7Uen2e z;E6F|oX7-sZIRyAiW^J<3rEkFTp39Eb=sq``>{F@(blT}6?{h|+ieTsaQuo!V2tmF z(;gWkKO&AoJrjFkv{HGI-J%(W5$abfSGZ2PKUffSsXpLATdr^w2bF6Mc8eY|<#O|H zwCzM)H|^J1B`ZI!S-UJ&4D&7D8X1mIfRZD8m!9SxVj<6Ky?Lkuqkl1FvY0YRFjT-S zt)puq_O}Dhcvaro3naBC%KEW(TP`XH>2DeWWzWW1ufMFgBo5MQUrzmCd^Bdn^}Z{~ zNZV4XS9PUPXE5WwKXdj=>3gtZkj7XmO{jFJy8YfdDE>hck| z#)&ZdX^#Y9gT%JdaD&+HxKWFRfx3@gKv8yST)31I2^D43*dMXh%cgr2B`oso4gB$X zHa4>X@(D?2hZ2+-F;4;*OO<0s7Oq5m!)kmbb&uAB4z&Zy)X(Sl8Qw#T^SvD@J}uUx zq+y-{_t;^(zb0NGq@Kh#JoYi@I)t>uX%0%`|JGDE2KH`_HR^fm6;3GK^bON;Ml>J1 z*dQ6vFqmoX~d}4d}2)NOGAN4PTr{%T8io#>c#uc3RPfN zw?BC|D6umLGQO`R@Ue(rS4yWK;(C|IdP2<6lk;-r;qSk&BmJVac7^yajX79J#_efN z*u5|0WPqBmY~YCNYim(G)P}MfV&i`e>0f6)2{JWNf1JM07$}pfn%cvyH4JfNh&=Y- z$#>(>8f>0daN$bCxR&}1A>bG<3emk4=y3YT9wYz<qj6e#wZ8BJ^!ujYVOlp3QnHv z_bHWtKCDp(PvhSMv9}w+L7VLe4x1Ca$l><@zbX&)Jn$DX_tLI{%S~d!!}rnVp!pa3h2H z{&U(FgZOW>cjegWBl-IE=r?LVo`rhqWi!h!Ou`9csyqyuZcTdjx%9dgEtB z_41V<5WA>&2XQvGyv}uI*>X*LRa?TlqqeGG4C@ti77`LelM|YLVtZc#)ZGa)+d?=Y zvR!S#huFmg`vx)a{TRr36axn*h4i>v)xmooAZIA>7_7uG*R=z=BFIBty+Ri9UCKGR zJcx}x^pyBLWKAwIi0|!q6FEK8Bg zj@aElaLV=Lwr{s!=+bF?-m&eteH^dcxQoB@B7ZWUves#-U9gIc-z+x-usO8jMh9p6zh^lp_ROO@0r5$b-)*l1UfEcd}Ux z2WMG+n4*kAci5xu>wYTKDQw)I5m{f2w@WkT?wzu^I@>L5>v%45&7Ln-qF@$Ww9 zL(aq-#im%Xoe<-j#`h9-gM4F@x!MlTx3nOLsuIF3^}=>)O{^wGzzw6{(g?^hxO<03k>CV`4u(Y0D0X@~n9!KMA0DhkHWJ!)X(vbvs*M{t zR%}`_wL>jMg?U28n4+wDcZxtzN>X9#@csX>1asa3LO@AAD&5&~c1fw~UntJRgmg*l zzb0jh4A7U-Gq?YzWcT%2fPg>70RtAyJ#kN!#Fbv!7Kaz@j`4WIhdjhuaZ9rNUt>GM zZ_^kQ2gn4lbbcM{*vvC4%!j{HSB>~MTr4|k5kRrjU|Aa{mblX=)7 zV#gS6=+Qyo1eMSie{bg|vAJFvg8ys$rv3iyys*sHN<&m3(XwGZrODff)7~ZS!%JItG6$XhaAl$uuV zM6-LAeWQ!%slQ^1RHm~X&^}=L0{bZ)zVL+JkyE{@TgCX~%&{Aht3F1Y1#aK9Y<3b* z+B;-$o`u|5w$A=fNMS_Zr>z2vDP0%&N3w8TRnAs%q}a#t{6jr8w(bMy@2O4{S?ae{ z-S~>=(=S2^ATJSkj%-}|%m2FGrJCTcZKSp@s?(D`XrK6(no3F_byw}tRf!+tGihV@ zOT4PfEAH&pTdbm$!S6H6yC`)t?}QpqEL&9v^{Yn05Pa-Hp13&36Na-BFLv3#5H=TJ zrmwkbg)m~pj`XtkV45G>Z^@3H7-hukGNJZy;y`$4&A^1yjj$s2wGH5(PPGH4mf)j- z%xc;9k|Or?-M_Y1yCHb>`F+d-$;n~K3p6V0?S2OT4zc;0IMN;VkN;^aK40d-0Px{a zD=%m-ZRSO?!RO8!C^DsJqePDFuoclh^5T~$azvOAueyX$d!GEgxDO>YCZZ0)up~o zM2R2iOvG4aAQ`9I#kN#dYXg21brH>y$3`tN-e%^q7YJY^2i`dkRIu$}Gywn1IR72a z4;Yyp1oOWqVE&!Got2uWy2ae@0*EcP6(y<@AG|;_4V(elG7c#iZW=9YwvNG}>i&Gtrr&VuWuE1dE`O~A*?@D~1-$=~Wv1Hk|r^#Lh z$G$wLVHxU5St7YQWT{6Q1_rO~6HsNlBh{27BX78foYk>pk2OFjSiqB;hkSKBdq)r5 zkoJ9K3J;!n0l`}@U}a!<#}Z2<54xsS+KW7BH2|hT6}qNTnr#(|cPL3mzCN@yXlEQp zc|r16;>DXdq~(cTIF87#y!~R)`WL4y;J1Ae(~H-FMVQa_@-=BT?F035-fY?`7gfyQ zt;#p4HD4eOP;dLDBht7t0+2FO`hX&~uSj_Mf*HK~gGJ@LbZV6|)GB4zBFpZYAbQPz z83{YJI6^;+vkYR*OQ%*=g8=r%T}^GwTdb}?>U|@6uM1=oA?E6ybuCW4zUcFwc>z+4 zRTg`QOSn|IlINk2)&s5{S=ZcVuQDJIe^C{S+nD-jUMH>k1Wgt^bl#jMnTwHZyf>U6 zIiw}Qru{r$Nd@*wUvNl8f@`IXqNf16v{FLR|KddCCPrKejDvCil<@q;G+ZINCdQ!Y zFQn5$Jp4Uo#b_A(oM2u~drX{GIyEiO?F8*RMNcK=<;X&nYq&vx40(*WPC0xEuF%1; zjG|s=-XBWE37Pp}RgCF`&(OS|%Qi4!-NW^C-0jZ;KsiJIkaYF`th;r*NO9JOF>Aqz z7HAYNEIpEod8tC^rU<0gA)a8=-Jnl}h9)%FnfIK@l*7hw^dRq3k)aXh#iu3tCFQUQ z{P5s++velhpGPC#al)YWeGwb}-2LE=a2zYF6w6^NkV3t*7vS|ntZA9jI0q_+tSMcE zZ>~D4#z^X1mftsi&n8MU_8^M`M@72+b7`+Y6PGakdJh~c(G^*SMybM_>yTl6I4Hk@vKXwi=mb%X6lb(V z&|ben%T&avpn$FsUEugBmwoR=KU!3W%HXZSN0^uEg2?P*Q~>PKYN7RVsm3H^4>^f~ zcI!G+$e}MeB-O)0d`wIynKokBDmXM#s62in@{h(6>qw@Ap3$Y)$JnI(=(R)_?tbBD zIfSg4(y?}#{W)yRO(~#=Gdluo&2<)EAo^S^VqwqD8S!YL6;` zRg>9LfLkMRL|amoNoie4nv8Q^YGF6rqigDV>lwSORr)dJPFz*wV_j(VY~RV_E)qprvwD(GHx%|*TBywl#jV5M ztMIx-7GL#l`b=vI_UMWhxI1g(b~4hw3t`@OHHf8|KOnd}|Ai5ekOZ$CyJDME&>d_ZYmmdNJHF z0PmQVY*4;p{L+NBnUB$8oawK35?OgVnjxrkw=K<9r%gyS_b@fWswp6Y!H<^&;rMG^5enfX(%9W@@ zXupKE&yvZOa>M!1CB`hS3 qmIuU$Ug|Fv>u#aU9*$U@XFzb|m$hj3d$G)(Hh>vh8C9I|y!L-x@wz|& literal 0 HcmV?d00001 diff --git a/web/public/icon-512x512.png b/web/public/icon-512x512.png new file mode 100644 index 0000000000000000000000000000000000000000..55a9c04be1a5441d0450b7acbb1347e8998d3671 GIT binary patch literal 11364 zcmZ8nc|6qX_kU)_mbJ~2wK9?-l{JiMVfav~ktK;KNp^+oX54P6gc?~&QH*3)$j-D# zDQRR&mWeRPmcf`|{66kY*YEp>7e3E<&Urs)d(P)`&W&S7O+*Bx1pxpekf{+K03`e; z5(x0YznFn7Z1~q2AJdb*00?bZ{y~8I52OIt3?QQeCjuXgbq95zt%ByJQZ^Cx&l)54 zY;}9Xd)q4g_}480*SD4#9hg&%q|;8(M{p_kKC;|B0|UtCf@yF@%yq z>4OO%ii|-T@;~4Um1Bwetn*Rw5%JmS!@t}A&iy)#M(O_A%4(KQz6!T7>SnuX!HhAT zhyJe5c9!P_zr$(SQ9P}G8-#a9H1TR9dXS+&cb%>fOP!9Rhga;B;}k^A{hFu?F`u~D zzV&17It-VLZbc^XNg4e3p(Xvq9T z=*+|W?PsXNREvoEG<}cAM%5bLeKNWgtb5|hLJ&UO@w>NxEO>A{^fX4l0yVO!d0)9a%Z5NCpoj-=qoZXC*H50O z2h#C`U_Td2*H|Elsz>M}cH$fz$&>`sBad0#+&6tW3(w^5SjrD>#L7Kz=(3<&3XoeQ zsh8^H=80nV{2!yn%>*?h%OrHO1R_4*98<{@LGh?BvL{u~O&j^OAJ0*Ms@AeDR7@zc zE8@{2DvL@s3&x4#pKCQLa-J52+br1Mme}>{8v=4uB={4s^w8958{=TT+3wR-&nP_&9?e%-_1}p$XyeC!R5;nNJyHWuz0p#a-zp( z7x$RKo#)4yL+0epGU?t3YCKJ&hMM6ANJEm9&$|^c-^|qf6?}5tg-jceg|1UpneLP3 z{Tdr|Wdct#hiu5#kcW9@LH_j=C?m#P$YCtS(2@q5)vkGhi~dIrZ?YumhXbbgIrX4YsH#x_-sex69PF-1FwKj!Dr$`!D5l zuiTW0Mf=xZF}^UDg@6uu*ClHYmFovf#A%X?a|Xk`AXV2Jq%o4Cag!Z+M||60he~kx zotA^toe>izO?a}KKVp*1n8)FTz$kD;4C0y&lclH7KI;qd%mqaiQ0Vt8*s(Lw9*_0j zc-WUT$8Q>j@DS>f!f;I8uDVC)7&n=d-R_2ScD~pYPkA;jW~&~YLO!wBzL*M9uBV(q zmvjo#-!ZrQFsqbYji_&_TC}2@l%wVH9b1FBv4Y?cTSDcH^d4d;)1r-CH@0bnGyhsXEFhJ2rR_f0ZPO#Kv&_%$s%Xhf|Pv zUJ`~BnTDm2HUEx`fW@ccl@U9|b=pnwHeq!#JQ-WSC`t!Myrh(c9DXujW89R3A4Pbp z)ELH5>Yba`+7%w%%J#aqN+Hi*DMc_i&)ss{-Oejm|AG&ZNf~L zeJ34>&`-nOA-6oLjA+L-)#8(ib0l^vvg5Wxh!h^tTPcwlI7D28x(Shu&f;zE|MbDQ z=>vX@G=#D-A@-rOjPsFgH&aqGI)Mxbz!96#Sy#sq+A%4a84ZYU^P#n9wTsoHhiOCZ zS$nB9)Le!|0^0wa&C4t4L!MbT)k43_CXp%MDaKc}88!9ezv?eG-Q@B>_{fJMsxp{V z^M1Zu>)gvqkaVNCYe@?u=(OEddL6ZqmMR4`yvw7enlw!`7a<)`T?&iP9g1+bkcR}O z$-D`8@EWXNTyuwV3nS80=wOb`iy2%h8{loP^w$`?iMzkz@wzUMs_nm9ke{F2 zqgCbB`CU5I7zlUawA9r zhi}v%m7p^ANNh zksHc3*eX_}x(ZOy^jD0XCgheN$;_1X-R+u3sYB@nQV?D{CU)FinxCFm*BnDeTb+?F zH1Q*TISWQ5bM`^x6B)yO zp=$qgehNR82pWX*%&&>)nYP^Gp~HUIpW=idh50yi2{q49y5kX33dh`(h|cn{^K<;k zOZT*hE<;0V&rbOfKS~#hP7;_W6VR^f#DKfW+Qb?la2pP>Aves6k!uvdm<;L6;k9K|VDRw;hBzVC$7#+}}1i3|E(l{=e zh$ck1Oqc|$bUgcOa4W;G^Cb2C>zHNX7w!BM#?S;I!cpeeICK`JoI0A$am@tgi1q}z zixAnakB>0SsOj89RZeS4LPO&Fc2pExMozA$-^j+DCQ}Hps8QTpdmE}oChQ3s%I+vl z^!5%{kdl64^CY?%aia|qK??O_21ngY#qEIw??Fjr8arL`b<+g{kkRn*7W!G z(wALKqk>|o>A{y{wUI)*A}wnWk*UI!3J7ll;P8y!z?(DQ-nEywXX*ZjjBOcKr!*a6 z%T9hi*!9!Is&ZzRF86T9S#{eHt=7Yrc6zU=440~z#UyEC*mBt-@=1I{OM&6XLSJ*I z51sSV&<1|5hG}7?;v^f%93@Eco`&S78UY7R4O_YDeZiGlE_&gY4sF8j$kJ6}tH@-4 zaKyeNA6GLhnyLD-KR`tMpHA7UO8EmZenEBqkoBA zI<%Cb5EfQaEetZoI)-MrUliBjRT39Ik?03P_N6;RAOQ{Q>&$9FSvCs z^*}24@Wk8OL`Gw#)kgioQlrgq@(mg9D0!9WdM6FKlOt)McP+8ouS6Iq&dco%`YcH` zF_BT9X%#DYfc5F@`w?NfmI70EGaVxAw2Taokmkr+ulf`d~~pJ{wZ z{9Efqbn4G*S)O7Kmjcr|2VR79UYx$L%Na<0UCh!Ey~Ho8&$i8qeX$Q6p0?A{)mXP= zXdgGOhVMhQA-CdPmN1BCRUY_6(rP~PqV-lh`&`3ZzjFEWcHPZ;*3$*V_=|NjQ*o!P;=|ug-XIO8jP(v*nHs86 zcLq;SILskIy>aZ*is41&ItwqWwmNLAJZ%BP6sQXCW%+hz?gb~tHLl3Q`Rq%!g2K$p z;CpJ#zrM$%n`n9u8%8D8Vz>r#dGHyN1#@>Z^yp5lvC(XLX+XV&hgEw{uN)?OzJjD&9-#F}RZc{H0BxcM+M_^ktv>Uo>!<56%=2UF+5ViagR+AmdU)$ItLk#D@y0Gg? zx!fq{C+_2e=}$A%UHHMekr!juM9I<9aCs>@5sNJd+lAWiIVfqR z^D>p*OfpR|x!spL!LnW0Hx>em^__VXMZ%28Y?wLVr2`DD6z1z0cN*)DFRdpUs-gBb z_UvXz(;F&GjDtS-zfK4UGYCF6J(+4leG}s$@^G1ff6pUxQsao6*nn3jlLh7FcaA(_ z(8g*iCq{ePKJQCJJhGl9*$7u4S+T+OhsrBQdzOjJ0&?7omBM=i_b&t$OTebPoGDTP z0>dlzlyawzee$Z_8II4%aVT+NGA@6sw}{3@wte{kj#Vm?wD>*wWgVAnw+HC-NMN&C ztz3N-esWTt< z0?odf7AJmBUe@T79p5p)uElleO{%{8Pk3dp`^pQm%2I6|(T0I+y2$1{aH(PO8C%j)m#DDiv}f(U(C4X!fM5t~2#wM;HFbYWjn zf;}H8rAJsG*D=>h)oMq53D6F8VLrWFub}X^v!f*OQ?3#WSZ} zzN|=KpFGq*{Y?E$s=9lqGZ46F?>Frz$U5{f#704uUCw%+*HH0U;lo?!HV@m7de*da zbb&C~GLG10%tt!y)KkjtQ*K|55i7R~zJs{f3px*cp@n%n`>+vB-Km^5OaJEfw1T9b z&OLj<1G&ZV_|l+hx>9AG1`F`=bgTmB}Sxl{YqXE25vX%oAnIVA?RVW3H!y}{gADDBnu+mH8cO} z7Fsh~4Wk6dA~kCdto1p=th6RRn19HEYCZB;xH5guA6XZJIP0c{K7vQ0^Il&Xmx8E2 z83B3W-9m+}2c|X<@9E9wGH9bQaMp;=gDr&EFSl37w)#Doe9Q>QEFN>)}IsO=Ox$?x`4zBDZQ2XgQFm*}Bk< zTu8<}4&f=r@E8Q>vs&|Lime#p%uAN93pmE#2w@v_)&cG|_CvGGhZ@A0XAInK>kMTH zFP0}$z<=5>cGm*e8yqv2`)mZt(CpJ@@5KuKZhaBs%_r3UWMV34>3Miaz{0!+c=|g0 zSirPncjZ#+i^aZDOtGBMqHK_$!9I;(ql(ck^ZurE_+&(BLaQE%T0@&SCjFtED4^c8 z@5v?#=(FLbbAHyo)wzr!>3J2v6ai_y4~xs>emn_P&BB**WtTeDcxZ0nLGw+IQH+jQKN)k`KX`^i`|UYXc5T%o|}DIxnTaz2ci7 zofeH0<6=U;Cr?Jn3>Dxr*}0YGp-wtrJL+5OI#46Em`~9o8Xn7iF##@sVG^1^uX#w(Bl;3hupTTg$3}Dm5Y3&l{da%P;S3f?|>|F$PmD&jw4l$2s zNv{Gs;OoRonof^3YuycsGlhXQT<3gN>6L~__1I7UpQuaSX^lkWWZ?gBaAv0==;bsM z%E&4N53D3bK{8GuI(wCJeYNd$!B2@W&FmP&BaAaBWFO-refk>o9ZW_r(vSPEQp~5v zLj0t-v{+p0p8sI&Q&yD)U3|KVtMCu?!h)8>|A%LJ;CJ9-$)r8iTTOcHDvElDW|IE@ zfO1mYxaO$o{}tsMk%0%c%52jUa53{o+r{SvL9&s;)ol1qU2&N>Z8HQRl97H4uAl!n zSMv)MP^H1%{{MC}XEy@T7(+oTxE%Q7S#r0L)cUm8gROi2J1C@Z1VQ(unLKve^q)~F zPL@Dd?SEMMxd{Tt*#BYqFdj(_NdF&}Lm9y5BJ=oDxDfo~sl%@}!XGgIXZPt8B-MXe z_UR?854&_ax0ZWu;avMHm}K<(G#=^B&hfs5wRzq0-ldKx(RsqruylUZUa@i;FRAwy zcfz!hMRcjR;ChOI)0!?`3+2*JEQldytyk&s=PnX|F?90zZd_XB@h0Ew+XdgW^Uz$ToWSu38H4Ik@_P3+ywi6*TS*KX|$dhF9%I&_i1oH5-ruzs`Z%(xoAS;M;1YdnO~P zZ&$;Rp@726tA$L%ks_G%ZNc6AwZ^}ea}(X|dK-voaynORhwJ8K4m$FXWRk-?SFDqs z@2CsxJAb;HuL$?2y+Y8j_g9fTfkXbN$854JOS@zjbFJiP*E0B_e-B*D|K z5QMnZBq9=`AV+5vn!E)f;*kI%R)@oGp8RcqpdYS{wE{p#bB?`&`mMdbHP9_6Z%o1`J`n`E?U0AE0}Ph&KD8%4UMu_Rsv_8iRvy;RdUbi z_6o|gL+}-pxO!7=X&Ko4{zyd2`F~>xmjaSlxyw4RX(h_8@a|kZ_iR~S=Kp*4ArMJD zFryH;BJVOMS{ZmaEL}AHZ8x{l_b|yhg7sqkR*|NEV)I1Ky{uC8Jz(P&Iy*Sl__r!f z2esG`U7sTG+ujYD+qmD(I59)!B&Gm^pI3XtANlIRt+AOCLl@paKX4##`jJCq=p?+ z0)>YMmR)AZ+V|E9p;>5A!g64TW$(kSoK&gjlnb!sO*+|l(d@TMqE%-Gt=xrxv4D@& z{;U5c_~@S@CCf-;4cHe~@(=EX_XY%^kr^bnXuBd9w^znCeRf%$A8`8CzlAiLhPRk5 ztCN5AGf}s_z@U`XaKP>EKbMLtrEMU zDrR8KOy-F0=#|T50>T~y|B(1Sj7!C*vH(P$G3+q2v z#u#cNkGx8)OU*em(pK4r74qD9wZm{PIE);R3F=++?YcL$A=UY0TN+%PGQK`b96yTD z{RiJ0#&L!aisXFKQx&!UdegOKfK|dtlG9vH9Uz>vmVv8=vKC**y%$jQn}fZ?B`Ki# z!43WbBt7Q{zunJza~J1g5!C0o+6nNhdWcvj(iSmk`1$^(6|#8wgJGW@9cfnVY>YYZ z-|m^FD=!cZ!;PdFxY$i-eY^Zg!Rm@OGQ9bxE;DL{VWiHInqZ)XZ~td3ANcUR)0U5P zONYBjov>Fs&lMgF5EfjX1@IyII?>cu2yk6Osu~xHiuI0bIMM!W!-byze3{xw{doRu zx}z{ia4vyA=#_-5w{`!_ORa6k$}c*>0gw|7e@pAG6{$dW6mzE-3M+~k)0X$U5zAxU z^jjsza?JToqkcL}Br*RS-nvq>f-gy+%XXsdzXNFNWH{(Cwg#-pO;|Y-e6 zr{>wPIbf*u zj<;~{?mYIMkv~i`O{ov7k(Ya^j56=uk%)29In&CpbrB{SI|Kf};sZgg{qb>g! zD7bjQ`y_RQs@NKBRl8#I9ecFC)pAqG>yK(Vwf<49S!n3(N~VXRkGEET>mM`R=}v6> zxQU7IVKMsuqrFp2{4D7j=0u;R)#v`PgJL-<$$+teP)mE8OI$GyrhBSDm9XAt@j`#w zAFj>$=G8u*O{i@H^?83NGd%Y(H0V{ooZA1;;cNCW^x;lm+`!v{KVlArAOny4EqU_N zDc|c0{%k*_uU#?m0%r#htk;uH9e;Q{?uwIm6E$9$hy01{lA3KQDTTiVynwymCTzY7 z4kF7Q8Mq=#gW=0*22=b4vLPG}z5#HCwi}DiWqpus9!(Ap1 zGe4pyhH#pIYgJT-@V8AO{NeV8GB7btRfEVoE(Q8IjtLV~==Za64rIz^o4L!?OV3F* zsG_u{2WUvCkx%=^c;>?&f)QkjC=5FGvP7Y*k2`bIU9_udEg~U$JpCb`$3Q25m+$d= zZ0N=ofd`wywBbfh=9e_id2LdBl*mRj9HKzudO9w&Z zze0CbSezHKl?mL;7B(jrU+0jt(mChaNZk^0{_yeyyH~3MJB#!QW`0e8n^SIZb4rB1 zkJ@PQ&zZfxyEWJ!&B?)|5TTzD-eC^EZ#31Qvr6GM4u6OcthM!Fyr$&f zA(JeA&%vVYu%W1+0PB zt(v`P=qp>iFx0R1ixeplA!f4NsQY;s1vfK?ilwNhZaQyLg0f#31k8^L(En!S7?bZt zJEd{%Upu8h=cn1+LaRg#Eh-z&X^9|gManSjhC68gwh59}8t0ywsk|c9-R7H~o8eZm>9<$ja@~$C2x?5e#CGUw z?ypjFKgZ*dpb}M-USJR5U47wJzB1cDZ3B*#~UW$#Epi*zq6 zZL1){o$c>5n(Jp_3p_rX#PZE-(_rz+jn*^Jzhdygtl3)_$3 z`)Qx6p$56(?6Sj38S{>2TL|WaV5agxaxi@lp^_2g$i`A7;Meg~VW^=)lRiV6u4W2T z&r_>uscWHz&k7Mo(uRVDPa;MUI>tmiT1ByzuPr*IH$w?&&ATg_`^FT{w+mr?Bc(m# zA}Rqq>cHcaG$k+7(_3z?6#?SC@V>NV8+;`}2Mv%Sqn#r28G(o7jFQfcY z0VC*Cws7H*DS;@otA}Mo-tySPCAcdNPgtBGw;U`*6$ogn@c+ zc!C?hD(?fS#T#)H3Egh}#a4Z4NJM=)HjKQHz6Nf(2iXduJnR={m7uVTE}dAVU~c>? zL=Fmji)&zA$Q(*R%1fo<3n}48k)l z7AlFYDB{}18wr$)Wm2}v!98~`g_zNI)88{JO3~40te;&i2$(nb2ihQ9d=W~dT^$d$zibI7$hgPus-C#Hiv5qniZ_cv$glM~! zvV?9FLxv#5jG6@DiJO{>U5d*SHv;sax`~T$&pxQGt8bejJ~`v>@oEH|PK73)FoKRW z>mqhaS_po;k%B?{H~&04SL2*MqyZ^`WMsQh6Pm0yU`Hro%$qk~he!O9Q@sZ|}4S)&lO{V0gG^Eg|cy?_+qR zN&(suE++e95QDeKXssfB3A5Wj60Jr}JiergSMBF#k&QY@G2_|`kGB*JU^qzroJd^N)>=#eewwbcSTKG92J z$F?|ETG4$<-F*ku-by^P3ZBiP-sD4MwMG+L89@i}*uSVPjFT24`($bwX74JGaAA2w_BWsap`?W`-{EHC~S(%rPvo!=5F!Kr|SxL`WQ1+Rh$Rg&JK^i zr=|KrcB*s{c=WJ~anEw3&^+oGW(ymRvO@?5;Ri?qc}$#{+@2!a1WpMp)e(~3G-*%& zLJgx8<+R}EBx)xLHZ2ClQ!1<_yEc>wBuQfW&D4C3JnI|0L`$`R+;|GZr-XfjDbPq< zWRz!_&MmI28J>xM%>jv=Jks8T{4oW|*pG(FY+q$454mviSp%W7?r_6POr6eY^=NJ= zgtuwi*a6Q_2C4@0C7P+y^m#ja@&c7yi{tqM)a0YhVof1W&CIfLt+2Yb>Mc>IqzoqwkY3(KOO-%g|@j7CHV-z9L zf1DmtXTwpCs_{~STGfrK#C?#HLf+_~C4S=td@-mO%z{v8$50#&ONhQ(bFk z%?Z|iE?+b#zL(@CGtN5RumKy=3KSqb4)$mpard3{fVTWIp#%EoSjr zU-e;?o^M;~LXJ!X#WSYhQI4^lGWk}Tjh-aT&Dy(IJA>EZZqGb_mDi=;!m5NT)|T5g zjvpY59Mp2Ubq(WmXKCY-WeBEcec;7*~_}dcF Y@%eV&2c}(Icx)Iz#z&3v4-)?RKT}rqVgLXD literal 0 HcmV?d00001 diff --git a/web/public/icon-72x72.png b/web/public/icon-72x72.png new file mode 100644 index 0000000000000000000000000000000000000000..2f159ce4bb1417b9b36fa7ed12eacbace1b03b0e GIT binary patch literal 1309 zcmV+&1>*XNP)wqcBMu4k;s+znpD~WCg^YWZ<6N( z@G5YmRwMWL#DPvM;0GJCLCVd6k8H2g7@ z(ig{wk&Qbl5B}Gq{`-1oS8zEY1s#`^v6rCb#LSkDD-Zt9K7al6oq}uUCMHOD+)I!o z*kk3J1LX%kX(1GR1`@AqFFjr^%w65p+s>~-4SnxuIa5qbMhgX4)Zu+{K?Z*3veG`r z&Bi2`E-NYNx|I?yUMql9e;xMAAq*kO55@c-p5NcUg>j3n&gclkW;$+VGL)DKS3$I z%@2$T@*&9Rq9@00LAl5m>5K~+zDOIbU^sRQIv6=n%($SQ$Wx7s3mTqk$O?92ICcwq z+IYIdv0Km#;|VjzUO{fcOlK8k?}HH>dj+{ES1m}k4;aC*S5SMgpj%9>L3HdCBrYb6 zu8oaKf>uY;q?$_KEVgq`YZfBzs37_DFs#gY-y5hh+H_-f@J$rAetZY9(3~&3^2> zAh#NoGlI-AfbX$~-q2ew!-5+pb*DVyma%OM9p}U(YEDWw;K`WoQE32og4+=!Rbr5w zE~6_4oh0+=itLu5Ile!5*$ z^183~lG2Rr;Fh^(0M7uMrFtoAaP%VqWu@E5V*=%Gc}@N&?~(Ve(8nhFn85!41yz3h TOrL_%00000NkvXXu0mjfP|j@> literal 0 HcmV?d00001 diff --git a/web/public/icon-96x96.png b/web/public/icon-96x96.png new file mode 100644 index 0000000000000000000000000000000000000000..e4966c05288f6b0114674b23009d018e604c77aa GIT binary patch literal 1694 zcmV;P24VS$P)l!y^O$_F1zDk?%7iNFXVBhze3(^1C?D@TMf%2CVwOmlv*oLyY?-aF@> zyZ1i(oPB<Rhp8&c8 z6M*-Cvn0=1buQ!O+=7f7ej>07clj2W4)hGNf;0x00~{bd`~=KSy%4~iz&E6qJ;2By zZ2&g`s|@sHlAr^48yFO%0bmkvjO=j~csOwUS>LFxn5@#F?(E)yO8`TF9r(j`;MTyQ z7wr-J;}|eJY2)7q{Dr@q0>&j}{K>$%q%Gh8G8s6{w(+NBq>HHwvBgwd#vh$u`9(Po zj5Te1nOi?u{P;P*X=5*D)zxfIx`ip=i1scj&8h>Q|=+QPv8y;tBSyqFruyG5Foeu*> zL-(OD=zf^=EPS!s%<&E%fz?egZUNl(2=uudf|{;N!;094Y^`W{Q@LwcVaeLk4Hhxp z+^FwZ?SH^C%c1vO(G0Fp0AW^C*$;!q$1}Vp0S-jE z3xLP5#KP6l8ou^}>W=ft*Kp17>Wr^J0J@wt1-i+Fi6tgKXTIV44?+J?)f-=v0N<5$ z{!$)m)|l83t>N>R#;d=h1BT7eV|+~l2zBKI5U*luJlzpYcMxx{v+| zJ!?zX8!jSAW)~AcT*R$&@-)m|0=*}xoa#{5)6yPB;#`1TZ7C@L#D8MUZjFs;?FTnCb0rb4z z9b%>X0<;u9|Fus$%iPP(@2f9|OE^7#z6&;OFI}E`xx4^%3o1XCpMTdrO?`t1P>TU% z5>3b8XW{DN^~=ctIY+7N`0ULnzfS)5Q)Vizy=JE3lNF*fhmWp zT!2Vy3sh{Zc5(qCu~!5*gaL8^B5^P<<#-i!98k9)o&bk_g|=Txm#&sO9T*1)?SYE$ zNQ`h%JOMH=5*E(o0yrQ*qQ0M@-vYE7dkIG+^jm;~#=40k#>N ziik?+w*c#nO~yqf^jm<%#-^jA68bGby|D$EsDyqCaA`rNZ<3KPp}zujE=eZ6C?EPO zK#LP@DWSgtEOWv!EA&@@@lLoVhJFfgxoe^lLH1I%PUxoqpB3|tmQA#+6Z$E@EMoy0 zA2&nOrs(CKIpqx{ab%U$_g|5?f^zlBaVxEJ&kqIzG?WOki+EMs{%HAzr@1tk3{g@7 z$QJIo05!=4=~W%3nhQ`xn5vFI?OcGeOf|k$K`uZ^B-XP>mjWmeBzZwBasf&*Gm`NO z?t)mG#pD7MWmn{@zd(fAIJ@IYwBzv;*(_(yS=z9vK!n$09Wtko*J2r82{1ryJeLy> z+35D>*a8&nppx$$S2-QpQl7}%R*Vzyon=~#uLQ`qF0MSqiQYUjvLUsnsY)tEq6lu$ zYWyqm#rT}Eq$|WWcNj7L6?tRw1P)gtaTX64HGY8zQ}Yximm#)z%!=`^NaEu{I$9U5 zd^`DLN<5BE;4deQ=Z%RVLXCR!`^ImVd^=qL7z})gUnxq41TLX=Tz@g+FXs*?lX(`R z+#HW)bYg8{kOqMM8BFLrFi0Ef1)b(Jx4VH6L7Gv^o3m`?B+!KTz|E|98PR3LA4Z;` zYJJpI_5sr?N;i@=l=D}eglJ-Uv+xqgIjmFX)GhD{Ivs+=1!lAInYYCSbxe6Q_Dk9h zP5|@)#sH1LP6IutHed}frKERqPVhexL8#Ur>LuBd^4yluwgeQ4F=dw*nFy02f6Hg` oKlzS4-sCs(Tj_~)Mk6}NzZ&8uuoQ&H_5c6?07*qoM6N<$f<-$P_y7O^ literal 0 HcmV?d00001 diff --git a/web/public/manifest.json b/web/public/manifest.json new file mode 100644 index 0000000000..a9f1f32436 --- /dev/null +++ b/web/public/manifest.json @@ -0,0 +1,58 @@ +{ + "name": "Dify", + "short_name": "Dify", + "description": "Build Production Ready Agentic AI Solutions", + "icons": [ + { + "src": "/icon-192x192.png", + "sizes": "192x192", + "type": "image/png", + "purpose": "any" + }, + { + "src": "/icon-192x192.png", + "sizes": "192x192", + "type": "image/png", + "purpose": "maskable" + }, + { + "src": "/icon-256x256.png", + "sizes": "256x256", + "type": "image/png" + }, + { + "src": "/icon-384x384.png", + "sizes": "384x384", + "type": "image/png" + }, + { + "src": "/icon-512x512.png", + "sizes": "512x512", + "type": "image/png" + } + ], + "theme_color": "#1C64F2", + "background_color": "#ffffff", + "display": "standalone", + "scope": "/", + "start_url": "/", + "orientation": "portrait-primary", + "categories": ["productivity", "utilities", "developer"], + "lang": "en-US", + "dir": "ltr", + "prefer_related_applications": false, + "shortcuts": [ + { + "name": "Apps", + "short_name": "Apps", + "url": "/apps", + "icons": [{ "src": "/icon-96x96.png", "sizes": "96x96" }] + }, + { + "name": "Datasets", + "short_name": "Datasets", + "url": "/datasets", + "icons": [{ "src": "/icon-96x96.png", "sizes": "96x96" }] + } + ] +} \ No newline at end of file diff --git a/web/public/sw.js b/web/public/sw.js new file mode 100644 index 0000000000..fd0d1166ca --- /dev/null +++ b/web/public/sw.js @@ -0,0 +1 @@ +if(!self.define){let e,s={};const a=(a,c)=>(a=new URL(a+".js",c).href,s[a]||new Promise(s=>{if("document"in self){const e=document.createElement("script");e.src=a,e.onload=s,document.head.appendChild(e)}else e=a,importScripts(a),s()}).then(()=>{let e=s[a];if(!e)throw new Error(`Module ${a} didn’t register its module`);return e}));self.define=(c,i)=>{const t=e||("document"in self?document.currentScript.src:"")||location.href;if(s[t])return;let n={};const r=e=>a(e,t),d={module:{uri:t},exports:n,require:r};s[t]=Promise.all(c.map(e=>d[e]||r(e))).then(e=>(i(...e),n))}}define(["./workbox-c05e7c83"],function(e){"use strict";importScripts("fallback-hxi5kegOl0PxtKhvDL_OX.js"),self.skipWaiting(),e.clientsClaim(),e.precacheAndRoute([{url:"/_next/app-build-manifest.json",revision:"e80949a4220e442866c83d989e958ae8"},{url:"/_next/static/chunks/05417924-77747cddee4d64f3.js",revision:"77747cddee4d64f3"},{url:"/_next/static/chunks/0b8e744a-e08dc785b2890dce.js",revision:"e08dc785b2890dce"},{url:"/_next/static/chunks/10227.2d6ce21b588b309f.js",revision:"2d6ce21b588b309f"},{url:"/_next/static/chunks/10404.d8efffe9b2fd4e0b.js",revision:"d8efffe9b2fd4e0b"},{url:"/_next/static/chunks/10600.4009af2369131bbf.js",revision:"4009af2369131bbf"},{url:"/_next/static/chunks/1093.5cfb52a48d3a96ae.js",revision:"5cfb52a48d3a96ae"},{url:"/_next/static/chunks/10973.9e10593aba66fc5c.js",revision:"9e10593aba66fc5c"},{url:"/_next/static/chunks/11216.13da4d102d204873.js",revision:"13da4d102d204873"},{url:"/_next/static/chunks/11270.a084bc48f9f032cc.js",revision:"a084bc48f9f032cc"},{url:"/_next/static/chunks/11307.364f3be8c5e998d0.js",revision:"364f3be8c5e998d0"},{url:"/_next/static/chunks/11413.fda7315bfdc36501.js",revision:"fda7315bfdc36501"},{url:"/_next/static/chunks/11529.42d5c37f670458ae.js",revision:"42d5c37f670458ae"},{url:"/_next/static/chunks/11865.516c4e568f1889be.js",revision:"516c4e568f1889be"},{url:"/_next/static/chunks/11917.ed6c454d6e630d86.js",revision:"ed6c454d6e630d86"},{url:"/_next/static/chunks/11940.6d97e23b9fab9add.js",revision:"6d97e23b9fab9add"},{url:"/_next/static/chunks/11949.590f8f677688a503.js",revision:"590f8f677688a503"},{url:"/_next/static/chunks/12125.92522667557fbbc2.js",revision:"92522667557fbbc2"},{url:"/_next/static/chunks/12276.da8644143fa9cc7f.js",revision:"da8644143fa9cc7f"},{url:"/_next/static/chunks/12365.108b2ebacf69576e.js",revision:"108b2ebacf69576e"},{url:"/_next/static/chunks/12421.6e80538a9f3cc1f2.js",revision:"6e80538a9f3cc1f2"},{url:"/_next/static/chunks/12524.ab059c0d47639851.js",revision:"ab059c0d47639851"},{url:"/_next/static/chunks/12625.67a653e933316864.js",revision:"67a653e933316864"},{url:"/_next/static/chunks/12631.10189fe2d597f55c.js",revision:"10189fe2d597f55c"},{url:"/_next/static/chunks/12706.4bdab3af288f10dc.js",revision:"4bdab3af288f10dc"},{url:"/_next/static/chunks/13025.46d60a4b94267957.js",revision:"46d60a4b94267957"},{url:"/_next/static/chunks/13056.f04bf48e4085b0d7.js",revision:"f04bf48e4085b0d7"},{url:"/_next/static/chunks/13072-5fc2f3d78982929e.js",revision:"5fc2f3d78982929e"},{url:"/_next/static/chunks/13110.5f8f979ca5e89dbc.js",revision:"5f8f979ca5e89dbc"},{url:"/_next/static/chunks/13149.67512e40a8990eef.js",revision:"67512e40a8990eef"},{url:"/_next/static/chunks/13211.64ab2c05050165a5.js",revision:"64ab2c05050165a5"},{url:"/_next/static/chunks/1326.14821b0f82cce223.js",revision:"14821b0f82cce223"},{url:"/_next/static/chunks/13269.8c3c6c48ddfc4989.js",revision:"8c3c6c48ddfc4989"},{url:"/_next/static/chunks/13271.1719276f2b86517b.js",revision:"1719276f2b86517b"},{url:"/_next/static/chunks/13360.fed9636864ee1394.js",revision:"fed9636864ee1394"},{url:"/_next/static/chunks/1343.99f3d3e1c273209b.js",revision:"99f3d3e1c273209b"},{url:"/_next/static/chunks/13526.0c697aa31858202f.js",revision:"0c697aa31858202f"},{url:"/_next/static/chunks/13611.4125ff9aa9e3d2fe.js",revision:"4125ff9aa9e3d2fe"},{url:"/_next/static/chunks/1379.be1a4d4dff4a20fd.js",revision:"be1a4d4dff4a20fd"},{url:"/_next/static/chunks/13857.c1b4faa54529c447.js",revision:"c1b4faa54529c447"},{url:"/_next/static/chunks/14043.63fb1ce74ba07ae8.js",revision:"63fb1ce74ba07ae8"},{url:"/_next/static/chunks/14564.cf799d3cbf98c087.js",revision:"cf799d3cbf98c087"},{url:"/_next/static/chunks/14619.e810b9d39980679d.js",revision:"e810b9d39980679d"},{url:"/_next/static/chunks/14665-34366d9806029de7.js",revision:"34366d9806029de7"},{url:"/_next/static/chunks/14683.90184754d0828bc9.js",revision:"90184754d0828bc9"},{url:"/_next/static/chunks/1471f7b3-f03c3b85e0555a0c.js",revision:"f03c3b85e0555a0c"},{url:"/_next/static/chunks/14963.ba92d743e1658e77.js",revision:"ba92d743e1658e77"},{url:"/_next/static/chunks/15041-31e6cb0e412468f0.js",revision:"31e6cb0e412468f0"},{url:"/_next/static/chunks/15377.c01fca90d1b21cad.js",revision:"c01fca90d1b21cad"},{url:"/_next/static/chunks/15405-f7c1619c9397a2ce.js",revision:"f7c1619c9397a2ce"},{url:"/_next/static/chunks/15448-18679861f0708c4e.js",revision:"18679861f0708c4e"},{url:"/_next/static/chunks/15606.af6f735a1c187dfc.js",revision:"af6f735a1c187dfc"},{url:"/_next/static/chunks/15721.016f333dcec9a52b.js",revision:"016f333dcec9a52b"},{url:"/_next/static/chunks/15849.6f06cb0f5cc392a3.js",revision:"6f06cb0f5cc392a3"},{url:"/_next/static/chunks/16379.868d0198c64b2724.js",revision:"868d0198c64b2724"},{url:"/_next/static/chunks/16399.6993c168f19369b1.js",revision:"6993c168f19369b1"},{url:"/_next/static/chunks/16486-8f2115a5e48b9dbc.js",revision:"8f2115a5e48b9dbc"},{url:"/_next/static/chunks/16511.63c987cddefd5020.js",revision:"63c987cddefd5020"},{url:"/_next/static/chunks/16546.899bcbd2209a4f76.js",revision:"899bcbd2209a4f76"},{url:"/_next/static/chunks/16563.4350b22478980bdf.js",revision:"4350b22478980bdf"},{url:"/_next/static/chunks/16604.c70557135c7f1ba6.js",revision:"c70557135c7f1ba6"},{url:"/_next/static/chunks/1668-91c9c25cc107181c.js",revision:"91c9c25cc107181c"},{url:"/_next/static/chunks/16711.4200241536dea973.js",revision:"4200241536dea973"},{url:"/_next/static/chunks/16898.a93e193378633099.js",revision:"a93e193378633099"},{url:"/_next/static/chunks/16971-1e1adb5405775f69.js",revision:"1e1adb5405775f69"},{url:"/_next/static/chunks/17025-8680e9021847923a.js",revision:"8680e9021847923a"},{url:"/_next/static/chunks/17041.14d694ac4e17f8f1.js",revision:"14d694ac4e17f8f1"},{url:"/_next/static/chunks/17231.6c64588b9cdd5c37.js",revision:"6c64588b9cdd5c37"},{url:"/_next/static/chunks/17376.d1e5510fb31e2c5c.js",revision:"d1e5510fb31e2c5c"},{url:"/_next/static/chunks/17557.eb9456ab57c1be50.js",revision:"eb9456ab57c1be50"},{url:"/_next/static/chunks/17751.918e5506df4b6950.js",revision:"918e5506df4b6950"},{url:"/_next/static/chunks/17771.acf53180d5e0111d.js",revision:"acf53180d5e0111d"},{url:"/_next/static/chunks/17855.66c5723d6a63df48.js",revision:"66c5723d6a63df48"},{url:"/_next/static/chunks/18000.ff1bd737b49f2c6c.js",revision:"ff1bd737b49f2c6c"},{url:"/_next/static/chunks/1802.7724e056289b15ae.js",revision:"7724e056289b15ae"},{url:"/_next/static/chunks/18067-c62a1f4f368a1121.js",revision:"c62a1f4f368a1121"},{url:"/_next/static/chunks/18467.cb08e501f2e3656d.js",revision:"cb08e501f2e3656d"},{url:"/_next/static/chunks/18863.8b28f5bfdb95d62c.js",revision:"8b28f5bfdb95d62c"},{url:"/_next/static/chunks/1898.89ba096be8637f07.js",revision:"89ba096be8637f07"},{url:"/_next/static/chunks/19296.d0643d9b5fe2eb41.js",revision:"d0643d9b5fe2eb41"},{url:"/_next/static/chunks/19326.5a7bfa108daf8280.js",revision:"5a7bfa108daf8280"},{url:"/_next/static/chunks/19405.826697a06fefcc57.js",revision:"826697a06fefcc57"},{url:"/_next/static/chunks/19790-c730088b8700d86e.js",revision:"c730088b8700d86e"},{url:"/_next/static/chunks/1ae6eb87-e6808a74cc7c700b.js",revision:"e6808a74cc7c700b"},{url:"/_next/static/chunks/20338.d10bc44a79634e16.js",revision:"d10bc44a79634e16"},{url:"/_next/static/chunks/20343.a73888eda3407330.js",revision:"a73888eda3407330"},{url:"/_next/static/chunks/20441.e156d233f7104b23.js",revision:"e156d233f7104b23"},{url:"/_next/static/chunks/20481.e04a45aa20b1976b.js",revision:"e04a45aa20b1976b"},{url:"/_next/static/chunks/20fdb61e.fbe1e616fa3d5495.js",revision:"fbe1e616fa3d5495"},{url:"/_next/static/chunks/21139.604a0b031308b62f.js",revision:"604a0b031308b62f"},{url:"/_next/static/chunks/21151.5c221cee5224c079.js",revision:"5c221cee5224c079"},{url:"/_next/static/chunks/21288.231a35b4e731cc9e.js",revision:"231a35b4e731cc9e"},{url:"/_next/static/chunks/21529.f87a17e08ed68b42.js",revision:"f87a17e08ed68b42"},{url:"/_next/static/chunks/21541.8902a74e4e69a6f1.js",revision:"8902a74e4e69a6f1"},{url:"/_next/static/chunks/2166.9848798428477e40.js",revision:"9848798428477e40"},{url:"/_next/static/chunks/21742-8072a0f644e9e8b3.js",revision:"8072a0f644e9e8b3"},{url:"/_next/static/chunks/2193.3bcbb3d0d023d9fe.js",revision:"3bcbb3d0d023d9fe"},{url:"/_next/static/chunks/21957.995aaef85cea119f.js",revision:"995aaef85cea119f"},{url:"/_next/static/chunks/22057.318686aa0e043a97.js",revision:"318686aa0e043a97"},{url:"/_next/static/chunks/22420-85b7a3cb6da6b29a.js",revision:"85b7a3cb6da6b29a"},{url:"/_next/static/chunks/22705.a8fb712c28c6bd77.js",revision:"a8fb712c28c6bd77"},{url:"/_next/static/chunks/22707.269fe334721e204e.js",revision:"269fe334721e204e"},{url:"/_next/static/chunks/23037.1772492ec76f98c7.js",revision:"1772492ec76f98c7"},{url:"/_next/static/chunks/23086.158757f15234834f.js",revision:"158757f15234834f"},{url:"/_next/static/chunks/23183.594e16513821b96c.js",revision:"594e16513821b96c"},{url:"/_next/static/chunks/23327.2a1db1d88c37a3e7.js",revision:"2a1db1d88c37a3e7"},{url:"/_next/static/chunks/23727.8a43501019bbde3c.js",revision:"8a43501019bbde3c"},{url:"/_next/static/chunks/23810-5c3dc746d77522a3.js",revision:"5c3dc746d77522a3"},{url:"/_next/static/chunks/24029.d30d06f4e6743bb2.js",revision:"d30d06f4e6743bb2"},{url:"/_next/static/chunks/2410.90bdf846234fe966.js",revision:"90bdf846234fe966"},{url:"/_next/static/chunks/24137-04a4765327fbdf71.js",revision:"04a4765327fbdf71"},{url:"/_next/static/chunks/24138.cbe8bccb36e3cce3.js",revision:"cbe8bccb36e3cce3"},{url:"/_next/static/chunks/24295.831d9fbde821e5b7.js",revision:"831d9fbde821e5b7"},{url:"/_next/static/chunks/24326.88b8564b7d9c2fc8.js",revision:"88b8564b7d9c2fc8"},{url:"/_next/static/chunks/24339-746c6445879fdddd.js",revision:"746c6445879fdddd"},{url:"/_next/static/chunks/24376.9c0fec1b5db36cae.js",revision:"9c0fec1b5db36cae"},{url:"/_next/static/chunks/24383.c7259ef158b876b5.js",revision:"c7259ef158b876b5"},{url:"/_next/static/chunks/24519.dce38e90251a8c25.js",revision:"dce38e90251a8c25"},{url:"/_next/static/chunks/24586-dd949d961c3ad33e.js",revision:"dd949d961c3ad33e"},{url:"/_next/static/chunks/24640-a41e87f26eaf5810.js",revision:"a41e87f26eaf5810"},{url:"/_next/static/chunks/24706.37c97d8ff9e47bd5.js",revision:"37c97d8ff9e47bd5"},{url:"/_next/static/chunks/24891.75a9aabdbc282338.js",revision:"75a9aabdbc282338"},{url:"/_next/static/chunks/24961.28f927feadfb31f5.js",revision:"28f927feadfb31f5"},{url:"/_next/static/chunks/25143.9a595a9dd94eb0a4.js",revision:"9a595a9dd94eb0a4"},{url:"/_next/static/chunks/25225.3fe24e6e47ca9db1.js",revision:"3fe24e6e47ca9db1"},{url:"/_next/static/chunks/25359.7d020c628154c814.js",revision:"7d020c628154c814"},{url:"/_next/static/chunks/25446-38ad86c587624f05.js",revision:"38ad86c587624f05"},{url:"/_next/static/chunks/25577.b375e938f6748ba0.js",revision:"b375e938f6748ba0"},{url:"/_next/static/chunks/25924-18679861f0708c4e.js",revision:"18679861f0708c4e"},{url:"/_next/static/chunks/26094.04829760397a1cd4.js",revision:"04829760397a1cd4"},{url:"/_next/static/chunks/26135-7c712a292ebd319c.js",revision:"7c712a292ebd319c"},{url:"/_next/static/chunks/26184.2f42d1b6a292d2ff.js",revision:"2f42d1b6a292d2ff"},{url:"/_next/static/chunks/26437-9a746fa27b1ab62d.js",revision:"9a746fa27b1ab62d"},{url:"/_next/static/chunks/2697-c61a87392df1c2bf.js",revision:"c61a87392df1c2bf"},{url:"/_next/static/chunks/27005.5c57cea3023af627.js",revision:"5c57cea3023af627"},{url:"/_next/static/chunks/27359.06e2f2d24d2ea8a8.js",revision:"06e2f2d24d2ea8a8"},{url:"/_next/static/chunks/27655-bf3fc8fe88e99aab.js",revision:"bf3fc8fe88e99aab"},{url:"/_next/static/chunks/27775.9a2c44d9bae18710.js",revision:"9a2c44d9bae18710"},{url:"/_next/static/chunks/27895.eae86f4cb32708f8.js",revision:"eae86f4cb32708f8"},{url:"/_next/static/chunks/27896-d8fccb53e302d9b8.js",revision:"d8fccb53e302d9b8"},{url:"/_next/static/chunks/28816.87ad8dce35181118.js",revision:"87ad8dce35181118"},{url:"/_next/static/chunks/29282.ebb929b1c842a24c.js",revision:"ebb929b1c842a24c"},{url:"/_next/static/chunks/29521.70184382916a2a6c.js",revision:"70184382916a2a6c"},{url:"/_next/static/chunks/29643.39ba5e394ff0bf2f.js",revision:"39ba5e394ff0bf2f"},{url:"/_next/static/chunks/2972.0232841c02104ceb.js",revision:"0232841c02104ceb"},{url:"/_next/static/chunks/30342.3e77ffbd5fef8bce.js",revision:"3e77ffbd5fef8bce"},{url:"/_next/static/chunks/30420.6e7d463d167dfbe2.js",revision:"6e7d463d167dfbe2"},{url:"/_next/static/chunks/30433.fc3e6abc2a147fcc.js",revision:"fc3e6abc2a147fcc"},{url:"/_next/static/chunks/30489.679b6d0eab2b69db.js",revision:"679b6d0eab2b69db"},{url:"/_next/static/chunks/30518.e026de6e5681fe07.js",revision:"e026de6e5681fe07"},{url:"/_next/static/chunks/30581.4499b5c9e8b1496c.js",revision:"4499b5c9e8b1496c"},{url:"/_next/static/chunks/30606.e63c845883cf578e.js",revision:"e63c845883cf578e"},{url:"/_next/static/chunks/30855.c62d4ee9866f5ed2.js",revision:"c62d4ee9866f5ed2"},{url:"/_next/static/chunks/30884-c95fd8a60ed0f565.js",revision:"c95fd8a60ed0f565"},{url:"/_next/static/chunks/30917.2da5a0ca0a161bbc.js",revision:"2da5a0ca0a161bbc"},{url:"/_next/static/chunks/31012.e5da378b15186382.js",revision:"e5da378b15186382"},{url:"/_next/static/chunks/31131.9a4b6e4f84e780c1.js",revision:"9a4b6e4f84e780c1"},{url:"/_next/static/chunks/31213.5cc3c2b8c52e447e.js",revision:"5cc3c2b8c52e447e"},{url:"/_next/static/chunks/31275-242bf62ca715c85b.js",revision:"242bf62ca715c85b"},{url:"/_next/static/chunks/31535.ec58b1214e87450c.js",revision:"ec58b1214e87450c"},{url:"/_next/static/chunks/32012.225bc4defd6f0a8f.js",revision:"225bc4defd6f0a8f"},{url:"/_next/static/chunks/32142.6ea9edc962f64509.js",revision:"6ea9edc962f64509"},{url:"/_next/static/chunks/32151.f69211736897e24b.js",revision:"f69211736897e24b"},{url:"/_next/static/chunks/32212.0552b8c89385bff4.js",revision:"0552b8c89385bff4"},{url:"/_next/static/chunks/32597.90b63b654b6b77f2.js",revision:"90b63b654b6b77f2"},{url:"/_next/static/chunks/32700.2d573741844545d2.js",revision:"2d573741844545d2"},{url:"/_next/static/chunks/32824.62795491d427890d.js",revision:"62795491d427890d"},{url:"/_next/static/chunks/33202.d90bd1b6fe3017bb.js",revision:"d90bd1b6fe3017bb"},{url:"/_next/static/chunks/33223.e32a3b2c6d598095.js",revision:"e32a3b2c6d598095"},{url:"/_next/static/chunks/33335.58c56dab39d85e97.js",revision:"58c56dab39d85e97"},{url:"/_next/static/chunks/33364.e2d58a67b8b48f39.js",revision:"e2d58a67b8b48f39"},{url:"/_next/static/chunks/33452.3213f3b04cde471b.js",revision:"3213f3b04cde471b"},{url:"/_next/static/chunks/33775.2ebbc8baea1023fc.js",revision:"2ebbc8baea1023fc"},{url:"/_next/static/chunks/33787.1f4e3fc4dce6d462.js",revision:"1f4e3fc4dce6d462"},{url:"/_next/static/chunks/34227.46e192cb73272dbb.js",revision:"46e192cb73272dbb"},{url:"/_next/static/chunks/34269-bf30d999b8b357ec.js",revision:"bf30d999b8b357ec"},{url:"/_next/static/chunks/34293.db0463f901a4e9d5.js",revision:"db0463f901a4e9d5"},{url:"/_next/static/chunks/34331.7208a1e7f1f88940.js",revision:"7208a1e7f1f88940"},{url:"/_next/static/chunks/34421.b0749a4047e8a98c.js",revision:"b0749a4047e8a98c"},{url:"/_next/static/chunks/34475.9be5637a0d474525.js",revision:"9be5637a0d474525"},{url:"/_next/static/chunks/34720.50a7f31aeb3f0d8e.js",revision:"50a7f31aeb3f0d8e"},{url:"/_next/static/chunks/34822.78d89e0ebaaa8cc6.js",revision:"78d89e0ebaaa8cc6"},{url:"/_next/static/chunks/34831.2b6e51f7ad0f1795.js",revision:"2b6e51f7ad0f1795"},{url:"/_next/static/chunks/34999.5d0ce7aa20ba0b83.js",revision:"5d0ce7aa20ba0b83"},{url:"/_next/static/chunks/35025.633ea8ca18d5f7de.js",revision:"633ea8ca18d5f7de"},{url:"/_next/static/chunks/35032.3a6c90f900419479.js",revision:"3a6c90f900419479"},{url:"/_next/static/chunks/35131.9b12c8a1947bc9e3.js",revision:"9b12c8a1947bc9e3"},{url:"/_next/static/chunks/35258.6bbcff2f7b7f9d06.js",revision:"6bbcff2f7b7f9d06"},{url:"/_next/static/chunks/35341.41f9204df71b96e3.js",revision:"41f9204df71b96e3"},{url:"/_next/static/chunks/35403.52f152abeeb5d623.js",revision:"52f152abeeb5d623"},{url:"/_next/static/chunks/3543-18679861f0708c4e.js",revision:"18679861f0708c4e"},{url:"/_next/static/chunks/35608.173410ef6c2ea27c.js",revision:"173410ef6c2ea27c"},{url:"/_next/static/chunks/35805.0c1ed9416b2bb3ee.js",revision:"0c1ed9416b2bb3ee"},{url:"/_next/static/chunks/35906-3e1eb7c7b780e16b.js",revision:"3e1eb7c7b780e16b"},{url:"/_next/static/chunks/36049.de560aa5e8d60f15.js",revision:"de560aa5e8d60f15"},{url:"/_next/static/chunks/36065.f3ffe4465d8a5817.js",revision:"f3ffe4465d8a5817"},{url:"/_next/static/chunks/36111.aac397f5903ff82c.js",revision:"aac397f5903ff82c"},{url:"/_next/static/chunks/36193.d084a34a68ab6873.js",revision:"d084a34a68ab6873"},{url:"/_next/static/chunks/36355.d8aec79e654937be.js",revision:"d8aec79e654937be"},{url:"/_next/static/chunks/36367-3aa9be18288264c0.js",revision:"3aa9be18288264c0"},{url:"/_next/static/chunks/36451.62e5e5932cb1ab19.js",revision:"62e5e5932cb1ab19"},{url:"/_next/static/chunks/36601.5a2457f93e152d85.js",revision:"5a2457f93e152d85"},{url:"/_next/static/chunks/36625.0a4a070381562d94.js",revision:"0a4a070381562d94"},{url:"/_next/static/chunks/36891.953b4d0ece6ada6f.js",revision:"953b4d0ece6ada6f"},{url:"/_next/static/chunks/37023.f07ac40c45201d4b.js",revision:"f07ac40c45201d4b"},{url:"/_next/static/chunks/37047-dede650dd0543bac.js",revision:"dede650dd0543bac"},{url:"/_next/static/chunks/37267.f57739536ef97b97.js",revision:"f57739536ef97b97"},{url:"/_next/static/chunks/37370.e7f30e73b6e77e5e.js",revision:"e7f30e73b6e77e5e"},{url:"/_next/static/chunks/37384.81c666dd9d2608b2.js",revision:"81c666dd9d2608b2"},{url:"/_next/static/chunks/37425.de736ee7bbef1a87.js",revision:"de736ee7bbef1a87"},{url:"/_next/static/chunks/37783.54c381528fca245b.js",revision:"54c381528fca245b"},{url:"/_next/static/chunks/38098.7bf64933931b6c3b.js",revision:"7bf64933931b6c3b"},{url:"/_next/static/chunks/38100.283b7c10302b6b21.js",revision:"283b7c10302b6b21"},{url:"/_next/static/chunks/38215.70ed9a3ebfbf88e6.js",revision:"70ed9a3ebfbf88e6"},{url:"/_next/static/chunks/38482-4129e273a4d3c782.js",revision:"4129e273a4d3c782"},{url:"/_next/static/chunks/38927.3119fd93e954e0ba.js",revision:"3119fd93e954e0ba"},{url:"/_next/static/chunks/38939.d6f5b345c4310296.js",revision:"d6f5b345c4310296"},{url:"/_next/static/chunks/39015.c2761b8e9159368d.js",revision:"c2761b8e9159368d"},{url:"/_next/static/chunks/39132.fc3380b03520116a.js",revision:"fc3380b03520116a"},{url:"/_next/static/chunks/39324.c141dcdbaf763a1f.js",revision:"c141dcdbaf763a1f"},{url:"/_next/static/chunks/3948.c1790e815f59fe15.js",revision:"c1790e815f59fe15"},{url:"/_next/static/chunks/39650.b28500edba896c3c.js",revision:"b28500edba896c3c"},{url:"/_next/static/chunks/39687.333e92331282ab94.js",revision:"333e92331282ab94"},{url:"/_next/static/chunks/39709.5d9960b5195030e7.js",revision:"5d9960b5195030e7"},{url:"/_next/static/chunks/39731.ee5661db1ed8a20d.js",revision:"ee5661db1ed8a20d"},{url:"/_next/static/chunks/39794.e9a979f7368ad3e5.js",revision:"e9a979f7368ad3e5"},{url:"/_next/static/chunks/39800.594c1845160ece20.js",revision:"594c1845160ece20"},{url:"/_next/static/chunks/39917.30526a7e8337a626.js",revision:"30526a7e8337a626"},{url:"/_next/static/chunks/3995.3ec55001172cdcb8.js",revision:"3ec55001172cdcb8"},{url:"/_next/static/chunks/39952.968ae90199fc5394.js",revision:"968ae90199fc5394"},{url:"/_next/static/chunks/39961.310dcbff7dfbcfe2.js",revision:"310dcbff7dfbcfe2"},{url:"/_next/static/chunks/4007.3777594ecf312bcb.js",revision:"3777594ecf312bcb"},{url:"/_next/static/chunks/40356.437355e9e3e89f89.js",revision:"437355e9e3e89f89"},{url:"/_next/static/chunks/4041.a38bef8c2bad6e81.js",revision:"a38bef8c2bad6e81"},{url:"/_next/static/chunks/40448-c62a1f4f368a1121.js",revision:"c62a1f4f368a1121"},{url:"/_next/static/chunks/40513.dee5882a5fb41218.js",revision:"dee5882a5fb41218"},{url:"/_next/static/chunks/40838.d7397ef66a3d6cf4.js",revision:"d7397ef66a3d6cf4"},{url:"/_next/static/chunks/40853.583057bcca92d245.js",revision:"583057bcca92d245"},{url:"/_next/static/chunks/410.6e3584848520c962.js",revision:"6e3584848520c962"},{url:"/_next/static/chunks/41039.7dc257fa65dd4709.js",revision:"7dc257fa65dd4709"},{url:"/_next/static/chunks/41059.be96e4ef5bebc2f2.js",revision:"be96e4ef5bebc2f2"},{url:"/_next/static/chunks/4106.9e6e17d57fdaa661.js",revision:"9e6e17d57fdaa661"},{url:"/_next/static/chunks/41193.0eb1d071eeb97fb0.js",revision:"0eb1d071eeb97fb0"},{url:"/_next/static/chunks/41220.8e755f7aafbf7980.js",revision:"8e755f7aafbf7980"},{url:"/_next/static/chunks/41314.bfaf95227838bcda.js",revision:"bfaf95227838bcda"},{url:"/_next/static/chunks/41347.763641d44414255a.js",revision:"763641d44414255a"},{url:"/_next/static/chunks/41497.7878f2f171ce8c5e.js",revision:"7878f2f171ce8c5e"},{url:"/_next/static/chunks/4151.8bbf8de7b1d955b5.js",revision:"8bbf8de7b1d955b5"},{url:"/_next/static/chunks/41563.ea5487abc22d830f.js",revision:"ea5487abc22d830f"},{url:"/_next/static/chunks/41597.1b844e749172cf14.js",revision:"1b844e749172cf14"},{url:"/_next/static/chunks/41697.dc5c0858a7ffa805.js",revision:"dc5c0858a7ffa805"},{url:"/_next/static/chunks/41793.978b2e9a60904a6e.js",revision:"978b2e9a60904a6e"},{url:"/_next/static/chunks/41851.bb64c4159f92755a.js",revision:"bb64c4159f92755a"},{url:"/_next/static/chunks/42054.a89c82b1a3fa50df.js",revision:"a89c82b1a3fa50df"},{url:"/_next/static/chunks/42217-3333b08e7803809b.js",revision:"3333b08e7803809b"},{url:"/_next/static/chunks/42343.b8526852ffb2eee0.js",revision:"b8526852ffb2eee0"},{url:"/_next/static/chunks/42353.9ff1f9a9d1ee6af7.js",revision:"9ff1f9a9d1ee6af7"},{url:"/_next/static/chunks/4249.757c4d44d2633ab4.js",revision:"757c4d44d2633ab4"},{url:"/_next/static/chunks/42530.3d6a9fb83aebc252.js",revision:"3d6a9fb83aebc252"},{url:"/_next/static/chunks/42949.5f6a69ec4a94818a.js",revision:"5f6a69ec4a94818a"},{url:"/_next/static/chunks/43051.90f3188002014a08.js",revision:"90f3188002014a08"},{url:"/_next/static/chunks/43054.ba17f57097d13614.js",revision:"ba17f57097d13614"},{url:"/_next/static/chunks/43196.11f65b652442c156.js",revision:"11f65b652442c156"},{url:"/_next/static/chunks/43243.cf4c66a0d9e3360e.js",revision:"cf4c66a0d9e3360e"},{url:"/_next/static/chunks/43252.5a107f2cfaf48ae3.js",revision:"5a107f2cfaf48ae3"},{url:"/_next/static/chunks/43628.bdc0377a0c1b2eb3.js",revision:"bdc0377a0c1b2eb3"},{url:"/_next/static/chunks/43700.84f1ca94a6d3340c.js",revision:"84f1ca94a6d3340c"},{url:"/_next/static/chunks/43769.0a99560cdc099772.js",revision:"0a99560cdc099772"},{url:"/_next/static/chunks/43772-ad054deaaf5fcd86.js",revision:"ad054deaaf5fcd86"},{url:"/_next/static/chunks/43862-0dbeea318fbfad11.js",revision:"0dbeea318fbfad11"},{url:"/_next/static/chunks/43878.1ff4836f0809ff68.js",revision:"1ff4836f0809ff68"},{url:"/_next/static/chunks/43894.7ffe482bd50e35c9.js",revision:"7ffe482bd50e35c9"},{url:"/_next/static/chunks/44123.b52d19519dfe1e42.js",revision:"b52d19519dfe1e42"},{url:"/_next/static/chunks/44144.5b91cc042fa44be2.js",revision:"5b91cc042fa44be2"},{url:"/_next/static/chunks/44248-1dfb4ac6f8d1fd07.js",revision:"1dfb4ac6f8d1fd07"},{url:"/_next/static/chunks/44254.2860794b0c0e1ef6.js",revision:"2860794b0c0e1ef6"},{url:"/_next/static/chunks/44381.9c8e16a6424adc8d.js",revision:"9c8e16a6424adc8d"},{url:"/_next/static/chunks/44531.8095bfe48023089b.js",revision:"8095bfe48023089b"},{url:"/_next/static/chunks/44572.ba41ecd79b41f525.js",revision:"ba41ecd79b41f525"},{url:"/_next/static/chunks/44610.49a93268c33d2651.js",revision:"49a93268c33d2651"},{url:"/_next/static/chunks/44640.52150bf827afcfb1.js",revision:"52150bf827afcfb1"},{url:"/_next/static/chunks/44991.2ed748436f014361.js",revision:"2ed748436f014361"},{url:"/_next/static/chunks/45191-d7de90a08075e8ee.js",revision:"d7de90a08075e8ee"},{url:"/_next/static/chunks/45318.19c3faad5c34d0d4.js",revision:"19c3faad5c34d0d4"},{url:"/_next/static/chunks/4556.de93eae2a91704e6.js",revision:"de93eae2a91704e6"},{url:"/_next/static/chunks/45888.daaede4f205e7e3d.js",revision:"daaede4f205e7e3d"},{url:"/_next/static/chunks/46277.4fc1f8adbdb50757.js",revision:"4fc1f8adbdb50757"},{url:"/_next/static/chunks/46300.34c56977efb12f86.js",revision:"34c56977efb12f86"},{url:"/_next/static/chunks/46914-8124a0324764302a.js",revision:"8124a0324764302a"},{url:"/_next/static/chunks/46985.f65c6455a96a19e6.js",revision:"f65c6455a96a19e6"},{url:"/_next/static/chunks/47499.cfa056dc05b3a960.js",revision:"cfa056dc05b3a960"},{url:"/_next/static/chunks/47681.3da8ce224d044119.js",revision:"3da8ce224d044119"},{url:"/_next/static/chunks/4779.896f41085b382d47.js",revision:"896f41085b382d47"},{url:"/_next/static/chunks/48140.584aaae48be3979a.js",revision:"584aaae48be3979a"},{url:"/_next/static/chunks/4850.64274c81a39b03d1.js",revision:"64274c81a39b03d1"},{url:"/_next/static/chunks/48567.f511415090809ef3.js",revision:"f511415090809ef3"},{url:"/_next/static/chunks/48723.3f8685fa8d9d547b.js",revision:"3f8685fa8d9d547b"},{url:"/_next/static/chunks/48760-b1141e9b031478d0.js",revision:"b1141e9b031478d0"},{url:"/_next/static/chunks/49219.a03a09318b60e813.js",revision:"a03a09318b60e813"},{url:"/_next/static/chunks/49249.9884136090ff649c.js",revision:"9884136090ff649c"},{url:"/_next/static/chunks/49268.b66911ab1b57fbc4.js",revision:"b66911ab1b57fbc4"},{url:"/_next/static/chunks/49285-bfa5a6b056f9921c.js",revision:"bfa5a6b056f9921c"},{url:"/_next/static/chunks/49324.bba4e3304305d3ee.js",revision:"bba4e3304305d3ee"},{url:"/_next/static/chunks/49470-e9617c6ff33ab30a.js",revision:"e9617c6ff33ab30a"},{url:"/_next/static/chunks/49719.b138ee24d17a3e8f.js",revision:"b138ee24d17a3e8f"},{url:"/_next/static/chunks/49935.117c4410fd1ce266.js",revision:"117c4410fd1ce266"},{url:"/_next/static/chunks/50154.1baa4e51196259e1.js",revision:"1baa4e51196259e1"},{url:"/_next/static/chunks/50164.c0312ac5c2784d2d.js",revision:"c0312ac5c2784d2d"},{url:"/_next/static/chunks/50189.6a6bd8d90f39c18c.js",revision:"6a6bd8d90f39c18c"},{url:"/_next/static/chunks/50301.179abf80291119dc.js",revision:"179abf80291119dc"},{url:"/_next/static/chunks/50363.654c0b10fe592ea6.js",revision:"654c0b10fe592ea6"},{url:"/_next/static/chunks/50479.071f732a65c46a70.js",revision:"071f732a65c46a70"},{url:"/_next/static/chunks/50555.ac4f1d68aaa9abb2.js",revision:"ac4f1d68aaa9abb2"},{url:"/_next/static/chunks/5071.eab2b8999165a153.js",revision:"eab2b8999165a153"},{url:"/_next/static/chunks/50795.a0e5bfc3f3d35b08.js",revision:"a0e5bfc3f3d35b08"},{url:"/_next/static/chunks/5091-60557a86e8a10330.js",revision:"60557a86e8a10330"},{url:"/_next/static/chunks/51087.98ad2e5a0075fdbe.js",revision:"98ad2e5a0075fdbe"},{url:"/_next/static/chunks/51206-26a3e2d474c87801.js",revision:"26a3e2d474c87801"},{url:"/_next/static/chunks/51226.3b789a36213ff16e.js",revision:"3b789a36213ff16e"},{url:"/_next/static/chunks/51240.9f0d5e47af611ae1.js",revision:"9f0d5e47af611ae1"},{url:"/_next/static/chunks/51321.76896859772ef958.js",revision:"76896859772ef958"},{url:"/_next/static/chunks/51410.a0f292d3c5f0cd9d.js",revision:"a0f292d3c5f0cd9d"},{url:"/_next/static/chunks/51726.094238d6785a8db0.js",revision:"094238d6785a8db0"},{url:"/_next/static/chunks/51864.3b61e4db819af663.js",revision:"3b61e4db819af663"},{url:"/_next/static/chunks/52055-15759d93ea8646f3.js",revision:"15759d93ea8646f3"},{url:"/_next/static/chunks/52380.6efeb54e2c326954.js",revision:"6efeb54e2c326954"},{url:"/_next/static/chunks/52468-3904482f4a92d8ff.js",revision:"3904482f4a92d8ff"},{url:"/_next/static/chunks/52863.a00298832c59de13.js",revision:"a00298832c59de13"},{url:"/_next/static/chunks/52922.93ebbabf09c6dc3c.js",revision:"93ebbabf09c6dc3c"},{url:"/_next/static/chunks/53284.7df6341d1515790f.js",revision:"7df6341d1515790f"},{url:"/_next/static/chunks/5335.3667d8346284401e.js",revision:"3667d8346284401e"},{url:"/_next/static/chunks/53375.a3c0d7a7288fb098.js",revision:"a3c0d7a7288fb098"},{url:"/_next/static/chunks/53450-1ada1109fbef544e.js",revision:"1ada1109fbef544e"},{url:"/_next/static/chunks/53452-c626edba51d827fd.js",revision:"c626edba51d827fd"},{url:"/_next/static/chunks/53509.f4071f7c08666834.js",revision:"f4071f7c08666834"},{url:"/_next/static/chunks/53529.5ad8bd2056fab944.js",revision:"5ad8bd2056fab944"},{url:"/_next/static/chunks/53727.aac93a096d1c8b77.js",revision:"aac93a096d1c8b77"},{url:"/_next/static/chunks/53731.b0718b98d2fb7ace.js",revision:"b0718b98d2fb7ace"},{url:"/_next/static/chunks/53789.02faf0e472ffa080.js",revision:"02faf0e472ffa080"},{url:"/_next/static/chunks/53999.81f148444ca61363.js",revision:"81f148444ca61363"},{url:"/_next/static/chunks/54207.bf7b4fb0f03da3d3.js",revision:"bf7b4fb0f03da3d3"},{url:"/_next/static/chunks/54216.3484b423a081b94e.js",revision:"3484b423a081b94e"},{url:"/_next/static/chunks/54221.0710202ae5dd437a.js",revision:"0710202ae5dd437a"},{url:"/_next/static/chunks/54243-336bbeee5c5b0fe8.js",revision:"336bbeee5c5b0fe8"},{url:"/_next/static/chunks/54381-6c5ec10a9bd34460.js",revision:"6c5ec10a9bd34460"},{url:"/_next/static/chunks/54528.702c70de8d3c007a.js",revision:"702c70de8d3c007a"},{url:"/_next/static/chunks/54577.ebeed3b0480030b6.js",revision:"ebeed3b0480030b6"},{url:"/_next/static/chunks/54958.f2db089e27ae839f.js",revision:"f2db089e27ae839f"},{url:"/_next/static/chunks/55129-47a156913c168ed4.js",revision:"47a156913c168ed4"},{url:"/_next/static/chunks/55199.f0358dbcd265e462.js",revision:"f0358dbcd265e462"},{url:"/_next/static/chunks/55218.bbf7b8037aa79f47.js",revision:"bbf7b8037aa79f47"},{url:"/_next/static/chunks/55649.b679f89ce00cebdc.js",revision:"b679f89ce00cebdc"},{url:"/_next/static/chunks/55761.f464c5c7a13f52f7.js",revision:"f464c5c7a13f52f7"},{url:"/_next/static/chunks/55771-803ee2c5e9f67875.js",revision:"803ee2c5e9f67875"},{url:"/_next/static/chunks/55863.3d64aef8864730dd.js",revision:"3d64aef8864730dd"},{url:"/_next/static/chunks/55886.f14b944beb4b9c76.js",revision:"f14b944beb4b9c76"},{url:"/_next/static/chunks/56079.df991a66e5e82f36.js",revision:"df991a66e5e82f36"},{url:"/_next/static/chunks/56292.16ed1d33114e698d.js",revision:"16ed1d33114e698d"},{url:"/_next/static/chunks/56350.0d59bb87ccfdb49c.js",revision:"0d59bb87ccfdb49c"},{url:"/_next/static/chunks/56490.63df43b48e5cb8fb.js",revision:"63df43b48e5cb8fb"},{url:"/_next/static/chunks/56494.f3f39a14916d4071.js",revision:"f3f39a14916d4071"},{url:"/_next/static/chunks/56529.51a5596d26d2e9b4.js",revision:"51a5596d26d2e9b4"},{url:"/_next/static/chunks/56539.752d077815d0d842.js",revision:"752d077815d0d842"},{url:"/_next/static/chunks/56585.2e4765683a5d0b90.js",revision:"2e4765683a5d0b90"},{url:"/_next/static/chunks/56608.88ca9fcfa0f48c48.js",revision:"88ca9fcfa0f48c48"},{url:"/_next/static/chunks/56725.a88db5a174bf2480.js",revision:"a88db5a174bf2480"},{url:"/_next/static/chunks/569.934a671a66be70c2.js",revision:"934a671a66be70c2"},{url:"/_next/static/chunks/56929.9c792022cb9f8cae.js",revision:"9c792022cb9f8cae"},{url:"/_next/static/chunks/57242.b0ed0af096a5a4cb.js",revision:"b0ed0af096a5a4cb"},{url:"/_next/static/chunks/573.ce956e00f24a272a.js",revision:"ce956e00f24a272a"},{url:"/_next/static/chunks/57361-38d45fa15ae9671d.js",revision:"38d45fa15ae9671d"},{url:"/_next/static/chunks/57391-e2ba7688f865c022.js",revision:"e2ba7688f865c022"},{url:"/_next/static/chunks/57641.3cf81a9d9e0c8531.js",revision:"3cf81a9d9e0c8531"},{url:"/_next/static/chunks/57714.2cf011027f4e94e5.js",revision:"2cf011027f4e94e5"},{url:"/_next/static/chunks/57871.555f6e7b903e71ef.js",revision:"555f6e7b903e71ef"},{url:"/_next/static/chunks/58310-e0c52408c1b894e6.js",revision:"e0c52408c1b894e6"},{url:"/_next/static/chunks/58347.9eb304955957e772.js",revision:"9eb304955957e772"},{url:"/_next/static/chunks/58407.617fafc36fdde431.js",revision:"617fafc36fdde431"},{url:"/_next/static/chunks/58486.c57e4f33e2c0c881.js",revision:"c57e4f33e2c0c881"},{url:"/_next/static/chunks/58503.78fbfc752d8d5b92.js",revision:"78fbfc752d8d5b92"},{url:"/_next/static/chunks/58567-7051f47a4c3df6bf.js",revision:"7051f47a4c3df6bf"},{url:"/_next/static/chunks/58748-3aa9be18288264c0.js",revision:"3aa9be18288264c0"},{url:"/_next/static/chunks/58753.cb93a00a4a5e0506.js",revision:"cb93a00a4a5e0506"},{url:"/_next/static/chunks/58781-18679861f0708c4e.js",revision:"18679861f0708c4e"},{url:"/_next/static/chunks/58800.8093642e74e578f3.js",revision:"8093642e74e578f3"},{url:"/_next/static/chunks/58826.ead36a86c535fbb7.js",revision:"ead36a86c535fbb7"},{url:"/_next/static/chunks/58854.cccd3dda7f227bbb.js",revision:"cccd3dda7f227bbb"},{url:"/_next/static/chunks/58986.a2656e58b0456a1b.js",revision:"a2656e58b0456a1b"},{url:"/_next/static/chunks/59474-98edcfc228e1c4ad.js",revision:"98edcfc228e1c4ad"},{url:"/_next/static/chunks/59583-422a987558783a3e.js",revision:"422a987558783a3e"},{url:"/_next/static/chunks/59683.b08ae85d9c384446.js",revision:"b08ae85d9c384446"},{url:"/_next/static/chunks/59754.8fb27cde3fadf5c4.js",revision:"8fb27cde3fadf5c4"},{url:"/_next/static/chunks/59831.fe6fa243d2ea9936.js",revision:"fe6fa243d2ea9936"},{url:"/_next/static/chunks/59909.62a5307678b5dbc0.js",revision:"62a5307678b5dbc0"},{url:"/_next/static/chunks/60188.42a57a537cb12097.js",revision:"42a57a537cb12097"},{url:"/_next/static/chunks/60291.77aa277599bafefd.js",revision:"77aa277599bafefd"},{url:"/_next/static/chunks/60996.373d14abb85bdd97.js",revision:"373d14abb85bdd97"},{url:"/_next/static/chunks/61068.6c10151d2f552ed6.js",revision:"6c10151d2f552ed6"},{url:"/_next/static/chunks/61264.f9fbb94e766302ea.js",revision:"f9fbb94e766302ea"},{url:"/_next/static/chunks/61319.4779278253bccfec.js",revision:"4779278253bccfec"},{url:"/_next/static/chunks/61396.a832f878a8d7d632.js",revision:"a832f878a8d7d632"},{url:"/_next/static/chunks/61422.d2e722b65b74f6e8.js",revision:"d2e722b65b74f6e8"},{url:"/_next/static/chunks/61442.bb64b9345864470e.js",revision:"bb64b9345864470e"},{url:"/_next/static/chunks/61604.69848dcb2d10163a.js",revision:"69848dcb2d10163a"},{url:"/_next/static/chunks/61785.2425015034d24170.js",revision:"2425015034d24170"},{url:"/_next/static/chunks/61821.31f026144a674559.js",revision:"31f026144a674559"},{url:"/_next/static/chunks/61848.b93ee821037f5825.js",revision:"b93ee821037f5825"},{url:"/_next/static/chunks/62051.eecbdd70c71a2500.js",revision:"eecbdd70c71a2500"},{url:"/_next/static/chunks/62068-333e92331282ab94.js",revision:"333e92331282ab94"},{url:"/_next/static/chunks/62483.8fd42015b6a24944.js",revision:"8fd42015b6a24944"},{url:"/_next/static/chunks/62512.96f95fc564a6b5ac.js",revision:"96f95fc564a6b5ac"},{url:"/_next/static/chunks/62613.770cb2d077e05599.js",revision:"770cb2d077e05599"},{url:"/_next/static/chunks/62738.374eee8039340e7e.js",revision:"374eee8039340e7e"},{url:"/_next/static/chunks/62955.2015c34009cdeb03.js",revision:"2015c34009cdeb03"},{url:"/_next/static/chunks/63360-1b35e94b9bc6b4b0.js",revision:"1b35e94b9bc6b4b0"},{url:"/_next/static/chunks/63482.b800e30a7519ef3c.js",revision:"b800e30a7519ef3c"},{url:"/_next/static/chunks/6352-c423a858ce858a06.js",revision:"c423a858ce858a06"},{url:"/_next/static/chunks/63847.e3f69be7969555f1.js",revision:"e3f69be7969555f1"},{url:"/_next/static/chunks/64196.517fc50cebd880fd.js",revision:"517fc50cebd880fd"},{url:"/_next/static/chunks/64209.5911d1a542fa7722.js",revision:"5911d1a542fa7722"},{url:"/_next/static/chunks/64296.8315b157513c2e8e.js",revision:"8315b157513c2e8e"},{url:"/_next/static/chunks/64301.97f0e2cff064cfe7.js",revision:"97f0e2cff064cfe7"},{url:"/_next/static/chunks/64419.4d5c93959464aa08.js",revision:"4d5c93959464aa08"},{url:"/_next/static/chunks/64577.96fa6510f117de8b.js",revision:"96fa6510f117de8b"},{url:"/_next/static/chunks/64598.ff88174c3fca859e.js",revision:"ff88174c3fca859e"},{url:"/_next/static/chunks/64655.856a66759092f3bd.js",revision:"856a66759092f3bd"},{url:"/_next/static/chunks/65140.16149fd00b724548.js",revision:"16149fd00b724548"},{url:"/_next/static/chunks/6516-f9734f6965877053.js",revision:"f9734f6965877053"},{url:"/_next/static/chunks/65246.0f3691d4ea7250f5.js",revision:"0f3691d4ea7250f5"},{url:"/_next/static/chunks/65457.174baa3ccbdfce60.js",revision:"174baa3ccbdfce60"},{url:"/_next/static/chunks/65934.a43c9ede551420e5.js",revision:"a43c9ede551420e5"},{url:"/_next/static/chunks/66185.272964edc75d712e.js",revision:"272964edc75d712e"},{url:"/_next/static/chunks/66229.2c90a9d8e082cacb.js",revision:"2c90a9d8e082cacb"},{url:"/_next/static/chunks/66246.54f600f5bdc5ae35.js",revision:"54f600f5bdc5ae35"},{url:"/_next/static/chunks/66282.747f460d20f8587b.js",revision:"747f460d20f8587b"},{url:"/_next/static/chunks/66293.83bb9e464c9a610c.js",revision:"83bb9e464c9a610c"},{url:"/_next/static/chunks/66551.a674b7157b76896b.js",revision:"a674b7157b76896b"},{url:"/_next/static/chunks/66669.fbf288f69e91d623.js",revision:"fbf288f69e91d623"},{url:"/_next/static/chunks/6671.7c624e6256c1b248.js",revision:"7c624e6256c1b248"},{url:"/_next/static/chunks/66892.5b8e3e238ba7c48f.js",revision:"5b8e3e238ba7c48f"},{url:"/_next/static/chunks/66912.89ef7185a6826031.js",revision:"89ef7185a6826031"},{url:"/_next/static/chunks/66933.4be197eb9b1bf28f.js",revision:"4be197eb9b1bf28f"},{url:"/_next/static/chunks/67187.b0e2cfbf950c7820.js",revision:"b0e2cfbf950c7820"},{url:"/_next/static/chunks/67238.355074b5cf5de0a0.js",revision:"355074b5cf5de0a0"},{url:"/_next/static/chunks/67558.02357faf5b097fd7.js",revision:"02357faf5b097fd7"},{url:"/_next/static/chunks/67636.c8c7013b8093c234.js",revision:"c8c7013b8093c234"},{url:"/_next/static/chunks/67735.f398171c8bcc48e4.js",revision:"f398171c8bcc48e4"},{url:"/_next/static/chunks/67736.d389ab6455eb3266.js",revision:"d389ab6455eb3266"},{url:"/_next/static/chunks/67773-8d020a288a814616.js",revision:"8d020a288a814616"},{url:"/_next/static/chunks/67944.8a8ce2e65c529550.js",revision:"8a8ce2e65c529550"},{url:"/_next/static/chunks/68238.e60df98c44763ac0.js",revision:"e60df98c44763ac0"},{url:"/_next/static/chunks/68261-8d70a852cd02d709.js",revision:"8d70a852cd02d709"},{url:"/_next/static/chunks/68317.475eca3fba66f2cb.js",revision:"475eca3fba66f2cb"},{url:"/_next/static/chunks/68374.75cd33e645f82990.js",revision:"75cd33e645f82990"},{url:"/_next/static/chunks/68593.eb3f64b0bd1adbf9.js",revision:"eb3f64b0bd1adbf9"},{url:"/_next/static/chunks/68613.d2dfefdb7be8729d.js",revision:"d2dfefdb7be8729d"},{url:"/_next/static/chunks/68623.a2fa8173a81e96c7.js",revision:"a2fa8173a81e96c7"},{url:"/_next/static/chunks/68678.678b7b11f9ead911.js",revision:"678b7b11f9ead911"},{url:"/_next/static/chunks/68716-7ef1dd5631ee3c27.js",revision:"7ef1dd5631ee3c27"},{url:"/_next/static/chunks/68767.5012a7f10f40031e.js",revision:"5012a7f10f40031e"},{url:"/_next/static/chunks/6903.1baf2eea6f9189ef.js",revision:"1baf2eea6f9189ef"},{url:"/_next/static/chunks/69061.2cc069352f9957cc.js",revision:"2cc069352f9957cc"},{url:"/_next/static/chunks/69078-5901674cfcfd7a3f.js",revision:"5901674cfcfd7a3f"},{url:"/_next/static/chunks/69092.5523bc55bec5c952.js",revision:"5523bc55bec5c952"},{url:"/_next/static/chunks/69121.7b277dfcc4d51063.js",revision:"7b277dfcc4d51063"},{url:"/_next/static/chunks/69370.ada60e73535d0af0.js",revision:"ada60e73535d0af0"},{url:"/_next/static/chunks/69462.8b2415640e299af0.js",revision:"8b2415640e299af0"},{url:"/_next/static/chunks/69576.d6a7f2f28c695281.js",revision:"d6a7f2f28c695281"},{url:"/_next/static/chunks/6994.40e0e85f71728898.js",revision:"40e0e85f71728898"},{url:"/_next/static/chunks/69940.38d06eea458aa1c2.js",revision:"38d06eea458aa1c2"},{url:"/_next/static/chunks/703630e8.b8508f7ffe4e8b83.js",revision:"b8508f7ffe4e8b83"},{url:"/_next/static/chunks/70462-474c347309d4b5e9.js",revision:"474c347309d4b5e9"},{url:"/_next/static/chunks/70467.24f5dad36a2a3d29.js",revision:"24f5dad36a2a3d29"},{url:"/_next/static/chunks/70583.ad7ddd3192b7872c.js",revision:"ad7ddd3192b7872c"},{url:"/_next/static/chunks/70773-cdc2c58b9193f68c.js",revision:"cdc2c58b9193f68c"},{url:"/_next/static/chunks/70777.55d75dc8398ab065.js",revision:"55d75dc8398ab065"},{url:"/_next/static/chunks/70980.36ba30616317f150.js",revision:"36ba30616317f150"},{url:"/_next/static/chunks/71090.da54499c46683a36.js",revision:"da54499c46683a36"},{url:"/_next/static/chunks/71166.1e43a5a12fe27c16.js",revision:"1e43a5a12fe27c16"},{url:"/_next/static/chunks/71228.0ab9d25ae83b2ed9.js",revision:"0ab9d25ae83b2ed9"},{url:"/_next/static/chunks/71237.43618b676fae3e34.js",revision:"43618b676fae3e34"},{url:"/_next/static/chunks/7140.049cae991f2522b3.js",revision:"049cae991f2522b3"},{url:"/_next/static/chunks/71434.43014b9e3119d98d.js",revision:"43014b9e3119d98d"},{url:"/_next/static/chunks/71479.678d6b1ff17a50c3.js",revision:"678d6b1ff17a50c3"},{url:"/_next/static/chunks/71587.1acfb60fc2468ddb.js",revision:"1acfb60fc2468ddb"},{url:"/_next/static/chunks/71639.9b777574909cbd92.js",revision:"9b777574909cbd92"},{url:"/_next/static/chunks/71673.1f125c11fab4593c.js",revision:"1f125c11fab4593c"},{url:"/_next/static/chunks/71825.d5a5cbefe14bac40.js",revision:"d5a5cbefe14bac40"},{url:"/_next/static/chunks/71935.e039613d47bb0c5d.js",revision:"e039613d47bb0c5d"},{url:"/_next/static/chunks/72072.a9db8d18318423a0.js",revision:"a9db8d18318423a0"},{url:"/_next/static/chunks/72102.0d413358b0bbdaff.js",revision:"0d413358b0bbdaff"},{url:"/_next/static/chunks/72335.c18abd8b4b0461ca.js",revision:"c18abd8b4b0461ca"},{url:"/_next/static/chunks/7246.c28ff77d1bd37883.js",revision:"c28ff77d1bd37883"},{url:"/_next/static/chunks/72774.5f0bfa8577d88734.js",revision:"5f0bfa8577d88734"},{url:"/_next/static/chunks/72890.81905cc00613cdc8.js",revision:"81905cc00613cdc8"},{url:"/_next/static/chunks/72923.6b6846eee8228f64.js",revision:"6b6846eee8228f64"},{url:"/_next/static/chunks/72976.a538f0a89fa73049.js",revision:"a538f0a89fa73049"},{url:"/_next/static/chunks/73021.1e20339c558cf8c2.js",revision:"1e20339c558cf8c2"},{url:"/_next/static/chunks/73221.5aed83c2295dd556.js",revision:"5aed83c2295dd556"},{url:"/_next/static/chunks/73229.0893d6f40dfb8833.js",revision:"0893d6f40dfb8833"},{url:"/_next/static/chunks/73328-beea7d94a6886e77.js",revision:"beea7d94a6886e77"},{url:"/_next/static/chunks/73340.7209dfc4e3583b4e.js",revision:"7209dfc4e3583b4e"},{url:"/_next/static/chunks/73519.34607c290cfecc9f.js",revision:"34607c290cfecc9f"},{url:"/_next/static/chunks/73622.a1ba2ff411e8482c.js",revision:"a1ba2ff411e8482c"},{url:"/_next/static/chunks/7366.8c901d4c2daa0729.js",revision:"8c901d4c2daa0729"},{url:"/_next/static/chunks/74063.be3ab6a0f3918b70.js",revision:"be3ab6a0f3918b70"},{url:"/_next/static/chunks/741.cbb370ec65ee2808.js",revision:"cbb370ec65ee2808"},{url:"/_next/static/chunks/74157.06fc5af420388b4b.js",revision:"06fc5af420388b4b"},{url:"/_next/static/chunks/74186.761fca007d0bd520.js",revision:"761fca007d0bd520"},{url:"/_next/static/chunks/74293.90e0d4f989187aec.js",revision:"90e0d4f989187aec"},{url:"/_next/static/chunks/74407.aab476720c379ac6.js",revision:"aab476720c379ac6"},{url:"/_next/static/chunks/74421.0fc85575a9018521.js",revision:"0fc85575a9018521"},{url:"/_next/static/chunks/74545.8bfc570b8ff75059.js",revision:"8bfc570b8ff75059"},{url:"/_next/static/chunks/74558.56eb7f399f5f5664.js",revision:"56eb7f399f5f5664"},{url:"/_next/static/chunks/74560.95757a9f205c029c.js",revision:"95757a9f205c029c"},{url:"/_next/static/chunks/74565.aec3da0ec73a62d8.js",revision:"aec3da0ec73a62d8"},{url:"/_next/static/chunks/7469.3252cf6f77993627.js",revision:"3252cf6f77993627"},{url:"/_next/static/chunks/74861.979f0cf6068e05c1.js",revision:"979f0cf6068e05c1"},{url:"/_next/static/chunks/75146d7d-b63b39ceb44c002b.js",revision:"b63b39ceb44c002b"},{url:"/_next/static/chunks/75173.bb71ecc2a8f5b4af.js",revision:"bb71ecc2a8f5b4af"},{url:"/_next/static/chunks/75248.1e369d9f4e6ace5a.js",revision:"1e369d9f4e6ace5a"},{url:"/_next/static/chunks/75461.a9a455a6705f456c.js",revision:"a9a455a6705f456c"},{url:"/_next/static/chunks/75515.69aa7bfcd419ab5e.js",revision:"69aa7bfcd419ab5e"},{url:"/_next/static/chunks/75525.0237d30991c3ef4b.js",revision:"0237d30991c3ef4b"},{url:"/_next/static/chunks/75681.c9f3cbab6e74e4f9.js",revision:"c9f3cbab6e74e4f9"},{url:"/_next/static/chunks/75716.001e5661f840e3c8.js",revision:"001e5661f840e3c8"},{url:"/_next/static/chunks/7577.4856d8c69efb89ba.js",revision:"4856d8c69efb89ba"},{url:"/_next/static/chunks/75778.0a85c942bfa1318f.js",revision:"0a85c942bfa1318f"},{url:"/_next/static/chunks/75950.7e9f0cd675abb350.js",revision:"7e9f0cd675abb350"},{url:"/_next/static/chunks/75959.b648ebaa7bfaf8ca.js",revision:"b648ebaa7bfaf8ca"},{url:"/_next/static/chunks/76000.9d6c36a18d9cb51e.js",revision:"9d6c36a18d9cb51e"},{url:"/_next/static/chunks/76056.be9bcd184fc90530.js",revision:"be9bcd184fc90530"},{url:"/_next/static/chunks/76164.c98a73c72f35a7ae.js",revision:"c98a73c72f35a7ae"},{url:"/_next/static/chunks/76439.eb923b1e57743dfe.js",revision:"eb923b1e57743dfe"},{url:"/_next/static/chunks/7661.16df573093d193c5.js",revision:"16df573093d193c5"},{url:"/_next/static/chunks/76759.42664a1e54421ac7.js",revision:"42664a1e54421ac7"},{url:"/_next/static/chunks/77039.f95e0ae378929fa5.js",revision:"f95e0ae378929fa5"},{url:"/_next/static/chunks/77590.c6cd98832731b1cc.js",revision:"c6cd98832731b1cc"},{url:"/_next/static/chunks/77999.0adfbfb8fd0d33ec.js",revision:"0adfbfb8fd0d33ec"},{url:"/_next/static/chunks/77ab3b1e-f8bf51a99cf43e29.js",revision:"f8bf51a99cf43e29"},{url:"/_next/static/chunks/78674.75626b44b4b132f0.js",revision:"75626b44b4b132f0"},{url:"/_next/static/chunks/78699.2e8225d968350d1d.js",revision:"2e8225d968350d1d"},{url:"/_next/static/chunks/78762.b9bd8dc350c94a83.js",revision:"b9bd8dc350c94a83"},{url:"/_next/static/chunks/79259.cddffd58a7eae3ef.js",revision:"cddffd58a7eae3ef"},{url:"/_next/static/chunks/7959.1b0aaa48eee6bf32.js",revision:"1b0aaa48eee6bf32"},{url:"/_next/static/chunks/79626.e351735d516ec28e.js",revision:"e351735d516ec28e"},{url:"/_next/static/chunks/79703.b587dc8ccad9d08d.js",revision:"b587dc8ccad9d08d"},{url:"/_next/static/chunks/79761.fe16da0d6d1a106f.js",revision:"fe16da0d6d1a106f"},{url:"/_next/static/chunks/79874-599c49f92d2ef4f5.js",revision:"599c49f92d2ef4f5"},{url:"/_next/static/chunks/79961-acede45d96adbe1d.js",revision:"acede45d96adbe1d"},{url:"/_next/static/chunks/80195.1b40476084482063.js",revision:"1b40476084482063"},{url:"/_next/static/chunks/80197.eb16655a681c6190.js",revision:"eb16655a681c6190"},{url:"/_next/static/chunks/80373.f23025b9f36a5e37.js",revision:"f23025b9f36a5e37"},{url:"/_next/static/chunks/80449.7e6b89e55159f1bc.js",revision:"7e6b89e55159f1bc"},{url:"/_next/static/chunks/80581.87453c93004051a7.js",revision:"87453c93004051a7"},{url:"/_next/static/chunks/8062.cfb9c805c06f6949.js",revision:"cfb9c805c06f6949"},{url:"/_next/static/chunks/8072.1ba3571ad6e23cfe.js",revision:"1ba3571ad6e23cfe"},{url:"/_next/static/chunks/8094.27df35d51034f739.js",revision:"27df35d51034f739"},{url:"/_next/static/chunks/81162-18679861f0708c4e.js",revision:"18679861f0708c4e"},{url:"/_next/static/chunks/81245.9038602c14e0dd4e.js",revision:"9038602c14e0dd4e"},{url:"/_next/static/chunks/81318.ccc850b7b5ae40bd.js",revision:"ccc850b7b5ae40bd"},{url:"/_next/static/chunks/81422-bbbc2ba3f0cc4e66.js",revision:"bbbc2ba3f0cc4e66"},{url:"/_next/static/chunks/81533.157b33a7c70b005e.js",revision:"157b33a7c70b005e"},{url:"/_next/static/chunks/81693.2f24dbcc00a5cb72.js",revision:"2f24dbcc00a5cb72"},{url:"/_next/static/chunks/8170.4a55e17ad2cad666.js",revision:"4a55e17ad2cad666"},{url:"/_next/static/chunks/81700.d60f7d7f6038c837.js",revision:"d60f7d7f6038c837"},{url:"/_next/static/chunks/8194.cbbfeafda1601a18.js",revision:"cbbfeafda1601a18"},{url:"/_next/static/chunks/8195-c6839858c3f9aec5.js",revision:"c6839858c3f9aec5"},{url:"/_next/static/chunks/8200.3c75f3bab215483e.js",revision:"3c75f3bab215483e"},{url:"/_next/static/chunks/82232.1052ff7208a67415.js",revision:"1052ff7208a67415"},{url:"/_next/static/chunks/82316.7b1c2c81f1086454.js",revision:"7b1c2c81f1086454"},{url:"/_next/static/chunks/82752.0261e82ccb154685.js",revision:"0261e82ccb154685"},{url:"/_next/static/chunks/83123.7265903156b4cf3a.js",revision:"7265903156b4cf3a"},{url:"/_next/static/chunks/83231.5c88d13812ff91dc.js",revision:"5c88d13812ff91dc"},{url:"/_next/static/chunks/83334-20d155f936e5c2d0.js",revision:"20d155f936e5c2d0"},{url:"/_next/static/chunks/83400.7412446ee7ab051d.js",revision:"7412446ee7ab051d"},{url:"/_next/static/chunks/83606-3866ba699eba7113.js",revision:"3866ba699eba7113"},{url:"/_next/static/chunks/84008.ee9796764b6cdd47.js",revision:"ee9796764b6cdd47"},{url:"/_next/static/chunks/85141.0a8a7d754464eb0f.js",revision:"0a8a7d754464eb0f"},{url:"/_next/static/chunks/85191.bb6acbbbe1179751.js",revision:"bb6acbbbe1179751"},{url:"/_next/static/chunks/8530.ba2ed5ce9f652717.js",revision:"ba2ed5ce9f652717"},{url:"/_next/static/chunks/85321.e9eefd44ed3e44f5.js",revision:"e9eefd44ed3e44f5"},{url:"/_next/static/chunks/85477.27550d696822bbf7.js",revision:"27550d696822bbf7"},{url:"/_next/static/chunks/85608.498835fa9446632d.js",revision:"498835fa9446632d"},{url:"/_next/static/chunks/85642.7f7cd4c48f43c3bc.js",revision:"7f7cd4c48f43c3bc"},{url:"/_next/static/chunks/85799.225cbb4ddd6940e1.js",revision:"225cbb4ddd6940e1"},{url:"/_next/static/chunks/85956.a742f2466e4015a3.js",revision:"a742f2466e4015a3"},{url:"/_next/static/chunks/86155-32c6a7bcb5a98572.js",revision:"32c6a7bcb5a98572"},{url:"/_next/static/chunks/86215-4678ab2fdccbd1e2.js",revision:"4678ab2fdccbd1e2"},{url:"/_next/static/chunks/86343.1d48e96df2594340.js",revision:"1d48e96df2594340"},{url:"/_next/static/chunks/86597.b725376659ad10fe.js",revision:"b725376659ad10fe"},{url:"/_next/static/chunks/86765.c4cc5a8d24a581ae.js",revision:"c4cc5a8d24a581ae"},{url:"/_next/static/chunks/86991.4d6502bfa8f7db19.js",revision:"4d6502bfa8f7db19"},{url:"/_next/static/chunks/87073.990b74086f778d94.js",revision:"990b74086f778d94"},{url:"/_next/static/chunks/87165.286f970d45bcafc2.js",revision:"286f970d45bcafc2"},{url:"/_next/static/chunks/87191.3409cf7f85aa0b47.js",revision:"3409cf7f85aa0b47"},{url:"/_next/static/chunks/87331.79c9de5462f08cb0.js",revision:"79c9de5462f08cb0"},{url:"/_next/static/chunks/87527-55eedb9c689577f5.js",revision:"55eedb9c689577f5"},{url:"/_next/static/chunks/87528.f5f8adef6c2697e3.js",revision:"f5f8adef6c2697e3"},{url:"/_next/static/chunks/87567.46e360d54425a042.js",revision:"46e360d54425a042"},{url:"/_next/static/chunks/87610.8bab545588dccdc3.js",revision:"8bab545588dccdc3"},{url:"/_next/static/chunks/87778.5229ce757bba9d0e.js",revision:"5229ce757bba9d0e"},{url:"/_next/static/chunks/87809.8bae30b457b37735.js",revision:"8bae30b457b37735"},{url:"/_next/static/chunks/87828.0ebcd13d9a353d8f.js",revision:"0ebcd13d9a353d8f"},{url:"/_next/static/chunks/87897.420554342c98d3e2.js",revision:"420554342c98d3e2"},{url:"/_next/static/chunks/88055.6ee53ad3edb985dd.js",revision:"6ee53ad3edb985dd"},{url:"/_next/static/chunks/88123-5e8c8f235311aeaf.js",revision:"5e8c8f235311aeaf"},{url:"/_next/static/chunks/88137.981329e59c74a4ce.js",revision:"981329e59c74a4ce"},{url:"/_next/static/chunks/88205.55aeaf641a4b6132.js",revision:"55aeaf641a4b6132"},{url:"/_next/static/chunks/88477-d6c6e51118f91382.js",revision:"d6c6e51118f91382"},{url:"/_next/static/chunks/88678.8a9b8c4027ac68fb.js",revision:"8a9b8c4027ac68fb"},{url:"/_next/static/chunks/88716.3a8ca48db56529e5.js",revision:"3a8ca48db56529e5"},{url:"/_next/static/chunks/88908.3a33af34520f7883.js",revision:"3a33af34520f7883"},{url:"/_next/static/chunks/89381.1b62aa1dbf7de07e.js",revision:"1b62aa1dbf7de07e"},{url:"/_next/static/chunks/89417.1620b5c658f31f73.js",revision:"1620b5c658f31f73"},{url:"/_next/static/chunks/89575-31d7d686051129fe.js",revision:"31d7d686051129fe"},{url:"/_next/static/chunks/89642.a85207ad9d763ef8.js",revision:"a85207ad9d763ef8"},{url:"/_next/static/chunks/90105.9be2284c3b93b5fd.js",revision:"9be2284c3b93b5fd"},{url:"/_next/static/chunks/90199.5c403c69c1e4357d.js",revision:"5c403c69c1e4357d"},{url:"/_next/static/chunks/90279-c9546d4e0bb400f8.js",revision:"c9546d4e0bb400f8"},{url:"/_next/static/chunks/90383.192b50ab145d8bd1.js",revision:"192b50ab145d8bd1"},{url:"/_next/static/chunks/90427.74f430d5b2ae45af.js",revision:"74f430d5b2ae45af"},{url:"/_next/static/chunks/90471.5f6e6f8a98ca5033.js",revision:"5f6e6f8a98ca5033"},{url:"/_next/static/chunks/90536.fe1726d6cd2ea357.js",revision:"fe1726d6cd2ea357"},{url:"/_next/static/chunks/90595.785124d1120d27f9.js",revision:"785124d1120d27f9"},{url:"/_next/static/chunks/9071.876ba5ef39371c47.js",revision:"876ba5ef39371c47"},{url:"/_next/static/chunks/90780.fdaa2a6b5e7dd697.js",revision:"fdaa2a6b5e7dd697"},{url:"/_next/static/chunks/90957.0490253f0ae6f485.js",revision:"0490253f0ae6f485"},{url:"/_next/static/chunks/91143-2a701f58798c89d0.js",revision:"2a701f58798c89d0"},{url:"/_next/static/chunks/91261.21406379ab458d52.js",revision:"21406379ab458d52"},{url:"/_next/static/chunks/91393.dc35da467774f444.js",revision:"dc35da467774f444"},{url:"/_next/static/chunks/91422.d9529e608800ea75.js",revision:"d9529e608800ea75"},{url:"/_next/static/chunks/91451.288156397e47d9b8.js",revision:"288156397e47d9b8"},{url:"/_next/static/chunks/91527.7ca5762ef10d40ee.js",revision:"7ca5762ef10d40ee"},{url:"/_next/static/chunks/91671.361167a6338cd901.js",revision:"361167a6338cd901"},{url:"/_next/static/chunks/91889-5a0ce10d39717b4f.js",revision:"5a0ce10d39717b4f"},{url:"/_next/static/chunks/92388.a207ebbfe7c3d26d.js",revision:"a207ebbfe7c3d26d"},{url:"/_next/static/chunks/92400.1fb3823935e73d42.js",revision:"1fb3823935e73d42"},{url:"/_next/static/chunks/92492.59a11478b339316b.js",revision:"59a11478b339316b"},{url:"/_next/static/chunks/92561.e1c3bf1e9f920802.js",revision:"e1c3bf1e9f920802"},{url:"/_next/static/chunks/92731-8ff5c1266b208156.js",revision:"8ff5c1266b208156"},{url:"/_next/static/chunks/92772.6880fad8f52c4feb.js",revision:"6880fad8f52c4feb"},{url:"/_next/static/chunks/92962.74ae7d8bd89b3e31.js",revision:"74ae7d8bd89b3e31"},{url:"/_next/static/chunks/92969-c5c9edce1e2e6c8b.js",revision:"c5c9edce1e2e6c8b"},{url:"/_next/static/chunks/93074.5c9d506a202dce96.js",revision:"5c9d506a202dce96"},{url:"/_next/static/chunks/93114.b76e36cd7bd6e19d.js",revision:"b76e36cd7bd6e19d"},{url:"/_next/static/chunks/93118.0440926174432bcf.js",revision:"0440926174432bcf"},{url:"/_next/static/chunks/93145-b63023ada2f33fff.js",revision:"b63023ada2f33fff"},{url:"/_next/static/chunks/93173.ade511976ed51856.js",revision:"ade511976ed51856"},{url:"/_next/static/chunks/93182.6ee1b69d0aa27e8c.js",revision:"6ee1b69d0aa27e8c"},{url:"/_next/static/chunks/93341-6783e5f3029a130b.js",revision:"6783e5f3029a130b"},{url:"/_next/static/chunks/93421.787d9aa35e07bc44.js",revision:"787d9aa35e07bc44"},{url:"/_next/static/chunks/93563.ab762101ccffb4e0.js",revision:"ab762101ccffb4e0"},{url:"/_next/static/chunks/93569.b12d2af31e0a6fa2.js",revision:"b12d2af31e0a6fa2"},{url:"/_next/static/chunks/93797.daaa7647b2a1dc6a.js",revision:"daaa7647b2a1dc6a"},{url:"/_next/static/chunks/93899.728e85db64be1bc6.js",revision:"728e85db64be1bc6"},{url:"/_next/static/chunks/94017.2e401f1acc097f7d.js",revision:"2e401f1acc097f7d"},{url:"/_next/static/chunks/94068.9faf55d51f6526c4.js",revision:"9faf55d51f6526c4"},{url:"/_next/static/chunks/94078.58a7480b32dae5a8.js",revision:"58a7480b32dae5a8"},{url:"/_next/static/chunks/94101.eab83afd2ca6d222.js",revision:"eab83afd2ca6d222"},{url:"/_next/static/chunks/94215.188da4736c80fc01.js",revision:"188da4736c80fc01"},{url:"/_next/static/chunks/94281-db58741f0aeb372e.js",revision:"db58741f0aeb372e"},{url:"/_next/static/chunks/94345-d0b23494b17cc99f.js",revision:"d0b23494b17cc99f"},{url:"/_next/static/chunks/94349.872b4a1e42ace7f2.js",revision:"872b4a1e42ace7f2"},{url:"/_next/static/chunks/94670.d6b2d3a678eb4da3.js",revision:"d6b2d3a678eb4da3"},{url:"/_next/static/chunks/94787.ceec61ab6dff6688.js",revision:"ceec61ab6dff6688"},{url:"/_next/static/chunks/94831-526536a85c9a6bdb.js",revision:"526536a85c9a6bdb"},{url:"/_next/static/chunks/94837.715e9dca315c39b4.js",revision:"715e9dca315c39b4"},{url:"/_next/static/chunks/9495.eb477a65bbbc2992.js",revision:"eb477a65bbbc2992"},{url:"/_next/static/chunks/94956.1b5c1e9f2fbc6df5.js",revision:"1b5c1e9f2fbc6df5"},{url:"/_next/static/chunks/94993.ad3f4bfaff049ca8.js",revision:"ad3f4bfaff049ca8"},{url:"/_next/static/chunks/9532.60130fa22f635a18.js",revision:"60130fa22f635a18"},{url:"/_next/static/chunks/95381.cce5dd15c25f2994.js",revision:"cce5dd15c25f2994"},{url:"/_next/static/chunks/95396.0934e7a5e10197d1.js",revision:"0934e7a5e10197d1"},{url:"/_next/static/chunks/95407.2ee1da2299bba1a8.js",revision:"2ee1da2299bba1a8"},{url:"/_next/static/chunks/95409.94814309f78e3c5c.js",revision:"94814309f78e3c5c"},{url:"/_next/static/chunks/95620.f9eddae9368015e5.js",revision:"f9eddae9368015e5"},{url:"/_next/static/chunks/9585.131a2c63e5b8a264.js",revision:"131a2c63e5b8a264"},{url:"/_next/static/chunks/96332.9430f87cbdb1705b.js",revision:"9430f87cbdb1705b"},{url:"/_next/static/chunks/96407.e7bf8b423fdbb39a.js",revision:"e7bf8b423fdbb39a"},{url:"/_next/static/chunks/96408.f022e26f95b48a75.js",revision:"f022e26f95b48a75"},{url:"/_next/static/chunks/96538.b1c0b59b9549e1e2.js",revision:"b1c0b59b9549e1e2"},{url:"/_next/static/chunks/97058-037c2683762e75ab.js",revision:"037c2683762e75ab"},{url:"/_next/static/chunks/9708.7044690bc88bb602.js",revision:"7044690bc88bb602"},{url:"/_next/static/chunks/97114-6ac8104fd90b0e7b.js",revision:"6ac8104fd90b0e7b"},{url:"/_next/static/chunks/97236.dfe49ef38d88cc45.js",revision:"dfe49ef38d88cc45"},{url:"/_next/static/chunks/97274.23ab786b634d9b99.js",revision:"23ab786b634d9b99"},{url:"/_next/static/chunks/97285.cb10fb2a3788209d.js",revision:"cb10fb2a3788209d"},{url:"/_next/static/chunks/97298.438147bc65fc7d9a.js",revision:"438147bc65fc7d9a"},{url:"/_next/static/chunks/9731.5940adfabf75a8c8.js",revision:"5940adfabf75a8c8"},{url:"/_next/static/chunks/9749-256161a3e8327791.js",revision:"256161a3e8327791"},{url:"/_next/static/chunks/97529.bf872828850d9294.js",revision:"bf872828850d9294"},{url:"/_next/static/chunks/97739.0ea276d823af3634.js",revision:"0ea276d823af3634"},{url:"/_next/static/chunks/98053.078efa31852ebf12.js",revision:"078efa31852ebf12"},{url:"/_next/static/chunks/98409.1172de839121afc6.js",revision:"1172de839121afc6"},{url:"/_next/static/chunks/98486.4f0be4f954a3a606.js",revision:"4f0be4f954a3a606"},{url:"/_next/static/chunks/98611-3385436ac869beb4.js",revision:"3385436ac869beb4"},{url:"/_next/static/chunks/98693.adc70834eff7c3ed.js",revision:"adc70834eff7c3ed"},{url:"/_next/static/chunks/98763.e845c55158eeb8f3.js",revision:"e845c55158eeb8f3"},{url:"/_next/static/chunks/98791.1dc24bae9079b508.js",revision:"1dc24bae9079b508"},{url:"/_next/static/chunks/98879-58310d4070df46f1.js",revision:"58310d4070df46f1"},{url:"/_next/static/chunks/99040-be2224b07fe6c1d4.js",revision:"be2224b07fe6c1d4"},{url:"/_next/static/chunks/99361-8072a0f644e9e8b3.js",revision:"8072a0f644e9e8b3"},{url:"/_next/static/chunks/99468.eeddf14d71bbba42.js",revision:"eeddf14d71bbba42"},{url:"/_next/static/chunks/99488.e6e6c67d29690e29.js",revision:"e6e6c67d29690e29"},{url:"/_next/static/chunks/99605.4bd3e037a36a009b.js",revision:"4bd3e037a36a009b"},{url:"/_next/static/chunks/9982.02faca849525389b.js",revision:"02faca849525389b"},{url:"/_next/static/chunks/ade92b7e-b80f4007963aa2ea.js",revision:"b80f4007963aa2ea"},{url:"/_next/static/chunks/adeb31b9-1bc732df2736a7c7.js",revision:"1bc732df2736a7c7"},{url:"/_next/static/chunks/app/(commonLayout)/app/(appDetailLayout)/%5BappId%5D/annotations/page-bed321fdfb3de005.js",revision:"bed321fdfb3de005"},{url:"/_next/static/chunks/app/(commonLayout)/app/(appDetailLayout)/%5BappId%5D/configuration/page-89c8fe27bca672af.js",revision:"89c8fe27bca672af"},{url:"/_next/static/chunks/app/(commonLayout)/app/(appDetailLayout)/%5BappId%5D/develop/page-24064ab04d3d57d6.js",revision:"24064ab04d3d57d6"},{url:"/_next/static/chunks/app/(commonLayout)/app/(appDetailLayout)/%5BappId%5D/layout-6c19b111064a2731.js",revision:"6c19b111064a2731"},{url:"/_next/static/chunks/app/(commonLayout)/app/(appDetailLayout)/%5BappId%5D/logs/page-ddb74395540182c1.js",revision:"ddb74395540182c1"},{url:"/_next/static/chunks/app/(commonLayout)/app/(appDetailLayout)/%5BappId%5D/overview/page-d2fb7ff2a8818796.js",revision:"d2fb7ff2a8818796"},{url:"/_next/static/chunks/app/(commonLayout)/app/(appDetailLayout)/%5BappId%5D/workflow/page-97159ef4cd2bd5a7.js",revision:"97159ef4cd2bd5a7"},{url:"/_next/static/chunks/app/(commonLayout)/app/(appDetailLayout)/layout-3c7730b7811ea1ae.js",revision:"3c7730b7811ea1ae"},{url:"/_next/static/chunks/app/(commonLayout)/apps/page-a3d0b21cdbaf962b.js",revision:"a3d0b21cdbaf962b"},{url:"/_next/static/chunks/app/(commonLayout)/datasets/(datasetDetailLayout)/%5BdatasetId%5D/api/page-7ac04c3c68eae26d.js",revision:"7ac04c3c68eae26d"},{url:"/_next/static/chunks/app/(commonLayout)/datasets/(datasetDetailLayout)/%5BdatasetId%5D/documents/%5BdocumentId%5D/page-94552d721af14748.js",revision:"94552d721af14748"},{url:"/_next/static/chunks/app/(commonLayout)/datasets/(datasetDetailLayout)/%5BdatasetId%5D/documents/%5BdocumentId%5D/settings/page-05ae79dbef8350cc.js",revision:"05ae79dbef8350cc"},{url:"/_next/static/chunks/app/(commonLayout)/datasets/(datasetDetailLayout)/%5BdatasetId%5D/documents/create/page-d2aa2a76e03ec53f.js",revision:"d2aa2a76e03ec53f"},{url:"/_next/static/chunks/app/(commonLayout)/datasets/(datasetDetailLayout)/%5BdatasetId%5D/documents/page-370cffab0f5b884a.js",revision:"370cffab0f5b884a"},{url:"/_next/static/chunks/app/(commonLayout)/datasets/(datasetDetailLayout)/%5BdatasetId%5D/hitTesting/page-20c8e200fc40de49.js",revision:"20c8e200fc40de49"},{url:"/_next/static/chunks/app/(commonLayout)/datasets/(datasetDetailLayout)/%5BdatasetId%5D/layout-c4910193b73acc38.js",revision:"c4910193b73acc38"},{url:"/_next/static/chunks/app/(commonLayout)/datasets/(datasetDetailLayout)/%5BdatasetId%5D/settings/page-d231cce377344c33.js",revision:"d231cce377344c33"},{url:"/_next/static/chunks/app/(commonLayout)/datasets/(datasetDetailLayout)/layout-7ac04c3c68eae26d.js",revision:"7ac04c3c68eae26d"},{url:"/_next/static/chunks/app/(commonLayout)/datasets/connect/page-222b21a0716d995e.js",revision:"222b21a0716d995e"},{url:"/_next/static/chunks/app/(commonLayout)/datasets/create/page-d2aa2a76e03ec53f.js",revision:"d2aa2a76e03ec53f"},{url:"/_next/static/chunks/app/(commonLayout)/datasets/layout-3726b0284e4f552b.js",revision:"3726b0284e4f552b"},{url:"/_next/static/chunks/app/(commonLayout)/datasets/page-03ff65eedb77ba4d.js",revision:"03ff65eedb77ba4d"},{url:"/_next/static/chunks/app/(commonLayout)/education-apply/page-291db89c2853e316.js",revision:"291db89c2853e316"},{url:"/_next/static/chunks/app/(commonLayout)/explore/apps/page-b6b03fc07666e36c.js",revision:"b6b03fc07666e36c"},{url:"/_next/static/chunks/app/(commonLayout)/explore/installed/%5BappId%5D/page-42bdc499cbe849eb.js",revision:"42bdc499cbe849eb"},{url:"/_next/static/chunks/app/(commonLayout)/explore/layout-07882b9360c8ff8b.js",revision:"07882b9360c8ff8b"},{url:"/_next/static/chunks/app/(commonLayout)/layout-180ee349235239dc.js",revision:"180ee349235239dc"},{url:"/_next/static/chunks/app/(commonLayout)/plugins/page-529f12cc5e2f9e0b.js",revision:"529f12cc5e2f9e0b"},{url:"/_next/static/chunks/app/(commonLayout)/tools/page-4ea8d3d5a7283926.js",revision:"4ea8d3d5a7283926"},{url:"/_next/static/chunks/app/(shareLayout)/chat/%5Btoken%5D/page-0f6b9f734fed56f9.js",revision:"0f6b9f734fed56f9"},{url:"/_next/static/chunks/app/(shareLayout)/chatbot/%5Btoken%5D/page-0a1e275f27786868.js",revision:"0a1e275f27786868"},{url:"/_next/static/chunks/app/(shareLayout)/completion/%5Btoken%5D/page-9d7b40ad12c37ab8.js",revision:"9d7b40ad12c37ab8"},{url:"/_next/static/chunks/app/(shareLayout)/layout-8fd27a89a617a8fd.js",revision:"8fd27a89a617a8fd"},{url:"/_next/static/chunks/app/(shareLayout)/webapp-reset-password/check-code/page-c4f111e617001d45.js",revision:"c4f111e617001d45"},{url:"/_next/static/chunks/app/(shareLayout)/webapp-reset-password/layout-598e0a9d3deb7093.js",revision:"598e0a9d3deb7093"},{url:"/_next/static/chunks/app/(shareLayout)/webapp-reset-password/page-e32ee30d405b03dd.js",revision:"e32ee30d405b03dd"},{url:"/_next/static/chunks/app/(shareLayout)/webapp-reset-password/set-password/page-dcb5b053896ba2f8.js",revision:"dcb5b053896ba2f8"},{url:"/_next/static/chunks/app/(shareLayout)/webapp-signin/check-code/page-6fcab2735c5ee65d.js",revision:"6fcab2735c5ee65d"},{url:"/_next/static/chunks/app/(shareLayout)/webapp-signin/layout-f6f60499c4b61eb5.js",revision:"f6f60499c4b61eb5"},{url:"/_next/static/chunks/app/(shareLayout)/webapp-signin/page-907e45c5a29faa8e.js",revision:"907e45c5a29faa8e"},{url:"/_next/static/chunks/app/(shareLayout)/workflow/%5Btoken%5D/page-9d7b40ad12c37ab8.js",revision:"9d7b40ad12c37ab8"},{url:"/_next/static/chunks/app/_not-found/page-2eeef5110e4b8b7e.js",revision:"2eeef5110e4b8b7e"},{url:"/_next/static/chunks/app/account/(commonLayout)/layout-3317cfcfa7c80c5e.js",revision:"3317cfcfa7c80c5e"},{url:"/_next/static/chunks/app/account/(commonLayout)/page-d8d8b5ed77c1c805.js",revision:"d8d8b5ed77c1c805"},{url:"/_next/static/chunks/app/account/oauth/authorize/layout-e7b4f9f7025b3cfb.js",revision:"e7b4f9f7025b3cfb"},{url:"/_next/static/chunks/app/account/oauth/authorize/page-e63ef7ac364ad40a.js",revision:"e63ef7ac364ad40a"},{url:"/_next/static/chunks/app/activate/page-dcaa7c3c8f7a2812.js",revision:"dcaa7c3c8f7a2812"},{url:"/_next/static/chunks/app/forgot-password/page-dba51d61349f4d18.js",revision:"dba51d61349f4d18"},{url:"/_next/static/chunks/app/init/page-8722713d36eff02f.js",revision:"8722713d36eff02f"},{url:"/_next/static/chunks/app/install/page-cb027e5896d9a96e.js",revision:"cb027e5896d9a96e"},{url:"/_next/static/chunks/app/layout-8ae1390b2153a336.js",revision:"8ae1390b2153a336"},{url:"/_next/static/chunks/app/oauth-callback/page-5b267867410ae1a7.js",revision:"5b267867410ae1a7"},{url:"/_next/static/chunks/app/page-404d11e3effcbff8.js",revision:"404d11e3effcbff8"},{url:"/_next/static/chunks/app/repos/%5Bowner%5D/%5Brepo%5D/releases/route-7ac04c3c68eae26d.js",revision:"7ac04c3c68eae26d"},{url:"/_next/static/chunks/app/reset-password/check-code/page-10bef517ef308dfb.js",revision:"10bef517ef308dfb"},{url:"/_next/static/chunks/app/reset-password/layout-f27825bca55d7830.js",revision:"f27825bca55d7830"},{url:"/_next/static/chunks/app/reset-password/page-cf30c370eb897f35.js",revision:"cf30c370eb897f35"},{url:"/_next/static/chunks/app/reset-password/set-password/page-d9d31640356b736b.js",revision:"d9d31640356b736b"},{url:"/_next/static/chunks/app/signin/check-code/page-a03bca2f9a4bfb8d.js",revision:"a03bca2f9a4bfb8d"},{url:"/_next/static/chunks/app/signin/invite-settings/page-1e7215ce95bb9140.js",revision:"1e7215ce95bb9140"},{url:"/_next/static/chunks/app/signin/layout-1f5ae3bfec73f783.js",revision:"1f5ae3bfec73f783"},{url:"/_next/static/chunks/app/signin/page-2ba8f06ba52c9167.js",revision:"2ba8f06ba52c9167"},{url:"/_next/static/chunks/bda40ab4-465678c6543fde64.js",revision:"465678c6543fde64"},{url:"/_next/static/chunks/e8b19606.458322a93703fefb.js",revision:"458322a93703fefb"},{url:"/_next/static/chunks/f707c8ea-8556dcacf5dfe4ac.js",revision:"8556dcacf5dfe4ac"},{url:"/_next/static/chunks/fc43f782-87ce714d5535dbd7.js",revision:"87ce714d5535dbd7"},{url:"/_next/static/chunks/framework-04e9e69c198b8f2b.js",revision:"04e9e69c198b8f2b"},{url:"/_next/static/chunks/main-app-a4623e6276e9b96e.js",revision:"a4623e6276e9b96e"},{url:"/_next/static/chunks/main-d162030eff8fdeec.js",revision:"d162030eff8fdeec"},{url:"/_next/static/chunks/pages/_app-20413ffd01cbb95e.js",revision:"20413ffd01cbb95e"},{url:"/_next/static/chunks/pages/_error-d3c892d153e773fa.js",revision:"d3c892d153e773fa"},{url:"/_next/static/chunks/polyfills-42372ed130431b0a.js",revision:"846118c33b2c0e922d7b3a7676f81f6f"},{url:"/_next/static/chunks/webpack-859633ab1bcec9ac.js",revision:"859633ab1bcec9ac"},{url:"/_next/static/css/054994666d6806c5.css",revision:"054994666d6806c5"},{url:"/_next/static/css/1935925f720c7d7b.css",revision:"1935925f720c7d7b"},{url:"/_next/static/css/1f87e86cd533e873.css",revision:"1f87e86cd533e873"},{url:"/_next/static/css/220a772cfe3c95f4.css",revision:"220a772cfe3c95f4"},{url:"/_next/static/css/2da23e89afd44708.css",revision:"2da23e89afd44708"},{url:"/_next/static/css/2f7a6ecf4e344b75.css",revision:"2f7a6ecf4e344b75"},{url:"/_next/static/css/5bb43505df05adfe.css",revision:"5bb43505df05adfe"},{url:"/_next/static/css/61080ff8f99d7fe2.css",revision:"61080ff8f99d7fe2"},{url:"/_next/static/css/64f9f179dbdcd998.css",revision:"64f9f179dbdcd998"},{url:"/_next/static/css/8163616c965c42dc.css",revision:"8163616c965c42dc"},{url:"/_next/static/css/9e90e05c5cca6fcc.css",revision:"9e90e05c5cca6fcc"},{url:"/_next/static/css/a01885eb9d0649e5.css",revision:"a01885eb9d0649e5"},{url:"/_next/static/css/a031600822501d72.css",revision:"a031600822501d72"},{url:"/_next/static/css/b7247e8b4219ed3e.css",revision:"b7247e8b4219ed3e"},{url:"/_next/static/css/bf38d9b349c92e2b.css",revision:"bf38d9b349c92e2b"},{url:"/_next/static/css/c31a5eb4ac1ad018.css",revision:"c31a5eb4ac1ad018"},{url:"/_next/static/css/e2d5add89ff4b6ec.css",revision:"e2d5add89ff4b6ec"},{url:"/_next/static/css/f1f829214ba58f39.css",revision:"f1f829214ba58f39"},{url:"/_next/static/css/f63ea6462efb620f.css",revision:"f63ea6462efb620f"},{url:"/_next/static/css/fab77c667364e2c1.css",revision:"fab77c667364e2c1"},{url:"/_next/static/hxi5kegOl0PxtKhvDL_OX/_buildManifest.js",revision:"19f5fadd0444f8ce77907b9889fa2523"},{url:"/_next/static/hxi5kegOl0PxtKhvDL_OX/_ssgManifest.js",revision:"b6652df95db52feb4daf4eca35380933"},{url:"/_next/static/media/D.c178ca36.png",revision:"c178ca36"},{url:"/_next/static/media/Grid.da5dce2f.svg",revision:"da5dce2f"},{url:"/_next/static/media/KaTeX_AMS-Regular.1608a09b.woff",revision:"1608a09b"},{url:"/_next/static/media/KaTeX_AMS-Regular.4aafdb68.ttf",revision:"4aafdb68"},{url:"/_next/static/media/KaTeX_AMS-Regular.a79f1c31.woff2",revision:"a79f1c31"},{url:"/_next/static/media/KaTeX_Caligraphic-Bold.b6770918.woff",revision:"b6770918"},{url:"/_next/static/media/KaTeX_Caligraphic-Bold.cce5b8ec.ttf",revision:"cce5b8ec"},{url:"/_next/static/media/KaTeX_Caligraphic-Bold.ec17d132.woff2",revision:"ec17d132"},{url:"/_next/static/media/KaTeX_Caligraphic-Regular.07ef19e7.ttf",revision:"07ef19e7"},{url:"/_next/static/media/KaTeX_Caligraphic-Regular.55fac258.woff2",revision:"55fac258"},{url:"/_next/static/media/KaTeX_Caligraphic-Regular.dad44a7f.woff",revision:"dad44a7f"},{url:"/_next/static/media/KaTeX_Fraktur-Bold.9f256b85.woff",revision:"9f256b85"},{url:"/_next/static/media/KaTeX_Fraktur-Bold.b18f59e1.ttf",revision:"b18f59e1"},{url:"/_next/static/media/KaTeX_Fraktur-Bold.d42a5579.woff2",revision:"d42a5579"},{url:"/_next/static/media/KaTeX_Fraktur-Regular.7c187121.woff",revision:"7c187121"},{url:"/_next/static/media/KaTeX_Fraktur-Regular.d3c882a6.woff2",revision:"d3c882a6"},{url:"/_next/static/media/KaTeX_Fraktur-Regular.ed38e79f.ttf",revision:"ed38e79f"},{url:"/_next/static/media/KaTeX_Main-Bold.b74a1a8b.ttf",revision:"b74a1a8b"},{url:"/_next/static/media/KaTeX_Main-Bold.c3fb5ac2.woff2",revision:"c3fb5ac2"},{url:"/_next/static/media/KaTeX_Main-Bold.d181c465.woff",revision:"d181c465"},{url:"/_next/static/media/KaTeX_Main-BoldItalic.6f2bb1df.woff2",revision:"6f2bb1df"},{url:"/_next/static/media/KaTeX_Main-BoldItalic.70d8b0a5.ttf",revision:"70d8b0a5"},{url:"/_next/static/media/KaTeX_Main-BoldItalic.e3f82f9d.woff",revision:"e3f82f9d"},{url:"/_next/static/media/KaTeX_Main-Italic.47373d1e.ttf",revision:"47373d1e"},{url:"/_next/static/media/KaTeX_Main-Italic.8916142b.woff2",revision:"8916142b"},{url:"/_next/static/media/KaTeX_Main-Italic.9024d815.woff",revision:"9024d815"},{url:"/_next/static/media/KaTeX_Main-Regular.0462f03b.woff2",revision:"0462f03b"},{url:"/_next/static/media/KaTeX_Main-Regular.7f51fe03.woff",revision:"7f51fe03"},{url:"/_next/static/media/KaTeX_Main-Regular.b7f8fe9b.ttf",revision:"b7f8fe9b"},{url:"/_next/static/media/KaTeX_Math-BoldItalic.572d331f.woff2",revision:"572d331f"},{url:"/_next/static/media/KaTeX_Math-BoldItalic.a879cf83.ttf",revision:"a879cf83"},{url:"/_next/static/media/KaTeX_Math-BoldItalic.f1035d8d.woff",revision:"f1035d8d"},{url:"/_next/static/media/KaTeX_Math-Italic.5295ba48.woff",revision:"5295ba48"},{url:"/_next/static/media/KaTeX_Math-Italic.939bc644.ttf",revision:"939bc644"},{url:"/_next/static/media/KaTeX_Math-Italic.f28c23ac.woff2",revision:"f28c23ac"},{url:"/_next/static/media/KaTeX_SansSerif-Bold.8c5b5494.woff2",revision:"8c5b5494"},{url:"/_next/static/media/KaTeX_SansSerif-Bold.94e1e8dc.ttf",revision:"94e1e8dc"},{url:"/_next/static/media/KaTeX_SansSerif-Bold.bf59d231.woff",revision:"bf59d231"},{url:"/_next/static/media/KaTeX_SansSerif-Italic.3b1e59b3.woff2",revision:"3b1e59b3"},{url:"/_next/static/media/KaTeX_SansSerif-Italic.7c9bc82b.woff",revision:"7c9bc82b"},{url:"/_next/static/media/KaTeX_SansSerif-Italic.b4c20c84.ttf",revision:"b4c20c84"},{url:"/_next/static/media/KaTeX_SansSerif-Regular.74048478.woff",revision:"74048478"},{url:"/_next/static/media/KaTeX_SansSerif-Regular.ba21ed5f.woff2",revision:"ba21ed5f"},{url:"/_next/static/media/KaTeX_SansSerif-Regular.d4d7ba48.ttf",revision:"d4d7ba48"},{url:"/_next/static/media/KaTeX_Script-Regular.03e9641d.woff2",revision:"03e9641d"},{url:"/_next/static/media/KaTeX_Script-Regular.07505710.woff",revision:"07505710"},{url:"/_next/static/media/KaTeX_Script-Regular.fe9cbbe1.ttf",revision:"fe9cbbe1"},{url:"/_next/static/media/KaTeX_Size1-Regular.e1e279cb.woff",revision:"e1e279cb"},{url:"/_next/static/media/KaTeX_Size1-Regular.eae34984.woff2",revision:"eae34984"},{url:"/_next/static/media/KaTeX_Size1-Regular.fabc004a.ttf",revision:"fabc004a"},{url:"/_next/static/media/KaTeX_Size2-Regular.57727022.woff",revision:"57727022"},{url:"/_next/static/media/KaTeX_Size2-Regular.5916a24f.woff2",revision:"5916a24f"},{url:"/_next/static/media/KaTeX_Size2-Regular.d6b476ec.ttf",revision:"d6b476ec"},{url:"/_next/static/media/KaTeX_Size3-Regular.9acaf01c.woff",revision:"9acaf01c"},{url:"/_next/static/media/KaTeX_Size3-Regular.a144ef58.ttf",revision:"a144ef58"},{url:"/_next/static/media/KaTeX_Size3-Regular.b4230e7e.woff2",revision:"b4230e7e"},{url:"/_next/static/media/KaTeX_Size4-Regular.10d95fd3.woff2",revision:"10d95fd3"},{url:"/_next/static/media/KaTeX_Size4-Regular.7a996c9d.woff",revision:"7a996c9d"},{url:"/_next/static/media/KaTeX_Size4-Regular.fbccdabe.ttf",revision:"fbccdabe"},{url:"/_next/static/media/KaTeX_Typewriter-Regular.6258592b.woff",revision:"6258592b"},{url:"/_next/static/media/KaTeX_Typewriter-Regular.a8709e36.woff2",revision:"a8709e36"},{url:"/_next/static/media/KaTeX_Typewriter-Regular.d97aaf4a.ttf",revision:"d97aaf4a"},{url:"/_next/static/media/Loading.e3210867.svg",revision:"e3210867"},{url:"/_next/static/media/action.943fbcb8.svg",revision:"943fbcb8"},{url:"/_next/static/media/alert-triangle.329eb694.svg",revision:"329eb694"},{url:"/_next/static/media/alpha.6ae07de6.svg",revision:"6ae07de6"},{url:"/_next/static/media/atSign.89c9e2f2.svg",revision:"89c9e2f2"},{url:"/_next/static/media/bezierCurve.3a25cfc7.svg",revision:"3a25cfc7"},{url:"/_next/static/media/bg-line-error.c74246ec.svg",revision:"c74246ec"},{url:"/_next/static/media/bg-line-running.738082be.svg",revision:"738082be"},{url:"/_next/static/media/bg-line-success.ef8d3b89.svg",revision:"ef8d3b89"},{url:"/_next/static/media/bg-line-warning.1d037d22.svg",revision:"1d037d22"},{url:"/_next/static/media/book-open-01.a92cde5a.svg",revision:"a92cde5a"},{url:"/_next/static/media/bookOpen.eb79709c.svg",revision:"eb79709c"},{url:"/_next/static/media/briefcase.bba83ea7.svg",revision:"bba83ea7"},{url:"/_next/static/media/cardLoading.816a9dec.svg",revision:"816a9dec"},{url:"/_next/static/media/chromeplugin-install.982c5cbf.svg",revision:"982c5cbf"},{url:"/_next/static/media/chromeplugin-option.435ebf5a.svg",revision:"435ebf5a"},{url:"/_next/static/media/clock.81f8162b.svg",revision:"81f8162b"},{url:"/_next/static/media/close.562225f1.svg",revision:"562225f1"},{url:"/_next/static/media/code-browser.d954b670.svg",revision:"d954b670"},{url:"/_next/static/media/copied.350b63f0.svg",revision:"350b63f0"},{url:"/_next/static/media/copy-hover.2cc86992.svg",revision:"2cc86992"},{url:"/_next/static/media/copy.89d68c8b.svg",revision:"89d68c8b"},{url:"/_next/static/media/csv.1e142089.svg",revision:"1e142089"},{url:"/_next/static/media/doc.cea48e13.svg",revision:"cea48e13"},{url:"/_next/static/media/docx.4beb0ca0.svg",revision:"4beb0ca0"},{url:"/_next/static/media/family-mod.be47b090.svg",revision:"1695c917b23f714303acd201ddad6363"},{url:"/_next/static/media/file-list-3-fill.57beb31b.svg",revision:"e56018243e089a817b2625f80b258f82"},{url:"/_next/static/media/file.5700c745.svg",revision:"5700c745"},{url:"/_next/static/media/file.889034a9.svg",revision:"889034a9"},{url:"/_next/static/media/github-dark.b93b0533.svg",revision:"b93b0533"},{url:"/_next/static/media/github.fb41aac3.svg",revision:"fb41aac3"},{url:"/_next/static/media/globe.52a87779.svg",revision:"52a87779"},{url:"/_next/static/media/gold.e08d4e7c.svg",revision:"93ad9287fde1e70efe3e1bec6a3ad9f3"},{url:"/_next/static/media/google.7645ae62.svg",revision:"7645ae62"},{url:"/_next/static/media/graduationHat.2baee5c1.svg",revision:"2baee5c1"},{url:"/_next/static/media/grid.9bbbc935.svg",revision:"9bbbc935"},{url:"/_next/static/media/highlight-dark.86cc2cbe.svg",revision:"86cc2cbe"},{url:"/_next/static/media/highlight.231803b1.svg",revision:"231803b1"},{url:"/_next/static/media/html.6b956ddd.svg",revision:"6b956ddd"},{url:"/_next/static/media/html.bff3af4b.svg",revision:"bff3af4b"},{url:"/_next/static/media/iframe-option.41805f40.svg",revision:"41805f40"},{url:"/_next/static/media/jina.525d376e.png",revision:"525d376e"},{url:"/_next/static/media/json.1ab407af.svg",revision:"1ab407af"},{url:"/_next/static/media/json.5ad12020.svg",revision:"5ad12020"},{url:"/_next/static/media/md.6486841c.svg",revision:"6486841c"},{url:"/_next/static/media/md.f85dd8b0.svg",revision:"f85dd8b0"},{url:"/_next/static/media/messageTextCircle.24db2aef.svg",revision:"24db2aef"},{url:"/_next/static/media/note-mod.334e50fd.svg",revision:"f746e0565df49a8eadc4cea12280733d"},{url:"/_next/static/media/notion.afdb6b11.svg",revision:"afdb6b11"},{url:"/_next/static/media/notion.e316d36c.svg",revision:"e316d36c"},{url:"/_next/static/media/option-card-effect-orange.fcb3bda2.svg",revision:"cc54f7162f90a9198f107143286aae13"},{url:"/_next/static/media/option-card-effect-purple.1dbb53f5.svg",revision:"1cd4afee70e7fabf69f09aa1a8de1c3f"},{url:"/_next/static/media/pattern-recognition-mod.f283dd95.svg",revision:"51fc8910ff44f3a59a086815fbf26db0"},{url:"/_next/static/media/pause.beff025a.svg",revision:"beff025a"},{url:"/_next/static/media/pdf.298460a5.svg",revision:"298460a5"},{url:"/_next/static/media/pdf.49702006.svg",revision:"49702006"},{url:"/_next/static/media/piggy-bank-mod.1beae759.svg",revision:"1beae759"},{url:"/_next/static/media/piggy-bank-mod.1beae759.svg",revision:"728fc8d7ea59e954765e40a4a2d2f0c6"},{url:"/_next/static/media/play.0ad13b6e.svg",revision:"0ad13b6e"},{url:"/_next/static/media/plugin.718fc7fe.svg",revision:"718fc7fe"},{url:"/_next/static/media/progress-indicator.8ff709be.svg",revision:"a6315d09605666b1f6720172b58a3a0c"},{url:"/_next/static/media/refresh-hover.c2bcec46.svg",revision:"c2bcec46"},{url:"/_next/static/media/refresh.f64f5df9.svg",revision:"f64f5df9"},{url:"/_next/static/media/rerank.6cbde0af.svg",revision:"939d3cb8eab6545bb005c66ab693c33b"},{url:"/_next/static/media/research-mod.286ce029.svg",revision:"9aa84f591c106979aa698a7a73567f54"},{url:"/_next/static/media/scripts-option.ef16020c.svg",revision:"ef16020c"},{url:"/_next/static/media/selection-mod.e28687c9.svg",revision:"d7774b2c255ecd9d1789426a22a37322"},{url:"/_next/static/media/setting-gear-mod.eb788cca.svg",revision:"46346b10978e03bb11cce585585398de"},{url:"/_next/static/media/sliders-02.b8d6ae6d.svg",revision:"b8d6ae6d"},{url:"/_next/static/media/star-07.a14990cc.svg",revision:"a14990cc"},{url:"/_next/static/media/svg.85d3fb3b.svg",revision:"85d3fb3b"},{url:"/_next/static/media/svged.195f7ae0.svg",revision:"195f7ae0"},{url:"/_next/static/media/target.1691a8e3.svg",revision:"1691a8e3"},{url:"/_next/static/media/trash-gray.6d5549c8.svg",revision:"6d5549c8"},{url:"/_next/static/media/trash-red.9c6112f1.svg",revision:"9c6112f1"},{url:"/_next/static/media/txt.4652b1ff.svg",revision:"4652b1ff"},{url:"/_next/static/media/txt.bbb9f1f0.svg",revision:"bbb9f1f0"},{url:"/_next/static/media/typeSquare.a01ce0c0.svg",revision:"a01ce0c0"},{url:"/_next/static/media/watercrawl.456df4c6.svg",revision:"456df4c6"},{url:"/_next/static/media/web.4fdc057a.svg",revision:"4fdc057a"},{url:"/_next/static/media/xlsx.3d8439ac.svg",revision:"3d8439ac"},{url:"/_next/static/media/zap-fast.eb282fc3.svg",revision:"eb282fc3"},{url:"/_offline.html",revision:"6df1c7be2399be47e9107957824b2f33"},{url:"/apple-touch-icon.png",revision:"3072cb473be6bd67e10f39b9887b4998"},{url:"/browserconfig.xml",revision:"7cb0a4f14fbbe75ef7c316298c2ea0b4"},{url:"/education/bg.png",revision:"32ac1b738d76379629bce73e65b15a4b"},{url:"/embed.js",revision:"fdee1d8a73c7eb20d58abf3971896f45"},{url:"/embed.min.js",revision:"62c34d441b1a461b97003be49583a59a"},{url:"/favicon.ico",revision:"b5466696d7e24bbee4680c08eeee73bd"},{url:"/icon-128x128.png",revision:"f2eacd031928ba49cb2c183a6039ff1b"},{url:"/icon-144x144.png",revision:"88052943fa82639bdb84102e7e0800aa"},{url:"/icon-152x152.png",revision:"e294d2c6d58f05b81b0eb2c349bc934f"},{url:"/icon-192x192.png",revision:"4a4abb74428197748404327094840bd7"},{url:"/icon-256x256.png",revision:"9a7187eee4e6d391785789c68d7e92e4"},{url:"/icon-384x384.png",revision:"56a2a569512088757ffb7b416c060832"},{url:"/icon-512x512.png",revision:"ae467f17a361d9a357361710cff58bb0"},{url:"/icon-72x72.png",revision:"01694236efb16addfd161c62f6ccd580"},{url:"/icon-96x96.png",revision:"1c262f1a4b819cfde8532904f5ad3631"},{url:"/logo/logo-embedded-chat-avatar.png",revision:"62e2a1ebdceb29ec980114742acdfab4"},{url:"/logo/logo-embedded-chat-header.png",revision:"dce0c40a62aeeadf11646796bb55fcc7"},{url:"/logo/logo-embedded-chat-header@2x.png",revision:"2d9b8ec2b68f104f112caa257db1ab10"},{url:"/logo/logo-embedded-chat-header@3x.png",revision:"2f0fffb8b5d688b46f5d69f5d41806f5"},{url:"/logo/logo-monochrome-white.svg",revision:"05dc7d4393da987f847d00ba4defc848"},{url:"/logo/logo-site-dark.png",revision:"61d930e6f60033a1b498bfaf55a186fe"},{url:"/logo/logo-site.png",revision:"348d7284d2a42844141fbf5f6e659241"},{url:"/logo/logo.svg",revision:"267ddced6a09348ccb2de8b67c4f5725"},{url:"/manifest.json",revision:"768f3123c15976a16031d62ba7f61a53"},{url:"/pdf.worker.min.mjs",revision:"6f73268496ec32ad4ec3472d5c1fddda"},{url:"/screenshots/dark/Agent.png",revision:"5da5f2211edbbc8c2b9c2d4c3e9bc414"},{url:"/screenshots/dark/Agent@2x.png",revision:"ef332b42e738ae8e7b0a293e223c58ef"},{url:"/screenshots/dark/Agent@3x.png",revision:"ffde1f8557081a6ad94e37adc9f6dd7e"},{url:"/screenshots/dark/Chatbot.png",revision:"bd32412a6ac3dbf7ed6ca61f0d403b6d"},{url:"/screenshots/dark/Chatbot@2x.png",revision:"aacbf6db8ae7902b71ebe04cb7e2bea7"},{url:"/screenshots/dark/Chatbot@3x.png",revision:"43ce7150b9a210bd010e349a52a5d63a"},{url:"/screenshots/dark/Chatflow.png",revision:"08c53a166fd3891ec691b2c779c35301"},{url:"/screenshots/dark/Chatflow@2x.png",revision:"4228de158176f24b515d624da4ca21f8"},{url:"/screenshots/dark/Chatflow@3x.png",revision:"32104899a0200f3632c90abd7a35320b"},{url:"/screenshots/dark/TextGenerator.png",revision:"4dab6e79409d0557c1bb6a143d75f623"},{url:"/screenshots/dark/TextGenerator@2x.png",revision:"20390a8e234085463f6a74c30826ec52"},{url:"/screenshots/dark/TextGenerator@3x.png",revision:"b39464faa1f11ee2d21252f45202ec82"},{url:"/screenshots/dark/Workflow.png",revision:"ac5348d7f952f489604c5c11dffb0073"},{url:"/screenshots/dark/Workflow@2x.png",revision:"3c411a2ddfdeefe23476bead99e3ada4"},{url:"/screenshots/dark/Workflow@3x.png",revision:"e4bc999a1b1b484bb3c6399a10718eda"},{url:"/screenshots/light/Agent.png",revision:"1447432ae0123183d1249fc826807283"},{url:"/screenshots/light/Agent@2x.png",revision:"6e69ff8a74806a1e634d39e37e5d6496"},{url:"/screenshots/light/Agent@3x.png",revision:"a5c637f3783335979b25c164817c7184"},{url:"/screenshots/light/Chatbot.png",revision:"5b885663241183c1b88def19719e45f8"},{url:"/screenshots/light/Chatbot@2x.png",revision:"68ff5a5268fe868fd27f83d4e68870b1"},{url:"/screenshots/light/Chatbot@3x.png",revision:"7b6e521f10da72436118b7c01419bd95"},{url:"/screenshots/light/Chatflow.png",revision:"207558c2355340cb62cef3a6183f3724"},{url:"/screenshots/light/Chatflow@2x.png",revision:"2c18cb0aef5639e294d2330b4d4ee660"},{url:"/screenshots/light/Chatflow@3x.png",revision:"a559c04589e29b9dd6b51c81767bcec5"},{url:"/screenshots/light/TextGenerator.png",revision:"1d2cefd9027087f53f8cca8123bee0cd"},{url:"/screenshots/light/TextGenerator@2x.png",revision:"0afbc4b63ef7dc8451f6dcee99c44262"},{url:"/screenshots/light/TextGenerator@3x.png",revision:"660989be44dad56e58037b71bb2feafb"},{url:"/screenshots/light/Workflow.png",revision:"18be4d29f727077f7a80d1b25d22560d"},{url:"/screenshots/light/Workflow@2x.png",revision:"db8a0b1c4672cc4347704dbe7f67a7a2"},{url:"/screenshots/light/Workflow@3x.png",revision:"d75275fb75f6fa84dee5b78406a9937c"},{url:"/vs/base/browser/ui/codicons/codicon/codicon.ttf",revision:"8129e5752396eec0a208afb9808b69cb"},{url:"/vs/base/common/worker/simpleWorker.nls.de.js",revision:"b3ec29f1182621a9934e1ce2466c8b1f"},{url:"/vs/base/common/worker/simpleWorker.nls.es.js",revision:"97f25620a0a2ed3de79912277e71a141"},{url:"/vs/base/common/worker/simpleWorker.nls.fr.js",revision:"9dd88bf169e7c3ef490f52c6bc64ef79"},{url:"/vs/base/common/worker/simpleWorker.nls.it.js",revision:"8998ee8cdf1ca43c62398c0773f4d674"},{url:"/vs/base/common/worker/simpleWorker.nls.ja.js",revision:"e51053e004aaf43aa76cc0daeb7cd131"},{url:"/vs/base/common/worker/simpleWorker.nls.js",revision:"25dea293cfe1fec511a5c25d080f6510"},{url:"/vs/base/common/worker/simpleWorker.nls.ko.js",revision:"da364f5232b4f9a37f263d0fd2e21f5d"},{url:"/vs/base/common/worker/simpleWorker.nls.ru.js",revision:"12ca132c03dc99b151e310a0952c0af9"},{url:"/vs/base/common/worker/simpleWorker.nls.zh-cn.js",revision:"5371c3a354cde1e243466d0df74f00c6"},{url:"/vs/base/common/worker/simpleWorker.nls.zh-tw.js",revision:"fa92caa9cd0f92c2a95a4b4f2bcd4f3e"},{url:"/vs/base/worker/workerMain.js",revision:"f073495e58023ac8a897447245d13f0a"},{url:"/vs/basic-languages/abap/abap.js",revision:"53667015b71bc7e1cc31b4ffaa0c8203"},{url:"/vs/basic-languages/apex/apex.js",revision:"5b8ed50a1be53dd8f0f7356b7717410b"},{url:"/vs/basic-languages/azcli/azcli.js",revision:"f0d77b00897645b1a4bb05137efe1052"},{url:"/vs/basic-languages/bat/bat.js",revision:"d92d6be90fcb052bde96c475e4c420ec"},{url:"/vs/basic-languages/bicep/bicep.js",revision:"e324e4eb8053b19a0d6b4c99cd09577f"},{url:"/vs/basic-languages/cameligo/cameligo.js",revision:"7aa6bf7f273684303a71472f65dd3fb4"},{url:"/vs/basic-languages/clojure/clojure.js",revision:"6de8d7906b075cc308569dd5c702b0d7"},{url:"/vs/basic-languages/coffee/coffee.js",revision:"81892a0a475e95990d2698dd2a94b20a"},{url:"/vs/basic-languages/cpp/cpp.js",revision:"07af5fc22ff07c515666f9cd32945236"},{url:"/vs/basic-languages/csharp/csharp.js",revision:"d1d07ab0729d06302c788bcfe56cf4fe"},{url:"/vs/basic-languages/csp/csp.js",revision:"7ce13b6a9d2a1934760d697db785a585"},{url:"/vs/basic-languages/css/css.js",revision:"49e243e85ff343fd19fe00aa699b0af2"},{url:"/vs/basic-languages/cypher/cypher.js",revision:"3344ccd0aceac0e6526f22c890d2f75f"},{url:"/vs/basic-languages/dart/dart.js",revision:"92ded6175557e666e245e6b7d8bdeb6a"},{url:"/vs/basic-languages/dockerfile/dockerfile.js",revision:"a5a8892976102830aad437b507f845f1"},{url:"/vs/basic-languages/ecl/ecl.js",revision:"c25aa69e7d0832492d4e893d67226f93"},{url:"/vs/basic-languages/elixir/elixir.js",revision:"b9d3838d1e23e04fa11148c922f0273f"},{url:"/vs/basic-languages/flow9/flow9.js",revision:"b38c4587b04f24bffe625d67b7d2a454"},{url:"/vs/basic-languages/freemarker2/freemarker2.js",revision:"82923f6e9d66d8a36e67bfa314217268"},{url:"/vs/basic-languages/fsharp/fsharp.js",revision:"122f69422bc6d50df1720d9051d51efb"},{url:"/vs/basic-languages/go/go.js",revision:"4b555a32b18cea6aeeb9a21eedf0093b"},{url:"/vs/basic-languages/graphql/graphql.js",revision:"5e46b51d0347d90b7058381452a6b7fa"},{url:"/vs/basic-languages/handlebars/handlebars.js",revision:"e9ab0b3d29d3ac7afe0050138a73e926"},{url:"/vs/basic-languages/hcl/hcl.js",revision:"5b25c2e4fd4bb527d12c5da4a7376dbf"},{url:"/vs/basic-languages/html/html.js",revision:"ea22ddb1e9a2047699a3943d3f09c7cb"},{url:"/vs/basic-languages/ini/ini.js",revision:"6e14fd0bf0b9cfc60516b35d8ad90380"},{url:"/vs/basic-languages/java/java.js",revision:"3bee5d21d7f94f08f52250ae69c85a99"},{url:"/vs/basic-languages/javascript/javascript.js",revision:"5671f443a99492d6405b9ddbad7273af"},{url:"/vs/basic-languages/julia/julia.js",revision:"0e7229b7256a1fe0d495bfa048a2792d"},{url:"/vs/basic-languages/kotlin/kotlin.js",revision:"2579e51fc2ac0d8ea14339b3a42bbee1"},{url:"/vs/basic-languages/less/less.js",revision:"57d9acf121144aa07080c1551409d7e4"},{url:"/vs/basic-languages/lexon/lexon.js",revision:"dfb01cfcebb9bdda2d9ded19b78a112b"},{url:"/vs/basic-languages/liquid/liquid.js",revision:"22511ef12ef1c36f6e19e42ff920c92d"},{url:"/vs/basic-languages/lua/lua.js",revision:"04513cbe8568d0fe216b267a51fa8d92"},{url:"/vs/basic-languages/m3/m3.js",revision:"1bc2d1b3d59968cd60b1962c3e2ae4ec"},{url:"/vs/basic-languages/markdown/markdown.js",revision:"176204c5e3760d4d9d24f44a48821aed"},{url:"/vs/basic-languages/mdx/mdx.js",revision:"bb784b1621e2f2b7b0954351378840bc"},{url:"/vs/basic-languages/mips/mips.js",revision:"8df1b7666059092a0d622f57d611b0d6"},{url:"/vs/basic-languages/msdax/msdax.js",revision:"475a8cf2a1facf13ed7f1336289b7d62"},{url:"/vs/basic-languages/mysql/mysql.js",revision:"3d58bde2509af02384cfeb2a0ff11c9b"},{url:"/vs/basic-languages/objective-c/objective-c.js",revision:"09225247de0b7b4a5d1e39714eb383d9"},{url:"/vs/basic-languages/pascal/pascal.js",revision:"6dcd01139ec53b3eff56e31eac66b571"},{url:"/vs/basic-languages/pascaligo/pascaligo.js",revision:"4a01ddf6d56ea8d9b264e3feec74b998"},{url:"/vs/basic-languages/perl/perl.js",revision:"89f017f79e145d9313e8496202ab3c6c"},{url:"/vs/basic-languages/pgsql/pgsql.js",revision:"aba2c11fdf841f79deafbacc74d9b62b"},{url:"/vs/basic-languages/php/php.js",revision:"817ecc6a30b373ac4231a116932eed0e"},{url:"/vs/basic-languages/pla/pla.js",revision:"b0142ba41843ccb1d2f769495f39d479"},{url:"/vs/basic-languages/postiats/postiats.js",revision:"5de9b76b02e64cb8166f67b508344ab8"},{url:"/vs/basic-languages/powerquery/powerquery.js",revision:"278f5ebfe9e9a1bd316e71196c0ee33a"},{url:"/vs/basic-languages/powershell/powershell.js",revision:"27496ecc3565d3a85a3c2de19b059074"},{url:"/vs/basic-languages/protobuf/protobuf.js",revision:"374f802aefc150c1b7331146334e5e9c"},{url:"/vs/basic-languages/pug/pug.js",revision:"e8bb2ec6f1eac7e9340600acaef0bfc9"},{url:"/vs/basic-languages/python/python.js",revision:"bf6d8f14254586a9be67de999585a611"},{url:"/vs/basic-languages/qsharp/qsharp.js",revision:"1f1905da654e04423d922792e2bf96f9"},{url:"/vs/basic-languages/r/r.js",revision:"811be171ae696de48d5cf1460339bcd3"},{url:"/vs/basic-languages/razor/razor.js",revision:"45ce4627e0e51c8d35d1832b98b44f70"},{url:"/vs/basic-languages/redis/redis.js",revision:"1388147a532cb0c270f746f626d18257"},{url:"/vs/basic-languages/redshift/redshift.js",revision:"f577d72fb1c392d60231067323973429"},{url:"/vs/basic-languages/restructuredtext/restructuredtext.js",revision:"e5db13b472ea650c6b4449e29c2ab9c2"},{url:"/vs/basic-languages/ruby/ruby.js",revision:"846f0e6866dd7dd2e4b3f400c0f02cbe"},{url:"/vs/basic-languages/rust/rust.js",revision:"9ccf47397fb3da550d956a0d1f5171cc"},{url:"/vs/basic-languages/sb/sb.js",revision:"6b58eb47ee5b22b9a57986ecfcae39b5"},{url:"/vs/basic-languages/scala/scala.js",revision:"85716f12c7d0e9adad94838b985f16f9"},{url:"/vs/basic-languages/scheme/scheme.js",revision:"17b27762dce5ef5f4a5e4ee187588a97"},{url:"/vs/basic-languages/scss/scss.js",revision:"13ce232403a3d3e295d34755bf25389d"},{url:"/vs/basic-languages/shell/shell.js",revision:"568c42ff434da53e87202c71d114f3f5"},{url:"/vs/basic-languages/solidity/solidity.js",revision:"a6ee03c1a0fefb48e60ddf634820d23b"},{url:"/vs/basic-languages/sophia/sophia.js",revision:"899110a22cd9a291f19239f023033ae4"},{url:"/vs/basic-languages/sparql/sparql.js",revision:"f680e2f2f063ed36f75ee0398623dad6"},{url:"/vs/basic-languages/sql/sql.js",revision:"cbec458977358549fb3db9a36446dec9"},{url:"/vs/basic-languages/st/st.js",revision:"50c146e353e088645a341daf0e1dc5d3"},{url:"/vs/basic-languages/swift/swift.js",revision:"1d67edfc9a58775eaf70ff942a87da57"},{url:"/vs/basic-languages/systemverilog/systemverilog.js",revision:"f87daab3f7be73baa7d044af6e017e94"},{url:"/vs/basic-languages/tcl/tcl.js",revision:"a8187a8f37d73d8f95ec64dde66f185f"},{url:"/vs/basic-languages/twig/twig.js",revision:"05910657d2a031c6fdb12bbdfdc16b2a"},{url:"/vs/basic-languages/typescript/typescript.js",revision:"6edb28e3121d7d222150c7535350b93c"},{url:"/vs/basic-languages/vb/vb.js",revision:"b0be2782e785f6e2c74a1e6db72fb1f1"},{url:"/vs/basic-languages/wgsl/wgsl.js",revision:"691180550221d086b9989621fca9492d"},{url:"/vs/basic-languages/xml/xml.js",revision:"8a164d9767c96cbadb59f41520039553"},{url:"/vs/basic-languages/yaml/yaml.js",revision:"3024c6bd6032b778f73f820c9bee5e28"},{url:"/vs/editor/editor.main.css",revision:"11461cfb08c709aef66244a33106a130"},{url:"/vs/editor/editor.main.js",revision:"21dbd6e0be055e4116c09f6018523b65"},{url:"/vs/editor/editor.main.nls.de.js",revision:"127b360e1c3a616495c1570e5136053a"},{url:"/vs/editor/editor.main.nls.es.js",revision:"6d539ad100283a6f35379a58699fe46a"},{url:"/vs/editor/editor.main.nls.fr.js",revision:"99e68d4d1632ed0716b74de72d45880d"},{url:"/vs/editor/editor.main.nls.it.js",revision:"359690e951c23250e3310f63d7032b04"},{url:"/vs/editor/editor.main.nls.ja.js",revision:"60e044eb568e7cb249397b637ab9f891"},{url:"/vs/editor/editor.main.nls.js",revision:"a3f0617e2d240c5cdd0c44ca2082f807"},{url:"/vs/editor/editor.main.nls.ko.js",revision:"33207d8a31f33215607ade7319119d0c"},{url:"/vs/editor/editor.main.nls.ru.js",revision:"da941bc486519fcd2386f12008e178ca"},{url:"/vs/editor/editor.main.nls.zh-cn.js",revision:"90e1bc4905e86a08892cb993e96ff6aa"},{url:"/vs/editor/editor.main.nls.zh-tw.js",revision:"84ba8853d6dd2b37291a387bbeab5516"},{url:"/vs/language/css/cssMode.js",revision:"23f8482fdf45d208bcc9443c808c08a3"},{url:"/vs/language/css/cssWorker.js",revision:"8482bf05374fb6424a3d0e97d49d5972"},{url:"/vs/language/html/htmlMode.js",revision:"a90c26dcf5fa3381c84a9c6681de1e4f"},{url:"/vs/language/html/htmlWorker.js",revision:"43feb5119cecd63ba161aa8ffd5c0ad1"},{url:"/vs/language/json/jsonMode.js",revision:"e3dfed3331d8aaf4e0299579ca85cc0b"},{url:"/vs/language/json/jsonWorker.js",revision:"d636995b5e79d5e9e309b4642778a79d"},{url:"/vs/language/typescript/tsMode.js",revision:"b900fea27f62814e9145a796bf69721a"},{url:"/vs/language/typescript/tsWorker.js",revision:"9010f97362a2bb0bfb1d89989985ff0e"},{url:"/vs/loader.js",revision:"96db6297a4335a6ef4d698f5c191cc85"}],{ignoreURLParametersMatching:[]}),e.cleanupOutdatedCaches(),e.registerRoute("/",new e.NetworkFirst({cacheName:"start-url",plugins:[{cacheWillUpdate:async({request:e,response:s,event:a,state:c})=>s&&"opaqueredirect"===s.type?new Response(s.body,{status:200,statusText:"OK",headers:s.headers}):s},{handlerDidError:async({request:e})=>self.fallback(e)}]}),"GET"),e.registerRoute(/^https:\/\/fonts\.googleapis\.com\/.*/i,new e.CacheFirst({cacheName:"google-fonts",plugins:[new e.ExpirationPlugin({maxEntries:4,maxAgeSeconds:31536e3}),{handlerDidError:async({request:e})=>self.fallback(e)}]}),"GET"),e.registerRoute(/^https:\/\/fonts\.gstatic\.com\/.*/i,new e.CacheFirst({cacheName:"google-fonts-webfonts",plugins:[new e.ExpirationPlugin({maxEntries:4,maxAgeSeconds:31536e3}),{handlerDidError:async({request:e})=>self.fallback(e)}]}),"GET"),e.registerRoute(/\.(?:png|jpg|jpeg|svg|gif|webp|avif)$/i,new e.CacheFirst({cacheName:"images",plugins:[new e.ExpirationPlugin({maxEntries:64,maxAgeSeconds:2592e3}),{handlerDidError:async({request:e})=>self.fallback(e)}]}),"GET"),e.registerRoute(/\.(?:js|css)$/i,new e.StaleWhileRevalidate({cacheName:"static-resources",plugins:[new e.ExpirationPlugin({maxEntries:32,maxAgeSeconds:86400}),{handlerDidError:async({request:e})=>self.fallback(e)}]}),"GET"),e.registerRoute(/^\/api\/.*/i,new e.NetworkFirst({cacheName:"api-cache",networkTimeoutSeconds:10,plugins:[new e.ExpirationPlugin({maxEntries:16,maxAgeSeconds:3600}),{handlerDidError:async({request:e})=>self.fallback(e)}]}),"GET")}); diff --git a/web/public/workbox-c05e7c83.js b/web/public/workbox-c05e7c83.js new file mode 100644 index 0000000000..c2e0217441 --- /dev/null +++ b/web/public/workbox-c05e7c83.js @@ -0,0 +1 @@ +define(["exports"],function(t){"use strict";try{self["workbox:core:6.5.4"]&&_()}catch(t){}const e=(t,...e)=>{let s=t;return e.length>0&&(s+=` :: ${JSON.stringify(e)}`),s};class s extends Error{constructor(t,s){super(e(t,s)),this.name=t,this.details=s}}try{self["workbox:routing:6.5.4"]&&_()}catch(t){}const n=t=>t&&"object"==typeof t?t:{handle:t};class i{constructor(t,e,s="GET"){this.handler=n(e),this.match=t,this.method=s}setCatchHandler(t){this.catchHandler=n(t)}}class r extends i{constructor(t,e,s){super(({url:e})=>{const s=t.exec(e.href);if(s&&(e.origin===location.origin||0===s.index))return s.slice(1)},e,s)}}class a{constructor(){this.t=new Map,this.i=new Map}get routes(){return this.t}addFetchListener(){self.addEventListener("fetch",t=>{const{request:e}=t,s=this.handleRequest({request:e,event:t});s&&t.respondWith(s)})}addCacheListener(){self.addEventListener("message",t=>{if(t.data&&"CACHE_URLS"===t.data.type){const{payload:e}=t.data,s=Promise.all(e.urlsToCache.map(e=>{"string"==typeof e&&(e=[e]);const s=new Request(...e);return this.handleRequest({request:s,event:t})}));t.waitUntil(s),t.ports&&t.ports[0]&&s.then(()=>t.ports[0].postMessage(!0))}})}handleRequest({request:t,event:e}){const s=new URL(t.url,location.href);if(!s.protocol.startsWith("http"))return;const n=s.origin===location.origin,{params:i,route:r}=this.findMatchingRoute({event:e,request:t,sameOrigin:n,url:s});let a=r&&r.handler;const o=t.method;if(!a&&this.i.has(o)&&(a=this.i.get(o)),!a)return;let c;try{c=a.handle({url:s,request:t,event:e,params:i})}catch(t){c=Promise.reject(t)}const h=r&&r.catchHandler;return c instanceof Promise&&(this.o||h)&&(c=c.catch(async n=>{if(h)try{return await h.handle({url:s,request:t,event:e,params:i})}catch(t){t instanceof Error&&(n=t)}if(this.o)return this.o.handle({url:s,request:t,event:e});throw n})),c}findMatchingRoute({url:t,sameOrigin:e,request:s,event:n}){const i=this.t.get(s.method)||[];for(const r of i){let i;const a=r.match({url:t,sameOrigin:e,request:s,event:n});if(a)return i=a,(Array.isArray(i)&&0===i.length||a.constructor===Object&&0===Object.keys(a).length||"boolean"==typeof a)&&(i=void 0),{route:r,params:i}}return{}}setDefaultHandler(t,e="GET"){this.i.set(e,n(t))}setCatchHandler(t){this.o=n(t)}registerRoute(t){this.t.has(t.method)||this.t.set(t.method,[]),this.t.get(t.method).push(t)}unregisterRoute(t){if(!this.t.has(t.method))throw new s("unregister-route-but-not-found-with-method",{method:t.method});const e=this.t.get(t.method).indexOf(t);if(!(e>-1))throw new s("unregister-route-route-not-registered");this.t.get(t.method).splice(e,1)}}let o;const c=()=>(o||(o=new a,o.addFetchListener(),o.addCacheListener()),o);function h(t,e,n){let a;if("string"==typeof t){const s=new URL(t,location.href);a=new i(({url:t})=>t.href===s.href,e,n)}else if(t instanceof RegExp)a=new r(t,e,n);else if("function"==typeof t)a=new i(t,e,n);else{if(!(t instanceof i))throw new s("unsupported-route-type",{moduleName:"workbox-routing",funcName:"registerRoute",paramName:"capture"});a=t}return c().registerRoute(a),a}try{self["workbox:strategies:6.5.4"]&&_()}catch(t){}const u={cacheWillUpdate:async({response:t})=>200===t.status||0===t.status?t:null},l={googleAnalytics:"googleAnalytics",precache:"precache-v2",prefix:"workbox",runtime:"runtime",suffix:"undefined"!=typeof registration?registration.scope:""},f=t=>[l.prefix,t,l.suffix].filter(t=>t&&t.length>0).join("-"),w=t=>t||f(l.precache),d=t=>t||f(l.runtime);function p(t,e){const s=new URL(t);for(const t of e)s.searchParams.delete(t);return s.href}class y{constructor(){this.promise=new Promise((t,e)=>{this.resolve=t,this.reject=e})}}const m=new Set;function g(t){return"string"==typeof t?new Request(t):t}class R{constructor(t,e){this.h={},Object.assign(this,e),this.event=e.event,this.u=t,this.l=new y,this.p=[],this.m=[...t.plugins],this.R=new Map;for(const t of this.m)this.R.set(t,{});this.event.waitUntil(this.l.promise)}async fetch(t){const{event:e}=this;let n=g(t);if("navigate"===n.mode&&e instanceof FetchEvent&&e.preloadResponse){const t=await e.preloadResponse;if(t)return t}const i=this.hasCallback("fetchDidFail")?n.clone():null;try{for(const t of this.iterateCallbacks("requestWillFetch"))n=await t({request:n.clone(),event:e})}catch(t){if(t instanceof Error)throw new s("plugin-error-request-will-fetch",{thrownErrorMessage:t.message})}const r=n.clone();try{let t;t=await fetch(n,"navigate"===n.mode?void 0:this.u.fetchOptions);for(const s of this.iterateCallbacks("fetchDidSucceed"))t=await s({event:e,request:r,response:t});return t}catch(t){throw i&&await this.runCallbacks("fetchDidFail",{error:t,event:e,originalRequest:i.clone(),request:r.clone()}),t}}async fetchAndCachePut(t){const e=await this.fetch(t),s=e.clone();return this.waitUntil(this.cachePut(t,s)),e}async cacheMatch(t){const e=g(t);let s;const{cacheName:n,matchOptions:i}=this.u,r=await this.getCacheKey(e,"read"),a=Object.assign(Object.assign({},i),{cacheName:n});s=await caches.match(r,a);for(const t of this.iterateCallbacks("cachedResponseWillBeUsed"))s=await t({cacheName:n,matchOptions:i,cachedResponse:s,request:r,event:this.event})||void 0;return s}async cachePut(t,e){const n=g(t);var i;await(i=0,new Promise(t=>setTimeout(t,i)));const r=await this.getCacheKey(n,"write");if(!e)throw new s("cache-put-with-no-response",{url:(a=r.url,new URL(String(a),location.href).href.replace(new RegExp(`^${location.origin}`),""))});var a;const o=await this.v(e);if(!o)return!1;const{cacheName:c,matchOptions:h}=this.u,u=await self.caches.open(c),l=this.hasCallback("cacheDidUpdate"),f=l?await async function(t,e,s,n){const i=p(e.url,s);if(e.url===i)return t.match(e,n);const r=Object.assign(Object.assign({},n),{ignoreSearch:!0}),a=await t.keys(e,r);for(const e of a)if(i===p(e.url,s))return t.match(e,n)}(u,r.clone(),["__WB_REVISION__"],h):null;try{await u.put(r,l?o.clone():o)}catch(t){if(t instanceof Error)throw"QuotaExceededError"===t.name&&await async function(){for(const t of m)await t()}(),t}for(const t of this.iterateCallbacks("cacheDidUpdate"))await t({cacheName:c,oldResponse:f,newResponse:o.clone(),request:r,event:this.event});return!0}async getCacheKey(t,e){const s=`${t.url} | ${e}`;if(!this.h[s]){let n=t;for(const t of this.iterateCallbacks("cacheKeyWillBeUsed"))n=g(await t({mode:e,request:n,event:this.event,params:this.params}));this.h[s]=n}return this.h[s]}hasCallback(t){for(const e of this.u.plugins)if(t in e)return!0;return!1}async runCallbacks(t,e){for(const s of this.iterateCallbacks(t))await s(e)}*iterateCallbacks(t){for(const e of this.u.plugins)if("function"==typeof e[t]){const s=this.R.get(e),n=n=>{const i=Object.assign(Object.assign({},n),{state:s});return e[t](i)};yield n}}waitUntil(t){return this.p.push(t),t}async doneWaiting(){let t;for(;t=this.p.shift();)await t}destroy(){this.l.resolve(null)}async v(t){let e=t,s=!1;for(const t of this.iterateCallbacks("cacheWillUpdate"))if(e=await t({request:this.request,response:e,event:this.event})||void 0,s=!0,!e)break;return s||e&&200!==e.status&&(e=void 0),e}}class v{constructor(t={}){this.cacheName=d(t.cacheName),this.plugins=t.plugins||[],this.fetchOptions=t.fetchOptions,this.matchOptions=t.matchOptions}handle(t){const[e]=this.handleAll(t);return e}handleAll(t){t instanceof FetchEvent&&(t={event:t,request:t.request});const e=t.event,s="string"==typeof t.request?new Request(t.request):t.request,n="params"in t?t.params:void 0,i=new R(this,{event:e,request:s,params:n}),r=this.q(i,s,e);return[r,this.D(r,i,s,e)]}async q(t,e,n){let i;await t.runCallbacks("handlerWillStart",{event:n,request:e});try{if(i=await this.U(e,t),!i||"error"===i.type)throw new s("no-response",{url:e.url})}catch(s){if(s instanceof Error)for(const r of t.iterateCallbacks("handlerDidError"))if(i=await r({error:s,event:n,request:e}),i)break;if(!i)throw s}for(const s of t.iterateCallbacks("handlerWillRespond"))i=await s({event:n,request:e,response:i});return i}async D(t,e,s,n){let i,r;try{i=await t}catch(r){}try{await e.runCallbacks("handlerDidRespond",{event:n,request:s,response:i}),await e.doneWaiting()}catch(t){t instanceof Error&&(r=t)}if(await e.runCallbacks("handlerDidComplete",{event:n,request:s,response:i,error:r}),e.destroy(),r)throw r}}function b(t){t.then(()=>{})}function q(){return q=Object.assign?Object.assign.bind():function(t){for(var e=1;e(t[e]=s,!0),has:(t,e)=>t instanceof IDBTransaction&&("done"===e||"store"===e)||e in t};function O(t){return t!==IDBDatabase.prototype.transaction||"objectStoreNames"in IDBTransaction.prototype?(U||(U=[IDBCursor.prototype.advance,IDBCursor.prototype.continue,IDBCursor.prototype.continuePrimaryKey])).includes(t)?function(...e){return t.apply(T(this),e),B(x.get(this))}:function(...e){return B(t.apply(T(this),e))}:function(e,...s){const n=t.call(T(this),e,...s);return L.set(n,e.sort?e.sort():[e]),B(n)}}function k(t){return"function"==typeof t?O(t):(t instanceof IDBTransaction&&function(t){if(I.has(t))return;const e=new Promise((e,s)=>{const n=()=>{t.removeEventListener("complete",i),t.removeEventListener("error",r),t.removeEventListener("abort",r)},i=()=>{e(),n()},r=()=>{s(t.error||new DOMException("AbortError","AbortError")),n()};t.addEventListener("complete",i),t.addEventListener("error",r),t.addEventListener("abort",r)});I.set(t,e)}(t),e=t,(D||(D=[IDBDatabase,IDBObjectStore,IDBIndex,IDBCursor,IDBTransaction])).some(t=>e instanceof t)?new Proxy(t,N):t);var e}function B(t){if(t instanceof IDBRequest)return function(t){const e=new Promise((e,s)=>{const n=()=>{t.removeEventListener("success",i),t.removeEventListener("error",r)},i=()=>{e(B(t.result)),n()},r=()=>{s(t.error),n()};t.addEventListener("success",i),t.addEventListener("error",r)});return e.then(e=>{e instanceof IDBCursor&&x.set(e,t)}).catch(()=>{}),C.set(e,t),e}(t);if(E.has(t))return E.get(t);const e=k(t);return e!==t&&(E.set(t,e),C.set(e,t)),e}const T=t=>C.get(t);const M=["get","getKey","getAll","getAllKeys","count"],P=["put","add","delete","clear"],W=new Map;function j(t,e){if(!(t instanceof IDBDatabase)||e in t||"string"!=typeof e)return;if(W.get(e))return W.get(e);const s=e.replace(/FromIndex$/,""),n=e!==s,i=P.includes(s);if(!(s in(n?IDBIndex:IDBObjectStore).prototype)||!i&&!M.includes(s))return;const r=async function(t,...e){const r=this.transaction(t,i?"readwrite":"readonly");let a=r.store;return n&&(a=a.index(e.shift())),(await Promise.all([a[s](...e),i&&r.done]))[0]};return W.set(e,r),r}N=(t=>q({},t,{get:(e,s,n)=>j(e,s)||t.get(e,s,n),has:(e,s)=>!!j(e,s)||t.has(e,s)}))(N);try{self["workbox:expiration:6.5.4"]&&_()}catch(t){}const S="cache-entries",K=t=>{const e=new URL(t,location.href);return e.hash="",e.href};class A{constructor(t){this._=null,this.I=t}L(t){const e=t.createObjectStore(S,{keyPath:"id"});e.createIndex("cacheName","cacheName",{unique:!1}),e.createIndex("timestamp","timestamp",{unique:!1})}C(t){this.L(t),this.I&&function(t,{blocked:e}={}){const s=indexedDB.deleteDatabase(t);e&&s.addEventListener("blocked",t=>e(t.oldVersion,t)),B(s).then(()=>{})}(this.I)}async setTimestamp(t,e){const s={url:t=K(t),timestamp:e,cacheName:this.I,id:this.N(t)},n=(await this.getDb()).transaction(S,"readwrite",{durability:"relaxed"});await n.store.put(s),await n.done}async getTimestamp(t){const e=await this.getDb(),s=await e.get(S,this.N(t));return null==s?void 0:s.timestamp}async expireEntries(t,e){const s=await this.getDb();let n=await s.transaction(S).store.index("timestamp").openCursor(null,"prev");const i=[];let r=0;for(;n;){const s=n.value;s.cacheName===this.I&&(t&&s.timestamp=e?i.push(n.value):r++),n=await n.continue()}const a=[];for(const t of i)await s.delete(S,t.id),a.push(t.url);return a}N(t){return this.I+"|"+K(t)}async getDb(){return this._||(this._=await function(t,e,{blocked:s,upgrade:n,blocking:i,terminated:r}={}){const a=indexedDB.open(t,e),o=B(a);return n&&a.addEventListener("upgradeneeded",t=>{n(B(a.result),t.oldVersion,t.newVersion,B(a.transaction),t)}),s&&a.addEventListener("blocked",t=>s(t.oldVersion,t.newVersion,t)),o.then(t=>{r&&t.addEventListener("close",()=>r()),i&&t.addEventListener("versionchange",t=>i(t.oldVersion,t.newVersion,t))}).catch(()=>{}),o}("workbox-expiration",1,{upgrade:this.C.bind(this)})),this._}}class F{constructor(t,e={}){this.O=!1,this.k=!1,this.B=e.maxEntries,this.T=e.maxAgeSeconds,this.M=e.matchOptions,this.I=t,this.P=new A(t)}async expireEntries(){if(this.O)return void(this.k=!0);this.O=!0;const t=this.T?Date.now()-1e3*this.T:0,e=await this.P.expireEntries(t,this.B),s=await self.caches.open(this.I);for(const t of e)await s.delete(t,this.M);this.O=!1,this.k&&(this.k=!1,b(this.expireEntries()))}async updateTimestamp(t){await this.P.setTimestamp(t,Date.now())}async isURLExpired(t){if(this.T){const e=await this.P.getTimestamp(t),s=Date.now()-1e3*this.T;return void 0===e||e{e&&(e.originalRequest=t)},this.cachedResponseWillBeUsed=async({event:t,state:e,cachedResponse:s})=>{if("install"===t.type&&e&&e.originalRequest&&e.originalRequest instanceof Request){const t=e.originalRequest.url;s?this.notUpdatedURLs.push(t):this.updatedURLs.push(t)}return s}}}class V{constructor({precacheController:t}){this.cacheKeyWillBeUsed=async({request:t,params:e})=>{const s=(null==e?void 0:e.cacheKey)||this.W.getCacheKeyForURL(t.url);return s?new Request(s,{headers:t.headers}):t},this.W=t}}let J,Q;async function z(t,e){let n=null;if(t.url){n=new URL(t.url).origin}if(n!==self.location.origin)throw new s("cross-origin-copy-response",{origin:n});const i=t.clone(),r={headers:new Headers(i.headers),status:i.status,statusText:i.statusText},a=e?e(r):r,o=function(){if(void 0===J){const t=new Response("");if("body"in t)try{new Response(t.body),J=!0}catch(t){J=!1}J=!1}return J}()?i.body:await i.blob();return new Response(o,a)}class X extends v{constructor(t={}){t.cacheName=w(t.cacheName),super(t),this.j=!1!==t.fallbackToNetwork,this.plugins.push(X.copyRedirectedCacheableResponsesPlugin)}async U(t,e){const s=await e.cacheMatch(t);return s||(e.event&&"install"===e.event.type?await this.S(t,e):await this.K(t,e))}async K(t,e){let n;const i=e.params||{};if(!this.j)throw new s("missing-precache-entry",{cacheName:this.cacheName,url:t.url});{const s=i.integrity,r=t.integrity,a=!r||r===s;n=await e.fetch(new Request(t,{integrity:"no-cors"!==t.mode?r||s:void 0})),s&&a&&"no-cors"!==t.mode&&(this.A(),await e.cachePut(t,n.clone()))}return n}async S(t,e){this.A();const n=await e.fetch(t);if(!await e.cachePut(t,n.clone()))throw new s("bad-precaching-response",{url:t.url,status:n.status});return n}A(){let t=null,e=0;for(const[s,n]of this.plugins.entries())n!==X.copyRedirectedCacheableResponsesPlugin&&(n===X.defaultPrecacheCacheabilityPlugin&&(t=s),n.cacheWillUpdate&&e++);0===e?this.plugins.push(X.defaultPrecacheCacheabilityPlugin):e>1&&null!==t&&this.plugins.splice(t,1)}}X.defaultPrecacheCacheabilityPlugin={cacheWillUpdate:async({response:t})=>!t||t.status>=400?null:t},X.copyRedirectedCacheableResponsesPlugin={cacheWillUpdate:async({response:t})=>t.redirected?await z(t):t};class Y{constructor({cacheName:t,plugins:e=[],fallbackToNetwork:s=!0}={}){this.F=new Map,this.H=new Map,this.$=new Map,this.u=new X({cacheName:w(t),plugins:[...e,new V({precacheController:this})],fallbackToNetwork:s}),this.install=this.install.bind(this),this.activate=this.activate.bind(this)}get strategy(){return this.u}precache(t){this.addToCacheList(t),this.G||(self.addEventListener("install",this.install),self.addEventListener("activate",this.activate),this.G=!0)}addToCacheList(t){const e=[];for(const n of t){"string"==typeof n?e.push(n):n&&void 0===n.revision&&e.push(n.url);const{cacheKey:t,url:i}=$(n),r="string"!=typeof n&&n.revision?"reload":"default";if(this.F.has(i)&&this.F.get(i)!==t)throw new s("add-to-cache-list-conflicting-entries",{firstEntry:this.F.get(i),secondEntry:t});if("string"!=typeof n&&n.integrity){if(this.$.has(t)&&this.$.get(t)!==n.integrity)throw new s("add-to-cache-list-conflicting-integrities",{url:i});this.$.set(t,n.integrity)}if(this.F.set(i,t),this.H.set(i,r),e.length>0){const t=`Workbox is precaching URLs without revision info: ${e.join(", ")}\nThis is generally NOT safe. Learn more at https://bit.ly/wb-precache`;console.warn(t)}}}install(t){return H(t,async()=>{const e=new G;this.strategy.plugins.push(e);for(const[e,s]of this.F){const n=this.$.get(s),i=this.H.get(e),r=new Request(e,{integrity:n,cache:i,credentials:"same-origin"});await Promise.all(this.strategy.handleAll({params:{cacheKey:s},request:r,event:t}))}const{updatedURLs:s,notUpdatedURLs:n}=e;return{updatedURLs:s,notUpdatedURLs:n}})}activate(t){return H(t,async()=>{const t=await self.caches.open(this.strategy.cacheName),e=await t.keys(),s=new Set(this.F.values()),n=[];for(const i of e)s.has(i.url)||(await t.delete(i),n.push(i.url));return{deletedURLs:n}})}getURLsToCacheKeys(){return this.F}getCachedURLs(){return[...this.F.keys()]}getCacheKeyForURL(t){const e=new URL(t,location.href);return this.F.get(e.href)}getIntegrityForCacheKey(t){return this.$.get(t)}async matchPrecache(t){const e=t instanceof Request?t.url:t,s=this.getCacheKeyForURL(e);if(s){return(await self.caches.open(this.strategy.cacheName)).match(s)}}createHandlerBoundToURL(t){const e=this.getCacheKeyForURL(t);if(!e)throw new s("non-precached-url",{url:t});return s=>(s.request=new Request(t),s.params=Object.assign({cacheKey:e},s.params),this.strategy.handle(s))}}const Z=()=>(Q||(Q=new Y),Q);class tt extends i{constructor(t,e){super(({request:s})=>{const n=t.getURLsToCacheKeys();for(const i of function*(t,{ignoreURLParametersMatching:e=[/^utm_/,/^fbclid$/],directoryIndex:s="index.html",cleanURLs:n=!0,urlManipulation:i}={}){const r=new URL(t,location.href);r.hash="",yield r.href;const a=function(t,e=[]){for(const s of[...t.searchParams.keys()])e.some(t=>t.test(s))&&t.searchParams.delete(s);return t}(r,e);if(yield a.href,s&&a.pathname.endsWith("/")){const t=new URL(a.href);t.pathname+=s,yield t.href}if(n){const t=new URL(a.href);t.pathname+=".html",yield t.href}if(i){const t=i({url:r});for(const e of t)yield e.href}}(s.url,e)){const e=n.get(i);if(e){return{cacheKey:e,integrity:t.getIntegrityForCacheKey(e)}}}},t.strategy)}}t.CacheFirst=class extends v{async U(t,e){let n,i=await e.cacheMatch(t);if(!i)try{i=await e.fetchAndCachePut(t)}catch(t){t instanceof Error&&(n=t)}if(!i)throw new s("no-response",{url:t.url,error:n});return i}},t.ExpirationPlugin=class{constructor(t={}){this.cachedResponseWillBeUsed=async({event:t,request:e,cacheName:s,cachedResponse:n})=>{if(!n)return null;const i=this.V(n),r=this.J(s);b(r.expireEntries());const a=r.updateTimestamp(e.url);if(t)try{t.waitUntil(a)}catch(t){}return i?n:null},this.cacheDidUpdate=async({cacheName:t,request:e})=>{const s=this.J(t);await s.updateTimestamp(e.url),await s.expireEntries()},this.X=t,this.T=t.maxAgeSeconds,this.Y=new Map,t.purgeOnQuotaError&&function(t){m.add(t)}(()=>this.deleteCacheAndMetadata())}J(t){if(t===d())throw new s("expire-custom-caches-only");let e=this.Y.get(t);return e||(e=new F(t,this.X),this.Y.set(t,e)),e}V(t){if(!this.T)return!0;const e=this.Z(t);if(null===e)return!0;return e>=Date.now()-1e3*this.T}Z(t){if(!t.headers.has("date"))return null;const e=t.headers.get("date"),s=new Date(e).getTime();return isNaN(s)?null:s}async deleteCacheAndMetadata(){for(const[t,e]of this.Y)await self.caches.delete(t),await e.delete();this.Y=new Map}},t.NetworkFirst=class extends v{constructor(t={}){super(t),this.plugins.some(t=>"cacheWillUpdate"in t)||this.plugins.unshift(u),this.tt=t.networkTimeoutSeconds||0}async U(t,e){const n=[],i=[];let r;if(this.tt){const{id:s,promise:a}=this.et({request:t,logs:n,handler:e});r=s,i.push(a)}const a=this.st({timeoutId:r,request:t,logs:n,handler:e});i.push(a);const o=await e.waitUntil((async()=>await e.waitUntil(Promise.race(i))||await a)());if(!o)throw new s("no-response",{url:t.url});return o}et({request:t,logs:e,handler:s}){let n;return{promise:new Promise(e=>{n=setTimeout(async()=>{e(await s.cacheMatch(t))},1e3*this.tt)}),id:n}}async st({timeoutId:t,request:e,logs:s,handler:n}){let i,r;try{r=await n.fetchAndCachePut(e)}catch(t){t instanceof Error&&(i=t)}return t&&clearTimeout(t),!i&&r||(r=await n.cacheMatch(e)),r}},t.StaleWhileRevalidate=class extends v{constructor(t={}){super(t),this.plugins.some(t=>"cacheWillUpdate"in t)||this.plugins.unshift(u)}async U(t,e){const n=e.fetchAndCachePut(t).catch(()=>{});e.waitUntil(n);let i,r=await e.cacheMatch(t);if(r);else try{r=await n}catch(t){t instanceof Error&&(i=t)}if(!r)throw new s("no-response",{url:t.url,error:i});return r}},t.cleanupOutdatedCaches=function(){self.addEventListener("activate",t=>{const e=w();t.waitUntil((async(t,e="-precache-")=>{const s=(await self.caches.keys()).filter(s=>s.includes(e)&&s.includes(self.registration.scope)&&s!==t);return await Promise.all(s.map(t=>self.caches.delete(t))),s})(e).then(t=>{}))})},t.clientsClaim=function(){self.addEventListener("activate",()=>self.clients.claim())},t.precacheAndRoute=function(t,e){!function(t){Z().precache(t)}(t),function(t){const e=Z();h(new tt(e,t))}(e)},t.registerRoute=h}); diff --git a/web/scripts/generate-icons.js b/web/scripts/generate-icons.js new file mode 100644 index 0000000000..074148e3bb --- /dev/null +++ b/web/scripts/generate-icons.js @@ -0,0 +1,51 @@ +const sharp = require('sharp'); +const fs = require('fs'); +const path = require('path'); + +const sizes = [ + { size: 192, name: 'icon-192x192.png' }, + { size: 256, name: 'icon-256x256.png' }, + { size: 384, name: 'icon-384x384.png' }, + { size: 512, name: 'icon-512x512.png' }, + { size: 96, name: 'icon-96x96.png' }, + { size: 72, name: 'icon-72x72.png' }, + { size: 128, name: 'icon-128x128.png' }, + { size: 144, name: 'icon-144x144.png' }, + { size: 152, name: 'icon-152x152.png' }, +]; + +const inputPath = path.join(__dirname, '../public/icon.svg'); +const outputDir = path.join(__dirname, '../public'); + +// Generate icons +async function generateIcons() { + try { + console.log('Generating PWA icons...'); + + for (const { size, name } of sizes) { + const outputPath = path.join(outputDir, name); + + await sharp(inputPath) + .resize(size, size) + .png() + .toFile(outputPath); + + console.log(`✓ Generated ${name} (${size}x${size})`); + } + + // Generate apple-touch-icon + await sharp(inputPath) + .resize(180, 180) + .png() + .toFile(path.join(outputDir, 'apple-touch-icon.png')); + + console.log('✓ Generated apple-touch-icon.png (180x180)'); + + console.log('\n✅ All icons generated successfully!'); + } catch (error) { + console.error('Error generating icons:', error); + process.exit(1); + } +} + +generateIcons(); \ No newline at end of file From 30e5c197cbc0acff5fa21e3aea0e9df5800b16c5 Mon Sep 17 00:00:00 2001 From: -LAN- Date: Sat, 6 Sep 2025 16:05:01 +0800 Subject: [PATCH 29/52] fix: standardize text color in install form to text-secondary (#25272) --- web/app/install/installForm.tsx | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/web/app/install/installForm.tsx b/web/app/install/installForm.tsx index 8ddb5276f0..65d1998fcc 100644 --- a/web/app/install/installForm.tsx +++ b/web/app/install/installForm.tsx @@ -134,7 +134,7 @@ const InstallForm = () => { {errors.email && {t(`${errors.email?.message}`)}}
@@ -149,7 +149,7 @@ const InstallForm = () => {
{errors.name && {t(`${errors.name.message}`)}} @@ -164,7 +164,7 @@ const InstallForm = () => { {...register('password')} type={showPassword ? 'text' : 'password'} placeholder={t('login.passwordPlaceholder') || ''} - className={'w-full appearance-none rounded-md border border-transparent bg-components-input-bg-normal py-[7px] pl-2 text-components-input-text-filled caret-primary-600 outline-none placeholder:text-components-input-text-placeholder hover:border-components-input-border-hover hover:bg-components-input-bg-hover focus:border-components-input-border-active focus:bg-components-input-bg-active focus:shadow-xs'} + className={'system-sm-regular w-full appearance-none rounded-md border border-transparent bg-components-input-bg-normal px-3 py-[7px] text-components-input-text-filled caret-primary-600 outline-none placeholder:text-components-input-text-placeholder hover:border-components-input-border-hover hover:bg-components-input-bg-hover focus:border-components-input-border-active focus:bg-components-input-bg-active focus:shadow-xs'} />
@@ -178,7 +178,7 @@ const InstallForm = () => {
-
{t('login.error.passwordInvalid')}
@@ -189,7 +189,7 @@ const InstallForm = () => {
-
+
{t('login.license.tip')}   Date: Sat, 6 Sep 2025 16:06:09 +0800 Subject: [PATCH 30/52] chore: translate i18n files and update type definitions (#25260) Co-authored-by: crazywoola <100913391+crazywoola@users.noreply.github.com> --- web/i18n/id-ID/workflow.ts | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/web/i18n/id-ID/workflow.ts b/web/i18n/id-ID/workflow.ts index e2daef6f7a..9da16bc94e 100644 --- a/web/i18n/id-ID/workflow.ts +++ b/web/i18n/id-ID/workflow.ts @@ -461,6 +461,12 @@ const translation = { contextTooltip: 'Anda dapat mengimpor Pengetahuan sebagai konteks', notSetContextInPromptTip: 'Untuk mengaktifkan fitur konteks, silakan isi variabel konteks di PROMPT.', context: 'konteks', + reasoningFormat: { + tagged: 'Tetap pikirkan tag', + title: 'Aktifkan pemisahan tag penalaran', + separated: 'Pisahkan tag pemikiran', + tooltip: 'Ekstrak konten dari tag pikir dan simpan di field reasoning_content.', + }, }, knowledgeRetrieval: { outputVars: { From b05245eab02dd03c100da2601ab6b7e88376cfc0 Mon Sep 17 00:00:00 2001 From: -LAN- Date: Sat, 6 Sep 2025 16:08:14 +0800 Subject: [PATCH 31/52] fix: resolve typing errors in configs module (#25268) Signed-off-by: -LAN- Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com> --- api/configs/middleware/__init__.py | 3 +- .../middleware/vdb/clickzetta_config.py | 5 +- .../middleware/vdb/matrixone_config.py | 5 +- api/configs/packaging/__init__.py | 2 +- .../remote_settings_sources/apollo/client.py | 62 ++++++++++--------- .../apollo/python_3x.py | 10 +-- .../remote_settings_sources/apollo/utils.py | 11 ++-- .../remote_settings_sources/nacos/__init__.py | 13 ++-- .../nacos/http_request.py | 22 ++++--- .../remote_settings_sources/nacos/utils.py | 2 +- api/pyrightconfig.json | 7 ++- 11 files changed, 77 insertions(+), 65 deletions(-) diff --git a/api/configs/middleware/__init__.py b/api/configs/middleware/__init__.py index 4751b96010..591c24cbe0 100644 --- a/api/configs/middleware/__init__.py +++ b/api/configs/middleware/__init__.py @@ -300,8 +300,7 @@ class DatasetQueueMonitorConfig(BaseSettings): class MiddlewareConfig( # place the configs in alphabet order - CeleryConfig, - DatabaseConfig, + CeleryConfig, # Note: CeleryConfig already inherits from DatabaseConfig KeywordStoreConfig, RedisConfig, # configs of storage and storage providers diff --git a/api/configs/middleware/vdb/clickzetta_config.py b/api/configs/middleware/vdb/clickzetta_config.py index 04f81e25fc..61bc01202b 100644 --- a/api/configs/middleware/vdb/clickzetta_config.py +++ b/api/configs/middleware/vdb/clickzetta_config.py @@ -1,9 +1,10 @@ from typing import Optional -from pydantic import BaseModel, Field +from pydantic import Field +from pydantic_settings import BaseSettings -class ClickzettaConfig(BaseModel): +class ClickzettaConfig(BaseSettings): """ Clickzetta Lakehouse vector database configuration """ diff --git a/api/configs/middleware/vdb/matrixone_config.py b/api/configs/middleware/vdb/matrixone_config.py index 9400612d8e..3e7ce7b672 100644 --- a/api/configs/middleware/vdb/matrixone_config.py +++ b/api/configs/middleware/vdb/matrixone_config.py @@ -1,7 +1,8 @@ -from pydantic import BaseModel, Field +from pydantic import Field +from pydantic_settings import BaseSettings -class MatrixoneConfig(BaseModel): +class MatrixoneConfig(BaseSettings): """Matrixone vector database configuration.""" MATRIXONE_HOST: str = Field(default="localhost", description="Host address of the Matrixone server") diff --git a/api/configs/packaging/__init__.py b/api/configs/packaging/__init__.py index f511e20e6b..b8d723ef4a 100644 --- a/api/configs/packaging/__init__.py +++ b/api/configs/packaging/__init__.py @@ -1,6 +1,6 @@ from pydantic import Field -from configs.packaging.pyproject import PyProjectConfig, PyProjectTomlConfig +from configs.packaging.pyproject import PyProjectTomlConfig class PackagingInfo(PyProjectTomlConfig): diff --git a/api/configs/remote_settings_sources/apollo/client.py b/api/configs/remote_settings_sources/apollo/client.py index 877ff8409f..e30e6218a1 100644 --- a/api/configs/remote_settings_sources/apollo/client.py +++ b/api/configs/remote_settings_sources/apollo/client.py @@ -4,8 +4,9 @@ import logging import os import threading import time -from collections.abc import Mapping +from collections.abc import Callable, Mapping from pathlib import Path +from typing import Any from .python_3x import http_request, makedirs_wrapper from .utils import ( @@ -25,13 +26,13 @@ logger = logging.getLogger(__name__) class ApolloClient: def __init__( self, - config_url, - app_id, - cluster="default", - secret="", - start_hot_update=True, - change_listener=None, - _notification_map=None, + config_url: str, + app_id: str, + cluster: str = "default", + secret: str = "", + start_hot_update: bool = True, + change_listener: Callable[[str, str, str, Any], None] | None = None, + _notification_map: dict[str, int] | None = None, ): # Core routing parameters self.config_url = config_url @@ -47,17 +48,17 @@ class ApolloClient: # Private control variables self._cycle_time = 5 self._stopping = False - self._cache = {} - self._no_key = {} - self._hash = {} + self._cache: dict[str, dict[str, Any]] = {} + self._no_key: dict[str, str] = {} + self._hash: dict[str, str] = {} self._pull_timeout = 75 self._cache_file_path = os.path.expanduser("~") + "/.dify/config/remote-settings/apollo/cache/" - self._long_poll_thread = None + self._long_poll_thread: threading.Thread | None = None self._change_listener = change_listener # "add" "delete" "update" if _notification_map is None: _notification_map = {"application": -1} self._notification_map = _notification_map - self.last_release_key = None + self.last_release_key: str | None = None # Private startup method self._path_checker() if start_hot_update: @@ -68,7 +69,7 @@ class ApolloClient: heartbeat.daemon = True heartbeat.start() - def get_json_from_net(self, namespace="application"): + def get_json_from_net(self, namespace: str = "application") -> dict[str, Any] | None: url = "{}/configs/{}/{}/{}?releaseKey={}&ip={}".format( self.config_url, self.app_id, self.cluster, namespace, "", self.ip ) @@ -88,7 +89,7 @@ class ApolloClient: logger.exception("an error occurred in get_json_from_net") return None - def get_value(self, key, default_val=None, namespace="application"): + def get_value(self, key: str, default_val: Any = None, namespace: str = "application") -> Any: try: # read memory configuration namespace_cache = self._cache.get(namespace) @@ -104,7 +105,8 @@ class ApolloClient: namespace_data = self.get_json_from_net(namespace) val = get_value_from_dict(namespace_data, key) if val is not None: - self._update_cache_and_file(namespace_data, namespace) + if namespace_data is not None: + self._update_cache_and_file(namespace_data, namespace) return val # read the file configuration @@ -126,23 +128,23 @@ class ApolloClient: # to ensure the real-time correctness of the function call. # If the user does not have the same default val twice # and the default val is used here, there may be a problem. - def _set_local_cache_none(self, namespace, key): + def _set_local_cache_none(self, namespace: str, key: str) -> None: no_key = no_key_cache_key(namespace, key) self._no_key[no_key] = key - def _start_hot_update(self): + def _start_hot_update(self) -> None: self._long_poll_thread = threading.Thread(target=self._listener) # When the asynchronous thread is started, the daemon thread will automatically exit # when the main thread is launched. self._long_poll_thread.daemon = True self._long_poll_thread.start() - def stop(self): + def stop(self) -> None: self._stopping = True logger.info("Stopping listener...") # Call the set callback function, and if it is abnormal, try it out - def _call_listener(self, namespace, old_kv, new_kv): + def _call_listener(self, namespace: str, old_kv: dict[str, Any] | None, new_kv: dict[str, Any] | None) -> None: if self._change_listener is None: return if old_kv is None: @@ -168,12 +170,12 @@ class ApolloClient: except BaseException as e: logger.warning(str(e)) - def _path_checker(self): + def _path_checker(self) -> None: if not os.path.isdir(self._cache_file_path): makedirs_wrapper(self._cache_file_path) # update the local cache and file cache - def _update_cache_and_file(self, namespace_data, namespace="application"): + def _update_cache_and_file(self, namespace_data: dict[str, Any], namespace: str = "application") -> None: # update the local cache self._cache[namespace] = namespace_data # update the file cache @@ -187,7 +189,7 @@ class ApolloClient: self._hash[namespace] = new_hash # get the configuration from the local file - def _get_local_cache(self, namespace="application"): + def _get_local_cache(self, namespace: str = "application") -> dict[str, Any]: cache_file_path = os.path.join(self._cache_file_path, f"{self.app_id}_configuration_{namespace}.txt") if os.path.isfile(cache_file_path): with open(cache_file_path) as f: @@ -195,8 +197,8 @@ class ApolloClient: return result return {} - def _long_poll(self): - notifications = [] + def _long_poll(self) -> None: + notifications: list[dict[str, Any]] = [] for key in self._cache: namespace_data = self._cache[key] notification_id = -1 @@ -236,7 +238,7 @@ class ApolloClient: except Exception as e: logger.warning(str(e)) - def _get_net_and_set_local(self, namespace, n_id, call_change=False): + def _get_net_and_set_local(self, namespace: str, n_id: int, call_change: bool = False) -> None: namespace_data = self.get_json_from_net(namespace) if not namespace_data: return @@ -248,7 +250,7 @@ class ApolloClient: new_kv = namespace_data.get(CONFIGURATIONS) self._call_listener(namespace, old_kv, new_kv) - def _listener(self): + def _listener(self) -> None: logger.info("start long_poll") while not self._stopping: self._long_poll() @@ -266,13 +268,13 @@ class ApolloClient: headers["Timestamp"] = time_unix_now return headers - def _heart_beat(self): + def _heart_beat(self) -> None: while not self._stopping: for namespace in self._notification_map: self._do_heart_beat(namespace) time.sleep(60 * 10) # 10 minutes - def _do_heart_beat(self, namespace): + def _do_heart_beat(self, namespace: str) -> None: url = f"{self.config_url}/configs/{self.app_id}/{self.cluster}/{namespace}?ip={self.ip}" try: code, body = http_request(url, timeout=3, headers=self._sign_headers(url)) @@ -292,7 +294,7 @@ class ApolloClient: logger.exception("an error occurred in _do_heart_beat") return None - def get_all_dicts(self, namespace): + def get_all_dicts(self, namespace: str) -> dict[str, Any] | None: namespace_data = self._cache.get(namespace) if namespace_data is None: net_namespace_data = self.get_json_from_net(namespace) diff --git a/api/configs/remote_settings_sources/apollo/python_3x.py b/api/configs/remote_settings_sources/apollo/python_3x.py index 6a5f381991..d21e0ecffe 100644 --- a/api/configs/remote_settings_sources/apollo/python_3x.py +++ b/api/configs/remote_settings_sources/apollo/python_3x.py @@ -2,6 +2,8 @@ import logging import os import ssl import urllib.request +from collections.abc import Mapping +from typing import Any from urllib import parse from urllib.error import HTTPError @@ -19,9 +21,9 @@ urllib.request.install_opener(opener) logger = logging.getLogger(__name__) -def http_request(url, timeout, headers={}): +def http_request(url: str, timeout: int | float, headers: Mapping[str, str] = {}) -> tuple[int, str | None]: try: - request = urllib.request.Request(url, headers=headers) + request = urllib.request.Request(url, headers=dict(headers)) res = urllib.request.urlopen(request, timeout=timeout) body = res.read().decode("utf-8") return res.code, body @@ -33,9 +35,9 @@ def http_request(url, timeout, headers={}): raise e -def url_encode(params): +def url_encode(params: dict[str, Any]) -> str: return parse.urlencode(params) -def makedirs_wrapper(path): +def makedirs_wrapper(path: str) -> None: os.makedirs(path, exist_ok=True) diff --git a/api/configs/remote_settings_sources/apollo/utils.py b/api/configs/remote_settings_sources/apollo/utils.py index f5b82908ee..cff187954d 100644 --- a/api/configs/remote_settings_sources/apollo/utils.py +++ b/api/configs/remote_settings_sources/apollo/utils.py @@ -1,5 +1,6 @@ import hashlib import socket +from typing import Any from .python_3x import url_encode @@ -10,7 +11,7 @@ NAMESPACE_NAME = "namespaceName" # add timestamps uris and keys -def signature(timestamp, uri, secret): +def signature(timestamp: str, uri: str, secret: str) -> str: import base64 import hmac @@ -19,16 +20,16 @@ def signature(timestamp, uri, secret): return base64.b64encode(hmac_code).decode() -def url_encode_wrapper(params): +def url_encode_wrapper(params: dict[str, Any]) -> str: return url_encode(params) -def no_key_cache_key(namespace, key): +def no_key_cache_key(namespace: str, key: str) -> str: return f"{namespace}{len(namespace)}{key}" # Returns whether the obtained value is obtained, and None if it does not -def get_value_from_dict(namespace_cache, key): +def get_value_from_dict(namespace_cache: dict[str, Any] | None, key: str) -> Any | None: if namespace_cache: kv_data = namespace_cache.get(CONFIGURATIONS) if kv_data is None: @@ -38,7 +39,7 @@ def get_value_from_dict(namespace_cache, key): return None -def init_ip(): +def init_ip() -> str: ip = "" s = None try: diff --git a/api/configs/remote_settings_sources/nacos/__init__.py b/api/configs/remote_settings_sources/nacos/__init__.py index c6efd6f3ac..f3e6306753 100644 --- a/api/configs/remote_settings_sources/nacos/__init__.py +++ b/api/configs/remote_settings_sources/nacos/__init__.py @@ -11,16 +11,16 @@ logger = logging.getLogger(__name__) from configs.remote_settings_sources.base import RemoteSettingsSource -from .utils import _parse_config +from .utils import parse_config class NacosSettingsSource(RemoteSettingsSource): def __init__(self, configs: Mapping[str, Any]): self.configs = configs - self.remote_configs: dict[str, Any] = {} + self.remote_configs: dict[str, str] = {} self.async_init() - def async_init(self): + def async_init(self) -> None: data_id = os.getenv("DIFY_ENV_NACOS_DATA_ID", "dify-api-env.properties") group = os.getenv("DIFY_ENV_NACOS_GROUP", "nacos-dify") tenant = os.getenv("DIFY_ENV_NACOS_NAMESPACE", "") @@ -33,18 +33,15 @@ class NacosSettingsSource(RemoteSettingsSource): logger.exception("[get-access-token] exception occurred") raise - def _parse_config(self, content: str): + def _parse_config(self, content: str) -> dict[str, str]: if not content: return {} try: - return _parse_config(self, content) + return parse_config(content) except Exception as e: raise RuntimeError(f"Failed to parse config: {e}") def get_field_value(self, field: FieldInfo, field_name: str) -> tuple[Any, str, bool]: - if not isinstance(self.remote_configs, dict): - raise ValueError(f"remote configs is not dict, but {type(self.remote_configs)}") - field_value = self.remote_configs.get(field_name) if field_value is None: return None, field_name, False diff --git a/api/configs/remote_settings_sources/nacos/http_request.py b/api/configs/remote_settings_sources/nacos/http_request.py index db9db84a80..6401c5830d 100644 --- a/api/configs/remote_settings_sources/nacos/http_request.py +++ b/api/configs/remote_settings_sources/nacos/http_request.py @@ -17,11 +17,17 @@ class NacosHttpClient: self.ak = os.getenv("DIFY_ENV_NACOS_ACCESS_KEY") self.sk = os.getenv("DIFY_ENV_NACOS_SECRET_KEY") self.server = os.getenv("DIFY_ENV_NACOS_SERVER_ADDR", "localhost:8848") - self.token = None + self.token: str | None = None self.token_ttl = 18000 self.token_expire_time: float = 0 - def http_request(self, url, method="GET", headers=None, params=None): + def http_request( + self, url: str, method: str = "GET", headers: dict[str, str] | None = None, params: dict[str, str] | None = None + ) -> str: + if headers is None: + headers = {} + if params is None: + params = {} try: self._inject_auth_info(headers, params) response = requests.request(method, url="http://" + self.server + url, headers=headers, params=params) @@ -30,7 +36,7 @@ class NacosHttpClient: except requests.RequestException as e: return f"Request to Nacos failed: {e}" - def _inject_auth_info(self, headers, params, module="config"): + def _inject_auth_info(self, headers: dict[str, str], params: dict[str, str], module: str = "config") -> None: headers.update({"User-Agent": "Nacos-Http-Client-In-Dify:v0.0.1"}) if module == "login": @@ -45,16 +51,17 @@ class NacosHttpClient: headers["timeStamp"] = ts if self.username and self.password: self.get_access_token(force_refresh=False) - params["accessToken"] = self.token + if self.token is not None: + params["accessToken"] = self.token - def __do_sign(self, sign_str, sk): + def __do_sign(self, sign_str: str, sk: str) -> str: return ( base64.encodebytes(hmac.new(sk.encode(), sign_str.encode(), digestmod=hashlib.sha1).digest()) .decode() .strip() ) - def get_sign_str(self, group, tenant, ts): + def get_sign_str(self, group: str, tenant: str, ts: str) -> str: sign_str = "" if tenant: sign_str = tenant + "+" @@ -63,7 +70,7 @@ class NacosHttpClient: sign_str += ts # Directly concatenate ts without conditional checks, because the nacos auth header forced it. return sign_str - def get_access_token(self, force_refresh=False): + def get_access_token(self, force_refresh: bool = False) -> str | None: current_time = time.time() if self.token and not force_refresh and self.token_expire_time > current_time: return self.token @@ -77,6 +84,7 @@ class NacosHttpClient: self.token = response_data.get("accessToken") self.token_ttl = response_data.get("tokenTtl", 18000) self.token_expire_time = current_time + self.token_ttl - 10 + return self.token except Exception: logger.exception("[get-access-token] exception occur") raise diff --git a/api/configs/remote_settings_sources/nacos/utils.py b/api/configs/remote_settings_sources/nacos/utils.py index f3372563b1..2d52b46af9 100644 --- a/api/configs/remote_settings_sources/nacos/utils.py +++ b/api/configs/remote_settings_sources/nacos/utils.py @@ -1,4 +1,4 @@ -def _parse_config(self, content: str) -> dict[str, str]: +def parse_config(content: str) -> dict[str, str]: config: dict[str, str] = {} if not content: return config diff --git a/api/pyrightconfig.json b/api/pyrightconfig.json index dfffdb8cff..8694f44fae 100644 --- a/api/pyrightconfig.json +++ b/api/pyrightconfig.json @@ -1,5 +1,7 @@ { - "include": ["."], + "include": [ + "." + ], "exclude": [ "tests/", "migrations/", @@ -19,10 +21,9 @@ "events/", "contexts/", "constants/", - "configs/", "commands.py" ], "typeCheckingMode": "strict", "pythonVersion": "3.11", "pythonPlatform": "All" -} +} \ No newline at end of file From 81fdc7c54b082df22cfd8dcbdf0253fafe257b2d Mon Sep 17 00:00:00 2001 From: -LAN- Date: Sat, 6 Sep 2025 16:09:59 +0800 Subject: [PATCH 32/52] fix: type errors Signed-off-by: -LAN- --- api/core/app/apps/advanced_chat/app_runner.py | 1 + api/core/app/apps/workflow/app_runner.py | 1 + api/models/tools.py | 2 +- 3 files changed, 3 insertions(+), 1 deletion(-) diff --git a/api/core/app/apps/advanced_chat/app_runner.py b/api/core/app/apps/advanced_chat/app_runner.py index 93d204a8f2..61fed3bae9 100644 --- a/api/core/app/apps/advanced_chat/app_runner.py +++ b/api/core/app/apps/advanced_chat/app_runner.py @@ -184,6 +184,7 @@ class AdvancedChatAppRunner(WorkflowBasedAppRunner): ), invoke_from=self.application_generate_entity.invoke_from, call_depth=self.application_generate_entity.call_depth, + variable_pool=variable_pool, graph_runtime_state=graph_runtime_state, command_channel=command_channel, ) diff --git a/api/core/app/apps/workflow/app_runner.py b/api/core/app/apps/workflow/app_runner.py index 5b857a2a7c..64ed9369d2 100644 --- a/api/core/app/apps/workflow/app_runner.py +++ b/api/core/app/apps/workflow/app_runner.py @@ -127,6 +127,7 @@ class WorkflowAppRunner(WorkflowBasedAppRunner): ), invoke_from=self.application_generate_entity.invoke_from, call_depth=self.application_generate_entity.call_depth, + variable_pool=variable_pool, graph_runtime_state=graph_runtime_state, command_channel=command_channel, ) diff --git a/api/models/tools.py b/api/models/tools.py index 443a4dce84..ee8f75ac04 100644 --- a/api/models/tools.py +++ b/api/models/tools.py @@ -1,6 +1,6 @@ import json from datetime import datetime -from typing import TYPE_CHECKING, Any, cast +from typing import TYPE_CHECKING, Optional, cast from urllib.parse import urlparse import sqlalchemy as sa From 9964cc202d83fe55dacb2e83edf6c13b1b267a6f Mon Sep 17 00:00:00 2001 From: NeatGuyCoding <15627489+NeatGuyCoding@users.noreply.github.com> Date: Sat, 6 Sep 2025 16:18:26 +0800 Subject: [PATCH 33/52] Feature add test containers batch clean document (#25287) Co-authored-by: crazywoola <100913391+crazywoola@users.noreply.github.com> --- .../tasks/test_batch_clean_document_task.py | 720 ++++++++++++++++++ 1 file changed, 720 insertions(+) create mode 100644 api/tests/test_containers_integration_tests/tasks/test_batch_clean_document_task.py diff --git a/api/tests/test_containers_integration_tests/tasks/test_batch_clean_document_task.py b/api/tests/test_containers_integration_tests/tasks/test_batch_clean_document_task.py new file mode 100644 index 0000000000..03b1539399 --- /dev/null +++ b/api/tests/test_containers_integration_tests/tasks/test_batch_clean_document_task.py @@ -0,0 +1,720 @@ +""" +Integration tests for batch_clean_document_task using testcontainers. + +This module tests the batch document cleaning functionality with real database +and storage containers to ensure proper cleanup of documents, segments, and files. +""" + +import json +import uuid +from unittest.mock import Mock, patch + +import pytest +from faker import Faker + +from extensions.ext_database import db +from models.account import Account, Tenant, TenantAccountJoin, TenantAccountRole +from models.dataset import Dataset, Document, DocumentSegment +from models.model import UploadFile +from tasks.batch_clean_document_task import batch_clean_document_task + + +class TestBatchCleanDocumentTask: + """Integration tests for batch_clean_document_task using testcontainers.""" + + @pytest.fixture + def mock_external_service_dependencies(self): + """Mock setup for external service dependencies.""" + with ( + patch("extensions.ext_storage.storage") as mock_storage, + patch("core.rag.index_processor.index_processor_factory.IndexProcessorFactory") as mock_index_factory, + patch("core.tools.utils.web_reader_tool.get_image_upload_file_ids") as mock_get_image_ids, + ): + # Setup default mock returns + mock_storage.delete.return_value = None + + # Mock index processor + mock_index_processor = Mock() + mock_index_processor.clean.return_value = None + mock_index_factory.return_value.init_index_processor.return_value = mock_index_processor + + # Mock image file ID extraction + mock_get_image_ids.return_value = [] + + yield { + "storage": mock_storage, + "index_factory": mock_index_factory, + "index_processor": mock_index_processor, + "get_image_ids": mock_get_image_ids, + } + + def _create_test_account(self, db_session_with_containers): + """ + Helper method to create a test account for testing. + + Args: + db_session_with_containers: Database session from testcontainers infrastructure + + Returns: + Account: Created account instance + """ + fake = Faker() + + # Create account + account = Account( + email=fake.email(), + name=fake.name(), + interface_language="en-US", + status="active", + ) + + db.session.add(account) + db.session.commit() + + # Create tenant for the account + tenant = Tenant( + name=fake.company(), + status="normal", + ) + db.session.add(tenant) + db.session.commit() + + # Create tenant-account join + join = TenantAccountJoin( + tenant_id=tenant.id, + account_id=account.id, + role=TenantAccountRole.OWNER.value, + current=True, + ) + db.session.add(join) + db.session.commit() + + # Set current tenant for account + account.current_tenant = tenant + + return account + + def _create_test_dataset(self, db_session_with_containers, account): + """ + Helper method to create a test dataset for testing. + + Args: + db_session_with_containers: Database session from testcontainers infrastructure + account: Account instance + + Returns: + Dataset: Created dataset instance + """ + fake = Faker() + + dataset = Dataset( + id=str(uuid.uuid4()), + tenant_id=account.current_tenant.id, + name=fake.word(), + description=fake.sentence(), + data_source_type="upload_file", + created_by=account.id, + embedding_model="text-embedding-ada-002", + embedding_model_provider="openai", + ) + + db.session.add(dataset) + db.session.commit() + + return dataset + + def _create_test_document(self, db_session_with_containers, dataset, account): + """ + Helper method to create a test document for testing. + + Args: + db_session_with_containers: Database session from testcontainers infrastructure + dataset: Dataset instance + account: Account instance + + Returns: + Document: Created document instance + """ + fake = Faker() + + document = Document( + id=str(uuid.uuid4()), + tenant_id=account.current_tenant.id, + dataset_id=dataset.id, + position=0, + name=fake.word(), + data_source_type="upload_file", + data_source_info=json.dumps({"upload_file_id": str(uuid.uuid4())}), + batch="test_batch", + created_from="test", + created_by=account.id, + indexing_status="completed", + doc_form="text_model", + ) + + db.session.add(document) + db.session.commit() + + return document + + def _create_test_document_segment(self, db_session_with_containers, document, account): + """ + Helper method to create a test document segment for testing. + + Args: + db_session_with_containers: Database session from testcontainers infrastructure + document: Document instance + account: Account instance + + Returns: + DocumentSegment: Created document segment instance + """ + fake = Faker() + + segment = DocumentSegment( + id=str(uuid.uuid4()), + tenant_id=account.current_tenant.id, + dataset_id=document.dataset_id, + document_id=document.id, + position=0, + content=fake.text(), + word_count=100, + tokens=50, + index_node_id=str(uuid.uuid4()), + created_by=account.id, + status="completed", + ) + + db.session.add(segment) + db.session.commit() + + return segment + + def _create_test_upload_file(self, db_session_with_containers, account): + """ + Helper method to create a test upload file for testing. + + Args: + db_session_with_containers: Database session from testcontainers infrastructure + account: Account instance + + Returns: + UploadFile: Created upload file instance + """ + fake = Faker() + from datetime import datetime + + from models.enums import CreatorUserRole + + upload_file = UploadFile( + tenant_id=account.current_tenant.id, + storage_type="local", + key=f"test_files/{fake.file_name()}", + name=fake.file_name(), + size=1024, + extension="txt", + mime_type="text/plain", + created_by_role=CreatorUserRole.ACCOUNT, + created_by=account.id, + created_at=datetime.utcnow(), + used=False, + ) + + db.session.add(upload_file) + db.session.commit() + + return upload_file + + def test_batch_clean_document_task_successful_cleanup( + self, db_session_with_containers, mock_external_service_dependencies + ): + """ + Test successful cleanup of documents with segments and files. + + This test verifies that the task properly cleans up: + - Document segments from the index + - Associated image files from storage + - Upload files from storage and database + """ + # Create test data + account = self._create_test_account(db_session_with_containers) + dataset = self._create_test_dataset(db_session_with_containers, account) + document = self._create_test_document(db_session_with_containers, dataset, account) + segment = self._create_test_document_segment(db_session_with_containers, document, account) + upload_file = self._create_test_upload_file(db_session_with_containers, account) + + # Update document to reference the upload file + document.data_source_info = json.dumps({"upload_file_id": upload_file.id}) + db.session.commit() + + # Store original IDs for verification + document_id = document.id + segment_id = segment.id + file_id = upload_file.id + + # Execute the task + batch_clean_document_task( + document_ids=[document_id], dataset_id=dataset.id, doc_form=dataset.doc_form, file_ids=[file_id] + ) + + # Verify that the task completed successfully + # The task should have processed the segment and cleaned up the database + + # Verify database cleanup + db.session.commit() # Ensure all changes are committed + + # Check that segment is deleted + deleted_segment = db.session.query(DocumentSegment).filter_by(id=segment_id).first() + assert deleted_segment is None + + # Check that upload file is deleted + deleted_file = db.session.query(UploadFile).filter_by(id=file_id).first() + assert deleted_file is None + + def test_batch_clean_document_task_with_image_files( + self, db_session_with_containers, mock_external_service_dependencies + ): + """ + Test cleanup of documents containing image references. + + This test verifies that the task properly handles documents with + image content and cleans up associated segments. + """ + # Create test data + account = self._create_test_account(db_session_with_containers) + dataset = self._create_test_dataset(db_session_with_containers, account) + document = self._create_test_document(db_session_with_containers, dataset, account) + + # Create segment with simple content (no image references) + segment = DocumentSegment( + id=str(uuid.uuid4()), + tenant_id=account.current_tenant.id, + dataset_id=document.dataset_id, + document_id=document.id, + position=0, + content="Simple text content without images", + word_count=100, + tokens=50, + index_node_id=str(uuid.uuid4()), + created_by=account.id, + status="completed", + ) + + db.session.add(segment) + db.session.commit() + + # Store original IDs for verification + segment_id = segment.id + document_id = document.id + + # Execute the task + batch_clean_document_task( + document_ids=[document_id], dataset_id=dataset.id, doc_form=dataset.doc_form, file_ids=[] + ) + + # Verify database cleanup + db.session.commit() + + # Check that segment is deleted + deleted_segment = db.session.query(DocumentSegment).filter_by(id=segment_id).first() + assert deleted_segment is None + + # Verify that the task completed successfully by checking the log output + # The task should have processed the segment and cleaned up the database + + def test_batch_clean_document_task_no_segments( + self, db_session_with_containers, mock_external_service_dependencies + ): + """ + Test cleanup when document has no segments. + + This test verifies that the task handles documents without segments + gracefully and still cleans up associated files. + """ + # Create test data without segments + account = self._create_test_account(db_session_with_containers) + dataset = self._create_test_dataset(db_session_with_containers, account) + document = self._create_test_document(db_session_with_containers, dataset, account) + upload_file = self._create_test_upload_file(db_session_with_containers, account) + + # Update document to reference the upload file + document.data_source_info = json.dumps({"upload_file_id": upload_file.id}) + db.session.commit() + + # Store original IDs for verification + document_id = document.id + file_id = upload_file.id + + # Execute the task + batch_clean_document_task( + document_ids=[document_id], dataset_id=dataset.id, doc_form=dataset.doc_form, file_ids=[file_id] + ) + + # Verify that the task completed successfully + # Since there are no segments, the task should handle this gracefully + + # Verify database cleanup + db.session.commit() + + # Check that upload file is deleted + deleted_file = db.session.query(UploadFile).filter_by(id=file_id).first() + assert deleted_file is None + + # Verify database cleanup + db.session.commit() + + # Check that upload file is deleted + deleted_file = db.session.query(UploadFile).filter_by(id=file_id).first() + assert deleted_file is None + + def test_batch_clean_document_task_dataset_not_found( + self, db_session_with_containers, mock_external_service_dependencies + ): + """ + Test cleanup when dataset is not found. + + This test verifies that the task properly handles the case where + the specified dataset does not exist in the database. + """ + # Create test data + account = self._create_test_account(db_session_with_containers) + dataset = self._create_test_dataset(db_session_with_containers, account) + document = self._create_test_document(db_session_with_containers, dataset, account) + + # Store original IDs for verification + document_id = document.id + dataset_id = dataset.id + + # Delete the dataset to simulate not found scenario + db.session.delete(dataset) + db.session.commit() + + # Execute the task with non-existent dataset + batch_clean_document_task(document_ids=[document_id], dataset_id=dataset_id, doc_form="text_model", file_ids=[]) + + # Verify that no index processing occurred + mock_external_service_dependencies["index_processor"].clean.assert_not_called() + + # Verify that no storage operations occurred + mock_external_service_dependencies["storage"].delete.assert_not_called() + + # Verify that no database cleanup occurred + db.session.commit() + + # Document should still exist since cleanup failed + existing_document = db.session.query(Document).filter_by(id=document_id).first() + assert existing_document is not None + + def test_batch_clean_document_task_storage_cleanup_failure( + self, db_session_with_containers, mock_external_service_dependencies + ): + """ + Test cleanup when storage operations fail. + + This test verifies that the task continues processing even when + storage cleanup operations fail, ensuring database cleanup still occurs. + """ + # Create test data + account = self._create_test_account(db_session_with_containers) + dataset = self._create_test_dataset(db_session_with_containers, account) + document = self._create_test_document(db_session_with_containers, dataset, account) + segment = self._create_test_document_segment(db_session_with_containers, document, account) + upload_file = self._create_test_upload_file(db_session_with_containers, account) + + # Update document to reference the upload file + document.data_source_info = json.dumps({"upload_file_id": upload_file.id}) + db.session.commit() + + # Store original IDs for verification + document_id = document.id + segment_id = segment.id + file_id = upload_file.id + + # Mock storage.delete to raise an exception + mock_external_service_dependencies["storage"].delete.side_effect = Exception("Storage error") + + # Execute the task + batch_clean_document_task( + document_ids=[document_id], dataset_id=dataset.id, doc_form=dataset.doc_form, file_ids=[file_id] + ) + + # Verify that the task completed successfully despite storage failure + # The task should continue processing even when storage operations fail + + # Verify database cleanup still occurred despite storage failure + db.session.commit() + + # Check that segment is deleted from database + deleted_segment = db.session.query(DocumentSegment).filter_by(id=segment_id).first() + assert deleted_segment is None + + # Check that upload file is deleted from database + deleted_file = db.session.query(UploadFile).filter_by(id=file_id).first() + assert deleted_file is None + + def test_batch_clean_document_task_multiple_documents( + self, db_session_with_containers, mock_external_service_dependencies + ): + """ + Test cleanup of multiple documents in a single batch operation. + + This test verifies that the task can handle multiple documents + efficiently and cleans up all associated resources. + """ + # Create test data for multiple documents + account = self._create_test_account(db_session_with_containers) + dataset = self._create_test_dataset(db_session_with_containers, account) + + documents = [] + segments = [] + upload_files = [] + + # Create 3 documents with segments and files + for i in range(3): + document = self._create_test_document(db_session_with_containers, dataset, account) + segment = self._create_test_document_segment(db_session_with_containers, document, account) + upload_file = self._create_test_upload_file(db_session_with_containers, account) + + # Update document to reference the upload file + document.data_source_info = json.dumps({"upload_file_id": upload_file.id}) + + documents.append(document) + segments.append(segment) + upload_files.append(upload_file) + + db.session.commit() + + # Store original IDs for verification + document_ids = [doc.id for doc in documents] + segment_ids = [seg.id for seg in segments] + file_ids = [file.id for file in upload_files] + + # Execute the task with multiple documents + batch_clean_document_task( + document_ids=document_ids, dataset_id=dataset.id, doc_form=dataset.doc_form, file_ids=file_ids + ) + + # Verify that the task completed successfully for all documents + # The task should process all documents and clean up all associated resources + + # Verify database cleanup for all resources + db.session.commit() + + # Check that all segments are deleted + for segment_id in segment_ids: + deleted_segment = db.session.query(DocumentSegment).filter_by(id=segment_id).first() + assert deleted_segment is None + + # Check that all upload files are deleted + for file_id in file_ids: + deleted_file = db.session.query(UploadFile).filter_by(id=file_id).first() + assert deleted_file is None + + def test_batch_clean_document_task_different_doc_forms( + self, db_session_with_containers, mock_external_service_dependencies + ): + """ + Test cleanup with different document form types. + + This test verifies that the task properly handles different + document form types and creates the appropriate index processor. + """ + # Create test data + account = self._create_test_account(db_session_with_containers) + + # Test different doc_form types + doc_forms = ["text_model", "qa_model", "hierarchical_model"] + + for doc_form in doc_forms: + dataset = self._create_test_dataset(db_session_with_containers, account) + db.session.commit() + + document = self._create_test_document(db_session_with_containers, dataset, account) + # Update document doc_form + document.doc_form = doc_form + db.session.commit() + + segment = self._create_test_document_segment(db_session_with_containers, document, account) + + # Store the ID before the object is deleted + segment_id = segment.id + + try: + # Execute the task + batch_clean_document_task( + document_ids=[document.id], dataset_id=dataset.id, doc_form=doc_form, file_ids=[] + ) + + # Verify that the task completed successfully for this doc_form + # The task should handle different document forms correctly + + # Verify database cleanup + db.session.commit() + + # Check that segment is deleted + deleted_segment = db.session.query(DocumentSegment).filter_by(id=segment_id).first() + assert deleted_segment is None + + except Exception as e: + # If the task fails due to external service issues (e.g., plugin daemon), + # we should still verify that the database state is consistent + # This is a common scenario in test environments where external services may not be available + db.session.commit() + + # Check if the segment still exists (task may have failed before deletion) + existing_segment = db.session.query(DocumentSegment).filter_by(id=segment_id).first() + if existing_segment is not None: + # If segment still exists, the task failed before deletion + # This is acceptable in test environments with external service issues + pass + else: + # If segment was deleted, the task succeeded + pass + + def test_batch_clean_document_task_large_batch_performance( + self, db_session_with_containers, mock_external_service_dependencies + ): + """ + Test cleanup performance with a large batch of documents. + + This test verifies that the task can handle large batches efficiently + and maintains performance characteristics. + """ + import time + + # Create test data for large batch + account = self._create_test_account(db_session_with_containers) + dataset = self._create_test_dataset(db_session_with_containers, account) + + documents = [] + segments = [] + upload_files = [] + + # Create 10 documents with segments and files (larger batch) + batch_size = 10 + for i in range(batch_size): + document = self._create_test_document(db_session_with_containers, dataset, account) + segment = self._create_test_document_segment(db_session_with_containers, document, account) + upload_file = self._create_test_upload_file(db_session_with_containers, account) + + # Update document to reference the upload file + document.data_source_info = json.dumps({"upload_file_id": upload_file.id}) + + documents.append(document) + segments.append(segment) + upload_files.append(upload_file) + + db.session.commit() + + # Store original IDs for verification + document_ids = [doc.id for doc in documents] + segment_ids = [seg.id for seg in segments] + file_ids = [file.id for file in upload_files] + + # Measure execution time + start_time = time.perf_counter() + + # Execute the task with large batch + batch_clean_document_task( + document_ids=document_ids, dataset_id=dataset.id, doc_form=dataset.doc_form, file_ids=file_ids + ) + + end_time = time.perf_counter() + execution_time = end_time - start_time + + # Verify performance characteristics (should complete within reasonable time) + assert execution_time < 5.0 # Should complete within 5 seconds + + # Verify that the task completed successfully for the large batch + # The task should handle large batches efficiently + + # Verify database cleanup for all resources + db.session.commit() + + # Check that all segments are deleted + for segment_id in segment_ids: + deleted_segment = db.session.query(DocumentSegment).filter_by(id=segment_id).first() + assert deleted_segment is None + + # Check that all upload files are deleted + for file_id in file_ids: + deleted_file = db.session.query(UploadFile).filter_by(id=file_id).first() + assert deleted_file is None + + def test_batch_clean_document_task_integration_with_real_database( + self, db_session_with_containers, mock_external_service_dependencies + ): + """ + Test full integration with real database operations. + + This test verifies that the task integrates properly with the + actual database and maintains data consistency throughout the process. + """ + # Create test data + account = self._create_test_account(db_session_with_containers) + dataset = self._create_test_dataset(db_session_with_containers, account) + + # Create document with complex structure + document = self._create_test_document(db_session_with_containers, dataset, account) + + # Create multiple segments for the document + segments = [] + for i in range(3): + segment = DocumentSegment( + id=str(uuid.uuid4()), + tenant_id=account.current_tenant.id, + dataset_id=document.dataset_id, + document_id=document.id, + position=i, + content=f"Segment content {i} with some text", + word_count=50 + i * 10, + tokens=25 + i * 5, + index_node_id=str(uuid.uuid4()), + created_by=account.id, + status="completed", + ) + segments.append(segment) + + # Create upload file + upload_file = self._create_test_upload_file(db_session_with_containers, account) + + # Update document to reference the upload file + document.data_source_info = json.dumps({"upload_file_id": upload_file.id}) + + # Add all to database + for segment in segments: + db.session.add(segment) + db.session.commit() + + # Verify initial state + assert db.session.query(DocumentSegment).filter_by(document_id=document.id).count() == 3 + assert db.session.query(UploadFile).filter_by(id=upload_file.id).first() is not None + + # Store original IDs for verification + document_id = document.id + segment_ids = [seg.id for seg in segments] + file_id = upload_file.id + + # Execute the task + batch_clean_document_task( + document_ids=[document_id], dataset_id=dataset.id, doc_form=dataset.doc_form, file_ids=[file_id] + ) + + # Verify that the task completed successfully + # The task should process all segments and clean up all associated resources + + # Verify database cleanup + db.session.commit() + + # Check that all segments are deleted + for segment_id in segment_ids: + deleted_segment = db.session.query(DocumentSegment).filter_by(id=segment_id).first() + assert deleted_segment is None + + # Check that upload file is deleted + deleted_file = db.session.query(UploadFile).filter_by(id=file_id).first() + assert deleted_file is None + + # Verify final database state + assert db.session.query(DocumentSegment).filter_by(document_id=document_id).count() == 0 + assert db.session.query(UploadFile).filter_by(id=file_id).first() is None From 3c28936796a9b3e5784e15c49cbbe72503ad7641 Mon Sep 17 00:00:00 2001 From: -LAN- Date: Sat, 6 Sep 2025 16:21:28 +0800 Subject: [PATCH 34/52] fix: test Signed-off-by: -LAN- --- .../core/workflow/test_workflow_entry_redis_channel.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/api/tests/unit_tests/core/workflow/test_workflow_entry_redis_channel.py b/api/tests/unit_tests/core/workflow/test_workflow_entry_redis_channel.py index e9cef2174b..c3d59aaf3f 100644 --- a/api/tests/unit_tests/core/workflow/test_workflow_entry_redis_channel.py +++ b/api/tests/unit_tests/core/workflow/test_workflow_entry_redis_channel.py @@ -41,6 +41,7 @@ class TestWorkflowEntryRedisChannel: user_from=UserFrom.ACCOUNT, invoke_from=InvokeFrom.DEBUGGER, call_depth=0, + variable_pool=mock_variable_pool, graph_runtime_state=mock_graph_runtime_state, command_channel=redis_channel, # Provide Redis channel ) @@ -81,6 +82,7 @@ class TestWorkflowEntryRedisChannel: user_from=UserFrom.ACCOUNT, invoke_from=InvokeFrom.DEBUGGER, call_depth=0, + variable_pool=mock_variable_pool, graph_runtime_state=mock_graph_runtime_state, command_channel=None, # No channel provided ) @@ -128,6 +130,7 @@ class TestWorkflowEntryRedisChannel: user_from=UserFrom.ACCOUNT, invoke_from=InvokeFrom.DEBUGGER, call_depth=0, + variable_pool=mock_variable_pool, graph_runtime_state=mock_graph_runtime_state, command_channel=redis_channel, ) From bbc43ca50d3674f6a50f788264a51f9daadf79cf Mon Sep 17 00:00:00 2001 From: Asuka Minato Date: Sat, 6 Sep 2025 23:53:01 +0900 Subject: [PATCH 35/52] example of no-unstable-context-value (#25279) --- .../components/app/configuration/index.tsx | 153 +++++++++--------- 1 file changed, 76 insertions(+), 77 deletions(-) diff --git a/web/app/components/app/configuration/index.tsx b/web/app/components/app/configuration/index.tsx index 512f57bccf..2bdab368fe 100644 --- a/web/app/components/app/configuration/index.tsx +++ b/web/app/components/app/configuration/index.tsx @@ -850,84 +850,83 @@ const Configuration: FC = () => {
} - + const value = { + appId, + isAPIKeySet, + isTrailFinished: false, + mode, + modelModeType, + promptMode, + isAdvancedMode, + isAgent, + isOpenAI, + isFunctionCall, + collectionList, + setPromptMode, + canReturnToSimpleMode, + setCanReturnToSimpleMode, + chatPromptConfig, + completionPromptConfig, + currentAdvancedPrompt, + setCurrentAdvancedPrompt, + conversationHistoriesRole: completionPromptConfig.conversation_histories_role, + showHistoryModal, + setConversationHistoriesRole, + hasSetBlockStatus, + conversationId, + introduction, + setIntroduction, + suggestedQuestions, + setSuggestedQuestions, + setConversationId, + controlClearChatMessage, + setControlClearChatMessage, + prevPromptConfig, + setPrevPromptConfig, + moreLikeThisConfig, + setMoreLikeThisConfig, + suggestedQuestionsAfterAnswerConfig, + setSuggestedQuestionsAfterAnswerConfig, + speechToTextConfig, + setSpeechToTextConfig, + textToSpeechConfig, + setTextToSpeechConfig, + citationConfig, + setCitationConfig, + annotationConfig, + setAnnotationConfig, + moderationConfig, + setModerationConfig, + externalDataToolsConfig, + setExternalDataToolsConfig, + formattingChanged, + setFormattingChanged, + inputs, + setInputs, + query, + setQuery, + completionParams, + setCompletionParams, + modelConfig, + setModelConfig, + showSelectDataSet, + dataSets, + setDataSets, + datasetConfigs, + datasetConfigsRef, + setDatasetConfigs, + hasSetContextVar, + isShowVisionConfig, + visionConfig, + setVisionConfig: handleSetVisionConfig, + isAllowVideoUpload, + isShowDocumentConfig, + isShowAudioConfig, + rerankSettingModalOpen, + setRerankSettingModalOpen, + } return ( - +
From afa722807612ffbb1b663151b5b7165b2aa6bd27 Mon Sep 17 00:00:00 2001 From: NeatGuyCoding <15627489+NeatGuyCoding@users.noreply.github.com> Date: Sat, 6 Sep 2025 22:53:26 +0800 Subject: [PATCH 36/52] fix: a failed index to be marked as created (#25290) Co-authored-by: crazywoola <100913391+crazywoola@users.noreply.github.com> --- api/core/rag/datasource/vdb/matrixone/matrixone_vector.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api/core/rag/datasource/vdb/matrixone/matrixone_vector.py b/api/core/rag/datasource/vdb/matrixone/matrixone_vector.py index 1bf8da5daa..9660cf8aba 100644 --- a/api/core/rag/datasource/vdb/matrixone/matrixone_vector.py +++ b/api/core/rag/datasource/vdb/matrixone/matrixone_vector.py @@ -99,9 +99,9 @@ class MatrixoneVector(BaseVector): return client try: client.create_full_text_index() + redis_client.set(collection_exist_cache_key, 1, ex=3600) except Exception: logger.exception("Failed to create full text index") - redis_client.set(collection_exist_cache_key, 1, ex=3600) return client def add_texts(self, documents: list[Document], embeddings: list[list[float]], **kwargs): From cc1d437dc17e620e419629fb4acc7bfacfaed329 Mon Sep 17 00:00:00 2001 From: -LAN- Date: Sun, 7 Sep 2025 12:48:50 +0800 Subject: [PATCH 37/52] fix: correct indentation in TokenBufferMemory get_history_prompt_messages method --- api/core/memory/token_buffer_memory.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/api/core/memory/token_buffer_memory.py b/api/core/memory/token_buffer_memory.py index 20a120840e..f2178b0270 100644 --- a/api/core/memory/token_buffer_memory.py +++ b/api/core/memory/token_buffer_memory.py @@ -167,11 +167,11 @@ class TokenBufferMemory: else: prompt_messages.append(AssistantPromptMessage(content=message.answer)) - if not prompt_messages: - return [] + if not prompt_messages: + return [] - # prune the chat message if it exceeds the max token limit - curr_message_tokens = self.model_instance.get_llm_num_tokens(prompt_messages) + # prune the chat message if it exceeds the max token limit + curr_message_tokens = self.model_instance.get_llm_num_tokens(prompt_messages) if curr_message_tokens > max_token_limit: while curr_message_tokens > max_token_limit and len(prompt_messages) > 1: From 92a939c40117449b750e23a6929d08b644784896 Mon Sep 17 00:00:00 2001 From: -LAN- Date: Sun, 7 Sep 2025 21:29:59 +0800 Subject: [PATCH 38/52] chore: ignore PWA generated files in version control (#25313) Signed-off-by: -LAN- --- .gitignore | 7 +++++++ web/public/fallback-hxi5kegOl0PxtKhvDL_OX.js | 1 - web/public/sw.js | 1 - 3 files changed, 7 insertions(+), 2 deletions(-) delete mode 100644 web/public/fallback-hxi5kegOl0PxtKhvDL_OX.js delete mode 100644 web/public/sw.js diff --git a/.gitignore b/.gitignore index 8a5a34cf88..03ff04d823 100644 --- a/.gitignore +++ b/.gitignore @@ -215,6 +215,13 @@ mise.toml # Next.js build output .next/ +# PWA generated files +web/public/sw.js +web/public/sw.js.map +web/public/workbox-*.js +web/public/workbox-*.js.map +web/public/fallback-*.js + # AI Assistant .roo/ api/.env.backup diff --git a/web/public/fallback-hxi5kegOl0PxtKhvDL_OX.js b/web/public/fallback-hxi5kegOl0PxtKhvDL_OX.js deleted file mode 100644 index b24fdf0702..0000000000 --- a/web/public/fallback-hxi5kegOl0PxtKhvDL_OX.js +++ /dev/null @@ -1 +0,0 @@ -(()=>{"use strict";self.fallback=async e=>"document"===e.destination?caches.match("/_offline.html",{ignoreSearch:!0}):Response.error()})(); \ No newline at end of file diff --git a/web/public/sw.js b/web/public/sw.js deleted file mode 100644 index fd0d1166ca..0000000000 --- a/web/public/sw.js +++ /dev/null @@ -1 +0,0 @@ -if(!self.define){let e,s={};const a=(a,c)=>(a=new URL(a+".js",c).href,s[a]||new Promise(s=>{if("document"in self){const e=document.createElement("script");e.src=a,e.onload=s,document.head.appendChild(e)}else e=a,importScripts(a),s()}).then(()=>{let e=s[a];if(!e)throw new Error(`Module ${a} didn’t register its module`);return e}));self.define=(c,i)=>{const t=e||("document"in self?document.currentScript.src:"")||location.href;if(s[t])return;let n={};const r=e=>a(e,t),d={module:{uri:t},exports:n,require:r};s[t]=Promise.all(c.map(e=>d[e]||r(e))).then(e=>(i(...e),n))}}define(["./workbox-c05e7c83"],function(e){"use strict";importScripts("fallback-hxi5kegOl0PxtKhvDL_OX.js"),self.skipWaiting(),e.clientsClaim(),e.precacheAndRoute([{url:"/_next/app-build-manifest.json",revision:"e80949a4220e442866c83d989e958ae8"},{url:"/_next/static/chunks/05417924-77747cddee4d64f3.js",revision:"77747cddee4d64f3"},{url:"/_next/static/chunks/0b8e744a-e08dc785b2890dce.js",revision:"e08dc785b2890dce"},{url:"/_next/static/chunks/10227.2d6ce21b588b309f.js",revision:"2d6ce21b588b309f"},{url:"/_next/static/chunks/10404.d8efffe9b2fd4e0b.js",revision:"d8efffe9b2fd4e0b"},{url:"/_next/static/chunks/10600.4009af2369131bbf.js",revision:"4009af2369131bbf"},{url:"/_next/static/chunks/1093.5cfb52a48d3a96ae.js",revision:"5cfb52a48d3a96ae"},{url:"/_next/static/chunks/10973.9e10593aba66fc5c.js",revision:"9e10593aba66fc5c"},{url:"/_next/static/chunks/11216.13da4d102d204873.js",revision:"13da4d102d204873"},{url:"/_next/static/chunks/11270.a084bc48f9f032cc.js",revision:"a084bc48f9f032cc"},{url:"/_next/static/chunks/11307.364f3be8c5e998d0.js",revision:"364f3be8c5e998d0"},{url:"/_next/static/chunks/11413.fda7315bfdc36501.js",revision:"fda7315bfdc36501"},{url:"/_next/static/chunks/11529.42d5c37f670458ae.js",revision:"42d5c37f670458ae"},{url:"/_next/static/chunks/11865.516c4e568f1889be.js",revision:"516c4e568f1889be"},{url:"/_next/static/chunks/11917.ed6c454d6e630d86.js",revision:"ed6c454d6e630d86"},{url:"/_next/static/chunks/11940.6d97e23b9fab9add.js",revision:"6d97e23b9fab9add"},{url:"/_next/static/chunks/11949.590f8f677688a503.js",revision:"590f8f677688a503"},{url:"/_next/static/chunks/12125.92522667557fbbc2.js",revision:"92522667557fbbc2"},{url:"/_next/static/chunks/12276.da8644143fa9cc7f.js",revision:"da8644143fa9cc7f"},{url:"/_next/static/chunks/12365.108b2ebacf69576e.js",revision:"108b2ebacf69576e"},{url:"/_next/static/chunks/12421.6e80538a9f3cc1f2.js",revision:"6e80538a9f3cc1f2"},{url:"/_next/static/chunks/12524.ab059c0d47639851.js",revision:"ab059c0d47639851"},{url:"/_next/static/chunks/12625.67a653e933316864.js",revision:"67a653e933316864"},{url:"/_next/static/chunks/12631.10189fe2d597f55c.js",revision:"10189fe2d597f55c"},{url:"/_next/static/chunks/12706.4bdab3af288f10dc.js",revision:"4bdab3af288f10dc"},{url:"/_next/static/chunks/13025.46d60a4b94267957.js",revision:"46d60a4b94267957"},{url:"/_next/static/chunks/13056.f04bf48e4085b0d7.js",revision:"f04bf48e4085b0d7"},{url:"/_next/static/chunks/13072-5fc2f3d78982929e.js",revision:"5fc2f3d78982929e"},{url:"/_next/static/chunks/13110.5f8f979ca5e89dbc.js",revision:"5f8f979ca5e89dbc"},{url:"/_next/static/chunks/13149.67512e40a8990eef.js",revision:"67512e40a8990eef"},{url:"/_next/static/chunks/13211.64ab2c05050165a5.js",revision:"64ab2c05050165a5"},{url:"/_next/static/chunks/1326.14821b0f82cce223.js",revision:"14821b0f82cce223"},{url:"/_next/static/chunks/13269.8c3c6c48ddfc4989.js",revision:"8c3c6c48ddfc4989"},{url:"/_next/static/chunks/13271.1719276f2b86517b.js",revision:"1719276f2b86517b"},{url:"/_next/static/chunks/13360.fed9636864ee1394.js",revision:"fed9636864ee1394"},{url:"/_next/static/chunks/1343.99f3d3e1c273209b.js",revision:"99f3d3e1c273209b"},{url:"/_next/static/chunks/13526.0c697aa31858202f.js",revision:"0c697aa31858202f"},{url:"/_next/static/chunks/13611.4125ff9aa9e3d2fe.js",revision:"4125ff9aa9e3d2fe"},{url:"/_next/static/chunks/1379.be1a4d4dff4a20fd.js",revision:"be1a4d4dff4a20fd"},{url:"/_next/static/chunks/13857.c1b4faa54529c447.js",revision:"c1b4faa54529c447"},{url:"/_next/static/chunks/14043.63fb1ce74ba07ae8.js",revision:"63fb1ce74ba07ae8"},{url:"/_next/static/chunks/14564.cf799d3cbf98c087.js",revision:"cf799d3cbf98c087"},{url:"/_next/static/chunks/14619.e810b9d39980679d.js",revision:"e810b9d39980679d"},{url:"/_next/static/chunks/14665-34366d9806029de7.js",revision:"34366d9806029de7"},{url:"/_next/static/chunks/14683.90184754d0828bc9.js",revision:"90184754d0828bc9"},{url:"/_next/static/chunks/1471f7b3-f03c3b85e0555a0c.js",revision:"f03c3b85e0555a0c"},{url:"/_next/static/chunks/14963.ba92d743e1658e77.js",revision:"ba92d743e1658e77"},{url:"/_next/static/chunks/15041-31e6cb0e412468f0.js",revision:"31e6cb0e412468f0"},{url:"/_next/static/chunks/15377.c01fca90d1b21cad.js",revision:"c01fca90d1b21cad"},{url:"/_next/static/chunks/15405-f7c1619c9397a2ce.js",revision:"f7c1619c9397a2ce"},{url:"/_next/static/chunks/15448-18679861f0708c4e.js",revision:"18679861f0708c4e"},{url:"/_next/static/chunks/15606.af6f735a1c187dfc.js",revision:"af6f735a1c187dfc"},{url:"/_next/static/chunks/15721.016f333dcec9a52b.js",revision:"016f333dcec9a52b"},{url:"/_next/static/chunks/15849.6f06cb0f5cc392a3.js",revision:"6f06cb0f5cc392a3"},{url:"/_next/static/chunks/16379.868d0198c64b2724.js",revision:"868d0198c64b2724"},{url:"/_next/static/chunks/16399.6993c168f19369b1.js",revision:"6993c168f19369b1"},{url:"/_next/static/chunks/16486-8f2115a5e48b9dbc.js",revision:"8f2115a5e48b9dbc"},{url:"/_next/static/chunks/16511.63c987cddefd5020.js",revision:"63c987cddefd5020"},{url:"/_next/static/chunks/16546.899bcbd2209a4f76.js",revision:"899bcbd2209a4f76"},{url:"/_next/static/chunks/16563.4350b22478980bdf.js",revision:"4350b22478980bdf"},{url:"/_next/static/chunks/16604.c70557135c7f1ba6.js",revision:"c70557135c7f1ba6"},{url:"/_next/static/chunks/1668-91c9c25cc107181c.js",revision:"91c9c25cc107181c"},{url:"/_next/static/chunks/16711.4200241536dea973.js",revision:"4200241536dea973"},{url:"/_next/static/chunks/16898.a93e193378633099.js",revision:"a93e193378633099"},{url:"/_next/static/chunks/16971-1e1adb5405775f69.js",revision:"1e1adb5405775f69"},{url:"/_next/static/chunks/17025-8680e9021847923a.js",revision:"8680e9021847923a"},{url:"/_next/static/chunks/17041.14d694ac4e17f8f1.js",revision:"14d694ac4e17f8f1"},{url:"/_next/static/chunks/17231.6c64588b9cdd5c37.js",revision:"6c64588b9cdd5c37"},{url:"/_next/static/chunks/17376.d1e5510fb31e2c5c.js",revision:"d1e5510fb31e2c5c"},{url:"/_next/static/chunks/17557.eb9456ab57c1be50.js",revision:"eb9456ab57c1be50"},{url:"/_next/static/chunks/17751.918e5506df4b6950.js",revision:"918e5506df4b6950"},{url:"/_next/static/chunks/17771.acf53180d5e0111d.js",revision:"acf53180d5e0111d"},{url:"/_next/static/chunks/17855.66c5723d6a63df48.js",revision:"66c5723d6a63df48"},{url:"/_next/static/chunks/18000.ff1bd737b49f2c6c.js",revision:"ff1bd737b49f2c6c"},{url:"/_next/static/chunks/1802.7724e056289b15ae.js",revision:"7724e056289b15ae"},{url:"/_next/static/chunks/18067-c62a1f4f368a1121.js",revision:"c62a1f4f368a1121"},{url:"/_next/static/chunks/18467.cb08e501f2e3656d.js",revision:"cb08e501f2e3656d"},{url:"/_next/static/chunks/18863.8b28f5bfdb95d62c.js",revision:"8b28f5bfdb95d62c"},{url:"/_next/static/chunks/1898.89ba096be8637f07.js",revision:"89ba096be8637f07"},{url:"/_next/static/chunks/19296.d0643d9b5fe2eb41.js",revision:"d0643d9b5fe2eb41"},{url:"/_next/static/chunks/19326.5a7bfa108daf8280.js",revision:"5a7bfa108daf8280"},{url:"/_next/static/chunks/19405.826697a06fefcc57.js",revision:"826697a06fefcc57"},{url:"/_next/static/chunks/19790-c730088b8700d86e.js",revision:"c730088b8700d86e"},{url:"/_next/static/chunks/1ae6eb87-e6808a74cc7c700b.js",revision:"e6808a74cc7c700b"},{url:"/_next/static/chunks/20338.d10bc44a79634e16.js",revision:"d10bc44a79634e16"},{url:"/_next/static/chunks/20343.a73888eda3407330.js",revision:"a73888eda3407330"},{url:"/_next/static/chunks/20441.e156d233f7104b23.js",revision:"e156d233f7104b23"},{url:"/_next/static/chunks/20481.e04a45aa20b1976b.js",revision:"e04a45aa20b1976b"},{url:"/_next/static/chunks/20fdb61e.fbe1e616fa3d5495.js",revision:"fbe1e616fa3d5495"},{url:"/_next/static/chunks/21139.604a0b031308b62f.js",revision:"604a0b031308b62f"},{url:"/_next/static/chunks/21151.5c221cee5224c079.js",revision:"5c221cee5224c079"},{url:"/_next/static/chunks/21288.231a35b4e731cc9e.js",revision:"231a35b4e731cc9e"},{url:"/_next/static/chunks/21529.f87a17e08ed68b42.js",revision:"f87a17e08ed68b42"},{url:"/_next/static/chunks/21541.8902a74e4e69a6f1.js",revision:"8902a74e4e69a6f1"},{url:"/_next/static/chunks/2166.9848798428477e40.js",revision:"9848798428477e40"},{url:"/_next/static/chunks/21742-8072a0f644e9e8b3.js",revision:"8072a0f644e9e8b3"},{url:"/_next/static/chunks/2193.3bcbb3d0d023d9fe.js",revision:"3bcbb3d0d023d9fe"},{url:"/_next/static/chunks/21957.995aaef85cea119f.js",revision:"995aaef85cea119f"},{url:"/_next/static/chunks/22057.318686aa0e043a97.js",revision:"318686aa0e043a97"},{url:"/_next/static/chunks/22420-85b7a3cb6da6b29a.js",revision:"85b7a3cb6da6b29a"},{url:"/_next/static/chunks/22705.a8fb712c28c6bd77.js",revision:"a8fb712c28c6bd77"},{url:"/_next/static/chunks/22707.269fe334721e204e.js",revision:"269fe334721e204e"},{url:"/_next/static/chunks/23037.1772492ec76f98c7.js",revision:"1772492ec76f98c7"},{url:"/_next/static/chunks/23086.158757f15234834f.js",revision:"158757f15234834f"},{url:"/_next/static/chunks/23183.594e16513821b96c.js",revision:"594e16513821b96c"},{url:"/_next/static/chunks/23327.2a1db1d88c37a3e7.js",revision:"2a1db1d88c37a3e7"},{url:"/_next/static/chunks/23727.8a43501019bbde3c.js",revision:"8a43501019bbde3c"},{url:"/_next/static/chunks/23810-5c3dc746d77522a3.js",revision:"5c3dc746d77522a3"},{url:"/_next/static/chunks/24029.d30d06f4e6743bb2.js",revision:"d30d06f4e6743bb2"},{url:"/_next/static/chunks/2410.90bdf846234fe966.js",revision:"90bdf846234fe966"},{url:"/_next/static/chunks/24137-04a4765327fbdf71.js",revision:"04a4765327fbdf71"},{url:"/_next/static/chunks/24138.cbe8bccb36e3cce3.js",revision:"cbe8bccb36e3cce3"},{url:"/_next/static/chunks/24295.831d9fbde821e5b7.js",revision:"831d9fbde821e5b7"},{url:"/_next/static/chunks/24326.88b8564b7d9c2fc8.js",revision:"88b8564b7d9c2fc8"},{url:"/_next/static/chunks/24339-746c6445879fdddd.js",revision:"746c6445879fdddd"},{url:"/_next/static/chunks/24376.9c0fec1b5db36cae.js",revision:"9c0fec1b5db36cae"},{url:"/_next/static/chunks/24383.c7259ef158b876b5.js",revision:"c7259ef158b876b5"},{url:"/_next/static/chunks/24519.dce38e90251a8c25.js",revision:"dce38e90251a8c25"},{url:"/_next/static/chunks/24586-dd949d961c3ad33e.js",revision:"dd949d961c3ad33e"},{url:"/_next/static/chunks/24640-a41e87f26eaf5810.js",revision:"a41e87f26eaf5810"},{url:"/_next/static/chunks/24706.37c97d8ff9e47bd5.js",revision:"37c97d8ff9e47bd5"},{url:"/_next/static/chunks/24891.75a9aabdbc282338.js",revision:"75a9aabdbc282338"},{url:"/_next/static/chunks/24961.28f927feadfb31f5.js",revision:"28f927feadfb31f5"},{url:"/_next/static/chunks/25143.9a595a9dd94eb0a4.js",revision:"9a595a9dd94eb0a4"},{url:"/_next/static/chunks/25225.3fe24e6e47ca9db1.js",revision:"3fe24e6e47ca9db1"},{url:"/_next/static/chunks/25359.7d020c628154c814.js",revision:"7d020c628154c814"},{url:"/_next/static/chunks/25446-38ad86c587624f05.js",revision:"38ad86c587624f05"},{url:"/_next/static/chunks/25577.b375e938f6748ba0.js",revision:"b375e938f6748ba0"},{url:"/_next/static/chunks/25924-18679861f0708c4e.js",revision:"18679861f0708c4e"},{url:"/_next/static/chunks/26094.04829760397a1cd4.js",revision:"04829760397a1cd4"},{url:"/_next/static/chunks/26135-7c712a292ebd319c.js",revision:"7c712a292ebd319c"},{url:"/_next/static/chunks/26184.2f42d1b6a292d2ff.js",revision:"2f42d1b6a292d2ff"},{url:"/_next/static/chunks/26437-9a746fa27b1ab62d.js",revision:"9a746fa27b1ab62d"},{url:"/_next/static/chunks/2697-c61a87392df1c2bf.js",revision:"c61a87392df1c2bf"},{url:"/_next/static/chunks/27005.5c57cea3023af627.js",revision:"5c57cea3023af627"},{url:"/_next/static/chunks/27359.06e2f2d24d2ea8a8.js",revision:"06e2f2d24d2ea8a8"},{url:"/_next/static/chunks/27655-bf3fc8fe88e99aab.js",revision:"bf3fc8fe88e99aab"},{url:"/_next/static/chunks/27775.9a2c44d9bae18710.js",revision:"9a2c44d9bae18710"},{url:"/_next/static/chunks/27895.eae86f4cb32708f8.js",revision:"eae86f4cb32708f8"},{url:"/_next/static/chunks/27896-d8fccb53e302d9b8.js",revision:"d8fccb53e302d9b8"},{url:"/_next/static/chunks/28816.87ad8dce35181118.js",revision:"87ad8dce35181118"},{url:"/_next/static/chunks/29282.ebb929b1c842a24c.js",revision:"ebb929b1c842a24c"},{url:"/_next/static/chunks/29521.70184382916a2a6c.js",revision:"70184382916a2a6c"},{url:"/_next/static/chunks/29643.39ba5e394ff0bf2f.js",revision:"39ba5e394ff0bf2f"},{url:"/_next/static/chunks/2972.0232841c02104ceb.js",revision:"0232841c02104ceb"},{url:"/_next/static/chunks/30342.3e77ffbd5fef8bce.js",revision:"3e77ffbd5fef8bce"},{url:"/_next/static/chunks/30420.6e7d463d167dfbe2.js",revision:"6e7d463d167dfbe2"},{url:"/_next/static/chunks/30433.fc3e6abc2a147fcc.js",revision:"fc3e6abc2a147fcc"},{url:"/_next/static/chunks/30489.679b6d0eab2b69db.js",revision:"679b6d0eab2b69db"},{url:"/_next/static/chunks/30518.e026de6e5681fe07.js",revision:"e026de6e5681fe07"},{url:"/_next/static/chunks/30581.4499b5c9e8b1496c.js",revision:"4499b5c9e8b1496c"},{url:"/_next/static/chunks/30606.e63c845883cf578e.js",revision:"e63c845883cf578e"},{url:"/_next/static/chunks/30855.c62d4ee9866f5ed2.js",revision:"c62d4ee9866f5ed2"},{url:"/_next/static/chunks/30884-c95fd8a60ed0f565.js",revision:"c95fd8a60ed0f565"},{url:"/_next/static/chunks/30917.2da5a0ca0a161bbc.js",revision:"2da5a0ca0a161bbc"},{url:"/_next/static/chunks/31012.e5da378b15186382.js",revision:"e5da378b15186382"},{url:"/_next/static/chunks/31131.9a4b6e4f84e780c1.js",revision:"9a4b6e4f84e780c1"},{url:"/_next/static/chunks/31213.5cc3c2b8c52e447e.js",revision:"5cc3c2b8c52e447e"},{url:"/_next/static/chunks/31275-242bf62ca715c85b.js",revision:"242bf62ca715c85b"},{url:"/_next/static/chunks/31535.ec58b1214e87450c.js",revision:"ec58b1214e87450c"},{url:"/_next/static/chunks/32012.225bc4defd6f0a8f.js",revision:"225bc4defd6f0a8f"},{url:"/_next/static/chunks/32142.6ea9edc962f64509.js",revision:"6ea9edc962f64509"},{url:"/_next/static/chunks/32151.f69211736897e24b.js",revision:"f69211736897e24b"},{url:"/_next/static/chunks/32212.0552b8c89385bff4.js",revision:"0552b8c89385bff4"},{url:"/_next/static/chunks/32597.90b63b654b6b77f2.js",revision:"90b63b654b6b77f2"},{url:"/_next/static/chunks/32700.2d573741844545d2.js",revision:"2d573741844545d2"},{url:"/_next/static/chunks/32824.62795491d427890d.js",revision:"62795491d427890d"},{url:"/_next/static/chunks/33202.d90bd1b6fe3017bb.js",revision:"d90bd1b6fe3017bb"},{url:"/_next/static/chunks/33223.e32a3b2c6d598095.js",revision:"e32a3b2c6d598095"},{url:"/_next/static/chunks/33335.58c56dab39d85e97.js",revision:"58c56dab39d85e97"},{url:"/_next/static/chunks/33364.e2d58a67b8b48f39.js",revision:"e2d58a67b8b48f39"},{url:"/_next/static/chunks/33452.3213f3b04cde471b.js",revision:"3213f3b04cde471b"},{url:"/_next/static/chunks/33775.2ebbc8baea1023fc.js",revision:"2ebbc8baea1023fc"},{url:"/_next/static/chunks/33787.1f4e3fc4dce6d462.js",revision:"1f4e3fc4dce6d462"},{url:"/_next/static/chunks/34227.46e192cb73272dbb.js",revision:"46e192cb73272dbb"},{url:"/_next/static/chunks/34269-bf30d999b8b357ec.js",revision:"bf30d999b8b357ec"},{url:"/_next/static/chunks/34293.db0463f901a4e9d5.js",revision:"db0463f901a4e9d5"},{url:"/_next/static/chunks/34331.7208a1e7f1f88940.js",revision:"7208a1e7f1f88940"},{url:"/_next/static/chunks/34421.b0749a4047e8a98c.js",revision:"b0749a4047e8a98c"},{url:"/_next/static/chunks/34475.9be5637a0d474525.js",revision:"9be5637a0d474525"},{url:"/_next/static/chunks/34720.50a7f31aeb3f0d8e.js",revision:"50a7f31aeb3f0d8e"},{url:"/_next/static/chunks/34822.78d89e0ebaaa8cc6.js",revision:"78d89e0ebaaa8cc6"},{url:"/_next/static/chunks/34831.2b6e51f7ad0f1795.js",revision:"2b6e51f7ad0f1795"},{url:"/_next/static/chunks/34999.5d0ce7aa20ba0b83.js",revision:"5d0ce7aa20ba0b83"},{url:"/_next/static/chunks/35025.633ea8ca18d5f7de.js",revision:"633ea8ca18d5f7de"},{url:"/_next/static/chunks/35032.3a6c90f900419479.js",revision:"3a6c90f900419479"},{url:"/_next/static/chunks/35131.9b12c8a1947bc9e3.js",revision:"9b12c8a1947bc9e3"},{url:"/_next/static/chunks/35258.6bbcff2f7b7f9d06.js",revision:"6bbcff2f7b7f9d06"},{url:"/_next/static/chunks/35341.41f9204df71b96e3.js",revision:"41f9204df71b96e3"},{url:"/_next/static/chunks/35403.52f152abeeb5d623.js",revision:"52f152abeeb5d623"},{url:"/_next/static/chunks/3543-18679861f0708c4e.js",revision:"18679861f0708c4e"},{url:"/_next/static/chunks/35608.173410ef6c2ea27c.js",revision:"173410ef6c2ea27c"},{url:"/_next/static/chunks/35805.0c1ed9416b2bb3ee.js",revision:"0c1ed9416b2bb3ee"},{url:"/_next/static/chunks/35906-3e1eb7c7b780e16b.js",revision:"3e1eb7c7b780e16b"},{url:"/_next/static/chunks/36049.de560aa5e8d60f15.js",revision:"de560aa5e8d60f15"},{url:"/_next/static/chunks/36065.f3ffe4465d8a5817.js",revision:"f3ffe4465d8a5817"},{url:"/_next/static/chunks/36111.aac397f5903ff82c.js",revision:"aac397f5903ff82c"},{url:"/_next/static/chunks/36193.d084a34a68ab6873.js",revision:"d084a34a68ab6873"},{url:"/_next/static/chunks/36355.d8aec79e654937be.js",revision:"d8aec79e654937be"},{url:"/_next/static/chunks/36367-3aa9be18288264c0.js",revision:"3aa9be18288264c0"},{url:"/_next/static/chunks/36451.62e5e5932cb1ab19.js",revision:"62e5e5932cb1ab19"},{url:"/_next/static/chunks/36601.5a2457f93e152d85.js",revision:"5a2457f93e152d85"},{url:"/_next/static/chunks/36625.0a4a070381562d94.js",revision:"0a4a070381562d94"},{url:"/_next/static/chunks/36891.953b4d0ece6ada6f.js",revision:"953b4d0ece6ada6f"},{url:"/_next/static/chunks/37023.f07ac40c45201d4b.js",revision:"f07ac40c45201d4b"},{url:"/_next/static/chunks/37047-dede650dd0543bac.js",revision:"dede650dd0543bac"},{url:"/_next/static/chunks/37267.f57739536ef97b97.js",revision:"f57739536ef97b97"},{url:"/_next/static/chunks/37370.e7f30e73b6e77e5e.js",revision:"e7f30e73b6e77e5e"},{url:"/_next/static/chunks/37384.81c666dd9d2608b2.js",revision:"81c666dd9d2608b2"},{url:"/_next/static/chunks/37425.de736ee7bbef1a87.js",revision:"de736ee7bbef1a87"},{url:"/_next/static/chunks/37783.54c381528fca245b.js",revision:"54c381528fca245b"},{url:"/_next/static/chunks/38098.7bf64933931b6c3b.js",revision:"7bf64933931b6c3b"},{url:"/_next/static/chunks/38100.283b7c10302b6b21.js",revision:"283b7c10302b6b21"},{url:"/_next/static/chunks/38215.70ed9a3ebfbf88e6.js",revision:"70ed9a3ebfbf88e6"},{url:"/_next/static/chunks/38482-4129e273a4d3c782.js",revision:"4129e273a4d3c782"},{url:"/_next/static/chunks/38927.3119fd93e954e0ba.js",revision:"3119fd93e954e0ba"},{url:"/_next/static/chunks/38939.d6f5b345c4310296.js",revision:"d6f5b345c4310296"},{url:"/_next/static/chunks/39015.c2761b8e9159368d.js",revision:"c2761b8e9159368d"},{url:"/_next/static/chunks/39132.fc3380b03520116a.js",revision:"fc3380b03520116a"},{url:"/_next/static/chunks/39324.c141dcdbaf763a1f.js",revision:"c141dcdbaf763a1f"},{url:"/_next/static/chunks/3948.c1790e815f59fe15.js",revision:"c1790e815f59fe15"},{url:"/_next/static/chunks/39650.b28500edba896c3c.js",revision:"b28500edba896c3c"},{url:"/_next/static/chunks/39687.333e92331282ab94.js",revision:"333e92331282ab94"},{url:"/_next/static/chunks/39709.5d9960b5195030e7.js",revision:"5d9960b5195030e7"},{url:"/_next/static/chunks/39731.ee5661db1ed8a20d.js",revision:"ee5661db1ed8a20d"},{url:"/_next/static/chunks/39794.e9a979f7368ad3e5.js",revision:"e9a979f7368ad3e5"},{url:"/_next/static/chunks/39800.594c1845160ece20.js",revision:"594c1845160ece20"},{url:"/_next/static/chunks/39917.30526a7e8337a626.js",revision:"30526a7e8337a626"},{url:"/_next/static/chunks/3995.3ec55001172cdcb8.js",revision:"3ec55001172cdcb8"},{url:"/_next/static/chunks/39952.968ae90199fc5394.js",revision:"968ae90199fc5394"},{url:"/_next/static/chunks/39961.310dcbff7dfbcfe2.js",revision:"310dcbff7dfbcfe2"},{url:"/_next/static/chunks/4007.3777594ecf312bcb.js",revision:"3777594ecf312bcb"},{url:"/_next/static/chunks/40356.437355e9e3e89f89.js",revision:"437355e9e3e89f89"},{url:"/_next/static/chunks/4041.a38bef8c2bad6e81.js",revision:"a38bef8c2bad6e81"},{url:"/_next/static/chunks/40448-c62a1f4f368a1121.js",revision:"c62a1f4f368a1121"},{url:"/_next/static/chunks/40513.dee5882a5fb41218.js",revision:"dee5882a5fb41218"},{url:"/_next/static/chunks/40838.d7397ef66a3d6cf4.js",revision:"d7397ef66a3d6cf4"},{url:"/_next/static/chunks/40853.583057bcca92d245.js",revision:"583057bcca92d245"},{url:"/_next/static/chunks/410.6e3584848520c962.js",revision:"6e3584848520c962"},{url:"/_next/static/chunks/41039.7dc257fa65dd4709.js",revision:"7dc257fa65dd4709"},{url:"/_next/static/chunks/41059.be96e4ef5bebc2f2.js",revision:"be96e4ef5bebc2f2"},{url:"/_next/static/chunks/4106.9e6e17d57fdaa661.js",revision:"9e6e17d57fdaa661"},{url:"/_next/static/chunks/41193.0eb1d071eeb97fb0.js",revision:"0eb1d071eeb97fb0"},{url:"/_next/static/chunks/41220.8e755f7aafbf7980.js",revision:"8e755f7aafbf7980"},{url:"/_next/static/chunks/41314.bfaf95227838bcda.js",revision:"bfaf95227838bcda"},{url:"/_next/static/chunks/41347.763641d44414255a.js",revision:"763641d44414255a"},{url:"/_next/static/chunks/41497.7878f2f171ce8c5e.js",revision:"7878f2f171ce8c5e"},{url:"/_next/static/chunks/4151.8bbf8de7b1d955b5.js",revision:"8bbf8de7b1d955b5"},{url:"/_next/static/chunks/41563.ea5487abc22d830f.js",revision:"ea5487abc22d830f"},{url:"/_next/static/chunks/41597.1b844e749172cf14.js",revision:"1b844e749172cf14"},{url:"/_next/static/chunks/41697.dc5c0858a7ffa805.js",revision:"dc5c0858a7ffa805"},{url:"/_next/static/chunks/41793.978b2e9a60904a6e.js",revision:"978b2e9a60904a6e"},{url:"/_next/static/chunks/41851.bb64c4159f92755a.js",revision:"bb64c4159f92755a"},{url:"/_next/static/chunks/42054.a89c82b1a3fa50df.js",revision:"a89c82b1a3fa50df"},{url:"/_next/static/chunks/42217-3333b08e7803809b.js",revision:"3333b08e7803809b"},{url:"/_next/static/chunks/42343.b8526852ffb2eee0.js",revision:"b8526852ffb2eee0"},{url:"/_next/static/chunks/42353.9ff1f9a9d1ee6af7.js",revision:"9ff1f9a9d1ee6af7"},{url:"/_next/static/chunks/4249.757c4d44d2633ab4.js",revision:"757c4d44d2633ab4"},{url:"/_next/static/chunks/42530.3d6a9fb83aebc252.js",revision:"3d6a9fb83aebc252"},{url:"/_next/static/chunks/42949.5f6a69ec4a94818a.js",revision:"5f6a69ec4a94818a"},{url:"/_next/static/chunks/43051.90f3188002014a08.js",revision:"90f3188002014a08"},{url:"/_next/static/chunks/43054.ba17f57097d13614.js",revision:"ba17f57097d13614"},{url:"/_next/static/chunks/43196.11f65b652442c156.js",revision:"11f65b652442c156"},{url:"/_next/static/chunks/43243.cf4c66a0d9e3360e.js",revision:"cf4c66a0d9e3360e"},{url:"/_next/static/chunks/43252.5a107f2cfaf48ae3.js",revision:"5a107f2cfaf48ae3"},{url:"/_next/static/chunks/43628.bdc0377a0c1b2eb3.js",revision:"bdc0377a0c1b2eb3"},{url:"/_next/static/chunks/43700.84f1ca94a6d3340c.js",revision:"84f1ca94a6d3340c"},{url:"/_next/static/chunks/43769.0a99560cdc099772.js",revision:"0a99560cdc099772"},{url:"/_next/static/chunks/43772-ad054deaaf5fcd86.js",revision:"ad054deaaf5fcd86"},{url:"/_next/static/chunks/43862-0dbeea318fbfad11.js",revision:"0dbeea318fbfad11"},{url:"/_next/static/chunks/43878.1ff4836f0809ff68.js",revision:"1ff4836f0809ff68"},{url:"/_next/static/chunks/43894.7ffe482bd50e35c9.js",revision:"7ffe482bd50e35c9"},{url:"/_next/static/chunks/44123.b52d19519dfe1e42.js",revision:"b52d19519dfe1e42"},{url:"/_next/static/chunks/44144.5b91cc042fa44be2.js",revision:"5b91cc042fa44be2"},{url:"/_next/static/chunks/44248-1dfb4ac6f8d1fd07.js",revision:"1dfb4ac6f8d1fd07"},{url:"/_next/static/chunks/44254.2860794b0c0e1ef6.js",revision:"2860794b0c0e1ef6"},{url:"/_next/static/chunks/44381.9c8e16a6424adc8d.js",revision:"9c8e16a6424adc8d"},{url:"/_next/static/chunks/44531.8095bfe48023089b.js",revision:"8095bfe48023089b"},{url:"/_next/static/chunks/44572.ba41ecd79b41f525.js",revision:"ba41ecd79b41f525"},{url:"/_next/static/chunks/44610.49a93268c33d2651.js",revision:"49a93268c33d2651"},{url:"/_next/static/chunks/44640.52150bf827afcfb1.js",revision:"52150bf827afcfb1"},{url:"/_next/static/chunks/44991.2ed748436f014361.js",revision:"2ed748436f014361"},{url:"/_next/static/chunks/45191-d7de90a08075e8ee.js",revision:"d7de90a08075e8ee"},{url:"/_next/static/chunks/45318.19c3faad5c34d0d4.js",revision:"19c3faad5c34d0d4"},{url:"/_next/static/chunks/4556.de93eae2a91704e6.js",revision:"de93eae2a91704e6"},{url:"/_next/static/chunks/45888.daaede4f205e7e3d.js",revision:"daaede4f205e7e3d"},{url:"/_next/static/chunks/46277.4fc1f8adbdb50757.js",revision:"4fc1f8adbdb50757"},{url:"/_next/static/chunks/46300.34c56977efb12f86.js",revision:"34c56977efb12f86"},{url:"/_next/static/chunks/46914-8124a0324764302a.js",revision:"8124a0324764302a"},{url:"/_next/static/chunks/46985.f65c6455a96a19e6.js",revision:"f65c6455a96a19e6"},{url:"/_next/static/chunks/47499.cfa056dc05b3a960.js",revision:"cfa056dc05b3a960"},{url:"/_next/static/chunks/47681.3da8ce224d044119.js",revision:"3da8ce224d044119"},{url:"/_next/static/chunks/4779.896f41085b382d47.js",revision:"896f41085b382d47"},{url:"/_next/static/chunks/48140.584aaae48be3979a.js",revision:"584aaae48be3979a"},{url:"/_next/static/chunks/4850.64274c81a39b03d1.js",revision:"64274c81a39b03d1"},{url:"/_next/static/chunks/48567.f511415090809ef3.js",revision:"f511415090809ef3"},{url:"/_next/static/chunks/48723.3f8685fa8d9d547b.js",revision:"3f8685fa8d9d547b"},{url:"/_next/static/chunks/48760-b1141e9b031478d0.js",revision:"b1141e9b031478d0"},{url:"/_next/static/chunks/49219.a03a09318b60e813.js",revision:"a03a09318b60e813"},{url:"/_next/static/chunks/49249.9884136090ff649c.js",revision:"9884136090ff649c"},{url:"/_next/static/chunks/49268.b66911ab1b57fbc4.js",revision:"b66911ab1b57fbc4"},{url:"/_next/static/chunks/49285-bfa5a6b056f9921c.js",revision:"bfa5a6b056f9921c"},{url:"/_next/static/chunks/49324.bba4e3304305d3ee.js",revision:"bba4e3304305d3ee"},{url:"/_next/static/chunks/49470-e9617c6ff33ab30a.js",revision:"e9617c6ff33ab30a"},{url:"/_next/static/chunks/49719.b138ee24d17a3e8f.js",revision:"b138ee24d17a3e8f"},{url:"/_next/static/chunks/49935.117c4410fd1ce266.js",revision:"117c4410fd1ce266"},{url:"/_next/static/chunks/50154.1baa4e51196259e1.js",revision:"1baa4e51196259e1"},{url:"/_next/static/chunks/50164.c0312ac5c2784d2d.js",revision:"c0312ac5c2784d2d"},{url:"/_next/static/chunks/50189.6a6bd8d90f39c18c.js",revision:"6a6bd8d90f39c18c"},{url:"/_next/static/chunks/50301.179abf80291119dc.js",revision:"179abf80291119dc"},{url:"/_next/static/chunks/50363.654c0b10fe592ea6.js",revision:"654c0b10fe592ea6"},{url:"/_next/static/chunks/50479.071f732a65c46a70.js",revision:"071f732a65c46a70"},{url:"/_next/static/chunks/50555.ac4f1d68aaa9abb2.js",revision:"ac4f1d68aaa9abb2"},{url:"/_next/static/chunks/5071.eab2b8999165a153.js",revision:"eab2b8999165a153"},{url:"/_next/static/chunks/50795.a0e5bfc3f3d35b08.js",revision:"a0e5bfc3f3d35b08"},{url:"/_next/static/chunks/5091-60557a86e8a10330.js",revision:"60557a86e8a10330"},{url:"/_next/static/chunks/51087.98ad2e5a0075fdbe.js",revision:"98ad2e5a0075fdbe"},{url:"/_next/static/chunks/51206-26a3e2d474c87801.js",revision:"26a3e2d474c87801"},{url:"/_next/static/chunks/51226.3b789a36213ff16e.js",revision:"3b789a36213ff16e"},{url:"/_next/static/chunks/51240.9f0d5e47af611ae1.js",revision:"9f0d5e47af611ae1"},{url:"/_next/static/chunks/51321.76896859772ef958.js",revision:"76896859772ef958"},{url:"/_next/static/chunks/51410.a0f292d3c5f0cd9d.js",revision:"a0f292d3c5f0cd9d"},{url:"/_next/static/chunks/51726.094238d6785a8db0.js",revision:"094238d6785a8db0"},{url:"/_next/static/chunks/51864.3b61e4db819af663.js",revision:"3b61e4db819af663"},{url:"/_next/static/chunks/52055-15759d93ea8646f3.js",revision:"15759d93ea8646f3"},{url:"/_next/static/chunks/52380.6efeb54e2c326954.js",revision:"6efeb54e2c326954"},{url:"/_next/static/chunks/52468-3904482f4a92d8ff.js",revision:"3904482f4a92d8ff"},{url:"/_next/static/chunks/52863.a00298832c59de13.js",revision:"a00298832c59de13"},{url:"/_next/static/chunks/52922.93ebbabf09c6dc3c.js",revision:"93ebbabf09c6dc3c"},{url:"/_next/static/chunks/53284.7df6341d1515790f.js",revision:"7df6341d1515790f"},{url:"/_next/static/chunks/5335.3667d8346284401e.js",revision:"3667d8346284401e"},{url:"/_next/static/chunks/53375.a3c0d7a7288fb098.js",revision:"a3c0d7a7288fb098"},{url:"/_next/static/chunks/53450-1ada1109fbef544e.js",revision:"1ada1109fbef544e"},{url:"/_next/static/chunks/53452-c626edba51d827fd.js",revision:"c626edba51d827fd"},{url:"/_next/static/chunks/53509.f4071f7c08666834.js",revision:"f4071f7c08666834"},{url:"/_next/static/chunks/53529.5ad8bd2056fab944.js",revision:"5ad8bd2056fab944"},{url:"/_next/static/chunks/53727.aac93a096d1c8b77.js",revision:"aac93a096d1c8b77"},{url:"/_next/static/chunks/53731.b0718b98d2fb7ace.js",revision:"b0718b98d2fb7ace"},{url:"/_next/static/chunks/53789.02faf0e472ffa080.js",revision:"02faf0e472ffa080"},{url:"/_next/static/chunks/53999.81f148444ca61363.js",revision:"81f148444ca61363"},{url:"/_next/static/chunks/54207.bf7b4fb0f03da3d3.js",revision:"bf7b4fb0f03da3d3"},{url:"/_next/static/chunks/54216.3484b423a081b94e.js",revision:"3484b423a081b94e"},{url:"/_next/static/chunks/54221.0710202ae5dd437a.js",revision:"0710202ae5dd437a"},{url:"/_next/static/chunks/54243-336bbeee5c5b0fe8.js",revision:"336bbeee5c5b0fe8"},{url:"/_next/static/chunks/54381-6c5ec10a9bd34460.js",revision:"6c5ec10a9bd34460"},{url:"/_next/static/chunks/54528.702c70de8d3c007a.js",revision:"702c70de8d3c007a"},{url:"/_next/static/chunks/54577.ebeed3b0480030b6.js",revision:"ebeed3b0480030b6"},{url:"/_next/static/chunks/54958.f2db089e27ae839f.js",revision:"f2db089e27ae839f"},{url:"/_next/static/chunks/55129-47a156913c168ed4.js",revision:"47a156913c168ed4"},{url:"/_next/static/chunks/55199.f0358dbcd265e462.js",revision:"f0358dbcd265e462"},{url:"/_next/static/chunks/55218.bbf7b8037aa79f47.js",revision:"bbf7b8037aa79f47"},{url:"/_next/static/chunks/55649.b679f89ce00cebdc.js",revision:"b679f89ce00cebdc"},{url:"/_next/static/chunks/55761.f464c5c7a13f52f7.js",revision:"f464c5c7a13f52f7"},{url:"/_next/static/chunks/55771-803ee2c5e9f67875.js",revision:"803ee2c5e9f67875"},{url:"/_next/static/chunks/55863.3d64aef8864730dd.js",revision:"3d64aef8864730dd"},{url:"/_next/static/chunks/55886.f14b944beb4b9c76.js",revision:"f14b944beb4b9c76"},{url:"/_next/static/chunks/56079.df991a66e5e82f36.js",revision:"df991a66e5e82f36"},{url:"/_next/static/chunks/56292.16ed1d33114e698d.js",revision:"16ed1d33114e698d"},{url:"/_next/static/chunks/56350.0d59bb87ccfdb49c.js",revision:"0d59bb87ccfdb49c"},{url:"/_next/static/chunks/56490.63df43b48e5cb8fb.js",revision:"63df43b48e5cb8fb"},{url:"/_next/static/chunks/56494.f3f39a14916d4071.js",revision:"f3f39a14916d4071"},{url:"/_next/static/chunks/56529.51a5596d26d2e9b4.js",revision:"51a5596d26d2e9b4"},{url:"/_next/static/chunks/56539.752d077815d0d842.js",revision:"752d077815d0d842"},{url:"/_next/static/chunks/56585.2e4765683a5d0b90.js",revision:"2e4765683a5d0b90"},{url:"/_next/static/chunks/56608.88ca9fcfa0f48c48.js",revision:"88ca9fcfa0f48c48"},{url:"/_next/static/chunks/56725.a88db5a174bf2480.js",revision:"a88db5a174bf2480"},{url:"/_next/static/chunks/569.934a671a66be70c2.js",revision:"934a671a66be70c2"},{url:"/_next/static/chunks/56929.9c792022cb9f8cae.js",revision:"9c792022cb9f8cae"},{url:"/_next/static/chunks/57242.b0ed0af096a5a4cb.js",revision:"b0ed0af096a5a4cb"},{url:"/_next/static/chunks/573.ce956e00f24a272a.js",revision:"ce956e00f24a272a"},{url:"/_next/static/chunks/57361-38d45fa15ae9671d.js",revision:"38d45fa15ae9671d"},{url:"/_next/static/chunks/57391-e2ba7688f865c022.js",revision:"e2ba7688f865c022"},{url:"/_next/static/chunks/57641.3cf81a9d9e0c8531.js",revision:"3cf81a9d9e0c8531"},{url:"/_next/static/chunks/57714.2cf011027f4e94e5.js",revision:"2cf011027f4e94e5"},{url:"/_next/static/chunks/57871.555f6e7b903e71ef.js",revision:"555f6e7b903e71ef"},{url:"/_next/static/chunks/58310-e0c52408c1b894e6.js",revision:"e0c52408c1b894e6"},{url:"/_next/static/chunks/58347.9eb304955957e772.js",revision:"9eb304955957e772"},{url:"/_next/static/chunks/58407.617fafc36fdde431.js",revision:"617fafc36fdde431"},{url:"/_next/static/chunks/58486.c57e4f33e2c0c881.js",revision:"c57e4f33e2c0c881"},{url:"/_next/static/chunks/58503.78fbfc752d8d5b92.js",revision:"78fbfc752d8d5b92"},{url:"/_next/static/chunks/58567-7051f47a4c3df6bf.js",revision:"7051f47a4c3df6bf"},{url:"/_next/static/chunks/58748-3aa9be18288264c0.js",revision:"3aa9be18288264c0"},{url:"/_next/static/chunks/58753.cb93a00a4a5e0506.js",revision:"cb93a00a4a5e0506"},{url:"/_next/static/chunks/58781-18679861f0708c4e.js",revision:"18679861f0708c4e"},{url:"/_next/static/chunks/58800.8093642e74e578f3.js",revision:"8093642e74e578f3"},{url:"/_next/static/chunks/58826.ead36a86c535fbb7.js",revision:"ead36a86c535fbb7"},{url:"/_next/static/chunks/58854.cccd3dda7f227bbb.js",revision:"cccd3dda7f227bbb"},{url:"/_next/static/chunks/58986.a2656e58b0456a1b.js",revision:"a2656e58b0456a1b"},{url:"/_next/static/chunks/59474-98edcfc228e1c4ad.js",revision:"98edcfc228e1c4ad"},{url:"/_next/static/chunks/59583-422a987558783a3e.js",revision:"422a987558783a3e"},{url:"/_next/static/chunks/59683.b08ae85d9c384446.js",revision:"b08ae85d9c384446"},{url:"/_next/static/chunks/59754.8fb27cde3fadf5c4.js",revision:"8fb27cde3fadf5c4"},{url:"/_next/static/chunks/59831.fe6fa243d2ea9936.js",revision:"fe6fa243d2ea9936"},{url:"/_next/static/chunks/59909.62a5307678b5dbc0.js",revision:"62a5307678b5dbc0"},{url:"/_next/static/chunks/60188.42a57a537cb12097.js",revision:"42a57a537cb12097"},{url:"/_next/static/chunks/60291.77aa277599bafefd.js",revision:"77aa277599bafefd"},{url:"/_next/static/chunks/60996.373d14abb85bdd97.js",revision:"373d14abb85bdd97"},{url:"/_next/static/chunks/61068.6c10151d2f552ed6.js",revision:"6c10151d2f552ed6"},{url:"/_next/static/chunks/61264.f9fbb94e766302ea.js",revision:"f9fbb94e766302ea"},{url:"/_next/static/chunks/61319.4779278253bccfec.js",revision:"4779278253bccfec"},{url:"/_next/static/chunks/61396.a832f878a8d7d632.js",revision:"a832f878a8d7d632"},{url:"/_next/static/chunks/61422.d2e722b65b74f6e8.js",revision:"d2e722b65b74f6e8"},{url:"/_next/static/chunks/61442.bb64b9345864470e.js",revision:"bb64b9345864470e"},{url:"/_next/static/chunks/61604.69848dcb2d10163a.js",revision:"69848dcb2d10163a"},{url:"/_next/static/chunks/61785.2425015034d24170.js",revision:"2425015034d24170"},{url:"/_next/static/chunks/61821.31f026144a674559.js",revision:"31f026144a674559"},{url:"/_next/static/chunks/61848.b93ee821037f5825.js",revision:"b93ee821037f5825"},{url:"/_next/static/chunks/62051.eecbdd70c71a2500.js",revision:"eecbdd70c71a2500"},{url:"/_next/static/chunks/62068-333e92331282ab94.js",revision:"333e92331282ab94"},{url:"/_next/static/chunks/62483.8fd42015b6a24944.js",revision:"8fd42015b6a24944"},{url:"/_next/static/chunks/62512.96f95fc564a6b5ac.js",revision:"96f95fc564a6b5ac"},{url:"/_next/static/chunks/62613.770cb2d077e05599.js",revision:"770cb2d077e05599"},{url:"/_next/static/chunks/62738.374eee8039340e7e.js",revision:"374eee8039340e7e"},{url:"/_next/static/chunks/62955.2015c34009cdeb03.js",revision:"2015c34009cdeb03"},{url:"/_next/static/chunks/63360-1b35e94b9bc6b4b0.js",revision:"1b35e94b9bc6b4b0"},{url:"/_next/static/chunks/63482.b800e30a7519ef3c.js",revision:"b800e30a7519ef3c"},{url:"/_next/static/chunks/6352-c423a858ce858a06.js",revision:"c423a858ce858a06"},{url:"/_next/static/chunks/63847.e3f69be7969555f1.js",revision:"e3f69be7969555f1"},{url:"/_next/static/chunks/64196.517fc50cebd880fd.js",revision:"517fc50cebd880fd"},{url:"/_next/static/chunks/64209.5911d1a542fa7722.js",revision:"5911d1a542fa7722"},{url:"/_next/static/chunks/64296.8315b157513c2e8e.js",revision:"8315b157513c2e8e"},{url:"/_next/static/chunks/64301.97f0e2cff064cfe7.js",revision:"97f0e2cff064cfe7"},{url:"/_next/static/chunks/64419.4d5c93959464aa08.js",revision:"4d5c93959464aa08"},{url:"/_next/static/chunks/64577.96fa6510f117de8b.js",revision:"96fa6510f117de8b"},{url:"/_next/static/chunks/64598.ff88174c3fca859e.js",revision:"ff88174c3fca859e"},{url:"/_next/static/chunks/64655.856a66759092f3bd.js",revision:"856a66759092f3bd"},{url:"/_next/static/chunks/65140.16149fd00b724548.js",revision:"16149fd00b724548"},{url:"/_next/static/chunks/6516-f9734f6965877053.js",revision:"f9734f6965877053"},{url:"/_next/static/chunks/65246.0f3691d4ea7250f5.js",revision:"0f3691d4ea7250f5"},{url:"/_next/static/chunks/65457.174baa3ccbdfce60.js",revision:"174baa3ccbdfce60"},{url:"/_next/static/chunks/65934.a43c9ede551420e5.js",revision:"a43c9ede551420e5"},{url:"/_next/static/chunks/66185.272964edc75d712e.js",revision:"272964edc75d712e"},{url:"/_next/static/chunks/66229.2c90a9d8e082cacb.js",revision:"2c90a9d8e082cacb"},{url:"/_next/static/chunks/66246.54f600f5bdc5ae35.js",revision:"54f600f5bdc5ae35"},{url:"/_next/static/chunks/66282.747f460d20f8587b.js",revision:"747f460d20f8587b"},{url:"/_next/static/chunks/66293.83bb9e464c9a610c.js",revision:"83bb9e464c9a610c"},{url:"/_next/static/chunks/66551.a674b7157b76896b.js",revision:"a674b7157b76896b"},{url:"/_next/static/chunks/66669.fbf288f69e91d623.js",revision:"fbf288f69e91d623"},{url:"/_next/static/chunks/6671.7c624e6256c1b248.js",revision:"7c624e6256c1b248"},{url:"/_next/static/chunks/66892.5b8e3e238ba7c48f.js",revision:"5b8e3e238ba7c48f"},{url:"/_next/static/chunks/66912.89ef7185a6826031.js",revision:"89ef7185a6826031"},{url:"/_next/static/chunks/66933.4be197eb9b1bf28f.js",revision:"4be197eb9b1bf28f"},{url:"/_next/static/chunks/67187.b0e2cfbf950c7820.js",revision:"b0e2cfbf950c7820"},{url:"/_next/static/chunks/67238.355074b5cf5de0a0.js",revision:"355074b5cf5de0a0"},{url:"/_next/static/chunks/67558.02357faf5b097fd7.js",revision:"02357faf5b097fd7"},{url:"/_next/static/chunks/67636.c8c7013b8093c234.js",revision:"c8c7013b8093c234"},{url:"/_next/static/chunks/67735.f398171c8bcc48e4.js",revision:"f398171c8bcc48e4"},{url:"/_next/static/chunks/67736.d389ab6455eb3266.js",revision:"d389ab6455eb3266"},{url:"/_next/static/chunks/67773-8d020a288a814616.js",revision:"8d020a288a814616"},{url:"/_next/static/chunks/67944.8a8ce2e65c529550.js",revision:"8a8ce2e65c529550"},{url:"/_next/static/chunks/68238.e60df98c44763ac0.js",revision:"e60df98c44763ac0"},{url:"/_next/static/chunks/68261-8d70a852cd02d709.js",revision:"8d70a852cd02d709"},{url:"/_next/static/chunks/68317.475eca3fba66f2cb.js",revision:"475eca3fba66f2cb"},{url:"/_next/static/chunks/68374.75cd33e645f82990.js",revision:"75cd33e645f82990"},{url:"/_next/static/chunks/68593.eb3f64b0bd1adbf9.js",revision:"eb3f64b0bd1adbf9"},{url:"/_next/static/chunks/68613.d2dfefdb7be8729d.js",revision:"d2dfefdb7be8729d"},{url:"/_next/static/chunks/68623.a2fa8173a81e96c7.js",revision:"a2fa8173a81e96c7"},{url:"/_next/static/chunks/68678.678b7b11f9ead911.js",revision:"678b7b11f9ead911"},{url:"/_next/static/chunks/68716-7ef1dd5631ee3c27.js",revision:"7ef1dd5631ee3c27"},{url:"/_next/static/chunks/68767.5012a7f10f40031e.js",revision:"5012a7f10f40031e"},{url:"/_next/static/chunks/6903.1baf2eea6f9189ef.js",revision:"1baf2eea6f9189ef"},{url:"/_next/static/chunks/69061.2cc069352f9957cc.js",revision:"2cc069352f9957cc"},{url:"/_next/static/chunks/69078-5901674cfcfd7a3f.js",revision:"5901674cfcfd7a3f"},{url:"/_next/static/chunks/69092.5523bc55bec5c952.js",revision:"5523bc55bec5c952"},{url:"/_next/static/chunks/69121.7b277dfcc4d51063.js",revision:"7b277dfcc4d51063"},{url:"/_next/static/chunks/69370.ada60e73535d0af0.js",revision:"ada60e73535d0af0"},{url:"/_next/static/chunks/69462.8b2415640e299af0.js",revision:"8b2415640e299af0"},{url:"/_next/static/chunks/69576.d6a7f2f28c695281.js",revision:"d6a7f2f28c695281"},{url:"/_next/static/chunks/6994.40e0e85f71728898.js",revision:"40e0e85f71728898"},{url:"/_next/static/chunks/69940.38d06eea458aa1c2.js",revision:"38d06eea458aa1c2"},{url:"/_next/static/chunks/703630e8.b8508f7ffe4e8b83.js",revision:"b8508f7ffe4e8b83"},{url:"/_next/static/chunks/70462-474c347309d4b5e9.js",revision:"474c347309d4b5e9"},{url:"/_next/static/chunks/70467.24f5dad36a2a3d29.js",revision:"24f5dad36a2a3d29"},{url:"/_next/static/chunks/70583.ad7ddd3192b7872c.js",revision:"ad7ddd3192b7872c"},{url:"/_next/static/chunks/70773-cdc2c58b9193f68c.js",revision:"cdc2c58b9193f68c"},{url:"/_next/static/chunks/70777.55d75dc8398ab065.js",revision:"55d75dc8398ab065"},{url:"/_next/static/chunks/70980.36ba30616317f150.js",revision:"36ba30616317f150"},{url:"/_next/static/chunks/71090.da54499c46683a36.js",revision:"da54499c46683a36"},{url:"/_next/static/chunks/71166.1e43a5a12fe27c16.js",revision:"1e43a5a12fe27c16"},{url:"/_next/static/chunks/71228.0ab9d25ae83b2ed9.js",revision:"0ab9d25ae83b2ed9"},{url:"/_next/static/chunks/71237.43618b676fae3e34.js",revision:"43618b676fae3e34"},{url:"/_next/static/chunks/7140.049cae991f2522b3.js",revision:"049cae991f2522b3"},{url:"/_next/static/chunks/71434.43014b9e3119d98d.js",revision:"43014b9e3119d98d"},{url:"/_next/static/chunks/71479.678d6b1ff17a50c3.js",revision:"678d6b1ff17a50c3"},{url:"/_next/static/chunks/71587.1acfb60fc2468ddb.js",revision:"1acfb60fc2468ddb"},{url:"/_next/static/chunks/71639.9b777574909cbd92.js",revision:"9b777574909cbd92"},{url:"/_next/static/chunks/71673.1f125c11fab4593c.js",revision:"1f125c11fab4593c"},{url:"/_next/static/chunks/71825.d5a5cbefe14bac40.js",revision:"d5a5cbefe14bac40"},{url:"/_next/static/chunks/71935.e039613d47bb0c5d.js",revision:"e039613d47bb0c5d"},{url:"/_next/static/chunks/72072.a9db8d18318423a0.js",revision:"a9db8d18318423a0"},{url:"/_next/static/chunks/72102.0d413358b0bbdaff.js",revision:"0d413358b0bbdaff"},{url:"/_next/static/chunks/72335.c18abd8b4b0461ca.js",revision:"c18abd8b4b0461ca"},{url:"/_next/static/chunks/7246.c28ff77d1bd37883.js",revision:"c28ff77d1bd37883"},{url:"/_next/static/chunks/72774.5f0bfa8577d88734.js",revision:"5f0bfa8577d88734"},{url:"/_next/static/chunks/72890.81905cc00613cdc8.js",revision:"81905cc00613cdc8"},{url:"/_next/static/chunks/72923.6b6846eee8228f64.js",revision:"6b6846eee8228f64"},{url:"/_next/static/chunks/72976.a538f0a89fa73049.js",revision:"a538f0a89fa73049"},{url:"/_next/static/chunks/73021.1e20339c558cf8c2.js",revision:"1e20339c558cf8c2"},{url:"/_next/static/chunks/73221.5aed83c2295dd556.js",revision:"5aed83c2295dd556"},{url:"/_next/static/chunks/73229.0893d6f40dfb8833.js",revision:"0893d6f40dfb8833"},{url:"/_next/static/chunks/73328-beea7d94a6886e77.js",revision:"beea7d94a6886e77"},{url:"/_next/static/chunks/73340.7209dfc4e3583b4e.js",revision:"7209dfc4e3583b4e"},{url:"/_next/static/chunks/73519.34607c290cfecc9f.js",revision:"34607c290cfecc9f"},{url:"/_next/static/chunks/73622.a1ba2ff411e8482c.js",revision:"a1ba2ff411e8482c"},{url:"/_next/static/chunks/7366.8c901d4c2daa0729.js",revision:"8c901d4c2daa0729"},{url:"/_next/static/chunks/74063.be3ab6a0f3918b70.js",revision:"be3ab6a0f3918b70"},{url:"/_next/static/chunks/741.cbb370ec65ee2808.js",revision:"cbb370ec65ee2808"},{url:"/_next/static/chunks/74157.06fc5af420388b4b.js",revision:"06fc5af420388b4b"},{url:"/_next/static/chunks/74186.761fca007d0bd520.js",revision:"761fca007d0bd520"},{url:"/_next/static/chunks/74293.90e0d4f989187aec.js",revision:"90e0d4f989187aec"},{url:"/_next/static/chunks/74407.aab476720c379ac6.js",revision:"aab476720c379ac6"},{url:"/_next/static/chunks/74421.0fc85575a9018521.js",revision:"0fc85575a9018521"},{url:"/_next/static/chunks/74545.8bfc570b8ff75059.js",revision:"8bfc570b8ff75059"},{url:"/_next/static/chunks/74558.56eb7f399f5f5664.js",revision:"56eb7f399f5f5664"},{url:"/_next/static/chunks/74560.95757a9f205c029c.js",revision:"95757a9f205c029c"},{url:"/_next/static/chunks/74565.aec3da0ec73a62d8.js",revision:"aec3da0ec73a62d8"},{url:"/_next/static/chunks/7469.3252cf6f77993627.js",revision:"3252cf6f77993627"},{url:"/_next/static/chunks/74861.979f0cf6068e05c1.js",revision:"979f0cf6068e05c1"},{url:"/_next/static/chunks/75146d7d-b63b39ceb44c002b.js",revision:"b63b39ceb44c002b"},{url:"/_next/static/chunks/75173.bb71ecc2a8f5b4af.js",revision:"bb71ecc2a8f5b4af"},{url:"/_next/static/chunks/75248.1e369d9f4e6ace5a.js",revision:"1e369d9f4e6ace5a"},{url:"/_next/static/chunks/75461.a9a455a6705f456c.js",revision:"a9a455a6705f456c"},{url:"/_next/static/chunks/75515.69aa7bfcd419ab5e.js",revision:"69aa7bfcd419ab5e"},{url:"/_next/static/chunks/75525.0237d30991c3ef4b.js",revision:"0237d30991c3ef4b"},{url:"/_next/static/chunks/75681.c9f3cbab6e74e4f9.js",revision:"c9f3cbab6e74e4f9"},{url:"/_next/static/chunks/75716.001e5661f840e3c8.js",revision:"001e5661f840e3c8"},{url:"/_next/static/chunks/7577.4856d8c69efb89ba.js",revision:"4856d8c69efb89ba"},{url:"/_next/static/chunks/75778.0a85c942bfa1318f.js",revision:"0a85c942bfa1318f"},{url:"/_next/static/chunks/75950.7e9f0cd675abb350.js",revision:"7e9f0cd675abb350"},{url:"/_next/static/chunks/75959.b648ebaa7bfaf8ca.js",revision:"b648ebaa7bfaf8ca"},{url:"/_next/static/chunks/76000.9d6c36a18d9cb51e.js",revision:"9d6c36a18d9cb51e"},{url:"/_next/static/chunks/76056.be9bcd184fc90530.js",revision:"be9bcd184fc90530"},{url:"/_next/static/chunks/76164.c98a73c72f35a7ae.js",revision:"c98a73c72f35a7ae"},{url:"/_next/static/chunks/76439.eb923b1e57743dfe.js",revision:"eb923b1e57743dfe"},{url:"/_next/static/chunks/7661.16df573093d193c5.js",revision:"16df573093d193c5"},{url:"/_next/static/chunks/76759.42664a1e54421ac7.js",revision:"42664a1e54421ac7"},{url:"/_next/static/chunks/77039.f95e0ae378929fa5.js",revision:"f95e0ae378929fa5"},{url:"/_next/static/chunks/77590.c6cd98832731b1cc.js",revision:"c6cd98832731b1cc"},{url:"/_next/static/chunks/77999.0adfbfb8fd0d33ec.js",revision:"0adfbfb8fd0d33ec"},{url:"/_next/static/chunks/77ab3b1e-f8bf51a99cf43e29.js",revision:"f8bf51a99cf43e29"},{url:"/_next/static/chunks/78674.75626b44b4b132f0.js",revision:"75626b44b4b132f0"},{url:"/_next/static/chunks/78699.2e8225d968350d1d.js",revision:"2e8225d968350d1d"},{url:"/_next/static/chunks/78762.b9bd8dc350c94a83.js",revision:"b9bd8dc350c94a83"},{url:"/_next/static/chunks/79259.cddffd58a7eae3ef.js",revision:"cddffd58a7eae3ef"},{url:"/_next/static/chunks/7959.1b0aaa48eee6bf32.js",revision:"1b0aaa48eee6bf32"},{url:"/_next/static/chunks/79626.e351735d516ec28e.js",revision:"e351735d516ec28e"},{url:"/_next/static/chunks/79703.b587dc8ccad9d08d.js",revision:"b587dc8ccad9d08d"},{url:"/_next/static/chunks/79761.fe16da0d6d1a106f.js",revision:"fe16da0d6d1a106f"},{url:"/_next/static/chunks/79874-599c49f92d2ef4f5.js",revision:"599c49f92d2ef4f5"},{url:"/_next/static/chunks/79961-acede45d96adbe1d.js",revision:"acede45d96adbe1d"},{url:"/_next/static/chunks/80195.1b40476084482063.js",revision:"1b40476084482063"},{url:"/_next/static/chunks/80197.eb16655a681c6190.js",revision:"eb16655a681c6190"},{url:"/_next/static/chunks/80373.f23025b9f36a5e37.js",revision:"f23025b9f36a5e37"},{url:"/_next/static/chunks/80449.7e6b89e55159f1bc.js",revision:"7e6b89e55159f1bc"},{url:"/_next/static/chunks/80581.87453c93004051a7.js",revision:"87453c93004051a7"},{url:"/_next/static/chunks/8062.cfb9c805c06f6949.js",revision:"cfb9c805c06f6949"},{url:"/_next/static/chunks/8072.1ba3571ad6e23cfe.js",revision:"1ba3571ad6e23cfe"},{url:"/_next/static/chunks/8094.27df35d51034f739.js",revision:"27df35d51034f739"},{url:"/_next/static/chunks/81162-18679861f0708c4e.js",revision:"18679861f0708c4e"},{url:"/_next/static/chunks/81245.9038602c14e0dd4e.js",revision:"9038602c14e0dd4e"},{url:"/_next/static/chunks/81318.ccc850b7b5ae40bd.js",revision:"ccc850b7b5ae40bd"},{url:"/_next/static/chunks/81422-bbbc2ba3f0cc4e66.js",revision:"bbbc2ba3f0cc4e66"},{url:"/_next/static/chunks/81533.157b33a7c70b005e.js",revision:"157b33a7c70b005e"},{url:"/_next/static/chunks/81693.2f24dbcc00a5cb72.js",revision:"2f24dbcc00a5cb72"},{url:"/_next/static/chunks/8170.4a55e17ad2cad666.js",revision:"4a55e17ad2cad666"},{url:"/_next/static/chunks/81700.d60f7d7f6038c837.js",revision:"d60f7d7f6038c837"},{url:"/_next/static/chunks/8194.cbbfeafda1601a18.js",revision:"cbbfeafda1601a18"},{url:"/_next/static/chunks/8195-c6839858c3f9aec5.js",revision:"c6839858c3f9aec5"},{url:"/_next/static/chunks/8200.3c75f3bab215483e.js",revision:"3c75f3bab215483e"},{url:"/_next/static/chunks/82232.1052ff7208a67415.js",revision:"1052ff7208a67415"},{url:"/_next/static/chunks/82316.7b1c2c81f1086454.js",revision:"7b1c2c81f1086454"},{url:"/_next/static/chunks/82752.0261e82ccb154685.js",revision:"0261e82ccb154685"},{url:"/_next/static/chunks/83123.7265903156b4cf3a.js",revision:"7265903156b4cf3a"},{url:"/_next/static/chunks/83231.5c88d13812ff91dc.js",revision:"5c88d13812ff91dc"},{url:"/_next/static/chunks/83334-20d155f936e5c2d0.js",revision:"20d155f936e5c2d0"},{url:"/_next/static/chunks/83400.7412446ee7ab051d.js",revision:"7412446ee7ab051d"},{url:"/_next/static/chunks/83606-3866ba699eba7113.js",revision:"3866ba699eba7113"},{url:"/_next/static/chunks/84008.ee9796764b6cdd47.js",revision:"ee9796764b6cdd47"},{url:"/_next/static/chunks/85141.0a8a7d754464eb0f.js",revision:"0a8a7d754464eb0f"},{url:"/_next/static/chunks/85191.bb6acbbbe1179751.js",revision:"bb6acbbbe1179751"},{url:"/_next/static/chunks/8530.ba2ed5ce9f652717.js",revision:"ba2ed5ce9f652717"},{url:"/_next/static/chunks/85321.e9eefd44ed3e44f5.js",revision:"e9eefd44ed3e44f5"},{url:"/_next/static/chunks/85477.27550d696822bbf7.js",revision:"27550d696822bbf7"},{url:"/_next/static/chunks/85608.498835fa9446632d.js",revision:"498835fa9446632d"},{url:"/_next/static/chunks/85642.7f7cd4c48f43c3bc.js",revision:"7f7cd4c48f43c3bc"},{url:"/_next/static/chunks/85799.225cbb4ddd6940e1.js",revision:"225cbb4ddd6940e1"},{url:"/_next/static/chunks/85956.a742f2466e4015a3.js",revision:"a742f2466e4015a3"},{url:"/_next/static/chunks/86155-32c6a7bcb5a98572.js",revision:"32c6a7bcb5a98572"},{url:"/_next/static/chunks/86215-4678ab2fdccbd1e2.js",revision:"4678ab2fdccbd1e2"},{url:"/_next/static/chunks/86343.1d48e96df2594340.js",revision:"1d48e96df2594340"},{url:"/_next/static/chunks/86597.b725376659ad10fe.js",revision:"b725376659ad10fe"},{url:"/_next/static/chunks/86765.c4cc5a8d24a581ae.js",revision:"c4cc5a8d24a581ae"},{url:"/_next/static/chunks/86991.4d6502bfa8f7db19.js",revision:"4d6502bfa8f7db19"},{url:"/_next/static/chunks/87073.990b74086f778d94.js",revision:"990b74086f778d94"},{url:"/_next/static/chunks/87165.286f970d45bcafc2.js",revision:"286f970d45bcafc2"},{url:"/_next/static/chunks/87191.3409cf7f85aa0b47.js",revision:"3409cf7f85aa0b47"},{url:"/_next/static/chunks/87331.79c9de5462f08cb0.js",revision:"79c9de5462f08cb0"},{url:"/_next/static/chunks/87527-55eedb9c689577f5.js",revision:"55eedb9c689577f5"},{url:"/_next/static/chunks/87528.f5f8adef6c2697e3.js",revision:"f5f8adef6c2697e3"},{url:"/_next/static/chunks/87567.46e360d54425a042.js",revision:"46e360d54425a042"},{url:"/_next/static/chunks/87610.8bab545588dccdc3.js",revision:"8bab545588dccdc3"},{url:"/_next/static/chunks/87778.5229ce757bba9d0e.js",revision:"5229ce757bba9d0e"},{url:"/_next/static/chunks/87809.8bae30b457b37735.js",revision:"8bae30b457b37735"},{url:"/_next/static/chunks/87828.0ebcd13d9a353d8f.js",revision:"0ebcd13d9a353d8f"},{url:"/_next/static/chunks/87897.420554342c98d3e2.js",revision:"420554342c98d3e2"},{url:"/_next/static/chunks/88055.6ee53ad3edb985dd.js",revision:"6ee53ad3edb985dd"},{url:"/_next/static/chunks/88123-5e8c8f235311aeaf.js",revision:"5e8c8f235311aeaf"},{url:"/_next/static/chunks/88137.981329e59c74a4ce.js",revision:"981329e59c74a4ce"},{url:"/_next/static/chunks/88205.55aeaf641a4b6132.js",revision:"55aeaf641a4b6132"},{url:"/_next/static/chunks/88477-d6c6e51118f91382.js",revision:"d6c6e51118f91382"},{url:"/_next/static/chunks/88678.8a9b8c4027ac68fb.js",revision:"8a9b8c4027ac68fb"},{url:"/_next/static/chunks/88716.3a8ca48db56529e5.js",revision:"3a8ca48db56529e5"},{url:"/_next/static/chunks/88908.3a33af34520f7883.js",revision:"3a33af34520f7883"},{url:"/_next/static/chunks/89381.1b62aa1dbf7de07e.js",revision:"1b62aa1dbf7de07e"},{url:"/_next/static/chunks/89417.1620b5c658f31f73.js",revision:"1620b5c658f31f73"},{url:"/_next/static/chunks/89575-31d7d686051129fe.js",revision:"31d7d686051129fe"},{url:"/_next/static/chunks/89642.a85207ad9d763ef8.js",revision:"a85207ad9d763ef8"},{url:"/_next/static/chunks/90105.9be2284c3b93b5fd.js",revision:"9be2284c3b93b5fd"},{url:"/_next/static/chunks/90199.5c403c69c1e4357d.js",revision:"5c403c69c1e4357d"},{url:"/_next/static/chunks/90279-c9546d4e0bb400f8.js",revision:"c9546d4e0bb400f8"},{url:"/_next/static/chunks/90383.192b50ab145d8bd1.js",revision:"192b50ab145d8bd1"},{url:"/_next/static/chunks/90427.74f430d5b2ae45af.js",revision:"74f430d5b2ae45af"},{url:"/_next/static/chunks/90471.5f6e6f8a98ca5033.js",revision:"5f6e6f8a98ca5033"},{url:"/_next/static/chunks/90536.fe1726d6cd2ea357.js",revision:"fe1726d6cd2ea357"},{url:"/_next/static/chunks/90595.785124d1120d27f9.js",revision:"785124d1120d27f9"},{url:"/_next/static/chunks/9071.876ba5ef39371c47.js",revision:"876ba5ef39371c47"},{url:"/_next/static/chunks/90780.fdaa2a6b5e7dd697.js",revision:"fdaa2a6b5e7dd697"},{url:"/_next/static/chunks/90957.0490253f0ae6f485.js",revision:"0490253f0ae6f485"},{url:"/_next/static/chunks/91143-2a701f58798c89d0.js",revision:"2a701f58798c89d0"},{url:"/_next/static/chunks/91261.21406379ab458d52.js",revision:"21406379ab458d52"},{url:"/_next/static/chunks/91393.dc35da467774f444.js",revision:"dc35da467774f444"},{url:"/_next/static/chunks/91422.d9529e608800ea75.js",revision:"d9529e608800ea75"},{url:"/_next/static/chunks/91451.288156397e47d9b8.js",revision:"288156397e47d9b8"},{url:"/_next/static/chunks/91527.7ca5762ef10d40ee.js",revision:"7ca5762ef10d40ee"},{url:"/_next/static/chunks/91671.361167a6338cd901.js",revision:"361167a6338cd901"},{url:"/_next/static/chunks/91889-5a0ce10d39717b4f.js",revision:"5a0ce10d39717b4f"},{url:"/_next/static/chunks/92388.a207ebbfe7c3d26d.js",revision:"a207ebbfe7c3d26d"},{url:"/_next/static/chunks/92400.1fb3823935e73d42.js",revision:"1fb3823935e73d42"},{url:"/_next/static/chunks/92492.59a11478b339316b.js",revision:"59a11478b339316b"},{url:"/_next/static/chunks/92561.e1c3bf1e9f920802.js",revision:"e1c3bf1e9f920802"},{url:"/_next/static/chunks/92731-8ff5c1266b208156.js",revision:"8ff5c1266b208156"},{url:"/_next/static/chunks/92772.6880fad8f52c4feb.js",revision:"6880fad8f52c4feb"},{url:"/_next/static/chunks/92962.74ae7d8bd89b3e31.js",revision:"74ae7d8bd89b3e31"},{url:"/_next/static/chunks/92969-c5c9edce1e2e6c8b.js",revision:"c5c9edce1e2e6c8b"},{url:"/_next/static/chunks/93074.5c9d506a202dce96.js",revision:"5c9d506a202dce96"},{url:"/_next/static/chunks/93114.b76e36cd7bd6e19d.js",revision:"b76e36cd7bd6e19d"},{url:"/_next/static/chunks/93118.0440926174432bcf.js",revision:"0440926174432bcf"},{url:"/_next/static/chunks/93145-b63023ada2f33fff.js",revision:"b63023ada2f33fff"},{url:"/_next/static/chunks/93173.ade511976ed51856.js",revision:"ade511976ed51856"},{url:"/_next/static/chunks/93182.6ee1b69d0aa27e8c.js",revision:"6ee1b69d0aa27e8c"},{url:"/_next/static/chunks/93341-6783e5f3029a130b.js",revision:"6783e5f3029a130b"},{url:"/_next/static/chunks/93421.787d9aa35e07bc44.js",revision:"787d9aa35e07bc44"},{url:"/_next/static/chunks/93563.ab762101ccffb4e0.js",revision:"ab762101ccffb4e0"},{url:"/_next/static/chunks/93569.b12d2af31e0a6fa2.js",revision:"b12d2af31e0a6fa2"},{url:"/_next/static/chunks/93797.daaa7647b2a1dc6a.js",revision:"daaa7647b2a1dc6a"},{url:"/_next/static/chunks/93899.728e85db64be1bc6.js",revision:"728e85db64be1bc6"},{url:"/_next/static/chunks/94017.2e401f1acc097f7d.js",revision:"2e401f1acc097f7d"},{url:"/_next/static/chunks/94068.9faf55d51f6526c4.js",revision:"9faf55d51f6526c4"},{url:"/_next/static/chunks/94078.58a7480b32dae5a8.js",revision:"58a7480b32dae5a8"},{url:"/_next/static/chunks/94101.eab83afd2ca6d222.js",revision:"eab83afd2ca6d222"},{url:"/_next/static/chunks/94215.188da4736c80fc01.js",revision:"188da4736c80fc01"},{url:"/_next/static/chunks/94281-db58741f0aeb372e.js",revision:"db58741f0aeb372e"},{url:"/_next/static/chunks/94345-d0b23494b17cc99f.js",revision:"d0b23494b17cc99f"},{url:"/_next/static/chunks/94349.872b4a1e42ace7f2.js",revision:"872b4a1e42ace7f2"},{url:"/_next/static/chunks/94670.d6b2d3a678eb4da3.js",revision:"d6b2d3a678eb4da3"},{url:"/_next/static/chunks/94787.ceec61ab6dff6688.js",revision:"ceec61ab6dff6688"},{url:"/_next/static/chunks/94831-526536a85c9a6bdb.js",revision:"526536a85c9a6bdb"},{url:"/_next/static/chunks/94837.715e9dca315c39b4.js",revision:"715e9dca315c39b4"},{url:"/_next/static/chunks/9495.eb477a65bbbc2992.js",revision:"eb477a65bbbc2992"},{url:"/_next/static/chunks/94956.1b5c1e9f2fbc6df5.js",revision:"1b5c1e9f2fbc6df5"},{url:"/_next/static/chunks/94993.ad3f4bfaff049ca8.js",revision:"ad3f4bfaff049ca8"},{url:"/_next/static/chunks/9532.60130fa22f635a18.js",revision:"60130fa22f635a18"},{url:"/_next/static/chunks/95381.cce5dd15c25f2994.js",revision:"cce5dd15c25f2994"},{url:"/_next/static/chunks/95396.0934e7a5e10197d1.js",revision:"0934e7a5e10197d1"},{url:"/_next/static/chunks/95407.2ee1da2299bba1a8.js",revision:"2ee1da2299bba1a8"},{url:"/_next/static/chunks/95409.94814309f78e3c5c.js",revision:"94814309f78e3c5c"},{url:"/_next/static/chunks/95620.f9eddae9368015e5.js",revision:"f9eddae9368015e5"},{url:"/_next/static/chunks/9585.131a2c63e5b8a264.js",revision:"131a2c63e5b8a264"},{url:"/_next/static/chunks/96332.9430f87cbdb1705b.js",revision:"9430f87cbdb1705b"},{url:"/_next/static/chunks/96407.e7bf8b423fdbb39a.js",revision:"e7bf8b423fdbb39a"},{url:"/_next/static/chunks/96408.f022e26f95b48a75.js",revision:"f022e26f95b48a75"},{url:"/_next/static/chunks/96538.b1c0b59b9549e1e2.js",revision:"b1c0b59b9549e1e2"},{url:"/_next/static/chunks/97058-037c2683762e75ab.js",revision:"037c2683762e75ab"},{url:"/_next/static/chunks/9708.7044690bc88bb602.js",revision:"7044690bc88bb602"},{url:"/_next/static/chunks/97114-6ac8104fd90b0e7b.js",revision:"6ac8104fd90b0e7b"},{url:"/_next/static/chunks/97236.dfe49ef38d88cc45.js",revision:"dfe49ef38d88cc45"},{url:"/_next/static/chunks/97274.23ab786b634d9b99.js",revision:"23ab786b634d9b99"},{url:"/_next/static/chunks/97285.cb10fb2a3788209d.js",revision:"cb10fb2a3788209d"},{url:"/_next/static/chunks/97298.438147bc65fc7d9a.js",revision:"438147bc65fc7d9a"},{url:"/_next/static/chunks/9731.5940adfabf75a8c8.js",revision:"5940adfabf75a8c8"},{url:"/_next/static/chunks/9749-256161a3e8327791.js",revision:"256161a3e8327791"},{url:"/_next/static/chunks/97529.bf872828850d9294.js",revision:"bf872828850d9294"},{url:"/_next/static/chunks/97739.0ea276d823af3634.js",revision:"0ea276d823af3634"},{url:"/_next/static/chunks/98053.078efa31852ebf12.js",revision:"078efa31852ebf12"},{url:"/_next/static/chunks/98409.1172de839121afc6.js",revision:"1172de839121afc6"},{url:"/_next/static/chunks/98486.4f0be4f954a3a606.js",revision:"4f0be4f954a3a606"},{url:"/_next/static/chunks/98611-3385436ac869beb4.js",revision:"3385436ac869beb4"},{url:"/_next/static/chunks/98693.adc70834eff7c3ed.js",revision:"adc70834eff7c3ed"},{url:"/_next/static/chunks/98763.e845c55158eeb8f3.js",revision:"e845c55158eeb8f3"},{url:"/_next/static/chunks/98791.1dc24bae9079b508.js",revision:"1dc24bae9079b508"},{url:"/_next/static/chunks/98879-58310d4070df46f1.js",revision:"58310d4070df46f1"},{url:"/_next/static/chunks/99040-be2224b07fe6c1d4.js",revision:"be2224b07fe6c1d4"},{url:"/_next/static/chunks/99361-8072a0f644e9e8b3.js",revision:"8072a0f644e9e8b3"},{url:"/_next/static/chunks/99468.eeddf14d71bbba42.js",revision:"eeddf14d71bbba42"},{url:"/_next/static/chunks/99488.e6e6c67d29690e29.js",revision:"e6e6c67d29690e29"},{url:"/_next/static/chunks/99605.4bd3e037a36a009b.js",revision:"4bd3e037a36a009b"},{url:"/_next/static/chunks/9982.02faca849525389b.js",revision:"02faca849525389b"},{url:"/_next/static/chunks/ade92b7e-b80f4007963aa2ea.js",revision:"b80f4007963aa2ea"},{url:"/_next/static/chunks/adeb31b9-1bc732df2736a7c7.js",revision:"1bc732df2736a7c7"},{url:"/_next/static/chunks/app/(commonLayout)/app/(appDetailLayout)/%5BappId%5D/annotations/page-bed321fdfb3de005.js",revision:"bed321fdfb3de005"},{url:"/_next/static/chunks/app/(commonLayout)/app/(appDetailLayout)/%5BappId%5D/configuration/page-89c8fe27bca672af.js",revision:"89c8fe27bca672af"},{url:"/_next/static/chunks/app/(commonLayout)/app/(appDetailLayout)/%5BappId%5D/develop/page-24064ab04d3d57d6.js",revision:"24064ab04d3d57d6"},{url:"/_next/static/chunks/app/(commonLayout)/app/(appDetailLayout)/%5BappId%5D/layout-6c19b111064a2731.js",revision:"6c19b111064a2731"},{url:"/_next/static/chunks/app/(commonLayout)/app/(appDetailLayout)/%5BappId%5D/logs/page-ddb74395540182c1.js",revision:"ddb74395540182c1"},{url:"/_next/static/chunks/app/(commonLayout)/app/(appDetailLayout)/%5BappId%5D/overview/page-d2fb7ff2a8818796.js",revision:"d2fb7ff2a8818796"},{url:"/_next/static/chunks/app/(commonLayout)/app/(appDetailLayout)/%5BappId%5D/workflow/page-97159ef4cd2bd5a7.js",revision:"97159ef4cd2bd5a7"},{url:"/_next/static/chunks/app/(commonLayout)/app/(appDetailLayout)/layout-3c7730b7811ea1ae.js",revision:"3c7730b7811ea1ae"},{url:"/_next/static/chunks/app/(commonLayout)/apps/page-a3d0b21cdbaf962b.js",revision:"a3d0b21cdbaf962b"},{url:"/_next/static/chunks/app/(commonLayout)/datasets/(datasetDetailLayout)/%5BdatasetId%5D/api/page-7ac04c3c68eae26d.js",revision:"7ac04c3c68eae26d"},{url:"/_next/static/chunks/app/(commonLayout)/datasets/(datasetDetailLayout)/%5BdatasetId%5D/documents/%5BdocumentId%5D/page-94552d721af14748.js",revision:"94552d721af14748"},{url:"/_next/static/chunks/app/(commonLayout)/datasets/(datasetDetailLayout)/%5BdatasetId%5D/documents/%5BdocumentId%5D/settings/page-05ae79dbef8350cc.js",revision:"05ae79dbef8350cc"},{url:"/_next/static/chunks/app/(commonLayout)/datasets/(datasetDetailLayout)/%5BdatasetId%5D/documents/create/page-d2aa2a76e03ec53f.js",revision:"d2aa2a76e03ec53f"},{url:"/_next/static/chunks/app/(commonLayout)/datasets/(datasetDetailLayout)/%5BdatasetId%5D/documents/page-370cffab0f5b884a.js",revision:"370cffab0f5b884a"},{url:"/_next/static/chunks/app/(commonLayout)/datasets/(datasetDetailLayout)/%5BdatasetId%5D/hitTesting/page-20c8e200fc40de49.js",revision:"20c8e200fc40de49"},{url:"/_next/static/chunks/app/(commonLayout)/datasets/(datasetDetailLayout)/%5BdatasetId%5D/layout-c4910193b73acc38.js",revision:"c4910193b73acc38"},{url:"/_next/static/chunks/app/(commonLayout)/datasets/(datasetDetailLayout)/%5BdatasetId%5D/settings/page-d231cce377344c33.js",revision:"d231cce377344c33"},{url:"/_next/static/chunks/app/(commonLayout)/datasets/(datasetDetailLayout)/layout-7ac04c3c68eae26d.js",revision:"7ac04c3c68eae26d"},{url:"/_next/static/chunks/app/(commonLayout)/datasets/connect/page-222b21a0716d995e.js",revision:"222b21a0716d995e"},{url:"/_next/static/chunks/app/(commonLayout)/datasets/create/page-d2aa2a76e03ec53f.js",revision:"d2aa2a76e03ec53f"},{url:"/_next/static/chunks/app/(commonLayout)/datasets/layout-3726b0284e4f552b.js",revision:"3726b0284e4f552b"},{url:"/_next/static/chunks/app/(commonLayout)/datasets/page-03ff65eedb77ba4d.js",revision:"03ff65eedb77ba4d"},{url:"/_next/static/chunks/app/(commonLayout)/education-apply/page-291db89c2853e316.js",revision:"291db89c2853e316"},{url:"/_next/static/chunks/app/(commonLayout)/explore/apps/page-b6b03fc07666e36c.js",revision:"b6b03fc07666e36c"},{url:"/_next/static/chunks/app/(commonLayout)/explore/installed/%5BappId%5D/page-42bdc499cbe849eb.js",revision:"42bdc499cbe849eb"},{url:"/_next/static/chunks/app/(commonLayout)/explore/layout-07882b9360c8ff8b.js",revision:"07882b9360c8ff8b"},{url:"/_next/static/chunks/app/(commonLayout)/layout-180ee349235239dc.js",revision:"180ee349235239dc"},{url:"/_next/static/chunks/app/(commonLayout)/plugins/page-529f12cc5e2f9e0b.js",revision:"529f12cc5e2f9e0b"},{url:"/_next/static/chunks/app/(commonLayout)/tools/page-4ea8d3d5a7283926.js",revision:"4ea8d3d5a7283926"},{url:"/_next/static/chunks/app/(shareLayout)/chat/%5Btoken%5D/page-0f6b9f734fed56f9.js",revision:"0f6b9f734fed56f9"},{url:"/_next/static/chunks/app/(shareLayout)/chatbot/%5Btoken%5D/page-0a1e275f27786868.js",revision:"0a1e275f27786868"},{url:"/_next/static/chunks/app/(shareLayout)/completion/%5Btoken%5D/page-9d7b40ad12c37ab8.js",revision:"9d7b40ad12c37ab8"},{url:"/_next/static/chunks/app/(shareLayout)/layout-8fd27a89a617a8fd.js",revision:"8fd27a89a617a8fd"},{url:"/_next/static/chunks/app/(shareLayout)/webapp-reset-password/check-code/page-c4f111e617001d45.js",revision:"c4f111e617001d45"},{url:"/_next/static/chunks/app/(shareLayout)/webapp-reset-password/layout-598e0a9d3deb7093.js",revision:"598e0a9d3deb7093"},{url:"/_next/static/chunks/app/(shareLayout)/webapp-reset-password/page-e32ee30d405b03dd.js",revision:"e32ee30d405b03dd"},{url:"/_next/static/chunks/app/(shareLayout)/webapp-reset-password/set-password/page-dcb5b053896ba2f8.js",revision:"dcb5b053896ba2f8"},{url:"/_next/static/chunks/app/(shareLayout)/webapp-signin/check-code/page-6fcab2735c5ee65d.js",revision:"6fcab2735c5ee65d"},{url:"/_next/static/chunks/app/(shareLayout)/webapp-signin/layout-f6f60499c4b61eb5.js",revision:"f6f60499c4b61eb5"},{url:"/_next/static/chunks/app/(shareLayout)/webapp-signin/page-907e45c5a29faa8e.js",revision:"907e45c5a29faa8e"},{url:"/_next/static/chunks/app/(shareLayout)/workflow/%5Btoken%5D/page-9d7b40ad12c37ab8.js",revision:"9d7b40ad12c37ab8"},{url:"/_next/static/chunks/app/_not-found/page-2eeef5110e4b8b7e.js",revision:"2eeef5110e4b8b7e"},{url:"/_next/static/chunks/app/account/(commonLayout)/layout-3317cfcfa7c80c5e.js",revision:"3317cfcfa7c80c5e"},{url:"/_next/static/chunks/app/account/(commonLayout)/page-d8d8b5ed77c1c805.js",revision:"d8d8b5ed77c1c805"},{url:"/_next/static/chunks/app/account/oauth/authorize/layout-e7b4f9f7025b3cfb.js",revision:"e7b4f9f7025b3cfb"},{url:"/_next/static/chunks/app/account/oauth/authorize/page-e63ef7ac364ad40a.js",revision:"e63ef7ac364ad40a"},{url:"/_next/static/chunks/app/activate/page-dcaa7c3c8f7a2812.js",revision:"dcaa7c3c8f7a2812"},{url:"/_next/static/chunks/app/forgot-password/page-dba51d61349f4d18.js",revision:"dba51d61349f4d18"},{url:"/_next/static/chunks/app/init/page-8722713d36eff02f.js",revision:"8722713d36eff02f"},{url:"/_next/static/chunks/app/install/page-cb027e5896d9a96e.js",revision:"cb027e5896d9a96e"},{url:"/_next/static/chunks/app/layout-8ae1390b2153a336.js",revision:"8ae1390b2153a336"},{url:"/_next/static/chunks/app/oauth-callback/page-5b267867410ae1a7.js",revision:"5b267867410ae1a7"},{url:"/_next/static/chunks/app/page-404d11e3effcbff8.js",revision:"404d11e3effcbff8"},{url:"/_next/static/chunks/app/repos/%5Bowner%5D/%5Brepo%5D/releases/route-7ac04c3c68eae26d.js",revision:"7ac04c3c68eae26d"},{url:"/_next/static/chunks/app/reset-password/check-code/page-10bef517ef308dfb.js",revision:"10bef517ef308dfb"},{url:"/_next/static/chunks/app/reset-password/layout-f27825bca55d7830.js",revision:"f27825bca55d7830"},{url:"/_next/static/chunks/app/reset-password/page-cf30c370eb897f35.js",revision:"cf30c370eb897f35"},{url:"/_next/static/chunks/app/reset-password/set-password/page-d9d31640356b736b.js",revision:"d9d31640356b736b"},{url:"/_next/static/chunks/app/signin/check-code/page-a03bca2f9a4bfb8d.js",revision:"a03bca2f9a4bfb8d"},{url:"/_next/static/chunks/app/signin/invite-settings/page-1e7215ce95bb9140.js",revision:"1e7215ce95bb9140"},{url:"/_next/static/chunks/app/signin/layout-1f5ae3bfec73f783.js",revision:"1f5ae3bfec73f783"},{url:"/_next/static/chunks/app/signin/page-2ba8f06ba52c9167.js",revision:"2ba8f06ba52c9167"},{url:"/_next/static/chunks/bda40ab4-465678c6543fde64.js",revision:"465678c6543fde64"},{url:"/_next/static/chunks/e8b19606.458322a93703fefb.js",revision:"458322a93703fefb"},{url:"/_next/static/chunks/f707c8ea-8556dcacf5dfe4ac.js",revision:"8556dcacf5dfe4ac"},{url:"/_next/static/chunks/fc43f782-87ce714d5535dbd7.js",revision:"87ce714d5535dbd7"},{url:"/_next/static/chunks/framework-04e9e69c198b8f2b.js",revision:"04e9e69c198b8f2b"},{url:"/_next/static/chunks/main-app-a4623e6276e9b96e.js",revision:"a4623e6276e9b96e"},{url:"/_next/static/chunks/main-d162030eff8fdeec.js",revision:"d162030eff8fdeec"},{url:"/_next/static/chunks/pages/_app-20413ffd01cbb95e.js",revision:"20413ffd01cbb95e"},{url:"/_next/static/chunks/pages/_error-d3c892d153e773fa.js",revision:"d3c892d153e773fa"},{url:"/_next/static/chunks/polyfills-42372ed130431b0a.js",revision:"846118c33b2c0e922d7b3a7676f81f6f"},{url:"/_next/static/chunks/webpack-859633ab1bcec9ac.js",revision:"859633ab1bcec9ac"},{url:"/_next/static/css/054994666d6806c5.css",revision:"054994666d6806c5"},{url:"/_next/static/css/1935925f720c7d7b.css",revision:"1935925f720c7d7b"},{url:"/_next/static/css/1f87e86cd533e873.css",revision:"1f87e86cd533e873"},{url:"/_next/static/css/220a772cfe3c95f4.css",revision:"220a772cfe3c95f4"},{url:"/_next/static/css/2da23e89afd44708.css",revision:"2da23e89afd44708"},{url:"/_next/static/css/2f7a6ecf4e344b75.css",revision:"2f7a6ecf4e344b75"},{url:"/_next/static/css/5bb43505df05adfe.css",revision:"5bb43505df05adfe"},{url:"/_next/static/css/61080ff8f99d7fe2.css",revision:"61080ff8f99d7fe2"},{url:"/_next/static/css/64f9f179dbdcd998.css",revision:"64f9f179dbdcd998"},{url:"/_next/static/css/8163616c965c42dc.css",revision:"8163616c965c42dc"},{url:"/_next/static/css/9e90e05c5cca6fcc.css",revision:"9e90e05c5cca6fcc"},{url:"/_next/static/css/a01885eb9d0649e5.css",revision:"a01885eb9d0649e5"},{url:"/_next/static/css/a031600822501d72.css",revision:"a031600822501d72"},{url:"/_next/static/css/b7247e8b4219ed3e.css",revision:"b7247e8b4219ed3e"},{url:"/_next/static/css/bf38d9b349c92e2b.css",revision:"bf38d9b349c92e2b"},{url:"/_next/static/css/c31a5eb4ac1ad018.css",revision:"c31a5eb4ac1ad018"},{url:"/_next/static/css/e2d5add89ff4b6ec.css",revision:"e2d5add89ff4b6ec"},{url:"/_next/static/css/f1f829214ba58f39.css",revision:"f1f829214ba58f39"},{url:"/_next/static/css/f63ea6462efb620f.css",revision:"f63ea6462efb620f"},{url:"/_next/static/css/fab77c667364e2c1.css",revision:"fab77c667364e2c1"},{url:"/_next/static/hxi5kegOl0PxtKhvDL_OX/_buildManifest.js",revision:"19f5fadd0444f8ce77907b9889fa2523"},{url:"/_next/static/hxi5kegOl0PxtKhvDL_OX/_ssgManifest.js",revision:"b6652df95db52feb4daf4eca35380933"},{url:"/_next/static/media/D.c178ca36.png",revision:"c178ca36"},{url:"/_next/static/media/Grid.da5dce2f.svg",revision:"da5dce2f"},{url:"/_next/static/media/KaTeX_AMS-Regular.1608a09b.woff",revision:"1608a09b"},{url:"/_next/static/media/KaTeX_AMS-Regular.4aafdb68.ttf",revision:"4aafdb68"},{url:"/_next/static/media/KaTeX_AMS-Regular.a79f1c31.woff2",revision:"a79f1c31"},{url:"/_next/static/media/KaTeX_Caligraphic-Bold.b6770918.woff",revision:"b6770918"},{url:"/_next/static/media/KaTeX_Caligraphic-Bold.cce5b8ec.ttf",revision:"cce5b8ec"},{url:"/_next/static/media/KaTeX_Caligraphic-Bold.ec17d132.woff2",revision:"ec17d132"},{url:"/_next/static/media/KaTeX_Caligraphic-Regular.07ef19e7.ttf",revision:"07ef19e7"},{url:"/_next/static/media/KaTeX_Caligraphic-Regular.55fac258.woff2",revision:"55fac258"},{url:"/_next/static/media/KaTeX_Caligraphic-Regular.dad44a7f.woff",revision:"dad44a7f"},{url:"/_next/static/media/KaTeX_Fraktur-Bold.9f256b85.woff",revision:"9f256b85"},{url:"/_next/static/media/KaTeX_Fraktur-Bold.b18f59e1.ttf",revision:"b18f59e1"},{url:"/_next/static/media/KaTeX_Fraktur-Bold.d42a5579.woff2",revision:"d42a5579"},{url:"/_next/static/media/KaTeX_Fraktur-Regular.7c187121.woff",revision:"7c187121"},{url:"/_next/static/media/KaTeX_Fraktur-Regular.d3c882a6.woff2",revision:"d3c882a6"},{url:"/_next/static/media/KaTeX_Fraktur-Regular.ed38e79f.ttf",revision:"ed38e79f"},{url:"/_next/static/media/KaTeX_Main-Bold.b74a1a8b.ttf",revision:"b74a1a8b"},{url:"/_next/static/media/KaTeX_Main-Bold.c3fb5ac2.woff2",revision:"c3fb5ac2"},{url:"/_next/static/media/KaTeX_Main-Bold.d181c465.woff",revision:"d181c465"},{url:"/_next/static/media/KaTeX_Main-BoldItalic.6f2bb1df.woff2",revision:"6f2bb1df"},{url:"/_next/static/media/KaTeX_Main-BoldItalic.70d8b0a5.ttf",revision:"70d8b0a5"},{url:"/_next/static/media/KaTeX_Main-BoldItalic.e3f82f9d.woff",revision:"e3f82f9d"},{url:"/_next/static/media/KaTeX_Main-Italic.47373d1e.ttf",revision:"47373d1e"},{url:"/_next/static/media/KaTeX_Main-Italic.8916142b.woff2",revision:"8916142b"},{url:"/_next/static/media/KaTeX_Main-Italic.9024d815.woff",revision:"9024d815"},{url:"/_next/static/media/KaTeX_Main-Regular.0462f03b.woff2",revision:"0462f03b"},{url:"/_next/static/media/KaTeX_Main-Regular.7f51fe03.woff",revision:"7f51fe03"},{url:"/_next/static/media/KaTeX_Main-Regular.b7f8fe9b.ttf",revision:"b7f8fe9b"},{url:"/_next/static/media/KaTeX_Math-BoldItalic.572d331f.woff2",revision:"572d331f"},{url:"/_next/static/media/KaTeX_Math-BoldItalic.a879cf83.ttf",revision:"a879cf83"},{url:"/_next/static/media/KaTeX_Math-BoldItalic.f1035d8d.woff",revision:"f1035d8d"},{url:"/_next/static/media/KaTeX_Math-Italic.5295ba48.woff",revision:"5295ba48"},{url:"/_next/static/media/KaTeX_Math-Italic.939bc644.ttf",revision:"939bc644"},{url:"/_next/static/media/KaTeX_Math-Italic.f28c23ac.woff2",revision:"f28c23ac"},{url:"/_next/static/media/KaTeX_SansSerif-Bold.8c5b5494.woff2",revision:"8c5b5494"},{url:"/_next/static/media/KaTeX_SansSerif-Bold.94e1e8dc.ttf",revision:"94e1e8dc"},{url:"/_next/static/media/KaTeX_SansSerif-Bold.bf59d231.woff",revision:"bf59d231"},{url:"/_next/static/media/KaTeX_SansSerif-Italic.3b1e59b3.woff2",revision:"3b1e59b3"},{url:"/_next/static/media/KaTeX_SansSerif-Italic.7c9bc82b.woff",revision:"7c9bc82b"},{url:"/_next/static/media/KaTeX_SansSerif-Italic.b4c20c84.ttf",revision:"b4c20c84"},{url:"/_next/static/media/KaTeX_SansSerif-Regular.74048478.woff",revision:"74048478"},{url:"/_next/static/media/KaTeX_SansSerif-Regular.ba21ed5f.woff2",revision:"ba21ed5f"},{url:"/_next/static/media/KaTeX_SansSerif-Regular.d4d7ba48.ttf",revision:"d4d7ba48"},{url:"/_next/static/media/KaTeX_Script-Regular.03e9641d.woff2",revision:"03e9641d"},{url:"/_next/static/media/KaTeX_Script-Regular.07505710.woff",revision:"07505710"},{url:"/_next/static/media/KaTeX_Script-Regular.fe9cbbe1.ttf",revision:"fe9cbbe1"},{url:"/_next/static/media/KaTeX_Size1-Regular.e1e279cb.woff",revision:"e1e279cb"},{url:"/_next/static/media/KaTeX_Size1-Regular.eae34984.woff2",revision:"eae34984"},{url:"/_next/static/media/KaTeX_Size1-Regular.fabc004a.ttf",revision:"fabc004a"},{url:"/_next/static/media/KaTeX_Size2-Regular.57727022.woff",revision:"57727022"},{url:"/_next/static/media/KaTeX_Size2-Regular.5916a24f.woff2",revision:"5916a24f"},{url:"/_next/static/media/KaTeX_Size2-Regular.d6b476ec.ttf",revision:"d6b476ec"},{url:"/_next/static/media/KaTeX_Size3-Regular.9acaf01c.woff",revision:"9acaf01c"},{url:"/_next/static/media/KaTeX_Size3-Regular.a144ef58.ttf",revision:"a144ef58"},{url:"/_next/static/media/KaTeX_Size3-Regular.b4230e7e.woff2",revision:"b4230e7e"},{url:"/_next/static/media/KaTeX_Size4-Regular.10d95fd3.woff2",revision:"10d95fd3"},{url:"/_next/static/media/KaTeX_Size4-Regular.7a996c9d.woff",revision:"7a996c9d"},{url:"/_next/static/media/KaTeX_Size4-Regular.fbccdabe.ttf",revision:"fbccdabe"},{url:"/_next/static/media/KaTeX_Typewriter-Regular.6258592b.woff",revision:"6258592b"},{url:"/_next/static/media/KaTeX_Typewriter-Regular.a8709e36.woff2",revision:"a8709e36"},{url:"/_next/static/media/KaTeX_Typewriter-Regular.d97aaf4a.ttf",revision:"d97aaf4a"},{url:"/_next/static/media/Loading.e3210867.svg",revision:"e3210867"},{url:"/_next/static/media/action.943fbcb8.svg",revision:"943fbcb8"},{url:"/_next/static/media/alert-triangle.329eb694.svg",revision:"329eb694"},{url:"/_next/static/media/alpha.6ae07de6.svg",revision:"6ae07de6"},{url:"/_next/static/media/atSign.89c9e2f2.svg",revision:"89c9e2f2"},{url:"/_next/static/media/bezierCurve.3a25cfc7.svg",revision:"3a25cfc7"},{url:"/_next/static/media/bg-line-error.c74246ec.svg",revision:"c74246ec"},{url:"/_next/static/media/bg-line-running.738082be.svg",revision:"738082be"},{url:"/_next/static/media/bg-line-success.ef8d3b89.svg",revision:"ef8d3b89"},{url:"/_next/static/media/bg-line-warning.1d037d22.svg",revision:"1d037d22"},{url:"/_next/static/media/book-open-01.a92cde5a.svg",revision:"a92cde5a"},{url:"/_next/static/media/bookOpen.eb79709c.svg",revision:"eb79709c"},{url:"/_next/static/media/briefcase.bba83ea7.svg",revision:"bba83ea7"},{url:"/_next/static/media/cardLoading.816a9dec.svg",revision:"816a9dec"},{url:"/_next/static/media/chromeplugin-install.982c5cbf.svg",revision:"982c5cbf"},{url:"/_next/static/media/chromeplugin-option.435ebf5a.svg",revision:"435ebf5a"},{url:"/_next/static/media/clock.81f8162b.svg",revision:"81f8162b"},{url:"/_next/static/media/close.562225f1.svg",revision:"562225f1"},{url:"/_next/static/media/code-browser.d954b670.svg",revision:"d954b670"},{url:"/_next/static/media/copied.350b63f0.svg",revision:"350b63f0"},{url:"/_next/static/media/copy-hover.2cc86992.svg",revision:"2cc86992"},{url:"/_next/static/media/copy.89d68c8b.svg",revision:"89d68c8b"},{url:"/_next/static/media/csv.1e142089.svg",revision:"1e142089"},{url:"/_next/static/media/doc.cea48e13.svg",revision:"cea48e13"},{url:"/_next/static/media/docx.4beb0ca0.svg",revision:"4beb0ca0"},{url:"/_next/static/media/family-mod.be47b090.svg",revision:"1695c917b23f714303acd201ddad6363"},{url:"/_next/static/media/file-list-3-fill.57beb31b.svg",revision:"e56018243e089a817b2625f80b258f82"},{url:"/_next/static/media/file.5700c745.svg",revision:"5700c745"},{url:"/_next/static/media/file.889034a9.svg",revision:"889034a9"},{url:"/_next/static/media/github-dark.b93b0533.svg",revision:"b93b0533"},{url:"/_next/static/media/github.fb41aac3.svg",revision:"fb41aac3"},{url:"/_next/static/media/globe.52a87779.svg",revision:"52a87779"},{url:"/_next/static/media/gold.e08d4e7c.svg",revision:"93ad9287fde1e70efe3e1bec6a3ad9f3"},{url:"/_next/static/media/google.7645ae62.svg",revision:"7645ae62"},{url:"/_next/static/media/graduationHat.2baee5c1.svg",revision:"2baee5c1"},{url:"/_next/static/media/grid.9bbbc935.svg",revision:"9bbbc935"},{url:"/_next/static/media/highlight-dark.86cc2cbe.svg",revision:"86cc2cbe"},{url:"/_next/static/media/highlight.231803b1.svg",revision:"231803b1"},{url:"/_next/static/media/html.6b956ddd.svg",revision:"6b956ddd"},{url:"/_next/static/media/html.bff3af4b.svg",revision:"bff3af4b"},{url:"/_next/static/media/iframe-option.41805f40.svg",revision:"41805f40"},{url:"/_next/static/media/jina.525d376e.png",revision:"525d376e"},{url:"/_next/static/media/json.1ab407af.svg",revision:"1ab407af"},{url:"/_next/static/media/json.5ad12020.svg",revision:"5ad12020"},{url:"/_next/static/media/md.6486841c.svg",revision:"6486841c"},{url:"/_next/static/media/md.f85dd8b0.svg",revision:"f85dd8b0"},{url:"/_next/static/media/messageTextCircle.24db2aef.svg",revision:"24db2aef"},{url:"/_next/static/media/note-mod.334e50fd.svg",revision:"f746e0565df49a8eadc4cea12280733d"},{url:"/_next/static/media/notion.afdb6b11.svg",revision:"afdb6b11"},{url:"/_next/static/media/notion.e316d36c.svg",revision:"e316d36c"},{url:"/_next/static/media/option-card-effect-orange.fcb3bda2.svg",revision:"cc54f7162f90a9198f107143286aae13"},{url:"/_next/static/media/option-card-effect-purple.1dbb53f5.svg",revision:"1cd4afee70e7fabf69f09aa1a8de1c3f"},{url:"/_next/static/media/pattern-recognition-mod.f283dd95.svg",revision:"51fc8910ff44f3a59a086815fbf26db0"},{url:"/_next/static/media/pause.beff025a.svg",revision:"beff025a"},{url:"/_next/static/media/pdf.298460a5.svg",revision:"298460a5"},{url:"/_next/static/media/pdf.49702006.svg",revision:"49702006"},{url:"/_next/static/media/piggy-bank-mod.1beae759.svg",revision:"1beae759"},{url:"/_next/static/media/piggy-bank-mod.1beae759.svg",revision:"728fc8d7ea59e954765e40a4a2d2f0c6"},{url:"/_next/static/media/play.0ad13b6e.svg",revision:"0ad13b6e"},{url:"/_next/static/media/plugin.718fc7fe.svg",revision:"718fc7fe"},{url:"/_next/static/media/progress-indicator.8ff709be.svg",revision:"a6315d09605666b1f6720172b58a3a0c"},{url:"/_next/static/media/refresh-hover.c2bcec46.svg",revision:"c2bcec46"},{url:"/_next/static/media/refresh.f64f5df9.svg",revision:"f64f5df9"},{url:"/_next/static/media/rerank.6cbde0af.svg",revision:"939d3cb8eab6545bb005c66ab693c33b"},{url:"/_next/static/media/research-mod.286ce029.svg",revision:"9aa84f591c106979aa698a7a73567f54"},{url:"/_next/static/media/scripts-option.ef16020c.svg",revision:"ef16020c"},{url:"/_next/static/media/selection-mod.e28687c9.svg",revision:"d7774b2c255ecd9d1789426a22a37322"},{url:"/_next/static/media/setting-gear-mod.eb788cca.svg",revision:"46346b10978e03bb11cce585585398de"},{url:"/_next/static/media/sliders-02.b8d6ae6d.svg",revision:"b8d6ae6d"},{url:"/_next/static/media/star-07.a14990cc.svg",revision:"a14990cc"},{url:"/_next/static/media/svg.85d3fb3b.svg",revision:"85d3fb3b"},{url:"/_next/static/media/svged.195f7ae0.svg",revision:"195f7ae0"},{url:"/_next/static/media/target.1691a8e3.svg",revision:"1691a8e3"},{url:"/_next/static/media/trash-gray.6d5549c8.svg",revision:"6d5549c8"},{url:"/_next/static/media/trash-red.9c6112f1.svg",revision:"9c6112f1"},{url:"/_next/static/media/txt.4652b1ff.svg",revision:"4652b1ff"},{url:"/_next/static/media/txt.bbb9f1f0.svg",revision:"bbb9f1f0"},{url:"/_next/static/media/typeSquare.a01ce0c0.svg",revision:"a01ce0c0"},{url:"/_next/static/media/watercrawl.456df4c6.svg",revision:"456df4c6"},{url:"/_next/static/media/web.4fdc057a.svg",revision:"4fdc057a"},{url:"/_next/static/media/xlsx.3d8439ac.svg",revision:"3d8439ac"},{url:"/_next/static/media/zap-fast.eb282fc3.svg",revision:"eb282fc3"},{url:"/_offline.html",revision:"6df1c7be2399be47e9107957824b2f33"},{url:"/apple-touch-icon.png",revision:"3072cb473be6bd67e10f39b9887b4998"},{url:"/browserconfig.xml",revision:"7cb0a4f14fbbe75ef7c316298c2ea0b4"},{url:"/education/bg.png",revision:"32ac1b738d76379629bce73e65b15a4b"},{url:"/embed.js",revision:"fdee1d8a73c7eb20d58abf3971896f45"},{url:"/embed.min.js",revision:"62c34d441b1a461b97003be49583a59a"},{url:"/favicon.ico",revision:"b5466696d7e24bbee4680c08eeee73bd"},{url:"/icon-128x128.png",revision:"f2eacd031928ba49cb2c183a6039ff1b"},{url:"/icon-144x144.png",revision:"88052943fa82639bdb84102e7e0800aa"},{url:"/icon-152x152.png",revision:"e294d2c6d58f05b81b0eb2c349bc934f"},{url:"/icon-192x192.png",revision:"4a4abb74428197748404327094840bd7"},{url:"/icon-256x256.png",revision:"9a7187eee4e6d391785789c68d7e92e4"},{url:"/icon-384x384.png",revision:"56a2a569512088757ffb7b416c060832"},{url:"/icon-512x512.png",revision:"ae467f17a361d9a357361710cff58bb0"},{url:"/icon-72x72.png",revision:"01694236efb16addfd161c62f6ccd580"},{url:"/icon-96x96.png",revision:"1c262f1a4b819cfde8532904f5ad3631"},{url:"/logo/logo-embedded-chat-avatar.png",revision:"62e2a1ebdceb29ec980114742acdfab4"},{url:"/logo/logo-embedded-chat-header.png",revision:"dce0c40a62aeeadf11646796bb55fcc7"},{url:"/logo/logo-embedded-chat-header@2x.png",revision:"2d9b8ec2b68f104f112caa257db1ab10"},{url:"/logo/logo-embedded-chat-header@3x.png",revision:"2f0fffb8b5d688b46f5d69f5d41806f5"},{url:"/logo/logo-monochrome-white.svg",revision:"05dc7d4393da987f847d00ba4defc848"},{url:"/logo/logo-site-dark.png",revision:"61d930e6f60033a1b498bfaf55a186fe"},{url:"/logo/logo-site.png",revision:"348d7284d2a42844141fbf5f6e659241"},{url:"/logo/logo.svg",revision:"267ddced6a09348ccb2de8b67c4f5725"},{url:"/manifest.json",revision:"768f3123c15976a16031d62ba7f61a53"},{url:"/pdf.worker.min.mjs",revision:"6f73268496ec32ad4ec3472d5c1fddda"},{url:"/screenshots/dark/Agent.png",revision:"5da5f2211edbbc8c2b9c2d4c3e9bc414"},{url:"/screenshots/dark/Agent@2x.png",revision:"ef332b42e738ae8e7b0a293e223c58ef"},{url:"/screenshots/dark/Agent@3x.png",revision:"ffde1f8557081a6ad94e37adc9f6dd7e"},{url:"/screenshots/dark/Chatbot.png",revision:"bd32412a6ac3dbf7ed6ca61f0d403b6d"},{url:"/screenshots/dark/Chatbot@2x.png",revision:"aacbf6db8ae7902b71ebe04cb7e2bea7"},{url:"/screenshots/dark/Chatbot@3x.png",revision:"43ce7150b9a210bd010e349a52a5d63a"},{url:"/screenshots/dark/Chatflow.png",revision:"08c53a166fd3891ec691b2c779c35301"},{url:"/screenshots/dark/Chatflow@2x.png",revision:"4228de158176f24b515d624da4ca21f8"},{url:"/screenshots/dark/Chatflow@3x.png",revision:"32104899a0200f3632c90abd7a35320b"},{url:"/screenshots/dark/TextGenerator.png",revision:"4dab6e79409d0557c1bb6a143d75f623"},{url:"/screenshots/dark/TextGenerator@2x.png",revision:"20390a8e234085463f6a74c30826ec52"},{url:"/screenshots/dark/TextGenerator@3x.png",revision:"b39464faa1f11ee2d21252f45202ec82"},{url:"/screenshots/dark/Workflow.png",revision:"ac5348d7f952f489604c5c11dffb0073"},{url:"/screenshots/dark/Workflow@2x.png",revision:"3c411a2ddfdeefe23476bead99e3ada4"},{url:"/screenshots/dark/Workflow@3x.png",revision:"e4bc999a1b1b484bb3c6399a10718eda"},{url:"/screenshots/light/Agent.png",revision:"1447432ae0123183d1249fc826807283"},{url:"/screenshots/light/Agent@2x.png",revision:"6e69ff8a74806a1e634d39e37e5d6496"},{url:"/screenshots/light/Agent@3x.png",revision:"a5c637f3783335979b25c164817c7184"},{url:"/screenshots/light/Chatbot.png",revision:"5b885663241183c1b88def19719e45f8"},{url:"/screenshots/light/Chatbot@2x.png",revision:"68ff5a5268fe868fd27f83d4e68870b1"},{url:"/screenshots/light/Chatbot@3x.png",revision:"7b6e521f10da72436118b7c01419bd95"},{url:"/screenshots/light/Chatflow.png",revision:"207558c2355340cb62cef3a6183f3724"},{url:"/screenshots/light/Chatflow@2x.png",revision:"2c18cb0aef5639e294d2330b4d4ee660"},{url:"/screenshots/light/Chatflow@3x.png",revision:"a559c04589e29b9dd6b51c81767bcec5"},{url:"/screenshots/light/TextGenerator.png",revision:"1d2cefd9027087f53f8cca8123bee0cd"},{url:"/screenshots/light/TextGenerator@2x.png",revision:"0afbc4b63ef7dc8451f6dcee99c44262"},{url:"/screenshots/light/TextGenerator@3x.png",revision:"660989be44dad56e58037b71bb2feafb"},{url:"/screenshots/light/Workflow.png",revision:"18be4d29f727077f7a80d1b25d22560d"},{url:"/screenshots/light/Workflow@2x.png",revision:"db8a0b1c4672cc4347704dbe7f67a7a2"},{url:"/screenshots/light/Workflow@3x.png",revision:"d75275fb75f6fa84dee5b78406a9937c"},{url:"/vs/base/browser/ui/codicons/codicon/codicon.ttf",revision:"8129e5752396eec0a208afb9808b69cb"},{url:"/vs/base/common/worker/simpleWorker.nls.de.js",revision:"b3ec29f1182621a9934e1ce2466c8b1f"},{url:"/vs/base/common/worker/simpleWorker.nls.es.js",revision:"97f25620a0a2ed3de79912277e71a141"},{url:"/vs/base/common/worker/simpleWorker.nls.fr.js",revision:"9dd88bf169e7c3ef490f52c6bc64ef79"},{url:"/vs/base/common/worker/simpleWorker.nls.it.js",revision:"8998ee8cdf1ca43c62398c0773f4d674"},{url:"/vs/base/common/worker/simpleWorker.nls.ja.js",revision:"e51053e004aaf43aa76cc0daeb7cd131"},{url:"/vs/base/common/worker/simpleWorker.nls.js",revision:"25dea293cfe1fec511a5c25d080f6510"},{url:"/vs/base/common/worker/simpleWorker.nls.ko.js",revision:"da364f5232b4f9a37f263d0fd2e21f5d"},{url:"/vs/base/common/worker/simpleWorker.nls.ru.js",revision:"12ca132c03dc99b151e310a0952c0af9"},{url:"/vs/base/common/worker/simpleWorker.nls.zh-cn.js",revision:"5371c3a354cde1e243466d0df74f00c6"},{url:"/vs/base/common/worker/simpleWorker.nls.zh-tw.js",revision:"fa92caa9cd0f92c2a95a4b4f2bcd4f3e"},{url:"/vs/base/worker/workerMain.js",revision:"f073495e58023ac8a897447245d13f0a"},{url:"/vs/basic-languages/abap/abap.js",revision:"53667015b71bc7e1cc31b4ffaa0c8203"},{url:"/vs/basic-languages/apex/apex.js",revision:"5b8ed50a1be53dd8f0f7356b7717410b"},{url:"/vs/basic-languages/azcli/azcli.js",revision:"f0d77b00897645b1a4bb05137efe1052"},{url:"/vs/basic-languages/bat/bat.js",revision:"d92d6be90fcb052bde96c475e4c420ec"},{url:"/vs/basic-languages/bicep/bicep.js",revision:"e324e4eb8053b19a0d6b4c99cd09577f"},{url:"/vs/basic-languages/cameligo/cameligo.js",revision:"7aa6bf7f273684303a71472f65dd3fb4"},{url:"/vs/basic-languages/clojure/clojure.js",revision:"6de8d7906b075cc308569dd5c702b0d7"},{url:"/vs/basic-languages/coffee/coffee.js",revision:"81892a0a475e95990d2698dd2a94b20a"},{url:"/vs/basic-languages/cpp/cpp.js",revision:"07af5fc22ff07c515666f9cd32945236"},{url:"/vs/basic-languages/csharp/csharp.js",revision:"d1d07ab0729d06302c788bcfe56cf4fe"},{url:"/vs/basic-languages/csp/csp.js",revision:"7ce13b6a9d2a1934760d697db785a585"},{url:"/vs/basic-languages/css/css.js",revision:"49e243e85ff343fd19fe00aa699b0af2"},{url:"/vs/basic-languages/cypher/cypher.js",revision:"3344ccd0aceac0e6526f22c890d2f75f"},{url:"/vs/basic-languages/dart/dart.js",revision:"92ded6175557e666e245e6b7d8bdeb6a"},{url:"/vs/basic-languages/dockerfile/dockerfile.js",revision:"a5a8892976102830aad437b507f845f1"},{url:"/vs/basic-languages/ecl/ecl.js",revision:"c25aa69e7d0832492d4e893d67226f93"},{url:"/vs/basic-languages/elixir/elixir.js",revision:"b9d3838d1e23e04fa11148c922f0273f"},{url:"/vs/basic-languages/flow9/flow9.js",revision:"b38c4587b04f24bffe625d67b7d2a454"},{url:"/vs/basic-languages/freemarker2/freemarker2.js",revision:"82923f6e9d66d8a36e67bfa314217268"},{url:"/vs/basic-languages/fsharp/fsharp.js",revision:"122f69422bc6d50df1720d9051d51efb"},{url:"/vs/basic-languages/go/go.js",revision:"4b555a32b18cea6aeeb9a21eedf0093b"},{url:"/vs/basic-languages/graphql/graphql.js",revision:"5e46b51d0347d90b7058381452a6b7fa"},{url:"/vs/basic-languages/handlebars/handlebars.js",revision:"e9ab0b3d29d3ac7afe0050138a73e926"},{url:"/vs/basic-languages/hcl/hcl.js",revision:"5b25c2e4fd4bb527d12c5da4a7376dbf"},{url:"/vs/basic-languages/html/html.js",revision:"ea22ddb1e9a2047699a3943d3f09c7cb"},{url:"/vs/basic-languages/ini/ini.js",revision:"6e14fd0bf0b9cfc60516b35d8ad90380"},{url:"/vs/basic-languages/java/java.js",revision:"3bee5d21d7f94f08f52250ae69c85a99"},{url:"/vs/basic-languages/javascript/javascript.js",revision:"5671f443a99492d6405b9ddbad7273af"},{url:"/vs/basic-languages/julia/julia.js",revision:"0e7229b7256a1fe0d495bfa048a2792d"},{url:"/vs/basic-languages/kotlin/kotlin.js",revision:"2579e51fc2ac0d8ea14339b3a42bbee1"},{url:"/vs/basic-languages/less/less.js",revision:"57d9acf121144aa07080c1551409d7e4"},{url:"/vs/basic-languages/lexon/lexon.js",revision:"dfb01cfcebb9bdda2d9ded19b78a112b"},{url:"/vs/basic-languages/liquid/liquid.js",revision:"22511ef12ef1c36f6e19e42ff920c92d"},{url:"/vs/basic-languages/lua/lua.js",revision:"04513cbe8568d0fe216b267a51fa8d92"},{url:"/vs/basic-languages/m3/m3.js",revision:"1bc2d1b3d59968cd60b1962c3e2ae4ec"},{url:"/vs/basic-languages/markdown/markdown.js",revision:"176204c5e3760d4d9d24f44a48821aed"},{url:"/vs/basic-languages/mdx/mdx.js",revision:"bb784b1621e2f2b7b0954351378840bc"},{url:"/vs/basic-languages/mips/mips.js",revision:"8df1b7666059092a0d622f57d611b0d6"},{url:"/vs/basic-languages/msdax/msdax.js",revision:"475a8cf2a1facf13ed7f1336289b7d62"},{url:"/vs/basic-languages/mysql/mysql.js",revision:"3d58bde2509af02384cfeb2a0ff11c9b"},{url:"/vs/basic-languages/objective-c/objective-c.js",revision:"09225247de0b7b4a5d1e39714eb383d9"},{url:"/vs/basic-languages/pascal/pascal.js",revision:"6dcd01139ec53b3eff56e31eac66b571"},{url:"/vs/basic-languages/pascaligo/pascaligo.js",revision:"4a01ddf6d56ea8d9b264e3feec74b998"},{url:"/vs/basic-languages/perl/perl.js",revision:"89f017f79e145d9313e8496202ab3c6c"},{url:"/vs/basic-languages/pgsql/pgsql.js",revision:"aba2c11fdf841f79deafbacc74d9b62b"},{url:"/vs/basic-languages/php/php.js",revision:"817ecc6a30b373ac4231a116932eed0e"},{url:"/vs/basic-languages/pla/pla.js",revision:"b0142ba41843ccb1d2f769495f39d479"},{url:"/vs/basic-languages/postiats/postiats.js",revision:"5de9b76b02e64cb8166f67b508344ab8"},{url:"/vs/basic-languages/powerquery/powerquery.js",revision:"278f5ebfe9e9a1bd316e71196c0ee33a"},{url:"/vs/basic-languages/powershell/powershell.js",revision:"27496ecc3565d3a85a3c2de19b059074"},{url:"/vs/basic-languages/protobuf/protobuf.js",revision:"374f802aefc150c1b7331146334e5e9c"},{url:"/vs/basic-languages/pug/pug.js",revision:"e8bb2ec6f1eac7e9340600acaef0bfc9"},{url:"/vs/basic-languages/python/python.js",revision:"bf6d8f14254586a9be67de999585a611"},{url:"/vs/basic-languages/qsharp/qsharp.js",revision:"1f1905da654e04423d922792e2bf96f9"},{url:"/vs/basic-languages/r/r.js",revision:"811be171ae696de48d5cf1460339bcd3"},{url:"/vs/basic-languages/razor/razor.js",revision:"45ce4627e0e51c8d35d1832b98b44f70"},{url:"/vs/basic-languages/redis/redis.js",revision:"1388147a532cb0c270f746f626d18257"},{url:"/vs/basic-languages/redshift/redshift.js",revision:"f577d72fb1c392d60231067323973429"},{url:"/vs/basic-languages/restructuredtext/restructuredtext.js",revision:"e5db13b472ea650c6b4449e29c2ab9c2"},{url:"/vs/basic-languages/ruby/ruby.js",revision:"846f0e6866dd7dd2e4b3f400c0f02cbe"},{url:"/vs/basic-languages/rust/rust.js",revision:"9ccf47397fb3da550d956a0d1f5171cc"},{url:"/vs/basic-languages/sb/sb.js",revision:"6b58eb47ee5b22b9a57986ecfcae39b5"},{url:"/vs/basic-languages/scala/scala.js",revision:"85716f12c7d0e9adad94838b985f16f9"},{url:"/vs/basic-languages/scheme/scheme.js",revision:"17b27762dce5ef5f4a5e4ee187588a97"},{url:"/vs/basic-languages/scss/scss.js",revision:"13ce232403a3d3e295d34755bf25389d"},{url:"/vs/basic-languages/shell/shell.js",revision:"568c42ff434da53e87202c71d114f3f5"},{url:"/vs/basic-languages/solidity/solidity.js",revision:"a6ee03c1a0fefb48e60ddf634820d23b"},{url:"/vs/basic-languages/sophia/sophia.js",revision:"899110a22cd9a291f19239f023033ae4"},{url:"/vs/basic-languages/sparql/sparql.js",revision:"f680e2f2f063ed36f75ee0398623dad6"},{url:"/vs/basic-languages/sql/sql.js",revision:"cbec458977358549fb3db9a36446dec9"},{url:"/vs/basic-languages/st/st.js",revision:"50c146e353e088645a341daf0e1dc5d3"},{url:"/vs/basic-languages/swift/swift.js",revision:"1d67edfc9a58775eaf70ff942a87da57"},{url:"/vs/basic-languages/systemverilog/systemverilog.js",revision:"f87daab3f7be73baa7d044af6e017e94"},{url:"/vs/basic-languages/tcl/tcl.js",revision:"a8187a8f37d73d8f95ec64dde66f185f"},{url:"/vs/basic-languages/twig/twig.js",revision:"05910657d2a031c6fdb12bbdfdc16b2a"},{url:"/vs/basic-languages/typescript/typescript.js",revision:"6edb28e3121d7d222150c7535350b93c"},{url:"/vs/basic-languages/vb/vb.js",revision:"b0be2782e785f6e2c74a1e6db72fb1f1"},{url:"/vs/basic-languages/wgsl/wgsl.js",revision:"691180550221d086b9989621fca9492d"},{url:"/vs/basic-languages/xml/xml.js",revision:"8a164d9767c96cbadb59f41520039553"},{url:"/vs/basic-languages/yaml/yaml.js",revision:"3024c6bd6032b778f73f820c9bee5e28"},{url:"/vs/editor/editor.main.css",revision:"11461cfb08c709aef66244a33106a130"},{url:"/vs/editor/editor.main.js",revision:"21dbd6e0be055e4116c09f6018523b65"},{url:"/vs/editor/editor.main.nls.de.js",revision:"127b360e1c3a616495c1570e5136053a"},{url:"/vs/editor/editor.main.nls.es.js",revision:"6d539ad100283a6f35379a58699fe46a"},{url:"/vs/editor/editor.main.nls.fr.js",revision:"99e68d4d1632ed0716b74de72d45880d"},{url:"/vs/editor/editor.main.nls.it.js",revision:"359690e951c23250e3310f63d7032b04"},{url:"/vs/editor/editor.main.nls.ja.js",revision:"60e044eb568e7cb249397b637ab9f891"},{url:"/vs/editor/editor.main.nls.js",revision:"a3f0617e2d240c5cdd0c44ca2082f807"},{url:"/vs/editor/editor.main.nls.ko.js",revision:"33207d8a31f33215607ade7319119d0c"},{url:"/vs/editor/editor.main.nls.ru.js",revision:"da941bc486519fcd2386f12008e178ca"},{url:"/vs/editor/editor.main.nls.zh-cn.js",revision:"90e1bc4905e86a08892cb993e96ff6aa"},{url:"/vs/editor/editor.main.nls.zh-tw.js",revision:"84ba8853d6dd2b37291a387bbeab5516"},{url:"/vs/language/css/cssMode.js",revision:"23f8482fdf45d208bcc9443c808c08a3"},{url:"/vs/language/css/cssWorker.js",revision:"8482bf05374fb6424a3d0e97d49d5972"},{url:"/vs/language/html/htmlMode.js",revision:"a90c26dcf5fa3381c84a9c6681de1e4f"},{url:"/vs/language/html/htmlWorker.js",revision:"43feb5119cecd63ba161aa8ffd5c0ad1"},{url:"/vs/language/json/jsonMode.js",revision:"e3dfed3331d8aaf4e0299579ca85cc0b"},{url:"/vs/language/json/jsonWorker.js",revision:"d636995b5e79d5e9e309b4642778a79d"},{url:"/vs/language/typescript/tsMode.js",revision:"b900fea27f62814e9145a796bf69721a"},{url:"/vs/language/typescript/tsWorker.js",revision:"9010f97362a2bb0bfb1d89989985ff0e"},{url:"/vs/loader.js",revision:"96db6297a4335a6ef4d698f5c191cc85"}],{ignoreURLParametersMatching:[]}),e.cleanupOutdatedCaches(),e.registerRoute("/",new e.NetworkFirst({cacheName:"start-url",plugins:[{cacheWillUpdate:async({request:e,response:s,event:a,state:c})=>s&&"opaqueredirect"===s.type?new Response(s.body,{status:200,statusText:"OK",headers:s.headers}):s},{handlerDidError:async({request:e})=>self.fallback(e)}]}),"GET"),e.registerRoute(/^https:\/\/fonts\.googleapis\.com\/.*/i,new e.CacheFirst({cacheName:"google-fonts",plugins:[new e.ExpirationPlugin({maxEntries:4,maxAgeSeconds:31536e3}),{handlerDidError:async({request:e})=>self.fallback(e)}]}),"GET"),e.registerRoute(/^https:\/\/fonts\.gstatic\.com\/.*/i,new e.CacheFirst({cacheName:"google-fonts-webfonts",plugins:[new e.ExpirationPlugin({maxEntries:4,maxAgeSeconds:31536e3}),{handlerDidError:async({request:e})=>self.fallback(e)}]}),"GET"),e.registerRoute(/\.(?:png|jpg|jpeg|svg|gif|webp|avif)$/i,new e.CacheFirst({cacheName:"images",plugins:[new e.ExpirationPlugin({maxEntries:64,maxAgeSeconds:2592e3}),{handlerDidError:async({request:e})=>self.fallback(e)}]}),"GET"),e.registerRoute(/\.(?:js|css)$/i,new e.StaleWhileRevalidate({cacheName:"static-resources",plugins:[new e.ExpirationPlugin({maxEntries:32,maxAgeSeconds:86400}),{handlerDidError:async({request:e})=>self.fallback(e)}]}),"GET"),e.registerRoute(/^\/api\/.*/i,new e.NetworkFirst({cacheName:"api-cache",networkTimeoutSeconds:10,plugins:[new e.ExpirationPlugin({maxEntries:16,maxAgeSeconds:3600}),{handlerDidError:async({request:e})=>self.fallback(e)}]}),"GET")}); From b623224d07ccfc64c30febd42b951484bb885cd7 Mon Sep 17 00:00:00 2001 From: lyzno1 <92089059+lyzno1@users.noreply.github.com> Date: Sun, 7 Sep 2025 21:31:05 +0800 Subject: [PATCH 39/52] fix: remove workflow file preview docs (#25318) --- .../develop/template/template_workflow.en.mdx | 78 ------------------- .../develop/template/template_workflow.ja.mdx | 78 ------------------- .../develop/template/template_workflow.zh.mdx | 77 ------------------ 3 files changed, 233 deletions(-) diff --git a/web/app/components/develop/template/template_workflow.en.mdx b/web/app/components/develop/template/template_workflow.en.mdx index 00e6189cb1..f286773685 100644 --- a/web/app/components/develop/template/template_workflow.en.mdx +++ b/web/app/components/develop/template/template_workflow.en.mdx @@ -740,84 +740,6 @@ Workflow applications offers non-session support and is ideal for translation, a --- - - - - Preview or download uploaded files. This endpoint allows you to access files that have been previously uploaded via the File Upload API. - - Files can only be accessed if they belong to messages within the requesting application. - - ### Path Parameters - - `file_id` (string) Required - The unique identifier of the file to preview, obtained from the File Upload API response. - - ### Query Parameters - - `as_attachment` (boolean) Optional - Whether to force download the file as an attachment. Default is `false` (preview in browser). - - ### Response - Returns the file content with appropriate headers for browser display or download. - - `Content-Type` Set based on file mime type - - `Content-Length` File size in bytes (if available) - - `Content-Disposition` Set to "attachment" if `as_attachment=true` - - `Cache-Control` Caching headers for performance - - `Accept-Ranges` Set to "bytes" for audio/video files - - ### Errors - - 400, `invalid_param`, abnormal parameter input - - 403, `file_access_denied`, file access denied or file does not belong to current application - - 404, `file_not_found`, file not found or has been deleted - - 500, internal server error - - - - ### Request Example - - - ### Download as Attachment - - - ### Response Headers Example - - ```http {{ title: 'Headers - Image Preview' }} - Content-Type: image/png - Content-Length: 1024 - Cache-Control: public, max-age=3600 - ``` - - - ### Download Response Headers - - ```http {{ title: 'Headers - File Download' }} - Content-Type: image/png - Content-Length: 1024 - Content-Disposition: attachment; filename*=UTF-8''example.png - Cache-Control: public, max-age=3600 - ``` - - - - ---- - - - - アップロードされたファイルをプレビューまたはダウンロードします。このエンドポイントを使用すると、以前にファイルアップロード API でアップロードされたファイルにアクセスできます。 - - ファイルは、リクエストしているアプリケーションのメッセージ範囲内にある場合のみアクセス可能です。 - - ### パスパラメータ - - `file_id` (string) 必須 - プレビューするファイルの一意識別子。ファイルアップロード API レスポンスから取得します。 - - ### クエリパラメータ - - `as_attachment` (boolean) オプション - ファイルを添付ファイルとして強制ダウンロードするかどうか。デフォルトは `false`(ブラウザでプレビュー)。 - - ### レスポンス - ブラウザ表示またはダウンロード用の適切なヘッダー付きでファイル内容を返します。 - - `Content-Type` ファイル MIME タイプに基づいて設定 - - `Content-Length` ファイルサイズ(バイト、利用可能な場合) - - `Content-Disposition` `as_attachment=true` の場合は "attachment" に設定 - - `Cache-Control` パフォーマンス向上のためのキャッシュヘッダー - - `Accept-Ranges` 音声/動画ファイルの場合は "bytes" に設定 - - ### エラー - - 400, `invalid_param`, パラメータ入力異常 - - 403, `file_access_denied`, ファイルアクセス拒否またはファイルが現在のアプリケーションに属していません - - 404, `file_not_found`, ファイルが見つからないか削除されています - - 500, サーバー内部エラー - - - - ### リクエスト例 - - - ### 添付ファイルとしてダウンロード - - - ### レスポンスヘッダー例 - - ```http {{ title: 'ヘッダー - 画像プレビュー' }} - Content-Type: image/png - Content-Length: 1024 - Cache-Control: public, max-age=3600 - ``` - - - ### ダウンロードレスポンスヘッダー - - ```http {{ title: 'ヘッダー - ファイルダウンロード' }} - Content-Type: image/png - Content-Length: 1024 - Content-Disposition: attachment; filename*=UTF-8''example.png - Cache-Control: public, max-age=3600 - ``` - - - - ---- - --- - - - - 预览或下载已上传的文件。此端点允许您访问先前通过文件上传 API 上传的文件。 - - 文件只能在属于请求应用程序的消息范围内访问。 - - ### 路径参数 - - `file_id` (string) 必需 - 要预览的文件的唯一标识符,从文件上传 API 响应中获得。 - - ### 查询参数 - - `as_attachment` (boolean) 可选 - 是否强制将文件作为附件下载。默认为 `false`(在浏览器中预览)。 - - ### 响应 - 返回带有适当浏览器显示或下载标头的文件内容。 - - `Content-Type` 根据文件 MIME 类型设置 - - `Content-Length` 文件大小(以字节为单位,如果可用) - - `Content-Disposition` 如果 `as_attachment=true` 则设置为 "attachment" - - `Cache-Control` 用于性能的缓存标头 - - `Accept-Ranges` 对于音频/视频文件设置为 "bytes" - - ### 错误 - - 400, `invalid_param`, 参数输入异常 - - 403, `file_access_denied`, 文件访问被拒绝或文件不属于当前应用程序 - - 404, `file_not_found`, 文件未找到或已被删除 - - 500, 服务内部错误 - - - - ### 请求示例 - - - ### 作为附件下载 - - - ### 响应标头示例 - - ```http {{ title: 'Headers - 图片预览' }} - Content-Type: image/png - Content-Length: 1024 - Cache-Control: public, max-age=3600 - ``` - - - ### 文件下载响应标头 - - ```http {{ title: 'Headers - 文件下载' }} - Content-Type: image/png - Content-Length: 1024 - Content-Disposition: attachment; filename*=UTF-8''example.png - Cache-Control: public, max-age=3600 - ``` - - - ---- - Date: Sun, 7 Sep 2025 21:31:41 +0800 Subject: [PATCH 40/52] fix: update iteration node to use correct variable segment types (#25315) --- api/core/workflow/nodes/iteration/iteration_node.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/api/core/workflow/nodes/iteration/iteration_node.py b/api/core/workflow/nodes/iteration/iteration_node.py index 9037677df9..52eb7fdd75 100644 --- a/api/core/workflow/nodes/iteration/iteration_node.py +++ b/api/core/workflow/nodes/iteration/iteration_node.py @@ -11,7 +11,7 @@ from typing import TYPE_CHECKING, Any, Optional, cast from flask import Flask, current_app from configs import dify_config -from core.variables import ArrayVariable, IntegerVariable, NoneVariable +from core.variables import IntegerVariable, NoneSegment from core.variables.segments import ArrayAnySegment, ArraySegment from core.workflow.entities.node_entities import ( NodeRunResult, @@ -112,10 +112,10 @@ class IterationNode(BaseNode): if not variable: raise IteratorVariableNotFoundError(f"iterator variable {self._node_data.iterator_selector} not found") - if not isinstance(variable, ArrayVariable) and not isinstance(variable, NoneVariable): + if not isinstance(variable, ArraySegment) and not isinstance(variable, NoneSegment): raise InvalidIteratorValueError(f"invalid iterator value: {variable}, please provide a list.") - if isinstance(variable, NoneVariable) or len(variable.value) == 0: + if isinstance(variable, NoneSegment) or len(variable.value) == 0: # Try our best to preserve the type informat. if isinstance(variable, ArraySegment): output = variable.model_copy(update={"value": []}) From beaa8de6481c7d7d7e0f58d2d3db8879e05e22cb Mon Sep 17 00:00:00 2001 From: Yongtao Huang Date: Mon, 8 Sep 2025 09:34:04 +0800 Subject: [PATCH 41/52] Fix: correct queryKey in useBatchUpdateDocMetadata and add test case (#25327) --- web/service/knowledge/use-metadata.spec.tsx | 84 +++++++++++++++++++++ web/service/knowledge/use-metadata.ts | 2 +- 2 files changed, 85 insertions(+), 1 deletion(-) create mode 100644 web/service/knowledge/use-metadata.spec.tsx diff --git a/web/service/knowledge/use-metadata.spec.tsx b/web/service/knowledge/use-metadata.spec.tsx new file mode 100644 index 0000000000..3a11da726c --- /dev/null +++ b/web/service/knowledge/use-metadata.spec.tsx @@ -0,0 +1,84 @@ +import { DataType } from '@/app/components/datasets/metadata/types' +import { act, renderHook } from '@testing-library/react' +import { QueryClient, QueryClientProvider } from '@tanstack/react-query' +import { useBatchUpdateDocMetadata } from '@/service/knowledge/use-metadata' +import { useDocumentListKey } from './use-document' + +// Mock the post function to avoid real network requests +jest.mock('@/service/base', () => ({ + post: jest.fn().mockResolvedValue({ success: true }), +})) + +const NAME_SPACE = 'dataset-metadata' + +describe('useBatchUpdateDocMetadata', () => { + let queryClient: QueryClient + + beforeEach(() => { + // Create a fresh QueryClient before each test + queryClient = new QueryClient() + }) + + // Wrapper for React Query context + const wrapper = ({ children }: { children: React.ReactNode }) => ( + {children} + ) + + it('should correctly invalidate dataset and document caches', async () => { + const { result } = renderHook(() => useBatchUpdateDocMetadata(), { wrapper }) + + // Spy on queryClient.invalidateQueries + const invalidateSpy = jest.spyOn(queryClient, 'invalidateQueries') + + // Correct payload type: each document has its own metadata_list array + + const payload = { + dataset_id: 'dataset-1', + metadata_list: [ + { + document_id: 'doc-1', + metadata_list: [ + { key: 'title-1', id: '01', name: 'name-1', type: DataType.string, value: 'new title 01' }, + ], + }, + { + document_id: 'doc-2', + metadata_list: [ + { key: 'title-2', id: '02', name: 'name-1', type: DataType.string, value: 'new title 02' }, + ], + }, + ], + } + + // Execute the mutation + await act(async () => { + await result.current.mutateAsync(payload) + }) + + // Expect invalidateQueries to have been called exactly 5 times + expect(invalidateSpy).toHaveBeenCalledTimes(5) + + // Dataset cache invalidation + expect(invalidateSpy).toHaveBeenNthCalledWith(1, { + queryKey: [NAME_SPACE, 'dataset', 'dataset-1'], + }) + + // Document list cache invalidation + expect(invalidateSpy).toHaveBeenNthCalledWith(2, { + queryKey: [NAME_SPACE, 'document', 'dataset-1'], + }) + + // useDocumentListKey cache invalidation + expect(invalidateSpy).toHaveBeenNthCalledWith(3, { + queryKey: [...useDocumentListKey, 'dataset-1'], + }) + + // Single document cache invalidation + expect(invalidateSpy.mock.calls.slice(3)).toEqual( + expect.arrayContaining([ + [{ queryKey: [NAME_SPACE, 'document', 'dataset-1', 'doc-1'] }], + [{ queryKey: [NAME_SPACE, 'document', 'dataset-1', 'doc-2'] }], + ]), + ) + }) +}) diff --git a/web/service/knowledge/use-metadata.ts b/web/service/knowledge/use-metadata.ts index 5e9186f539..eb85142d9f 100644 --- a/web/service/knowledge/use-metadata.ts +++ b/web/service/knowledge/use-metadata.ts @@ -119,7 +119,7 @@ export const useBatchUpdateDocMetadata = () => { }) // meta data in document list await queryClient.invalidateQueries({ - queryKey: [NAME_SPACE, 'dataset', payload.dataset_id], + queryKey: [NAME_SPACE, 'document', payload.dataset_id], }) await queryClient.invalidateQueries({ queryKey: [...useDocumentListKey, payload.dataset_id], From e1f871fefe8fdff558b0fd5d5aea02086027fd01 Mon Sep 17 00:00:00 2001 From: "Krito." Date: Mon, 8 Sep 2025 09:41:51 +0800 Subject: [PATCH 42/52] fix: ensure consistent DSL export behavior across UI entry (#25317) Co-authored-by: crazywoola <100913391+crazywoola@users.noreply.github.com> --- web/app/components/app-sidebar/app-info.tsx | 19 +++++++++++++++++++ web/i18n/en-US/workflow.ts | 4 ++++ web/i18n/ja-JP/workflow.ts | 4 ++++ web/i18n/zh-Hans/workflow.ts | 4 ++++ 4 files changed, 31 insertions(+) diff --git a/web/app/components/app-sidebar/app-info.tsx b/web/app/components/app-sidebar/app-info.tsx index cf55c0d68d..2037647b99 100644 --- a/web/app/components/app-sidebar/app-info.tsx +++ b/web/app/components/app-sidebar/app-info.tsx @@ -72,6 +72,7 @@ const AppInfo = ({ expand, onlyShowDetail = false, openState = false, onDetailEx const [showSwitchModal, setShowSwitchModal] = useState(false) const [showImportDSLModal, setShowImportDSLModal] = useState(false) const [secretEnvList, setSecretEnvList] = useState([]) + const [showExportWarning, setShowExportWarning] = useState(false) const onEdit: CreateAppModalProps['onConfirm'] = useCallback(async ({ name, @@ -159,6 +160,14 @@ const AppInfo = ({ expand, onlyShowDetail = false, openState = false, onDetailEx onExport() return } + + setShowExportWarning(true) + } + + const handleConfirmExport = async () => { + if (!appDetail) + return + setShowExportWarning(false) try { const workflowDraft = await fetchWorkflowDraft(`/apps/${appDetail.id}/workflows/draft`) const list = (workflowDraft.environment_variables || []).filter(env => env.value_type === 'secret') @@ -407,6 +416,16 @@ const AppInfo = ({ expand, onlyShowDetail = false, openState = false, onDetailEx onClose={() => setSecretEnvList([])} /> )} + {showExportWarning && ( + setShowExportWarning(false)} + /> + )}
) } diff --git a/web/i18n/en-US/workflow.ts b/web/i18n/en-US/workflow.ts index eae63e9c2f..5da97a7692 100644 --- a/web/i18n/en-US/workflow.ts +++ b/web/i18n/en-US/workflow.ts @@ -140,6 +140,10 @@ const translation = { export: 'Export DSL with secret values ', }, }, + sidebar: { + exportWarning: 'Export Current Saved Version', + exportWarningDesc: 'This will export the current saved version of your workflow. If you have unsaved changes in the editor, please save them first by using the export option in the workflow canvas.', + }, chatVariable: { panelTitle: 'Conversation Variables', panelDescription: 'Conversation Variables are used to store interactive information that LLM needs to remember, including conversation history, uploaded files, user preferences. They are read-write. ', diff --git a/web/i18n/ja-JP/workflow.ts b/web/i18n/ja-JP/workflow.ts index 2a3ee304f3..707a119c45 100644 --- a/web/i18n/ja-JP/workflow.ts +++ b/web/i18n/ja-JP/workflow.ts @@ -140,6 +140,10 @@ const translation = { export: 'シークレット値付きでエクスポート', }, }, + sidebar: { + exportWarning: '現在保存されているバージョンをエクスポート', + exportWarningDesc: 'これは現在保存されているワークフローのバージョンをエクスポートします。エディターで未保存の変更がある場合は、まずワークフローキャンバスのエクスポートオプションを使用して保存してください。', + }, chatVariable: { panelTitle: '会話変数', panelDescription: '対話情報を保存・管理(会話履歴/ファイル/ユーザー設定など)。書き換えができます。', diff --git a/web/i18n/zh-Hans/workflow.ts b/web/i18n/zh-Hans/workflow.ts index 4573fa7bda..60c65a080c 100644 --- a/web/i18n/zh-Hans/workflow.ts +++ b/web/i18n/zh-Hans/workflow.ts @@ -140,6 +140,10 @@ const translation = { export: '导出包含 Secret 值的 DSL', }, }, + sidebar: { + exportWarning: '导出当前已保存版本', + exportWarningDesc: '这将导出您工作流的当前已保存版本。如果您在编辑器中有未保存的更改,请先使用工作流画布中的导出选项保存它们。', + }, chatVariable: { panelTitle: '会话变量', panelDescription: '会话变量用于存储 LLM 需要的上下文信息,如用户偏好、对话历史等。它是可读写的。', From 9b8a03b53b1163ffeffc6646ad827a375b498d77 Mon Sep 17 00:00:00 2001 From: -LAN- Date: Mon, 8 Sep 2025 09:42:27 +0800 Subject: [PATCH 43/52] [Chore/Refactor] Improve type annotations in models module (#25281) Signed-off-by: -LAN- Co-authored-by: crazywoola <100913391+crazywoola@users.noreply.github.com> --- api/controllers/console/apikey.py | 2 +- .../console/datasets/datasets_document.py | 6 + api/controllers/console/explore/parameter.py | 2 + api/controllers/console/explore/workflow.py | 4 + api/core/app/apps/completion/app_generator.py | 3 + api/core/rag/extractor/notion_extractor.py | 3 +- api/core/tools/mcp_tool/provider.py | 4 +- api/core/tools/tool_manager.py | 4 +- api/models/account.py | 8 +- api/models/dataset.py | 134 +++++----- api/models/model.py | 251 +++++++++++------- api/models/provider.py | 4 +- api/models/tools.py | 24 +- api/models/types.py | 38 +-- api/models/workflow.py | 62 ++--- api/pyrightconfig.json | 1 - api/services/agent_service.py | 4 +- api/services/app_service.py | 5 +- api/services/audio_service.py | 6 +- api/services/dataset_service.py | 7 +- api/services/external_knowledge_service.py | 5 +- .../tools/mcp_tools_manage_service.py | 2 +- .../unit_tests/models/test_types_enum_text.py | 4 +- 23 files changed, 332 insertions(+), 251 deletions(-) diff --git a/api/controllers/console/apikey.py b/api/controllers/console/apikey.py index 758b574d1a..cfd5f73ade 100644 --- a/api/controllers/console/apikey.py +++ b/api/controllers/console/apikey.py @@ -87,7 +87,7 @@ class BaseApiKeyListResource(Resource): custom="max_keys_exceeded", ) - key = ApiToken.generate_api_key(self.token_prefix, 24) + key = ApiToken.generate_api_key(self.token_prefix or "", 24) api_token = ApiToken() setattr(api_token, self.resource_id_field, resource_id) api_token.tenant_id = current_user.current_tenant_id diff --git a/api/controllers/console/datasets/datasets_document.py b/api/controllers/console/datasets/datasets_document.py index f9703f5a21..c9c0b6a5ce 100644 --- a/api/controllers/console/datasets/datasets_document.py +++ b/api/controllers/console/datasets/datasets_document.py @@ -475,6 +475,8 @@ class DocumentBatchIndexingEstimateApi(DocumentResource): data_source_info = document.data_source_info_dict if document.data_source_type == "upload_file": + if not data_source_info: + continue file_id = data_source_info["upload_file_id"] file_detail = ( db.session.query(UploadFile) @@ -491,6 +493,8 @@ class DocumentBatchIndexingEstimateApi(DocumentResource): extract_settings.append(extract_setting) elif document.data_source_type == "notion_import": + if not data_source_info: + continue extract_setting = ExtractSetting( datasource_type=DatasourceType.NOTION.value, notion_info={ @@ -503,6 +507,8 @@ class DocumentBatchIndexingEstimateApi(DocumentResource): ) extract_settings.append(extract_setting) elif document.data_source_type == "website_crawl": + if not data_source_info: + continue extract_setting = ExtractSetting( datasource_type=DatasourceType.WEBSITE.value, website_info={ diff --git a/api/controllers/console/explore/parameter.py b/api/controllers/console/explore/parameter.py index c368744759..d9afb5bab2 100644 --- a/api/controllers/console/explore/parameter.py +++ b/api/controllers/console/explore/parameter.py @@ -43,6 +43,8 @@ class ExploreAppMetaApi(InstalledAppResource): def get(self, installed_app: InstalledApp): """Get app meta""" app_model = installed_app.app + if not app_model: + raise ValueError("App not found") return AppService().get_app_meta(app_model) diff --git a/api/controllers/console/explore/workflow.py b/api/controllers/console/explore/workflow.py index 0a5a88d6f5..d80bfcfabd 100644 --- a/api/controllers/console/explore/workflow.py +++ b/api/controllers/console/explore/workflow.py @@ -35,6 +35,8 @@ class InstalledAppWorkflowRunApi(InstalledAppResource): Run workflow """ app_model = installed_app.app + if not app_model: + raise NotWorkflowAppError() app_mode = AppMode.value_of(app_model.mode) if app_mode != AppMode.WORKFLOW: raise NotWorkflowAppError() @@ -73,6 +75,8 @@ class InstalledAppWorkflowTaskStopApi(InstalledAppResource): Stop workflow task """ app_model = installed_app.app + if not app_model: + raise NotWorkflowAppError() app_mode = AppMode.value_of(app_model.mode) if app_mode != AppMode.WORKFLOW: raise NotWorkflowAppError() diff --git a/api/core/app/apps/completion/app_generator.py b/api/core/app/apps/completion/app_generator.py index 6e43e5ec94..8485ce7519 100644 --- a/api/core/app/apps/completion/app_generator.py +++ b/api/core/app/apps/completion/app_generator.py @@ -262,6 +262,9 @@ class CompletionAppGenerator(MessageBasedAppGenerator): raise MessageNotExistsError() current_app_model_config = app_model.app_model_config + if not current_app_model_config: + raise MoreLikeThisDisabledError() + more_like_this = current_app_model_config.more_like_this_dict if not current_app_model_config.more_like_this or more_like_this.get("enabled", False) is False: diff --git a/api/core/rag/extractor/notion_extractor.py b/api/core/rag/extractor/notion_extractor.py index 206b2bb921..fa96d73cf2 100644 --- a/api/core/rag/extractor/notion_extractor.py +++ b/api/core/rag/extractor/notion_extractor.py @@ -334,7 +334,8 @@ class NotionExtractor(BaseExtractor): last_edited_time = self.get_notion_last_edited_time() data_source_info = document_model.data_source_info_dict - data_source_info["last_edited_time"] = last_edited_time + if data_source_info: + data_source_info["last_edited_time"] = last_edited_time db.session.query(DocumentModel).filter_by(id=document_model.id).update( {DocumentModel.data_source_info: json.dumps(data_source_info)} diff --git a/api/core/tools/mcp_tool/provider.py b/api/core/tools/mcp_tool/provider.py index fa99cccb80..dd9d3a137f 100644 --- a/api/core/tools/mcp_tool/provider.py +++ b/api/core/tools/mcp_tool/provider.py @@ -1,5 +1,5 @@ import json -from typing import Any, Optional +from typing import Any, Optional, Self from core.mcp.types import Tool as RemoteMCPTool from core.tools.__base.tool_provider import ToolProviderController @@ -48,7 +48,7 @@ class MCPToolProviderController(ToolProviderController): return ToolProviderType.MCP @classmethod - def _from_db(cls, db_provider: MCPToolProvider) -> "MCPToolProviderController": + def from_db(cls, db_provider: MCPToolProvider) -> Self: """ from db provider """ diff --git a/api/core/tools/tool_manager.py b/api/core/tools/tool_manager.py index 834f58be66..00fc57a3f1 100644 --- a/api/core/tools/tool_manager.py +++ b/api/core/tools/tool_manager.py @@ -773,7 +773,7 @@ class ToolManager: if provider is None: raise ToolProviderNotFoundError(f"mcp provider {provider_id} not found") - controller = MCPToolProviderController._from_db(provider) + controller = MCPToolProviderController.from_db(provider) return controller @@ -928,7 +928,7 @@ class ToolManager: tenant_id: str, provider_type: ToolProviderType, provider_id: str, - ) -> Union[str, dict]: + ) -> Union[str, dict[str, Any]]: """ get the tool icon diff --git a/api/models/account.py b/api/models/account.py index 4fec41c4e7..019159d2da 100644 --- a/api/models/account.py +++ b/api/models/account.py @@ -1,10 +1,10 @@ import enum import json from datetime import datetime -from typing import Optional +from typing import Any, Optional import sqlalchemy as sa -from flask_login import UserMixin +from flask_login import UserMixin # type: ignore[import-untyped] from sqlalchemy import DateTime, String, func, select from sqlalchemy.orm import Mapped, Session, mapped_column, reconstructor @@ -225,11 +225,11 @@ class Tenant(Base): ) @property - def custom_config_dict(self): + def custom_config_dict(self) -> dict[str, Any]: return json.loads(self.custom_config) if self.custom_config else {} @custom_config_dict.setter - def custom_config_dict(self, value: dict): + def custom_config_dict(self, value: dict[str, Any]) -> None: self.custom_config = json.dumps(value) diff --git a/api/models/dataset.py b/api/models/dataset.py index 1d2cb410fd..38b5c74de1 100644 --- a/api/models/dataset.py +++ b/api/models/dataset.py @@ -286,7 +286,7 @@ class DatasetProcessRule(Base): "segmentation": {"delimiter": "\n", "max_tokens": 500, "chunk_overlap": 50}, } - def to_dict(self): + def to_dict(self) -> dict[str, Any]: return { "id": self.id, "dataset_id": self.dataset_id, @@ -295,7 +295,7 @@ class DatasetProcessRule(Base): } @property - def rules_dict(self): + def rules_dict(self) -> dict[str, Any] | None: try: return json.loads(self.rules) if self.rules else None except JSONDecodeError: @@ -392,10 +392,10 @@ class Document(Base): return status @property - def data_source_info_dict(self): + def data_source_info_dict(self) -> dict[str, Any] | None: if self.data_source_info: try: - data_source_info_dict = json.loads(self.data_source_info) + data_source_info_dict: dict[str, Any] = json.loads(self.data_source_info) except JSONDecodeError: data_source_info_dict = {} @@ -403,10 +403,10 @@ class Document(Base): return None @property - def data_source_detail_dict(self): + def data_source_detail_dict(self) -> dict[str, Any]: if self.data_source_info: if self.data_source_type == "upload_file": - data_source_info_dict = json.loads(self.data_source_info) + data_source_info_dict: dict[str, Any] = json.loads(self.data_source_info) file_detail = ( db.session.query(UploadFile) .where(UploadFile.id == data_source_info_dict["upload_file_id"]) @@ -425,7 +425,8 @@ class Document(Base): } } elif self.data_source_type in {"notion_import", "website_crawl"}: - return json.loads(self.data_source_info) + result: dict[str, Any] = json.loads(self.data_source_info) + return result return {} @property @@ -471,7 +472,7 @@ class Document(Base): return self.updated_at @property - def doc_metadata_details(self): + def doc_metadata_details(self) -> list[dict[str, Any]] | None: if self.doc_metadata: document_metadatas = ( db.session.query(DatasetMetadata) @@ -481,9 +482,9 @@ class Document(Base): ) .all() ) - metadata_list = [] + metadata_list: list[dict[str, Any]] = [] for metadata in document_metadatas: - metadata_dict = { + metadata_dict: dict[str, Any] = { "id": metadata.id, "name": metadata.name, "type": metadata.type, @@ -497,13 +498,13 @@ class Document(Base): return None @property - def process_rule_dict(self): - if self.dataset_process_rule_id: + def process_rule_dict(self) -> dict[str, Any] | None: + if self.dataset_process_rule_id and self.dataset_process_rule: return self.dataset_process_rule.to_dict() return None - def get_built_in_fields(self): - built_in_fields = [] + def get_built_in_fields(self) -> list[dict[str, Any]]: + built_in_fields: list[dict[str, Any]] = [] built_in_fields.append( { "id": "built-in", @@ -546,7 +547,7 @@ class Document(Base): ) return built_in_fields - def to_dict(self): + def to_dict(self) -> dict[str, Any]: return { "id": self.id, "tenant_id": self.tenant_id, @@ -592,13 +593,13 @@ class Document(Base): "data_source_info_dict": self.data_source_info_dict, "average_segment_length": self.average_segment_length, "dataset_process_rule": self.dataset_process_rule.to_dict() if self.dataset_process_rule else None, - "dataset": self.dataset.to_dict() if self.dataset else None, + "dataset": None, # Dataset class doesn't have a to_dict method "segment_count": self.segment_count, "hit_count": self.hit_count, } @classmethod - def from_dict(cls, data: dict): + def from_dict(cls, data: dict[str, Any]): return cls( id=data.get("id"), tenant_id=data.get("tenant_id"), @@ -711,46 +712,48 @@ class DocumentSegment(Base): ) @property - def child_chunks(self): - process_rule = self.document.dataset_process_rule - if process_rule.mode == "hierarchical": - rules = Rule(**process_rule.rules_dict) - if rules.parent_mode and rules.parent_mode != ParentMode.FULL_DOC: - child_chunks = ( - db.session.query(ChildChunk) - .where(ChildChunk.segment_id == self.id) - .order_by(ChildChunk.position.asc()) - .all() - ) - return child_chunks or [] - else: - return [] - else: + def child_chunks(self) -> list[Any]: + if not self.document: return [] + process_rule = self.document.dataset_process_rule + if process_rule and process_rule.mode == "hierarchical": + rules_dict = process_rule.rules_dict + if rules_dict: + rules = Rule(**rules_dict) + if rules.parent_mode and rules.parent_mode != ParentMode.FULL_DOC: + child_chunks = ( + db.session.query(ChildChunk) + .where(ChildChunk.segment_id == self.id) + .order_by(ChildChunk.position.asc()) + .all() + ) + return child_chunks or [] + return [] - def get_child_chunks(self): - process_rule = self.document.dataset_process_rule - if process_rule.mode == "hierarchical": - rules = Rule(**process_rule.rules_dict) - if rules.parent_mode: - child_chunks = ( - db.session.query(ChildChunk) - .where(ChildChunk.segment_id == self.id) - .order_by(ChildChunk.position.asc()) - .all() - ) - return child_chunks or [] - else: - return [] - else: + def get_child_chunks(self) -> list[Any]: + if not self.document: return [] + process_rule = self.document.dataset_process_rule + if process_rule and process_rule.mode == "hierarchical": + rules_dict = process_rule.rules_dict + if rules_dict: + rules = Rule(**rules_dict) + if rules.parent_mode: + child_chunks = ( + db.session.query(ChildChunk) + .where(ChildChunk.segment_id == self.id) + .order_by(ChildChunk.position.asc()) + .all() + ) + return child_chunks or [] + return [] @property - def sign_content(self): + def sign_content(self) -> str: return self.get_sign_content() - def get_sign_content(self): - signed_urls = [] + def get_sign_content(self) -> str: + signed_urls: list[tuple[int, int, str]] = [] text = self.content # For data before v0.10.0 @@ -890,17 +893,22 @@ class DatasetKeywordTable(Base): ) @property - def keyword_table_dict(self): + def keyword_table_dict(self) -> dict[str, set[Any]] | None: class SetDecoder(json.JSONDecoder): - def __init__(self, *args, **kwargs): - super().__init__(object_hook=self.object_hook, *args, **kwargs) + def __init__(self, *args: Any, **kwargs: Any) -> None: + def object_hook(dct: Any) -> Any: + if isinstance(dct, dict): + result: dict[str, Any] = {} + items = cast(dict[str, Any], dct).items() + for keyword, node_idxs in items: + if isinstance(node_idxs, list): + result[keyword] = set(cast(list[Any], node_idxs)) + else: + result[keyword] = node_idxs + return result + return dct - def object_hook(self, dct): - if isinstance(dct, dict): - for keyword, node_idxs in dct.items(): - if isinstance(node_idxs, list): - dct[keyword] = set(node_idxs) - return dct + super().__init__(object_hook=object_hook, *args, **kwargs) # get dataset dataset = db.session.query(Dataset).filter_by(id=self.dataset_id).first() @@ -1026,7 +1034,7 @@ class ExternalKnowledgeApis(Base): updated_by = mapped_column(StringUUID, nullable=True) updated_at: Mapped[datetime] = mapped_column(DateTime, nullable=False, server_default=func.current_timestamp()) - def to_dict(self): + def to_dict(self) -> dict[str, Any]: return { "id": self.id, "tenant_id": self.tenant_id, @@ -1039,14 +1047,14 @@ class ExternalKnowledgeApis(Base): } @property - def settings_dict(self): + def settings_dict(self) -> dict[str, Any] | None: try: return json.loads(self.settings) if self.settings else None except JSONDecodeError: return None @property - def dataset_bindings(self): + def dataset_bindings(self) -> list[dict[str, Any]]: external_knowledge_bindings = ( db.session.query(ExternalKnowledgeBindings) .where(ExternalKnowledgeBindings.external_knowledge_api_id == self.id) @@ -1054,7 +1062,7 @@ class ExternalKnowledgeApis(Base): ) dataset_ids = [binding.dataset_id for binding in external_knowledge_bindings] datasets = db.session.query(Dataset).where(Dataset.id.in_(dataset_ids)).all() - dataset_bindings = [] + dataset_bindings: list[dict[str, Any]] = [] for dataset in datasets: dataset_bindings.append({"id": dataset.id, "name": dataset.name}) diff --git a/api/models/model.py b/api/models/model.py index fbebdc817c..f8ead1f872 100644 --- a/api/models/model.py +++ b/api/models/model.py @@ -16,7 +16,7 @@ if TYPE_CHECKING: import sqlalchemy as sa from flask import request -from flask_login import UserMixin +from flask_login import UserMixin # type: ignore[import-untyped] from sqlalchemy import Float, Index, PrimaryKeyConstraint, String, exists, func, select, text from sqlalchemy.orm import Mapped, Session, mapped_column @@ -24,7 +24,7 @@ from configs import dify_config from constants import DEFAULT_FILE_NUMBER_LIMITS from core.file import FILE_MODEL_IDENTITY, File, FileTransferMethod, FileType from core.file import helpers as file_helpers -from libs.helper import generate_string +from libs.helper import generate_string # type: ignore[import-not-found] from .account import Account, Tenant from .base import Base @@ -98,7 +98,7 @@ class App(Base): use_icon_as_answer_icon: Mapped[bool] = mapped_column(sa.Boolean, nullable=False, server_default=sa.text("false")) @property - def desc_or_prompt(self): + def desc_or_prompt(self) -> str: if self.description: return self.description else: @@ -109,12 +109,12 @@ class App(Base): return "" @property - def site(self): + def site(self) -> Optional["Site"]: site = db.session.query(Site).where(Site.app_id == self.id).first() return site @property - def app_model_config(self): + def app_model_config(self) -> Optional["AppModelConfig"]: if self.app_model_config_id: return db.session.query(AppModelConfig).where(AppModelConfig.id == self.app_model_config_id).first() @@ -130,11 +130,11 @@ class App(Base): return None @property - def api_base_url(self): + def api_base_url(self) -> str: return (dify_config.SERVICE_API_URL or request.host_url.rstrip("/")) + "/v1" @property - def tenant(self): + def tenant(self) -> Optional[Tenant]: tenant = db.session.query(Tenant).where(Tenant.id == self.tenant_id).first() return tenant @@ -162,7 +162,7 @@ class App(Base): return str(self.mode) @property - def deleted_tools(self): + def deleted_tools(self) -> list[dict[str, str]]: from core.tools.tool_manager import ToolManager from services.plugin.plugin_service import PluginService @@ -242,7 +242,7 @@ class App(Base): provider_id.provider_name: existence[i] for i, provider_id in enumerate(builtin_provider_ids) } - deleted_tools = [] + deleted_tools: list[dict[str, str]] = [] for tool in tools: keys = list(tool.keys()) @@ -275,7 +275,7 @@ class App(Base): return deleted_tools @property - def tags(self): + def tags(self) -> list["Tag"]: tags = ( db.session.query(Tag) .join(TagBinding, Tag.id == TagBinding.tag_id) @@ -291,7 +291,7 @@ class App(Base): return tags or [] @property - def author_name(self): + def author_name(self) -> Optional[str]: if self.created_by: account = db.session.query(Account).where(Account.id == self.created_by).first() if account: @@ -334,20 +334,20 @@ class AppModelConfig(Base): file_upload = mapped_column(sa.Text) @property - def app(self): + def app(self) -> Optional[App]: app = db.session.query(App).where(App.id == self.app_id).first() return app @property - def model_dict(self): + def model_dict(self) -> dict[str, Any]: return json.loads(self.model) if self.model else {} @property - def suggested_questions_list(self): + def suggested_questions_list(self) -> list[str]: return json.loads(self.suggested_questions) if self.suggested_questions else [] @property - def suggested_questions_after_answer_dict(self): + def suggested_questions_after_answer_dict(self) -> dict[str, Any]: return ( json.loads(self.suggested_questions_after_answer) if self.suggested_questions_after_answer @@ -355,19 +355,19 @@ class AppModelConfig(Base): ) @property - def speech_to_text_dict(self): + def speech_to_text_dict(self) -> dict[str, Any]: return json.loads(self.speech_to_text) if self.speech_to_text else {"enabled": False} @property - def text_to_speech_dict(self): + def text_to_speech_dict(self) -> dict[str, Any]: return json.loads(self.text_to_speech) if self.text_to_speech else {"enabled": False} @property - def retriever_resource_dict(self): + def retriever_resource_dict(self) -> dict[str, Any]: return json.loads(self.retriever_resource) if self.retriever_resource else {"enabled": True} @property - def annotation_reply_dict(self): + def annotation_reply_dict(self) -> dict[str, Any]: annotation_setting = ( db.session.query(AppAnnotationSetting).where(AppAnnotationSetting.app_id == self.app_id).first() ) @@ -390,11 +390,11 @@ class AppModelConfig(Base): return {"enabled": False} @property - def more_like_this_dict(self): + def more_like_this_dict(self) -> dict[str, Any]: return json.loads(self.more_like_this) if self.more_like_this else {"enabled": False} @property - def sensitive_word_avoidance_dict(self): + def sensitive_word_avoidance_dict(self) -> dict[str, Any]: return ( json.loads(self.sensitive_word_avoidance) if self.sensitive_word_avoidance @@ -402,15 +402,15 @@ class AppModelConfig(Base): ) @property - def external_data_tools_list(self) -> list[dict]: + def external_data_tools_list(self) -> list[dict[str, Any]]: return json.loads(self.external_data_tools) if self.external_data_tools else [] @property - def user_input_form_list(self): + def user_input_form_list(self) -> list[dict[str, Any]]: return json.loads(self.user_input_form) if self.user_input_form else [] @property - def agent_mode_dict(self): + def agent_mode_dict(self) -> dict[str, Any]: return ( json.loads(self.agent_mode) if self.agent_mode @@ -418,17 +418,17 @@ class AppModelConfig(Base): ) @property - def chat_prompt_config_dict(self): + def chat_prompt_config_dict(self) -> dict[str, Any]: return json.loads(self.chat_prompt_config) if self.chat_prompt_config else {} @property - def completion_prompt_config_dict(self): + def completion_prompt_config_dict(self) -> dict[str, Any]: return json.loads(self.completion_prompt_config) if self.completion_prompt_config else {} @property - def dataset_configs_dict(self): + def dataset_configs_dict(self) -> dict[str, Any]: if self.dataset_configs: - dataset_configs: dict = json.loads(self.dataset_configs) + dataset_configs: dict[str, Any] = json.loads(self.dataset_configs) if "retrieval_model" not in dataset_configs: return {"retrieval_model": "single"} else: @@ -438,7 +438,7 @@ class AppModelConfig(Base): } @property - def file_upload_dict(self): + def file_upload_dict(self) -> dict[str, Any]: return ( json.loads(self.file_upload) if self.file_upload @@ -452,7 +452,7 @@ class AppModelConfig(Base): } ) - def to_dict(self): + def to_dict(self) -> dict[str, Any]: return { "opening_statement": self.opening_statement, "suggested_questions": self.suggested_questions_list, @@ -546,7 +546,7 @@ class RecommendedApp(Base): updated_at = mapped_column(sa.DateTime, nullable=False, server_default=func.current_timestamp()) @property - def app(self): + def app(self) -> Optional[App]: app = db.session.query(App).where(App.id == self.app_id).first() return app @@ -570,12 +570,12 @@ class InstalledApp(Base): created_at = mapped_column(sa.DateTime, nullable=False, server_default=func.current_timestamp()) @property - def app(self): + def app(self) -> Optional[App]: app = db.session.query(App).where(App.id == self.app_id).first() return app @property - def tenant(self): + def tenant(self) -> Optional[Tenant]: tenant = db.session.query(Tenant).where(Tenant.id == self.tenant_id).first() return tenant @@ -622,7 +622,7 @@ class Conversation(Base): mode: Mapped[str] = mapped_column(String(255)) name: Mapped[str] = mapped_column(String(255), nullable=False) summary = mapped_column(sa.Text) - _inputs: Mapped[dict] = mapped_column("inputs", sa.JSON) + _inputs: Mapped[dict[str, Any]] = mapped_column("inputs", sa.JSON) introduction = mapped_column(sa.Text) system_instruction = mapped_column(sa.Text) system_instruction_tokens: Mapped[int] = mapped_column(sa.Integer, nullable=False, server_default=sa.text("0")) @@ -652,7 +652,7 @@ class Conversation(Base): is_deleted: Mapped[bool] = mapped_column(sa.Boolean, nullable=False, server_default=sa.text("false")) @property - def inputs(self): + def inputs(self) -> dict[str, Any]: inputs = self._inputs.copy() # Convert file mapping to File object @@ -660,22 +660,39 @@ class Conversation(Base): # NOTE: It's not the best way to implement this, but it's the only way to avoid circular import for now. from factories import file_factory - if isinstance(value, dict) and value.get("dify_model_identity") == FILE_MODEL_IDENTITY: - if value["transfer_method"] == FileTransferMethod.TOOL_FILE: - value["tool_file_id"] = value["related_id"] - elif value["transfer_method"] in [FileTransferMethod.LOCAL_FILE, FileTransferMethod.REMOTE_URL]: - value["upload_file_id"] = value["related_id"] - inputs[key] = file_factory.build_from_mapping(mapping=value, tenant_id=value["tenant_id"]) - elif isinstance(value, list) and all( - isinstance(item, dict) and item.get("dify_model_identity") == FILE_MODEL_IDENTITY for item in value + if ( + isinstance(value, dict) + and cast(dict[str, Any], value).get("dify_model_identity") == FILE_MODEL_IDENTITY ): - inputs[key] = [] - for item in value: - if item["transfer_method"] == FileTransferMethod.TOOL_FILE: - item["tool_file_id"] = item["related_id"] - elif item["transfer_method"] in [FileTransferMethod.LOCAL_FILE, FileTransferMethod.REMOTE_URL]: - item["upload_file_id"] = item["related_id"] - inputs[key].append(file_factory.build_from_mapping(mapping=item, tenant_id=item["tenant_id"])) + value_dict = cast(dict[str, Any], value) + if value_dict["transfer_method"] == FileTransferMethod.TOOL_FILE: + value_dict["tool_file_id"] = value_dict["related_id"] + elif value_dict["transfer_method"] in [FileTransferMethod.LOCAL_FILE, FileTransferMethod.REMOTE_URL]: + value_dict["upload_file_id"] = value_dict["related_id"] + tenant_id = cast(str, value_dict.get("tenant_id", "")) + inputs[key] = file_factory.build_from_mapping(mapping=value_dict, tenant_id=tenant_id) + elif isinstance(value, list): + value_list = cast(list[Any], value) + if all( + isinstance(item, dict) + and cast(dict[str, Any], item).get("dify_model_identity") == FILE_MODEL_IDENTITY + for item in value_list + ): + file_list: list[File] = [] + for item in value_list: + if not isinstance(item, dict): + continue + item_dict = cast(dict[str, Any], item) + if item_dict["transfer_method"] == FileTransferMethod.TOOL_FILE: + item_dict["tool_file_id"] = item_dict["related_id"] + elif item_dict["transfer_method"] in [ + FileTransferMethod.LOCAL_FILE, + FileTransferMethod.REMOTE_URL, + ]: + item_dict["upload_file_id"] = item_dict["related_id"] + tenant_id = cast(str, item_dict.get("tenant_id", "")) + file_list.append(file_factory.build_from_mapping(mapping=item_dict, tenant_id=tenant_id)) + inputs[key] = file_list return inputs @@ -685,8 +702,10 @@ class Conversation(Base): for k, v in inputs.items(): if isinstance(v, File): inputs[k] = v.model_dump() - elif isinstance(v, list) and all(isinstance(item, File) for item in v): - inputs[k] = [item.model_dump() for item in v] + elif isinstance(v, list): + v_list = cast(list[Any], v) + if all(isinstance(item, File) for item in v_list): + inputs[k] = [item.model_dump() for item in v_list if isinstance(item, File)] self._inputs = inputs @property @@ -826,7 +845,7 @@ class Conversation(Base): ) @property - def app(self): + def app(self) -> Optional[App]: return db.session.query(App).where(App.id == self.app_id).first() @property @@ -839,7 +858,7 @@ class Conversation(Base): return None @property - def from_account_name(self): + def from_account_name(self) -> Optional[str]: if self.from_account_id: account = db.session.query(Account).where(Account.id == self.from_account_id).first() if account: @@ -848,10 +867,10 @@ class Conversation(Base): return None @property - def in_debug_mode(self): + def in_debug_mode(self) -> bool: return self.override_model_configs is not None - def to_dict(self): + def to_dict(self) -> dict[str, Any]: return { "id": self.id, "app_id": self.app_id, @@ -897,7 +916,7 @@ class Message(Base): model_id = mapped_column(String(255), nullable=True) override_model_configs = mapped_column(sa.Text) conversation_id = mapped_column(StringUUID, sa.ForeignKey("conversations.id"), nullable=False) - _inputs: Mapped[dict] = mapped_column("inputs", sa.JSON) + _inputs: Mapped[dict[str, Any]] = mapped_column("inputs", sa.JSON) query: Mapped[str] = mapped_column(sa.Text, nullable=False) message = mapped_column(sa.JSON, nullable=False) message_tokens: Mapped[int] = mapped_column(sa.Integer, nullable=False, server_default=sa.text("0")) @@ -924,28 +943,45 @@ class Message(Base): workflow_run_id: Mapped[Optional[str]] = mapped_column(StringUUID) @property - def inputs(self): + def inputs(self) -> dict[str, Any]: inputs = self._inputs.copy() for key, value in inputs.items(): # NOTE: It's not the best way to implement this, but it's the only way to avoid circular import for now. from factories import file_factory - if isinstance(value, dict) and value.get("dify_model_identity") == FILE_MODEL_IDENTITY: - if value["transfer_method"] == FileTransferMethod.TOOL_FILE: - value["tool_file_id"] = value["related_id"] - elif value["transfer_method"] in [FileTransferMethod.LOCAL_FILE, FileTransferMethod.REMOTE_URL]: - value["upload_file_id"] = value["related_id"] - inputs[key] = file_factory.build_from_mapping(mapping=value, tenant_id=value["tenant_id"]) - elif isinstance(value, list) and all( - isinstance(item, dict) and item.get("dify_model_identity") == FILE_MODEL_IDENTITY for item in value + if ( + isinstance(value, dict) + and cast(dict[str, Any], value).get("dify_model_identity") == FILE_MODEL_IDENTITY ): - inputs[key] = [] - for item in value: - if item["transfer_method"] == FileTransferMethod.TOOL_FILE: - item["tool_file_id"] = item["related_id"] - elif item["transfer_method"] in [FileTransferMethod.LOCAL_FILE, FileTransferMethod.REMOTE_URL]: - item["upload_file_id"] = item["related_id"] - inputs[key].append(file_factory.build_from_mapping(mapping=item, tenant_id=item["tenant_id"])) + value_dict = cast(dict[str, Any], value) + if value_dict["transfer_method"] == FileTransferMethod.TOOL_FILE: + value_dict["tool_file_id"] = value_dict["related_id"] + elif value_dict["transfer_method"] in [FileTransferMethod.LOCAL_FILE, FileTransferMethod.REMOTE_URL]: + value_dict["upload_file_id"] = value_dict["related_id"] + tenant_id = cast(str, value_dict.get("tenant_id", "")) + inputs[key] = file_factory.build_from_mapping(mapping=value_dict, tenant_id=tenant_id) + elif isinstance(value, list): + value_list = cast(list[Any], value) + if all( + isinstance(item, dict) + and cast(dict[str, Any], item).get("dify_model_identity") == FILE_MODEL_IDENTITY + for item in value_list + ): + file_list: list[File] = [] + for item in value_list: + if not isinstance(item, dict): + continue + item_dict = cast(dict[str, Any], item) + if item_dict["transfer_method"] == FileTransferMethod.TOOL_FILE: + item_dict["tool_file_id"] = item_dict["related_id"] + elif item_dict["transfer_method"] in [ + FileTransferMethod.LOCAL_FILE, + FileTransferMethod.REMOTE_URL, + ]: + item_dict["upload_file_id"] = item_dict["related_id"] + tenant_id = cast(str, item_dict.get("tenant_id", "")) + file_list.append(file_factory.build_from_mapping(mapping=item_dict, tenant_id=tenant_id)) + inputs[key] = file_list return inputs @inputs.setter @@ -954,8 +990,10 @@ class Message(Base): for k, v in inputs.items(): if isinstance(v, File): inputs[k] = v.model_dump() - elif isinstance(v, list) and all(isinstance(item, File) for item in v): - inputs[k] = [item.model_dump() for item in v] + elif isinstance(v, list): + v_list = cast(list[Any], v) + if all(isinstance(item, File) for item in v_list): + inputs[k] = [item.model_dump() for item in v_list if isinstance(item, File)] self._inputs = inputs @property @@ -1083,15 +1121,15 @@ class Message(Base): return None @property - def in_debug_mode(self): + def in_debug_mode(self) -> bool: return self.override_model_configs is not None @property - def message_metadata_dict(self): + def message_metadata_dict(self) -> dict[str, Any]: return json.loads(self.message_metadata) if self.message_metadata else {} @property - def agent_thoughts(self): + def agent_thoughts(self) -> list["MessageAgentThought"]: return ( db.session.query(MessageAgentThought) .where(MessageAgentThought.message_id == self.id) @@ -1100,11 +1138,11 @@ class Message(Base): ) @property - def retriever_resources(self): + def retriever_resources(self) -> Any | list[Any]: return self.message_metadata_dict.get("retriever_resources") if self.message_metadata else [] @property - def message_files(self): + def message_files(self) -> list[dict[str, Any]]: from factories import file_factory message_files = db.session.query(MessageFile).where(MessageFile.message_id == self.id).all() @@ -1112,7 +1150,7 @@ class Message(Base): if not current_app: raise ValueError(f"App {self.app_id} not found") - files = [] + files: list[File] = [] for message_file in message_files: if message_file.transfer_method == FileTransferMethod.LOCAL_FILE.value: if message_file.upload_file_id is None: @@ -1159,7 +1197,7 @@ class Message(Base): ) files.append(file) - result = [ + result: list[dict[str, Any]] = [ {"belongs_to": message_file.belongs_to, "upload_file_id": message_file.upload_file_id, **file.to_dict()} for (file, message_file) in zip(files, message_files) ] @@ -1176,7 +1214,7 @@ class Message(Base): return None - def to_dict(self): + def to_dict(self) -> dict[str, Any]: return { "id": self.id, "app_id": self.app_id, @@ -1200,7 +1238,7 @@ class Message(Base): } @classmethod - def from_dict(cls, data: dict): + def from_dict(cls, data: dict[str, Any]) -> "Message": return cls( id=data["id"], app_id=data["app_id"], @@ -1250,7 +1288,7 @@ class MessageFeedback(Base): account = db.session.query(Account).where(Account.id == self.from_account_id).first() return account - def to_dict(self): + def to_dict(self) -> dict[str, Any]: return { "id": str(self.id), "app_id": str(self.app_id), @@ -1435,7 +1473,18 @@ class EndUser(Base, UserMixin): type: Mapped[str] = mapped_column(String(255), nullable=False) external_user_id = mapped_column(String(255), nullable=True) name = mapped_column(String(255)) - is_anonymous: Mapped[bool] = mapped_column(sa.Boolean, nullable=False, server_default=sa.text("true")) + _is_anonymous: Mapped[bool] = mapped_column( + "is_anonymous", sa.Boolean, nullable=False, server_default=sa.text("true") + ) + + @property + def is_anonymous(self) -> Literal[False]: + return False + + @is_anonymous.setter + def is_anonymous(self, value: bool) -> None: + self._is_anonymous = value + session_id: Mapped[str] = mapped_column() created_at = mapped_column(sa.DateTime, nullable=False, server_default=func.current_timestamp()) updated_at = mapped_column(sa.DateTime, nullable=False, server_default=func.current_timestamp()) @@ -1461,7 +1510,7 @@ class AppMCPServer(Base): updated_at = mapped_column(sa.DateTime, nullable=False, server_default=func.current_timestamp()) @staticmethod - def generate_server_code(n): + def generate_server_code(n: int) -> str: while True: result = generate_string(n) while db.session.query(AppMCPServer).where(AppMCPServer.server_code == result).count() > 0: @@ -1518,7 +1567,7 @@ class Site(Base): self._custom_disclaimer = value @staticmethod - def generate_code(n): + def generate_code(n: int) -> str: while True: result = generate_string(n) while db.session.query(Site).where(Site.code == result).count() > 0: @@ -1549,7 +1598,7 @@ class ApiToken(Base): created_at = mapped_column(sa.DateTime, nullable=False, server_default=func.current_timestamp()) @staticmethod - def generate_api_key(prefix, n): + def generate_api_key(prefix: str, n: int) -> str: while True: result = prefix + generate_string(n) if db.session.scalar(select(exists().where(ApiToken.token == result))): @@ -1689,7 +1738,7 @@ class MessageAgentThought(Base): created_at = mapped_column(sa.DateTime, nullable=False, server_default=db.func.current_timestamp()) @property - def files(self): + def files(self) -> list[Any]: if self.message_files: return cast(list[Any], json.loads(self.message_files)) else: @@ -1700,32 +1749,32 @@ class MessageAgentThought(Base): return self.tool.split(";") if self.tool else [] @property - def tool_labels(self): + def tool_labels(self) -> dict[str, Any]: try: if self.tool_labels_str: - return cast(dict, json.loads(self.tool_labels_str)) + return cast(dict[str, Any], json.loads(self.tool_labels_str)) else: return {} except Exception: return {} @property - def tool_meta(self): + def tool_meta(self) -> dict[str, Any]: try: if self.tool_meta_str: - return cast(dict, json.loads(self.tool_meta_str)) + return cast(dict[str, Any], json.loads(self.tool_meta_str)) else: return {} except Exception: return {} @property - def tool_inputs_dict(self): + def tool_inputs_dict(self) -> dict[str, Any]: tools = self.tools try: if self.tool_input: data = json.loads(self.tool_input) - result = {} + result: dict[str, Any] = {} for tool in tools: if tool in data: result[tool] = data[tool] @@ -1741,12 +1790,12 @@ class MessageAgentThought(Base): return {} @property - def tool_outputs_dict(self): + def tool_outputs_dict(self) -> dict[str, Any]: tools = self.tools try: if self.observation: data = json.loads(self.observation) - result = {} + result: dict[str, Any] = {} for tool in tools: if tool in data: result[tool] = data[tool] @@ -1844,14 +1893,14 @@ class TraceAppConfig(Base): is_active: Mapped[bool] = mapped_column(sa.Boolean, nullable=False, server_default=sa.text("true")) @property - def tracing_config_dict(self): + def tracing_config_dict(self) -> dict[str, Any]: return self.tracing_config or {} @property - def tracing_config_str(self): + def tracing_config_str(self) -> str: return json.dumps(self.tracing_config_dict) - def to_dict(self): + def to_dict(self) -> dict[str, Any]: return { "id": self.id, "app_id": self.app_id, diff --git a/api/models/provider.py b/api/models/provider.py index 18bf0ac5ad..9a344ea56d 100644 --- a/api/models/provider.py +++ b/api/models/provider.py @@ -17,7 +17,7 @@ class ProviderType(Enum): SYSTEM = "system" @staticmethod - def value_of(value): + def value_of(value: str) -> "ProviderType": for member in ProviderType: if member.value == value: return member @@ -35,7 +35,7 @@ class ProviderQuotaType(Enum): """hosted trial quota""" @staticmethod - def value_of(value): + def value_of(value: str) -> "ProviderQuotaType": for member in ProviderQuotaType: if member.value == value: return member diff --git a/api/models/tools.py b/api/models/tools.py index 8755570ee1..09c8cd4002 100644 --- a/api/models/tools.py +++ b/api/models/tools.py @@ -1,6 +1,6 @@ import json from datetime import datetime -from typing import Optional, cast +from typing import Any, Optional, cast from urllib.parse import urlparse import sqlalchemy as sa @@ -54,8 +54,8 @@ class ToolOAuthTenantClient(Base): encrypted_oauth_params: Mapped[str] = mapped_column(sa.Text, nullable=False) @property - def oauth_params(self): - return cast(dict, json.loads(self.encrypted_oauth_params or "{}")) + def oauth_params(self) -> dict[str, Any]: + return cast(dict[str, Any], json.loads(self.encrypted_oauth_params or "{}")) class BuiltinToolProvider(Base): @@ -96,8 +96,8 @@ class BuiltinToolProvider(Base): expires_at: Mapped[int] = mapped_column(sa.BigInteger, nullable=False, server_default=sa.text("-1")) @property - def credentials(self): - return cast(dict, json.loads(self.encrypted_credentials)) + def credentials(self) -> dict[str, Any]: + return cast(dict[str, Any], json.loads(self.encrypted_credentials)) class ApiToolProvider(Base): @@ -146,8 +146,8 @@ class ApiToolProvider(Base): return [ApiToolBundle(**tool) for tool in json.loads(self.tools_str)] @property - def credentials(self): - return dict(json.loads(self.credentials_str)) + def credentials(self) -> dict[str, Any]: + return dict[str, Any](json.loads(self.credentials_str)) @property def user(self) -> Account | None: @@ -289,9 +289,9 @@ class MCPToolProvider(Base): return db.session.query(Tenant).where(Tenant.id == self.tenant_id).first() @property - def credentials(self): + def credentials(self) -> dict[str, Any]: try: - return cast(dict, json.loads(self.encrypted_credentials)) or {} + return cast(dict[str, Any], json.loads(self.encrypted_credentials)) or {} except Exception: return {} @@ -327,12 +327,12 @@ class MCPToolProvider(Base): return mask_url(self.decrypted_server_url) @property - def decrypted_credentials(self): + def decrypted_credentials(self) -> dict[str, Any]: from core.helper.provider_cache import NoOpProviderCredentialCache from core.tools.mcp_tool.provider import MCPToolProviderController from core.tools.utils.encryption import create_provider_encrypter - provider_controller = MCPToolProviderController._from_db(self) + provider_controller = MCPToolProviderController.from_db(self) encrypter, _ = create_provider_encrypter( tenant_id=self.tenant_id, @@ -340,7 +340,7 @@ class MCPToolProvider(Base): cache=NoOpProviderCredentialCache(), ) - return encrypter.decrypt(self.credentials) # type: ignore + return encrypter.decrypt(self.credentials) class ToolModelInvoke(Base): diff --git a/api/models/types.py b/api/models/types.py index e5581c3ab0..cc69ae4f57 100644 --- a/api/models/types.py +++ b/api/models/types.py @@ -1,29 +1,34 @@ import enum -from typing import Generic, TypeVar +import uuid +from typing import Any, Generic, TypeVar from sqlalchemy import CHAR, VARCHAR, TypeDecorator from sqlalchemy.dialects.postgresql import UUID +from sqlalchemy.engine.interfaces import Dialect +from sqlalchemy.sql.type_api import TypeEngine -class StringUUID(TypeDecorator): +class StringUUID(TypeDecorator[uuid.UUID | str | None]): impl = CHAR cache_ok = True - def process_bind_param(self, value, dialect): + def process_bind_param(self, value: uuid.UUID | str | None, dialect: Dialect) -> str | None: if value is None: return value elif dialect.name == "postgresql": return str(value) else: - return value.hex + if isinstance(value, uuid.UUID): + return value.hex + return value - def load_dialect_impl(self, dialect): + def load_dialect_impl(self, dialect: Dialect) -> TypeEngine[Any]: if dialect.name == "postgresql": return dialect.type_descriptor(UUID()) else: return dialect.type_descriptor(CHAR(36)) - def process_result_value(self, value, dialect): + def process_result_value(self, value: uuid.UUID | str | None, dialect: Dialect) -> str | None: if value is None: return value return str(value) @@ -32,7 +37,7 @@ class StringUUID(TypeDecorator): _E = TypeVar("_E", bound=enum.StrEnum) -class EnumText(TypeDecorator, Generic[_E]): +class EnumText(TypeDecorator[_E | None], Generic[_E]): impl = VARCHAR cache_ok = True @@ -50,28 +55,25 @@ class EnumText(TypeDecorator, Generic[_E]): # leave some rooms for future longer enum values. self._length = max(max_enum_value_len, 20) - def process_bind_param(self, value: _E | str | None, dialect): + def process_bind_param(self, value: _E | str | None, dialect: Dialect) -> str | None: if value is None: return value if isinstance(value, self._enum_class): return value.value - elif isinstance(value, str): - self._enum_class(value) - return value - else: - raise TypeError(f"expected str or {self._enum_class}, got {type(value)}") + # Since _E is bound to StrEnum which inherits from str, at this point value must be str + self._enum_class(value) + return value - def load_dialect_impl(self, dialect): + def load_dialect_impl(self, dialect: Dialect) -> TypeEngine[Any]: return dialect.type_descriptor(VARCHAR(self._length)) - def process_result_value(self, value, dialect) -> _E | None: + def process_result_value(self, value: str | None, dialect: Dialect) -> _E | None: if value is None: return value - if not isinstance(value, str): - raise TypeError(f"expected str, got {type(value)}") + # Type annotation guarantees value is str at this point return self._enum_class(value) - def compare_values(self, x, y): + def compare_values(self, x: _E | None, y: _E | None) -> bool: if x is None or y is None: return x is y return x == y diff --git a/api/models/workflow.py b/api/models/workflow.py index 23f18929d4..4686b38b01 100644 --- a/api/models/workflow.py +++ b/api/models/workflow.py @@ -3,7 +3,7 @@ import logging from collections.abc import Mapping, Sequence from datetime import datetime from enum import Enum, StrEnum -from typing import TYPE_CHECKING, Any, Optional, Union +from typing import TYPE_CHECKING, Any, Optional, Union, cast from uuid import uuid4 import sqlalchemy as sa @@ -224,7 +224,7 @@ class Workflow(Base): raise WorkflowDataError("nodes not found in workflow graph") try: - node_config = next(filter(lambda node: node["id"] == node_id, nodes)) + node_config: dict[str, Any] = next(filter(lambda node: node["id"] == node_id, nodes)) except StopIteration: raise NodeNotFoundError(node_id) assert isinstance(node_config, dict) @@ -289,7 +289,7 @@ class Workflow(Base): def features_dict(self) -> dict[str, Any]: return json.loads(self.features) if self.features else {} - def user_input_form(self, to_old_structure: bool = False): + def user_input_form(self, to_old_structure: bool = False) -> list[Any]: # get start node from graph if not self.graph: return [] @@ -306,7 +306,7 @@ class Workflow(Base): variables: list[Any] = start_node.get("data", {}).get("variables", []) if to_old_structure: - old_structure_variables = [] + old_structure_variables: list[dict[str, Any]] = [] for variable in variables: old_structure_variables.append({variable["type"]: variable}) @@ -346,9 +346,7 @@ class Workflow(Base): @property def environment_variables(self) -> Sequence[StringVariable | IntegerVariable | FloatVariable | SecretVariable]: - # TODO: find some way to init `self._environment_variables` when instance created. - if self._environment_variables is None: - self._environment_variables = "{}" + # _environment_variables is guaranteed to be non-None due to server_default="{}" # Use workflow.tenant_id to avoid relying on request user in background threads tenant_id = self.tenant_id @@ -362,17 +360,18 @@ class Workflow(Base): ] # decrypt secret variables value - def decrypt_func(var): + def decrypt_func(var: Variable) -> StringVariable | IntegerVariable | FloatVariable | SecretVariable: if isinstance(var, SecretVariable): return var.model_copy(update={"value": encrypter.decrypt_token(tenant_id=tenant_id, token=var.value)}) elif isinstance(var, (StringVariable, IntegerVariable, FloatVariable)): return var else: - raise AssertionError("this statement should be unreachable.") + # Other variable types are not supported for environment variables + raise AssertionError(f"Unexpected variable type for environment variable: {type(var)}") - decrypted_results: list[SecretVariable | StringVariable | IntegerVariable | FloatVariable] = list( - map(decrypt_func, results) - ) + decrypted_results: list[SecretVariable | StringVariable | IntegerVariable | FloatVariable] = [ + decrypt_func(var) for var in results + ] return decrypted_results @environment_variables.setter @@ -400,7 +399,7 @@ class Workflow(Base): value[i] = origin_variables_dictionary[variable.id].model_copy(update={"name": variable.name}) # encrypt secret variables value - def encrypt_func(var): + def encrypt_func(var: Variable) -> Variable: if isinstance(var, SecretVariable): return var.model_copy(update={"value": encrypter.encrypt_token(tenant_id=tenant_id, token=var.value)}) else: @@ -430,9 +429,7 @@ class Workflow(Base): @property def conversation_variables(self) -> Sequence[Variable]: - # TODO: find some way to init `self._conversation_variables` when instance created. - if self._conversation_variables is None: - self._conversation_variables = "{}" + # _conversation_variables is guaranteed to be non-None due to server_default="{}" variables_dict: dict[str, Any] = json.loads(self._conversation_variables) results = [variable_factory.build_conversation_variable_from_mapping(v) for v in variables_dict.values()] @@ -577,7 +574,7 @@ class WorkflowRun(Base): } @classmethod - def from_dict(cls, data: dict) -> "WorkflowRun": + def from_dict(cls, data: dict[str, Any]) -> "WorkflowRun": return cls( id=data.get("id"), tenant_id=data.get("tenant_id"), @@ -662,7 +659,8 @@ class WorkflowNodeExecutionModel(Base): __tablename__ = "workflow_node_executions" @declared_attr - def __table_args__(cls): # noqa + @classmethod + def __table_args__(cls) -> Any: return ( PrimaryKeyConstraint("id", name="workflow_node_execution_pkey"), Index( @@ -699,7 +697,7 @@ class WorkflowNodeExecutionModel(Base): # MyPy may flag the following line because it doesn't recognize that # the `declared_attr` decorator passes the receiving class as the first # argument to this method, allowing us to reference class attributes. - cls.created_at.desc(), # type: ignore + cls.created_at.desc(), ), ) @@ -761,15 +759,15 @@ class WorkflowNodeExecutionModel(Base): return json.loads(self.execution_metadata) if self.execution_metadata else {} @property - def extras(self): + def extras(self) -> dict[str, Any]: from core.tools.tool_manager import ToolManager - extras = {} + extras: dict[str, Any] = {} if self.execution_metadata_dict: from core.workflow.nodes import NodeType if self.node_type == NodeType.TOOL.value and "tool_info" in self.execution_metadata_dict: - tool_info = self.execution_metadata_dict["tool_info"] + tool_info: dict[str, Any] = self.execution_metadata_dict["tool_info"] extras["icon"] = ToolManager.get_tool_icon( tenant_id=self.tenant_id, provider_type=tool_info["provider_type"], @@ -1037,7 +1035,7 @@ class WorkflowDraftVariable(Base): # making this attribute harder to access from outside the class. __value: Segment | None - def __init__(self, *args, **kwargs): + def __init__(self, *args: Any, **kwargs: Any) -> None: """ The constructor of `WorkflowDraftVariable` is not intended for direct use outside this file. Its solo purpose is setup private state @@ -1055,15 +1053,15 @@ class WorkflowDraftVariable(Base): self.__value = None def get_selector(self) -> list[str]: - selector = json.loads(self.selector) + selector: Any = json.loads(self.selector) if not isinstance(selector, list): logger.error( "invalid selector loaded from database, type=%s, value=%s", - type(selector), + type(selector).__name__, self.selector, ) raise ValueError("invalid selector.") - return selector + return cast(list[str], selector) def _set_selector(self, value: list[str]): self.selector = json.dumps(value) @@ -1086,15 +1084,17 @@ class WorkflowDraftVariable(Base): # `WorkflowEntry.handle_special_values`, making a comprehensive migration challenging. if isinstance(value, dict): if not maybe_file_object(value): - return value + return cast(Any, value) return File.model_validate(value) elif isinstance(value, list) and value: - first = value[0] + value_list = cast(list[Any], value) + first: Any = value_list[0] if not maybe_file_object(first): - return value - return [File.model_validate(i) for i in value] + return cast(Any, value) + file_list: list[File] = [File.model_validate(cast(dict[str, Any], i)) for i in value_list] + return cast(Any, file_list) else: - return value + return cast(Any, value) @classmethod def build_segment_with_type(cls, segment_type: SegmentType, value: Any) -> Segment: diff --git a/api/pyrightconfig.json b/api/pyrightconfig.json index 8694f44fae..059b8bba4f 100644 --- a/api/pyrightconfig.json +++ b/api/pyrightconfig.json @@ -6,7 +6,6 @@ "tests/", "migrations/", ".venv/", - "models/", "core/", "controllers/", "tasks/", diff --git a/api/services/agent_service.py b/api/services/agent_service.py index 72833b9d69..76267a2fe1 100644 --- a/api/services/agent_service.py +++ b/api/services/agent_service.py @@ -1,5 +1,5 @@ import threading -from typing import Optional +from typing import Any, Optional import pytz from flask_login import current_user @@ -68,7 +68,7 @@ class AgentService: if not app_model_config: raise ValueError("App model config not found") - result = { + result: dict[str, Any] = { "meta": { "status": "success", "executor": executor, diff --git a/api/services/app_service.py b/api/services/app_service.py index 4502fa9296..09aab5f0c4 100644 --- a/api/services/app_service.py +++ b/api/services/app_service.py @@ -171,6 +171,8 @@ class AppService: # get original app model config if app.mode == AppMode.AGENT_CHAT.value or app.is_agent: model_config = app.app_model_config + if not model_config: + return app agent_mode = model_config.agent_mode_dict # decrypt agent tool parameters if it's secret-input for tool in agent_mode.get("tools") or []: @@ -205,7 +207,8 @@ class AppService: pass # override agent mode - model_config.agent_mode = json.dumps(agent_mode) + if model_config: + model_config.agent_mode = json.dumps(agent_mode) class ModifiedApp(App): """ diff --git a/api/services/audio_service.py b/api/services/audio_service.py index 0084eebb32..9b1999d813 100644 --- a/api/services/audio_service.py +++ b/api/services/audio_service.py @@ -12,7 +12,7 @@ from core.model_manager import ModelManager from core.model_runtime.entities.model_entities import ModelType from extensions.ext_database import db from models.enums import MessageStatus -from models.model import App, AppMode, AppModelConfig, Message +from models.model import App, AppMode, Message from services.errors.audio import ( AudioTooLargeServiceError, NoAudioUploadedServiceError, @@ -40,7 +40,9 @@ class AudioService: if "speech_to_text" not in features_dict or not features_dict["speech_to_text"].get("enabled"): raise ValueError("Speech to text is not enabled") else: - app_model_config: AppModelConfig = app_model.app_model_config + app_model_config = app_model.app_model_config + if not app_model_config: + raise ValueError("Speech to text is not enabled") if not app_model_config.speech_to_text_dict["enabled"]: raise ValueError("Speech to text is not enabled") diff --git a/api/services/dataset_service.py b/api/services/dataset_service.py index e0885f3257..c0c97fbd77 100644 --- a/api/services/dataset_service.py +++ b/api/services/dataset_service.py @@ -973,7 +973,7 @@ class DocumentService: file_ids = [ document.data_source_info_dict["upload_file_id"] for document in documents - if document.data_source_type == "upload_file" + if document.data_source_type == "upload_file" and document.data_source_info_dict ] batch_clean_document_task.delay(document_ids, dataset.id, dataset.doc_form, file_ids) @@ -1067,8 +1067,9 @@ class DocumentService: # sync document indexing document.indexing_status = "waiting" data_source_info = document.data_source_info_dict - data_source_info["mode"] = "scrape" - document.data_source_info = json.dumps(data_source_info, ensure_ascii=False) + if data_source_info: + data_source_info["mode"] = "scrape" + document.data_source_info = json.dumps(data_source_info, ensure_ascii=False) db.session.add(document) db.session.commit() diff --git a/api/services/external_knowledge_service.py b/api/services/external_knowledge_service.py index 783d6c2428..3262a00663 100644 --- a/api/services/external_knowledge_service.py +++ b/api/services/external_knowledge_service.py @@ -114,8 +114,9 @@ class ExternalDatasetService: ) if external_knowledge_api is None: raise ValueError("api template not found") - if args.get("settings") and args.get("settings").get("api_key") == HIDDEN_VALUE: - args.get("settings")["api_key"] = external_knowledge_api.settings_dict.get("api_key") + settings = args.get("settings") + if settings and settings.get("api_key") == HIDDEN_VALUE and external_knowledge_api.settings_dict: + settings["api_key"] = external_knowledge_api.settings_dict.get("api_key") external_knowledge_api.name = args.get("name") external_knowledge_api.description = args.get("description", "") diff --git a/api/services/tools/mcp_tools_manage_service.py b/api/services/tools/mcp_tools_manage_service.py index 665ef27d66..b557d2155a 100644 --- a/api/services/tools/mcp_tools_manage_service.py +++ b/api/services/tools/mcp_tools_manage_service.py @@ -226,7 +226,7 @@ class MCPToolManageService: def update_mcp_provider_credentials( cls, mcp_provider: MCPToolProvider, credentials: dict[str, Any], authed: bool = False ): - provider_controller = MCPToolProviderController._from_db(mcp_provider) + provider_controller = MCPToolProviderController.from_db(mcp_provider) tool_configuration = ProviderConfigEncrypter( tenant_id=mcp_provider.tenant_id, config=list(provider_controller.get_credentials_schema()), # ty: ignore [invalid-argument-type] diff --git a/api/tests/unit_tests/models/test_types_enum_text.py b/api/tests/unit_tests/models/test_types_enum_text.py index e4061b72c7..c59afcf0db 100644 --- a/api/tests/unit_tests/models/test_types_enum_text.py +++ b/api/tests/unit_tests/models/test_types_enum_text.py @@ -154,7 +154,7 @@ class TestEnumText: TestCase( name="session insert with invalid type", action=lambda s: _session_insert_with_value(s, 1), - exc_type=TypeError, + exc_type=ValueError, ), TestCase( name="insert with invalid value", @@ -164,7 +164,7 @@ class TestEnumText: TestCase( name="insert with invalid type", action=lambda s: _insert_with_user(s, 1), - exc_type=TypeError, + exc_type=ValueError, ), ] for idx, c in enumerate(cases, 1): From 27bf244b3beb236dc8fdf1d8c337ad084e29d6e2 Mon Sep 17 00:00:00 2001 From: Asuka Minato Date: Mon, 8 Sep 2025 10:42:39 +0900 Subject: [PATCH 44/52] keep add and remove the same (#25277) --- web/app/components/plugins/marketplace/plugin-type-switch.tsx | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/web/app/components/plugins/marketplace/plugin-type-switch.tsx b/web/app/components/plugins/marketplace/plugin-type-switch.tsx index 9c071c5dc7..d852266aff 100644 --- a/web/app/components/plugins/marketplace/plugin-type-switch.tsx +++ b/web/app/components/plugins/marketplace/plugin-type-switch.tsx @@ -82,9 +82,7 @@ const PluginTypeSwitch = ({ }, [showSearchParams, handleActivePluginTypeChange]) useEffect(() => { - window.addEventListener('popstate', () => { - handlePopState() - }) + window.addEventListener('popstate', handlePopState) return () => { window.removeEventListener('popstate', handlePopState) } From 98204d78fb462b90b138839eb247f75715befa67 Mon Sep 17 00:00:00 2001 From: zyileven <40888939+zyileven@users.noreply.github.com> Date: Mon, 8 Sep 2025 09:46:02 +0800 Subject: [PATCH 45/52] =?UTF-8?q?Refactor=EF=BC=9Aupgrade=20react19=20ref?= =?UTF-8?q?=20as=20props=20(#25225)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: crazywoola <100913391+crazywoola@users.noreply.github.com> --- .../components/base/action-button/index.tsx | 35 ++++++++------- web/app/components/base/button/index.tsx | 37 ++++++++-------- web/app/components/base/input/index.tsx | 8 ++-- web/app/components/base/mermaid/index.tsx | 11 +++-- web/app/components/base/textarea/index.tsx | 43 +++++++++---------- .../components/datasets/preview/container.tsx | 8 ++-- .../install-bundle/steps/install-multi.tsx | 9 ++-- .../market-place-plugin/list.tsx | 10 +++-- 8 files changed, 83 insertions(+), 78 deletions(-) diff --git a/web/app/components/base/action-button/index.tsx b/web/app/components/base/action-button/index.tsx index c90d1a8de8..f70bfb4448 100644 --- a/web/app/components/base/action-button/index.tsx +++ b/web/app/components/base/action-button/index.tsx @@ -32,6 +32,7 @@ export type ActionButtonProps = { size?: 'xs' | 's' | 'm' | 'l' | 'xl' state?: ActionButtonState styleCss?: CSSProperties + ref?: React.Ref } & React.ButtonHTMLAttributes & VariantProps function getActionButtonState(state: ActionButtonState) { @@ -49,24 +50,22 @@ function getActionButtonState(state: ActionButtonState) { } } -const ActionButton = React.forwardRef( - ({ className, size, state = ActionButtonState.Default, styleCss, children, ...props }, ref) => { - return ( - - ) - }, -) +const ActionButton = ({ className, size, state = ActionButtonState.Default, styleCss, children, ref, ...props }: ActionButtonProps) => { + return ( + + ) +} ActionButton.displayName = 'ActionButton' export default ActionButton diff --git a/web/app/components/base/button/index.tsx b/web/app/components/base/button/index.tsx index 2040c65d34..4f75aec5a5 100644 --- a/web/app/components/base/button/index.tsx +++ b/web/app/components/base/button/index.tsx @@ -35,27 +35,26 @@ export type ButtonProps = { loading?: boolean styleCss?: CSSProperties spinnerClassName?: string + ref?: React.Ref } & React.ButtonHTMLAttributes & VariantProps -const Button = React.forwardRef( - ({ className, variant, size, destructive, loading, styleCss, children, spinnerClassName, ...props }, ref) => { - return ( - - ) - }, -) +const Button = ({ className, variant, size, destructive, loading, styleCss, children, spinnerClassName, ref, ...props }: ButtonProps) => { + return ( + + ) +} Button.displayName = 'Button' export default Button diff --git a/web/app/components/base/input/index.tsx b/web/app/components/base/input/index.tsx index ae171b0a76..63ba0e89af 100644 --- a/web/app/components/base/input/index.tsx +++ b/web/app/components/base/input/index.tsx @@ -30,9 +30,10 @@ export type InputProps = { wrapperClassName?: string styleCss?: CSSProperties unit?: string + ref?: React.Ref } & Omit, 'size'> & VariantProps -const Input = React.forwardRef(({ +const Input = ({ size, disabled, destructive, @@ -46,8 +47,9 @@ const Input = React.forwardRef(({ placeholder, onChange = noop, unit, + ref, ...props -}, ref) => { +}: InputProps) => { const { t } = useTranslation() return (
@@ -93,7 +95,7 @@ const Input = React.forwardRef(({ }
) -}) +} Input.displayName = 'Input' diff --git a/web/app/components/base/mermaid/index.tsx b/web/app/components/base/mermaid/index.tsx index 7df9ee398c..c1deab6e09 100644 --- a/web/app/components/base/mermaid/index.tsx +++ b/web/app/components/base/mermaid/index.tsx @@ -107,10 +107,13 @@ const initMermaid = () => { return isMermaidInitialized } -const Flowchart = React.forwardRef((props: { +type FlowchartProps = { PrimitiveCode: string theme?: 'light' | 'dark' -}, ref) => { + ref?: React.Ref +} + +const Flowchart = (props: FlowchartProps) => { const { t } = useTranslation() const [svgString, setSvgString] = useState(null) const [look, setLook] = useState<'classic' | 'handDrawn'>('classic') @@ -490,7 +493,7 @@ const Flowchart = React.forwardRef((props: { } return ( -
} className={themeClasses.container}> +
} className={themeClasses.container}>
) -}) +} Flowchart.displayName = 'Flowchart' diff --git a/web/app/components/base/textarea/index.tsx b/web/app/components/base/textarea/index.tsx index 43cc33d62e..8b01aa9b59 100644 --- a/web/app/components/base/textarea/index.tsx +++ b/web/app/components/base/textarea/index.tsx @@ -24,30 +24,29 @@ export type TextareaProps = { disabled?: boolean destructive?: boolean styleCss?: CSSProperties + ref?: React.Ref } & React.TextareaHTMLAttributes & VariantProps -const Textarea = React.forwardRef( - ({ className, value, onChange, disabled, size, destructive, styleCss, ...props }, ref) => { - return ( - - ) - }, -) +const Textarea = ({ className, value, onChange, disabled, size, destructive, styleCss, ref, ...props }: TextareaProps) => { + return ( + + ) +} Textarea.displayName = 'Textarea' export default Textarea diff --git a/web/app/components/datasets/preview/container.tsx b/web/app/components/datasets/preview/container.tsx index 69412e65a8..3be7aa6a0b 100644 --- a/web/app/components/datasets/preview/container.tsx +++ b/web/app/components/datasets/preview/container.tsx @@ -1,14 +1,14 @@ import type { ComponentProps, FC, ReactNode } from 'react' -import { forwardRef } from 'react' import classNames from '@/utils/classnames' export type PreviewContainerProps = ComponentProps<'div'> & { header: ReactNode mainClassName?: string + ref?: React.Ref } -export const PreviewContainer: FC = forwardRef((props, ref) => { - const { children, className, header, mainClassName, ...rest } = props +export const PreviewContainer: FC = (props) => { + const { children, className, header, mainClassName, ref, ...rest } = props return
= forwardRef((props, re
-}) +} PreviewContainer.displayName = 'PreviewContainer' diff --git a/web/app/components/plugins/install-plugin/install-bundle/steps/install-multi.tsx b/web/app/components/plugins/install-plugin/install-bundle/steps/install-multi.tsx index 2691877a07..57732653e3 100644 --- a/web/app/components/plugins/install-plugin/install-bundle/steps/install-multi.tsx +++ b/web/app/components/plugins/install-plugin/install-bundle/steps/install-multi.tsx @@ -1,5 +1,4 @@ 'use client' -import type { ForwardRefRenderFunction } from 'react' import { useImperativeHandle } from 'react' import React, { useCallback, useEffect, useMemo, useState } from 'react' import type { Dependency, GitHubItemAndMarketPlaceDependency, PackageDependency, Plugin, VersionInfo } from '../../../types' @@ -21,6 +20,7 @@ type Props = { onDeSelectAll: () => void onLoadedAllPlugin: (installedInfo: Record) => void isFromMarketPlace?: boolean + ref?: React.Ref } export type ExposeRefs = { @@ -28,7 +28,7 @@ export type ExposeRefs = { deSelectAllPlugins: () => void } -const InstallByDSLList: ForwardRefRenderFunction = ({ +const InstallByDSLList = ({ allPlugins, selectedPlugins, onSelect, @@ -36,7 +36,8 @@ const InstallByDSLList: ForwardRefRenderFunction = ({ onDeSelectAll, onLoadedAllPlugin, isFromMarketPlace, -}, ref) => { + ref, +}: Props) => { const systemFeatures = useGlobalPublicStore(s => s.systemFeatures) // DSL has id, to get plugin info to show more info const { isLoading: isFetchingMarketplaceDataById, data: infoGetById, error: infoByIdError } = useFetchPluginsInMarketPlaceByInfo(allPlugins.filter(d => d.type === 'marketplace').map((d) => { @@ -268,4 +269,4 @@ const InstallByDSLList: ForwardRefRenderFunction = ({ ) } -export default React.forwardRef(InstallByDSLList) +export default InstallByDSLList diff --git a/web/app/components/workflow/block-selector/market-place-plugin/list.tsx b/web/app/components/workflow/block-selector/market-place-plugin/list.tsx index 98b799adf4..49d7082832 100644 --- a/web/app/components/workflow/block-selector/market-place-plugin/list.tsx +++ b/web/app/components/workflow/block-selector/market-place-plugin/list.tsx @@ -1,5 +1,5 @@ 'use client' -import React, { forwardRef, useEffect, useImperativeHandle, useMemo, useRef } from 'react' +import React, { useEffect, useImperativeHandle, useMemo, useRef } from 'react' import { useTranslation } from 'react-i18next' import useStickyScroll, { ScrollPosition } from '../use-sticky-scroll' import Item from './item' @@ -17,18 +17,20 @@ export type ListProps = { tags: string[] toolContentClassName?: string disableMaxWidth?: boolean + ref?: React.Ref } export type ListRef = { handleScroll: () => void } -const List = forwardRef(({ +const List = ({ wrapElemRef, searchText, tags, list, toolContentClassName, disableMaxWidth = false, -}, ref) => { + ref, +}: ListProps) => { const { t } = useTranslation() const hasFilter = !searchText const hasRes = list.length > 0 @@ -125,7 +127,7 @@ const List = forwardRef(({
) -}) +} List.displayName = 'List' From 16a3e21410076f72ca067b50d4a7657de9e4214f Mon Sep 17 00:00:00 2001 From: Asuka Minato Date: Mon, 8 Sep 2025 10:59:43 +0900 Subject: [PATCH 46/52] more assert (#24996) Signed-off-by: -LAN- Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com> Co-authored-by: -LAN- Co-authored-by: crazywoola <100913391+crazywoola@users.noreply.github.com> --- api/controllers/console/billing/billing.py | 9 ++- api/services/agent_service.py | 5 +- api/services/annotation_service.py | 31 ++++++++- api/services/app_service.py | 10 ++- api/services/billing_service.py | 2 +- api/services/dataset_service.py | 49 +++++++++++++- api/services/file_service.py | 5 +- .../services/test_agent_service.py | 5 +- .../services/test_annotation_service.py | 7 +- .../services/test_app_service.py | 46 ++++++++++--- .../services/test_file_service.py | 29 ++++---- .../services/test_metadata_service.py | 6 +- .../services/test_tag_service.py | 4 +- .../services/test_website_service.py | 67 +++++++++++-------- .../test_dataset_service_update_dataset.py | 9 ++- .../services/test_metadata_bug_complete.py | 17 +++-- .../services/test_metadata_nullable_bug.py | 24 ++++--- 17 files changed, 235 insertions(+), 90 deletions(-) diff --git a/api/controllers/console/billing/billing.py b/api/controllers/console/billing/billing.py index 8ebb745a60..39fc7dec6b 100644 --- a/api/controllers/console/billing/billing.py +++ b/api/controllers/console/billing/billing.py @@ -1,9 +1,9 @@ -from flask_login import current_user from flask_restx import Resource, reqparse from controllers.console import api from controllers.console.wraps import account_initialization_required, only_edition_cloud, setup_required -from libs.login import login_required +from libs.login import current_user, login_required +from models.model import Account from services.billing_service import BillingService @@ -17,9 +17,10 @@ class Subscription(Resource): parser.add_argument("plan", type=str, required=True, location="args", choices=["professional", "team"]) parser.add_argument("interval", type=str, required=True, location="args", choices=["month", "year"]) args = parser.parse_args() + assert isinstance(current_user, Account) BillingService.is_tenant_owner_or_admin(current_user) - + assert current_user.current_tenant_id is not None return BillingService.get_subscription( args["plan"], args["interval"], current_user.email, current_user.current_tenant_id ) @@ -31,7 +32,9 @@ class Invoices(Resource): @account_initialization_required @only_edition_cloud def get(self): + assert isinstance(current_user, Account) BillingService.is_tenant_owner_or_admin(current_user) + assert current_user.current_tenant_id is not None return BillingService.get_invoices(current_user.email, current_user.current_tenant_id) diff --git a/api/services/agent_service.py b/api/services/agent_service.py index 76267a2fe1..8578f38a0d 100644 --- a/api/services/agent_service.py +++ b/api/services/agent_service.py @@ -2,7 +2,6 @@ import threading from typing import Any, Optional import pytz -from flask_login import current_user import contexts from core.app.app_config.easy_ui_based_app.agent.manager import AgentConfigManager @@ -10,6 +9,7 @@ from core.plugin.impl.agent import PluginAgentClient from core.plugin.impl.exc import PluginDaemonClientSideError from core.tools.tool_manager import ToolManager from extensions.ext_database import db +from libs.login import current_user from models.account import Account from models.model import App, Conversation, EndUser, Message, MessageAgentThought @@ -61,7 +61,8 @@ class AgentService: executor = executor.name else: executor = "Unknown" - + assert isinstance(current_user, Account) + assert current_user.timezone is not None timezone = pytz.timezone(current_user.timezone) app_model_config = app_model.app_model_config diff --git a/api/services/annotation_service.py b/api/services/annotation_service.py index 24567cc34c..ba86a31240 100644 --- a/api/services/annotation_service.py +++ b/api/services/annotation_service.py @@ -2,7 +2,6 @@ import uuid from typing import Optional import pandas as pd -from flask_login import current_user from sqlalchemy import or_, select from werkzeug.datastructures import FileStorage from werkzeug.exceptions import NotFound @@ -10,6 +9,8 @@ from werkzeug.exceptions import NotFound from extensions.ext_database import db from extensions.ext_redis import redis_client from libs.datetime_utils import naive_utc_now +from libs.login import current_user +from models.account import Account from models.model import App, AppAnnotationHitHistory, AppAnnotationSetting, Message, MessageAnnotation from services.feature_service import FeatureService from tasks.annotation.add_annotation_to_index_task import add_annotation_to_index_task @@ -24,6 +25,7 @@ class AppAnnotationService: @classmethod def up_insert_app_annotation_from_message(cls, args: dict, app_id: str) -> MessageAnnotation: # get app info + assert isinstance(current_user, Account) app = ( db.session.query(App) .where(App.id == app_id, App.tenant_id == current_user.current_tenant_id, App.status == "normal") @@ -62,6 +64,7 @@ class AppAnnotationService: db.session.commit() # if annotation reply is enabled , add annotation to index annotation_setting = db.session.query(AppAnnotationSetting).where(AppAnnotationSetting.app_id == app_id).first() + assert current_user.current_tenant_id is not None if annotation_setting: add_annotation_to_index_task.delay( annotation.id, @@ -84,6 +87,8 @@ class AppAnnotationService: enable_app_annotation_job_key = f"enable_app_annotation_job_{str(job_id)}" # send batch add segments task redis_client.setnx(enable_app_annotation_job_key, "waiting") + assert isinstance(current_user, Account) + assert current_user.current_tenant_id is not None enable_annotation_reply_task.delay( str(job_id), app_id, @@ -97,6 +102,8 @@ class AppAnnotationService: @classmethod def disable_app_annotation(cls, app_id: str): + assert isinstance(current_user, Account) + assert current_user.current_tenant_id is not None disable_app_annotation_key = f"disable_app_annotation_{str(app_id)}" cache_result = redis_client.get(disable_app_annotation_key) if cache_result is not None: @@ -113,6 +120,8 @@ class AppAnnotationService: @classmethod def get_annotation_list_by_app_id(cls, app_id: str, page: int, limit: int, keyword: str): # get app info + assert isinstance(current_user, Account) + assert current_user.current_tenant_id is not None app = ( db.session.query(App) .where(App.id == app_id, App.tenant_id == current_user.current_tenant_id, App.status == "normal") @@ -145,6 +154,8 @@ class AppAnnotationService: @classmethod def export_annotation_list_by_app_id(cls, app_id: str): # get app info + assert isinstance(current_user, Account) + assert current_user.current_tenant_id is not None app = ( db.session.query(App) .where(App.id == app_id, App.tenant_id == current_user.current_tenant_id, App.status == "normal") @@ -164,6 +175,8 @@ class AppAnnotationService: @classmethod def insert_app_annotation_directly(cls, args: dict, app_id: str) -> MessageAnnotation: # get app info + assert isinstance(current_user, Account) + assert current_user.current_tenant_id is not None app = ( db.session.query(App) .where(App.id == app_id, App.tenant_id == current_user.current_tenant_id, App.status == "normal") @@ -193,6 +206,8 @@ class AppAnnotationService: @classmethod def update_app_annotation_directly(cls, args: dict, app_id: str, annotation_id: str): # get app info + assert isinstance(current_user, Account) + assert current_user.current_tenant_id is not None app = ( db.session.query(App) .where(App.id == app_id, App.tenant_id == current_user.current_tenant_id, App.status == "normal") @@ -230,6 +245,8 @@ class AppAnnotationService: @classmethod def delete_app_annotation(cls, app_id: str, annotation_id: str): # get app info + assert isinstance(current_user, Account) + assert current_user.current_tenant_id is not None app = ( db.session.query(App) .where(App.id == app_id, App.tenant_id == current_user.current_tenant_id, App.status == "normal") @@ -269,6 +286,8 @@ class AppAnnotationService: @classmethod def delete_app_annotations_in_batch(cls, app_id: str, annotation_ids: list[str]): # get app info + assert isinstance(current_user, Account) + assert current_user.current_tenant_id is not None app = ( db.session.query(App) .where(App.id == app_id, App.tenant_id == current_user.current_tenant_id, App.status == "normal") @@ -317,6 +336,8 @@ class AppAnnotationService: @classmethod def batch_import_app_annotations(cls, app_id, file: FileStorage): # get app info + assert isinstance(current_user, Account) + assert current_user.current_tenant_id is not None app = ( db.session.query(App) .where(App.id == app_id, App.tenant_id == current_user.current_tenant_id, App.status == "normal") @@ -355,6 +376,8 @@ class AppAnnotationService: @classmethod def get_annotation_hit_histories(cls, app_id: str, annotation_id: str, page, limit): + assert isinstance(current_user, Account) + assert current_user.current_tenant_id is not None # get app info app = ( db.session.query(App) @@ -425,6 +448,8 @@ class AppAnnotationService: @classmethod def get_app_annotation_setting_by_app_id(cls, app_id: str): + assert isinstance(current_user, Account) + assert current_user.current_tenant_id is not None # get app info app = ( db.session.query(App) @@ -451,6 +476,8 @@ class AppAnnotationService: @classmethod def update_app_annotation_setting(cls, app_id: str, annotation_setting_id: str, args: dict): + assert isinstance(current_user, Account) + assert current_user.current_tenant_id is not None # get app info app = ( db.session.query(App) @@ -491,6 +518,8 @@ class AppAnnotationService: @classmethod def clear_all_annotations(cls, app_id: str): + assert isinstance(current_user, Account) + assert current_user.current_tenant_id is not None app = ( db.session.query(App) .where(App.id == app_id, App.tenant_id == current_user.current_tenant_id, App.status == "normal") diff --git a/api/services/app_service.py b/api/services/app_service.py index 09aab5f0c4..9b200a570d 100644 --- a/api/services/app_service.py +++ b/api/services/app_service.py @@ -2,7 +2,6 @@ import json import logging from typing import Optional, TypedDict, cast -from flask_login import current_user from flask_sqlalchemy.pagination import Pagination from configs import dify_config @@ -17,6 +16,7 @@ from core.tools.utils.configuration import ToolParameterConfigurationManager from events.app_event import app_was_created from extensions.ext_database import db from libs.datetime_utils import naive_utc_now +from libs.login import current_user from models.account import Account from models.model import App, AppMode, AppModelConfig, Site from models.tools import ApiToolProvider @@ -168,6 +168,8 @@ class AppService: """ Get App """ + assert isinstance(current_user, Account) + assert current_user.current_tenant_id is not None # get original app model config if app.mode == AppMode.AGENT_CHAT.value or app.is_agent: model_config = app.app_model_config @@ -242,6 +244,7 @@ class AppService: :param args: request args :return: App instance """ + assert current_user is not None app.name = args["name"] app.description = args["description"] app.icon_type = args["icon_type"] @@ -262,6 +265,7 @@ class AppService: :param name: new name :return: App instance """ + assert current_user is not None app.name = name app.updated_by = current_user.id app.updated_at = naive_utc_now() @@ -277,6 +281,7 @@ class AppService: :param icon_background: new icon_background :return: App instance """ + assert current_user is not None app.icon = icon app.icon_background = icon_background app.updated_by = current_user.id @@ -294,7 +299,7 @@ class AppService: """ if enable_site == app.enable_site: return app - + assert current_user is not None app.enable_site = enable_site app.updated_by = current_user.id app.updated_at = naive_utc_now() @@ -311,6 +316,7 @@ class AppService: """ if enable_api == app.enable_api: return app + assert current_user is not None app.enable_api = enable_api app.updated_by = current_user.id diff --git a/api/services/billing_service.py b/api/services/billing_service.py index 40d45af376..066bed3234 100644 --- a/api/services/billing_service.py +++ b/api/services/billing_service.py @@ -70,7 +70,7 @@ class BillingService: return response.json() @staticmethod - def is_tenant_owner_or_admin(current_user): + def is_tenant_owner_or_admin(current_user: Account): tenant_id = current_user.current_tenant_id join: Optional[TenantAccountJoin] = ( diff --git a/api/services/dataset_service.py b/api/services/dataset_service.py index c0c97fbd77..2b151f9a8e 100644 --- a/api/services/dataset_service.py +++ b/api/services/dataset_service.py @@ -8,7 +8,7 @@ import uuid from collections import Counter from typing import Any, Literal, Optional -from flask_login import current_user +import sqlalchemy as sa from sqlalchemy import exists, func, select from sqlalchemy.orm import Session from werkzeug.exceptions import NotFound @@ -27,6 +27,7 @@ from extensions.ext_database import db from extensions.ext_redis import redis_client from libs import helper from libs.datetime_utils import naive_utc_now +from libs.login import current_user from models.account import Account, TenantAccountRole from models.dataset import ( AppDatasetJoin, @@ -498,8 +499,11 @@ class DatasetService: data: Update data dictionary filtered_data: Filtered update data to modify """ + # assert isinstance(current_user, Account) and current_user.current_tenant_id is not None try: model_manager = ModelManager() + assert isinstance(current_user, Account) + assert current_user.current_tenant_id is not None embedding_model = model_manager.get_model_instance( tenant_id=current_user.current_tenant_id, provider=data["embedding_model_provider"], @@ -611,8 +615,12 @@ class DatasetService: data: Update data dictionary filtered_data: Filtered update data to modify """ + # assert isinstance(current_user, Account) and current_user.current_tenant_id is not None + model_manager = ModelManager() try: + assert isinstance(current_user, Account) + assert current_user.current_tenant_id is not None embedding_model = model_manager.get_model_instance( tenant_id=current_user.current_tenant_id, provider=data["embedding_model_provider"], @@ -720,6 +728,8 @@ class DatasetService: @staticmethod def get_dataset_auto_disable_logs(dataset_id: str): + assert isinstance(current_user, Account) + assert current_user.current_tenant_id is not None features = FeatureService.get_features(current_user.current_tenant_id) if not features.billing.enabled or features.billing.subscription.plan == "sandbox": return { @@ -924,6 +934,8 @@ class DocumentService: @staticmethod def get_batch_documents(dataset_id: str, batch: str) -> list[Document]: + assert isinstance(current_user, Account) + documents = ( db.session.query(Document) .where( @@ -983,6 +995,8 @@ class DocumentService: @staticmethod def rename_document(dataset_id: str, document_id: str, name: str) -> Document: + assert isinstance(current_user, Account) + dataset = DatasetService.get_dataset(dataset_id) if not dataset: raise ValueError("Dataset not found.") @@ -1012,6 +1026,7 @@ class DocumentService: if document.indexing_status not in {"waiting", "parsing", "cleaning", "splitting", "indexing"}: raise DocumentIndexingError() # update document to be paused + assert current_user is not None document.is_paused = True document.paused_by = current_user.id document.paused_at = naive_utc_now() @@ -1098,6 +1113,9 @@ class DocumentService: # check doc_form DatasetService.check_doc_form(dataset, knowledge_config.doc_form) # check document limit + assert isinstance(current_user, Account) + assert current_user.current_tenant_id is not None + features = FeatureService.get_features(current_user.current_tenant_id) if features.billing.enabled: @@ -1434,6 +1452,8 @@ class DocumentService: @staticmethod def get_tenant_documents_count(): + assert isinstance(current_user, Account) + documents_count = ( db.session.query(Document) .where( @@ -1454,6 +1474,8 @@ class DocumentService: dataset_process_rule: Optional[DatasetProcessRule] = None, created_from: str = "web", ): + assert isinstance(current_user, Account) + DatasetService.check_dataset_model_setting(dataset) document = DocumentService.get_document(dataset.id, document_data.original_document_id) if document is None: @@ -1513,7 +1535,7 @@ class DocumentService: data_source_binding = ( db.session.query(DataSourceOauthBinding) .where( - db.and_( + sa.and_( DataSourceOauthBinding.tenant_id == current_user.current_tenant_id, DataSourceOauthBinding.provider == "notion", DataSourceOauthBinding.disabled == False, @@ -1574,6 +1596,9 @@ class DocumentService: @staticmethod def save_document_without_dataset_id(tenant_id: str, knowledge_config: KnowledgeConfig, account: Account): + assert isinstance(current_user, Account) + assert current_user.current_tenant_id is not None + features = FeatureService.get_features(current_user.current_tenant_id) if features.billing.enabled: @@ -2013,6 +2038,9 @@ class SegmentService: @classmethod def create_segment(cls, args: dict, document: Document, dataset: Dataset): + assert isinstance(current_user, Account) + assert current_user.current_tenant_id is not None + content = args["content"] doc_id = str(uuid.uuid4()) segment_hash = helper.generate_text_hash(content) @@ -2075,6 +2103,9 @@ class SegmentService: @classmethod def multi_create_segment(cls, segments: list, document: Document, dataset: Dataset): + assert isinstance(current_user, Account) + assert current_user.current_tenant_id is not None + lock_name = f"multi_add_segment_lock_document_id_{document.id}" increment_word_count = 0 with redis_client.lock(lock_name, timeout=600): @@ -2158,6 +2189,9 @@ class SegmentService: @classmethod def update_segment(cls, args: SegmentUpdateArgs, segment: DocumentSegment, document: Document, dataset: Dataset): + assert isinstance(current_user, Account) + assert current_user.current_tenant_id is not None + indexing_cache_key = f"segment_{segment.id}_indexing" cache_result = redis_client.get(indexing_cache_key) if cache_result is not None: @@ -2349,6 +2383,7 @@ class SegmentService: @classmethod def delete_segments(cls, segment_ids: list, document: Document, dataset: Dataset): + assert isinstance(current_user, Account) segments = ( db.session.query(DocumentSegment.index_node_id, DocumentSegment.word_count) .where( @@ -2379,6 +2414,8 @@ class SegmentService: def update_segments_status( cls, segment_ids: list, action: Literal["enable", "disable"], dataset: Dataset, document: Document ): + assert current_user is not None + # Check if segment_ids is not empty to avoid WHERE false condition if not segment_ids or len(segment_ids) == 0: return @@ -2441,6 +2478,8 @@ class SegmentService: def create_child_chunk( cls, content: str, segment: DocumentSegment, document: Document, dataset: Dataset ) -> ChildChunk: + assert isinstance(current_user, Account) + lock_name = f"add_child_lock_{segment.id}" with redis_client.lock(lock_name, timeout=20): index_node_id = str(uuid.uuid4()) @@ -2488,6 +2527,8 @@ class SegmentService: document: Document, dataset: Dataset, ) -> list[ChildChunk]: + assert isinstance(current_user, Account) + child_chunks = ( db.session.query(ChildChunk) .where( @@ -2562,6 +2603,8 @@ class SegmentService: document: Document, dataset: Dataset, ) -> ChildChunk: + assert current_user is not None + try: child_chunk.content = content child_chunk.word_count = len(content) @@ -2592,6 +2635,8 @@ class SegmentService: def get_child_chunks( cls, segment_id: str, document_id: str, dataset_id: str, page: int, limit: int, keyword: Optional[str] = None ): + assert isinstance(current_user, Account) + query = ( select(ChildChunk) .filter_by( diff --git a/api/services/file_service.py b/api/services/file_service.py index 4c0a0f451c..8a4655d25e 100644 --- a/api/services/file_service.py +++ b/api/services/file_service.py @@ -3,7 +3,6 @@ import os import uuid from typing import Any, Literal, Union -from flask_login import current_user from werkzeug.exceptions import NotFound from configs import dify_config @@ -19,6 +18,7 @@ from extensions.ext_database import db from extensions.ext_storage import storage from libs.datetime_utils import naive_utc_now from libs.helper import extract_tenant_id +from libs.login import current_user from models.account import Account from models.enums import CreatorUserRole from models.model import EndUser, UploadFile @@ -111,6 +111,9 @@ class FileService: @staticmethod def upload_text(text: str, text_name: str) -> UploadFile: + assert isinstance(current_user, Account) + assert current_user.current_tenant_id is not None + if len(text_name) > 200: text_name = text_name[:200] # user uuid as file name diff --git a/api/tests/test_containers_integration_tests/services/test_agent_service.py b/api/tests/test_containers_integration_tests/services/test_agent_service.py index d63b188b12..c572ddc925 100644 --- a/api/tests/test_containers_integration_tests/services/test_agent_service.py +++ b/api/tests/test_containers_integration_tests/services/test_agent_service.py @@ -1,10 +1,11 @@ import json -from unittest.mock import MagicMock, patch +from unittest.mock import MagicMock, create_autospec, patch import pytest from faker import Faker from core.plugin.impl.exc import PluginDaemonClientSideError +from models.account import Account from models.model import AppModelConfig, Conversation, EndUser, Message, MessageAgentThought from services.account_service import AccountService, TenantService from services.agent_service import AgentService @@ -21,7 +22,7 @@ class TestAgentService: patch("services.agent_service.PluginAgentClient") as mock_plugin_agent_client, patch("services.agent_service.ToolManager") as mock_tool_manager, patch("services.agent_service.AgentConfigManager") as mock_agent_config_manager, - patch("services.agent_service.current_user") as mock_current_user, + patch("services.agent_service.current_user", create_autospec(Account, instance=True)) as mock_current_user, patch("services.app_service.FeatureService") as mock_feature_service, patch("services.app_service.EnterpriseService") as mock_enterprise_service, patch("services.app_service.ModelManager") as mock_model_manager, diff --git a/api/tests/test_containers_integration_tests/services/test_annotation_service.py b/api/tests/test_containers_integration_tests/services/test_annotation_service.py index 4184420880..3cb7424df8 100644 --- a/api/tests/test_containers_integration_tests/services/test_annotation_service.py +++ b/api/tests/test_containers_integration_tests/services/test_annotation_service.py @@ -1,9 +1,10 @@ -from unittest.mock import patch +from unittest.mock import create_autospec, patch import pytest from faker import Faker from werkzeug.exceptions import NotFound +from models.account import Account from models.model import MessageAnnotation from services.annotation_service import AppAnnotationService from services.app_service import AppService @@ -24,7 +25,9 @@ class TestAnnotationService: patch("services.annotation_service.enable_annotation_reply_task") as mock_enable_task, patch("services.annotation_service.disable_annotation_reply_task") as mock_disable_task, patch("services.annotation_service.batch_import_annotations_task") as mock_batch_import_task, - patch("services.annotation_service.current_user") as mock_current_user, + patch( + "services.annotation_service.current_user", create_autospec(Account, instance=True) + ) as mock_current_user, ): # Setup default mock returns mock_account_feature_service.get_features.return_value.billing.enabled = False diff --git a/api/tests/test_containers_integration_tests/services/test_app_service.py b/api/tests/test_containers_integration_tests/services/test_app_service.py index 69cd9fafee..cbbbbddb21 100644 --- a/api/tests/test_containers_integration_tests/services/test_app_service.py +++ b/api/tests/test_containers_integration_tests/services/test_app_service.py @@ -1,9 +1,10 @@ -from unittest.mock import patch +from unittest.mock import create_autospec, patch import pytest from faker import Faker from constants.model_template import default_app_templates +from models.account import Account from models.model import App, Site from services.account_service import AccountService, TenantService from services.app_service import AppService @@ -161,8 +162,13 @@ class TestAppService: app_service = AppService() created_app = app_service.create_app(tenant.id, app_args, account) - # Get app using the service - retrieved_app = app_service.get_app(created_app) + # Get app using the service - needs current_user mock + mock_current_user = create_autospec(Account, instance=True) + mock_current_user.id = account.id + mock_current_user.current_tenant_id = account.current_tenant_id + + with patch("services.app_service.current_user", mock_current_user): + retrieved_app = app_service.get_app(created_app) # Verify retrieved app matches created app assert retrieved_app.id == created_app.id @@ -406,7 +412,11 @@ class TestAppService: "use_icon_as_answer_icon": True, } - with patch("flask_login.utils._get_user", return_value=account): + mock_current_user = create_autospec(Account, instance=True) + mock_current_user.id = account.id + mock_current_user.current_tenant_id = account.current_tenant_id + + with patch("services.app_service.current_user", mock_current_user): updated_app = app_service.update_app(app, update_args) # Verify updated fields @@ -456,7 +466,11 @@ class TestAppService: # Update app name new_name = "New App Name" - with patch("flask_login.utils._get_user", return_value=account): + mock_current_user = create_autospec(Account, instance=True) + mock_current_user.id = account.id + mock_current_user.current_tenant_id = account.current_tenant_id + + with patch("services.app_service.current_user", mock_current_user): updated_app = app_service.update_app_name(app, new_name) assert updated_app.name == new_name @@ -504,7 +518,11 @@ class TestAppService: # Update app icon new_icon = "🌟" new_icon_background = "#FFD93D" - with patch("flask_login.utils._get_user", return_value=account): + mock_current_user = create_autospec(Account, instance=True) + mock_current_user.id = account.id + mock_current_user.current_tenant_id = account.current_tenant_id + + with patch("services.app_service.current_user", mock_current_user): updated_app = app_service.update_app_icon(app, new_icon, new_icon_background) assert updated_app.icon == new_icon @@ -551,13 +569,17 @@ class TestAppService: original_site_status = app.enable_site # Update site status to disabled - with patch("flask_login.utils._get_user", return_value=account): + mock_current_user = create_autospec(Account, instance=True) + mock_current_user.id = account.id + mock_current_user.current_tenant_id = account.current_tenant_id + + with patch("services.app_service.current_user", mock_current_user): updated_app = app_service.update_app_site_status(app, False) assert updated_app.enable_site is False assert updated_app.updated_by == account.id # Update site status back to enabled - with patch("flask_login.utils._get_user", return_value=account): + with patch("services.app_service.current_user", mock_current_user): updated_app = app_service.update_app_site_status(updated_app, True) assert updated_app.enable_site is True assert updated_app.updated_by == account.id @@ -602,13 +624,17 @@ class TestAppService: original_api_status = app.enable_api # Update API status to disabled - with patch("flask_login.utils._get_user", return_value=account): + mock_current_user = create_autospec(Account, instance=True) + mock_current_user.id = account.id + mock_current_user.current_tenant_id = account.current_tenant_id + + with patch("services.app_service.current_user", mock_current_user): updated_app = app_service.update_app_api_status(app, False) assert updated_app.enable_api is False assert updated_app.updated_by == account.id # Update API status back to enabled - with patch("flask_login.utils._get_user", return_value=account): + with patch("services.app_service.current_user", mock_current_user): updated_app = app_service.update_app_api_status(updated_app, True) assert updated_app.enable_api is True assert updated_app.updated_by == account.id diff --git a/api/tests/test_containers_integration_tests/services/test_file_service.py b/api/tests/test_containers_integration_tests/services/test_file_service.py index 965c9c6242..5e5e680a5d 100644 --- a/api/tests/test_containers_integration_tests/services/test_file_service.py +++ b/api/tests/test_containers_integration_tests/services/test_file_service.py @@ -1,6 +1,6 @@ import hashlib from io import BytesIO -from unittest.mock import patch +from unittest.mock import create_autospec, patch import pytest from faker import Faker @@ -417,11 +417,12 @@ class TestFileService: text = "This is a test text content" text_name = "test_text.txt" - # Mock current_user - with patch("services.file_service.current_user") as mock_current_user: - mock_current_user.current_tenant_id = str(fake.uuid4()) - mock_current_user.id = str(fake.uuid4()) + # Mock current_user using create_autospec + mock_current_user = create_autospec(Account, instance=True) + mock_current_user.current_tenant_id = str(fake.uuid4()) + mock_current_user.id = str(fake.uuid4()) + with patch("services.file_service.current_user", mock_current_user): upload_file = FileService.upload_text(text=text, text_name=text_name) assert upload_file is not None @@ -443,11 +444,12 @@ class TestFileService: text = "test content" long_name = "a" * 250 # Longer than 200 characters - # Mock current_user - with patch("services.file_service.current_user") as mock_current_user: - mock_current_user.current_tenant_id = str(fake.uuid4()) - mock_current_user.id = str(fake.uuid4()) + # Mock current_user using create_autospec + mock_current_user = create_autospec(Account, instance=True) + mock_current_user.current_tenant_id = str(fake.uuid4()) + mock_current_user.id = str(fake.uuid4()) + with patch("services.file_service.current_user", mock_current_user): upload_file = FileService.upload_text(text=text, text_name=long_name) # Verify name was truncated @@ -846,11 +848,12 @@ class TestFileService: text = "" text_name = "empty.txt" - # Mock current_user - with patch("services.file_service.current_user") as mock_current_user: - mock_current_user.current_tenant_id = str(fake.uuid4()) - mock_current_user.id = str(fake.uuid4()) + # Mock current_user using create_autospec + mock_current_user = create_autospec(Account, instance=True) + mock_current_user.current_tenant_id = str(fake.uuid4()) + mock_current_user.id = str(fake.uuid4()) + with patch("services.file_service.current_user", mock_current_user): upload_file = FileService.upload_text(text=text, text_name=text_name) assert upload_file is not None diff --git a/api/tests/test_containers_integration_tests/services/test_metadata_service.py b/api/tests/test_containers_integration_tests/services/test_metadata_service.py index 7fef572c14..4646531a4e 100644 --- a/api/tests/test_containers_integration_tests/services/test_metadata_service.py +++ b/api/tests/test_containers_integration_tests/services/test_metadata_service.py @@ -1,4 +1,4 @@ -from unittest.mock import patch +from unittest.mock import create_autospec, patch import pytest from faker import Faker @@ -17,7 +17,9 @@ class TestMetadataService: def mock_external_service_dependencies(self): """Mock setup for external service dependencies.""" with ( - patch("services.metadata_service.current_user") as mock_current_user, + patch( + "services.metadata_service.current_user", create_autospec(Account, instance=True) + ) as mock_current_user, patch("services.metadata_service.redis_client") as mock_redis_client, patch("services.dataset_service.DocumentService") as mock_document_service, ): diff --git a/api/tests/test_containers_integration_tests/services/test_tag_service.py b/api/tests/test_containers_integration_tests/services/test_tag_service.py index 2d5cdf426d..d09a4a17ab 100644 --- a/api/tests/test_containers_integration_tests/services/test_tag_service.py +++ b/api/tests/test_containers_integration_tests/services/test_tag_service.py @@ -1,4 +1,4 @@ -from unittest.mock import patch +from unittest.mock import create_autospec, patch import pytest from faker import Faker @@ -17,7 +17,7 @@ class TestTagService: def mock_external_service_dependencies(self): """Mock setup for external service dependencies.""" with ( - patch("services.tag_service.current_user") as mock_current_user, + patch("services.tag_service.current_user", create_autospec(Account, instance=True)) as mock_current_user, ): # Setup default mock returns mock_current_user.current_tenant_id = "test-tenant-id" diff --git a/api/tests/test_containers_integration_tests/services/test_website_service.py b/api/tests/test_containers_integration_tests/services/test_website_service.py index ec2f1556af..5ac9ce820a 100644 --- a/api/tests/test_containers_integration_tests/services/test_website_service.py +++ b/api/tests/test_containers_integration_tests/services/test_website_service.py @@ -1,5 +1,5 @@ from datetime import datetime -from unittest.mock import MagicMock, patch +from unittest.mock import MagicMock, create_autospec, patch import pytest from faker import Faker @@ -231,9 +231,10 @@ class TestWebsiteService: fake = Faker() # Mock current_user for the test - with patch("services.website_service.current_user") as mock_current_user: - mock_current_user.current_tenant_id = account.current_tenant.id + mock_current_user = create_autospec(Account, instance=True) + mock_current_user.current_tenant_id = account.current_tenant.id + with patch("services.website_service.current_user", mock_current_user): # Create API request api_request = WebsiteCrawlApiRequest( provider="firecrawl", @@ -285,9 +286,10 @@ class TestWebsiteService: account = self._create_test_account(db_session_with_containers, mock_external_service_dependencies) # Mock current_user for the test - with patch("services.website_service.current_user") as mock_current_user: - mock_current_user.current_tenant_id = account.current_tenant.id + mock_current_user = create_autospec(Account, instance=True) + mock_current_user.current_tenant_id = account.current_tenant.id + with patch("services.website_service.current_user", mock_current_user): # Create API request api_request = WebsiteCrawlApiRequest( provider="watercrawl", @@ -336,9 +338,10 @@ class TestWebsiteService: account = self._create_test_account(db_session_with_containers, mock_external_service_dependencies) # Mock current_user for the test - with patch("services.website_service.current_user") as mock_current_user: - mock_current_user.current_tenant_id = account.current_tenant.id + mock_current_user = create_autospec(Account, instance=True) + mock_current_user.current_tenant_id = account.current_tenant.id + with patch("services.website_service.current_user", mock_current_user): # Create API request for single page crawling api_request = WebsiteCrawlApiRequest( provider="jinareader", @@ -389,9 +392,10 @@ class TestWebsiteService: account = self._create_test_account(db_session_with_containers, mock_external_service_dependencies) # Mock current_user for the test - with patch("services.website_service.current_user") as mock_current_user: - mock_current_user.current_tenant_id = account.current_tenant.id + mock_current_user = create_autospec(Account, instance=True) + mock_current_user.current_tenant_id = account.current_tenant.id + with patch("services.website_service.current_user", mock_current_user): # Create API request with invalid provider api_request = WebsiteCrawlApiRequest( provider="invalid_provider", @@ -419,9 +423,10 @@ class TestWebsiteService: account = self._create_test_account(db_session_with_containers, mock_external_service_dependencies) # Mock current_user for the test - with patch("services.website_service.current_user") as mock_current_user: - mock_current_user.current_tenant_id = account.current_tenant.id + mock_current_user = create_autospec(Account, instance=True) + mock_current_user.current_tenant_id = account.current_tenant.id + with patch("services.website_service.current_user", mock_current_user): # Create API request api_request = WebsiteCrawlStatusApiRequest(provider="firecrawl", job_id="test_job_id_123") @@ -463,9 +468,10 @@ class TestWebsiteService: account = self._create_test_account(db_session_with_containers, mock_external_service_dependencies) # Mock current_user for the test - with patch("services.website_service.current_user") as mock_current_user: - mock_current_user.current_tenant_id = account.current_tenant.id + mock_current_user = create_autospec(Account, instance=True) + mock_current_user.current_tenant_id = account.current_tenant.id + with patch("services.website_service.current_user", mock_current_user): # Create API request api_request = WebsiteCrawlStatusApiRequest(provider="watercrawl", job_id="watercrawl_job_123") @@ -502,9 +508,10 @@ class TestWebsiteService: account = self._create_test_account(db_session_with_containers, mock_external_service_dependencies) # Mock current_user for the test - with patch("services.website_service.current_user") as mock_current_user: - mock_current_user.current_tenant_id = account.current_tenant.id + mock_current_user = create_autospec(Account, instance=True) + mock_current_user.current_tenant_id = account.current_tenant.id + with patch("services.website_service.current_user", mock_current_user): # Create API request api_request = WebsiteCrawlStatusApiRequest(provider="jinareader", job_id="jina_job_123") @@ -544,9 +551,10 @@ class TestWebsiteService: account = self._create_test_account(db_session_with_containers, mock_external_service_dependencies) # Mock current_user for the test - with patch("services.website_service.current_user") as mock_current_user: - mock_current_user.current_tenant_id = account.current_tenant.id + mock_current_user = create_autospec(Account, instance=True) + mock_current_user.current_tenant_id = account.current_tenant.id + with patch("services.website_service.current_user", mock_current_user): # Create API request with invalid provider api_request = WebsiteCrawlStatusApiRequest(provider="invalid_provider", job_id="test_job_id_123") @@ -569,9 +577,10 @@ class TestWebsiteService: account = self._create_test_account(db_session_with_containers, mock_external_service_dependencies) # Mock current_user for the test - with patch("services.website_service.current_user") as mock_current_user: - mock_current_user.current_tenant_id = account.current_tenant.id + mock_current_user = create_autospec(Account, instance=True) + mock_current_user.current_tenant_id = account.current_tenant.id + with patch("services.website_service.current_user", mock_current_user): # Mock missing credentials mock_external_service_dependencies["api_key_auth_service"].get_auth_credentials.return_value = None @@ -597,9 +606,10 @@ class TestWebsiteService: account = self._create_test_account(db_session_with_containers, mock_external_service_dependencies) # Mock current_user for the test - with patch("services.website_service.current_user") as mock_current_user: - mock_current_user.current_tenant_id = account.current_tenant.id + mock_current_user = create_autospec(Account, instance=True) + mock_current_user.current_tenant_id = account.current_tenant.id + with patch("services.website_service.current_user", mock_current_user): # Mock missing API key in config mock_external_service_dependencies["api_key_auth_service"].get_auth_credentials.return_value = { "config": {"base_url": "https://api.example.com"} @@ -995,9 +1005,10 @@ class TestWebsiteService: account = self._create_test_account(db_session_with_containers, mock_external_service_dependencies) # Mock current_user for the test - with patch("services.website_service.current_user") as mock_current_user: - mock_current_user.current_tenant_id = account.current_tenant.id + mock_current_user = create_autospec(Account, instance=True) + mock_current_user.current_tenant_id = account.current_tenant.id + with patch("services.website_service.current_user", mock_current_user): # Create API request for sub-page crawling api_request = WebsiteCrawlApiRequest( provider="jinareader", @@ -1054,9 +1065,10 @@ class TestWebsiteService: mock_external_service_dependencies["requests"].get.return_value = mock_failed_response # Mock current_user for the test - with patch("services.website_service.current_user") as mock_current_user: - mock_current_user.current_tenant_id = account.current_tenant.id + mock_current_user = create_autospec(Account, instance=True) + mock_current_user.current_tenant_id = account.current_tenant.id + with patch("services.website_service.current_user", mock_current_user): # Create API request api_request = WebsiteCrawlApiRequest( provider="jinareader", @@ -1096,9 +1108,10 @@ class TestWebsiteService: mock_external_service_dependencies["firecrawl_app"].return_value = mock_firecrawl_instance # Mock current_user for the test - with patch("services.website_service.current_user") as mock_current_user: - mock_current_user.current_tenant_id = account.current_tenant.id + mock_current_user = create_autospec(Account, instance=True) + mock_current_user.current_tenant_id = account.current_tenant.id + with patch("services.website_service.current_user", mock_current_user): # Create API request api_request = WebsiteCrawlStatusApiRequest(provider="firecrawl", job_id="active_job_123") diff --git a/api/tests/unit_tests/services/test_dataset_service_update_dataset.py b/api/tests/unit_tests/services/test_dataset_service_update_dataset.py index 7c40b1e556..fb23863043 100644 --- a/api/tests/unit_tests/services/test_dataset_service_update_dataset.py +++ b/api/tests/unit_tests/services/test_dataset_service_update_dataset.py @@ -2,11 +2,12 @@ import datetime from typing import Any, Optional # Mock redis_client before importing dataset_service -from unittest.mock import Mock, patch +from unittest.mock import Mock, create_autospec, patch import pytest from core.model_runtime.entities.model_entities import ModelType +from models.account import Account from models.dataset import Dataset, ExternalKnowledgeBindings from services.dataset_service import DatasetService from services.errors.account import NoPermissionError @@ -78,7 +79,7 @@ class DatasetUpdateTestDataFactory: @staticmethod def create_current_user_mock(tenant_id: str = "tenant-123") -> Mock: """Create a mock current user.""" - current_user = Mock() + current_user = create_autospec(Account, instance=True) current_user.current_tenant_id = tenant_id return current_user @@ -135,7 +136,9 @@ class TestDatasetServiceUpdateDataset: "services.dataset_service.DatasetCollectionBindingService.get_dataset_collection_binding" ) as mock_get_binding, patch("services.dataset_service.deal_dataset_vector_index_task") as mock_task, - patch("services.dataset_service.current_user") as mock_current_user, + patch( + "services.dataset_service.current_user", create_autospec(Account, instance=True) + ) as mock_current_user, ): mock_current_user.current_tenant_id = "tenant-123" yield { diff --git a/api/tests/unit_tests/services/test_metadata_bug_complete.py b/api/tests/unit_tests/services/test_metadata_bug_complete.py index 0fc36510b9..ad65175e89 100644 --- a/api/tests/unit_tests/services/test_metadata_bug_complete.py +++ b/api/tests/unit_tests/services/test_metadata_bug_complete.py @@ -1,9 +1,10 @@ -from unittest.mock import Mock, patch +from unittest.mock import Mock, create_autospec, patch import pytest from flask_restx import reqparse from werkzeug.exceptions import BadRequest +from models.account import Account from services.entities.knowledge_entities.knowledge_entities import MetadataArgs from services.metadata_service import MetadataService @@ -35,19 +36,21 @@ class TestMetadataBugCompleteValidation: mock_metadata_args.name = None mock_metadata_args.type = "string" - with patch("services.metadata_service.current_user") as mock_user: - mock_user.current_tenant_id = "tenant-123" - mock_user.id = "user-456" + mock_user = create_autospec(Account, instance=True) + mock_user.current_tenant_id = "tenant-123" + mock_user.id = "user-456" + with patch("services.metadata_service.current_user", mock_user): # Should crash with TypeError with pytest.raises(TypeError, match="object of type 'NoneType' has no len"): MetadataService.create_metadata("dataset-123", mock_metadata_args) # Test update method as well - with patch("services.metadata_service.current_user") as mock_user: - mock_user.current_tenant_id = "tenant-123" - mock_user.id = "user-456" + mock_user = create_autospec(Account, instance=True) + mock_user.current_tenant_id = "tenant-123" + mock_user.id = "user-456" + with patch("services.metadata_service.current_user", mock_user): with pytest.raises(TypeError, match="object of type 'NoneType' has no len"): MetadataService.update_metadata_name("dataset-123", "metadata-456", None) diff --git a/api/tests/unit_tests/services/test_metadata_nullable_bug.py b/api/tests/unit_tests/services/test_metadata_nullable_bug.py index 7f6344f942..d151100cf3 100644 --- a/api/tests/unit_tests/services/test_metadata_nullable_bug.py +++ b/api/tests/unit_tests/services/test_metadata_nullable_bug.py @@ -1,8 +1,9 @@ -from unittest.mock import Mock, patch +from unittest.mock import Mock, create_autospec, patch import pytest from flask_restx import reqparse +from models.account import Account from services.entities.knowledge_entities.knowledge_entities import MetadataArgs from services.metadata_service import MetadataService @@ -24,20 +25,22 @@ class TestMetadataNullableBug: mock_metadata_args.name = None # This will cause len() to crash mock_metadata_args.type = "string" - with patch("services.metadata_service.current_user") as mock_user: - mock_user.current_tenant_id = "tenant-123" - mock_user.id = "user-456" + mock_user = create_autospec(Account, instance=True) + mock_user.current_tenant_id = "tenant-123" + mock_user.id = "user-456" + with patch("services.metadata_service.current_user", mock_user): # This should crash with TypeError when calling len(None) with pytest.raises(TypeError, match="object of type 'NoneType' has no len"): MetadataService.create_metadata("dataset-123", mock_metadata_args) def test_metadata_service_update_with_none_name_crashes(self): """Test that MetadataService.update_metadata_name crashes when name is None.""" - with patch("services.metadata_service.current_user") as mock_user: - mock_user.current_tenant_id = "tenant-123" - mock_user.id = "user-456" + mock_user = create_autospec(Account, instance=True) + mock_user.current_tenant_id = "tenant-123" + mock_user.id = "user-456" + with patch("services.metadata_service.current_user", mock_user): # This should crash with TypeError when calling len(None) with pytest.raises(TypeError, match="object of type 'NoneType' has no len"): MetadataService.update_metadata_name("dataset-123", "metadata-456", None) @@ -81,10 +84,11 @@ class TestMetadataNullableBug: mock_metadata_args.name = None # From args["name"] mock_metadata_args.type = None # From args["type"] - with patch("services.metadata_service.current_user") as mock_user: - mock_user.current_tenant_id = "tenant-123" - mock_user.id = "user-456" + mock_user = create_autospec(Account, instance=True) + mock_user.current_tenant_id = "tenant-123" + mock_user.id = "user-456" + with patch("services.metadata_service.current_user", mock_user): # Step 4: Service layer crashes on len(None) with pytest.raises(TypeError, match="object of type 'NoneType' has no len"): MetadataService.create_metadata("dataset-123", mock_metadata_args) From 593f7989b87b02cfe47a311d12aea6e3c38ba93f Mon Sep 17 00:00:00 2001 From: qxo <49526356@qq.com> Date: Mon, 8 Sep 2025 09:59:53 +0800 Subject: [PATCH 47/52] fix: 'curr_message_tokens' where it is not associated with a value #25307 (#25308) Co-authored-by: crazywoola <100913391+crazywoola@users.noreply.github.com> Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com> --- api/core/memory/token_buffer_memory.py | 1 + 1 file changed, 1 insertion(+) diff --git a/api/core/memory/token_buffer_memory.py b/api/core/memory/token_buffer_memory.py index f2178b0270..7be695812a 100644 --- a/api/core/memory/token_buffer_memory.py +++ b/api/core/memory/token_buffer_memory.py @@ -124,6 +124,7 @@ class TokenBufferMemory: messages = list(reversed(thread_messages)) + curr_message_tokens = 0 prompt_messages: list[PromptMessage] = [] for message in messages: # Process user message with files From 3d16767fb374f220dce1955019fc74bfcb454a63 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Mon, 8 Sep 2025 10:05:25 +0800 Subject: [PATCH 48/52] chore: translate i18n files and update type definitions (#25334) Co-authored-by: crazywoola <100913391+crazywoola@users.noreply.github.com> --- web/i18n/de-DE/workflow.ts | 4 ++++ web/i18n/es-ES/workflow.ts | 4 ++++ web/i18n/fa-IR/workflow.ts | 4 ++++ web/i18n/fr-FR/workflow.ts | 4 ++++ web/i18n/hi-IN/workflow.ts | 4 ++++ web/i18n/id-ID/workflow.ts | 4 ++++ web/i18n/it-IT/workflow.ts | 4 ++++ web/i18n/ko-KR/workflow.ts | 4 ++++ web/i18n/pl-PL/workflow.ts | 4 ++++ web/i18n/pt-BR/workflow.ts | 4 ++++ web/i18n/ro-RO/workflow.ts | 4 ++++ web/i18n/ru-RU/workflow.ts | 4 ++++ web/i18n/sl-SI/workflow.ts | 4 ++++ web/i18n/th-TH/workflow.ts | 4 ++++ web/i18n/tr-TR/workflow.ts | 4 ++++ web/i18n/uk-UA/workflow.ts | 4 ++++ web/i18n/vi-VN/workflow.ts | 4 ++++ web/i18n/zh-Hant/workflow.ts | 4 ++++ 18 files changed, 72 insertions(+) diff --git a/web/i18n/de-DE/workflow.ts b/web/i18n/de-DE/workflow.ts index 576afc2af1..03c90c04ac 100644 --- a/web/i18n/de-DE/workflow.ts +++ b/web/i18n/de-DE/workflow.ts @@ -1004,6 +1004,10 @@ const translation = { noLastRunFound: 'Kein vorheriger Lauf gefunden', lastOutput: 'Letzte Ausgabe', }, + sidebar: { + exportWarning: 'Aktuelle gespeicherte Version exportieren', + exportWarningDesc: 'Dies wird die derzeit gespeicherte Version Ihres Workflows exportieren. Wenn Sie ungespeicherte Änderungen im Editor haben, speichern Sie diese bitte zuerst, indem Sie die Exportoption im Workflow-Canvas verwenden.', + }, } export default translation diff --git a/web/i18n/es-ES/workflow.ts b/web/i18n/es-ES/workflow.ts index 238eb016ad..87260c7104 100644 --- a/web/i18n/es-ES/workflow.ts +++ b/web/i18n/es-ES/workflow.ts @@ -1004,6 +1004,10 @@ const translation = { noMatchingInputsFound: 'No se encontraron entradas coincidentes de la última ejecución.', lastOutput: 'Última salida', }, + sidebar: { + exportWarning: 'Exportar la versión guardada actual', + exportWarningDesc: 'Esto exportará la versión guardada actual de tu flujo de trabajo. Si tienes cambios no guardados en el editor, guárdalos primero utilizando la opción de exportar en el lienzo del flujo de trabajo.', + }, } export default translation diff --git a/web/i18n/fa-IR/workflow.ts b/web/i18n/fa-IR/workflow.ts index 1a2d9aa227..d2fa3391ee 100644 --- a/web/i18n/fa-IR/workflow.ts +++ b/web/i18n/fa-IR/workflow.ts @@ -1004,6 +1004,10 @@ const translation = { copyLastRunError: 'نتوانستم ورودی‌های آخرین اجرای را کپی کنم', lastOutput: 'آخرین خروجی', }, + sidebar: { + exportWarning: 'صادرات نسخه ذخیره شده فعلی', + exportWarningDesc: 'این نسخه فعلی ذخیره شده از کار خود را صادر خواهد کرد. اگر تغییرات غیرذخیره شده‌ای در ویرایشگر دارید، لطفاً ابتدا از گزینه صادرات در بوم کار برای ذخیره آنها استفاده کنید.', + }, } export default translation diff --git a/web/i18n/fr-FR/workflow.ts b/web/i18n/fr-FR/workflow.ts index c2eb056198..22f3229b89 100644 --- a/web/i18n/fr-FR/workflow.ts +++ b/web/i18n/fr-FR/workflow.ts @@ -1004,6 +1004,10 @@ const translation = { copyLastRunError: 'Échec de la copie des entrées de la dernière exécution', lastOutput: 'Dernière sortie', }, + sidebar: { + exportWarning: 'Exporter la version enregistrée actuelle', + exportWarningDesc: 'Cela exportera la version actuelle enregistrée de votre flux de travail. Si vous avez des modifications non enregistrées dans l\'éditeur, veuillez d\'abord les enregistrer en utilisant l\'option d\'exportation dans le canevas du flux de travail.', + }, } export default translation diff --git a/web/i18n/hi-IN/workflow.ts b/web/i18n/hi-IN/workflow.ts index 8df3e4b745..19145784ba 100644 --- a/web/i18n/hi-IN/workflow.ts +++ b/web/i18n/hi-IN/workflow.ts @@ -1024,6 +1024,10 @@ const translation = { copyLastRunError: 'अंतिम रन इनपुट को कॉपी करने में विफल', lastOutput: 'अंतिम आउटपुट', }, + sidebar: { + exportWarning: 'वर्तमान सहेजी गई संस्करण निर्यात करें', + exportWarningDesc: 'यह आपके कार्यप्रवाह का वर्तमान सहेजा हुआ संस्करण निर्यात करेगा। यदि आपके संपादक में कोई असहेजा किए गए परिवर्तन हैं, तो कृपया पहले उन्हें सहेजें, कार्यप्रवाह कैनवास में निर्यात विकल्प का उपयोग करके।', + }, } export default translation diff --git a/web/i18n/id-ID/workflow.ts b/web/i18n/id-ID/workflow.ts index 9da16bc94e..e1fd9162a8 100644 --- a/web/i18n/id-ID/workflow.ts +++ b/web/i18n/id-ID/workflow.ts @@ -967,6 +967,10 @@ const translation = { lastOutput: 'Keluaran Terakhir', noLastRunFound: 'Tidak ada eksekusi sebelumnya ditemukan', }, + sidebar: { + exportWarning: 'Ekspor Versi Tersimpan Saat Ini', + exportWarningDesc: 'Ini akan mengekspor versi terkini dari alur kerja Anda yang telah disimpan. Jika Anda memiliki perubahan yang belum disimpan di editor, harap simpan terlebih dahulu dengan menggunakan opsi ekspor di kanvas alur kerja.', + }, } export default translation diff --git a/web/i18n/it-IT/workflow.ts b/web/i18n/it-IT/workflow.ts index 821e7544c7..751404d1a9 100644 --- a/web/i18n/it-IT/workflow.ts +++ b/web/i18n/it-IT/workflow.ts @@ -1030,6 +1030,10 @@ const translation = { noLastRunFound: 'Nessuna esecuzione precedente trovata', lastOutput: 'Ultimo output', }, + sidebar: { + exportWarning: 'Esporta la versione salvata corrente', + exportWarningDesc: 'Questo exporterà l\'attuale versione salvata del tuo flusso di lavoro. Se hai modifiche non salvate nell\'editor, ti preghiamo di salvarle prima utilizzando l\'opzione di esportazione nel canvas del flusso di lavoro.', + }, } export default translation diff --git a/web/i18n/ko-KR/workflow.ts b/web/i18n/ko-KR/workflow.ts index bc73e67e6a..74c4c5ec9d 100644 --- a/web/i18n/ko-KR/workflow.ts +++ b/web/i18n/ko-KR/workflow.ts @@ -1055,6 +1055,10 @@ const translation = { copyLastRunError: '마지막 실행 입력을 복사하는 데 실패했습니다.', lastOutput: '마지막 출력', }, + sidebar: { + exportWarning: '현재 저장된 버전 내보내기', + exportWarningDesc: '이 작업은 현재 저장된 워크플로우 버전을 내보냅니다. 편집기에서 저장되지 않은 변경 사항이 있는 경우, 먼저 워크플로우 캔버스의 내보내기 옵션을 사용하여 저장해 주세요.', + }, } export default translation diff --git a/web/i18n/pl-PL/workflow.ts b/web/i18n/pl-PL/workflow.ts index b5cd95d245..7ebf369756 100644 --- a/web/i18n/pl-PL/workflow.ts +++ b/web/i18n/pl-PL/workflow.ts @@ -1004,6 +1004,10 @@ const translation = { copyLastRunError: 'Nie udało się skopiować danych wejściowych z ostatniego uruchomienia', lastOutput: 'Ostatni wynik', }, + sidebar: { + exportWarning: 'Eksportuj obecną zapisaną wersję', + exportWarningDesc: 'To wyeksportuje aktualnie zapisaną wersję twojego przepływu pracy. Jeśli masz niesave\'owane zmiany w edytorze, najpierw je zapisz, korzystając z opcji eksportu w kanwie przepływu pracy.', + }, } export default translation diff --git a/web/i18n/pt-BR/workflow.ts b/web/i18n/pt-BR/workflow.ts index a7ece8417f..d30992b778 100644 --- a/web/i18n/pt-BR/workflow.ts +++ b/web/i18n/pt-BR/workflow.ts @@ -1004,6 +1004,10 @@ const translation = { copyLastRun: 'Copiar Última Execução', lastOutput: 'Última Saída', }, + sidebar: { + exportWarning: 'Exportar a versão salva atual', + exportWarningDesc: 'Isto irá exportar a versão atual salva do seu fluxo de trabalho. Se você tiver alterações não salvas no editor, por favor, salve-as primeiro utilizando a opção de exportação na tela do fluxo de trabalho.', + }, } export default translation diff --git a/web/i18n/ro-RO/workflow.ts b/web/i18n/ro-RO/workflow.ts index ce393406d2..b38f864711 100644 --- a/web/i18n/ro-RO/workflow.ts +++ b/web/i18n/ro-RO/workflow.ts @@ -1004,6 +1004,10 @@ const translation = { copyLastRunError: 'Nu s-au putut copia ultimele intrări de rulare', lastOutput: 'Ultimul rezultat', }, + sidebar: { + exportWarning: 'Exportați versiunea salvată curentă', + exportWarningDesc: 'Aceasta va exporta versiunea curent salvată a fluxului dumneavoastră de lucru. Dacă aveți modificări nesalvate în editor, vă rugăm să le salvați mai întâi utilizând opțiunea de export din canvasul fluxului de lucru.', + }, } export default translation diff --git a/web/i18n/ru-RU/workflow.ts b/web/i18n/ru-RU/workflow.ts index 1290f7e6b7..ec6fa3c95b 100644 --- a/web/i18n/ru-RU/workflow.ts +++ b/web/i18n/ru-RU/workflow.ts @@ -1004,6 +1004,10 @@ const translation = { noMatchingInputsFound: 'Не найдено соответствующих входных данных из последнего запуска.', lastOutput: 'Последний вывод', }, + sidebar: { + exportWarning: 'Экспортировать текущую сохранённую версию', + exportWarningDesc: 'Это экспортирует текущую сохранённую версию вашего рабочего процесса. Если у вас есть несохранённые изменения в редакторе, сначала сохраните их с помощью опции экспорта на полотне рабочего процесса.', + }, } export default translation diff --git a/web/i18n/sl-SI/workflow.ts b/web/i18n/sl-SI/workflow.ts index 57b9fa5ed8..5f33333eb1 100644 --- a/web/i18n/sl-SI/workflow.ts +++ b/web/i18n/sl-SI/workflow.ts @@ -1004,6 +1004,10 @@ const translation = { noMatchingInputsFound: 'Ni podatkov, ki bi ustrezali prejšnjemu zagonu', lastOutput: 'Nazadnje izhod', }, + sidebar: { + exportWarning: 'Izvozi trenutna shranjena različica', + exportWarningDesc: 'To bo izvozilo trenutno shranjeno različico vašega delovnega toka. Če imate neshranjene spremembe v urejevalniku, jih najprej shranite z uporabo možnosti izvoza na platnu delovnega toka.', + }, } export default translation diff --git a/web/i18n/th-TH/workflow.ts b/web/i18n/th-TH/workflow.ts index 7d6e892178..4247fa127c 100644 --- a/web/i18n/th-TH/workflow.ts +++ b/web/i18n/th-TH/workflow.ts @@ -1004,6 +1004,10 @@ const translation = { noMatchingInputsFound: 'ไม่พบข้อมูลที่ตรงกันจากการรันครั้งล่าสุด', lastOutput: 'ผลลัพธ์สุดท้าย', }, + sidebar: { + exportWarning: 'ส่งออกเวอร์ชันที่บันทึกปัจจุบัน', + exportWarningDesc: 'นี่จะส่งออกเวอร์ชันที่บันทึกไว้ปัจจุบันของเวิร์กโฟลว์ของคุณ หากคุณมีการเปลี่ยนแปลงที่ยังไม่ได้บันทึกในแก้ไข กรุณาบันทึกมันก่อนโดยใช้ตัวเลือกส่งออกในผืนผ้าใบเวิร์กโฟลว์', + }, } export default translation diff --git a/web/i18n/tr-TR/workflow.ts b/web/i18n/tr-TR/workflow.ts index cda742fb68..f33ea189bd 100644 --- a/web/i18n/tr-TR/workflow.ts +++ b/web/i18n/tr-TR/workflow.ts @@ -1005,6 +1005,10 @@ const translation = { copyLastRunError: 'Son çalışma girdilerini kopyalamak başarısız oldu.', lastOutput: 'Son Çıktı', }, + sidebar: { + exportWarning: 'Mevcut Kaydedilmiş Versiyonu Dışa Aktar', + exportWarningDesc: 'Bu, çalışma akışınızın mevcut kaydedilmiş sürümünü dışa aktaracaktır. Editörde kaydedilmemiş değişiklikleriniz varsa, lütfen önce bunları çalışma akışı alanındaki dışa aktarma seçeneğini kullanarak kaydedin.', + }, } export default translation diff --git a/web/i18n/uk-UA/workflow.ts b/web/i18n/uk-UA/workflow.ts index 999d1bfb3d..3ead47f7dc 100644 --- a/web/i18n/uk-UA/workflow.ts +++ b/web/i18n/uk-UA/workflow.ts @@ -1004,6 +1004,10 @@ const translation = { noMatchingInputsFound: 'Не знайдено відповідних вхідних даних з останнього запуску', lastOutput: 'Останній вихід', }, + sidebar: { + exportWarning: 'Експортувати поточну збережену версію', + exportWarningDesc: 'Це експортує поточну збережену версію вашого робочого процесу. Якщо у вас є незбережені зміни в редакторі, будь ласка, спочатку збережіть їх, використовуючи опцію експорту на полотні робочого процесу.', + }, } export default translation diff --git a/web/i18n/vi-VN/workflow.ts b/web/i18n/vi-VN/workflow.ts index 2f8e20d08d..b668ef9f83 100644 --- a/web/i18n/vi-VN/workflow.ts +++ b/web/i18n/vi-VN/workflow.ts @@ -1004,6 +1004,10 @@ const translation = { copyLastRunError: 'Không thể sao chép đầu vào của lần chạy trước', lastOutput: 'Đầu ra cuối cùng', }, + sidebar: { + exportWarning: 'Xuất Phiên Bản Đã Lưu Hiện Tại', + exportWarningDesc: 'Điều này sẽ xuất phiên bản hiện tại đã được lưu của quy trình làm việc của bạn. Nếu bạn có những thay đổi chưa được lưu trong trình soạn thảo, vui lòng lưu chúng trước bằng cách sử dụng tùy chọn xuất trong bản vẽ quy trình.', + }, } export default translation diff --git a/web/i18n/zh-Hant/workflow.ts b/web/i18n/zh-Hant/workflow.ts index 6f79177d14..e6dce04c9d 100644 --- a/web/i18n/zh-Hant/workflow.ts +++ b/web/i18n/zh-Hant/workflow.ts @@ -1004,6 +1004,10 @@ const translation = { noLastRunFound: '沒有找到之前的運行', lastOutput: '最後的輸出', }, + sidebar: { + exportWarning: '導出當前保存的版本', + exportWarningDesc: '這將導出當前保存的工作流程版本。如果您在編輯器中有未保存的更改,請先通過使用工作流程畫布中的導出選項來保存它們。', + }, } export default translation From ce2281d31b87e59ba71cf49657dde616c5c1dd39 Mon Sep 17 00:00:00 2001 From: Ding <44717411+ding113@users.noreply.github.com> Date: Mon, 8 Sep 2025 10:29:12 +0800 Subject: [PATCH 49/52] Fix: Parameter Extractor Uses Correct Prompt for Prompt Mode in Chat Models (#24636) Co-authored-by: -LAN- --- .../nodes/parameter_extractor/parameter_extractor_node.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/api/core/workflow/nodes/parameter_extractor/parameter_extractor_node.py b/api/core/workflow/nodes/parameter_extractor/parameter_extractor_node.py index a854c7e87e..1e1c10a11a 100644 --- a/api/core/workflow/nodes/parameter_extractor/parameter_extractor_node.py +++ b/api/core/workflow/nodes/parameter_extractor/parameter_extractor_node.py @@ -52,6 +52,7 @@ from .exc import ( ) from .prompts import ( CHAT_EXAMPLE, + CHAT_GENERATE_JSON_PROMPT, CHAT_GENERATE_JSON_USER_MESSAGE_TEMPLATE, COMPLETION_GENERATE_JSON_PROMPT, FUNCTION_CALLING_EXTRACTOR_EXAMPLE, @@ -752,7 +753,7 @@ class ParameterExtractorNode(BaseNode): if model_mode == ModelMode.CHAT: system_prompt_messages = ChatModelMessage( role=PromptMessageRole.SYSTEM, - text=FUNCTION_CALLING_EXTRACTOR_SYSTEM_PROMPT.format(histories=memory_str, instruction=instruction), + text=CHAT_GENERATE_JSON_PROMPT.format(histories=memory_str).replace("{{instructions}}", instruction), ) user_prompt_message = ChatModelMessage(role=PromptMessageRole.USER, text=input_text) return [system_prompt_messages, user_prompt_message] From f6059ef38991abc87acf2739fa8492bd1779fc6a Mon Sep 17 00:00:00 2001 From: Asuka Minato Date: Mon, 8 Sep 2025 11:40:00 +0900 Subject: [PATCH 50/52] add more typing (#24949) Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com> --- api/controllers/console/admin.py | 8 ++- api/controllers/console/auth/oauth_server.py | 26 ++++---- api/controllers/console/explore/wraps.py | 26 ++++---- api/controllers/console/workspace/__init__.py | 9 ++- api/controllers/console/wraps.py | 61 ++++++++++--------- api/controllers/service_api/wraps.py | 17 +++--- api/controllers/web/wraps.py | 4 ++ .../vdb/matrixone/matrixone_vector.py | 4 ++ api/libs/login.py | 16 ++--- 9 files changed, 97 insertions(+), 74 deletions(-) diff --git a/api/controllers/console/admin.py b/api/controllers/console/admin.py index cae2d7cbe3..1306efacf4 100644 --- a/api/controllers/console/admin.py +++ b/api/controllers/console/admin.py @@ -1,4 +1,6 @@ +from collections.abc import Callable from functools import wraps +from typing import ParamSpec, TypeVar from flask import request from flask_restx import Resource, reqparse @@ -6,6 +8,8 @@ from sqlalchemy import select from sqlalchemy.orm import Session from werkzeug.exceptions import NotFound, Unauthorized +P = ParamSpec("P") +R = TypeVar("R") from configs import dify_config from constants.languages import supported_language from controllers.console import api @@ -14,9 +18,9 @@ from extensions.ext_database import db from models.model import App, InstalledApp, RecommendedApp -def admin_required(view): +def admin_required(view: Callable[P, R]): @wraps(view) - def decorated(*args, **kwargs): + def decorated(*args: P.args, **kwargs: P.kwargs): if not dify_config.ADMIN_API_KEY: raise Unauthorized("API key is invalid.") diff --git a/api/controllers/console/auth/oauth_server.py b/api/controllers/console/auth/oauth_server.py index a8ba417847..a54c1443f8 100644 --- a/api/controllers/console/auth/oauth_server.py +++ b/api/controllers/console/auth/oauth_server.py @@ -1,5 +1,6 @@ +from collections.abc import Callable from functools import wraps -from typing import cast +from typing import Concatenate, ParamSpec, TypeVar, cast import flask_login from flask import jsonify, request @@ -15,10 +16,14 @@ from services.oauth_server import OAUTH_ACCESS_TOKEN_EXPIRES_IN, OAuthGrantType, from .. import api +P = ParamSpec("P") +R = TypeVar("R") +T = TypeVar("T") -def oauth_server_client_id_required(view): + +def oauth_server_client_id_required(view: Callable[Concatenate[T, OAuthProviderApp, P], R]): @wraps(view) - def decorated(*args, **kwargs): + def decorated(self: T, *args: P.args, **kwargs: P.kwargs): parser = reqparse.RequestParser() parser.add_argument("client_id", type=str, required=True, location="json") parsed_args = parser.parse_args() @@ -30,18 +35,15 @@ def oauth_server_client_id_required(view): if not oauth_provider_app: raise NotFound("client_id is invalid") - kwargs["oauth_provider_app"] = oauth_provider_app - - return view(*args, **kwargs) + return view(self, oauth_provider_app, *args, **kwargs) return decorated -def oauth_server_access_token_required(view): +def oauth_server_access_token_required(view: Callable[Concatenate[T, OAuthProviderApp, Account, P], R]): @wraps(view) - def decorated(*args, **kwargs): - oauth_provider_app = kwargs.get("oauth_provider_app") - if not oauth_provider_app or not isinstance(oauth_provider_app, OAuthProviderApp): + def decorated(self: T, oauth_provider_app: OAuthProviderApp, *args: P.args, **kwargs: P.kwargs): + if not isinstance(oauth_provider_app, OAuthProviderApp): raise BadRequest("Invalid oauth_provider_app") authorization_header = request.headers.get("Authorization") @@ -79,9 +81,7 @@ def oauth_server_access_token_required(view): response.headers["WWW-Authenticate"] = "Bearer" return response - kwargs["account"] = account - - return view(*args, **kwargs) + return view(self, oauth_provider_app, account, *args, **kwargs) return decorated diff --git a/api/controllers/console/explore/wraps.py b/api/controllers/console/explore/wraps.py index e86103184a..6401f804c0 100644 --- a/api/controllers/console/explore/wraps.py +++ b/api/controllers/console/explore/wraps.py @@ -1,4 +1,6 @@ +from collections.abc import Callable from functools import wraps +from typing import Concatenate, Optional, ParamSpec, TypeVar from flask_login import current_user from flask_restx import Resource @@ -13,19 +15,15 @@ from services.app_service import AppService from services.enterprise.enterprise_service import EnterpriseService from services.feature_service import FeatureService +P = ParamSpec("P") +R = TypeVar("R") +T = TypeVar("T") -def installed_app_required(view=None): - def decorator(view): + +def installed_app_required(view: Optional[Callable[Concatenate[InstalledApp, P], R]] = None): + def decorator(view: Callable[Concatenate[InstalledApp, P], R]): @wraps(view) - def decorated(*args, **kwargs): - if not kwargs.get("installed_app_id"): - raise ValueError("missing installed_app_id in path parameters") - - installed_app_id = kwargs.get("installed_app_id") - installed_app_id = str(installed_app_id) - - del kwargs["installed_app_id"] - + def decorated(installed_app_id: str, *args: P.args, **kwargs: P.kwargs): installed_app = ( db.session.query(InstalledApp) .where( @@ -52,10 +50,10 @@ def installed_app_required(view=None): return decorator -def user_allowed_to_access_app(view=None): - def decorator(view): +def user_allowed_to_access_app(view: Optional[Callable[Concatenate[InstalledApp, P], R]] = None): + def decorator(view: Callable[Concatenate[InstalledApp, P], R]): @wraps(view) - def decorated(installed_app: InstalledApp, *args, **kwargs): + def decorated(installed_app: InstalledApp, *args: P.args, **kwargs: P.kwargs): feature = FeatureService.get_system_features() if feature.webapp_auth.enabled: app_id = installed_app.app_id diff --git a/api/controllers/console/workspace/__init__.py b/api/controllers/console/workspace/__init__.py index ef814dd738..4a048f3c5e 100644 --- a/api/controllers/console/workspace/__init__.py +++ b/api/controllers/console/workspace/__init__.py @@ -1,4 +1,6 @@ +from collections.abc import Callable from functools import wraps +from typing import ParamSpec, TypeVar from flask_login import current_user from sqlalchemy.orm import Session @@ -7,14 +9,17 @@ from werkzeug.exceptions import Forbidden from extensions.ext_database import db from models.account import TenantPluginPermission +P = ParamSpec("P") +R = TypeVar("R") + def plugin_permission_required( install_required: bool = False, debug_required: bool = False, ): - def interceptor(view): + def interceptor(view: Callable[P, R]): @wraps(view) - def decorated(*args, **kwargs): + def decorated(*args: P.args, **kwargs: P.kwargs): user = current_user tenant_id = user.current_tenant_id diff --git a/api/controllers/console/wraps.py b/api/controllers/console/wraps.py index d3fd1d52e5..e375fe285b 100644 --- a/api/controllers/console/wraps.py +++ b/api/controllers/console/wraps.py @@ -2,7 +2,9 @@ import contextlib import json import os import time +from collections.abc import Callable from functools import wraps +from typing import ParamSpec, TypeVar from flask import abort, request from flask_login import current_user @@ -19,10 +21,13 @@ from services.operation_service import OperationService from .error import NotInitValidateError, NotSetupError, UnauthorizedAndForceLogout +P = ParamSpec("P") +R = TypeVar("R") -def account_initialization_required(view): + +def account_initialization_required(view: Callable[P, R]): @wraps(view) - def decorated(*args, **kwargs): + def decorated(*args: P.args, **kwargs: P.kwargs): # check account initialization account = current_user @@ -34,9 +39,9 @@ def account_initialization_required(view): return decorated -def only_edition_cloud(view): +def only_edition_cloud(view: Callable[P, R]): @wraps(view) - def decorated(*args, **kwargs): + def decorated(*args: P.args, **kwargs: P.kwargs): if dify_config.EDITION != "CLOUD": abort(404) @@ -45,9 +50,9 @@ def only_edition_cloud(view): return decorated -def only_edition_enterprise(view): +def only_edition_enterprise(view: Callable[P, R]): @wraps(view) - def decorated(*args, **kwargs): + def decorated(*args: P.args, **kwargs: P.kwargs): if not dify_config.ENTERPRISE_ENABLED: abort(404) @@ -56,9 +61,9 @@ def only_edition_enterprise(view): return decorated -def only_edition_self_hosted(view): +def only_edition_self_hosted(view: Callable[P, R]): @wraps(view) - def decorated(*args, **kwargs): + def decorated(*args: P.args, **kwargs: P.kwargs): if dify_config.EDITION != "SELF_HOSTED": abort(404) @@ -67,9 +72,9 @@ def only_edition_self_hosted(view): return decorated -def cloud_edition_billing_enabled(view): +def cloud_edition_billing_enabled(view: Callable[P, R]): @wraps(view) - def decorated(*args, **kwargs): + def decorated(*args: P.args, **kwargs: P.kwargs): features = FeatureService.get_features(current_user.current_tenant_id) if not features.billing.enabled: abort(403, "Billing feature is not enabled.") @@ -79,9 +84,9 @@ def cloud_edition_billing_enabled(view): def cloud_edition_billing_resource_check(resource: str): - def interceptor(view): + def interceptor(view: Callable[P, R]): @wraps(view) - def decorated(*args, **kwargs): + def decorated(*args: P.args, **kwargs: P.kwargs): features = FeatureService.get_features(current_user.current_tenant_id) if features.billing.enabled: members = features.members @@ -120,9 +125,9 @@ def cloud_edition_billing_resource_check(resource: str): def cloud_edition_billing_knowledge_limit_check(resource: str): - def interceptor(view): + def interceptor(view: Callable[P, R]): @wraps(view) - def decorated(*args, **kwargs): + def decorated(*args: P.args, **kwargs: P.kwargs): features = FeatureService.get_features(current_user.current_tenant_id) if features.billing.enabled: if resource == "add_segment": @@ -142,9 +147,9 @@ def cloud_edition_billing_knowledge_limit_check(resource: str): def cloud_edition_billing_rate_limit_check(resource: str): - def interceptor(view): + def interceptor(view: Callable[P, R]): @wraps(view) - def decorated(*args, **kwargs): + def decorated(*args: P.args, **kwargs: P.kwargs): if resource == "knowledge": knowledge_rate_limit = FeatureService.get_knowledge_rate_limit(current_user.current_tenant_id) if knowledge_rate_limit.enabled: @@ -176,9 +181,9 @@ def cloud_edition_billing_rate_limit_check(resource: str): return interceptor -def cloud_utm_record(view): +def cloud_utm_record(view: Callable[P, R]): @wraps(view) - def decorated(*args, **kwargs): + def decorated(*args: P.args, **kwargs: P.kwargs): with contextlib.suppress(Exception): features = FeatureService.get_features(current_user.current_tenant_id) @@ -194,9 +199,9 @@ def cloud_utm_record(view): return decorated -def setup_required(view): +def setup_required(view: Callable[P, R]): @wraps(view) - def decorated(*args, **kwargs): + def decorated(*args: P.args, **kwargs: P.kwargs): # check setup if ( dify_config.EDITION == "SELF_HOSTED" @@ -212,9 +217,9 @@ def setup_required(view): return decorated -def enterprise_license_required(view): +def enterprise_license_required(view: Callable[P, R]): @wraps(view) - def decorated(*args, **kwargs): + def decorated(*args: P.args, **kwargs: P.kwargs): settings = FeatureService.get_system_features() if settings.license.status in [LicenseStatus.INACTIVE, LicenseStatus.EXPIRED, LicenseStatus.LOST]: raise UnauthorizedAndForceLogout("Your license is invalid. Please contact your administrator.") @@ -224,9 +229,9 @@ def enterprise_license_required(view): return decorated -def email_password_login_enabled(view): +def email_password_login_enabled(view: Callable[P, R]): @wraps(view) - def decorated(*args, **kwargs): + def decorated(*args: P.args, **kwargs: P.kwargs): features = FeatureService.get_system_features() if features.enable_email_password_login: return view(*args, **kwargs) @@ -237,9 +242,9 @@ def email_password_login_enabled(view): return decorated -def enable_change_email(view): +def enable_change_email(view: Callable[P, R]): @wraps(view) - def decorated(*args, **kwargs): + def decorated(*args: P.args, **kwargs: P.kwargs): features = FeatureService.get_system_features() if features.enable_change_email: return view(*args, **kwargs) @@ -250,9 +255,9 @@ def enable_change_email(view): return decorated -def is_allow_transfer_owner(view): +def is_allow_transfer_owner(view: Callable[P, R]): @wraps(view) - def decorated(*args, **kwargs): + def decorated(*args: P.args, **kwargs: P.kwargs): features = FeatureService.get_features(current_user.current_tenant_id) if features.is_allow_transfer_workspace: return view(*args, **kwargs) diff --git a/api/controllers/service_api/wraps.py b/api/controllers/service_api/wraps.py index 67d48319d4..4d71e58396 100644 --- a/api/controllers/service_api/wraps.py +++ b/api/controllers/service_api/wraps.py @@ -3,7 +3,7 @@ from collections.abc import Callable from datetime import timedelta from enum import StrEnum, auto from functools import wraps -from typing import Optional +from typing import Optional, ParamSpec, TypeVar from flask import current_app, request from flask_login import user_logged_in @@ -22,6 +22,9 @@ from models.dataset import Dataset, RateLimitLog from models.model import ApiToken, App, EndUser from services.feature_service import FeatureService +P = ParamSpec("P") +R = TypeVar("R") + class WhereisUserArg(StrEnum): """ @@ -118,8 +121,8 @@ def validate_app_token(view: Optional[Callable] = None, *, fetch_user_arg: Optio def cloud_edition_billing_resource_check(resource: str, api_token_type: str): - def interceptor(view): - def decorated(*args, **kwargs): + def interceptor(view: Callable[P, R]): + def decorated(*args: P.args, **kwargs: P.kwargs): api_token = validate_and_get_api_token(api_token_type) features = FeatureService.get_features(api_token.tenant_id) @@ -148,9 +151,9 @@ def cloud_edition_billing_resource_check(resource: str, api_token_type: str): def cloud_edition_billing_knowledge_limit_check(resource: str, api_token_type: str): - def interceptor(view): + def interceptor(view: Callable[P, R]): @wraps(view) - def decorated(*args, **kwargs): + def decorated(*args: P.args, **kwargs: P.kwargs): api_token = validate_and_get_api_token(api_token_type) features = FeatureService.get_features(api_token.tenant_id) if features.billing.enabled: @@ -170,9 +173,9 @@ def cloud_edition_billing_knowledge_limit_check(resource: str, api_token_type: s def cloud_edition_billing_rate_limit_check(resource: str, api_token_type: str): - def interceptor(view): + def interceptor(view: Callable[P, R]): @wraps(view) - def decorated(*args, **kwargs): + def decorated(*args: P.args, **kwargs: P.kwargs): api_token = validate_and_get_api_token(api_token_type) if resource == "knowledge": diff --git a/api/controllers/web/wraps.py b/api/controllers/web/wraps.py index 1fc8916cab..1fbb2c165f 100644 --- a/api/controllers/web/wraps.py +++ b/api/controllers/web/wraps.py @@ -1,5 +1,6 @@ from datetime import UTC, datetime from functools import wraps +from typing import ParamSpec, TypeVar from flask import request from flask_restx import Resource @@ -15,6 +16,9 @@ from services.enterprise.enterprise_service import EnterpriseService, WebAppSett from services.feature_service import FeatureService from services.webapp_auth_service import WebAppAuthService +P = ParamSpec("P") +R = TypeVar("R") + def validate_jwt_token(view=None): def decorator(view): diff --git a/api/core/rag/datasource/vdb/matrixone/matrixone_vector.py b/api/core/rag/datasource/vdb/matrixone/matrixone_vector.py index 9660cf8aba..7da830f643 100644 --- a/api/core/rag/datasource/vdb/matrixone/matrixone_vector.py +++ b/api/core/rag/datasource/vdb/matrixone/matrixone_vector.py @@ -17,6 +17,10 @@ from extensions.ext_redis import redis_client from models.dataset import Dataset logger = logging.getLogger(__name__) +from typing import ParamSpec, TypeVar + +P = ParamSpec("P") +R = TypeVar("R") class MatrixoneConfig(BaseModel): diff --git a/api/libs/login.py b/api/libs/login.py index 711d16e3b9..0535f52ea1 100644 --- a/api/libs/login.py +++ b/api/libs/login.py @@ -1,3 +1,4 @@ +from collections.abc import Callable from functools import wraps from typing import Union, cast @@ -12,9 +13,13 @@ from models.model import EndUser #: A proxy for the current user. If no user is logged in, this will be an #: anonymous user current_user = cast(Union[Account, EndUser, None], LocalProxy(lambda: _get_user())) +from typing import ParamSpec, TypeVar + +P = ParamSpec("P") +R = TypeVar("R") -def login_required(func): +def login_required(func: Callable[P, R]): """ If you decorate a view with this, it will ensure that the current user is logged in and authenticated before calling the actual view. (If they are @@ -49,17 +54,12 @@ def login_required(func): """ @wraps(func) - def decorated_view(*args, **kwargs): + def decorated_view(*args: P.args, **kwargs: P.kwargs): if request.method in EXEMPT_METHODS or dify_config.LOGIN_DISABLED: pass elif current_user is not None and not current_user.is_authenticated: return current_app.login_manager.unauthorized() # type: ignore - - # flask 1.x compatibility - # current_app.ensure_sync is only available in Flask >= 2.0 - if callable(getattr(current_app, "ensure_sync", None)): - return current_app.ensure_sync(func)(*args, **kwargs) - return func(*args, **kwargs) + return current_app.ensure_sync(func)(*args, **kwargs) return decorated_view From 4ee49f355068ce88a4ac4ecf4995c015f3c517bf Mon Sep 17 00:00:00 2001 From: ZalterCitty Date: Mon, 8 Sep 2025 10:44:36 +0800 Subject: [PATCH 51/52] chore: remove weird account login (#22247) Co-authored-by: zhuqingchao Co-authored-by: crazywoola <100913391+crazywoola@users.noreply.github.com> --- .gitignore | 1 + api/controllers/service_api/wraps.py | 21 --------------------- 2 files changed, 1 insertion(+), 21 deletions(-) diff --git a/.gitignore b/.gitignore index 03ff04d823..bc354e639e 100644 --- a/.gitignore +++ b/.gitignore @@ -198,6 +198,7 @@ sdks/python-client/dify_client.egg-info !.vscode/launch.json.template !.vscode/README.md api/.vscode +web/.vscode # vscode Code History Extension .history diff --git a/api/controllers/service_api/wraps.py b/api/controllers/service_api/wraps.py index 4d71e58396..2df00d9fc7 100644 --- a/api/controllers/service_api/wraps.py +++ b/api/controllers/service_api/wraps.py @@ -63,27 +63,6 @@ def validate_app_token(view: Optional[Callable] = None, *, fetch_user_arg: Optio if tenant.status == TenantStatus.ARCHIVE: raise Forbidden("The workspace's status is archived.") - tenant_account_join = ( - db.session.query(Tenant, TenantAccountJoin) - .where(Tenant.id == api_token.tenant_id) - .where(TenantAccountJoin.tenant_id == Tenant.id) - .where(TenantAccountJoin.role.in_(["owner"])) - .where(Tenant.status == TenantStatus.NORMAL) - .one_or_none() - ) # TODO: only owner information is required, so only one is returned. - if tenant_account_join: - tenant, ta = tenant_account_join - account = db.session.query(Account).where(Account.id == ta.account_id).first() - # Login admin - if account: - account.current_tenant = tenant - current_app.login_manager._update_request_context_with_user(account) # type: ignore - user_logged_in.send(current_app._get_current_object(), user=_get_user()) # type: ignore - else: - raise Unauthorized("Tenant owner account does not exist.") - else: - raise Unauthorized("Tenant does not exist.") - kwargs["app_model"] = app_model if fetch_user_arg: From 5d0a50042f15252c74f255564ed5ee491157b94c Mon Sep 17 00:00:00 2001 From: NeatGuyCoding <15627489+NeatGuyCoding@users.noreply.github.com> Date: Mon, 8 Sep 2025 13:09:53 +0800 Subject: [PATCH 52/52] feat: add test containers based tests for clean dataset task (#25341) Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com> --- .../tasks/test_clean_dataset_task.py | 1144 +++++++++++++++++ 1 file changed, 1144 insertions(+) create mode 100644 api/tests/test_containers_integration_tests/tasks/test_clean_dataset_task.py diff --git a/api/tests/test_containers_integration_tests/tasks/test_clean_dataset_task.py b/api/tests/test_containers_integration_tests/tasks/test_clean_dataset_task.py new file mode 100644 index 0000000000..0083011070 --- /dev/null +++ b/api/tests/test_containers_integration_tests/tasks/test_clean_dataset_task.py @@ -0,0 +1,1144 @@ +""" +Integration tests for clean_dataset_task using testcontainers. + +This module provides comprehensive integration tests for the dataset cleanup task +using TestContainers infrastructure. The tests ensure that the task properly +cleans up all dataset-related data including vector indexes, documents, +segments, metadata, and storage files in a real database environment. + +All tests use the testcontainers infrastructure to ensure proper database isolation +and realistic testing scenarios with actual PostgreSQL and Redis instances. +""" + +import uuid +from datetime import datetime +from unittest.mock import MagicMock, patch + +import pytest +from faker import Faker + +from models.account import Account, Tenant, TenantAccountJoin, TenantAccountRole +from models.dataset import ( + AppDatasetJoin, + Dataset, + DatasetMetadata, + DatasetMetadataBinding, + DatasetProcessRule, + DatasetQuery, + Document, + DocumentSegment, +) +from models.enums import CreatorUserRole +from models.model import UploadFile +from tasks.clean_dataset_task import clean_dataset_task + + +class TestCleanDatasetTask: + """Integration tests for clean_dataset_task using testcontainers.""" + + @pytest.fixture(autouse=True) + def cleanup_database(self, db_session_with_containers): + """Clean up database before each test to ensure isolation.""" + from extensions.ext_database import db + from extensions.ext_redis import redis_client + + # Clear all test data + db.session.query(DatasetMetadataBinding).delete() + db.session.query(DatasetMetadata).delete() + db.session.query(AppDatasetJoin).delete() + db.session.query(DatasetQuery).delete() + db.session.query(DatasetProcessRule).delete() + db.session.query(DocumentSegment).delete() + db.session.query(Document).delete() + db.session.query(Dataset).delete() + db.session.query(UploadFile).delete() + db.session.query(TenantAccountJoin).delete() + db.session.query(Tenant).delete() + db.session.query(Account).delete() + db.session.commit() + + # Clear Redis cache + redis_client.flushdb() + + @pytest.fixture + def mock_external_service_dependencies(self): + """Mock setup for external service dependencies.""" + with ( + patch("tasks.clean_dataset_task.storage") as mock_storage, + patch("tasks.clean_dataset_task.IndexProcessorFactory") as mock_index_processor_factory, + ): + # Setup default mock returns + mock_storage.delete.return_value = None + + # Mock index processor + mock_index_processor = MagicMock() + mock_index_processor.clean.return_value = None + mock_index_processor_factory_instance = MagicMock() + mock_index_processor_factory_instance.init_index_processor.return_value = mock_index_processor + mock_index_processor_factory.return_value = mock_index_processor_factory_instance + + yield { + "storage": mock_storage, + "index_processor_factory": mock_index_processor_factory, + "index_processor": mock_index_processor, + } + + def _create_test_account_and_tenant(self, db_session_with_containers): + """ + Helper method to create a test account and tenant for testing. + + Args: + db_session_with_containers: Database session from testcontainers infrastructure + + Returns: + tuple: (Account, Tenant) created instances + """ + fake = Faker() + + # Create account + account = Account( + email=fake.email(), + name=fake.name(), + interface_language="en-US", + status="active", + ) + + from extensions.ext_database import db + + db.session.add(account) + db.session.commit() + + # Create tenant + tenant = Tenant( + name=fake.company(), + plan="basic", + status="active", + ) + + db.session.add(tenant) + db.session.commit() + + # Create tenant-account relationship + tenant_account_join = TenantAccountJoin( + tenant_id=tenant.id, + account_id=account.id, + role=TenantAccountRole.OWNER, + ) + + db.session.add(tenant_account_join) + db.session.commit() + + return account, tenant + + def _create_test_dataset(self, db_session_with_containers, account, tenant): + """ + Helper method to create a test dataset for testing. + + Args: + db_session_with_containers: Database session from testcontainers infrastructure + account: Account instance + tenant: Tenant instance + + Returns: + Dataset: Created dataset instance + """ + dataset = Dataset( + id=str(uuid.uuid4()), + tenant_id=tenant.id, + name="test_dataset", + description="Test dataset for cleanup testing", + indexing_technique="high_quality", + index_struct='{"type": "paragraph"}', + collection_binding_id=str(uuid.uuid4()), + created_by=account.id, + created_at=datetime.now(), + updated_at=datetime.now(), + ) + + from extensions.ext_database import db + + db.session.add(dataset) + db.session.commit() + + return dataset + + def _create_test_document(self, db_session_with_containers, account, tenant, dataset): + """ + Helper method to create a test document for testing. + + Args: + db_session_with_containers: Database session from testcontainers infrastructure + account: Account instance + tenant: Tenant instance + dataset: Dataset instance + + Returns: + Document: Created document instance + """ + document = Document( + id=str(uuid.uuid4()), + tenant_id=tenant.id, + dataset_id=dataset.id, + position=1, + data_source_type="upload_file", + batch="test_batch", + name="test_document", + created_from="upload_file", + created_by=account.id, + indexing_status="completed", + enabled=True, + archived=False, + doc_form="paragraph_index", + word_count=100, + created_at=datetime.now(), + updated_at=datetime.now(), + ) + + from extensions.ext_database import db + + db.session.add(document) + db.session.commit() + + return document + + def _create_test_segment(self, db_session_with_containers, account, tenant, dataset, document): + """ + Helper method to create a test document segment for testing. + + Args: + db_session_with_containers: Database session from testcontainers infrastructure + account: Account instance + tenant: Tenant instance + dataset: Dataset instance + document: Document instance + + Returns: + DocumentSegment: Created document segment instance + """ + segment = DocumentSegment( + id=str(uuid.uuid4()), + tenant_id=tenant.id, + dataset_id=dataset.id, + document_id=document.id, + position=1, + content="This is a test segment content for cleanup testing", + word_count=20, + tokens=30, + created_by=account.id, + status="completed", + index_node_id=str(uuid.uuid4()), + index_node_hash="test_hash", + created_at=datetime.now(), + updated_at=datetime.now(), + ) + + from extensions.ext_database import db + + db.session.add(segment) + db.session.commit() + + return segment + + def _create_test_upload_file(self, db_session_with_containers, account, tenant): + """ + Helper method to create a test upload file for testing. + + Args: + db_session_with_containers: Database session from testcontainers infrastructure + account: Account instance + tenant: Tenant instance + + Returns: + UploadFile: Created upload file instance + """ + fake = Faker() + + upload_file = UploadFile( + tenant_id=tenant.id, + storage_type="local", + key=f"test_files/{fake.file_name()}", + name=fake.file_name(), + size=1024, + extension=".txt", + mime_type="text/plain", + created_by_role=CreatorUserRole.ACCOUNT, + created_by=account.id, + created_at=datetime.now(), + used=False, + ) + + from extensions.ext_database import db + + db.session.add(upload_file) + db.session.commit() + + return upload_file + + def test_clean_dataset_task_success_basic_cleanup( + self, db_session_with_containers, mock_external_service_dependencies + ): + """ + Test successful basic dataset cleanup with minimal data. + + This test verifies that the task can successfully: + 1. Clean up vector database indexes + 2. Delete documents and segments + 3. Remove dataset metadata and bindings + 4. Handle empty document scenarios + 5. Complete cleanup process without errors + """ + # Create test data + account, tenant = self._create_test_account_and_tenant(db_session_with_containers) + dataset = self._create_test_dataset(db_session_with_containers, account, tenant) + + # Execute the task + clean_dataset_task( + dataset_id=dataset.id, + tenant_id=tenant.id, + indexing_technique=dataset.indexing_technique, + index_struct=dataset.index_struct, + collection_binding_id=dataset.collection_binding_id, + doc_form=dataset.doc_form, + ) + + # Verify results + from extensions.ext_database import db + + # Check that dataset-related data was cleaned up + documents = db.session.query(Document).filter_by(dataset_id=dataset.id).all() + assert len(documents) == 0 + + segments = db.session.query(DocumentSegment).filter_by(dataset_id=dataset.id).all() + assert len(segments) == 0 + + # Check that metadata and bindings were cleaned up + metadata = db.session.query(DatasetMetadata).filter_by(dataset_id=dataset.id).all() + assert len(metadata) == 0 + + bindings = db.session.query(DatasetMetadataBinding).filter_by(dataset_id=dataset.id).all() + assert len(bindings) == 0 + + # Check that process rules and queries were cleaned up + process_rules = db.session.query(DatasetProcessRule).filter_by(dataset_id=dataset.id).all() + assert len(process_rules) == 0 + + queries = db.session.query(DatasetQuery).filter_by(dataset_id=dataset.id).all() + assert len(queries) == 0 + + # Check that app dataset joins were cleaned up + app_joins = db.session.query(AppDatasetJoin).filter_by(dataset_id=dataset.id).all() + assert len(app_joins) == 0 + + # Verify index processor was called + mock_index_processor = mock_external_service_dependencies["index_processor"] + mock_index_processor.clean.assert_called_once() + + # Verify storage was not called (no files to delete) + mock_storage = mock_external_service_dependencies["storage"] + mock_storage.delete.assert_not_called() + + def test_clean_dataset_task_success_with_documents_and_segments( + self, db_session_with_containers, mock_external_service_dependencies + ): + """ + Test successful dataset cleanup with documents and segments. + + This test verifies that the task can successfully: + 1. Clean up vector database indexes + 2. Delete multiple documents and segments + 3. Handle document segments with image references + 4. Clean up storage files associated with documents + 5. Remove all dataset-related data completely + """ + # Create test data + account, tenant = self._create_test_account_and_tenant(db_session_with_containers) + dataset = self._create_test_dataset(db_session_with_containers, account, tenant) + + # Create multiple documents + documents = [] + for i in range(3): + document = self._create_test_document(db_session_with_containers, account, tenant, dataset) + documents.append(document) + + # Create segments for each document + segments = [] + for i, document in enumerate(documents): + segment = self._create_test_segment(db_session_with_containers, account, tenant, dataset, document) + segments.append(segment) + + # Create upload files for documents + upload_files = [] + upload_file_ids = [] + for document in documents: + upload_file = self._create_test_upload_file(db_session_with_containers, account, tenant) + upload_files.append(upload_file) + upload_file_ids.append(upload_file.id) + + # Update document with file reference + import json + + document.data_source_info = json.dumps({"upload_file_id": upload_file.id}) + from extensions.ext_database import db + + db.session.commit() + + # Create dataset metadata and bindings + metadata = DatasetMetadata( + id=str(uuid.uuid4()), + dataset_id=dataset.id, + tenant_id=tenant.id, + name="test_metadata", + type="string", + created_by=account.id, + created_at=datetime.now(), + ) + + binding = DatasetMetadataBinding( + id=str(uuid.uuid4()), + tenant_id=tenant.id, + dataset_id=dataset.id, + metadata_id=metadata.id, + document_id=documents[0].id, # Use first document as example + created_by=account.id, + created_at=datetime.now(), + ) + + from extensions.ext_database import db + + db.session.add(metadata) + db.session.add(binding) + db.session.commit() + + # Execute the task + clean_dataset_task( + dataset_id=dataset.id, + tenant_id=tenant.id, + indexing_technique=dataset.indexing_technique, + index_struct=dataset.index_struct, + collection_binding_id=dataset.collection_binding_id, + doc_form=dataset.doc_form, + ) + + # Verify results + # Check that all documents were deleted + remaining_documents = db.session.query(Document).filter_by(dataset_id=dataset.id).all() + assert len(remaining_documents) == 0 + + # Check that all segments were deleted + remaining_segments = db.session.query(DocumentSegment).filter_by(dataset_id=dataset.id).all() + assert len(remaining_segments) == 0 + + # Check that all upload files were deleted + remaining_files = db.session.query(UploadFile).where(UploadFile.id.in_(upload_file_ids)).all() + assert len(remaining_files) == 0 + + # Check that metadata and bindings were cleaned up + remaining_metadata = db.session.query(DatasetMetadata).filter_by(dataset_id=dataset.id).all() + assert len(remaining_metadata) == 0 + + remaining_bindings = db.session.query(DatasetMetadataBinding).filter_by(dataset_id=dataset.id).all() + assert len(remaining_bindings) == 0 + + # Verify index processor was called + mock_index_processor = mock_external_service_dependencies["index_processor"] + mock_index_processor.clean.assert_called_once() + + # Verify storage delete was called for each file + mock_storage = mock_external_service_dependencies["storage"] + assert mock_storage.delete.call_count == 3 + + def test_clean_dataset_task_success_with_invalid_doc_form( + self, db_session_with_containers, mock_external_service_dependencies + ): + """ + Test successful dataset cleanup with invalid doc_form handling. + + This test verifies that the task can successfully: + 1. Handle None, empty, or whitespace-only doc_form values + 2. Use default paragraph index type for cleanup + 3. Continue with vector database cleanup using default type + 4. Complete all cleanup operations successfully + 5. Log appropriate warnings for invalid doc_form values + """ + # Create test data + account, tenant = self._create_test_account_and_tenant(db_session_with_containers) + dataset = self._create_test_dataset(db_session_with_containers, account, tenant) + + # Create a document and segment + document = self._create_test_document(db_session_with_containers, account, tenant, dataset) + segment = self._create_test_segment(db_session_with_containers, account, tenant, dataset, document) + + # Execute the task with invalid doc_form values + test_cases = [None, "", " ", "\t\n"] + + for invalid_doc_form in test_cases: + # Reset mock to clear previous calls + mock_index_processor = mock_external_service_dependencies["index_processor"] + mock_index_processor.clean.reset_mock() + + clean_dataset_task( + dataset_id=dataset.id, + tenant_id=tenant.id, + indexing_technique=dataset.indexing_technique, + index_struct=dataset.index_struct, + collection_binding_id=dataset.collection_binding_id, + doc_form=invalid_doc_form, + ) + + # Verify that index processor was called with default type + mock_index_processor.clean.assert_called_once() + + # Check that all data was cleaned up + from extensions.ext_database import db + + remaining_documents = db.session.query(Document).filter_by(dataset_id=dataset.id).all() + assert len(remaining_documents) == 0 + + remaining_segments = db.session.query(DocumentSegment).filter_by(dataset_id=dataset.id).all() + assert len(remaining_segments) == 0 + + # Recreate data for next test case + document = self._create_test_document(db_session_with_containers, account, tenant, dataset) + segment = self._create_test_segment(db_session_with_containers, account, tenant, dataset, document) + + # Verify that IndexProcessorFactory was called with default type + mock_factory = mock_external_service_dependencies["index_processor_factory"] + # Should be called 4 times (once for each test case) + assert mock_factory.call_count == 4 + + def test_clean_dataset_task_error_handling_and_rollback( + self, db_session_with_containers, mock_external_service_dependencies + ): + """ + Test error handling and rollback mechanism when database operations fail. + + This test verifies that the task can properly: + 1. Handle database operation failures gracefully + 2. Rollback database session to prevent dirty state + 3. Continue cleanup operations even if some parts fail + 4. Log appropriate error messages + 5. Maintain database session integrity + """ + # Create test data + account, tenant = self._create_test_account_and_tenant(db_session_with_containers) + dataset = self._create_test_dataset(db_session_with_containers, account, tenant) + document = self._create_test_document(db_session_with_containers, account, tenant, dataset) + segment = self._create_test_segment(db_session_with_containers, account, tenant, dataset, document) + + # Mock IndexProcessorFactory to raise an exception + mock_index_processor = mock_external_service_dependencies["index_processor"] + mock_index_processor.clean.side_effect = Exception("Vector database cleanup failed") + + # Execute the task - it should handle the exception gracefully + clean_dataset_task( + dataset_id=dataset.id, + tenant_id=tenant.id, + indexing_technique=dataset.indexing_technique, + index_struct=dataset.index_struct, + collection_binding_id=dataset.collection_binding_id, + doc_form=dataset.doc_form, + ) + + # Verify results - even with vector cleanup failure, documents and segments should be deleted + from extensions.ext_database import db + + # Check that documents were still deleted despite vector cleanup failure + remaining_documents = db.session.query(Document).filter_by(dataset_id=dataset.id).all() + assert len(remaining_documents) == 0 + + # Check that segments were still deleted despite vector cleanup failure + remaining_segments = db.session.query(DocumentSegment).filter_by(dataset_id=dataset.id).all() + assert len(remaining_segments) == 0 + + # Verify that index processor was called and failed + mock_index_processor.clean.assert_called_once() + + # Verify that the task continued with cleanup despite the error + # This demonstrates the resilience of the cleanup process + + def test_clean_dataset_task_with_image_file_references( + self, db_session_with_containers, mock_external_service_dependencies + ): + """ + Test dataset cleanup with image file references in document segments. + + This test verifies that the task can properly: + 1. Identify image upload file references in segment content + 2. Clean up image files from storage + 3. Remove image file database records + 4. Handle multiple image references in segments + 5. Clean up all image-related data completely + """ + # Create test data + account, tenant = self._create_test_account_and_tenant(db_session_with_containers) + dataset = self._create_test_dataset(db_session_with_containers, account, tenant) + document = self._create_test_document(db_session_with_containers, account, tenant, dataset) + + # Create image upload files + image_files = [] + for i in range(3): + image_file = self._create_test_upload_file(db_session_with_containers, account, tenant) + image_file.extension = ".jpg" + image_file.mime_type = "image/jpeg" + image_file.name = f"test_image_{i}.jpg" + image_files.append(image_file) + + # Create segment with image references in content + segment_content = f""" + This is a test segment with image references. + Image 1 + Image 2 + Image 3 + """ + + segment = DocumentSegment( + id=str(uuid.uuid4()), + tenant_id=tenant.id, + dataset_id=dataset.id, + document_id=document.id, + position=1, + content=segment_content, + word_count=len(segment_content), + tokens=50, + created_by=account.id, + status="completed", + index_node_id=str(uuid.uuid4()), + index_node_hash="test_hash", + created_at=datetime.now(), + updated_at=datetime.now(), + ) + + from extensions.ext_database import db + + db.session.add(segment) + db.session.commit() + + # Mock the get_image_upload_file_ids function to return our image file IDs + with patch("tasks.clean_dataset_task.get_image_upload_file_ids") as mock_get_image_ids: + mock_get_image_ids.return_value = [f.id for f in image_files] + + # Execute the task + clean_dataset_task( + dataset_id=dataset.id, + tenant_id=tenant.id, + indexing_technique=dataset.indexing_technique, + index_struct=dataset.index_struct, + collection_binding_id=dataset.collection_binding_id, + doc_form=dataset.doc_form, + ) + + # Verify results + # Check that all documents were deleted + remaining_documents = db.session.query(Document).filter_by(dataset_id=dataset.id).all() + assert len(remaining_documents) == 0 + + # Check that all segments were deleted + remaining_segments = db.session.query(DocumentSegment).filter_by(dataset_id=dataset.id).all() + assert len(remaining_segments) == 0 + + # Check that all image files were deleted from database + image_file_ids = [f.id for f in image_files] + remaining_image_files = db.session.query(UploadFile).where(UploadFile.id.in_(image_file_ids)).all() + assert len(remaining_image_files) == 0 + + # Verify that storage.delete was called for each image file + mock_storage = mock_external_service_dependencies["storage"] + assert mock_storage.delete.call_count == 3 + + # Verify that get_image_upload_file_ids was called + mock_get_image_ids.assert_called_once() + + def test_clean_dataset_task_performance_with_large_dataset( + self, db_session_with_containers, mock_external_service_dependencies + ): + """ + Test dataset cleanup performance with large amounts of data. + + This test verifies that the task can efficiently: + 1. Handle large numbers of documents and segments + 2. Process multiple upload files efficiently + 3. Maintain reasonable performance with complex data structures + 4. Scale cleanup operations appropriately + 5. Complete cleanup within acceptable time limits + """ + # Create test data + account, tenant = self._create_test_account_and_tenant(db_session_with_containers) + dataset = self._create_test_dataset(db_session_with_containers, account, tenant) + + # Create a large number of documents (simulating real-world scenario) + documents = [] + segments = [] + upload_files = [] + upload_file_ids = [] + + # Create 50 documents with segments and upload files + for i in range(50): + document = self._create_test_document(db_session_with_containers, account, tenant, dataset) + documents.append(document) + + # Create 3 segments per document + for j in range(3): + segment = self._create_test_segment(db_session_with_containers, account, tenant, dataset, document) + segments.append(segment) + + # Create upload file for each document + upload_file = self._create_test_upload_file(db_session_with_containers, account, tenant) + upload_files.append(upload_file) + upload_file_ids.append(upload_file.id) + + # Update document with file reference + import json + + document.data_source_info = json.dumps({"upload_file_id": upload_file.id}) + + # Create dataset metadata and bindings + metadata_items = [] + bindings = [] + + for i in range(10): # Create 10 metadata items + metadata = DatasetMetadata( + id=str(uuid.uuid4()), + dataset_id=dataset.id, + tenant_id=tenant.id, + name=f"test_metadata_{i}", + type="string", + created_by=account.id, + created_at=datetime.now(), + ) + metadata_items.append(metadata) + + # Create binding for each metadata item + binding = DatasetMetadataBinding( + id=str(uuid.uuid4()), + tenant_id=tenant.id, + dataset_id=dataset.id, + metadata_id=metadata.id, + document_id=documents[i % len(documents)].id, + created_by=account.id, + created_at=datetime.now(), + ) + bindings.append(binding) + + from extensions.ext_database import db + + db.session.add_all(metadata_items) + db.session.add_all(bindings) + db.session.commit() + + # Measure cleanup performance + import time + + start_time = time.time() + + # Execute the task + clean_dataset_task( + dataset_id=dataset.id, + tenant_id=tenant.id, + indexing_technique=dataset.indexing_technique, + index_struct=dataset.index_struct, + collection_binding_id=dataset.collection_binding_id, + doc_form=dataset.doc_form, + ) + + end_time = time.time() + cleanup_duration = end_time - start_time + + # Verify results + # Check that all documents were deleted + remaining_documents = db.session.query(Document).filter_by(dataset_id=dataset.id).all() + assert len(remaining_documents) == 0 + + # Check that all segments were deleted + remaining_segments = db.session.query(DocumentSegment).filter_by(dataset_id=dataset.id).all() + assert len(remaining_segments) == 0 + + # Check that all upload files were deleted + remaining_files = db.session.query(UploadFile).where(UploadFile.id.in_(upload_file_ids)).all() + assert len(remaining_files) == 0 + + # Check that all metadata and bindings were deleted + remaining_metadata = db.session.query(DatasetMetadata).filter_by(dataset_id=dataset.id).all() + assert len(remaining_metadata) == 0 + + remaining_bindings = db.session.query(DatasetMetadataBinding).filter_by(dataset_id=dataset.id).all() + assert len(remaining_bindings) == 0 + + # Verify performance expectations + # Cleanup should complete within reasonable time (adjust threshold as needed) + assert cleanup_duration < 10.0, f"Cleanup took too long: {cleanup_duration:.2f} seconds" + + # Verify that storage.delete was called for each file + mock_storage = mock_external_service_dependencies["storage"] + assert mock_storage.delete.call_count == 50 + + # Verify that index processor was called + mock_index_processor = mock_external_service_dependencies["index_processor"] + mock_index_processor.clean.assert_called_once() + + # Log performance metrics + print("\nPerformance Test Results:") + print(f"Documents processed: {len(documents)}") + print(f"Segments processed: {len(segments)}") + print(f"Upload files processed: {len(upload_files)}") + print(f"Metadata items processed: {len(metadata_items)}") + print(f"Total cleanup time: {cleanup_duration:.3f} seconds") + print(f"Average time per document: {cleanup_duration / len(documents):.3f} seconds") + + def test_clean_dataset_task_concurrent_cleanup_scenarios( + self, db_session_with_containers, mock_external_service_dependencies + ): + """ + Test dataset cleanup with concurrent cleanup scenarios and race conditions. + + This test verifies that the task can properly: + 1. Handle multiple cleanup operations on the same dataset + 2. Prevent data corruption during concurrent access + 3. Maintain data consistency across multiple cleanup attempts + 4. Handle race conditions gracefully + 5. Ensure idempotent cleanup operations + """ + # Create test data + account, tenant = self._create_test_account_and_tenant(db_session_with_containers) + dataset = self._create_test_dataset(db_session_with_containers, account, tenant) + document = self._create_test_document(db_session_with_containers, account, tenant, dataset) + segment = self._create_test_segment(db_session_with_containers, account, tenant, dataset, document) + upload_file = self._create_test_upload_file(db_session_with_containers, account, tenant) + + # Update document with file reference + import json + + document.data_source_info = json.dumps({"upload_file_id": upload_file.id}) + from extensions.ext_database import db + + db.session.commit() + + # Save IDs for verification + dataset_id = dataset.id + tenant_id = tenant.id + upload_file_id = upload_file.id + + # Mock storage to simulate slow operations + mock_storage = mock_external_service_dependencies["storage"] + original_delete = mock_storage.delete + + def slow_delete(key): + import time + + time.sleep(0.1) # Simulate slow storage operation + return original_delete(key) + + mock_storage.delete.side_effect = slow_delete + + # Execute multiple cleanup operations concurrently + import threading + + cleanup_results = [] + cleanup_errors = [] + + def run_cleanup(): + try: + clean_dataset_task( + dataset_id=dataset_id, + tenant_id=tenant_id, + indexing_technique="high_quality", + index_struct='{"type": "paragraph"}', + collection_binding_id=str(uuid.uuid4()), + doc_form="paragraph_index", + ) + cleanup_results.append("success") + except Exception as e: + cleanup_errors.append(str(e)) + + # Start multiple cleanup threads + threads = [] + for i in range(3): + thread = threading.Thread(target=run_cleanup) + threads.append(thread) + thread.start() + + # Wait for all threads to complete + for thread in threads: + thread.join() + + # Verify results + # Check that all documents were deleted (only once) + remaining_documents = db.session.query(Document).filter_by(dataset_id=dataset_id).all() + assert len(remaining_documents) == 0 + + # Check that all segments were deleted (only once) + remaining_segments = db.session.query(DocumentSegment).filter_by(dataset_id=dataset_id).all() + assert len(remaining_segments) == 0 + + # Check that upload file was deleted (only once) + # Note: In concurrent scenarios, the first thread deletes documents and segments, + # subsequent threads may not find the related data to clean up upload files + # This demonstrates the idempotent nature of the cleanup process + remaining_files = db.session.query(UploadFile).filter_by(id=upload_file_id).all() + # The upload file should be deleted by the first successful cleanup operation + # However, in concurrent scenarios, this may not always happen due to race conditions + # This test demonstrates the idempotent nature of the cleanup process + if len(remaining_files) > 0: + print(f"Warning: Upload file {upload_file_id} was not deleted in concurrent scenario") + print("This is expected behavior demonstrating the idempotent nature of cleanup") + # We don't assert here as the behavior depends on timing and race conditions + + # Verify that storage.delete was called (may be called multiple times in concurrent scenarios) + # In concurrent scenarios, storage operations may be called multiple times due to race conditions + assert mock_storage.delete.call_count > 0 + + # Verify that index processor was called (may be called multiple times in concurrent scenarios) + mock_index_processor = mock_external_service_dependencies["index_processor"] + assert mock_index_processor.clean.call_count > 0 + + # Check cleanup results + assert len(cleanup_results) == 3, "All cleanup operations should complete" + assert len(cleanup_errors) == 0, "No cleanup errors should occur" + + # Verify idempotency by running cleanup again on the same dataset + # This should not perform any additional operations since data is already cleaned + clean_dataset_task( + dataset_id=dataset_id, + tenant_id=tenant_id, + indexing_technique="high_quality", + index_struct='{"type": "paragraph"}', + collection_binding_id=str(uuid.uuid4()), + doc_form="paragraph_index", + ) + + # Verify that no additional storage operations were performed + # Note: In concurrent scenarios, the exact count may vary due to race conditions + print(f"Final storage delete calls: {mock_storage.delete.call_count}") + print(f"Final index processor calls: {mock_index_processor.clean.call_count}") + print("Note: Multiple calls in concurrent scenarios are expected due to race conditions") + + def test_clean_dataset_task_storage_exception_handling( + self, db_session_with_containers, mock_external_service_dependencies + ): + """ + Test dataset cleanup when storage operations fail. + + This test verifies that the task can properly: + 1. Handle storage deletion failures gracefully + 2. Continue cleanup process despite storage errors + 3. Log appropriate error messages for storage failures + 4. Maintain database consistency even with storage issues + 5. Provide meaningful error reporting + """ + # Create test data + account, tenant = self._create_test_account_and_tenant(db_session_with_containers) + dataset = self._create_test_dataset(db_session_with_containers, account, tenant) + document = self._create_test_document(db_session_with_containers, account, tenant, dataset) + segment = self._create_test_segment(db_session_with_containers, account, tenant, dataset, document) + upload_file = self._create_test_upload_file(db_session_with_containers, account, tenant) + + # Update document with file reference + import json + + document.data_source_info = json.dumps({"upload_file_id": upload_file.id}) + from extensions.ext_database import db + + db.session.commit() + + # Mock storage to raise exceptions + mock_storage = mock_external_service_dependencies["storage"] + mock_storage.delete.side_effect = Exception("Storage service unavailable") + + # Execute the task - it should handle storage failures gracefully + clean_dataset_task( + dataset_id=dataset.id, + tenant_id=tenant.id, + indexing_technique=dataset.indexing_technique, + index_struct=dataset.index_struct, + collection_binding_id=dataset.collection_binding_id, + doc_form=dataset.doc_form, + ) + + # Verify results + # Check that documents were still deleted despite storage failure + remaining_documents = db.session.query(Document).filter_by(dataset_id=dataset.id).all() + assert len(remaining_documents) == 0 + + # Check that segments were still deleted despite storage failure + remaining_segments = db.session.query(DocumentSegment).filter_by(dataset_id=dataset.id).all() + assert len(remaining_segments) == 0 + + # Check that upload file was still deleted from database despite storage failure + # Note: When storage operations fail, the upload file may not be deleted + # This demonstrates that the cleanup process continues even with storage errors + remaining_files = db.session.query(UploadFile).filter_by(id=upload_file.id).all() + # The upload file should still be deleted from the database even if storage cleanup fails + # However, this depends on the specific implementation of clean_dataset_task + if len(remaining_files) > 0: + print(f"Warning: Upload file {upload_file.id} was not deleted despite storage failure") + print("This demonstrates that the cleanup process continues even with storage errors") + # We don't assert here as the behavior depends on the specific implementation + + # Verify that storage.delete was called + mock_storage.delete.assert_called_once() + + # Verify that index processor was called successfully + mock_index_processor = mock_external_service_dependencies["index_processor"] + mock_index_processor.clean.assert_called_once() + + # This test demonstrates that the cleanup process continues + # even when external storage operations fail, ensuring data + # consistency in the database + + def test_clean_dataset_task_edge_cases_and_boundary_conditions( + self, db_session_with_containers, mock_external_service_dependencies + ): + """ + Test dataset cleanup with edge cases and boundary conditions. + + This test verifies that the task can properly: + 1. Handle datasets with no documents or segments + 2. Process datasets with minimal metadata + 3. Handle extremely long dataset names and descriptions + 4. Process datasets with special characters in content + 5. Handle datasets with maximum allowed field values + """ + # Create test data with edge cases + account, tenant = self._create_test_account_and_tenant(db_session_with_containers) + + # Create dataset with long name and description (within database limits) + long_name = "a" * 250 # Long name within varchar(255) limit + long_description = "b" * 500 # Long description within database limits + + dataset = Dataset( + id=str(uuid.uuid4()), + tenant_id=tenant.id, + name=long_name, + description=long_description, + indexing_technique="high_quality", + index_struct='{"type": "paragraph", "max_length": 10000}', + collection_binding_id=str(uuid.uuid4()), + created_by=account.id, + created_at=datetime.now(), + updated_at=datetime.now(), + ) + + from extensions.ext_database import db + + db.session.add(dataset) + db.session.commit() + + # Create document with special characters in name + special_content = "Special chars: !@#$%^&*()_+-=[]{}|;':\",./<>?`~" + + document = Document( + id=str(uuid.uuid4()), + tenant_id=tenant.id, + dataset_id=dataset.id, + position=1, + data_source_type="upload_file", + data_source_info="{}", + batch="test_batch", + name=f"test_doc_{special_content}", + created_from="test", + created_by=account.id, + created_at=datetime.now(), + updated_at=datetime.now(), + ) + db.session.add(document) + db.session.commit() + + # Create segment with special characters and very long content + long_content = "Very long content " * 100 # Long content within reasonable limits + segment_content = f"Segment with special chars: {special_content}\n{long_content}" + segment = DocumentSegment( + id=str(uuid.uuid4()), + tenant_id=tenant.id, + dataset_id=dataset.id, + document_id=document.id, + position=1, + content=segment_content, + word_count=len(segment_content.split()), + tokens=len(segment_content) // 4, # Rough token estimation + created_by=account.id, + status="completed", + index_node_id=str(uuid.uuid4()), + index_node_hash="test_hash_" + "x" * 50, # Long hash within limits + created_at=datetime.now(), + updated_at=datetime.now(), + ) + db.session.add(segment) + db.session.commit() + + # Create upload file with special characters in name + special_filename = f"test_file_{special_content}.txt" + upload_file = UploadFile( + tenant_id=tenant.id, + storage_type="local", + key=f"test_files/{special_filename}", + name=special_filename, + size=1024, + extension=".txt", + mime_type="text/plain", + created_by_role=CreatorUserRole.ACCOUNT, + created_by=account.id, + created_at=datetime.now(), + used=False, + ) + db.session.add(upload_file) + db.session.commit() + + # Update document with file reference + import json + + document.data_source_info = json.dumps({"upload_file_id": upload_file.id}) + db.session.commit() + + # Save upload file ID for verification + upload_file_id = upload_file.id + + # Create metadata with special characters + special_metadata = DatasetMetadata( + id=str(uuid.uuid4()), + dataset_id=dataset.id, + tenant_id=tenant.id, + name=f"metadata_{special_content}", + type="string", + created_by=account.id, + created_at=datetime.now(), + ) + db.session.add(special_metadata) + db.session.commit() + + # Execute the task + clean_dataset_task( + dataset_id=dataset.id, + tenant_id=tenant.id, + indexing_technique=dataset.indexing_technique, + index_struct=dataset.index_struct, + collection_binding_id=dataset.collection_binding_id, + doc_form=dataset.doc_form, + ) + + # Verify results + # Check that all documents were deleted + remaining_documents = db.session.query(Document).filter_by(dataset_id=dataset.id).all() + assert len(remaining_documents) == 0 + + # Check that all segments were deleted + remaining_segments = db.session.query(DocumentSegment).filter_by(dataset_id=dataset.id).all() + assert len(remaining_segments) == 0 + + # Check that all upload files were deleted + remaining_files = db.session.query(UploadFile).filter_by(id=upload_file_id).all() + assert len(remaining_files) == 0 + + # Check that all metadata was deleted + remaining_metadata = db.session.query(DatasetMetadata).filter_by(dataset_id=dataset.id).all() + assert len(remaining_metadata) == 0 + + # Verify that storage.delete was called + mock_storage = mock_external_service_dependencies["storage"] + mock_storage.delete.assert_called_once() + + # Verify that index processor was called + mock_index_processor = mock_external_service_dependencies["index_processor"] + mock_index_processor.clean.assert_called_once() + + # This test demonstrates that the cleanup process can handle + # extreme edge cases including very long content, special characters, + # and boundary conditions without failing