Compare commits

...

37 Commits

Author SHA1 Message Date
NFish 3c404d18b3 Merge branch 'fix/web-app-support-session-in-url' into deploy/enterprise 6 months ago
GareArc ff25bbca9f 1.7.0
-----BEGIN PGP SIGNATURE-----
 
 iQGzBAABCAAdFiEEFK5K98uJ0hmL9JLza6DRCN7QEf8FAmiAvFgACgkQa6DRCN7Q
 Ef816Qv+NYHzK0yCcwji6lvzcUgf7V1l8ZCbbJdbzztbQuoKlUsB2XQhyr2y30X5
 kYHafWGSXbEAVOII7ca39EuUGVnvLx/AR7AsPzxOL4bxmWNricCUaK/XFtlbFuo5
 Rp5PQSPXa0VOFfBzktH7R1B3ET5eGfKauA5exDesiAHG6EDWbchnsFSYxpXzHLLs
 wLX7IMhQjFqBLyOKfI88+IxN+Gyo2NOTUhjt5yEqm6pUJANi3pg6ZwLl3/ODW+fx
 fu9rcOWZj7SHMhS6J5tIqRi6YO2o/b1tgBhsgI5gsAKJOdV8BwC71Vfwe+sJv3oC
 aMn6l4z0GENKC+256ag13Ku4/EKXytOY4LGZZrMUHr4n7EEGI1ODsVjXXOr5Fh6S
 wPO4GziBHaSyVogvvR8Mq7w1E5D6neqe2H87zc3dLe+E/vkZsv1W/E+Qo3iTJmqU
 VN1Q6WyeF/MhPEafXVPhBTLqrwiHmtZHVARuTpFvJb1wVGV3Cb28a6YMnMLOTYf3
 KW8VxjGZ
 =EOwC
 -----END PGP SIGNATURE-----
gpgsig -----BEGIN SSH SIGNATURE-----
 U1NIU0lHAAAAAQAAADMAAAALc3NoLWVkMjU1MTkAAAAg6SWWoDRBZt3I2ReXCRLrVSezuD
 ZkSRk8YmJa0R3Cde8AAAADZ2l0AAAAAAAAAAZzaGE1MTIAAABTAAAAC3NzaC1lZDI1NTE5
 AAAAQEZuS8+VT7OGNR+ITQUEyJM/KdyuP6rcLIaf48ccZ6dRLgGvRVV6UxtFjKiApRkPQZ
 uwVfos66Dd9sZxbEiFagE=
 -----END SSH SIGNATURE-----

Merge tag '1.7.0' into deploy/enterprise

1.7.0
6 months ago
NFish 24fdf10d1d fix: support authorization using session and user_id in URL. 6 months ago
-LAN- 51f26a83c6
test: add comprehensive unit tests for EmailI18nService
- Created comprehensive test suite with 19 test cases covering all EmailI18nService functionality
- Implemented mock classes (MockEmailRenderer, MockBrandingService, MockEmailSender) following protocol pattern
- Avoided using patch decorator, instead using constructor dependency injection for cleaner testing
- Tests cover:
  * Email sending with different languages (English, Chinese, fallback handling)
  * Branding enabled/disabled scenarios
  * Change email workflows (old/new phases)
  * Raw email sending (single and multiple recipients)
  * Error handling for invalid phases and missing templates
  * Subject templating with variables
  * Integration tests for default configuration and service creation
  * Flask-specific components (renderer and sender)

The tests follow DDD principles with proper separation of concerns and use
dependency injection rather than mocking frameworks for cleaner, more maintainable tests.

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
7 months ago
-LAN- 1fe87c01c5
refactor: migrate direct mail.send usages to EmailI18nService
- Updated mail_enterprise_task.py to use EmailI18nService.send_raw_email()
- Updated queue_monitor_task.py to use EmailI18nService with new QUEUE_MONITOR_ALERT type
- Updated mail_clean_document_notify_task.py to use EmailI18nService with new DOCUMENT_CLEAN_NOTIFY type
- Added send_raw_email() method for backward compatibility with pre-rendered HTML emails
- Added new email types: ENTERPRISE_CUSTOM, QUEUE_MONITOR_ALERT, DOCUMENT_CLEAN_NOTIFY
- Added email template configurations for the new email types
- Removed unused imports (render_template, mail) from refactored files

