Skip to content
Merged
78 changes: 75 additions & 3 deletions api/controllers/console/app/workflow.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

from flask import abort, request
from flask_restx import Resource, fields
from pydantic import AliasChoices, BaseModel, Field, RootModel, ValidationError, field_validator
from pydantic import AliasChoices, BaseModel, ConfigDict, Field, RootModel, ValidationError, field_validator
from sqlalchemy.orm import Session, sessionmaker
from werkzeug.exceptions import BadRequest, Forbidden, InternalServerError, NotFound

Expand Down Expand Up @@ -159,8 +159,71 @@ class ConvertToWorkflowPayload(BaseModel):
icon_background: str | None = None


class WorkflowFeatureTogglePayload(BaseModel):
model_config = ConfigDict(extra="allow")

enabled: bool | None = None


class WorkflowSuggestedQuestionsAfterAnswerPayload(WorkflowFeatureTogglePayload):
model: dict[str, Any] | None = None
prompt: str | None = None


class WorkflowTextToSpeechPayload(WorkflowFeatureTogglePayload):
language: str | None = None
voice: str | None = None
autoPlay: str | None = None


class WorkflowSensitiveWordAvoidancePayload(WorkflowFeatureTogglePayload):
type: str | None = None
config: dict[str, Any] | None = None


class WorkflowFileUploadTransferPayload(WorkflowFeatureTogglePayload):
number_limits: int | None = None
transfer_methods: list[str] | None = None


class WorkflowFileUploadImagePayload(WorkflowFileUploadTransferPayload):
detail: str | None = None


class WorkflowFileUploadPreviewConfigPayload(BaseModel):
mode: str | None = None
file_type_list: list[str] | None = None


class WorkflowFileUploadPayload(WorkflowFeatureTogglePayload):
allowed_file_types: list[str] | None = None
allowed_file_extensions: list[str] | None = None
allowed_file_upload_methods: list[str] | None = None
number_limits: int | None = None
image: WorkflowFileUploadImagePayload | None = None
document: WorkflowFileUploadTransferPayload | None = None
audio: WorkflowFileUploadTransferPayload | None = None
video: WorkflowFileUploadTransferPayload | None = None
custom: WorkflowFileUploadTransferPayload | None = None
preview_config: WorkflowFileUploadPreviewConfigPayload | None = None
fileUploadConfig: dict[str, Any] | None = None


class WorkflowFeaturesConfigPayload(BaseModel):
model_config = ConfigDict(extra="allow")

opening_statement: str | None = None
suggested_questions: list[str] | None = None
suggested_questions_after_answer: WorkflowSuggestedQuestionsAfterAnswerPayload | None = None
text_to_speech: WorkflowTextToSpeechPayload | None = None
speech_to_text: WorkflowFeatureTogglePayload | None = None
retriever_resource: WorkflowFeatureTogglePayload | None = None
sensitive_word_avoidance: WorkflowSensitiveWordAvoidancePayload | None = None
file_upload: WorkflowFileUploadPayload | None = None


