diff --git a/api/configs/feature/__init__.py b/api/configs/feature/__init__.py
index 7caa6df79c..26a5a5eb54 100644
--- a/api/configs/feature/__init__.py
+++ b/api/configs/feature/__init__.py
@@ -373,11 +373,11 @@ class HttpConfig(BaseSettings):
)
HTTP_REQUEST_MAX_READ_TIMEOUT: int = Field(
- ge=1, description="Maximum read timeout in seconds for HTTP requests", default=60
+ ge=1, description="Maximum read timeout in seconds for HTTP requests", default=600
)
HTTP_REQUEST_MAX_WRITE_TIMEOUT: int = Field(
- ge=1, description="Maximum write timeout in seconds for HTTP requests", default=20
+ ge=1, description="Maximum write timeout in seconds for HTTP requests", default=600
)
HTTP_REQUEST_NODE_MAX_BINARY_SIZE: PositiveInt = Field(
@@ -782,7 +782,7 @@ class MailConfig(BaseSettings):
MAIL_TEMPLATING_TIMEOUT: int = Field(
description="""
- Timeout for email templating in seconds. Used to prevent infinite loops in malicious templates.
+ Timeout for email templating in seconds. Used to prevent infinite loops in malicious templates.
Only available in sandbox mode.""",
default=3,
)
diff --git a/api/constants/__init__.py b/api/constants/__init__.py
index fe8f4f8785..9141fbea95 100644
--- a/api/constants/__init__.py
+++ b/api/constants/__init__.py
@@ -1,4 +1,5 @@
from configs import dify_config
+from libs.collection_utils import convert_to_lower_and_upper_set
HIDDEN_VALUE = "[__HIDDEN__]"
UNKNOWN_VALUE = "[__UNKNOWN__]"
@@ -6,24 +7,39 @@ UUID_NIL = "00000000-0000-0000-0000-000000000000"
DEFAULT_FILE_NUMBER_LIMITS = 3
-IMAGE_EXTENSIONS = ["jpg", "jpeg", "png", "webp", "gif", "svg"]
-IMAGE_EXTENSIONS.extend([ext.upper() for ext in IMAGE_EXTENSIONS])
+IMAGE_EXTENSIONS = convert_to_lower_and_upper_set({"jpg", "jpeg", "png", "webp", "gif", "svg"})
-VIDEO_EXTENSIONS = ["mp4", "mov", "mpeg", "webm"]
-VIDEO_EXTENSIONS.extend([ext.upper() for ext in VIDEO_EXTENSIONS])
+VIDEO_EXTENSIONS = convert_to_lower_and_upper_set({"mp4", "mov", "mpeg", "webm"})
-AUDIO_EXTENSIONS = ["mp3", "m4a", "wav", "amr", "mpga"]
-AUDIO_EXTENSIONS.extend([ext.upper() for ext in AUDIO_EXTENSIONS])
+AUDIO_EXTENSIONS = convert_to_lower_and_upper_set({"mp3", "m4a", "wav", "amr", "mpga"})
-
-_doc_extensions: list[str]
+_doc_extensions: set[str]
if dify_config.ETL_TYPE == "Unstructured":
- _doc_extensions = ["txt", "markdown", "md", "mdx", "pdf", "html", "htm", "xlsx", "xls", "vtt", "properties"]
- _doc_extensions.extend(("doc", "docx", "csv", "eml", "msg", "pptx", "xml", "epub"))
+ _doc_extensions = {
+ "txt",
+ "markdown",
+ "md",
+ "mdx",
+ "pdf",
+ "html",
+ "htm",
+ "xlsx",
+ "xls",
+ "vtt",
+ "properties",
+ "doc",
+ "docx",
+ "csv",
+ "eml",
+ "msg",
+ "pptx",
+ "xml",
+ "epub",
+ }
if dify_config.UNSTRUCTURED_API_URL:
- _doc_extensions.append("ppt")
+ _doc_extensions.add("ppt")
else:
- _doc_extensions = [
+ _doc_extensions = {
"txt",
"markdown",
"md",
@@ -37,5 +53,5 @@ else:
"csv",
"vtt",
"properties",
- ]
-DOCUMENT_EXTENSIONS = _doc_extensions + [ext.upper() for ext in _doc_extensions]
+ }
+DOCUMENT_EXTENSIONS: set[str] = convert_to_lower_and_upper_set(_doc_extensions)
diff --git a/api/core/app/apps/base_app_runner.py b/api/core/app/apps/base_app_runner.py
index e7db3bc41b..61ac040c05 100644
--- a/api/core/app/apps/base_app_runner.py
+++ b/api/core/app/apps/base_app_runner.py
@@ -61,9 +61,6 @@ class AppRunner:
if model_context_tokens is None:
return -1
- if max_tokens is None:
- max_tokens = 0
-
prompt_tokens = model_instance.get_llm_num_tokens(prompt_messages)
if prompt_tokens + max_tokens > model_context_tokens:
diff --git a/api/core/plugin/utils/chunk_merger.py b/api/core/plugin/utils/chunk_merger.py
index e30076f9d3..28cb70f96a 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, cast
+from typing import TypeVar, Union
from core.agent.entities import AgentInvokeMessage
from core.tools.entities.tool_entities import ToolInvokeMessage
@@ -87,7 +87,8 @@ def merge_blob_chunks(
),
meta=resp.meta,
)
- yield cast(MessageType, merged_message)
+ assert isinstance(merged_message, (ToolInvokeMessage, AgentInvokeMessage))
+ yield merged_message # type: ignore
# Clean up the buffer
del files[chunk_id]
else:
diff --git a/api/core/workflow/nodes/iteration/iteration_node.py b/api/core/workflow/nodes/iteration/iteration_node.py
index a05a6b1b96..965e22b74c 100644
--- a/api/core/workflow/nodes/iteration/iteration_node.py
+++ b/api/core/workflow/nodes/iteration/iteration_node.py
@@ -342,10 +342,13 @@ class IterationNode(Node):
iterator_list_value: Sequence[object],
iter_run_map: dict[str, float],
) -> Generator[NodeEventBase, None, None]:
+ # Flatten the list of lists if all outputs are lists
+ flattened_outputs = self._flatten_outputs_if_needed(outputs)
+
yield IterationSucceededEvent(
start_at=started_at,
inputs=inputs,
- outputs={"output": outputs},
+ outputs={"output": flattened_outputs},
steps=len(iterator_list_value),
metadata={
WorkflowNodeExecutionMetadataKey.TOTAL_TOKENS: self.graph_runtime_state.total_tokens,
@@ -357,13 +360,39 @@ class IterationNode(Node):
yield StreamCompletedEvent(
node_run_result=NodeRunResult(
status=WorkflowNodeExecutionStatus.SUCCEEDED,
- outputs={"output": outputs},
+ outputs={"output": flattened_outputs},
metadata={
WorkflowNodeExecutionMetadataKey.TOTAL_TOKENS: self.graph_runtime_state.total_tokens,
},
)
)
+ def _flatten_outputs_if_needed(self, outputs: list[object]) -> list[object]:
+ """
+ Flatten the outputs list if all elements are lists.
+ This maintains backward compatibility with version 1.8.1 behavior.
+ """
+ if not outputs:
+ return outputs
+
+ # Check if all non-None outputs are lists
+ non_none_outputs = [output for output in outputs if output is not None]
+ if not non_none_outputs:
+ return outputs
+
+ if all(isinstance(output, list) for output in non_none_outputs):
+ # Flatten the list of lists
+ flattened: list[Any] = []
+ for output in outputs:
+ if isinstance(output, list):
+ flattened.extend(output)
+ elif output is not None:
+ # This shouldn't happen based on our check, but handle it gracefully
+ flattened.append(output)
+ return flattened
+
+ return outputs
+
def _handle_iteration_failure(
self,
started_at: datetime,
@@ -373,10 +402,13 @@ class IterationNode(Node):
iter_run_map: dict[str, float],
error: IterationNodeError,
) -> Generator[NodeEventBase, None, None]:
+ # Flatten the list of lists if all outputs are lists (even in failure case)
+ flattened_outputs = self._flatten_outputs_if_needed(outputs)
+
yield IterationFailedEvent(
start_at=started_at,
inputs=inputs,
- outputs={"output": outputs},
+ outputs={"output": flattened_outputs},
steps=len(iterator_list_value),
metadata={
WorkflowNodeExecutionMetadataKey.TOTAL_TOKENS: self.graph_runtime_state.total_tokens,
diff --git a/api/core/workflow/nodes/knowledge_index/knowledge_index_node.py b/api/core/workflow/nodes/knowledge_index/knowledge_index_node.py
index 8d685fa82e..05e0c7707a 100644
--- a/api/core/workflow/nodes/knowledge_index/knowledge_index_node.py
+++ b/api/core/workflow/nodes/knowledge_index/knowledge_index_node.py
@@ -2,7 +2,7 @@ import datetime
import logging
import time
from collections.abc import Mapping
-from typing import Any, cast
+from typing import Any
from sqlalchemy import func, select
@@ -62,7 +62,7 @@ class KnowledgeIndexNode(Node):
return self._node_data
def _run(self) -> NodeRunResult: # type: ignore
- node_data = cast(KnowledgeIndexNodeData, self._node_data)
+ node_data = self._node_data
variable_pool = self.graph_runtime_state.variable_pool
dataset_id = variable_pool.get(["sys", SystemVariableKey.DATASET_ID])
if not dataset_id:
diff --git a/api/extensions/ext_otel.py b/api/extensions/ext_otel.py
index b0059693e2..19c6e68c6b 100644
--- a/api/extensions/ext_otel.py
+++ b/api/extensions/ext_otel.py
@@ -136,6 +136,7 @@ def init_app(app: DifyApp):
from opentelemetry.exporter.otlp.proto.http.trace_exporter import OTLPSpanExporter as HTTPSpanExporter
from opentelemetry.instrumentation.celery import CeleryInstrumentor
from opentelemetry.instrumentation.flask import FlaskInstrumentor
+ from opentelemetry.instrumentation.httpx import HTTPXClientInstrumentor
from opentelemetry.instrumentation.redis import RedisInstrumentor
from opentelemetry.instrumentation.requests import RequestsInstrumentor
from opentelemetry.instrumentation.sqlalchemy import SQLAlchemyInstrumentor
@@ -238,6 +239,7 @@ def init_app(app: DifyApp):
init_sqlalchemy_instrumentor(app)
RedisInstrumentor().instrument()
RequestsInstrumentor().instrument()
+ HTTPXClientInstrumentor().instrument()
atexit.register(shutdown_tracer)
diff --git a/api/libs/collection_utils.py b/api/libs/collection_utils.py
new file mode 100644
index 0000000000..f97308ca44
--- /dev/null
+++ b/api/libs/collection_utils.py
@@ -0,0 +1,14 @@
+def convert_to_lower_and_upper_set(inputs: list[str] | set[str]) -> set[str]:
+ """
+ Convert a list or set of strings to a set containing both lower and upper case versions of each string.
+
+ Args:
+ inputs (list[str] | set[str]): A list or set of strings to be converted.
+
+ Returns:
+ set[str]: A set containing both lower and upper case versions of each string.
+ """
+ if not inputs:
+ return set()
+ else:
+ return {case for s in inputs if s for case in (s.lower(), s.upper())}
diff --git a/api/pyproject.toml b/api/pyproject.toml
index 033b5ceb1f..b93ea8265f 100644
--- a/api/pyproject.toml
+++ b/api/pyproject.toml
@@ -46,6 +46,7 @@ dependencies = [
"opentelemetry-instrumentation==0.48b0",
"opentelemetry-instrumentation-celery==0.48b0",
"opentelemetry-instrumentation-flask==0.48b0",
+ "opentelemetry-instrumentation-httpx==0.48b0",
"opentelemetry-instrumentation-redis==0.48b0",
"opentelemetry-instrumentation-requests==0.48b0",
"opentelemetry-instrumentation-sqlalchemy==0.48b0",
diff --git a/api/pyrightconfig.json b/api/pyrightconfig.json
index c733059331..67571316a9 100644
--- a/api/pyrightconfig.json
+++ b/api/pyrightconfig.json
@@ -12,6 +12,7 @@
"flask_login",
"opentelemetry.instrumentation.celery",
"opentelemetry.instrumentation.flask",
+ "opentelemetry.instrumentation.httpx",
"opentelemetry.instrumentation.requests",
"opentelemetry.instrumentation.sqlalchemy",
"opentelemetry.instrumentation.redis"
@@ -23,9 +24,7 @@
"reportUnknownLambdaType": "hint",
"reportMissingParameterType": "hint",
"reportMissingTypeArgument": "hint",
- "reportUnnecessaryContains": "hint",
"reportUnnecessaryComparison": "hint",
- "reportUnnecessaryCast": "hint",
"reportUnnecessaryIsInstance": "hint",
"reportUntypedFunctionDecorator": "hint",
diff --git a/api/services/rag_pipeline/rag_pipeline_transform_service.py b/api/services/rag_pipeline/rag_pipeline_transform_service.py
index db9508824b..3d5a85b57f 100644
--- a/api/services/rag_pipeline/rag_pipeline_transform_service.py
+++ b/api/services/rag_pipeline/rag_pipeline_transform_service.py
@@ -149,8 +149,7 @@ class RagPipelineTransformService:
file_extensions = node.get("data", {}).get("fileExtensions", [])
if not file_extensions:
return node
- file_extensions = [file_extension.lower() for file_extension in file_extensions]
- node["data"]["fileExtensions"] = DOCUMENT_EXTENSIONS
+ node["data"]["fileExtensions"] = [ext.lower() for ext in file_extensions if ext in DOCUMENT_EXTENSIONS]
return node
def _deal_knowledge_index(
diff --git a/api/services/tools/mcp_tools_manage_service.py b/api/services/tools/mcp_tools_manage_service.py
index dd626dd615..605ad8379b 100644
--- a/api/services/tools/mcp_tools_manage_service.py
+++ b/api/services/tools/mcp_tools_manage_service.py
@@ -1,7 +1,7 @@
import hashlib
import json
from datetime import datetime
-from typing import Any, cast
+from typing import Any
from sqlalchemy import or_
from sqlalchemy.exc import IntegrityError
@@ -55,7 +55,7 @@ class MCPToolManageService:
cache=NoOpProviderCredentialCache(),
)
- return cast(dict[str, str], encrypter_instance.encrypt(headers))
+ return encrypter_instance.encrypt(headers)
@staticmethod
def get_mcp_provider_by_provider_id(provider_id: str, tenant_id: str) -> MCPToolProvider:
diff --git a/api/tasks/workflow_draft_var_tasks.py b/api/tasks/workflow_draft_var_tasks.py
index 457d46a9d8..fcb98ec39e 100644
--- a/api/tasks/workflow_draft_var_tasks.py
+++ b/api/tasks/workflow_draft_var_tasks.py
@@ -5,15 +5,10 @@ These tasks provide asynchronous storage capabilities for workflow execution dat
improving performance by offloading storage operations to background workers.
"""
-import logging
-
from celery import shared_task # type: ignore[import-untyped]
from sqlalchemy.orm import Session
from extensions.ext_database import db
-
-_logger = logging.getLogger(__name__)
-
from services.workflow_draft_variable_service import DraftVarFileDeletion, WorkflowDraftVariableService
diff --git a/api/tests/unit_tests/configs/test_dify_config.py b/api/tests/unit_tests/configs/test_dify_config.py
index 2968de4b91..209b6bf59b 100644
--- a/api/tests/unit_tests/configs/test_dify_config.py
+++ b/api/tests/unit_tests/configs/test_dify_config.py
@@ -15,13 +15,13 @@ def test_dify_config(monkeypatch: pytest.MonkeyPatch):
# Set environment variables using monkeypatch
monkeypatch.setenv("CONSOLE_API_URL", "https://example.com")
monkeypatch.setenv("CONSOLE_WEB_URL", "https://example.com")
- monkeypatch.setenv("HTTP_REQUEST_MAX_WRITE_TIMEOUT", "30")
+ monkeypatch.setenv("HTTP_REQUEST_MAX_WRITE_TIMEOUT", "30") # Custom value for testing
monkeypatch.setenv("DB_USERNAME", "postgres")
monkeypatch.setenv("DB_PASSWORD", "postgres")
monkeypatch.setenv("DB_HOST", "localhost")
monkeypatch.setenv("DB_PORT", "5432")
monkeypatch.setenv("DB_DATABASE", "dify")
- monkeypatch.setenv("HTTP_REQUEST_MAX_READ_TIMEOUT", "600")
+ monkeypatch.setenv("HTTP_REQUEST_MAX_READ_TIMEOUT", "300") # Custom value for testing
# load dotenv file with pydantic-settings
config = DifyConfig()
@@ -35,16 +35,36 @@ def test_dify_config(monkeypatch: pytest.MonkeyPatch):
assert config.SENTRY_TRACES_SAMPLE_RATE == 1.0
assert config.TEMPLATE_TRANSFORM_MAX_LENGTH == 400_000
- # annotated field with default value
- assert config.HTTP_REQUEST_MAX_READ_TIMEOUT == 600
+ # annotated field with custom configured value
+ assert config.HTTP_REQUEST_MAX_READ_TIMEOUT == 300
- # annotated field with configured value
+ # annotated field with custom configured value
assert config.HTTP_REQUEST_MAX_WRITE_TIMEOUT == 30
# values from pyproject.toml
assert Version(config.project.version) >= Version("1.0.0")
+def test_http_timeout_defaults(monkeypatch: pytest.MonkeyPatch):
+ """Test that HTTP timeout defaults are correctly set"""
+ # clear system environment variables
+ os.environ.clear()
+
+ # Set minimal required env vars
+ monkeypatch.setenv("DB_USERNAME", "postgres")
+ monkeypatch.setenv("DB_PASSWORD", "postgres")
+ monkeypatch.setenv("DB_HOST", "localhost")
+ monkeypatch.setenv("DB_PORT", "5432")
+ monkeypatch.setenv("DB_DATABASE", "dify")
+
+ config = DifyConfig()
+
+ # Verify default timeout values
+ assert config.HTTP_REQUEST_MAX_CONNECT_TIMEOUT == 10
+ assert config.HTTP_REQUEST_MAX_READ_TIMEOUT == 600
+ assert config.HTTP_REQUEST_MAX_WRITE_TIMEOUT == 600
+
+
# NOTE: If there is a `.env` file in your Workspace, this test might not succeed as expected.
# This is due to `pymilvus` loading all the variables from the `.env` file into `os.environ`.
def test_flask_configs(monkeypatch: pytest.MonkeyPatch):
@@ -55,7 +75,6 @@ def test_flask_configs(monkeypatch: pytest.MonkeyPatch):
# Set environment variables using monkeypatch
monkeypatch.setenv("CONSOLE_API_URL", "https://example.com")
monkeypatch.setenv("CONSOLE_WEB_URL", "https://example.com")
- monkeypatch.setenv("HTTP_REQUEST_MAX_WRITE_TIMEOUT", "30")
monkeypatch.setenv("DB_USERNAME", "postgres")
monkeypatch.setenv("DB_PASSWORD", "postgres")
monkeypatch.setenv("DB_HOST", "localhost")
@@ -105,7 +124,6 @@ def test_inner_api_config_exist(monkeypatch: pytest.MonkeyPatch):
# Set environment variables using monkeypatch
monkeypatch.setenv("CONSOLE_API_URL", "https://example.com")
monkeypatch.setenv("CONSOLE_WEB_URL", "https://example.com")
- monkeypatch.setenv("HTTP_REQUEST_MAX_WRITE_TIMEOUT", "30")
monkeypatch.setenv("DB_USERNAME", "postgres")
monkeypatch.setenv("DB_PASSWORD", "postgres")
monkeypatch.setenv("DB_HOST", "localhost")
diff --git a/api/uv.lock b/api/uv.lock
index d27cd4c814..aa5c4fe63c 100644
--- a/api/uv.lock
+++ b/api/uv.lock
@@ -1337,6 +1337,7 @@ dependencies = [
{ name = "opentelemetry-instrumentation" },
{ name = "opentelemetry-instrumentation-celery" },
{ name = "opentelemetry-instrumentation-flask" },
+ { name = "opentelemetry-instrumentation-httpx" },
{ name = "opentelemetry-instrumentation-redis" },
{ name = "opentelemetry-instrumentation-requests" },
{ name = "opentelemetry-instrumentation-sqlalchemy" },
@@ -1528,6 +1529,7 @@ requires-dist = [
{ name = "opentelemetry-instrumentation", specifier = "==0.48b0" },
{ name = "opentelemetry-instrumentation-celery", specifier = "==0.48b0" },
{ name = "opentelemetry-instrumentation-flask", specifier = "==0.48b0" },
+ { name = "opentelemetry-instrumentation-httpx", specifier = "==0.48b0" },
{ name = "opentelemetry-instrumentation-redis", specifier = "==0.48b0" },
{ name = "opentelemetry-instrumentation-requests", specifier = "==0.48b0" },
{ name = "opentelemetry-instrumentation-sqlalchemy", specifier = "==0.48b0" },
@@ -3893,6 +3895,21 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/78/3d/fcde4f8f0bf9fa1ee73a12304fa538076fb83fe0a2ae966ab0f0b7da5109/opentelemetry_instrumentation_flask-0.48b0-py3-none-any.whl", hash = "sha256:26b045420b9d76e85493b1c23fcf27517972423480dc6cf78fd6924248ba5808", size = 14588, upload-time = "2024-08-28T21:26:58.504Z" },
]
+[[package]]
+name = "opentelemetry-instrumentation-httpx"
+version = "0.48b0"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "opentelemetry-api" },
+ { name = "opentelemetry-instrumentation" },
+ { name = "opentelemetry-semantic-conventions" },
+ { name = "opentelemetry-util-http" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/d3/d9/c65d818607c16d1b7ea8d2de6111c6cecadf8d2fd38c1885a72733a7c6d3/opentelemetry_instrumentation_httpx-0.48b0.tar.gz", hash = "sha256:ee977479e10398931921fb995ac27ccdeea2e14e392cb27ef012fc549089b60a", size = 16931, upload-time = "2024-08-28T21:28:03.794Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/c2/fe/f2daa9d6d988c093b8c7b1d35df675761a8ece0b600b035dc04982746c9d/opentelemetry_instrumentation_httpx-0.48b0-py3-none-any.whl", hash = "sha256:d94f9d612c82d09fe22944d1904a30a464c19bea2ba76be656c99a28ad8be8e5", size = 13900, upload-time = "2024-08-28T21:27:01.566Z" },
+]
+
[[package]]
name = "opentelemetry-instrumentation-redis"
version = "0.48b0"
diff --git a/docker/.env.example b/docker/.env.example
index 65bfbfb41d..6b14641a74 100644
--- a/docker/.env.example
+++ b/docker/.env.example
@@ -930,6 +930,16 @@ WORKFLOW_LOG_CLEANUP_BATCH_SIZE=100
HTTP_REQUEST_NODE_MAX_BINARY_SIZE=10485760
HTTP_REQUEST_NODE_MAX_TEXT_SIZE=1048576
HTTP_REQUEST_NODE_SSL_VERIFY=True
+
+# HTTP request node timeout configuration
+# Maximum timeout values (in seconds) that users can set in HTTP request nodes
+# - Connect timeout: Time to wait for establishing connection (default: 10s)
+# - Read timeout: Time to wait for receiving response data (default: 600s, 10 minutes)
+# - Write timeout: Time to wait for sending request data (default: 600s, 10 minutes)
+HTTP_REQUEST_MAX_CONNECT_TIMEOUT=10
+HTTP_REQUEST_MAX_READ_TIMEOUT=600
+HTTP_REQUEST_MAX_WRITE_TIMEOUT=600
+
# Base64 encoded CA certificate data for custom certificate verification (PEM format, optional)
# HTTP_REQUEST_NODE_SSL_CERT_DATA=LS0tLS1CRUdJTi...
# Base64 encoded client certificate data for mutual TLS authentication (PEM format, optional)
diff --git a/docker/docker-compose.yaml b/docker/docker-compose.yaml
index 898ae81f11..7db470e13f 100644
--- a/docker/docker-compose.yaml
+++ b/docker/docker-compose.yaml
@@ -419,6 +419,9 @@ x-shared-env: &shared-api-worker-env
HTTP_REQUEST_NODE_MAX_TEXT_SIZE: ${HTTP_REQUEST_NODE_MAX_TEXT_SIZE:-1048576}
HTTP_REQUEST_NODE_SSL_VERIFY: ${HTTP_REQUEST_NODE_SSL_VERIFY:-True}
WEBHOOK_REQUEST_BODY_MAX_SIZE: ${WEBHOOK_REQUEST_BODY_MAX_SIZE:-10485760}
+ HTTP_REQUEST_MAX_CONNECT_TIMEOUT: ${HTTP_REQUEST_MAX_CONNECT_TIMEOUT:-10}
+ HTTP_REQUEST_MAX_READ_TIMEOUT: ${HTTP_REQUEST_MAX_READ_TIMEOUT:-600}
+ HTTP_REQUEST_MAX_WRITE_TIMEOUT: ${HTTP_REQUEST_MAX_WRITE_TIMEOUT:-600}
RESPECT_XFORWARD_HEADERS_ENABLED: ${RESPECT_XFORWARD_HEADERS_ENABLED:-false}
SSRF_PROXY_HTTP_URL: ${SSRF_PROXY_HTTP_URL:-http://ssrf_proxy:3128}
SSRF_PROXY_HTTPS_URL: ${SSRF_PROXY_HTTPS_URL:-http://ssrf_proxy:3128}
diff --git a/web/__tests__/goto-anything/command-selector.test.tsx b/web/__tests__/goto-anything/command-selector.test.tsx
index 1db4be31fb..6d4e045d49 100644
--- a/web/__tests__/goto-anything/command-selector.test.tsx
+++ b/web/__tests__/goto-anything/command-selector.test.tsx
@@ -16,7 +16,7 @@ jest.mock('cmdk', () => ({
Item: ({ children, onSelect, value, className }: any) => (
onSelect && onSelect()}
+ onClick={() => onSelect?.()}
data-value={value}
data-testid={`command-item-${value}`}
>
diff --git a/web/app/(commonLayout)/app/(appDetailLayout)/[appId]/overview/tracing/config-button.tsx b/web/app/(commonLayout)/app/(appDetailLayout)/[appId]/overview/tracing/config-button.tsx
index 1ab40e31bf..246a1eb6a3 100644
--- a/web/app/(commonLayout)/app/(appDetailLayout)/[appId]/overview/tracing/config-button.tsx
+++ b/web/app/(commonLayout)/app/(appDetailLayout)/[appId]/overview/tracing/config-button.tsx
@@ -4,6 +4,7 @@ import React, { useCallback, useRef, useState } from 'react'
import type { PopupProps } from './config-popup'
import ConfigPopup from './config-popup'
+import cn from '@/utils/classnames'
import {
PortalToFollowElem,
PortalToFollowElemContent,
@@ -45,7 +46,7 @@ const ConfigBtn: FC
= ({
offset={12}
>
-
+
{children}
diff --git a/web/app/components/app/annotation/batch-add-annotation-modal/csv-uploader.tsx b/web/app/components/app/annotation/batch-add-annotation-modal/csv-uploader.tsx
index dfc8d10087..b98eb815f9 100644
--- a/web/app/components/app/annotation/batch-add-annotation-modal/csv-uploader.tsx
+++ b/web/app/components/app/annotation/batch-add-annotation-modal/csv-uploader.tsx
@@ -28,7 +28,8 @@ const CSVUploader: FC
= ({
const handleDragEnter = (e: DragEvent) => {
e.preventDefault()
e.stopPropagation()
- e.target !== dragRef.current && setDragging(true)
+ if (e.target !== dragRef.current)
+ setDragging(true)
}
const handleDragOver = (e: DragEvent) => {
e.preventDefault()
@@ -37,7 +38,8 @@ const CSVUploader: FC = ({
const handleDragLeave = (e: DragEvent) => {
e.preventDefault()
e.stopPropagation()
- e.target === dragRef.current && setDragging(false)
+ if (e.target === dragRef.current)
+ setDragging(false)
}
const handleDrop = (e: DragEvent) => {
e.preventDefault()
diff --git a/web/app/components/app/app-publisher/index.tsx b/web/app/components/app/app-publisher/index.tsx
index 6be5ce6a8a..253acddd81 100644
--- a/web/app/components/app/app-publisher/index.tsx
+++ b/web/app/components/app/app-publisher/index.tsx
@@ -348,7 +348,8 @@ const AppPublisher = ({
{
- publishedAt && handleOpenInExplore()
+ if (publishedAt)
+ handleOpenInExplore()
}}
disabled={!publishedAt || (systemFeatures.webapp_auth.enabled && !userCanAccessApp?.result)}
icon={}
diff --git a/web/app/components/app/app-publisher/version-info-modal.tsx b/web/app/components/app/app-publisher/version-info-modal.tsx
index 4d5d3705c1..263f187736 100644
--- a/web/app/components/app/app-publisher/version-info-modal.tsx
+++ b/web/app/components/app/app-publisher/version-info-modal.tsx
@@ -40,7 +40,8 @@ const VersionInfoModal: FC = ({
return
}
else {
- titleError && setTitleError(false)
+ if (titleError)
+ setTitleError(false)
}
if (releaseNotes.length > RELEASE_NOTES_MAX_LENGTH) {
@@ -52,7 +53,8 @@ const VersionInfoModal: FC = ({
return
}
else {
- releaseNotesError && setReleaseNotesError(false)
+ if (releaseNotesError)
+ setReleaseNotesError(false)
}
onPublish({ title, releaseNotes, id: versionInfo?.id })
diff --git a/web/app/components/app/configuration/base/icons/citation.tsx b/web/app/components/app/configuration/base/icons/citation.tsx
index e69de29bb2..3aa6b0f0e1 100644
--- a/web/app/components/app/configuration/base/icons/citation.tsx
+++ b/web/app/components/app/configuration/base/icons/citation.tsx
@@ -0,0 +1,29 @@
+import type { SVGProps } from 'react'
+
+const CitationIcon = (props: SVGProps) => (
+
+)
+
+export default CitationIcon
diff --git a/web/app/components/app/configuration/config-var/config-modal/index.tsx b/web/app/components/app/configuration/config-var/config-modal/index.tsx
index bedcbfedbd..8a02ca8caa 100644
--- a/web/app/components/app/configuration/config-var/config-modal/index.tsx
+++ b/web/app/components/app/configuration/config-var/config-modal/index.tsx
@@ -79,7 +79,7 @@ const ConfigModal: FC = ({
try {
return JSON.stringify(JSON.parse(tempPayload.json_schema).properties, null, 2)
}
- catch (_e) {
+ catch {
return ''
}
}, [tempPayload.json_schema])
@@ -123,7 +123,7 @@ const ConfigModal: FC = ({
}
handlePayloadChange('json_schema')(JSON.stringify(res, null, 2))
}
- catch (_e) {
+ catch {
return null
}
}, [handlePayloadChange])
diff --git a/web/app/components/app/configuration/index.tsx b/web/app/components/app/configuration/index.tsx
index f1f81ebf97..20229c9717 100644
--- a/web/app/components/app/configuration/index.tsx
+++ b/web/app/components/app/configuration/index.tsx
@@ -480,7 +480,7 @@ const Configuration: FC = () => {
Toast.notify({ type: 'warning', message: `${t('common.modelProvider.parametersInvalidRemoved')}: ${Object.entries(removedDetails).map(([k, reason]) => `${k} (${reason})`).join(', ')}` })
setCompletionParams(filtered)
}
- catch (e) {
+ catch {
Toast.notify({ type: 'error', message: t('common.error') })
setCompletionParams({})
}
diff --git a/web/app/components/app/configuration/prompt-value-panel/index.tsx b/web/app/components/app/configuration/prompt-value-panel/index.tsx
index e88268ba40..43c836132f 100644
--- a/web/app/components/app/configuration/prompt-value-panel/index.tsx
+++ b/web/app/components/app/configuration/prompt-value-panel/index.tsx
@@ -192,7 +192,7 @@ const PromptValuePanel: FC = ({
)}
diff --git a/web/app/components/base/date-and-time-picker/types.ts b/web/app/components/base/date-and-time-picker/types.ts
index 68d6967c2b..db3c7fdbc1 100644
--- a/web/app/components/base/date-and-time-picker/types.ts
+++ b/web/app/components/base/date-and-time-picker/types.ts
@@ -55,7 +55,7 @@ export type TriggerParams = {
onClick: (e: React.MouseEvent) => void
}
export type TimePickerProps = {
- value: Dayjs | undefined
+ value: Dayjs | string | undefined
timezone?: string
placeholder?: string
onChange: (date: Dayjs | undefined) => void
diff --git a/web/app/components/base/date-and-time-picker/utils/dayjs.spec.ts b/web/app/components/base/date-and-time-picker/utils/dayjs.spec.ts
new file mode 100644
index 0000000000..549ab01029
--- /dev/null
+++ b/web/app/components/base/date-and-time-picker/utils/dayjs.spec.ts
@@ -0,0 +1,67 @@
+import dayjs from './dayjs'
+import {
+ getDateWithTimezone,
+ isDayjsObject,
+ toDayjs,
+} from './dayjs'
+
+describe('dayjs utilities', () => {
+ const timezone = 'UTC'
+
+ test('toDayjs parses time-only strings with timezone support', () => {
+ const result = toDayjs('18:45', { timezone })
+ expect(result).toBeDefined()
+ expect(result?.format('HH:mm')).toBe('18:45')
+ expect(result?.utcOffset()).toBe(getDateWithTimezone({ timezone }).utcOffset())
+ })
+
+ test('toDayjs parses 12-hour time strings', () => {
+ const tz = 'America/New_York'
+ const result = toDayjs('07:15 PM', { timezone: tz })
+ expect(result).toBeDefined()
+ expect(result?.format('HH:mm')).toBe('19:15')
+ expect(result?.utcOffset()).toBe(getDateWithTimezone({ timezone: tz }).utcOffset())
+ })
+
+ test('isDayjsObject detects dayjs instances', () => {
+ const date = dayjs()
+ expect(isDayjsObject(date)).toBe(true)
+ expect(isDayjsObject(getDateWithTimezone({ timezone }))).toBe(true)
+ expect(isDayjsObject('2024-01-01')).toBe(false)
+ expect(isDayjsObject({})).toBe(false)
+ })
+
+ test('toDayjs parses datetime strings in target timezone', () => {
+ const value = '2024-05-01 12:00:00'
+ const tz = 'America/New_York'
+
+ const result = toDayjs(value, { timezone: tz })
+
+ expect(result).toBeDefined()
+ expect(result?.hour()).toBe(12)
+ expect(result?.format('YYYY-MM-DD HH:mm')).toBe('2024-05-01 12:00')
+ })
+
+ test('toDayjs parses ISO datetime strings in target timezone', () => {
+ const value = '2024-05-01T14:30:00'
+ const tz = 'Europe/London'
+
+ const result = toDayjs(value, { timezone: tz })
+
+ expect(result).toBeDefined()
+ expect(result?.hour()).toBe(14)
+ expect(result?.minute()).toBe(30)
+ })
+
+ test('toDayjs handles dates without time component', () => {
+ const value = '2024-05-01'
+ const tz = 'America/Los_Angeles'
+
+ const result = toDayjs(value, { timezone: tz })
+
+ expect(result).toBeDefined()
+ expect(result?.format('YYYY-MM-DD')).toBe('2024-05-01')
+ expect(result?.hour()).toBe(0)
+ expect(result?.minute()).toBe(0)
+ })
+})
diff --git a/web/app/components/base/date-and-time-picker/utils/dayjs.ts b/web/app/components/base/date-and-time-picker/utils/dayjs.ts
index 27200e76e9..808b50247a 100644
--- a/web/app/components/base/date-and-time-picker/utils/dayjs.ts
+++ b/web/app/components/base/date-and-time-picker/utils/dayjs.ts
@@ -10,6 +10,25 @@ dayjs.extend(timezone)
export default dayjs
const monthMaps: Record = {}
+const DEFAULT_OFFSET_STR = 'UTC+0'
+const TIME_ONLY_REGEX = /^(\d{1,2}):(\d{2})(?::(\d{2})(?:\.(\d{1,3}))?)?$/
+const TIME_ONLY_12H_REGEX = /^(\d{1,2}):(\d{2})(?::(\d{2}))?\s?(AM|PM)$/i
+
+const COMMON_PARSE_FORMATS = [
+ 'YYYY-MM-DD',
+ 'YYYY/MM/DD',
+ 'DD-MM-YYYY',
+ 'DD/MM/YYYY',
+ 'MM-DD-YYYY',
+ 'MM/DD/YYYY',
+ 'YYYY-MM-DDTHH:mm:ss.SSSZ',
+ 'YYYY-MM-DDTHH:mm:ssZ',
+ 'YYYY-MM-DD HH:mm:ss',
+ 'YYYY-MM-DDTHH:mm',
+ 'YYYY-MM-DDTHH:mmZ',
+ 'YYYY-MM-DDTHH:mm:ss',
+ 'YYYY-MM-DDTHH:mm:ss.SSS',
+]
export const cloneTime = (targetDate: Dayjs, sourceDate: Dayjs) => {
return targetDate.clone()
@@ -76,21 +95,116 @@ export const getHourIn12Hour = (date: Dayjs) => {
return hour === 0 ? 12 : hour >= 12 ? hour - 12 : hour
}
-export const getDateWithTimezone = (props: { date?: Dayjs, timezone?: string }) => {
- return props.date ? dayjs.tz(props.date, props.timezone) : dayjs().tz(props.timezone)
+export const getDateWithTimezone = ({ date, timezone }: { date?: Dayjs, timezone?: string }) => {
+ if (!timezone)
+ return (date ?? dayjs()).clone()
+ return date ? dayjs.tz(date, timezone) : dayjs().tz(timezone)
}
-// Asia/Shanghai -> UTC+8
-const DEFAULT_OFFSET_STR = 'UTC+0'
export const convertTimezoneToOffsetStr = (timezone?: string) => {
if (!timezone)
return DEFAULT_OFFSET_STR
const tzItem = tz.find(item => item.value === timezone)
- if(!tzItem)
+ if (!tzItem)
return DEFAULT_OFFSET_STR
return `UTC${tzItem.name.charAt(0)}${tzItem.name.charAt(2)}`
}
+export const isDayjsObject = (value: unknown): value is Dayjs => dayjs.isDayjs(value)
+
+export type ToDayjsOptions = {
+ timezone?: string
+ format?: string
+ formats?: string[]
+}
+
+const warnParseFailure = (value: string) => {
+ if (process.env.NODE_ENV !== 'production')
+ console.warn('[TimePicker] Failed to parse time value', value)
+}
+
+const normalizeMillisecond = (value: string | undefined) => {
+ if (!value) return 0
+ if (value.length === 3) return Number(value)
+ if (value.length > 3) return Number(value.slice(0, 3))
+ return Number(value.padEnd(3, '0'))
+}
+
+const applyTimezone = (date: Dayjs, timezone?: string) => {
+ return timezone ? getDateWithTimezone({ date, timezone }) : date
+}
+
+export const toDayjs = (value: string | Dayjs | undefined, options: ToDayjsOptions = {}): Dayjs | undefined => {
+ if (!value)
+ return undefined
+
+ const { timezone: tzName, format, formats } = options
+
+ if (isDayjsObject(value))
+ return applyTimezone(value, tzName)
+
+ if (typeof value !== 'string')
+ return undefined
+
+ const trimmed = value.trim()
+
+ if (format) {
+ const parsedWithFormat = tzName
+ ? dayjs.tz(trimmed, format, tzName, true)
+ : dayjs(trimmed, format, true)
+ if (parsedWithFormat.isValid())
+ return parsedWithFormat
+ }
+
+ const timeMatch = TIME_ONLY_REGEX.exec(trimmed)
+ if (timeMatch) {
+ const base = applyTimezone(dayjs(), tzName).startOf('day')
+ const rawHour = Number(timeMatch[1])
+ const minute = Number(timeMatch[2])
+ const second = timeMatch[3] ? Number(timeMatch[3]) : 0
+ const millisecond = normalizeMillisecond(timeMatch[4])
+
+ return base
+ .set('hour', rawHour)
+ .set('minute', minute)
+ .set('second', second)
+ .set('millisecond', millisecond)
+ }
+
+ const timeMatch12h = TIME_ONLY_12H_REGEX.exec(trimmed)
+ if (timeMatch12h) {
+ const base = applyTimezone(dayjs(), tzName).startOf('day')
+ let hour = Number(timeMatch12h[1]) % 12
+ const isPM = timeMatch12h[4]?.toUpperCase() === 'PM'
+ if (isPM)
+ hour += 12
+ const minute = Number(timeMatch12h[2])
+ const second = timeMatch12h[3] ? Number(timeMatch12h[3]) : 0
+
+ return base
+ .set('hour', hour)
+ .set('minute', minute)
+ .set('second', second)
+ .set('millisecond', 0)
+ }
+
+ const candidateFormats = formats ?? COMMON_PARSE_FORMATS
+ for (const fmt of candidateFormats) {
+ const parsed = tzName
+ ? dayjs.tz(trimmed, fmt, tzName, true)
+ : dayjs(trimmed, fmt, true)
+ if (parsed.isValid())
+ return parsed
+ }
+
+ const fallbackParsed = tzName ? dayjs.tz(trimmed, tzName) : dayjs(trimmed)
+ if (fallbackParsed.isValid())
+ return fallbackParsed
+
+ warnParseFailure(value)
+ return undefined
+}
+
// Parse date with multiple format support
export const parseDateWithFormat = (dateString: string, format?: string): Dayjs | null => {
if (!dateString) return null
@@ -103,15 +217,7 @@ export const parseDateWithFormat = (dateString: string, format?: string): Dayjs
// Try common date formats
const formats = [
- 'YYYY-MM-DD', // Standard format
- 'YYYY/MM/DD', // Slash format
- 'DD-MM-YYYY', // European format
- 'DD/MM/YYYY', // European slash format
- 'MM-DD-YYYY', // US format
- 'MM/DD/YYYY', // US slash format
- 'YYYY-MM-DDTHH:mm:ss.SSSZ', // ISO format
- 'YYYY-MM-DDTHH:mm:ssZ', // ISO format (no milliseconds)
- 'YYYY-MM-DD HH:mm:ss', // Standard datetime format
+ ...COMMON_PARSE_FORMATS,
]
for (const fmt of formats) {
@@ -124,7 +230,7 @@ export const parseDateWithFormat = (dateString: string, format?: string): Dayjs
}
// Format date output with localization support
-export const formatDateForOutput = (date: Dayjs, includeTime: boolean = false, locale: string = 'en-US'): string => {
+export const formatDateForOutput = (date: Dayjs, includeTime: boolean = false, _locale: string = 'en-US'): string => {
if (!date || !date.isValid()) return ''
if (includeTime) {
diff --git a/web/app/components/base/drawer/index.tsx b/web/app/components/base/drawer/index.tsx
index 8217caae97..c35acbeac7 100644
--- a/web/app/components/base/drawer/index.tsx
+++ b/web/app/components/base/drawer/index.tsx
@@ -47,7 +47,10 @@ export default function Drawer({
@@ -122,7 +122,7 @@ const ImageList: FC = ({
'rounded-2xl shadow-lg hover:bg-state-base-hover',
item.progress === -1 ? 'flex' : 'hidden group-hover:flex',
)}
- onClick={() => onRemove && onRemove(item._id)}
+ onClick={() => onRemove?.(item._id)}
>
diff --git a/web/app/components/base/image-uploader/image-preview.tsx b/web/app/components/base/image-uploader/image-preview.tsx
index e67edaa3ca..53c22e344f 100644
--- a/web/app/components/base/image-uploader/image-preview.tsx
+++ b/web/app/components/base/image-uploader/image-preview.tsx
@@ -20,7 +20,7 @@ const isBase64 = (str: string): boolean => {
try {
return btoa(atob(str)) === str
}
- catch (err) {
+ catch {
return false
}
}
diff --git a/web/app/components/base/markdown-blocks/code-block.tsx b/web/app/components/base/markdown-blocks/code-block.tsx
index 6814659a00..bc41c65fd5 100644
--- a/web/app/components/base/markdown-blocks/code-block.tsx
+++ b/web/app/components/base/markdown-blocks/code-block.tsx
@@ -127,7 +127,7 @@ const CodeBlock: any = memo(({ inline, className, children = '', ...props }: any
// Store event handlers in useMemo to avoid recreating them
const echartsEvents = useMemo(() => ({
- finished: (params: EChartsEventParams) => {
+ finished: (_params: EChartsEventParams) => {
// Limit finished event frequency to avoid infinite loops
finishedEventCountRef.current++
if (finishedEventCountRef.current > 3) {
diff --git a/web/app/components/base/mermaid/utils.ts b/web/app/components/base/mermaid/utils.ts
index 9d56494227..7e59869de1 100644
--- a/web/app/components/base/mermaid/utils.ts
+++ b/web/app/components/base/mermaid/utils.ts
@@ -60,7 +60,7 @@ export function svgToBase64(svgGraph: string): Promise {
reader.readAsDataURL(blob)
})
}
- catch (error) {
+ catch {
return Promise.resolve('')
}
}
diff --git a/web/app/components/base/pagination/hook.ts b/web/app/components/base/pagination/hook.ts
index 32a2af8013..9b9d86a4ef 100644
--- a/web/app/components/base/pagination/hook.ts
+++ b/web/app/components/base/pagination/hook.ts
@@ -10,9 +10,7 @@ const usePagination = ({
edgePageCount,
middlePagesSiblingCount,
}: IPaginationProps): IUsePagination => {
- const pages = new Array(totalPages)
- .fill(0)
- .map((_, i) => i + 1)
+ const pages = React.useMemo(() => Array.from({ length: totalPages }, (_, i) => i + 1), [totalPages])
const hasPreviousPage = currentPage > 1
const hasNextPage = currentPage < totalPages
diff --git a/web/app/components/base/popover/index.tsx b/web/app/components/base/popover/index.tsx
index 0e7c384564..41df06f43a 100644
--- a/web/app/components/base/popover/index.tsx
+++ b/web/app/components/base/popover/index.tsx
@@ -37,13 +37,16 @@ export default function CustomPopover({
const timeOutRef = useRef(null)
const onMouseEnter = (isOpen: boolean) => {
- timeOutRef.current && window.clearTimeout(timeOutRef.current)
- !isOpen && buttonRef.current?.click()
+ if (timeOutRef.current != null)
+ window.clearTimeout(timeOutRef.current)
+ if (!isOpen)
+ buttonRef.current?.click()
}
const onMouseLeave = (isOpen: boolean) => {
timeOutRef.current = window.setTimeout(() => {
- isOpen && buttonRef.current?.click()
+ if (isOpen)
+ buttonRef.current?.click()
}, timeoutDuration)
}
diff --git a/web/app/components/base/select/locale-signin.tsx b/web/app/components/base/select/locale-signin.tsx
index 2d487c4be3..2ec491f4bf 100644
--- a/web/app/components/base/select/locale-signin.tsx
+++ b/web/app/components/base/select/locale-signin.tsx
@@ -43,7 +43,7 @@ export default function LocaleSigninSelect({
className={'group flex w-full items-center rounded-lg px-3 py-2 text-sm text-text-secondary data-[active]:bg-state-base-hover'}
onClick={(evt) => {
evt.preventDefault()
- onChange && onChange(item.value)
+ onChange?.(item.value)
}}
>
{item.name}
diff --git a/web/app/components/base/select/locale.tsx b/web/app/components/base/select/locale.tsx
index cc5662f53b..2033488435 100644
--- a/web/app/components/base/select/locale.tsx
+++ b/web/app/components/base/select/locale.tsx
@@ -43,7 +43,7 @@ export default function Select({
className={'group flex w-full items-center rounded-lg px-3 py-2 text-sm text-text-secondary data-[active]:bg-state-base-hover'}
onClick={(evt) => {
evt.preventDefault()
- onChange && onChange(item.value)
+ onChange?.(item.value)
}}
>
{item.name}
diff --git a/web/app/components/base/tag-management/panel.tsx b/web/app/components/base/tag-management/panel.tsx
index 79031e9f8a..3cfb68fef0 100644
--- a/web/app/components/base/tag-management/panel.tsx
+++ b/web/app/components/base/tag-management/panel.tsx
@@ -97,10 +97,13 @@ const Panel = (props: PanelProps) => {
const removeTagIDs = value.filter(v => !selectedTagIDs.includes(v))
const selectedTags = tagList.filter(tag => selectedTagIDs.includes(tag.id))
onCacheUpdate(selectedTags)
- Promise.all([
- ...(addTagIDs.length ? [bind(addTagIDs)] : []),
- ...[removeTagIDs.length ? removeTagIDs.map(tagID => unbind(tagID)) : []],
- ]).finally(() => {
+ const operations: Promise[] = []
+ if (addTagIDs.length)
+ operations.push(bind(addTagIDs))
+ if (removeTagIDs.length)
+ operations.push(...removeTagIDs.map(tagID => unbind(tagID)))
+
+ Promise.all(operations).finally(() => {
if (onChange)
onChange()
})
diff --git a/web/app/components/base/voice-input/index.tsx b/web/app/components/base/voice-input/index.tsx
index 5a5400ad30..6587a61217 100644
--- a/web/app/components/base/voice-input/index.tsx
+++ b/web/app/components/base/voice-input/index.tsx
@@ -81,7 +81,8 @@ const VoiceInput = ({
setStartRecord(false)
setStartConvert(true)
recorder.current.stop()
- drawRecordId.current && cancelAnimationFrame(drawRecordId.current)
+ if (drawRecordId.current)
+ cancelAnimationFrame(drawRecordId.current)
drawRecordId.current = null
const canvas = canvasRef.current!
const ctx = ctxRef.current!
diff --git a/web/app/components/datasets/create-from-pipeline/create-options/create-from-dsl-modal/uploader.tsx b/web/app/components/datasets/create-from-pipeline/create-options/create-from-dsl-modal/uploader.tsx
index 433b7851d7..57509b646f 100644
--- a/web/app/components/datasets/create-from-pipeline/create-options/create-from-dsl-modal/uploader.tsx
+++ b/web/app/components/datasets/create-from-pipeline/create-options/create-from-dsl-modal/uploader.tsx
@@ -34,7 +34,8 @@ const Uploader: FC = ({
const handleDragEnter = (e: DragEvent) => {
e.preventDefault()
e.stopPropagation()
- e.target !== dragRef.current && setDragging(true)
+ if (e.target !== dragRef.current)
+ setDragging(true)
}
const handleDragOver = (e: DragEvent) => {
e.preventDefault()
@@ -43,7 +44,8 @@ const Uploader: FC = ({
const handleDragLeave = (e: DragEvent) => {
e.preventDefault()
e.stopPropagation()
- e.target === dragRef.current && setDragging(false)
+ if (e.target === dragRef.current)
+ setDragging(false)
}
const handleDrop = (e: DragEvent) => {
e.preventDefault()
diff --git a/web/app/components/datasets/create/file-uploader/index.tsx b/web/app/components/datasets/create/file-uploader/index.tsx
index 4dfdbc4e96..e2bbad2776 100644
--- a/web/app/components/datasets/create/file-uploader/index.tsx
+++ b/web/app/components/datasets/create/file-uploader/index.tsx
@@ -185,7 +185,8 @@ const FileUploader = ({
const handleDragEnter = (e: DragEvent) => {
e.preventDefault()
e.stopPropagation()
- e.target !== dragRef.current && setDragging(true)
+ if (e.target !== dragRef.current)
+ setDragging(true)
}
const handleDragOver = (e: DragEvent) => {
e.preventDefault()
@@ -194,7 +195,8 @@ const FileUploader = ({
const handleDragLeave = (e: DragEvent) => {
e.preventDefault()
e.stopPropagation()
- e.target === dragRef.current && setDragging(false)
+ if (e.target === dragRef.current)
+ setDragging(false)
}
type FileWithPath = {
relativePath?: string
diff --git a/web/app/components/datasets/create/step-two/index.tsx b/web/app/components/datasets/create/step-two/index.tsx
index 650dc9425a..4c2e129cd2 100644
--- a/web/app/components/datasets/create/step-two/index.tsx
+++ b/web/app/components/datasets/create/step-two/index.tsx
@@ -568,9 +568,9 @@ const StepTwo = ({
params,
{
onSuccess(data) {
- updateIndexingTypeCache && updateIndexingTypeCache(indexType as string)
- updateResultCache && updateResultCache(data)
- updateRetrievalMethodCache && updateRetrievalMethodCache(retrievalConfig.search_method as string)
+ updateIndexingTypeCache?.(indexType as string)
+ updateResultCache?.(data)
+ updateRetrievalMethodCache?.(retrievalConfig.search_method as string)
},
},
)
@@ -578,17 +578,18 @@ const StepTwo = ({
else {
await createDocumentMutation.mutateAsync(params, {
onSuccess(data) {
- updateIndexingTypeCache && updateIndexingTypeCache(indexType as string)
- updateResultCache && updateResultCache(data)
- updateRetrievalMethodCache && updateRetrievalMethodCache(retrievalConfig.search_method as string)
+ updateIndexingTypeCache?.(indexType as string)
+ updateResultCache?.(data)
+ updateRetrievalMethodCache?.(retrievalConfig.search_method as string)
},
})
}
if (mutateDatasetRes)
mutateDatasetRes()
invalidDatasetList()
- onStepChange && onStepChange(+1)
- isSetting && onSave && onSave()
+ onStepChange?.(+1)
+ if (isSetting)
+ onSave?.()
}
useEffect(() => {
@@ -1026,7 +1027,7 @@ const StepTwo = ({
{!isSetting
? (
-
onStepChange && onStepChange(-1)}>
+ onStepChange?.(-1)}>
{t('datasetCreation.stepTwo.previousStep')}
diff --git a/web/app/components/datasets/create/website/jina-reader/base/options-wrap.tsx b/web/app/components/datasets/create/website/jina-reader/base/options-wrap.tsx
deleted file mode 100644
index e69de29bb2..0000000000
diff --git a/web/app/components/datasets/documents/create-from-pipeline/data-source/local-file/index.tsx b/web/app/components/datasets/documents/create-from-pipeline/data-source/local-file/index.tsx
index 0692680005..ad05f0729b 100644
--- a/web/app/components/datasets/documents/create-from-pipeline/data-source/local-file/index.tsx
+++ b/web/app/components/datasets/documents/create-from-pipeline/data-source/local-file/index.tsx
@@ -200,7 +200,8 @@ const LocalFile = ({
const handleDragEnter = (e: DragEvent) => {
e.preventDefault()
e.stopPropagation()
- e.target !== dragRef.current && setDragging(true)
+ if (e.target !== dragRef.current)
+ setDragging(true)
}
const handleDragOver = (e: DragEvent) => {
e.preventDefault()
@@ -209,7 +210,8 @@ const LocalFile = ({
const handleDragLeave = (e: DragEvent) => {
e.preventDefault()
e.stopPropagation()
- e.target === dragRef.current && setDragging(false)
+ if (e.target === dragRef.current)
+ setDragging(false)
}
const handleDrop = useCallback((e: DragEvent) => {
diff --git a/web/app/components/datasets/documents/create-from-pipeline/data-source/website-crawl/base/crawled-result.tsx b/web/app/components/datasets/documents/create-from-pipeline/data-source/website-crawl/base/crawled-result.tsx
index 28c9ae456e..cd410c4d1e 100644
--- a/web/app/components/datasets/documents/create-from-pipeline/data-source/website-crawl/base/crawled-result.tsx
+++ b/web/app/components/datasets/documents/create-from-pipeline/data-source/website-crawl/base/crawled-result.tsx
@@ -45,10 +45,13 @@ const CrawledResult = ({
const handleItemCheckChange = useCallback((item: CrawlResultItem) => {
return (checked: boolean) => {
- if (checked)
- isMultipleChoice ? onSelectedChange([...checkedList, item]) : onSelectedChange([item])
- else
- onSelectedChange(checkedList.filter(checkedItem => checkedItem.source_url !== item.source_url))
+ if (checked) {
+ if (isMultipleChoice)
+ onSelectedChange([...checkedList, item])
+ else
+ onSelectedChange([item])
+ }
+ else { onSelectedChange(checkedList.filter(checkedItem => checkedItem.source_url !== item.source_url)) }
}
}, [checkedList, onSelectedChange, isMultipleChoice])
diff --git a/web/app/components/datasets/documents/create-from-pipeline/index.tsx b/web/app/components/datasets/documents/create-from-pipeline/index.tsx
index 75c31acd1b..77b77700ca 100644
--- a/web/app/components/datasets/documents/create-from-pipeline/index.tsx
+++ b/web/app/components/datasets/documents/create-from-pipeline/index.tsx
@@ -326,7 +326,10 @@ const CreateFormPipeline = () => {
}, [])
const handleSubmit = useCallback((data: Record) => {
- isPreview.current ? handlePreviewChunks(data) : handleProcess(data)
+ if (isPreview.current)
+ handlePreviewChunks(data)
+ else
+ handleProcess(data)
}, [handlePreviewChunks, handleProcess])
const handlePreviewFileChange = useCallback((file: DocumentItem) => {
diff --git a/web/app/components/datasets/documents/detail/batch-modal/csv-uploader.tsx b/web/app/components/datasets/documents/detail/batch-modal/csv-uploader.tsx
index aaf9ed8ffd..7e8749f0bf 100644
--- a/web/app/components/datasets/documents/detail/batch-modal/csv-uploader.tsx
+++ b/web/app/components/datasets/documents/detail/batch-modal/csv-uploader.tsx
@@ -99,7 +99,8 @@ const CSVUploader: FC = ({
const handleDragEnter = (e: DragEvent) => {
e.preventDefault()
e.stopPropagation()
- e.target !== dragRef.current && setDragging(true)
+ if (e.target !== dragRef.current)
+ setDragging(true)
}
const handleDragOver = (e: DragEvent) => {
e.preventDefault()
@@ -108,7 +109,8 @@ const CSVUploader: FC = ({
const handleDragLeave = (e: DragEvent) => {
e.preventDefault()
e.stopPropagation()
- e.target === dragRef.current && setDragging(false)
+ if (e.target === dragRef.current)
+ setDragging(false)
}
const handleDrop = (e: DragEvent) => {
e.preventDefault()
diff --git a/web/app/components/datasets/documents/detail/completed/index.tsx b/web/app/components/datasets/documents/detail/completed/index.tsx
index 726be7519a..8fa167f976 100644
--- a/web/app/components/datasets/documents/detail/completed/index.tsx
+++ b/web/app/components/datasets/documents/detail/completed/index.tsx
@@ -284,7 +284,8 @@ const Completed: FC = ({
onSuccess: () => {
notify({ type: 'success', message: t('common.actionMsg.modifiedSuccessfully') })
resetList()
- !segId && setSelectedSegmentIds([])
+ if (!segId)
+ setSelectedSegmentIds([])
},
onError: () => {
notify({ type: 'error', message: t('common.actionMsg.modifiedUnsuccessfully') })
@@ -438,7 +439,8 @@ const Completed: FC = ({
}
else {
resetList()
- currentPage !== totalPages && setCurrentPage(totalPages)
+ if (currentPage !== totalPages)
+ setCurrentPage(totalPages)
}
}, [segmentListData, limit, currentPage, resetList])
@@ -491,7 +493,8 @@ const Completed: FC = ({
}
else {
resetChildList()
- currentPage !== totalPages && setCurrentPage(totalPages)
+ if (currentPage !== totalPages)
+ setCurrentPage(totalPages)
}
}, [childChunkListData, limit, currentPage, resetChildList])
diff --git a/web/app/components/datasets/documents/detail/metadata/index.tsx b/web/app/components/datasets/documents/detail/metadata/index.tsx
index 4cb5fe97e9..88c359f8b2 100644
--- a/web/app/components/datasets/documents/detail/metadata/index.tsx
+++ b/web/app/components/datasets/documents/detail/metadata/index.tsx
@@ -66,7 +66,7 @@ export const FieldInfo: FC = ({
? displayedValue
: inputType === 'select'
? onUpdate && onUpdate(value as string)}
+ onSelect={({ value }) => onUpdate?.(value as string)}
items={selectOptions}
defaultValue={value}
className={s.select}
@@ -75,7 +75,7 @@ export const FieldInfo: FC = ({
/>
: inputType === 'textarea'
? onUpdate && onUpdate(e.target.value)}
+ onChange={e => onUpdate?.(e.target.value)}
value={value}
className={s.textArea}
placeholder={`${t('datasetDocuments.metadata.placeholder.add')}${label}`}
diff --git a/web/app/components/datasets/documents/detail/settings/pipeline-settings/index.tsx b/web/app/components/datasets/documents/detail/settings/pipeline-settings/index.tsx
index e69481c3ea..1ab47be445 100644
--- a/web/app/components/datasets/documents/detail/settings/pipeline-settings/index.tsx
+++ b/web/app/components/datasets/documents/detail/settings/pipeline-settings/index.tsx
@@ -148,7 +148,10 @@ const PipelineSettings = ({
}, [])
const handleSubmit = useCallback((data: Record) => {
- isPreview.current ? handlePreviewChunks(data) : handleProcess(data)
+ if (isPreview.current)
+ handlePreviewChunks(data)
+ else
+ handleProcess(data)
}, [handlePreviewChunks, handleProcess])
if (isFetchingLastRunData) {
diff --git a/web/app/components/datasets/hit-testing/textarea.tsx b/web/app/components/datasets/hit-testing/textarea.tsx
index a9d66b0cc1..0e9dd16d56 100644
--- a/web/app/components/datasets/hit-testing/textarea.tsx
+++ b/web/app/components/datasets/hit-testing/textarea.tsx
@@ -80,7 +80,8 @@ const TextAreaWithButton = ({
onUpdateList?.()
}
setLoading(false)
- _onSubmit && _onSubmit()
+ if (_onSubmit)
+ _onSubmit()
}
const externalRetrievalTestingOnSubmit = async () => {
diff --git a/web/app/components/datasets/list/dataset-card/index.tsx b/web/app/components/datasets/list/dataset-card/index.tsx
index db8ee0226d..b1304e578e 100644
--- a/web/app/components/datasets/list/dataset-card/index.tsx
+++ b/web/app/components/datasets/list/dataset-card/index.tsx
@@ -157,12 +157,12 @@ const DatasetCard = ({
data-disable-nprogress={true}
onClick={(e) => {
e.preventDefault()
- isExternalProvider
- ? push(`/datasets/${dataset.id}/hitTesting`)
- // eslint-disable-next-line sonarjs/no-nested-conditional
- : isPipelineUnpublished
- ? push(`/datasets/${dataset.id}/pipeline`)
- : push(`/datasets/${dataset.id}/documents`)
+ if (isExternalProvider)
+ push(`/datasets/${dataset.id}/hitTesting`)
+ else if (isPipelineUnpublished)
+ push(`/datasets/${dataset.id}/pipeline`)
+ else
+ push(`/datasets/${dataset.id}/documents`)
}}
>
{!dataset.embedding_available && (
diff --git a/web/app/components/datasets/loading.tsx b/web/app/components/datasets/loading.tsx
index e69de29bb2..182c1f91de 100644
--- a/web/app/components/datasets/loading.tsx
+++ b/web/app/components/datasets/loading.tsx
@@ -0,0 +1,3 @@
+const DatasetsLoading = () => null
+
+export default DatasetsLoading
diff --git a/web/app/components/datasets/preview/index.tsx b/web/app/components/datasets/preview/index.tsx
index e69de29bb2..e71c440c20 100644
--- a/web/app/components/datasets/preview/index.tsx
+++ b/web/app/components/datasets/preview/index.tsx
@@ -0,0 +1,3 @@
+const DatasetPreview = () => null
+
+export default DatasetPreview
diff --git a/web/app/components/header/account-setting/collapse/index.tsx b/web/app/components/header/account-setting/collapse/index.tsx
index 2ad4a97cd1..44360df8cd 100644
--- a/web/app/components/header/account-setting/collapse/index.tsx
+++ b/web/app/components/header/account-setting/collapse/index.tsx
@@ -39,7 +39,7 @@ const Collapse = ({
{
items.map(item => (
-
onSelect && onSelect(item)}>
+
onSelect?.(item)}>
{renderItem(item)}
))
diff --git a/web/app/components/header/account-setting/model-provider-page/model-modal/Form.tsx b/web/app/components/header/account-setting/model-provider-page/model-modal/Form.tsx
index 7c259f1a78..bdaeacb5c0 100644
--- a/web/app/components/header/account-setting/model-provider-page/model-modal/Form.tsx
+++ b/web/app/components/header/account-setting/model-provider-page/model-modal/Form.tsx
@@ -276,7 +276,7 @@ function Form<
-
{label[language] || label.en_US}
+
{label[language] || label.en_US}
{required && (
*
)}
diff --git a/web/app/components/header/account-setting/model-provider-page/provider-added-card/model-load-balancing-configs.tsx b/web/app/components/header/account-setting/model-provider-page/provider-added-card/model-load-balancing-configs.tsx
index 29da0ffc0c..291ba013f7 100644
--- a/web/app/components/header/account-setting/model-provider-page/provider-added-card/model-load-balancing-configs.tsx
+++ b/web/app/components/header/account-setting/model-provider-page/provider-added-card/model-load-balancing-configs.tsx
@@ -49,7 +49,7 @@ const ModelLoadBalancingConfigs = ({
provider,
model,
configurationMethod,
- currentCustomConfigurationModelFixedFields,
+ currentCustomConfigurationModelFixedFields: _currentCustomConfigurationModelFixedFields,
withSwitch = false,
className,
modelCredential,
diff --git a/web/app/components/plugins/plugin-detail-panel/app-selector/app-picker.tsx b/web/app/components/plugins/plugin-detail-panel/app-selector/app-picker.tsx
index 3c79acb653..10c28507f7 100644
--- a/web/app/components/plugins/plugin-detail-panel/app-selector/app-picker.tsx
+++ b/web/app/components/plugins/plugin-detail-panel/app-selector/app-picker.tsx
@@ -33,7 +33,7 @@ type Props = {
}
const AppPicker: FC
= ({
- scope,
+ scope: _scope,
disabled,
trigger,
placement = 'right-start',
@@ -90,7 +90,7 @@ const AppPicker: FC = ({
}
// Set up MutationObserver to watch DOM changes
- mutationObserver = new MutationObserver((mutations) => {
+ mutationObserver = new MutationObserver((_mutations) => {
if (observerTarget.current) {
setupIntersectionObserver()
mutationObserver?.disconnect()
diff --git a/web/app/components/plugins/plugin-detail-panel/model-selector/index.tsx b/web/app/components/plugins/plugin-detail-panel/model-selector/index.tsx
index fb4c99e1e4..873f187e8f 100644
--- a/web/app/components/plugins/plugin-detail-panel/model-selector/index.tsx
+++ b/web/app/components/plugins/plugin-detail-panel/model-selector/index.tsx
@@ -148,7 +148,7 @@ const ModelParameterModal: FC = ({
})
}
}
- catch (e) {
+ catch {
Toast.notify({ type: 'error', message: t('common.error') })
}
}
diff --git a/web/app/components/rag-pipeline/components/panel/input-field/field-list/hooks.ts b/web/app/components/rag-pipeline/components/panel/input-field/field-list/hooks.ts
index d5c0797c9b..376894b1bb 100644
--- a/web/app/components/rag-pipeline/components/panel/input-field/field-list/hooks.ts
+++ b/web/app/components/rag-pipeline/components/panel/input-field/field-list/hooks.ts
@@ -51,7 +51,7 @@ export const useFieldList = ({
const handleListSortChange = useCallback((list: SortableItem[]) => {
const newInputFields = list.map((item) => {
- const { id, chosen, selected, ...filed } = item
+ const { id: _id, chosen: _chosen, selected: _selected, ...filed } = item
return filed
})
handleInputFieldsChange(newInputFields)
diff --git a/web/app/components/rag-pipeline/components/panel/test-run/header.tsx b/web/app/components/rag-pipeline/components/panel/test-run/header.tsx
index 16291f868b..a536f66137 100644
--- a/web/app/components/rag-pipeline/components/panel/test-run/header.tsx
+++ b/web/app/components/rag-pipeline/components/panel/test-run/header.tsx
@@ -15,7 +15,8 @@ const Header = () => {
isPreparingDataSource,
setIsPreparingDataSource,
} = workflowStore.getState()
- isPreparingDataSource && setIsPreparingDataSource?.(false)
+ if (isPreparingDataSource)
+ setIsPreparingDataSource?.(false)
handleCancelDebugAndPreviewPanel()
}, [workflowStore])
diff --git a/web/app/components/rag-pipeline/hooks/use-nodes-sync-draft.ts b/web/app/components/rag-pipeline/hooks/use-nodes-sync-draft.ts
index 86e44dced7..ad757f36a7 100644
--- a/web/app/components/rag-pipeline/hooks/use-nodes-sync-draft.ts
+++ b/web/app/components/rag-pipeline/hooks/use-nodes-sync-draft.ts
@@ -104,7 +104,7 @@ export const useNodesSyncDraft = () => {
const res = await syncWorkflowDraft(postParams)
setSyncWorkflowDraftHash(res.hash)
setDraftUpdatedAt(res.updated_at)
- callback?.onSuccess && callback.onSuccess()
+ callback?.onSuccess?.()
}
catch (error: any) {
if (error && error.json && !error.bodyUsed) {
@@ -113,10 +113,10 @@ export const useNodesSyncDraft = () => {
handleRefreshWorkflowDraft()
})
}
- callback?.onError && callback.onError()
+ callback?.onError?.()
}
finally {
- callback?.onSettled && callback.onSettled()
+ callback?.onSettled?.()
}
}
}, [getPostParams, getNodesReadOnly, workflowStore, handleRefreshWorkflowDraft])
diff --git a/web/app/components/share/text-generation/index.tsx b/web/app/components/share/text-generation/index.tsx
index da5b09b065..98804c7311 100644
--- a/web/app/components/share/text-generation/index.tsx
+++ b/web/app/components/share/text-generation/index.tsx
@@ -363,7 +363,8 @@ const TextGeneration: FC = ({
(async () => {
if (!appData || !appParams)
return
- !isWorkflow && fetchSavedMessage()
+ if (!isWorkflow)
+ fetchSavedMessage()
const { app_id: appId, site: siteInfo, custom_config } = appData
setAppId(appId)
setSiteInfo(siteInfo as SiteInfo)
diff --git a/web/app/components/share/text-generation/result/index.tsx b/web/app/components/share/text-generation/result/index.tsx
index ddc0d772c3..7a4e606636 100644
--- a/web/app/components/share/text-generation/result/index.tsx
+++ b/web/app/components/share/text-generation/result/index.tsx
@@ -78,15 +78,15 @@ const Result: FC = ({
setRespondingFalse()
}, [controlStopResponding])
- const [completionRes, doSetCompletionRes] = useState('')
- const completionResRef = useRef()
- const setCompletionRes = (res: any) => {
+ const [completionRes, doSetCompletionRes] = useState('')
+ const completionResRef = useRef('')
+ const setCompletionRes = (res: string) => {
completionResRef.current = res
doSetCompletionRes(res)
}
const getCompletionRes = () => completionResRef.current
const [workflowProcessData, doSetWorkflowProcessData] = useState()
- const workflowProcessDataRef = useRef()
+ const workflowProcessDataRef = useRef(undefined)
const setWorkflowProcessData = (data: WorkflowProcess) => {
workflowProcessDataRef.current = data
doSetWorkflowProcessData(data)
diff --git a/web/app/components/swr-initializer.tsx b/web/app/components/swr-initializer.tsx
index 0a873400d6..fd9432fdd8 100644
--- a/web/app/components/swr-initializer.tsx
+++ b/web/app/components/swr-initializer.tsx
@@ -62,8 +62,10 @@ const SwrInitializer = ({
return
}
if (searchParams.has('access_token') || searchParams.has('refresh_token')) {
- consoleToken && localStorage.setItem('console_token', consoleToken)
- refreshToken && localStorage.setItem('refresh_token', refreshToken)
+ if (consoleToken)
+ localStorage.setItem('console_token', consoleToken)
+ if (refreshToken)
+ localStorage.setItem('refresh_token', refreshToken)
const redirectUrl = resolvePostLoginRedirect(searchParams)
if (redirectUrl)
location.replace(redirectUrl)
diff --git a/web/app/components/tools/utils/to-form-schema.ts b/web/app/components/tools/utils/to-form-schema.ts
index c1d17b48ef..8e85a5f9b0 100644
--- a/web/app/components/tools/utils/to-form-schema.ts
+++ b/web/app/components/tools/utils/to-form-schema.ts
@@ -45,6 +45,7 @@ export const toolCredentialToFormSchemas = (parameters: ToolCredential[]) => {
return {
...parameter,
variable: parameter.name,
+ type: toType(parameter.type),
label: parameter.label,
tooltip: parameter.help,
show_on: [],
diff --git a/web/app/components/workflow-app/hooks/use-nodes-sync-draft.ts b/web/app/components/workflow-app/hooks/use-nodes-sync-draft.ts
index bd1fa0a19f..033cfeec53 100644
--- a/web/app/components/workflow-app/hooks/use-nodes-sync-draft.ts
+++ b/web/app/components/workflow-app/hooks/use-nodes-sync-draft.ts
@@ -122,7 +122,7 @@ export const useNodesSyncDraft = () => {
const res = await syncWorkflowDraft(postParams)
setSyncWorkflowDraftHash(res.hash)
setDraftUpdatedAt(res.updated_at)
- callback?.onSuccess && callback.onSuccess()
+ callback?.onSuccess?.()
}
catch (error: any) {
if (error && error.json && !error.bodyUsed) {
@@ -131,10 +131,10 @@ export const useNodesSyncDraft = () => {
handleRefreshWorkflowDraft()
})
}
- callback?.onError && callback.onError()
+ callback?.onError?.()
}
finally {
- callback?.onSettled && callback.onSettled()
+ callback?.onSettled?.()
}
}
}, [workflowStore, getPostParams, getNodesReadOnly, handleRefreshWorkflowDraft])
diff --git a/web/app/components/workflow/block-selector/tool/tool.tsx b/web/app/components/workflow/block-selector/tool/tool.tsx
index d75ab0c383..0cbe5f6086 100644
--- a/web/app/components/workflow/block-selector/tool/tool.tsx
+++ b/web/app/components/workflow/block-selector/tool/tool.tsx
@@ -74,7 +74,7 @@ const Tool: FC = ({
if (isHovering && !isAllSelected) {
return (
{
+ onClick={() => {
onSelectMultiple?.(BlockEnum.Tool, actions.filter(action => !getIsDisabled(action)).map((tool) => {
const params: Record = {}
if (tool.parameters) {
diff --git a/web/app/components/workflow/hooks/use-shortcuts.ts b/web/app/components/workflow/hooks/use-shortcuts.ts
index d81e2fc553..fa9b019011 100644
--- a/web/app/components/workflow/hooks/use-shortcuts.ts
+++ b/web/app/components/workflow/hooks/use-shortcuts.ts
@@ -108,7 +108,8 @@ export const useShortcuts = (): void => {
const { showDebugAndPreviewPanel } = workflowStore.getState()
if (shouldHandleShortcut(e) && !showDebugAndPreviewPanel) {
e.preventDefault()
- workflowHistoryShortcutsEnabled && handleHistoryBack()
+ if (workflowHistoryShortcutsEnabled)
+ handleHistoryBack()
}
}, { exactMatch: true, useCapture: true })
@@ -117,7 +118,8 @@ export const useShortcuts = (): void => {
(e) => {
if (shouldHandleShortcut(e)) {
e.preventDefault()
- workflowHistoryShortcutsEnabled && handleHistoryForward()
+ if (workflowHistoryShortcutsEnabled)
+ handleHistoryForward()
}
},
{ exactMatch: true, useCapture: true },
diff --git a/web/app/components/workflow/hooks/use-workflow-history.ts b/web/app/components/workflow/hooks/use-workflow-history.ts
index a9b2f0f699..58bbe415a8 100644
--- a/web/app/components/workflow/hooks/use-workflow-history.ts
+++ b/web/app/components/workflow/hooks/use-workflow-history.ts
@@ -41,16 +41,16 @@ export const useWorkflowHistory = () => {
const { store: workflowHistoryStore } = useWorkflowHistoryStore()
const { t } = useTranslation()
- const [undoCallbacks, setUndoCallbacks] = useState([])
- const [redoCallbacks, setRedoCallbacks] = useState([])
+ const [undoCallbacks, setUndoCallbacks] = useState<(() => void)[]>([])
+ const [redoCallbacks, setRedoCallbacks] = useState<(() => void)[]>([])
- const onUndo = useCallback((callback: unknown) => {
- setUndoCallbacks((prev: any) => [...prev, callback])
+ const onUndo = useCallback((callback: () => void) => {
+ setUndoCallbacks(prev => [...prev, callback])
return () => setUndoCallbacks(prev => prev.filter(cb => cb !== callback))
}, [])
- const onRedo = useCallback((callback: unknown) => {
- setRedoCallbacks((prev: any) => [...prev, callback])
+ const onRedo = useCallback((callback: () => void) => {
+ setRedoCallbacks(prev => [...prev, callback])
return () => setRedoCallbacks(prev => prev.filter(cb => cb !== callback))
}, [])
diff --git a/web/app/components/workflow/hooks/use-workflow.ts b/web/app/components/workflow/hooks/use-workflow.ts
index 70c6fb298c..dc9c8bd1f8 100644
--- a/web/app/components/workflow/hooks/use-workflow.ts
+++ b/web/app/components/workflow/hooks/use-workflow.ts
@@ -386,7 +386,7 @@ export const useWorkflow = () => {
return startNodes
}, [nodesMap, getRootNodesById])
- const isValidConnection = useCallback(({ source, sourceHandle, target }: Connection) => {
+ const isValidConnection = useCallback(({ source, sourceHandle: _sourceHandle, target }: Connection) => {
const {
edges,
getNodes,
diff --git a/web/app/components/workflow/nodes/_base/components/retry/utils.ts b/web/app/components/workflow/nodes/_base/components/retry/utils.ts
index e69de29bb2..336ce12bb9 100644
--- a/web/app/components/workflow/nodes/_base/components/retry/utils.ts
+++ b/web/app/components/workflow/nodes/_base/components/retry/utils.ts
@@ -0,0 +1 @@
+export {}
diff --git a/web/app/components/workflow/nodes/_base/components/variable/var-reference-picker.tsx b/web/app/components/workflow/nodes/_base/components/variable/var-reference-picker.tsx
index c39d41b4fb..fea1415421 100644
--- a/web/app/components/workflow/nodes/_base/components/variable/var-reference-picker.tsx
+++ b/web/app/components/workflow/nodes/_base/components/variable/var-reference-picker.tsx
@@ -129,7 +129,7 @@ const VarReferencePicker: FC = ({
const reactflow = useReactFlow()
- const startNode = availableNodes.find((node: any) => {
+ const startNode = availableNodes.find((node: Node) => {
return node.data.type === BlockEnum.Start
})
@@ -409,7 +409,10 @@ const VarReferencePicker: FC = ({
{
if (readonly)
return
- !isConstant ? setOpen(!open) : setControlFocus(Date.now())
+ if (!isConstant)
+ setOpen(!open)
+ else
+ setControlFocus(Date.now())
}} className='group/picker-trigger-wrap relative !flex'>
<>
{isAddBtnTrigger
@@ -459,7 +462,10 @@ const VarReferencePicker: FC = ({
onClick={() => {
if (readonly)
return
- !isConstant ? setOpen(!open) : setControlFocus(Date.now())
+ if (!isConstant)
+ setOpen(!open)
+ else
+ setControlFocus(Date.now())
}}
className='h-full grow'
>
diff --git a/web/app/components/workflow/nodes/_base/components/variable/var-reference-vars.tsx b/web/app/components/workflow/nodes/_base/components/variable/var-reference-vars.tsx
index 067dbf8652..e70cfed97c 100644
--- a/web/app/components/workflow/nodes/_base/components/variable/var-reference-vars.tsx
+++ b/web/app/components/workflow/nodes/_base/components/variable/var-reference-vars.tsx
@@ -137,7 +137,7 @@ const Item: FC = ({
const isHovering = isItemHovering || isChildrenHovering
const open = (isObj || isStructureOutput) && isHovering
useEffect(() => {
- onHovering && onHovering(isHovering)
+ onHovering?.(isHovering)
}, [isHovering])
const handleChosen = (e: React.MouseEvent) => {
e.stopPropagation()
diff --git a/web/app/components/workflow/nodes/_base/components/workflow-panel/last-run/index.tsx b/web/app/components/workflow/nodes/_base/components/workflow-panel/last-run/index.tsx
index 06962389c9..b26dd74714 100644
--- a/web/app/components/workflow/nodes/_base/components/workflow-panel/last-run/index.tsx
+++ b/web/app/components/workflow/nodes/_base/components/workflow-panel/last-run/index.tsx
@@ -25,12 +25,12 @@ type Props = {
} & Partial
const LastRun: FC = ({
- appId,
+ appId: _appId,
nodeId,
canSingleRun,
isRunAfterSingleRun,
updateNodeRunningStatus,
- nodeInfo,
+ nodeInfo: _nodeInfo,
runningStatus: oneStepRunRunningStatus,
onSingleRunClicked,
singleRunResult,
diff --git a/web/app/components/workflow/nodes/http/components/timeout/index.tsx b/web/app/components/workflow/nodes/http/components/timeout/index.tsx
index 40ebab0e2a..bb84091d67 100644
--- a/web/app/components/workflow/nodes/http/components/timeout/index.tsx
+++ b/web/app/components/workflow/nodes/http/components/timeout/index.tsx
@@ -5,6 +5,8 @@ import { useTranslation } from 'react-i18next'
import type { Timeout as TimeoutPayloadType } from '../../types'
import Input from '@/app/components/base/input'
import { FieldCollapse } from '@/app/components/workflow/nodes/_base/components/collapse'
+import { useStore } from '@/app/components/workflow/store'
+import { BlockEnum } from '@/app/components/workflow/types'
type Props = {
readonly: boolean
@@ -61,6 +63,11 @@ const Timeout: FC = ({ readonly, payload, onChange }) => {
const { t } = useTranslation()
const { connect, read, write, max_connect_timeout, max_read_timeout, max_write_timeout } = payload ?? {}
+ // Get default config from store for max timeout values
+ const nodesDefaultConfigs = useStore(s => s.nodesDefaultConfigs)
+ const defaultConfig = nodesDefaultConfigs?.[BlockEnum.HttpRequest]
+ const defaultTimeout = defaultConfig?.timeout || {}
+
return (
@@ -73,7 +80,7 @@ const Timeout: FC
= ({ readonly, payload, onChange }) => {
value={connect}
onChange={v => onChange?.({ ...payload, connect: v })}
min={1}
- max={max_connect_timeout || 300}
+ max={max_connect_timeout || defaultTimeout.max_connect_timeout || 10}
/>
= ({ readonly, payload, onChange }) => {
value={read}
onChange={v => onChange?.({ ...payload, read: v })}
min={1}
- max={max_read_timeout || 600}
+ max={max_read_timeout || defaultTimeout.max_read_timeout || 600}
/>
= ({ readonly, payload, onChange }) => {
value={write}
onChange={v => onChange?.({ ...payload, write: v })}
min={1}
- max={max_write_timeout || 600}
+ max={max_write_timeout || defaultTimeout.max_write_timeout || 600}
/>
diff --git a/web/app/components/workflow/nodes/knowledge-base/components/option-card.tsx b/web/app/components/workflow/nodes/knowledge-base/components/option-card.tsx
index 789e24835f..99ee0d25b5 100644
--- a/web/app/components/workflow/nodes/knowledge-base/components/option-card.tsx
+++ b/web/app/components/workflow/nodes/knowledge-base/components/option-card.tsx
@@ -88,7 +88,8 @@ const OptionCard = memo(({
)}
onClick={(e) => {
e.stopPropagation()
- !readonly && enableSelect && id && onClick?.(id)
+ if (!readonly && enableSelect && id)
+ onClick?.(id)
}}
>
= ({
setJson(JSON.stringify(schema, null, 2))
}, [currentTab])
- const handleSubmit = useCallback((schema: any) => {
+ const handleSubmit = useCallback((schema: Record
) => {
const jsonSchema = jsonToSchema(schema) as SchemaRoot
if (currentTab === SchemaView.VisualEditor)
setJsonSchema(jsonSchema)
@@ -139,8 +139,10 @@ const JsonSchemaConfig: FC = ({
const handleResetDefaults = useCallback(() => {
if (currentTab === SchemaView.VisualEditor) {
setHoveringProperty(null)
- advancedEditing && setAdvancedEditing(false)
- isAddingNewField && setIsAddingNewField(false)
+ if (advancedEditing)
+ setAdvancedEditing(false)
+ if (isAddingNewField)
+ setIsAddingNewField(false)
}
setJsonSchema(DEFAULT_SCHEMA)
setJson(JSON.stringify(DEFAULT_SCHEMA, null, 2))
diff --git a/web/app/components/workflow/nodes/llm/components/json-schema-config-modal/visual-editor/edit-card/index.tsx b/web/app/components/workflow/nodes/llm/components/json-schema-config-modal/visual-editor/edit-card/index.tsx
index ae72d494d1..4aa0f99d3f 100644
--- a/web/app/components/workflow/nodes/llm/components/json-schema-config-modal/visual-editor/edit-card/index.tsx
+++ b/web/app/components/workflow/nodes/llm/components/json-schema-config-modal/visual-editor/edit-card/index.tsx
@@ -87,8 +87,10 @@ const EditCard: FC = ({
})
useSubscribe('fieldChangeSuccess', () => {
- isAddingNewField && setIsAddingNewField(false)
- advancedEditing && setAdvancedEditing(false)
+ if (isAddingNewField)
+ setIsAddingNewField(false)
+ if (advancedEditing)
+ setAdvancedEditing(false)
})
const emitPropertyNameChange = useCallback(() => {
@@ -150,14 +152,16 @@ const EditCard: FC = ({
}, [isAdvancedEditing, emitPropertyOptionsChange, currentFields])
const handleAdvancedOptionsChange = useCallback((options: AdvancedOptionsType) => {
- let enumValue: any = options.enum
- if (enumValue === '') {
+ let enumValue: SchemaEnumType | undefined
+ if (options.enum === '') {
enumValue = undefined
}
else {
- enumValue = options.enum.replace(/\s/g, '').split(',')
+ const stringArray = options.enum.replace(/\s/g, '').split(',')
if (currentFields.type === Type.number)
- enumValue = (enumValue as SchemaEnumType).map(value => Number(value)).filter(num => !Number.isNaN(num))
+ enumValue = stringArray.map(value => Number(value)).filter(num => !Number.isNaN(num))
+ else
+ enumValue = stringArray
}
setCurrentFields(prev => ({ ...prev, enum: enumValue }))
if (isAdvancedEditing) return
diff --git a/web/app/components/workflow/nodes/llm/components/json-schema-config-modal/visual-editor/hooks.ts b/web/app/components/workflow/nodes/llm/components/json-schema-config-modal/visual-editor/hooks.ts
index 8256a3c862..4f7e1e6f00 100644
--- a/web/app/components/workflow/nodes/llm/components/json-schema-config-modal/visual-editor/hooks.ts
+++ b/web/app/components/workflow/nodes/llm/components/json-schema-config-modal/visual-editor/hooks.ts
@@ -45,8 +45,10 @@ export const useSchemaNodeOperations = (props: VisualEditorProps) => {
onChange(backupSchema)
setBackupSchema(null)
}
- isAddingNewField && setIsAddingNewField(false)
- advancedEditing && setAdvancedEditing(false)
+ if (isAddingNewField)
+ setIsAddingNewField(false)
+ if (advancedEditing)
+ setAdvancedEditing(false)
setHoveringProperty(null)
})
@@ -221,7 +223,8 @@ export const useSchemaNodeOperations = (props: VisualEditorProps) => {
})
useSubscribe('addField', (params) => {
- advancedEditing && setAdvancedEditing(false)
+ if (advancedEditing)
+ setAdvancedEditing(false)
setBackupSchema(jsonSchema)
const { path } = params as AddEventParams
setIsAddingNewField(true)
diff --git a/web/app/components/workflow/nodes/llm/panel.tsx b/web/app/components/workflow/nodes/llm/panel.tsx
index 03569f6f7a..cd79b9f3d9 100644
--- a/web/app/components/workflow/nodes/llm/panel.tsx
+++ b/web/app/components/workflow/nodes/llm/panel.tsx
@@ -293,6 +293,11 @@ const Panel: FC> = ({
type='string'
description={t(`${i18nPrefix}.outputVars.output`)}
/>
+
{
diff --git a/web/app/components/workflow/panel/chat-variable-panel/components/variable-modal-trigger.tsx b/web/app/components/workflow/panel/chat-variable-panel/components/variable-modal-trigger.tsx
index 07eb79a269..9d19b61093 100644
--- a/web/app/components/workflow/panel/chat-variable-panel/components/variable-modal-trigger.tsx
+++ b/web/app/components/workflow/panel/chat-variable-panel/components/variable-modal-trigger.tsx
@@ -35,7 +35,8 @@ const VariableModalTrigger = ({
open={open}
onOpenChange={() => {
setOpen(v => !v)
- open && onClose()
+ if (open)
+ onClose()
}}
placement='left-start'
offset={{
@@ -45,7 +46,8 @@ const VariableModalTrigger = ({
>
{
setOpen(v => !v)
- open && onClose()
+ if (open)
+ onClose()
}}>
diff --git a/web/app/components/workflow/panel/env-panel/variable-trigger.tsx b/web/app/components/workflow/panel/env-panel/variable-trigger.tsx
index 52474860b1..604fceef81 100644
--- a/web/app/components/workflow/panel/env-panel/variable-trigger.tsx
+++ b/web/app/components/workflow/panel/env-panel/variable-trigger.tsx
@@ -33,7 +33,8 @@ const VariableTrigger = ({
open={open}
onOpenChange={() => {
setOpen(v => !v)
- open && onClose()
+ if (open)
+ onClose()
}}
placement='left-start'
offset={{
@@ -43,7 +44,8 @@ const VariableTrigger = ({
>
{
setOpen(v => !v)
- open && onClose()
+ if (open)
+ onClose()
}}>
diff --git a/web/app/components/workflow/run/index.tsx b/web/app/components/workflow/run/index.tsx
index 2b32b05796..5f6b07033d 100644
--- a/web/app/components/workflow/run/index.tsx
+++ b/web/app/components/workflow/run/index.tsx
@@ -86,9 +86,12 @@ const RunPanel: FC = ({
const switchTab = async (tab: string) => {
setCurrentTab(tab)
- if (tab === 'RESULT')
- runDetailUrl && await getResult()
- tracingListUrl && await getTracingList()
+ if (tab === 'RESULT') {
+ if (runDetailUrl)
+ await getResult()
+ }
+ if (tracingListUrl)
+ await getTracingList()
}
useEffect(() => {
diff --git a/web/app/components/workflow/workflow-preview/components/nodes/loop/node.tsx b/web/app/components/workflow/workflow-preview/components/nodes/loop/node.tsx
index 4c0080ec70..f41fa120a6 100644
--- a/web/app/components/workflow/workflow-preview/components/nodes/loop/node.tsx
+++ b/web/app/components/workflow/workflow-preview/components/nodes/loop/node.tsx
@@ -15,7 +15,7 @@ import { useNodeLoopInteractions } from './hooks'
const Node: FC> = ({
id,
- data,
+ data: _data,
}) => {
const { zoom } = useViewport()
const nodesInitialized = useNodesInitialized()
diff --git a/web/app/signin/components/mail-and-password-auth.tsx b/web/app/signin/components/mail-and-password-auth.tsx
index aaadc0b197..5214b73ee0 100644
--- a/web/app/signin/components/mail-and-password-auth.tsx
+++ b/web/app/signin/components/mail-and-password-auth.tsx
@@ -19,7 +19,7 @@ type MailAndPasswordAuthProps = {
allowRegistration: boolean
}
-export default function MailAndPasswordAuth({ isInvite, isEmailSetup, allowRegistration }: MailAndPasswordAuthProps) {
+export default function MailAndPasswordAuth({ isInvite, isEmailSetup, allowRegistration: _allowRegistration }: MailAndPasswordAuthProps) {
const { t } = useTranslation()
const { locale } = useContext(I18NContext)
const router = useRouter()
diff --git a/web/i18n-config/index.ts b/web/i18n-config/index.ts
index fdb31c49b4..b2b83fa76a 100644
--- a/web/i18n-config/index.ts
+++ b/web/i18n-config/index.ts
@@ -14,7 +14,8 @@ export type Locale = typeof i18n['locales'][number]
export const setLocaleOnClient = async (locale: Locale, reloadPage = true) => {
Cookies.set(LOCALE_COOKIE_NAME, locale, { expires: 365 })
await changeLanguage(locale)
- reloadPage && location.reload()
+ if (reloadPage)
+ location.reload()
}
export const getLocaleOnClient = (): Locale => {
diff --git a/web/i18n/de-DE/workflow.ts b/web/i18n/de-DE/workflow.ts
index b058caba88..63bce527ca 100644
--- a/web/i18n/de-DE/workflow.ts
+++ b/web/i18n/de-DE/workflow.ts
@@ -442,6 +442,7 @@ const translation = {
},
outputVars: {
output: 'Generierter Inhalt',
+ reasoning_content: 'Reasoning-Inhalt',
usage: 'Nutzungsinformationen des Modells',
},
singleRun: {
diff --git a/web/i18n/en-US/workflow.ts b/web/i18n/en-US/workflow.ts
index 1b715c3349..9fae86d861 100644
--- a/web/i18n/en-US/workflow.ts
+++ b/web/i18n/en-US/workflow.ts
@@ -486,6 +486,7 @@ const translation = {
},
outputVars: {
output: 'Generate content',
+ reasoning_content: 'Reasoning Content',
usage: 'Model Usage Information',
},
singleRun: {
diff --git a/web/i18n/es-ES/workflow.ts b/web/i18n/es-ES/workflow.ts
index fb831be722..a423e4479e 100644
--- a/web/i18n/es-ES/workflow.ts
+++ b/web/i18n/es-ES/workflow.ts
@@ -442,6 +442,7 @@ const translation = {
},
outputVars: {
output: 'Generar contenido',
+ reasoning_content: 'Contenido de razonamiento',
usage: 'Información de uso del modelo',
},
singleRun: {
diff --git a/web/i18n/fa-IR/workflow.ts b/web/i18n/fa-IR/workflow.ts
index ef2503a039..db9544f8c4 100644
--- a/web/i18n/fa-IR/workflow.ts
+++ b/web/i18n/fa-IR/workflow.ts
@@ -442,6 +442,7 @@ const translation = {
},
outputVars: {
output: 'تولید محتوا',
+ reasoning_content: 'محتوای استدلال',
usage: 'اطلاعات استفاده از مدل',
},
singleRun: {
diff --git a/web/i18n/fr-FR/workflow.ts b/web/i18n/fr-FR/workflow.ts
index 11d0c1f8c9..eab8c5d359 100644
--- a/web/i18n/fr-FR/workflow.ts
+++ b/web/i18n/fr-FR/workflow.ts
@@ -442,6 +442,7 @@ const translation = {
},
outputVars: {
output: 'Contenu généré',
+ reasoning_content: 'Contenu de raisonnement',
usage: 'Informations sur l\'utilisation du modèle',
},
singleRun: {
diff --git a/web/i18n/hi-IN/workflow.ts b/web/i18n/hi-IN/workflow.ts
index 08efdbc027..df75a4e367 100644
--- a/web/i18n/hi-IN/workflow.ts
+++ b/web/i18n/hi-IN/workflow.ts
@@ -455,6 +455,7 @@ const translation = {
},
outputVars: {
output: 'सामग्री उत्पन्न करें',
+ reasoning_content: 'तर्क सामग्री',
usage: 'मॉडल उपयोग जानकारी',
},
singleRun: {
diff --git a/web/i18n/id-ID/workflow.ts b/web/i18n/id-ID/workflow.ts
index 4bfbe934f7..969b7bb8b0 100644
--- a/web/i18n/id-ID/workflow.ts
+++ b/web/i18n/id-ID/workflow.ts
@@ -427,6 +427,7 @@ const translation = {
},
outputVars: {
output: 'Hasilkan konten',
+ reasoning_content: 'Konten penalaran',
usage: 'Informasi Penggunaan Model',
},
singleRun: {
diff --git a/web/i18n/it-IT/workflow.ts b/web/i18n/it-IT/workflow.ts
index 5b7b940208..eeb8472428 100644
--- a/web/i18n/it-IT/workflow.ts
+++ b/web/i18n/it-IT/workflow.ts
@@ -459,6 +459,7 @@ const translation = {
},
outputVars: {
output: 'Genera contenuto',
+ reasoning_content: 'Contenuto del ragionamento',
usage: 'Informazioni sull\'utilizzo del modello',
},
singleRun: {
diff --git a/web/i18n/ja-JP/workflow.ts b/web/i18n/ja-JP/workflow.ts
index e7125bd7da..418bd23545 100644
--- a/web/i18n/ja-JP/workflow.ts
+++ b/web/i18n/ja-JP/workflow.ts
@@ -482,6 +482,7 @@ const translation = {
},
outputVars: {
output: '生成内容',
+ reasoning_content: '推論内容',
usage: 'モデル使用量',
},
singleRun: {
diff --git a/web/i18n/ko-KR/workflow.ts b/web/i18n/ko-KR/workflow.ts
index 58d716028f..5012e4f660 100644
--- a/web/i18n/ko-KR/workflow.ts
+++ b/web/i18n/ko-KR/workflow.ts
@@ -467,6 +467,7 @@ const translation = {
},
outputVars: {
output: '생성된 내용',
+ reasoning_content: '추론 내용',
usage: '모델 사용 정보',
},
singleRun: {
diff --git a/web/i18n/pl-PL/workflow.ts b/web/i18n/pl-PL/workflow.ts
index 57a4d5570b..02ef9278a6 100644
--- a/web/i18n/pl-PL/workflow.ts
+++ b/web/i18n/pl-PL/workflow.ts
@@ -442,6 +442,7 @@ const translation = {
},
outputVars: {
output: 'Generowana treść',
+ reasoning_content: 'Treść rozumowania',
usage: 'Informacje o użyciu modelu',
},
singleRun: {
diff --git a/web/i18n/pt-BR/workflow.ts b/web/i18n/pt-BR/workflow.ts
index 03c387c09a..c693c47965 100644
--- a/web/i18n/pt-BR/workflow.ts
+++ b/web/i18n/pt-BR/workflow.ts
@@ -442,6 +442,7 @@ const translation = {
},
outputVars: {
output: 'Conteúdo gerado',
+ reasoning_content: 'Conteúdo de raciocínio',
usage: 'Informações de uso do modelo',
},
singleRun: {
diff --git a/web/i18n/ro-RO/workflow.ts b/web/i18n/ro-RO/workflow.ts
index 7390ab07b3..3d7e5218cd 100644
--- a/web/i18n/ro-RO/workflow.ts
+++ b/web/i18n/ro-RO/workflow.ts
@@ -442,6 +442,7 @@ const translation = {
},
outputVars: {
output: 'Conținut generat',
+ reasoning_content: 'Conținut de raționament',
usage: 'Informații de utilizare a modelului',
},
singleRun: {
diff --git a/web/i18n/ru-RU/workflow.ts b/web/i18n/ru-RU/workflow.ts
index a6fd710a66..71fe3853ba 100644
--- a/web/i18n/ru-RU/workflow.ts
+++ b/web/i18n/ru-RU/workflow.ts
@@ -442,6 +442,7 @@ const translation = {
},
outputVars: {
output: 'Создать контент',
+ reasoning_content: 'Содержимое рассуждений',
usage: 'Информация об использовании модели',
},
singleRun: {
diff --git a/web/i18n/sl-SI/workflow.ts b/web/i18n/sl-SI/workflow.ts
index 6f8e301daf..b4fe903d2a 100644
--- a/web/i18n/sl-SI/workflow.ts
+++ b/web/i18n/sl-SI/workflow.ts
@@ -440,6 +440,7 @@ const translation = {
},
outputVars: {
output: 'Ustvari vsebino',
+ reasoning_content: 'Vsebina razmišljanja',
usage: 'Informacije o uporabi modela',
},
singleRun: {
diff --git a/web/i18n/th-TH/workflow.ts b/web/i18n/th-TH/workflow.ts
index 24f9f1d42b..4efc63fad2 100644
--- a/web/i18n/th-TH/workflow.ts
+++ b/web/i18n/th-TH/workflow.ts
@@ -442,6 +442,7 @@ const translation = {
},
outputVars: {
output: 'สร้างเนื้อหา',
+ reasoning_content: 'เนื้อหาการให้เหตุผล',
usage: 'ข้อมูลการใช้งานรุ่น',
},
singleRun: {
diff --git a/web/i18n/tr-TR/workflow.ts b/web/i18n/tr-TR/workflow.ts
index 2ccd1c1013..7a1107e48b 100644
--- a/web/i18n/tr-TR/workflow.ts
+++ b/web/i18n/tr-TR/workflow.ts
@@ -442,6 +442,7 @@ const translation = {
},
outputVars: {
output: 'İçerik Üret',
+ reasoning_content: 'Akıl yürütme içeriği',
usage: 'Model Kullanım Bilgileri',
},
singleRun: {
diff --git a/web/i18n/uk-UA/workflow.ts b/web/i18n/uk-UA/workflow.ts
index d0c9474b68..9140171323 100644
--- a/web/i18n/uk-UA/workflow.ts
+++ b/web/i18n/uk-UA/workflow.ts
@@ -442,6 +442,7 @@ const translation = {
},
outputVars: {
output: 'Генерований вміст',
+ reasoning_content: 'Зміст міркування',
usage: 'Інформація про використання моделі',
},
singleRun: {
diff --git a/web/i18n/vi-VN/workflow.ts b/web/i18n/vi-VN/workflow.ts
index d540763ca3..4d8c26231a 100644
--- a/web/i18n/vi-VN/workflow.ts
+++ b/web/i18n/vi-VN/workflow.ts
@@ -442,6 +442,7 @@ const translation = {
},
outputVars: {
output: 'Nội dung được tạo',
+ reasoning_content: 'Nội dung lập luận',
usage: 'Thông tin sử dụng mô hình',
},
singleRun: {
diff --git a/web/i18n/zh-Hans/workflow.ts b/web/i18n/zh-Hans/workflow.ts
index 9dfdb0a2fb..6bd473712b 100644
--- a/web/i18n/zh-Hans/workflow.ts
+++ b/web/i18n/zh-Hans/workflow.ts
@@ -485,6 +485,7 @@ const translation = {
},
outputVars: {
output: '生成内容',
+ reasoning_content: '推理内容',
usage: '模型用量信息',
},
singleRun: {
diff --git a/web/i18n/zh-Hant/workflow.ts b/web/i18n/zh-Hant/workflow.ts
index 791fd1269c..9f4e7f8a87 100644
--- a/web/i18n/zh-Hant/workflow.ts
+++ b/web/i18n/zh-Hant/workflow.ts
@@ -442,6 +442,7 @@ const translation = {
},
outputVars: {
output: '生成內容',
+ reasoning_content: '推理內容',
usage: '模型用量信息',
},
singleRun: {
diff --git a/web/service/base.ts b/web/service/base.ts
index b0a2332e56..af4b01c0ae 100644
--- a/web/service/base.ts
+++ b/web/service/base.ts
@@ -180,9 +180,9 @@ export const handleStream = (
let isFirstMessage = true
function read() {
let hasError = false
- reader?.read().then((result: any) => {
+ reader?.read().then((result: ReadableStreamReadResult) => {
if (result.done) {
- onCompleted && onCompleted()
+ onCompleted?.()
return
}
buffer += decoder.decode(result.value, { stream: true })
@@ -322,7 +322,21 @@ export const handleStream = (
const baseFetch = base
-export const upload = async (options: any, isPublicAPI?: boolean, url?: string, searchParams?: string): Promise => {
+type UploadOptions = {
+ xhr: XMLHttpRequest
+ method: string
+ url?: string
+ headers?: Record
+ data: FormData
+ onprogress?: (this: XMLHttpRequest, ev: ProgressEvent) => void
+}
+
+type UploadResponse = {
+ id: string
+ [key: string]: unknown
+}
+
+export const upload = async (options: UploadOptions, isPublicAPI?: boolean, url?: string, searchParams?: string): Promise => {
const urlPrefix = isPublicAPI ? PUBLIC_API_PREFIX : API_PREFIX
const token = await getAccessToken(isPublicAPI)
const defaultOptions = {
@@ -331,18 +345,18 @@ export const upload = async (options: any, isPublicAPI?: boolean, url?: string,
headers: {
Authorization: `Bearer ${token}`,
},
- data: {},
}
- options = {
+ const mergedOptions = {
...defaultOptions,
...options,
- headers: { ...defaultOptions.headers, ...options.headers },
+ url: options.url || defaultOptions.url,
+ headers: { ...defaultOptions.headers, ...options.headers } as Record,
}
return new Promise((resolve, reject) => {
- const xhr = options.xhr
- xhr.open(options.method, options.url)
- for (const key in options.headers)
- xhr.setRequestHeader(key, options.headers[key])
+ const xhr = mergedOptions.xhr
+ xhr.open(mergedOptions.method, mergedOptions.url)
+ for (const key in mergedOptions.headers)
+ xhr.setRequestHeader(key, mergedOptions.headers[key])
xhr.withCredentials = true
xhr.responseType = 'json'
@@ -354,8 +368,9 @@ export const upload = async (options: any, isPublicAPI?: boolean, url?: string,
reject(xhr)
}
}
- xhr.upload.onprogress = options.onprogress
- xhr.send(options.data)
+ if (mergedOptions.onprogress)
+ xhr.upload.onprogress = mergedOptions.onprogress
+ xhr.send(mergedOptions.data)
})
}
@@ -432,7 +447,7 @@ export const ssePost = async (
if (!/^[23]\d{2}$/.test(String(res.status))) {
if (res.status === 401) {
if (isPublicAPI) {
- res.json().then((data: any) => {
+ res.json().then((data: { code?: string; message?: string }) => {
if (isPublicAPI) {
if (data.code === 'web_app_access_denied')
requiredWebSSOLogin(data.message, 403)
diff --git a/web/service/knowledge/use-hit-testing.ts b/web/service/knowledge/use-hit-testing.ts
index e69de29bb2..336ce12bb9 100644
--- a/web/service/knowledge/use-hit-testing.ts
+++ b/web/service/knowledge/use-hit-testing.ts
@@ -0,0 +1 @@
+export {}
diff --git a/web/service/share.ts b/web/service/share.ts
index f1e512564b..ab8e0deb4a 100644
--- a/web/service/share.ts
+++ b/web/service/share.ts
@@ -290,8 +290,10 @@ export const fetchAccessToken = async ({ appCode, userId, webAppAccessToken }: {
const headers = new Headers()
headers.append('X-App-Code', appCode)
const params = new URLSearchParams()
- webAppAccessToken && params.append('web_app_access_token', webAppAccessToken)
- userId && params.append('user_id', userId)
+ if (webAppAccessToken)
+ params.append('web_app_access_token', webAppAccessToken)
+ if (userId)
+ params.append('user_id', userId)
const url = `/passport?${params.toString()}`
return get(url, { headers }) as Promise<{ access_token: string }>
}
diff --git a/web/utils/var.ts b/web/utils/var.ts
index a9849bdc4b..3181d2bbd7 100644
--- a/web/utils/var.ts
+++ b/web/utils/var.ts
@@ -29,7 +29,7 @@ export const getNewVar = (key: string, type: string) => {
}
export const getNewVarInWorkflow = (key: string, type = InputVarType.textInput): InputVar => {
- const { max_length, ...rest } = VAR_ITEM_TEMPLATE_IN_WORKFLOW
+ const { max_length: _maxLength, ...rest } = VAR_ITEM_TEMPLATE_IN_WORKFLOW
if (type !== InputVarType.textInput) {
return {
...rest,
@@ -49,7 +49,7 @@ export const getNewVarInWorkflow = (key: string, type = InputVarType.textInput):
}
}
-export const checkKey = (key: string, canBeEmpty?: boolean, keys?: string[]) => {
+export const checkKey = (key: string, canBeEmpty?: boolean, _keys?: string[]) => {
if (key.length === 0 && !canBeEmpty)
return 'canNoBeEmpty'