This change centralizes email handling through EmailI18nService while maintaining
backward compatibility for legacy email sending patterns.

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
7 months ago
-LAN- f05e7e7068
refactor: centralize email internationalization handling
- Create elegant email i18n module following DDD principles
- Eliminate repetitive language switching logic across email tasks
- Add comprehensive type hints and proper abstractions
- Support all existing email types with centralized configuration
- Reduce code duplication by 50% while maintaining backward compatibility
- Improve maintainability with single responsibility and dependency injection
7 months ago
NFish fc6017c46c fix: the text/icon shows wrong color in darkmode 7 months ago
crazywoola 7e0d865152 Chore/update gh template (#22480) 7 months ago
heyszt f4b92bb038 fix aliyun trace session_id (#22468) 7 months ago
Wu Tianwei 61de7a8654 fix: add background color for chat bubble in light and dark themes (#22472) 7 months ago
QuantumGhost 9269989924 feat(api): add UUIDv7 implementation in SQL and Python (#22058)
This PR introduces UUIDv7 implementations in both Python and SQL to establish the foundation for migrating from UUIDv4 to UUIDv7 as proposed in #19754.

ID generation algorithm of existing models are not changed, and new models should use UUIDv7 for ID generation.

Close #19754.
7 months ago
QuantumGhost 59c35a49b1 refactor(api): Separate SegmentType for Integer/Float to Enable Pydantic Serialization (#22025)
refactor(api): Separate SegmentType for Integer/Float to Enable Pydantic Serialization (#22025)

This PR addresses serialization issues in the VariablePool model by separating the `value_type` tags for `IntegerSegment`/`FloatSegment` and `IntegerVariable`/`FloatVariable`. Previously, both Integer and Float types shared the same `SegmentType.NUMBER` tag, causing conflicts during serialization.

Key changes:
- Introduce distinct `value_type` tags for Integer and Float segments/variables
- Add `VariableUnion` and `SegmentUnion` types for proper type discrimination
- Leverage Pydantic's discriminated union feature for seamless serialization/deserialization
- Enable accurate serialization of data structures containing these types

Closes #22024.
7 months ago
Kerwin Bryant 4a06e4d4d9 Improve Tooltip UX by enabling delay by default (#21383) 7 months ago
yolofit 5ba6983727 fix: When var value changed, PromptEditor should be reset (#22219) 7 months ago
NeatGuyCoding 8ef7f0fed2 minor fix: using Pydantic model_validate instead of deprecated parse_obj (#22239)
Signed-off-by: neatguycoding <15627489+NeatGuyCoding@users.noreply.github.com>
7 months ago
Jason Young b4779d4042 test: add comprehensive unit tests for console authentication and authorization decorators (#22439) 7 months ago
znn 23996a5605 adding tooltip for bindingCount (#22450)
Co-authored-by: crazywoola <100913391+crazywoola@users.noreply.github.com>
Co-authored-by: crazywoola <427733928@qq.com>
7 months ago
NeatGuyCoding 780748460d fix(api): Fix potential thread leak in MCP `BaseSession` (#22169)
The `BaseSession` class in the `core/mcp/session` package uses `ThreadPoolExecutor` 
to run the receive loop but fails to properly clean up the executor and receiver 
future, leading to potential thread leaks.

This PR addresses this issue by:
- Initializing `_executor` and `_receiver_future` attributes to `None` for proper cleanup checks
- Adding graceful shutdown with a 5-second timeout in the `__exit__` method
- Ensuring the ThreadPoolExecutor is properly shut down to prevent resource leaks

This fix prevents memory leaks and hanging threads in long-running scenarios where 
multiple MCP sessions are created and destroyed.

Signed-off-by: neatguycoding <15627489+NeatGuyCoding@users.noreply.github.com>
Co-authored-by: QuantumGhost <obelisk.reg+git@gmail.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
7 months ago
Jacky Wu e48483b52d chore: add SQLALCHEMY_POOL_USE_LIFO option and missing SQLALCHEMY_POOL_PRE_PING env default value. (#22371) 7 months ago
GuanMu db2b3650ca fix: Disable question editing in chat history (#22438) 7 months ago
GuanMu 6f35fa1e46 fix: Update condition items to support variable type acquisition (#22414) 7 months ago
zyssyz123 3484cee5cf
Feat/change user email (#22425)
Co-authored-by: JzoNg <jzongcode@gmail.com>
7 months ago
Garfield Dai 0fe9d4955c Merge remote-tracking branch 'origin/main' into deploy/enterprise 7 months ago
NFish 2a0a315187 Merge branch 'perf/web-app-authrozation' into deploy/enterprise 7 months ago
NFish 3e18dd41e7 fix: show App is UnAvailable when no app info found in explore page 7 months ago
NFish 128f8de382 Merge branch 'perf/web-app-authrozation' into deploy/enterprise 7 months ago
NFish 8ead8961ce fix: check user can access web app in background task 7 months ago
NFish 8a888e082d Merge branch 'perf/web-app-authrozation' into deploy/enterprise 7 months ago
NFish 513af98729 perf: use component to handle webapp info fetch, authorization 7 months ago
NFish 35d2a935a3 Merge branch 'fix/allow-update-plugin-settings' into deploy/enterprise 7 months ago
NFish 207d0f78f5 fix: allow update plugin install settings 7 months ago
NFish 56e8b9711d Merge branch 'perf/web-app-authrozation' into deploy/enterprise 7 months ago
NFish e4b6c33bdd wip: Adjust the authentication process to improve user experience 7 months ago
NFish c0e73c1659 Merge branch 'fix/install-preference-error' into deploy/enterprise 7 months ago
NFish 434c809866 don't add search params when opening detail links from marketplace. 7 months ago
NFish 6ab09397ef Merge branch 'perf/web-app-authrozation' into deploy/enterprise 7 months ago
NFish 3bead19f19 wip: enhance user experience by refining authorization verification process 7 months ago

@ -43,6 +43,18 @@ class OwnerTransferRateLimitExceededError(BaseHTTPException):
code = 429
class EmailChangeRateLimitExceededError(BaseHTTPException):
error_code = "email_change_rate_limit_exceeded"
description = "Too many email change emails have been sent. Please try again in 1 minutes."
code = 429
class OwnerTransferRateLimitExceededError(BaseHTTPException):
error_code = "owner_transfer_rate_limit_exceeded"
description = "Too many owner tansfer emails have been sent. Please try again in 1 minutes."
code = 429
class EmailCodeError(BaseHTTPException):
error_code = "email_code_error"
description = "Email code is invalid or expired."

@ -1,38 +1,26 @@
import pytz
from flask import request
from flask_login import current_user
from flask_restful import Resource, fields, marshal_with, reqparse
from sqlalchemy import select
from sqlalchemy.orm import Session
from configs import dify_config
from constants.languages import supported_language
from controllers.console import api
from controllers.console.auth.error import (
EmailAlreadyInUseError,
EmailChangeLimitError,
EmailCodeError,
InvalidEmailError,
InvalidTokenError,
)
from controllers.console.auth.error import (EmailAlreadyInUseError,
EmailChangeLimitError,
EmailCodeError, InvalidEmailError,
InvalidTokenError)
from controllers.console.error import AccountNotFound, EmailSendIpLimitError
from controllers.console.workspace.error import (
AccountAlreadyInitedError,
CurrentPasswordIncorrectError,
InvalidAccountDeletionCodeError,
InvalidInvitationCodeError,
RepeatPasswordNotMatchError,
)
from controllers.console.wraps import (
account_initialization_required,
cloud_edition_billing_enabled,
enable_change_email,
enterprise_license_required,
only_edition_cloud,
setup_required,
)
AccountAlreadyInitedError, CurrentPasswordIncorrectError,
InvalidAccountDeletionCodeError, InvalidInvitationCodeError,
RepeatPasswordNotMatchError)
from controllers.console.wraps import (account_initialization_required,
cloud_edition_billing_enabled,
enable_change_email,
enterprise_license_required,
only_edition_cloud, setup_required)
from extensions.ext_database import db
from fields.member_fields import account_fields
from flask import request
from flask_login import current_user
from flask_restful import Resource, fields, marshal_with, reqparse
from libs.datetime_utils import naive_utc_now
from libs.helper import TimestampField, email, extract_remote_ip, timezone
from libs.login import login_required
@ -40,7 +28,10 @@ from models import AccountIntegrate, InvitationCode
from models.account import Account
from services.account_service import AccountService
from services.billing_service import BillingService
from services.errors.account import CurrentPasswordIncorrectError as ServiceCurrentPasswordIncorrectError
from services.errors.account import \
CurrentPasswordIncorrectError as ServiceCurrentPasswordIncorrectError
from sqlalchemy import select
from sqlalchemy.orm import Session
class AccountInitApi(Resource):

@ -1,34 +1,29 @@
from urllib import parse
from flask import request
from flask_login import current_user
from flask_restful import Resource, abort, marshal_with, reqparse
import services
from configs import dify_config
from controllers.console import api
from controllers.console.auth.error import (
CannotTransferOwnerToSelfError,
EmailCodeError,
InvalidEmailError,
InvalidTokenError,
MemberNotInTenantError,
NotOwnerError,
OwnerTransferLimitError,
)
from controllers.console.error import EmailSendIpLimitError, WorkspaceMembersLimitExceeded
from controllers.console.wraps import (
account_initialization_required,
cloud_edition_billing_resource_check,
is_allow_transfer_owner,
setup_required,
)
from controllers.console.auth.error import (CannotTransferOwnerToSelfError,
EmailCodeError, InvalidEmailError,
InvalidTokenError,
MemberNotInTenantError,
NotOwnerError,
OwnerTransferLimitError)
from controllers.console.error import (EmailSendIpLimitError,
WorkspaceMembersLimitExceeded)
from controllers.console.wraps import (account_initialization_required,
cloud_edition_billing_resource_check,
is_allow_transfer_owner, setup_required)
from extensions.ext_database import db
from fields.member_fields import account_with_role_list_fields
from flask import request
from flask_login import current_user
from flask_restful import Resource, abort, marshal_with, reqparse
from libs.helper import extract_remote_ip
from libs.login import login_required
from models.account import Account, TenantAccountRole
from services.account_service import AccountService, RegisterService, TenantService
from services.account_service import (AccountService, RegisterService,
TenantService)
from services.errors.account import AccountAlreadyInTenantError
from services.feature_service import FeatureService

@ -2,24 +2,18 @@ import logging
from collections.abc import Mapping
from typing import Any, Optional, cast
from sqlalchemy import select
from sqlalchemy.orm import Session
from configs import dify_config
from core.app.apps.advanced_chat.app_config_manager import AdvancedChatAppConfig
from core.app.apps.advanced_chat.app_config_manager import \
AdvancedChatAppConfig
from core.app.apps.base_app_queue_manager import AppQueueManager
from core.app.apps.workflow_app_runner import WorkflowBasedAppRunner
from core.app.entities.app_invoke_entities import (
AdvancedChatAppGenerateEntity,
AppGenerateEntity,
InvokeFrom,
)
from core.app.entities.queue_entities import (
QueueAnnotationReplyEvent,
QueueStopEvent,
QueueTextChunkEvent,
)
from core.app.features.annotation_reply.annotation_reply import AnnotationReplyFeature
AdvancedChatAppGenerateEntity, AppGenerateEntity, InvokeFrom)
from core.app.entities.queue_entities import (QueueAnnotationReplyEvent,
QueueStopEvent,
QueueTextChunkEvent)
from core.app.features.annotation_reply.annotation_reply import \
AnnotationReplyFeature
from core.moderation.base import ModerationError
from core.moderation.input_moderation import InputModeration
from core.variables.variables import VariableUnion
@ -33,6 +27,8 @@ from models import Workflow
from models.enums import UserFrom
from models.model import App, Conversation, Message, MessageAnnotation
from models.workflow import ConversationVariable, WorkflowType
from sqlalchemy import select
from sqlalchemy.orm import Session
logger = logging.getLogger(__name__)

@ -5,10 +5,8 @@ from configs import dify_config
from core.app.apps.base_app_queue_manager import AppQueueManager
from core.app.apps.workflow.app_config_manager import WorkflowAppConfig
from core.app.apps.workflow_app_runner import WorkflowBasedAppRunner
from core.app.entities.app_invoke_entities import (
InvokeFrom,
WorkflowAppGenerateEntity,
)
from core.app.entities.app_invoke_entities import (InvokeFrom,
WorkflowAppGenerateEntity)
from core.workflow.callbacks import WorkflowCallback, WorkflowLoggingCallback
from core.workflow.entities.variable_pool import VariablePool
from core.workflow.system_variable import SystemVariable

@ -4,75 +4,59 @@ from collections.abc import Callable, Generator
from contextlib import contextmanager
from typing import Any, Optional, Union
from sqlalchemy.orm import Session
from constants.tts_auto_play_timeout import TTS_AUTO_PLAY_TIMEOUT, TTS_AUTO_PLAY_YIELD_CPU_TIME
from constants.tts_auto_play_timeout import (TTS_AUTO_PLAY_TIMEOUT,
TTS_AUTO_PLAY_YIELD_CPU_TIME)
from core.app.apps.base_app_queue_manager import AppQueueManager
from core.app.apps.common.workflow_response_converter import WorkflowResponseConverter
from core.app.entities.app_invoke_entities import (
InvokeFrom,
WorkflowAppGenerateEntity,
)
from core.app.apps.common.workflow_response_converter import \
WorkflowResponseConverter
from core.app.entities.app_invoke_entities import (InvokeFrom,
WorkflowAppGenerateEntity)
from core.app.entities.queue_entities import (
MessageQueueMessage,
QueueAgentLogEvent,
QueueErrorEvent,
QueueIterationCompletedEvent,
QueueIterationNextEvent,
QueueIterationStartEvent,
QueueLoopCompletedEvent,
QueueLoopNextEvent,
QueueLoopStartEvent,
QueueNodeExceptionEvent,
QueueNodeFailedEvent,
QueueNodeInIterationFailedEvent,
QueueNodeInLoopFailedEvent,
QueueNodeRetryEvent,
QueueNodeStartedEvent,
QueueNodeSucceededEvent,
QueueParallelBranchRunFailedEvent,
QueueParallelBranchRunStartedEvent,
QueueParallelBranchRunSucceededEvent,
QueuePingEvent,
QueueStopEvent,
QueueTextChunkEvent,
QueueWorkflowFailedEvent,
QueueWorkflowPartialSuccessEvent,
QueueWorkflowStartedEvent,
QueueWorkflowSucceededEvent,
WorkflowQueueMessage,
)
from core.app.entities.task_entities import (
ErrorStreamResponse,
MessageAudioEndStreamResponse,
MessageAudioStreamResponse,
PingStreamResponse,
StreamResponse,
TextChunkStreamResponse,
WorkflowAppBlockingResponse,
WorkflowAppStreamResponse,
WorkflowFinishStreamResponse,
WorkflowStartStreamResponse,
)
from core.app.task_pipeline.based_generate_task_pipeline import BasedGenerateTaskPipeline
MessageQueueMessage, QueueAgentLogEvent, QueueErrorEvent,
QueueIterationCompletedEvent, QueueIterationNextEvent,
QueueIterationStartEvent, QueueLoopCompletedEvent, QueueLoopNextEvent,
QueueLoopStartEvent, QueueNodeExceptionEvent, QueueNodeFailedEvent,
QueueNodeInIterationFailedEvent, QueueNodeInLoopFailedEvent,
QueueNodeRetryEvent, QueueNodeStartedEvent, QueueNodeSucceededEvent,
QueueParallelBranchRunFailedEvent, QueueParallelBranchRunStartedEvent,
QueueParallelBranchRunSucceededEvent, QueuePingEvent, QueueStopEvent,
QueueTextChunkEvent, QueueWorkflowFailedEvent,
QueueWorkflowPartialSuccessEvent, QueueWorkflowStartedEvent,
QueueWorkflowSucceededEvent, WorkflowQueueMessage)
from core.app.entities.task_entities import (ErrorStreamResponse,
MessageAudioEndStreamResponse,
MessageAudioStreamResponse,
PingStreamResponse,
StreamResponse,
TextChunkStreamResponse,
WorkflowAppBlockingResponse,
WorkflowAppStreamResponse,
WorkflowFinishStreamResponse,
WorkflowStartStreamResponse)
from core.app.task_pipeline.based_generate_task_pipeline import \
BasedGenerateTaskPipeline
from core.base.tts import AppGeneratorTTSPublisher, AudioTrunk
from core.ops.ops_trace_manager import TraceQueueManager
from core.workflow.entities.workflow_execution import WorkflowExecution, WorkflowExecutionStatus, WorkflowType
from core.workflow.graph_engine.entities.graph_runtime_state import GraphRuntimeState
from core.workflow.repositories.draft_variable_repository import DraftVariableSaverFactory
from core.workflow.repositories.workflow_execution_repository import WorkflowExecutionRepository
from core.workflow.repositories.workflow_node_execution_repository import WorkflowNodeExecutionRepository
from core.workflow.entities.workflow_execution import (WorkflowExecution,
WorkflowExecutionStatus,
WorkflowType)
from core.workflow.graph_engine.entities.graph_runtime_state import \
GraphRuntimeState
from core.workflow.repositories.draft_variable_repository import \
DraftVariableSaverFactory
from core.workflow.repositories.workflow_execution_repository import \
WorkflowExecutionRepository
from core.workflow.repositories.workflow_node_execution_repository import \
WorkflowNodeExecutionRepository
from core.workflow.system_variable import SystemVariable
from core.workflow.workflow_cycle_manager import CycleManagerWorkflowInfo, WorkflowCycleManager
from core.workflow.workflow_cycle_manager import (CycleManagerWorkflowInfo,
WorkflowCycleManager)
from extensions.ext_database import db
from models.account import Account
from models.enums import CreatorUserRole
from models.model import EndUser
from models.workflow import (
Workflow,
WorkflowAppLog,
WorkflowAppLogCreatedFrom,
)
from models.workflow import Workflow, WorkflowAppLog, WorkflowAppLogCreatedFrom
from sqlalchemy.orm import Session
logger = logging.getLogger(__name__)

@ -3,16 +3,17 @@ from collections import defaultdict
from collections.abc import Mapping, Sequence
from typing import Annotated, Any, Union, cast
from pydantic import BaseModel, Field
from core.file import File, FileAttribute, file_manager
from core.variables import Segment, SegmentGroup, Variable
from core.variables.consts import MIN_SELECTORS_LENGTH
from core.variables.segments import FileSegment, NoneSegment
from core.variables.variables import VariableUnion
from core.workflow.constants import CONVERSATION_VARIABLE_NODE_ID, ENVIRONMENT_VARIABLE_NODE_ID, SYSTEM_VARIABLE_NODE_ID
from core.workflow.constants import (CONVERSATION_VARIABLE_NODE_ID,
ENVIRONMENT_VARIABLE_NODE_ID,
SYSTEM_VARIABLE_NODE_ID)
from core.workflow.system_variable import SystemVariable
from factories import variable_factory
from pydantic import BaseModel, Field
VariableValue = Union[str, int, float, dict, list, File]
@ -186,3 +187,4 @@ class VariablePool(BaseModel):
def empty(cls) -> "VariablePool":
"""Create an empty variable pool."""
return cls(system_variables=SystemVariable.empty())
return cls(system_variables=SystemVariable.empty())

@ -4,28 +4,29 @@ from datetime import datetime
from typing import Any, Optional, Union
from uuid import uuid4
from core.app.entities.app_invoke_entities import AdvancedChatAppGenerateEntity, WorkflowAppGenerateEntity
from core.app.entities.queue_entities import (
QueueNodeExceptionEvent,
QueueNodeFailedEvent,
QueueNodeInIterationFailedEvent,
QueueNodeInLoopFailedEvent,
QueueNodeRetryEvent,
QueueNodeStartedEvent,
QueueNodeSucceededEvent,
)
from core.app.entities.app_invoke_entities import (
AdvancedChatAppGenerateEntity, WorkflowAppGenerateEntity)
from core.app.entities.queue_entities import (QueueNodeExceptionEvent,
QueueNodeFailedEvent,
QueueNodeInIterationFailedEvent,
QueueNodeInLoopFailedEvent,
QueueNodeRetryEvent,
QueueNodeStartedEvent,
QueueNodeSucceededEvent)
from core.app.task_pipeline.exc import WorkflowRunNotFoundError
from core.ops.entities.trace_entity import TraceTaskName
from core.ops.ops_trace_manager import TraceQueueManager, TraceTask
from core.workflow.entities.workflow_execution import WorkflowExecution, WorkflowExecutionStatus, WorkflowType
from core.workflow.entities.workflow_execution import (WorkflowExecution,
WorkflowExecutionStatus,
WorkflowType)
from core.workflow.entities.workflow_node_execution import (
WorkflowNodeExecution,
WorkflowNodeExecutionMetadataKey,
WorkflowNodeExecutionStatus,
)
WorkflowNodeExecution, WorkflowNodeExecutionMetadataKey,
WorkflowNodeExecutionStatus)
from core.workflow.enums import SystemVariableKey
from core.workflow.repositories.workflow_execution_repository import WorkflowExecutionRepository
from core.workflow.repositories.workflow_node_execution_repository import WorkflowNodeExecutionRepository
from core.workflow.repositories.workflow_execution_repository import \
WorkflowExecutionRepository
from core.workflow.repositories.workflow_node_execution_repository import \
WorkflowNodeExecutionRepository
from core.workflow.system_variable import SystemVariable
from core.workflow.workflow_entry import WorkflowEntry
from libs.datetime_utils import naive_utc_now
@ -453,3 +454,4 @@ class WorkflowCycleManager:
execution_metadata_dict.update(event.execution_metadata)
return {**execution_metadata_dict, **origin_metadata} if execution_metadata_dict else origin_metadata
return {**execution_metadata_dict, **origin_metadata} if execution_metadata_dict else origin_metadata

@ -5,11 +5,9 @@ from collections.abc import Callable, Generator, Mapping, Sequence
from typing import Any, Optional, cast
from uuid import uuid4
from sqlalchemy import select
from sqlalchemy.orm import Session, sessionmaker
from core.app.app_config.entities import VariableEntityType
from core.app.apps.advanced_chat.app_config_manager import AdvancedChatAppConfigManager
from core.app.apps.advanced_chat.app_config_manager import \
AdvancedChatAppConfigManager
from core.app.apps.workflow.app_config_manager import WorkflowAppConfigManager
from core.file import File
from core.repositories import DifyCoreRepositoryFactory
@ -17,7 +15,8 @@ from core.variables import Variable
from core.variables.variables import VariableUnion
from core.workflow.entities.node_entities import NodeRunResult
from core.workflow.entities.variable_pool import VariablePool
from core.workflow.entities.workflow_node_execution import WorkflowNodeExecution, WorkflowNodeExecutionStatus
from core.workflow.entities.workflow_node_execution import (
WorkflowNodeExecution, WorkflowNodeExecutionStatus)
from core.workflow.errors import WorkflowNodeRunFailedError
from core.workflow.graph_engine.entities.event import InNodeEvent
from core.workflow.nodes import NodeType
@ -25,33 +24,32 @@ from core.workflow.nodes.base.node import BaseNode
from core.workflow.nodes.enums import ErrorStrategy
from core.workflow.nodes.event import RunCompletedEvent
from core.workflow.nodes.event.types import NodeEvent
from core.workflow.nodes.node_mapping import LATEST_VERSION, NODE_TYPE_CLASSES_MAPPING
from core.workflow.nodes.node_mapping import (LATEST_VERSION,
NODE_TYPE_CLASSES_MAPPING)
from core.workflow.nodes.start.entities import StartNodeData
from core.workflow.system_variable import SystemVariable
from core.workflow.workflow_entry import WorkflowEntry
from events.app_event import app_draft_workflow_was_synced, app_published_workflow_was_updated
from events.app_event import (app_draft_workflow_was_synced,
app_published_workflow_was_updated)
from extensions.ext_database import db
from factories.file_factory import build_from_mapping, build_from_mappings
from libs.datetime_utils import naive_utc_now
from models.account import Account
from models.model import App, AppMode
from models.tools import WorkflowToolProvider
from models.workflow import (
Workflow,
WorkflowNodeExecutionModel,
WorkflowNodeExecutionTriggeredFrom,
WorkflowType,
)
from models.workflow import (Workflow, WorkflowNodeExecutionModel,
WorkflowNodeExecutionTriggeredFrom, WorkflowType)
from repositories.factory import DifyAPIRepositoryFactory
from services.errors.app import IsDraftWorkflowError, WorkflowHashNotEqualError
from services.workflow.workflow_converter import WorkflowConverter
from sqlalchemy import select
from sqlalchemy.orm import Session, sessionmaker
from .errors.workflow_service import DraftWorkflowDeletionError, WorkflowInUseError
from .workflow_draft_variable_service import (
DraftVariableSaver,
DraftVarLoader,
WorkflowDraftVariableService,
)
from .errors.workflow_service import (DraftWorkflowDeletionError,
WorkflowInUseError)
from .workflow_draft_variable_service import (DraftVariableSaver,
DraftVarLoader,
WorkflowDraftVariableService)
class WorkflowService:

@ -42,7 +42,8 @@
font-family: Inter;
font-style: normal;
font-weight: 600;
line-height: 120%; /* 28.8px */
line-height: 120%;
/* 28.8px */
}
.description {
@ -51,7 +52,8 @@
font-family: Inter;
font-style: normal;
font-weight: 400;
line-height: 20px; /* 142.857% */
line-height: 20px;
/* 142.857% */
letter-spacing: -0.07px;
}
@ -96,7 +98,8 @@
font-family: Inter;
font-style: normal;
font-weight: 400;
line-height: 20px; /* 142.857% */
line-height: 20px;
/* 142.857% */
letter-spacing: -0.07px;
}
</style>
@ -121,5 +124,4 @@
</div>
</body>
</html>
</html>

@ -42,7 +42,8 @@
font-family: Inter;
font-style: normal;
font-weight: 600;
line-height: 120%; /* 28.8px */
line-height: 120%;
/* 28.8px */
}
.description {
@ -51,7 +52,8 @@
font-family: Inter;
font-style: normal;
font-weight: 400;
line-height: 20px; /* 142.857% */
line-height: 20px;
/* 142.857% */
letter-spacing: -0.07px;
}
@ -96,7 +98,8 @@
font-family: Inter;
font-style: normal;
font-weight: 400;
line-height: 20px; /* 142.857% */
line-height: 20px;
/* 142.857% */
letter-spacing: -0.07px;
}
</style>
@ -121,5 +124,4 @@
</div>
</body>
</html>
</html>

@ -42,7 +42,8 @@
font-family: Inter;
font-style: normal;
font-weight: 600;
line-height: 120%; /* 28.8px */
line-height: 120%;
/* 28.8px */
}
.description {
@ -51,7 +52,8 @@
font-family: Inter;
font-style: normal;
font-weight: 400;
line-height: 20px; /* 142.857% */
line-height: 20px;
/* 142.857% */
letter-spacing: -0.07px;
}
@ -96,7 +98,8 @@
font-family: Inter;
font-style: normal;
font-weight: 400;
line-height: 20px; /* 142.857% */
line-height: 20px;
/* 142.857% */
letter-spacing: -0.07px;
}
</style>
@ -121,5 +124,4 @@
</div>
</body>
</html>
</html>

@ -42,7 +42,8 @@
font-family: Inter;
font-style: normal;
font-weight: 600;
line-height: 120%; /* 28.8px */
line-height: 120%;
/* 28.8px */
}
.description {
@ -51,7 +52,8 @@
font-family: Inter;
font-style: normal;
font-weight: 400;
line-height: 20px; /* 142.857% */
line-height: 20px;
/* 142.857% */
letter-spacing: -0.07px;
}
@ -96,7 +98,8 @@
font-family: Inter;
font-style: normal;
font-weight: 400;
line-height: 20px; /* 142.857% */
line-height: 20px;
/* 142.857% */
letter-spacing: -0.07px;
}
</style>
@ -120,5 +123,4 @@
</div>
</body>
</html>
</html>

@ -42,7 +42,8 @@
font-family: Inter;
font-style: normal;
font-weight: 600;
line-height: 120%; /* 28.8px */
line-height: 120%;
/* 28.8px */
}
.description {
@ -51,7 +52,8 @@
font-family: Inter;
font-style: normal;
font-weight: 400;
line-height: 20px; /* 142.857% */
line-height: 20px;
/* 142.857% */
letter-spacing: -0.07px;
}
@ -88,5 +90,4 @@
</div>
</body>
</html>
</html>

@ -42,7 +42,8 @@
font-family: Inter;
font-style: normal;
font-weight: 600;
line-height: 120%; /* 28.8px */
line-height: 120%;
/* 28.8px */
}
.description {
@ -51,7 +52,8 @@
font-family: Inter;
font-style: normal;
font-weight: 400;
line-height: 20px; /* 142.857% */
line-height: 20px;
/* 142.857% */
letter-spacing: -0.07px;
}
@ -88,5 +90,4 @@
</div>
</body>
</html>
</html>

@ -42,7 +42,8 @@
font-family: Inter;
font-style: normal;
font-weight: 600;
line-height: 120%; /* 28.8px */
line-height: 120%;
/* 28.8px */
}
.description {
@ -51,7 +52,8 @@
font-family: Inter;
font-style: normal;
font-weight: 400;
line-height: 20px; /* 142.857% */
line-height: 20px;
/* 142.857% */
letter-spacing: -0.07px;
}
@ -97,7 +99,8 @@
font-family: Inter;
font-style: normal;
font-weight: 400;
line-height: 20px; /* 142.857% */
line-height: 20px;
/* 142.857% */
letter-spacing: -0.07px;
}
</style>
@ -111,12 +114,14 @@
</div>
<p class="title">Workspace ownership has been transferred</p>
<div class="description">
<p class="content1">You have successfully transferred ownership of the workspace "{{WorkspaceName}}" to {{NewOwnerEmail}}.</p>
<p class="content2">You no longer have owner privileges for this workspace. Your access level has been changed to Admin.</p>
<p class="content3">If you did not initiate this transfer or have concerns about this change, please contact support@dify.ai immediately.</p>
<p class="content1">You have successfully transferred ownership of the workspace "{{WorkspaceName}}" to
{{NewOwnerEmail}}.</p>
<p class="content2">You no longer have owner privileges for this workspace. Your access level has been changed to
Admin.</p>
<p class="content3">If you did not initiate this transfer or have concerns about this change, please contact
support@dify.ai immediately.</p>
</div>
</div>
</body>
</html>
</html>