class WorkflowFeaturesPayload(BaseModel):
features: dict[str, Any] = Field(
features: WorkflowFeaturesConfigPayload = Field(
...,
description="Workflow feature configuration",
)
Expand Down Expand Up @@ -344,6 +407,15 @@ class DraftWorkflowTriggerRunAllPayload(BaseModel):
ConvertToWorkflowPayload,
WorkflowListQuery,
WorkflowUpdatePayload,
WorkflowFeatureTogglePayload,
WorkflowSuggestedQuestionsAfterAnswerPayload,
WorkflowTextToSpeechPayload,
WorkflowSensitiveWordAvoidancePayload,
WorkflowFileUploadTransferPayload,
WorkflowFileUploadImagePayload,
WorkflowFileUploadPreviewConfigPayload,
WorkflowFileUploadPayload,
WorkflowFeaturesConfigPayload,
WorkflowFeaturesPayload,
WorkflowOnlineUsersPayload,
DraftWorkflowTriggerRunPayload,
Expand Down Expand Up @@ -1275,7 +1347,7 @@ class WorkflowFeaturesApi(Resource):
def post(self, current_user: Account, app_model: App):

args = WorkflowFeaturesPayload.model_validate(console_ns.payload or {})
features = args.features
features = args.features.model_dump(mode="json", exclude_unset=True)

workflow_service = WorkflowService()
workflow_service.update_draft_workflow_features(app_model=app_model, features=features, account=current_user)
Expand Down
4 changes: 2 additions & 2 deletions api/controllers/console/app/workflow_comment.py
Original file line number Diff line number Diff line change
Expand Up @@ -189,14 +189,14 @@ def _normalize_timestamp(cls, value: datetime | int | None) -> int | None:

register_schema_models(
console_ns,
AccountWithRole,
WorkflowCommentMentionUsersPayload,
WorkflowCommentCreatePayload,
WorkflowCommentUpdatePayload,
WorkflowCommentReplyPayload,
)
register_response_schema_models(
console_ns,
AccountWithRole,
WorkflowCommentMentionUsersPayload,
WorkflowCommentAccount,
WorkflowCommentReply,
WorkflowCommentMention,
Expand Down
34 changes: 29 additions & 5 deletions api/controllers/console/app/workflow_draft_variable.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

from flask import Response, request
from flask_restx import Resource, fields, marshal, marshal_with
from pydantic import BaseModel, Field
from pydantic import BaseModel, ConfigDict, Field
from sqlalchemy.orm import sessionmaker

from controllers.common.errors import InvalidArgumentError, NotFoundError
Expand Down Expand Up @@ -79,15 +79,33 @@ class WorkflowDraftVariableUpdatePayload(BaseModel):
value: Any | None = Field(default=None, description="Variable value")


class WorkflowVariableItemPayload(BaseModel):
model_config = ConfigDict(extra="allow")

id: str | None = None
name: str | None = None
value_type: str | None = None
value: Any | None = None
description: str | None = None


class ConversationVariableItemPayload(WorkflowVariableItemPayload):
pass


class EnvironmentVariableItemPayload(WorkflowVariableItemPayload):
pass


class ConversationVariableUpdatePayload(BaseModel):
conversation_variables: list[dict[str, Any]] = Field(
conversation_variables: list[ConversationVariableItemPayload] = Field(
...,
description="Conversation variables for the draft workflow",
)


class EnvironmentVariableUpdatePayload(BaseModel):
environment_variables: list[dict[str, Any]] = Field(
environment_variables: list[EnvironmentVariableItemPayload] = Field(
...,
description="Environment variables for the draft workflow",
)
Expand All @@ -114,7 +132,9 @@ class EnvironmentVariableListResponse(ResponseModel):
console_ns,
WorkflowDraftVariableListQuery,
WorkflowDraftVariableUpdatePayload,
ConversationVariableItemPayload,
ConversationVariableUpdatePayload,
EnvironmentVariableItemPayload,
EnvironmentVariableUpdatePayload,
)
register_response_schema_models(console_ns, SimpleResultResponse, EnvironmentVariableListResponse)
Expand Down Expand Up @@ -615,7 +635,9 @@ def post(self, current_user: Account, app_model: App):

workflow_service = WorkflowService()

conversation_variables_list = payload.conversation_variables
conversation_variables_list = [
variable.model_dump(mode="json", exclude_unset=True) for variable in payload.conversation_variables
]
conversation_variables = [
variable_factory.build_conversation_variable_from_mapping(obj) for obj in conversation_variables_list
]
Expand Down Expand Up @@ -707,7 +729,9 @@ def post(self, current_user: Account, app_model: App):

workflow_service = WorkflowService()

environment_variables_list = payload.environment_variables
environment_variables_list = [
variable.model_dump(mode="json", exclude_unset=True) for variable in payload.environment_variables
]
environment_variables = [
variable_factory.build_environment_variable_from_mapping(obj) for obj in environment_variables_list
]
Expand Down
9 changes: 7 additions & 2 deletions api/controllers/console/billing/billing.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
)
from enums.cloud_plan import CloudPlan
from extensions.ext_database import db
from fields.base import ResponseModel
from libs.login import login_required
from models import Account
from services.billing_service import BillingService
Expand All @@ -35,8 +36,12 @@ class BillingResponse(RootModel[dict[str, Any]]):
root: dict[str, Any]


class BillingInvoiceResponse(ResponseModel):
url: str


register_schema_models(console_ns, SubscriptionQuery, PartnerTenantsPayload)
register_response_schema_models(console_ns, BillingResponse)
register_response_schema_models(console_ns, BillingResponse, BillingInvoiceResponse)


@console_ns.route("/billing/subscription")
Expand All @@ -57,7 +62,7 @@ def get(self, current_tenant_id: str, current_user: Account):

@console_ns.route("/billing/invoices")
class Invoices(Resource):
@console_ns.response(200, "Success", console_ns.models[BillingResponse.__name__])
@console_ns.response(200, "Success", console_ns.models[BillingInvoiceResponse.__name__])
@setup_required
@login_required
@account_initialization_required
Expand Down
12 changes: 9 additions & 3 deletions api/controllers/console/explore/recommended_app.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

from flask import request
from flask_restx import Resource
from pydantic import BaseModel, Field, RootModel, computed_field, field_validator
from pydantic import BaseModel, Field, computed_field, field_validator

from constants.languages import languages
from controllers.common.schema import query_params_from_model, register_response_schema_models, register_schema_models
Expand Down Expand Up @@ -70,8 +70,14 @@ class LearnDifyAppListResponse(ResponseModel):
recommended_apps: list[RecommendedAppResponse]


class RecommendedAppDetailResponse(RootModel[dict[str, Any]]):
root: dict[str, Any]
class RecommendedAppDetailResponse(ResponseModel):
id: str
name: str
icon: str | None = None
icon_background: str | None = None
mode: str
export_data: str
can_trial: bool | None = None


register_schema_models(
Expand Down
17 changes: 17 additions & 0 deletions api/controllers/console/files.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,22 @@

PREVIEW_WORDS_LIMIT = 3000

_FILE_UPLOAD_PARAMS = {
"file": {
"description": "File to upload",
"in": "formData",
"type": "file",
"required": True,
},
"source": {
"description": "Optional upload source",
"in": "formData",
"type": "string",
"enum": ["datasets"],
"required": False,
},
}


@console_ns.route("/files/upload")
class FileApi(Resource):
Expand All @@ -64,6 +80,7 @@ def get(self):
@login_required
@account_initialization_required
@cloud_edition_billing_resource_check("documents")
@console_ns.doc(consumes=["multipart/form-data"], params=_FILE_UPLOAD_PARAMS)
@console_ns.response(201, "File uploaded successfully", console_ns.models[FileResponse.__name__])
@with_current_user
def post(self, current_user: Account):
Expand Down
4 changes: 2 additions & 2 deletions api/controllers/console/workspace/members.py
Original file line number Diff line number Diff line change
Expand Up @@ -84,8 +84,6 @@ class MemberActionTenantResponse(ResponseModel):
register_enum_models(console_ns, TenantAccountRole)
register_schema_models(
console_ns,
AccountWithRole,
AccountWithRoleList,
MemberInvitePayload,
MemberRoleUpdatePayload,
OwnerTransferEmailPayload,
Expand All @@ -94,6 +92,8 @@ class MemberActionTenantResponse(ResponseModel):
)
register_response_schema_models(
console_ns,
AccountWithRole,
AccountWithRoleList,
SimpleResultDataResponse,
SimpleResultResponse,
VerificationTokenResponse,
Expand Down
21 changes: 19 additions & 2 deletions api/controllers/console/workspace/plugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -302,11 +302,28 @@ class PluginListResponse(ResponseModel):


class PluginVersionsResponse(ResponseModel):
versions: Any
versions: Mapping[str, PluginService.LatestPluginCache | None]


class PluginInstallationItemResponse(ResponseModel):
id: str
created_at: datetime
updated_at: datetime
tenant_id: str
endpoints_setups: int
endpoints_active: int
runtime_type: str
source: PluginInstallationSource
meta: Mapping[str, Any]
plugin_id: str
plugin_unique_identifier: str
version: str
checksum: str
declaration: Mapping[str, Any]


class PluginInstallationsResponse(ResponseModel):
plugins: Any
plugins: list[PluginInstallationItemResponse]


class PluginManifestResponse(ResponseModel):
Expand Down
Loading
Loading