| from importlib import import_module | |||||
| from flask import Blueprint | from flask import Blueprint | ||||
| from flask_restx import Namespace | from flask_restx import Namespace | ||||
| from libs.external_api import ExternalApi | from libs.external_api import ExternalApi | ||||
| from .app.app_import import AppImportApi, AppImportCheckDependenciesApi, AppImportConfirmApi | |||||
| from .explore.audio import ChatAudioApi, ChatTextApi | |||||
| from .explore.completion import ChatApi, ChatStopApi, CompletionApi, CompletionStopApi | |||||
| from .explore.conversation import ( | |||||
| ConversationApi, | |||||
| ConversationListApi, | |||||
| ConversationPinApi, | |||||
| ConversationRenameApi, | |||||
| ConversationUnPinApi, | |||||
| ) | |||||
| from .explore.message import ( | |||||
| MessageFeedbackApi, | |||||
| MessageListApi, | |||||
| MessageMoreLikeThisApi, | |||||
| MessageSuggestedQuestionApi, | |||||
| ) | |||||
| from .explore.workflow import ( | |||||
| InstalledAppWorkflowRunApi, | |||||
| InstalledAppWorkflowTaskStopApi, | |||||
| ) | |||||
| from .files import FileApi, FilePreviewApi, FileSupportTypeApi | |||||
| from .remote_files import RemoteFileInfoApi, RemoteFileUploadApi | |||||
| bp = Blueprint("console", __name__, url_prefix="/console/api") | bp = Blueprint("console", __name__, url_prefix="/console/api") | ||||
| api = ExternalApi( | api = ExternalApi( | ||||
| description="Console management APIs for app configuration, monitoring, and administration", | description="Console management APIs for app configuration, monitoring, and administration", | ||||
| ) | ) | ||||
| # Create namespace | |||||
| console_ns = Namespace("console", description="Console management API operations", path="/") | console_ns = Namespace("console", description="Console management API operations", path="/") | ||||
| # File | |||||
| api.add_resource(FileApi, "/files/upload") | |||||
| api.add_resource(FilePreviewApi, "/files/<uuid:file_id>/preview") | |||||
| api.add_resource(FileSupportTypeApi, "/files/support-type") | |||||
| # Remote files | |||||
| api.add_resource(RemoteFileInfoApi, "/remote-files/<path:url>") | |||||
| api.add_resource(RemoteFileUploadApi, "/remote-files/upload") | |||||
| RESOURCE_MODULES = ( | |||||
| "controllers.console.app.app_import", | |||||
| "controllers.console.explore.audio", | |||||
| "controllers.console.explore.completion", | |||||
| "controllers.console.explore.conversation", | |||||
| "controllers.console.explore.message", | |||||
| "controllers.console.explore.workflow", | |||||
| "controllers.console.files", | |||||
| "controllers.console.remote_files", | |||||
| ) | |||||
| # Import App | |||||
| api.add_resource(AppImportApi, "/apps/imports") | |||||
| api.add_resource(AppImportConfirmApi, "/apps/imports/<string:import_id>/confirm") | |||||
| api.add_resource(AppImportCheckDependenciesApi, "/apps/imports/<string:app_id>/check-dependencies") | |||||
| for module_name in RESOURCE_MODULES: | |||||
| import_module(module_name) | |||||
| # Ensure resource modules are imported so route decorators are evaluated. | |||||
| # Import other controllers | # Import other controllers | ||||
| from . import ( | from . import ( | ||||
| admin, | admin, | ||||
| workspace, | workspace, | ||||
| ) | ) | ||||
| # Explore Audio | |||||
| api.add_resource(ChatAudioApi, "/installed-apps/<uuid:installed_app_id>/audio-to-text", endpoint="installed_app_audio") | |||||
| api.add_resource(ChatTextApi, "/installed-apps/<uuid:installed_app_id>/text-to-audio", endpoint="installed_app_text") | |||||
| # Explore Completion | |||||
| api.add_resource( | |||||
| CompletionApi, "/installed-apps/<uuid:installed_app_id>/completion-messages", endpoint="installed_app_completion" | |||||
| ) | |||||
| api.add_resource( | |||||
| CompletionStopApi, | |||||
| "/installed-apps/<uuid:installed_app_id>/completion-messages/<string:task_id>/stop", | |||||
| endpoint="installed_app_stop_completion", | |||||
| ) | |||||
| api.add_resource( | |||||
| ChatApi, "/installed-apps/<uuid:installed_app_id>/chat-messages", endpoint="installed_app_chat_completion" | |||||
| ) | |||||
| api.add_resource( | |||||
| ChatStopApi, | |||||
| "/installed-apps/<uuid:installed_app_id>/chat-messages/<string:task_id>/stop", | |||||
| endpoint="installed_app_stop_chat_completion", | |||||
| ) | |||||
| # Explore Conversation | |||||
| api.add_resource( | |||||
| ConversationRenameApi, | |||||
| "/installed-apps/<uuid:installed_app_id>/conversations/<uuid:c_id>/name", | |||||
| endpoint="installed_app_conversation_rename", | |||||
| ) | |||||
| api.add_resource( | |||||
| ConversationListApi, "/installed-apps/<uuid:installed_app_id>/conversations", endpoint="installed_app_conversations" | |||||
| ) | |||||
| api.add_resource( | |||||
| ConversationApi, | |||||
| "/installed-apps/<uuid:installed_app_id>/conversations/<uuid:c_id>", | |||||
| endpoint="installed_app_conversation", | |||||
| ) | |||||
| api.add_resource( | |||||
| ConversationPinApi, | |||||
| "/installed-apps/<uuid:installed_app_id>/conversations/<uuid:c_id>/pin", | |||||
| endpoint="installed_app_conversation_pin", | |||||
| ) | |||||
| api.add_resource( | |||||
| ConversationUnPinApi, | |||||
| "/installed-apps/<uuid:installed_app_id>/conversations/<uuid:c_id>/unpin", | |||||
| endpoint="installed_app_conversation_unpin", | |||||
| ) | |||||
| # Explore Message | |||||
| api.add_resource(MessageListApi, "/installed-apps/<uuid:installed_app_id>/messages", endpoint="installed_app_messages") | |||||
| api.add_resource( | |||||
| MessageFeedbackApi, | |||||
| "/installed-apps/<uuid:installed_app_id>/messages/<uuid:message_id>/feedbacks", | |||||
| endpoint="installed_app_message_feedback", | |||||
| ) | |||||
| api.add_resource( | |||||
| MessageMoreLikeThisApi, | |||||
| "/installed-apps/<uuid:installed_app_id>/messages/<uuid:message_id>/more-like-this", | |||||
| endpoint="installed_app_more_like_this", | |||||
| ) | |||||
| api.add_resource( | |||||
| MessageSuggestedQuestionApi, | |||||
| "/installed-apps/<uuid:installed_app_id>/messages/<uuid:message_id>/suggested-questions", | |||||
| endpoint="installed_app_suggested_question", | |||||
| ) | |||||
| # Explore Workflow | |||||
| api.add_resource(InstalledAppWorkflowRunApi, "/installed-apps/<uuid:installed_app_id>/workflows/run") | |||||
| api.add_resource( | |||||
| InstalledAppWorkflowTaskStopApi, "/installed-apps/<uuid:installed_app_id>/workflows/tasks/<string:task_id>/stop" | |||||
| ) | |||||
| api.add_namespace(console_ns) | api.add_namespace(console_ns) | ||||
| __all__ = [ | __all__ = [ |
| from services.enterprise.enterprise_service import EnterpriseService | from services.enterprise.enterprise_service import EnterpriseService | ||||
| from services.feature_service import FeatureService | from services.feature_service import FeatureService | ||||
| from .. import console_ns | |||||
| @console_ns.route("/apps/imports") | |||||
| class AppImportApi(Resource): | class AppImportApi(Resource): | ||||
| @setup_required | @setup_required | ||||
| @login_required | @login_required | ||||
| return result.model_dump(mode="json"), 200 | return result.model_dump(mode="json"), 200 | ||||
| @console_ns.route("/apps/imports/<string:import_id>/confirm") | |||||
| class AppImportConfirmApi(Resource): | class AppImportConfirmApi(Resource): | ||||
| @setup_required | @setup_required | ||||
| @login_required | @login_required | ||||
| return result.model_dump(mode="json"), 200 | return result.model_dump(mode="json"), 200 | ||||
| @console_ns.route("/apps/imports/<string:app_id>/check-dependencies") | |||||
| class AppImportCheckDependenciesApi(Resource): | class AppImportCheckDependenciesApi(Resource): | ||||
| @setup_required | @setup_required | ||||
| @login_required | @login_required |
| from flask_restx import Resource, reqparse | from flask_restx import Resource, reqparse | ||||
| from werkzeug.exceptions import Forbidden | from werkzeug.exceptions import Forbidden | ||||
| from controllers.console import api | |||||
| from controllers.console import console_ns | |||||
| from controllers.console.auth.error import ApiKeyAuthFailedError | from controllers.console.auth.error import ApiKeyAuthFailedError | ||||
| from libs.login import login_required | from libs.login import login_required | ||||
| from services.auth.api_key_auth_service import ApiKeyAuthService | from services.auth.api_key_auth_service import ApiKeyAuthService | ||||
| from ..wraps import account_initialization_required, setup_required | from ..wraps import account_initialization_required, setup_required | ||||
| @console_ns.route("/api-key-auth/data-source") | |||||
| class ApiKeyAuthDataSource(Resource): | class ApiKeyAuthDataSource(Resource): | ||||
| @setup_required | @setup_required | ||||
| @login_required | @login_required | ||||
| return {"sources": []} | return {"sources": []} | ||||
| @console_ns.route("/api-key-auth/data-source/binding") | |||||
| class ApiKeyAuthDataSourceBinding(Resource): | class ApiKeyAuthDataSourceBinding(Resource): | ||||
| @setup_required | @setup_required | ||||
| @login_required | @login_required | ||||
| return {"result": "success"}, 200 | return {"result": "success"}, 200 | ||||
| @console_ns.route("/api-key-auth/data-source/<uuid:binding_id>") | |||||
| class ApiKeyAuthDataSourceBindingDelete(Resource): | class ApiKeyAuthDataSourceBindingDelete(Resource): | ||||
| @setup_required | @setup_required | ||||
| @login_required | @login_required | ||||
| ApiKeyAuthService.delete_provider_auth(current_user.current_tenant_id, binding_id) | ApiKeyAuthService.delete_provider_auth(current_user.current_tenant_id, binding_id) | ||||
| return {"result": "success"}, 204 | return {"result": "success"}, 204 | ||||
| api.add_resource(ApiKeyAuthDataSource, "/api-key-auth/data-source") | |||||
| api.add_resource(ApiKeyAuthDataSourceBinding, "/api-key-auth/data-source/binding") | |||||
| api.add_resource(ApiKeyAuthDataSourceBindingDelete, "/api-key-auth/data-source/<uuid:binding_id>") |
| from configs import dify_config | from configs import dify_config | ||||
| from constants.languages import languages | from constants.languages import languages | ||||
| from controllers.console import api | |||||
| from controllers.console import console_ns | |||||
| from controllers.console.auth.error import ( | from controllers.console.auth.error import ( | ||||
| EmailAlreadyInUseError, | EmailAlreadyInUseError, | ||||
| EmailCodeError, | EmailCodeError, | ||||
| from services.errors.account import AccountNotFoundError, AccountRegisterError | from services.errors.account import AccountNotFoundError, AccountRegisterError | ||||
| @console_ns.route("/email-register/send-email") | |||||
| class EmailRegisterSendEmailApi(Resource): | class EmailRegisterSendEmailApi(Resource): | ||||
| @setup_required | @setup_required | ||||
| @email_password_login_enabled | @email_password_login_enabled | ||||
| return {"result": "success", "data": token} | return {"result": "success", "data": token} | ||||
| @console_ns.route("/email-register/validity") | |||||
| class EmailRegisterCheckApi(Resource): | class EmailRegisterCheckApi(Resource): | ||||
| @setup_required | @setup_required | ||||
| @email_password_login_enabled | @email_password_login_enabled | ||||
| return {"is_valid": True, "email": token_data.get("email"), "token": new_token} | return {"is_valid": True, "email": token_data.get("email"), "token": new_token} | ||||
| @console_ns.route("/email-register") | |||||
| class EmailRegisterResetApi(Resource): | class EmailRegisterResetApi(Resource): | ||||
| @setup_required | @setup_required | ||||
| @email_password_login_enabled | @email_password_login_enabled | ||||
| raise AccountInFreezeError() | raise AccountInFreezeError() | ||||
| return account | return account | ||||
| api.add_resource(EmailRegisterSendEmailApi, "/email-register/send-email") | |||||
| api.add_resource(EmailRegisterCheckApi, "/email-register/validity") | |||||
| api.add_resource(EmailRegisterResetApi, "/email-register") |
| TenantService.create_tenant_member(tenant, account, role="owner") | TenantService.create_tenant_member(tenant, account, role="owner") | ||||
| account.current_tenant = tenant | account.current_tenant = tenant | ||||
| tenant_was_created.send(tenant) | tenant_was_created.send(tenant) | ||||
| api.add_resource(ForgotPasswordSendEmailApi, "/forgot-password") | |||||
| api.add_resource(ForgotPasswordCheckApi, "/forgot-password/validity") | |||||
| api.add_resource(ForgotPasswordResetApi, "/forgot-password/resets") |
| import services | import services | ||||
| from configs import dify_config | from configs import dify_config | ||||
| from constants.languages import languages | from constants.languages import languages | ||||
| from controllers.console import api | |||||
| from controllers.console import console_ns | |||||
| from controllers.console.auth.error import ( | from controllers.console.auth.error import ( | ||||
| AuthenticationFailedError, | AuthenticationFailedError, | ||||
| EmailCodeError, | EmailCodeError, | ||||
| from services.feature_service import FeatureService | from services.feature_service import FeatureService | ||||
| @console_ns.route("/login") | |||||
| class LoginApi(Resource): | class LoginApi(Resource): | ||||
| """Resource for user login.""" | """Resource for user login.""" | ||||
| return {"result": "success", "data": token_pair.model_dump()} | return {"result": "success", "data": token_pair.model_dump()} | ||||
| @console_ns.route("/logout") | |||||
| class LogoutApi(Resource): | class LogoutApi(Resource): | ||||
| @setup_required | @setup_required | ||||
| def get(self): | def get(self): | ||||
| return {"result": "success"} | return {"result": "success"} | ||||
| @console_ns.route("/reset-password") | |||||
| class ResetPasswordSendEmailApi(Resource): | class ResetPasswordSendEmailApi(Resource): | ||||
| @setup_required | @setup_required | ||||
| @email_password_login_enabled | @email_password_login_enabled | ||||
| return {"result": "success", "data": token} | return {"result": "success", "data": token} | ||||
| @console_ns.route("/email-code-login") | |||||
| class EmailCodeLoginSendEmailApi(Resource): | class EmailCodeLoginSendEmailApi(Resource): | ||||
| @setup_required | @setup_required | ||||
| def post(self): | def post(self): | ||||
| return {"result": "success", "data": token} | return {"result": "success", "data": token} | ||||
| @console_ns.route("/email-code-login/validity") | |||||
| class EmailCodeLoginApi(Resource): | class EmailCodeLoginApi(Resource): | ||||
| @setup_required | @setup_required | ||||
| def post(self): | def post(self): | ||||
| return {"result": "success", "data": token_pair.model_dump()} | return {"result": "success", "data": token_pair.model_dump()} | ||||
| @console_ns.route("/refresh-token") | |||||
| class RefreshTokenApi(Resource): | class RefreshTokenApi(Resource): | ||||
| def post(self): | def post(self): | ||||
| parser = reqparse.RequestParser() | parser = reqparse.RequestParser() | ||||
| return {"result": "success", "data": new_token_pair.model_dump()} | return {"result": "success", "data": new_token_pair.model_dump()} | ||||
| except Exception as e: | except Exception as e: | ||||
| return {"result": "fail", "data": str(e)}, 401 | return {"result": "fail", "data": str(e)}, 401 | ||||
| api.add_resource(LoginApi, "/login") | |||||
| api.add_resource(LogoutApi, "/logout") | |||||
| api.add_resource(EmailCodeLoginSendEmailApi, "/email-code-login") | |||||
| api.add_resource(EmailCodeLoginApi, "/email-code-login/validity") | |||||
| api.add_resource(ResetPasswordSendEmailApi, "/reset-password") | |||||
| api.add_resource(RefreshTokenApi, "/refresh-token") |
| from models.model import OAuthProviderApp | from models.model import OAuthProviderApp | ||||
| from services.oauth_server import OAUTH_ACCESS_TOKEN_EXPIRES_IN, OAuthGrantType, OAuthServerService | from services.oauth_server import OAUTH_ACCESS_TOKEN_EXPIRES_IN, OAuthGrantType, OAuthServerService | ||||
| from .. import api | |||||
| from .. import console_ns | |||||
| P = ParamSpec("P") | P = ParamSpec("P") | ||||
| R = TypeVar("R") | R = TypeVar("R") | ||||
| return decorated | return decorated | ||||
| @console_ns.route("/oauth/provider") | |||||
| class OAuthServerAppApi(Resource): | class OAuthServerAppApi(Resource): | ||||
| @setup_required | @setup_required | ||||
| @oauth_server_client_id_required | @oauth_server_client_id_required | ||||
| ) | ) | ||||
| @console_ns.route("/oauth/provider/authorize") | |||||
| class OAuthServerUserAuthorizeApi(Resource): | class OAuthServerUserAuthorizeApi(Resource): | ||||
| @setup_required | @setup_required | ||||
| @login_required | @login_required | ||||
| ) | ) | ||||
| @console_ns.route("/oauth/provider/token") | |||||
| class OAuthServerUserTokenApi(Resource): | class OAuthServerUserTokenApi(Resource): | ||||
| @setup_required | @setup_required | ||||
| @oauth_server_client_id_required | @oauth_server_client_id_required | ||||
| ) | ) | ||||
| @console_ns.route("/oauth/provider/account") | |||||
| class OAuthServerUserAccountApi(Resource): | class OAuthServerUserAccountApi(Resource): | ||||
| @setup_required | @setup_required | ||||
| @oauth_server_client_id_required | @oauth_server_client_id_required | ||||
| "timezone": account.timezone, | "timezone": account.timezone, | ||||
| } | } | ||||
| ) | ) | ||||
| api.add_resource(OAuthServerAppApi, "/oauth/provider") | |||||
| api.add_resource(OAuthServerUserAuthorizeApi, "/oauth/provider/authorize") | |||||
| api.add_resource(OAuthServerUserTokenApi, "/oauth/provider/token") | |||||
| api.add_resource(OAuthServerUserAccountApi, "/oauth/provider/account") |
| from flask_restx import Resource, reqparse | from flask_restx import Resource, reqparse | ||||
| from controllers.console import api | |||||
| from controllers.console import console_ns | |||||
| from controllers.console.wraps import account_initialization_required, only_edition_cloud, setup_required | from controllers.console.wraps import account_initialization_required, only_edition_cloud, setup_required | ||||
| from libs.login import current_user, login_required | from libs.login import current_user, login_required | ||||
| from models.model import Account | from models.model import Account | ||||
| from services.billing_service import BillingService | from services.billing_service import BillingService | ||||
| @console_ns.route("/billing/subscription") | |||||
| class Subscription(Resource): | class Subscription(Resource): | ||||
| @setup_required | @setup_required | ||||
| @login_required | @login_required | ||||
| ) | ) | ||||
| @console_ns.route("/billing/invoices") | |||||
| class Invoices(Resource): | class Invoices(Resource): | ||||
| @setup_required | @setup_required | ||||
| @login_required | @login_required | ||||
| BillingService.is_tenant_owner_or_admin(current_user) | BillingService.is_tenant_owner_or_admin(current_user) | ||||
| assert current_user.current_tenant_id is not None | assert current_user.current_tenant_id is not None | ||||
| return BillingService.get_invoices(current_user.email, current_user.current_tenant_id) | return BillingService.get_invoices(current_user.email, current_user.current_tenant_id) | ||||
| api.add_resource(Subscription, "/billing/subscription") | |||||
| api.add_resource(Invoices, "/billing/invoices") |
| from libs.login import login_required | from libs.login import login_required | ||||
| from services.billing_service import BillingService | from services.billing_service import BillingService | ||||
| from .. import api | |||||
| from .. import console_ns | |||||
| from ..wraps import account_initialization_required, only_edition_cloud, setup_required | from ..wraps import account_initialization_required, only_edition_cloud, setup_required | ||||
| @console_ns.route("/compliance/download") | |||||
| class ComplianceApi(Resource): | class ComplianceApi(Resource): | ||||
| @setup_required | @setup_required | ||||
| @login_required | @login_required | ||||
| ip=ip_address, | ip=ip_address, | ||||
| device_info=device_info, | device_info=device_info, | ||||
| ) | ) | ||||
| api.add_resource(ComplianceApi, "/compliance/download") |
| from sqlalchemy.orm import Session | from sqlalchemy.orm import Session | ||||
| from werkzeug.exceptions import NotFound | from werkzeug.exceptions import NotFound | ||||
| from controllers.console import api | |||||
| from controllers.console import console_ns | |||||
| from controllers.console.wraps import account_initialization_required, setup_required | from controllers.console.wraps import account_initialization_required, setup_required | ||||
| from core.datasource.entities.datasource_entities import DatasourceProviderType, OnlineDocumentPagesMessage | from core.datasource.entities.datasource_entities import DatasourceProviderType, OnlineDocumentPagesMessage | ||||
| from core.datasource.online_document.online_document_plugin import OnlineDocumentDatasourcePlugin | from core.datasource.online_document.online_document_plugin import OnlineDocumentDatasourcePlugin | ||||
| from tasks.document_indexing_sync_task import document_indexing_sync_task | from tasks.document_indexing_sync_task import document_indexing_sync_task | ||||
| @console_ns.route( | |||||
| "/data-source/integrates", | |||||
| "/data-source/integrates/<uuid:binding_id>/<string:action>", | |||||
| ) | |||||
| class DataSourceApi(Resource): | class DataSourceApi(Resource): | ||||
| @setup_required | @setup_required | ||||
| @login_required | @login_required | ||||
| return {"result": "success"}, 200 | return {"result": "success"}, 200 | ||||
| @console_ns.route("/notion/pre-import/pages") | |||||
| class DataSourceNotionListApi(Resource): | class DataSourceNotionListApi(Resource): | ||||
| @setup_required | @setup_required | ||||
| @login_required | @login_required | ||||
| return {"notion_info": {**workspace_info, "pages": pages}}, 200 | return {"notion_info": {**workspace_info, "pages": pages}}, 200 | ||||
| @console_ns.route( | |||||
| "/notion/workspaces/<uuid:workspace_id>/pages/<uuid:page_id>/<string:page_type>/preview", | |||||
| "/datasets/notion-indexing-estimate", | |||||
| ) | |||||
| class DataSourceNotionApi(Resource): | class DataSourceNotionApi(Resource): | ||||
| @setup_required | @setup_required | ||||
| @login_required | @login_required | ||||
| return response.model_dump(), 200 | return response.model_dump(), 200 | ||||
| @console_ns.route("/datasets/<uuid:dataset_id>/notion/sync") | |||||
| class DataSourceNotionDatasetSyncApi(Resource): | class DataSourceNotionDatasetSyncApi(Resource): | ||||
| @setup_required | @setup_required | ||||
| @login_required | @login_required | ||||
| return {"result": "success"}, 200 | return {"result": "success"}, 200 | ||||
| @console_ns.route("/datasets/<uuid:dataset_id>/documents/<uuid:document_id>/notion/sync") | |||||
| class DataSourceNotionDocumentSyncApi(Resource): | class DataSourceNotionDocumentSyncApi(Resource): | ||||
| @setup_required | @setup_required | ||||
| @login_required | @login_required | ||||
| raise NotFound("Document not found.") | raise NotFound("Document not found.") | ||||
| document_indexing_sync_task.delay(dataset_id_str, document_id_str) | document_indexing_sync_task.delay(dataset_id_str, document_id_str) | ||||
| return {"result": "success"}, 200 | return {"result": "success"}, 200 | ||||
| api.add_resource(DataSourceApi, "/data-source/integrates", "/data-source/integrates/<uuid:binding_id>/<string:action>") | |||||
| api.add_resource(DataSourceNotionListApi, "/notion/pre-import/pages") | |||||
| api.add_resource( | |||||
| DataSourceNotionApi, | |||||
| "/notion/workspaces/<uuid:workspace_id>/pages/<uuid:page_id>/<string:page_type>/preview", | |||||
| "/datasets/notion-indexing-estimate", | |||||
| ) | |||||
| api.add_resource(DataSourceNotionDatasetSyncApi, "/datasets/<uuid:dataset_id>/notion/sync") | |||||
| api.add_resource( | |||||
| DataSourceNotionDocumentSyncApi, "/datasets/<uuid:dataset_id>/documents/<uuid:document_id>/notion/sync" | |||||
| ) |
| return {"result": "success"}, 200 | return {"result": "success"}, 200 | ||||
| @console_ns.route("/datasets/<uuid:dataset_id>/documents/<uuid:document_id>/pipeline-execution-log") | |||||
| class DocumentPipelineExecutionLogApi(DocumentResource): | class DocumentPipelineExecutionLogApi(DocumentResource): | ||||
| @setup_required | @setup_required | ||||
| @login_required | @login_required | ||||
| "input_data": log.input_data, | "input_data": log.input_data, | ||||
| "datasource_node_id": log.datasource_node_id, | "datasource_node_id": log.datasource_node_id, | ||||
| }, 200 | }, 200 | ||||
| api.add_resource(GetProcessRuleApi, "/datasets/process-rule") | |||||
| api.add_resource(DatasetDocumentListApi, "/datasets/<uuid:dataset_id>/documents") | |||||
| api.add_resource(DatasetInitApi, "/datasets/init") | |||||
| api.add_resource( | |||||
| DocumentIndexingEstimateApi, "/datasets/<uuid:dataset_id>/documents/<uuid:document_id>/indexing-estimate" | |||||
| ) | |||||
| api.add_resource(DocumentBatchIndexingEstimateApi, "/datasets/<uuid:dataset_id>/batch/<string:batch>/indexing-estimate") | |||||
| api.add_resource(DocumentBatchIndexingStatusApi, "/datasets/<uuid:dataset_id>/batch/<string:batch>/indexing-status") | |||||
| api.add_resource(DocumentIndexingStatusApi, "/datasets/<uuid:dataset_id>/documents/<uuid:document_id>/indexing-status") | |||||
| api.add_resource(DocumentApi, "/datasets/<uuid:dataset_id>/documents/<uuid:document_id>") | |||||
| api.add_resource( | |||||
| DocumentProcessingApi, "/datasets/<uuid:dataset_id>/documents/<uuid:document_id>/processing/<string:action>" | |||||
| ) | |||||
| api.add_resource(DocumentMetadataApi, "/datasets/<uuid:dataset_id>/documents/<uuid:document_id>/metadata") | |||||
| api.add_resource(DocumentStatusApi, "/datasets/<uuid:dataset_id>/documents/status/<string:action>/batch") | |||||
| api.add_resource(DocumentPauseApi, "/datasets/<uuid:dataset_id>/documents/<uuid:document_id>/processing/pause") | |||||
| api.add_resource(DocumentRecoverApi, "/datasets/<uuid:dataset_id>/documents/<uuid:document_id>/processing/resume") | |||||
| api.add_resource(DocumentRetryApi, "/datasets/<uuid:dataset_id>/retry") | |||||
| api.add_resource(DocumentRenameApi, "/datasets/<uuid:dataset_id>/documents/<uuid:document_id>/rename") | |||||
| api.add_resource(WebsiteDocumentSyncApi, "/datasets/<uuid:dataset_id>/documents/<uuid:document_id>/website-sync") | |||||
| api.add_resource( | |||||
| DocumentPipelineExecutionLogApi, "/datasets/<uuid:dataset_id>/documents/<uuid:document_id>/pipeline-execution-log" | |||||
| ) |
| from werkzeug.exceptions import Forbidden, NotFound | from werkzeug.exceptions import Forbidden, NotFound | ||||
| import services | import services | ||||
| from controllers.console import api | |||||
| from controllers.console import console_ns | |||||
| from controllers.console.app.error import ProviderNotInitializeError | from controllers.console.app.error import ProviderNotInitializeError | ||||
| from controllers.console.datasets.error import ( | from controllers.console.datasets.error import ( | ||||
| ChildChunkDeleteIndexError, | ChildChunkDeleteIndexError, | ||||
| from tasks.batch_create_segment_to_index_task import batch_create_segment_to_index_task | from tasks.batch_create_segment_to_index_task import batch_create_segment_to_index_task | ||||
| @console_ns.route("/datasets/<uuid:dataset_id>/documents/<uuid:document_id>/segments") | |||||
| class DatasetDocumentSegmentListApi(Resource): | class DatasetDocumentSegmentListApi(Resource): | ||||
| @setup_required | @setup_required | ||||
| @login_required | @login_required | ||||
| return {"result": "success"}, 204 | return {"result": "success"}, 204 | ||||
| @console_ns.route("/datasets/<uuid:dataset_id>/documents/<uuid:document_id>/segment/<string:action>") | |||||
| class DatasetDocumentSegmentApi(Resource): | class DatasetDocumentSegmentApi(Resource): | ||||
| @setup_required | @setup_required | ||||
| @login_required | @login_required | ||||
| return {"result": "success"}, 200 | return {"result": "success"}, 200 | ||||
| @console_ns.route("/datasets/<uuid:dataset_id>/documents/<uuid:document_id>/segment") | |||||
| class DatasetDocumentSegmentAddApi(Resource): | class DatasetDocumentSegmentAddApi(Resource): | ||||
| @setup_required | @setup_required | ||||
| @login_required | @login_required | ||||
| return {"data": marshal(segment, segment_fields), "doc_form": document.doc_form}, 200 | return {"data": marshal(segment, segment_fields), "doc_form": document.doc_form}, 200 | ||||
| @console_ns.route("/datasets/<uuid:dataset_id>/documents/<uuid:document_id>/segments/<uuid:segment_id>") | |||||
| class DatasetDocumentSegmentUpdateApi(Resource): | class DatasetDocumentSegmentUpdateApi(Resource): | ||||
| @setup_required | @setup_required | ||||
| @login_required | @login_required | ||||
| return {"result": "success"}, 204 | return {"result": "success"}, 204 | ||||
| @console_ns.route( | |||||
| "/datasets/<uuid:dataset_id>/documents/<uuid:document_id>/segments/batch_import", | |||||
| "/datasets/batch_import_status/<uuid:job_id>", | |||||
| ) | |||||
| class DatasetDocumentSegmentBatchImportApi(Resource): | class DatasetDocumentSegmentBatchImportApi(Resource): | ||||
| @setup_required | @setup_required | ||||
| @login_required | @login_required | ||||
| @setup_required | @setup_required | ||||
| @login_required | @login_required | ||||
| @account_initialization_required | @account_initialization_required | ||||
| def get(self, job_id): | |||||
| def get(self, job_id=None, dataset_id=None, document_id=None): | |||||
| if job_id is None: | |||||
| raise NotFound("The job does not exist.") | |||||
| job_id = str(job_id) | job_id = str(job_id) | ||||
| indexing_cache_key = f"segment_batch_import_{job_id}" | indexing_cache_key = f"segment_batch_import_{job_id}" | ||||
| cache_result = redis_client.get(indexing_cache_key) | cache_result = redis_client.get(indexing_cache_key) | ||||
| return {"job_id": job_id, "job_status": cache_result.decode()}, 200 | return {"job_id": job_id, "job_status": cache_result.decode()}, 200 | ||||
| @console_ns.route("/datasets/<uuid:dataset_id>/documents/<uuid:document_id>/segments/<uuid:segment_id>/child_chunks") | |||||
| class ChildChunkAddApi(Resource): | class ChildChunkAddApi(Resource): | ||||
| @setup_required | @setup_required | ||||
| @login_required | @login_required | ||||
| return {"data": marshal(child_chunks, child_chunk_fields)}, 200 | return {"data": marshal(child_chunks, child_chunk_fields)}, 200 | ||||
| @console_ns.route( | |||||
| "/datasets/<uuid:dataset_id>/documents/<uuid:document_id>/segments/<uuid:segment_id>/child_chunks/<uuid:child_chunk_id>" | |||||
| ) | |||||
| class ChildChunkUpdateApi(Resource): | class ChildChunkUpdateApi(Resource): | ||||
| @setup_required | @setup_required | ||||
| @login_required | @login_required | ||||
| except ChildChunkIndexingServiceError as e: | except ChildChunkIndexingServiceError as e: | ||||
| raise ChildChunkIndexingError(str(e)) | raise ChildChunkIndexingError(str(e)) | ||||
| return {"data": marshal(child_chunk, child_chunk_fields)}, 200 | return {"data": marshal(child_chunk, child_chunk_fields)}, 200 | ||||
| api.add_resource(DatasetDocumentSegmentListApi, "/datasets/<uuid:dataset_id>/documents/<uuid:document_id>/segments") | |||||
| api.add_resource( | |||||
| DatasetDocumentSegmentApi, "/datasets/<uuid:dataset_id>/documents/<uuid:document_id>/segment/<string:action>" | |||||
| ) | |||||
| api.add_resource(DatasetDocumentSegmentAddApi, "/datasets/<uuid:dataset_id>/documents/<uuid:document_id>/segment") | |||||
| api.add_resource( | |||||
| DatasetDocumentSegmentUpdateApi, | |||||
| "/datasets/<uuid:dataset_id>/documents/<uuid:document_id>/segments/<uuid:segment_id>", | |||||
| ) | |||||
| api.add_resource( | |||||
| DatasetDocumentSegmentBatchImportApi, | |||||
| "/datasets/<uuid:dataset_id>/documents/<uuid:document_id>/segments/batch_import", | |||||
| "/datasets/batch_import_status/<uuid:job_id>", | |||||
| ) | |||||
| api.add_resource( | |||||
| ChildChunkAddApi, | |||||
| "/datasets/<uuid:dataset_id>/documents/<uuid:document_id>/segments/<uuid:segment_id>/child_chunks", | |||||
| ) | |||||
| api.add_resource( | |||||
| ChildChunkUpdateApi, | |||||
| "/datasets/<uuid:dataset_id>/documents/<uuid:document_id>/segments/<uuid:segment_id>/child_chunks/<uuid:child_chunk_id>", | |||||
| ) |
| from flask_restx import Resource, marshal_with, reqparse | from flask_restx import Resource, marshal_with, reqparse | ||||
| from werkzeug.exceptions import NotFound | from werkzeug.exceptions import NotFound | ||||
| from controllers.console import api | |||||
| from controllers.console import console_ns | |||||
| from controllers.console.wraps import account_initialization_required, enterprise_license_required, setup_required | from controllers.console.wraps import account_initialization_required, enterprise_license_required, setup_required | ||||
| from fields.dataset_fields import dataset_metadata_fields | from fields.dataset_fields import dataset_metadata_fields | ||||
| from libs.login import login_required | from libs.login import login_required | ||||
| from services.metadata_service import MetadataService | from services.metadata_service import MetadataService | ||||
| @console_ns.route("/datasets/<uuid:dataset_id>/metadata") | |||||
| class DatasetMetadataCreateApi(Resource): | class DatasetMetadataCreateApi(Resource): | ||||
| @setup_required | @setup_required | ||||
| @login_required | @login_required | ||||
| return MetadataService.get_dataset_metadatas(dataset), 200 | return MetadataService.get_dataset_metadatas(dataset), 200 | ||||
| @console_ns.route("/datasets/<uuid:dataset_id>/metadata/<uuid:metadata_id>") | |||||
| class DatasetMetadataApi(Resource): | class DatasetMetadataApi(Resource): | ||||
| @setup_required | @setup_required | ||||
| @login_required | @login_required | ||||
| return {"result": "success"}, 204 | return {"result": "success"}, 204 | ||||
| @console_ns.route("/datasets/metadata/built-in") | |||||
| class DatasetMetadataBuiltInFieldApi(Resource): | class DatasetMetadataBuiltInFieldApi(Resource): | ||||
| @setup_required | @setup_required | ||||
| @login_required | @login_required | ||||
| return {"fields": built_in_fields}, 200 | return {"fields": built_in_fields}, 200 | ||||
| @console_ns.route("/datasets/<uuid:dataset_id>/metadata/built-in/<string:action>") | |||||
| class DatasetMetadataBuiltInFieldActionApi(Resource): | class DatasetMetadataBuiltInFieldActionApi(Resource): | ||||
| @setup_required | @setup_required | ||||
| @login_required | @login_required | ||||
| return {"result": "success"}, 200 | return {"result": "success"}, 200 | ||||
| @console_ns.route("/datasets/<uuid:dataset_id>/documents/metadata") | |||||
| class DocumentMetadataEditApi(Resource): | class DocumentMetadataEditApi(Resource): | ||||
| @setup_required | @setup_required | ||||
| @login_required | @login_required | ||||
| MetadataService.update_documents_metadata(dataset, metadata_args) | MetadataService.update_documents_metadata(dataset, metadata_args) | ||||
| return {"result": "success"}, 200 | return {"result": "success"}, 200 | ||||
| api.add_resource(DatasetMetadataCreateApi, "/datasets/<uuid:dataset_id>/metadata") | |||||
| api.add_resource(DatasetMetadataApi, "/datasets/<uuid:dataset_id>/metadata/<uuid:metadata_id>") | |||||
| api.add_resource(DatasetMetadataBuiltInFieldApi, "/datasets/metadata/built-in") | |||||
| api.add_resource(DatasetMetadataBuiltInFieldActionApi, "/datasets/<uuid:dataset_id>/metadata/built-in/<string:action>") | |||||
| api.add_resource(DocumentMetadataEditApi, "/datasets/<uuid:dataset_id>/documents/metadata") |
| from werkzeug.exceptions import Forbidden, NotFound | from werkzeug.exceptions import Forbidden, NotFound | ||||
| from configs import dify_config | from configs import dify_config | ||||
| from controllers.console import api | |||||
| from controllers.console import console_ns | |||||
| from controllers.console.wraps import ( | from controllers.console.wraps import ( | ||||
| account_initialization_required, | account_initialization_required, | ||||
| setup_required, | setup_required, | ||||
| from services.plugin.oauth_service import OAuthProxyService | from services.plugin.oauth_service import OAuthProxyService | ||||
| @console_ns.route("/oauth/plugin/<path:provider_id>/datasource/get-authorization-url") | |||||
| class DatasourcePluginOAuthAuthorizationUrl(Resource): | class DatasourcePluginOAuthAuthorizationUrl(Resource): | ||||
| @setup_required | @setup_required | ||||
| @login_required | @login_required | ||||
| return response | return response | ||||
| @console_ns.route("/oauth/plugin/<path:provider_id>/datasource/callback") | |||||
| class DatasourceOAuthCallback(Resource): | class DatasourceOAuthCallback(Resource): | ||||
| @setup_required | @setup_required | ||||
| def get(self, provider_id: str): | def get(self, provider_id: str): | ||||
| return redirect(f"{dify_config.CONSOLE_WEB_URL}/oauth-callback") | return redirect(f"{dify_config.CONSOLE_WEB_URL}/oauth-callback") | ||||
| @console_ns.route("/auth/plugin/datasource/<path:provider_id>") | |||||
| class DatasourceAuth(Resource): | class DatasourceAuth(Resource): | ||||
| @setup_required | @setup_required | ||||
| @login_required | @login_required | ||||
| return {"result": datasources}, 200 | return {"result": datasources}, 200 | ||||
| @console_ns.route("/auth/plugin/datasource/<path:provider_id>/delete") | |||||
| class DatasourceAuthDeleteApi(Resource): | class DatasourceAuthDeleteApi(Resource): | ||||
| @setup_required | @setup_required | ||||
| @login_required | @login_required | ||||
| return {"result": "success"}, 200 | return {"result": "success"}, 200 | ||||
| @console_ns.route("/auth/plugin/datasource/<path:provider_id>/update") | |||||
| class DatasourceAuthUpdateApi(Resource): | class DatasourceAuthUpdateApi(Resource): | ||||
| @setup_required | @setup_required | ||||
| @login_required | @login_required | ||||
| return {"result": "success"}, 201 | return {"result": "success"}, 201 | ||||
| @console_ns.route("/auth/plugin/datasource/list") | |||||
| class DatasourceAuthListApi(Resource): | class DatasourceAuthListApi(Resource): | ||||
| @setup_required | @setup_required | ||||
| @login_required | @login_required | ||||
| return {"result": jsonable_encoder(datasources)}, 200 | return {"result": jsonable_encoder(datasources)}, 200 | ||||
| @console_ns.route("/auth/plugin/datasource/default-list") | |||||
| class DatasourceHardCodeAuthListApi(Resource): | class DatasourceHardCodeAuthListApi(Resource): | ||||
| @setup_required | @setup_required | ||||
| @login_required | @login_required | ||||
| return {"result": jsonable_encoder(datasources)}, 200 | return {"result": jsonable_encoder(datasources)}, 200 | ||||
| @console_ns.route("/auth/plugin/datasource/<path:provider_id>/custom-client") | |||||
| class DatasourceAuthOauthCustomClient(Resource): | class DatasourceAuthOauthCustomClient(Resource): | ||||
| @setup_required | @setup_required | ||||
| @login_required | @login_required | ||||
| return {"result": "success"}, 200 | return {"result": "success"}, 200 | ||||
| @console_ns.route("/auth/plugin/datasource/<path:provider_id>/default") | |||||
| class DatasourceAuthDefaultApi(Resource): | class DatasourceAuthDefaultApi(Resource): | ||||
| @setup_required | @setup_required | ||||
| @login_required | @login_required | ||||
| return {"result": "success"}, 200 | return {"result": "success"}, 200 | ||||
| @console_ns.route("/auth/plugin/datasource/<path:provider_id>/update-name") | |||||
| class DatasourceUpdateProviderNameApi(Resource): | class DatasourceUpdateProviderNameApi(Resource): | ||||
| @setup_required | @setup_required | ||||
| @login_required | @login_required | ||||
| credential_id=args["credential_id"], | credential_id=args["credential_id"], | ||||
| ) | ) | ||||
| return {"result": "success"}, 200 | return {"result": "success"}, 200 | ||||
| api.add_resource( | |||||
| DatasourcePluginOAuthAuthorizationUrl, | |||||
| "/oauth/plugin/<path:provider_id>/datasource/get-authorization-url", | |||||
| ) | |||||
| api.add_resource( | |||||
| DatasourceOAuthCallback, | |||||
| "/oauth/plugin/<path:provider_id>/datasource/callback", | |||||
| ) | |||||
| api.add_resource( | |||||
| DatasourceAuth, | |||||
| "/auth/plugin/datasource/<path:provider_id>", | |||||
| ) | |||||
| api.add_resource( | |||||
| DatasourceAuthUpdateApi, | |||||
| "/auth/plugin/datasource/<path:provider_id>/update", | |||||
| ) | |||||
| api.add_resource( | |||||
| DatasourceAuthDeleteApi, | |||||
| "/auth/plugin/datasource/<path:provider_id>/delete", | |||||
| ) | |||||
| api.add_resource( | |||||
| DatasourceAuthListApi, | |||||
| "/auth/plugin/datasource/list", | |||||
| ) | |||||
| api.add_resource( | |||||
| DatasourceHardCodeAuthListApi, | |||||
| "/auth/plugin/datasource/default-list", | |||||
| ) | |||||
| api.add_resource( | |||||
| DatasourceAuthOauthCustomClient, | |||||
| "/auth/plugin/datasource/<path:provider_id>/custom-client", | |||||
| ) | |||||
| api.add_resource( | |||||
| DatasourceAuthDefaultApi, | |||||
| "/auth/plugin/datasource/<path:provider_id>/default", | |||||
| ) | |||||
| api.add_resource( | |||||
| DatasourceUpdateProviderNameApi, | |||||
| "/auth/plugin/datasource/<path:provider_id>/update-name", | |||||
| ) |
| ) | ) | ||||
| from werkzeug.exceptions import Forbidden | from werkzeug.exceptions import Forbidden | ||||
| from controllers.console import api | |||||
| from controllers.console import console_ns | |||||
| from controllers.console.datasets.wraps import get_rag_pipeline | from controllers.console.datasets.wraps import get_rag_pipeline | ||||
| from controllers.console.wraps import account_initialization_required, setup_required | from controllers.console.wraps import account_initialization_required, setup_required | ||||
| from libs.login import current_user, login_required | from libs.login import current_user, login_required | ||||
| from services.rag_pipeline.rag_pipeline import RagPipelineService | from services.rag_pipeline.rag_pipeline import RagPipelineService | ||||
| @console_ns.route("/rag/pipelines/<uuid:pipeline_id>/workflows/published/datasource/nodes/<string:node_id>/preview") | |||||
| class DataSourceContentPreviewApi(Resource): | class DataSourceContentPreviewApi(Resource): | ||||
| @setup_required | @setup_required | ||||
| @login_required | @login_required | ||||
| credential_id=args.get("credential_id"), | credential_id=args.get("credential_id"), | ||||
| ) | ) | ||||
| return preview_content, 200 | return preview_content, 200 | ||||
| api.add_resource( | |||||
| DataSourceContentPreviewApi, | |||||
| "/rag/pipelines/<uuid:pipeline_id>/workflows/published/datasource/nodes/<string:node_id>/preview", | |||||
| ) |
| from flask_restx import Resource, reqparse | from flask_restx import Resource, reqparse | ||||
| from sqlalchemy.orm import Session | from sqlalchemy.orm import Session | ||||
| from controllers.console import api | |||||
| from controllers.console import console_ns | |||||
| from controllers.console.wraps import ( | from controllers.console.wraps import ( | ||||
| account_initialization_required, | account_initialization_required, | ||||
| enterprise_license_required, | enterprise_license_required, | ||||
| return description | return description | ||||
| @console_ns.route("/rag/pipeline/templates") | |||||
| class PipelineTemplateListApi(Resource): | class PipelineTemplateListApi(Resource): | ||||
| @setup_required | @setup_required | ||||
| @login_required | @login_required | ||||
| return pipeline_templates, 200 | return pipeline_templates, 200 | ||||
| @console_ns.route("/rag/pipeline/templates/<string:template_id>") | |||||
| class PipelineTemplateDetailApi(Resource): | class PipelineTemplateDetailApi(Resource): | ||||
| @setup_required | @setup_required | ||||
| @login_required | @login_required | ||||
| return pipeline_template, 200 | return pipeline_template, 200 | ||||
| @console_ns.route("/rag/pipeline/customized/templates/<string:template_id>") | |||||
| class CustomizedPipelineTemplateApi(Resource): | class CustomizedPipelineTemplateApi(Resource): | ||||
| @setup_required | @setup_required | ||||
| @login_required | @login_required | ||||
| return {"data": template.yaml_content}, 200 | return {"data": template.yaml_content}, 200 | ||||
| @console_ns.route("/rag/pipelines/<string:pipeline_id>/customized/publish") | |||||
| class PublishCustomizedPipelineTemplateApi(Resource): | class PublishCustomizedPipelineTemplateApi(Resource): | ||||
| @setup_required | @setup_required | ||||
| @login_required | @login_required | ||||
| rag_pipeline_service = RagPipelineService() | rag_pipeline_service = RagPipelineService() | ||||
| rag_pipeline_service.publish_customized_pipeline_template(pipeline_id, args) | rag_pipeline_service.publish_customized_pipeline_template(pipeline_id, args) | ||||
| return {"result": "success"} | return {"result": "success"} | ||||
| api.add_resource( | |||||
| PipelineTemplateListApi, | |||||
| "/rag/pipeline/templates", | |||||
| ) | |||||
| api.add_resource( | |||||
| PipelineTemplateDetailApi, | |||||
| "/rag/pipeline/templates/<string:template_id>", | |||||
| ) | |||||
| api.add_resource( | |||||
| CustomizedPipelineTemplateApi, | |||||
| "/rag/pipeline/customized/templates/<string:template_id>", | |||||
| ) | |||||
| api.add_resource( | |||||
| PublishCustomizedPipelineTemplateApi, | |||||
| "/rag/pipelines/<string:pipeline_id>/customized/publish", | |||||
| ) |
| UnsupportedAudioTypeServiceError, | UnsupportedAudioTypeServiceError, | ||||
| ) | ) | ||||
| from .. import console_ns | |||||
| logger = logging.getLogger(__name__) | logger = logging.getLogger(__name__) | ||||
| @console_ns.route( | |||||
| "/installed-apps/<uuid:installed_app_id>/audio-to-text", | |||||
| endpoint="installed_app_audio", | |||||
| ) | |||||
| class ChatAudioApi(InstalledAppResource): | class ChatAudioApi(InstalledAppResource): | ||||
| def post(self, installed_app): | def post(self, installed_app): | ||||
| app_model = installed_app.app | app_model = installed_app.app | ||||
| raise InternalServerError() | raise InternalServerError() | ||||
| @console_ns.route( | |||||
| "/installed-apps/<uuid:installed_app_id>/text-to-audio", | |||||
| endpoint="installed_app_text", | |||||
| ) | |||||
| class ChatTextApi(InstalledAppResource): | class ChatTextApi(InstalledAppResource): | ||||
| def post(self, installed_app): | def post(self, installed_app): | ||||
| from flask_restx import reqparse | from flask_restx import reqparse |
| from services.app_generate_service import AppGenerateService | from services.app_generate_service import AppGenerateService | ||||
| from services.errors.llm import InvokeRateLimitError | from services.errors.llm import InvokeRateLimitError | ||||
| from .. import console_ns | |||||
| logger = logging.getLogger(__name__) | logger = logging.getLogger(__name__) | ||||
| # define completion api for user | # define completion api for user | ||||
| @console_ns.route( | |||||
| "/installed-apps/<uuid:installed_app_id>/completion-messages", | |||||
| endpoint="installed_app_completion", | |||||
| ) | |||||
| class CompletionApi(InstalledAppResource): | class CompletionApi(InstalledAppResource): | ||||
| def post(self, installed_app): | def post(self, installed_app): | ||||
| app_model = installed_app.app | app_model = installed_app.app | ||||
| raise InternalServerError() | raise InternalServerError() | ||||
| @console_ns.route( | |||||
| "/installed-apps/<uuid:installed_app_id>/completion-messages/<string:task_id>/stop", | |||||
| endpoint="installed_app_stop_completion", | |||||
| ) | |||||
| class CompletionStopApi(InstalledAppResource): | class CompletionStopApi(InstalledAppResource): | ||||
| def post(self, installed_app, task_id): | def post(self, installed_app, task_id): | ||||
| app_model = installed_app.app | app_model = installed_app.app | ||||
| return {"result": "success"}, 200 | return {"result": "success"}, 200 | ||||
| @console_ns.route( | |||||
| "/installed-apps/<uuid:installed_app_id>/chat-messages", | |||||
| endpoint="installed_app_chat_completion", | |||||
| ) | |||||
| class ChatApi(InstalledAppResource): | class ChatApi(InstalledAppResource): | ||||
| def post(self, installed_app): | def post(self, installed_app): | ||||
| app_model = installed_app.app | app_model = installed_app.app | ||||
| raise InternalServerError() | raise InternalServerError() | ||||
| @console_ns.route( | |||||
| "/installed-apps/<uuid:installed_app_id>/chat-messages/<string:task_id>/stop", | |||||
| endpoint="installed_app_stop_chat_completion", | |||||
| ) | |||||
| class ChatStopApi(InstalledAppResource): | class ChatStopApi(InstalledAppResource): | ||||
| def post(self, installed_app, task_id): | def post(self, installed_app, task_id): | ||||
| app_model = installed_app.app | app_model = installed_app.app |
| from services.errors.conversation import ConversationNotExistsError, LastConversationNotExistsError | from services.errors.conversation import ConversationNotExistsError, LastConversationNotExistsError | ||||
| from services.web_conversation_service import WebConversationService | from services.web_conversation_service import WebConversationService | ||||
| from .. import console_ns | |||||
| @console_ns.route( | |||||
| "/installed-apps/<uuid:installed_app_id>/conversations", | |||||
| endpoint="installed_app_conversations", | |||||
| ) | |||||
| class ConversationListApi(InstalledAppResource): | class ConversationListApi(InstalledAppResource): | ||||
| @marshal_with(conversation_infinite_scroll_pagination_fields) | @marshal_with(conversation_infinite_scroll_pagination_fields) | ||||
| def get(self, installed_app): | def get(self, installed_app): | ||||
| raise NotFound("Last Conversation Not Exists.") | raise NotFound("Last Conversation Not Exists.") | ||||
| @console_ns.route( | |||||
| "/installed-apps/<uuid:installed_app_id>/conversations/<uuid:c_id>", | |||||
| endpoint="installed_app_conversation", | |||||
| ) | |||||
| class ConversationApi(InstalledAppResource): | class ConversationApi(InstalledAppResource): | ||||
| def delete(self, installed_app, c_id): | def delete(self, installed_app, c_id): | ||||
| app_model = installed_app.app | app_model = installed_app.app | ||||
| return {"result": "success"}, 204 | return {"result": "success"}, 204 | ||||
| @console_ns.route( | |||||
| "/installed-apps/<uuid:installed_app_id>/conversations/<uuid:c_id>/name", | |||||
| endpoint="installed_app_conversation_rename", | |||||
| ) | |||||
| class ConversationRenameApi(InstalledAppResource): | class ConversationRenameApi(InstalledAppResource): | ||||
| @marshal_with(simple_conversation_fields) | @marshal_with(simple_conversation_fields) | ||||
| def post(self, installed_app, c_id): | def post(self, installed_app, c_id): | ||||
| raise NotFound("Conversation Not Exists.") | raise NotFound("Conversation Not Exists.") | ||||
| @console_ns.route( | |||||
| "/installed-apps/<uuid:installed_app_id>/conversations/<uuid:c_id>/pin", | |||||
| endpoint="installed_app_conversation_pin", | |||||
| ) | |||||
| class ConversationPinApi(InstalledAppResource): | class ConversationPinApi(InstalledAppResource): | ||||
| def patch(self, installed_app, c_id): | def patch(self, installed_app, c_id): | ||||
| app_model = installed_app.app | app_model = installed_app.app | ||||
| return {"result": "success"} | return {"result": "success"} | ||||
| @console_ns.route( | |||||
| "/installed-apps/<uuid:installed_app_id>/conversations/<uuid:c_id>/unpin", | |||||
| endpoint="installed_app_conversation_unpin", | |||||
| ) | |||||
| class ConversationUnPinApi(InstalledAppResource): | class ConversationUnPinApi(InstalledAppResource): | ||||
| def patch(self, installed_app, c_id): | def patch(self, installed_app, c_id): | ||||
| app_model = installed_app.app | app_model = installed_app.app |
| ) | ) | ||||
| from services.message_service import MessageService | from services.message_service import MessageService | ||||
| from .. import console_ns | |||||
| logger = logging.getLogger(__name__) | logger = logging.getLogger(__name__) | ||||
| @console_ns.route( | |||||
| "/installed-apps/<uuid:installed_app_id>/messages", | |||||
| endpoint="installed_app_messages", | |||||
| ) | |||||
| class MessageListApi(InstalledAppResource): | class MessageListApi(InstalledAppResource): | ||||
| @marshal_with(message_infinite_scroll_pagination_fields) | @marshal_with(message_infinite_scroll_pagination_fields) | ||||
| def get(self, installed_app): | def get(self, installed_app): | ||||
| raise NotFound("First Message Not Exists.") | raise NotFound("First Message Not Exists.") | ||||
| @console_ns.route( | |||||
| "/installed-apps/<uuid:installed_app_id>/messages/<uuid:message_id>/feedbacks", | |||||
| endpoint="installed_app_message_feedback", | |||||
| ) | |||||
| class MessageFeedbackApi(InstalledAppResource): | class MessageFeedbackApi(InstalledAppResource): | ||||
| def post(self, installed_app, message_id): | def post(self, installed_app, message_id): | ||||
| app_model = installed_app.app | app_model = installed_app.app | ||||
| return {"result": "success"} | return {"result": "success"} | ||||
| @console_ns.route( | |||||
| "/installed-apps/<uuid:installed_app_id>/messages/<uuid:message_id>/more-like-this", | |||||
| endpoint="installed_app_more_like_this", | |||||
| ) | |||||
| class MessageMoreLikeThisApi(InstalledAppResource): | class MessageMoreLikeThisApi(InstalledAppResource): | ||||
| def get(self, installed_app, message_id): | def get(self, installed_app, message_id): | ||||
| app_model = installed_app.app | app_model = installed_app.app | ||||
| raise InternalServerError() | raise InternalServerError() | ||||
| @console_ns.route( | |||||
| "/installed-apps/<uuid:installed_app_id>/messages/<uuid:message_id>/suggested-questions", | |||||
| endpoint="installed_app_suggested_question", | |||||
| ) | |||||
| class MessageSuggestedQuestionApi(InstalledAppResource): | class MessageSuggestedQuestionApi(InstalledAppResource): | ||||
| def get(self, installed_app, message_id): | def get(self, installed_app, message_id): | ||||
| app_model = installed_app.app | app_model = installed_app.app |
| from services.app_generate_service import AppGenerateService | from services.app_generate_service import AppGenerateService | ||||
| from services.errors.llm import InvokeRateLimitError | from services.errors.llm import InvokeRateLimitError | ||||
| from .. import console_ns | |||||
| logger = logging.getLogger(__name__) | logger = logging.getLogger(__name__) | ||||
| @console_ns.route("/installed-apps/<uuid:installed_app_id>/workflows/run") | |||||
| class InstalledAppWorkflowRunApi(InstalledAppResource): | class InstalledAppWorkflowRunApi(InstalledAppResource): | ||||
| def post(self, installed_app: InstalledApp): | def post(self, installed_app: InstalledApp): | ||||
| """ | """ | ||||
| raise InternalServerError() | raise InternalServerError() | ||||
| @console_ns.route("/installed-apps/<uuid:installed_app_id>/workflows/tasks/<string:task_id>/stop") | |||||
| class InstalledAppWorkflowTaskStopApi(InstalledAppResource): | class InstalledAppWorkflowTaskStopApi(InstalledAppResource): | ||||
| def post(self, installed_app: InstalledApp, task_id: str): | def post(self, installed_app: InstalledApp, task_id: str): | ||||
| """ | """ |
| from models import Account | from models import Account | ||||
| from services.file_service import FileService | from services.file_service import FileService | ||||
| from . import console_ns | |||||
| PREVIEW_WORDS_LIMIT = 3000 | PREVIEW_WORDS_LIMIT = 3000 | ||||
| @console_ns.route("/files/upload") | |||||
| class FileApi(Resource): | class FileApi(Resource): | ||||
| @setup_required | @setup_required | ||||
| @login_required | @login_required | ||||
| return upload_file, 201 | return upload_file, 201 | ||||
| @console_ns.route("/files/<uuid:file_id>/preview") | |||||
| class FilePreviewApi(Resource): | class FilePreviewApi(Resource): | ||||
| @setup_required | @setup_required | ||||
| @login_required | @login_required | ||||
| return {"content": text} | return {"content": text} | ||||
| @console_ns.route("/files/support-type") | |||||
| class FileSupportTypeApi(Resource): | class FileSupportTypeApi(Resource): | ||||
| @setup_required | @setup_required | ||||
| @login_required | @login_required |
| from models.account import Account | from models.account import Account | ||||
| from services.file_service import FileService | from services.file_service import FileService | ||||
| from . import console_ns | |||||
| @console_ns.route("/remote-files/<path:url>") | |||||
| class RemoteFileInfoApi(Resource): | class RemoteFileInfoApi(Resource): | ||||
| @marshal_with(remote_file_info_fields) | @marshal_with(remote_file_info_fields) | ||||
| def get(self, url): | def get(self, url): | ||||
| } | } | ||||
| @console_ns.route("/remote-files/upload") | |||||
| class RemoteFileUploadApi(Resource): | class RemoteFileUploadApi(Resource): | ||||
| @marshal_with(file_fields_with_signed_url) | @marshal_with(file_fields_with_signed_url) | ||||
| def post(self): | def post(self): |
| from flask_restx import Resource | from flask_restx import Resource | ||||
| from controllers.console import api | |||||
| from controllers.console.wraps import ( | from controllers.console.wraps import ( | ||||
| account_initialization_required, | account_initialization_required, | ||||
| setup_required, | setup_required, | ||||
| from core.schemas.schema_manager import SchemaManager | from core.schemas.schema_manager import SchemaManager | ||||
| from libs.login import login_required | from libs.login import login_required | ||||
| from . import console_ns | |||||
| logger = logging.getLogger(__name__) | logger = logging.getLogger(__name__) | ||||
| @console_ns.route("/spec/schema-definitions") | |||||
| class SpecSchemaDefinitionsApi(Resource): | class SpecSchemaDefinitionsApi(Resource): | ||||
| @setup_required | @setup_required | ||||
| @login_required | @login_required | ||||
| logger.exception("Failed to get schema definitions from local registry") | logger.exception("Failed to get schema definitions from local registry") | ||||
| # Return empty array as fallback | # Return empty array as fallback | ||||
| return [], 200 | return [], 200 | ||||
| api.add_resource(SpecSchemaDefinitionsApi, "/spec/schema-definitions") |