@ -42,7 +42,8 @@
font-family: Inter;
font-style: normal;
font-weight: 600;
line-height: 120%; /* 28.8px */
line-height: 120%;
/* 28.8px */
}
.description {
@ -51,7 +52,8 @@
font-family: Inter;
font-style: normal;
font-weight: 400;
line-height: 20px; /* 142.857% */
line-height: 20px;
/* 142.857% */
letter-spacing: -0.07px;
}
@ -97,7 +99,8 @@
font-family: Inter;
font-style: normal;
font-weight: 400;
line-height: 20px; /* 142.857% */
line-height: 20px;
/* 142.857% */
letter-spacing: -0.07px;
}
</style>
@ -118,5 +121,4 @@
</div>
</body>
</html>
</html>

@ -42,7 +42,8 @@
font-family: Inter;
font-style: normal;
font-weight: 600;
line-height: 120%; /* 28.8px */
line-height: 120%;
/* 28.8px */
}
.description {
@ -51,7 +52,8 @@
font-family: Inter;
font-style: normal;
font-weight: 400;
line-height: 20px; /* 142.857% */
line-height: 20px;
/* 142.857% */
letter-spacing: -0.07px;
}
@ -95,7 +97,8 @@
font-size: 14px;
font-style: normal;
font-weight: 600;
line-height: 20px; /* 142.857% */
line-height: 20px;
/* 142.857% */
}
.warningList {
@ -106,7 +109,8 @@
font-size: 14px;
font-style: normal;
font-weight: 400;
line-height: 20px; /* 142.857% */
line-height: 20px;
/* 142.857% */
letter-spacing: -0.07px;
}
@ -119,7 +123,8 @@
font-family: Inter;
font-style: normal;
font-weight: 400;
line-height: 20px; /* 142.857% */
line-height: 20px;
/* 142.857% */
letter-spacing: -0.07px;
}
</style>
@ -149,5 +154,4 @@
</div>
</body>
</html>
</html>

@ -42,7 +42,8 @@
font-family: Inter;
font-style: normal;
font-weight: 600;
line-height: 120%; /* 28.8px */
line-height: 120%;
/* 28.8px */
}
.description {
@ -51,7 +52,8 @@
font-family: Inter;
font-style: normal;
font-weight: 400;
line-height: 20px; /* 142.857% */
line-height: 20px;
/* 142.857% */
letter-spacing: -0.07px;
}
@ -95,7 +97,8 @@
font-size: 14px;
font-style: normal;
font-weight: 600;
line-height: 20px; /* 142.857% */
line-height: 20px;
/* 142.857% */
}
.warningList {
@ -106,7 +109,8 @@
font-size: 14px;
font-style: normal;
font-weight: 400;
line-height: 20px; /* 142.857% */
line-height: 20px;
/* 142.857% */
letter-spacing: -0.07px;
}
@ -119,7 +123,8 @@
font-family: Inter;
font-style: normal;
font-weight: 400;
line-height: 20px; /* 142.857% */
line-height: 20px;
/* 142.857% */
letter-spacing: -0.07px;
}
</style>
@ -149,5 +154,4 @@
</div>
</body>
</html>
</html>

@ -42,7 +42,8 @@
font-family: Inter;
font-style: normal;
font-weight: 600;
line-height: 120%; /* 28.8px */
line-height: 120%;
/* 28.8px */
}
.description {
@ -51,7 +52,8 @@
font-family: Inter;
font-style: normal;
font-weight: 400;
line-height: 20px; /* 142.857% */
line-height: 20px;
/* 142.857% */
letter-spacing: -0.07px;
}
@ -96,7 +98,8 @@
font-family: Inter;
font-style: normal;
font-weight: 400;
line-height: 20px; /* 142.857% */
line-height: 20px;
/* 142.857% */
letter-spacing: -0.07px;
}
</style>
@ -118,5 +121,4 @@
</div>
</body>
</html>
</html>

@ -42,7 +42,8 @@
font-family: Inter;
font-style: normal;
font-weight: 600;
line-height: 120%; /* 28.8px */
line-height: 120%;
/* 28.8px */
}
.description {
@ -51,7 +52,8 @@
font-family: Inter;
font-style: normal;
font-weight: 400;
line-height: 20px; /* 142.857% */
line-height: 20px;
/* 142.857% */
letter-spacing: -0.07px;
}
@ -96,7 +98,8 @@
font-family: Inter;
font-style: normal;
font-weight: 400;
line-height: 20px; /* 142.857% */
line-height: 20px;
/* 142.857% */
letter-spacing: -0.07px;
}
</style>
@ -118,5 +121,4 @@
</div>
</body>
</html>
</html>

@ -42,7 +42,8 @@
font-family: Inter;
font-style: normal;
font-weight: 600;
line-height: 120%; /* 28.8px */
line-height: 120%;
/* 28.8px */
}
.description {
@ -51,7 +52,8 @@
font-family: Inter;
font-style: normal;
font-weight: 400;
line-height: 20px; /* 142.857% */
line-height: 20px;
/* 142.857% */
letter-spacing: -0.07px;
}
@ -96,7 +98,8 @@
font-family: Inter;
font-style: normal;
font-weight: 400;
line-height: 20px; /* 142.857% */
line-height: 20px;
/* 142.857% */
letter-spacing: -0.07px;
}
</style>
@ -118,5 +121,4 @@
</div>
</body>
</html>
</html>

@ -42,7 +42,8 @@
font-family: Inter;
font-style: normal;
font-weight: 600;
line-height: 120%; /* 28.8px */
line-height: 120%;
/* 28.8px */
}
.description {
@ -51,7 +52,8 @@
font-family: Inter;
font-style: normal;
font-weight: 400;
line-height: 20px; /* 142.857% */
line-height: 20px;
/* 142.857% */
letter-spacing: -0.07px;
}
@ -96,7 +98,8 @@
font-family: Inter;
font-style: normal;
font-weight: 400;
line-height: 20px; /* 142.857% */
line-height: 20px;
/* 142.857% */
letter-spacing: -0.07px;
}
</style>
@ -117,5 +120,4 @@
</div>
</body>
</html>
</html>

@ -42,7 +42,8 @@
font-family: Inter;
font-style: normal;
font-weight: 600;
line-height: 120%; /* 28.8px */
line-height: 120%;
/* 28.8px */
}
.description {
@ -51,7 +52,8 @@
font-family: Inter;
font-style: normal;
font-weight: 400;
line-height: 20px; /* 142.857% */
line-height: 20px;
/* 142.857% */
letter-spacing: -0.07px;
}
@ -85,5 +87,4 @@
</div>
</body>
</html>
</html>

@ -42,7 +42,8 @@
font-family: Inter;
font-style: normal;
font-weight: 600;
line-height: 120%; /* 28.8px */
line-height: 120%;
/* 28.8px */
}
.description {
@ -51,7 +52,8 @@
font-family: Inter;
font-style: normal;
font-weight: 400;
line-height: 20px; /* 142.857% */
line-height: 20px;
/* 142.857% */
letter-spacing: -0.07px;
}
@ -85,5 +87,4 @@
</div>
</body>
</html>
</html>

@ -42,7 +42,8 @@
font-family: Inter;
font-style: normal;
font-weight: 600;
line-height: 120%; /* 28.8px */
line-height: 120%;
/* 28.8px */
}
.description {
@ -51,7 +52,8 @@
font-family: Inter;
font-style: normal;
font-weight: 400;
line-height: 20px; /* 142.857% */
line-height: 20px;
/* 142.857% */
letter-spacing: -0.07px;
}
@ -97,7 +99,8 @@
font-family: Inter;
font-style: normal;
font-weight: 400;
line-height: 20px; /* 142.857% */
line-height: 20px;
/* 142.857% */
letter-spacing: -0.07px;
}
</style>
@ -108,12 +111,14 @@
<div class="header"></div>
<p class="title">Workspace ownership has been transferred</p>
<div class="description">
<p class="content1">You have successfully transferred ownership of the workspace "{{WorkspaceName}}" to {{NewOwnerEmail}}.</p>
<p class="content2">You no longer have owner privileges for this workspace. Your access level has been changed to Admin.</p>
<p class="content3">If you did not initiate this transfer or have concerns about this change, please contact support@dify.ai immediately.</p>
<p class="content1">You have successfully transferred ownership of the workspace "{{WorkspaceName}}" to
{{NewOwnerEmail}}.</p>
<p class="content2">You no longer have owner privileges for this workspace. Your access level has been changed to
Admin.</p>
<p class="content3">If you did not initiate this transfer or have concerns about this change, please contact
support@dify.ai immediately.</p>
</div>
</div>
</body>
</html>
</html>

@ -42,7 +42,8 @@
font-family: Inter;
font-style: normal;
font-weight: 600;
line-height: 120%; /* 28.8px */
line-height: 120%;
/* 28.8px */
}
.description {
@ -51,7 +52,8 @@
font-family: Inter;
font-style: normal;
font-weight: 400;
line-height: 20px; /* 142.857% */
line-height: 20px;
/* 142.857% */
letter-spacing: -0.07px;
}
@ -97,7 +99,8 @@
font-family: Inter;
font-style: normal;
font-weight: 400;
line-height: 20px; /* 142.857% */
line-height: 20px;
/* 142.857% */
letter-spacing: -0.07px;
}
</style>
@ -115,5 +118,4 @@
</div>
</body>
</html>
</html>

@ -42,7 +42,8 @@
font-family: Inter;
font-style: normal;
font-weight: 600;
line-height: 120%; /* 28.8px */
line-height: 120%;
/* 28.8px */
}
.description {
@ -51,7 +52,8 @@
font-family: Inter;
font-style: normal;
font-weight: 400;
line-height: 20px; /* 142.857% */
line-height: 20px;
/* 142.857% */
letter-spacing: -0.07px;
}
@ -95,7 +97,8 @@
font-size: 14px;
font-style: normal;
font-weight: 600;
line-height: 20px; /* 142.857% */
line-height: 20px;
/* 142.857% */
}
.warningList {
@ -106,7 +109,8 @@
font-size: 14px;
font-style: normal;
font-weight: 400;
line-height: 20px; /* 142.857% */
line-height: 20px;
/* 142.857% */
letter-spacing: -0.07px;
}
@ -119,7 +123,8 @@
font-family: Inter;
font-style: normal;
font-weight: 400;
line-height: 20px; /* 142.857% */
line-height: 20px;
/* 142.857% */
letter-spacing: -0.07px;
}
</style>
@ -146,5 +151,4 @@
</div>
</body>
</html>
</html>

@ -42,7 +42,8 @@
font-family: Inter;
font-style: normal;
font-weight: 600;
line-height: 120%; /* 28.8px */
line-height: 120%;
/* 28.8px */
}
.description {
@ -51,7 +52,8 @@
font-family: Inter;
font-style: normal;
font-weight: 400;
line-height: 20px; /* 142.857% */
line-height: 20px;
/* 142.857% */
letter-spacing: -0.07px;
}
@ -95,7 +97,8 @@
font-size: 14px;
font-style: normal;
font-weight: 600;
line-height: 20px; /* 142.857% */
line-height: 20px;
/* 142.857% */
}
.warningList {
@ -106,7 +109,8 @@
font-size: 14px;
font-style: normal;
font-weight: 400;
line-height: 20px; /* 142.857% */
line-height: 20px;
/* 142.857% */
letter-spacing: -0.07px;
}
@ -119,7 +123,8 @@
font-family: Inter;
font-style: normal;
font-weight: 400;
line-height: 20px; /* 142.857% */
line-height: 20px;
/* 142.857% */
letter-spacing: -0.07px;
}
</style>
@ -146,5 +151,4 @@
</div>
</body>
</html>
</html>

@ -1,44 +1,24 @@
import dataclasses
from pydantic import BaseModel
from core.file import File, FileTransferMethod, FileType
from core.helper import encrypter
from core.variables.segments import (
ArrayAnySegment,
ArrayFileSegment,
ArrayNumberSegment,
ArrayObjectSegment,
ArrayStringSegment,
FileSegment,
FloatSegment,
IntegerSegment,
NoneSegment,
ObjectSegment,
Segment,
SegmentUnion,
StringSegment,
get_segment_discriminator,
)
from core.variables.segments import (ArrayAnySegment, ArrayFileSegment,
ArrayNumberSegment, ArrayObjectSegment,
ArrayStringSegment, FileSegment,
FloatSegment, IntegerSegment, NoneSegment,
ObjectSegment, Segment, SegmentUnion,
StringSegment, get_segment_discriminator)
from core.variables.types import SegmentType
from core.variables.variables import (
ArrayAnyVariable,
ArrayFileVariable,
ArrayNumberVariable,
ArrayObjectVariable,
ArrayStringVariable,
FileVariable,
FloatVariable,
IntegerVariable,
NoneVariable,
ObjectVariable,
SecretVariable,
StringVariable,
Variable,
VariableUnion,
)
from core.variables.variables import (ArrayAnyVariable, ArrayFileVariable,
ArrayNumberVariable, ArrayObjectVariable,
ArrayStringVariable, FileVariable,
FloatVariable, IntegerVariable,
NoneVariable, ObjectVariable,
SecretVariable, StringVariable, Variable,
VariableUnion)
from core.workflow.entities.variable_pool import VariablePool
from core.workflow.system_variable import SystemVariable
from pydantic import BaseModel
def test_segment_group_to_text():

@ -1,12 +1,7 @@
import React, { useState } from 'react'
import { Trans, useTranslation } from 'react-i18next'
import { useRouter } from 'next/navigation'
import { useContext } from 'use-context-selector'
import { ToastContext } from '@/app/components/base/toast'
import { RiCloseLine } from '@remixicon/react'
import Modal from '@/app/components/base/modal'
import Button from '@/app/components/base/button'
import Input from '@/app/components/base/input'
import Modal from '@/app/components/base/modal'
import { ToastContext } from '@/app/components/base/toast'
import {
checkEmailExisted,
logout,
@ -14,7 +9,12 @@ import {
sendVerifyCode,
verifyEmail,
} from '@/service/common'
import { RiCloseLine } from '@remixicon/react'
import { noop } from 'lodash-es'
import { useRouter } from 'next/navigation'
import { useState } from 'react'
import { Trans, useTranslation } from 'react-i18next'
import { useContext } from 'use-context-selector'
type Props = {
show: boolean

@ -1,30 +1,28 @@
'use client'
import { useState } from 'react'
import useSWR from 'swr'
import { useTranslation } from 'react-i18next'
import AppIcon from '@/app/components/base/app-icon'
import Button from '@/app/components/base/button'
import Input from '@/app/components/base/input'
import Modal from '@/app/components/base/modal'
import PremiumBadge from '@/app/components/base/premium-badge'
import { ToastContext } from '@/app/components/base/toast'
import type { IItem } from '@/app/components/header/account-setting/collapse'
import Collapse from '@/app/components/header/account-setting/collapse'
import { IS_CE_EDITION, validPassword } from '@/config'
import { useAppContext } from '@/context/app-context'
import { useGlobalPublicStore } from '@/context/global-public-context'
import { useProviderContext } from '@/context/provider-context'
import { fetchAppList } from '@/service/apps'
import { updateUserProfile } from '@/service/common'
import {
RiGraduationCapFill,
} from '@remixicon/react'
import { useState } from 'react'
import { useTranslation } from 'react-i18next'
import useSWR from 'swr'
import { useContext } from 'use-context-selector'
import DeleteAccount from '../delete-account'
import AvatarWithEdit from './AvatarWithEdit'
import Collapse from '@/app/components/header/account-setting/collapse'
import type { IItem } from '@/app/components/header/account-setting/collapse'
import Modal from '@/app/components/base/modal'
import Button from '@/app/components/base/button'
import { updateUserProfile } from '@/service/common'
import { useAppContext } from '@/context/app-context'
import { useProviderContext } from '@/context/provider-context'
import { ToastContext } from '@/app/components/base/toast'
import AppIcon from '@/app/components/base/app-icon'
import { IS_CE_EDITION } from '@/config'
import Input from '@/app/components/base/input'
import PremiumBadge from '@/app/components/base/premium-badge'
import { useGlobalPublicStore } from '@/context/global-public-context'
import EmailChangeModal from './email-change-modal'
import { validPassword } from '@/config'
import { fetchAppList } from '@/service/apps'
import type { App } from '@/types/app'
const titleClassName = `
system-sm-semibold text-text-secondary
@ -207,7 +205,7 @@ export default function AccountPage() {
{!!apps.length && (
<Collapse
title={`${t('common.account.showAppLength', { length: apps.length })}`}
items={apps.map((app: App) => ({ ...app, key: app.id, name: app.name }))}
items={apps.map(app => ({ key: app.id, name: app.name }))}
renderItem={renderAppItem}
wrapperClassName='mt-2'
/>

@ -117,7 +117,7 @@ const Question: FC<QuestionProps> = ({
</div>
<div
ref={contentRef}
className='w-full rounded-2xl bg-background-gradient-bg-fill-chat-bubble-bg-3 px-4 py-3 text-sm text-text-primary'
className='bg-background-gradient-bg-fill-chat-bubble-bg-3 w-full rounded-2xl px-4 py-3 text-sm text-text-primary'
style={theme?.chatBubbleColorStyle ? CssTransform(theme.chatBubbleColorStyle) : {}}
>
{

@ -1,19 +1,19 @@
import React, { useState } from 'react'
import { Trans, useTranslation } from 'react-i18next'
import { useContext } from 'use-context-selector'
import { RiCloseLine } from '@remixicon/react'
import { useAppContext } from '@/context/app-context'
import { ToastContext } from '@/app/components/base/toast'
import Modal from '@/app/components/base/modal'
import Button from '@/app/components/base/button'
import Input from '@/app/components/base/input'
import MemberSelector from './member-selector'
import Modal from '@/app/components/base/modal'
import { ToastContext } from '@/app/components/base/toast'
import { useAppContext } from '@/context/app-context'
import {
ownershipTransfer,
sendOwnerEmail,
verifyOwnerEmail,
} from '@/service/common'
import { RiCloseLine } from '@remixicon/react'
import { noop } from 'lodash-es'
import { useState } from 'react'
import { Trans, useTranslation } from 'react-i18next'
import { useContext } from 'use-context-selector'
import MemberSelector from './member-selector'
type Props = {
show: boolean

@ -2,6 +2,7 @@
import type { ChatConfig } from '@/app/components/base/chat/types'
import Loading from '@/app/components/base/loading'
import { checkOrSetAccessToken } from '@/app/components/share/utils'
import { AccessMode } from '@/models/access-control'
import type { AppData, AppMeta } from '@/models/share'
import { useGetWebAppAccessModeByCode } from '@/service/use-share'
@ -60,6 +61,8 @@ const WebAppStoreProvider: FC<PropsWithChildren> = ({ children }) => {
const pathname = usePathname()
const searchParams = useSearchParams()
const redirectUrlParam = searchParams.get('redirect_url')
const session = searchParams.get('session')
const sysUserId = searchParams.get('sys.user_id')
const [shareCode, setShareCode] = useState<string | null>(null)
useEffect(() => {
const shareCodeFromRedirect = getShareCodeFromRedirectUrl(redirectUrlParam)
@ -69,11 +72,22 @@ const WebAppStoreProvider: FC<PropsWithChildren> = ({ children }) => {
updateShareCode(newShareCode)
}, [pathname, redirectUrlParam, updateShareCode])
const { isFetching, data: accessModeResult } = useGetWebAppAccessModeByCode(shareCode)
const [isFetchingAccessToken, setIsFetchingAccessToken] = useState(true)
useEffect(() => {
if (accessModeResult?.accessMode)
if (accessModeResult?.accessMode) {
updateWebAppAccessMode(accessModeResult.accessMode)
}, [accessModeResult, updateWebAppAccessMode])
if (isFetching) {
if (accessModeResult?.accessMode === AccessMode.PUBLIC && session && sysUserId) {
setIsFetchingAccessToken(true)
checkOrSetAccessToken(shareCode).finally(() => {
setIsFetchingAccessToken(false)
})
}
else {
setIsFetchingAccessToken(false)
}
}
}, [accessModeResult, updateWebAppAccessMode, setIsFetchingAccessToken, shareCode, session, sysUserId])
if (isFetching || isFetchingAccessToken) {
return <div className='flex h-full w-full items-center justify-center'>
<Loading />
</div>

@ -1,5 +1,16 @@
import type { Fetcher } from 'swr'
import { del, get, patch, post, put } from './base'
import type {
DefaultModelResponse,
Model,
ModelItem,
ModelLoadBalancingConfig,
ModelParameterRule,
ModelProvider,
ModelTypeEnum,
} from '@/app/components/header/account-setting/model-provider-page/declarations'
import type {
UpdateOpenAIKeyResponse,
ValidateOpenAIKeyResponse,
} from '@/models/app'
import type {
AccountIntegrate,
ApiBasedExtension,
@ -22,21 +33,10 @@ import type {
SetupStatusResponse,
UserProfileOriginResponse,
} from '@/models/common'
import type {
UpdateOpenAIKeyResponse,
ValidateOpenAIKeyResponse,
} from '@/models/app'
import type {
DefaultModelResponse,
Model,
ModelItem,
ModelLoadBalancingConfig,
ModelParameterRule,
ModelProvider,
ModelTypeEnum,
} from '@/app/components/header/account-setting/model-provider-page/declarations'
import type { RETRIEVE_METHOD } from '@/types/app'
import type { SystemFeatures } from '@/types/feature'
import type { Fetcher } from 'swr'
import { del, get, patch, post, put } from './base'
type LoginSuccess = {
result: 'success'

Loading…
Cancel
Save