diff --git a/api/controllers/web/app.py b/api/controllers/web/app.py index 6e6c39a9c..e0c3e997c 100644 --- a/api/controllers/web/app.py +++ b/api/controllers/web/app.py @@ -5,7 +5,7 @@ from flask_restx import Resource, marshal_with, reqparse from werkzeug.exceptions import Unauthorized from controllers.common import fields -from controllers.web import api +from controllers.web import web_ns from controllers.web.error import AppUnavailableError from controllers.web.wraps import WebApiResource from core.app.app_config.common.parameters_mapping import get_parameters_from_feature_dict @@ -19,9 +19,22 @@ from services.webapp_auth_service import WebAppAuthService logger = logging.getLogger(__name__) +@web_ns.route("/parameters") class AppParameterApi(WebApiResource): """Resource for app variables.""" + @web_ns.doc("Get App Parameters") + @web_ns.doc(description="Retrieve the parameters for a specific app.") + @web_ns.doc( + responses={ + 200: "Success", + 400: "Bad Request", + 401: "Unauthorized", + 403: "Forbidden", + 404: "App Not Found", + 500: "Internal Server Error", + } + ) @marshal_with(fields.parameters_fields) def get(self, app_model: App, end_user): """Retrieve app parameters.""" @@ -44,13 +57,42 @@ class AppParameterApi(WebApiResource): return get_parameters_from_feature_dict(features_dict=features_dict, user_input_form=user_input_form) +@web_ns.route("/meta") class AppMeta(WebApiResource): + @web_ns.doc("Get App Meta") + @web_ns.doc(description="Retrieve the metadata for a specific app.") + @web_ns.doc( + responses={ + 200: "Success", + 400: "Bad Request", + 401: "Unauthorized", + 403: "Forbidden", + 404: "App Not Found", + 500: "Internal Server Error", + } + ) def get(self, app_model: App, end_user): """Get app meta""" return AppService().get_app_meta(app_model) +@web_ns.route("/webapp/access-mode") class AppAccessMode(Resource): + @web_ns.doc("Get App Access Mode") + @web_ns.doc(description="Retrieve the access mode for a web application (public or restricted).") + @web_ns.doc( + params={ + "appId": {"description": "Application ID", "type": "string", "required": False}, + "appCode": {"description": "Application code", "type": "string", "required": False}, + } + ) + @web_ns.doc( + responses={ + 200: "Success", + 400: "Bad Request", + 500: "Internal Server Error", + } + ) def get(self): parser = reqparse.RequestParser() parser.add_argument("appId", type=str, required=False, location="args") @@ -74,7 +116,19 @@ class AppAccessMode(Resource): return {"accessMode": res.access_mode} +@web_ns.route("/webapp/permission") class AppWebAuthPermission(Resource): + @web_ns.doc("Check App Permission") + @web_ns.doc(description="Check if user has permission to access a web application.") + @web_ns.doc(params={"appId": {"description": "Application ID", "type": "string", "required": True}}) + @web_ns.doc( + responses={ + 200: "Success", + 400: "Bad Request", + 401: "Unauthorized", + 500: "Internal Server Error", + } + ) def get(self): user_id = "visitor" try: @@ -112,10 +166,3 @@ class AppWebAuthPermission(Resource): if WebAppAuthService.is_app_require_permission_check(app_id=app_id): res = EnterpriseService.WebAppAuth.is_user_allowed_to_access_webapp(str(user_id), app_code) return {"result": res} - - -api.add_resource(AppParameterApi, "/parameters") -api.add_resource(AppMeta, "/meta") -# webapp auth apis -api.add_resource(AppAccessMode, "/webapp/access-mode") -api.add_resource(AppWebAuthPermission, "/webapp/permission") diff --git a/api/controllers/web/completion.py b/api/controllers/web/completion.py index 3947411c0..a42bf5fc6 100644 --- a/api/controllers/web/completion.py +++ b/api/controllers/web/completion.py @@ -36,6 +36,32 @@ logger = logging.getLogger(__name__) # define completion api for user class CompletionApi(WebApiResource): + @api.doc("Create Completion Message") + @api.doc(description="Create a completion message for text generation applications.") + @api.doc( + params={ + "inputs": {"description": "Input variables for the completion", "type": "object", "required": True}, + "query": {"description": "Query text for completion", "type": "string", "required": False}, + "files": {"description": "Files to be processed", "type": "array", "required": False}, + "response_mode": { + "description": "Response mode: blocking or streaming", + "type": "string", + "enum": ["blocking", "streaming"], + "required": False, + }, + "retriever_from": {"description": "Source of retriever", "type": "string", "required": False}, + } + ) + @api.doc( + responses={ + 200: "Success", + 400: "Bad Request", + 401: "Unauthorized", + 403: "Forbidden", + 404: "App Not Found", + 500: "Internal Server Error", + } + ) def post(self, app_model, end_user): if app_model.mode != "completion": raise NotCompletionAppError() @@ -81,6 +107,19 @@ class CompletionApi(WebApiResource): class CompletionStopApi(WebApiResource): + @api.doc("Stop Completion Message") + @api.doc(description="Stop a running completion message task.") + @api.doc(params={"task_id": {"description": "Task ID to stop", "type": "string", "required": True}}) + @api.doc( + responses={ + 200: "Success", + 400: "Bad Request", + 401: "Unauthorized", + 403: "Forbidden", + 404: "Task Not Found", + 500: "Internal Server Error", + } + ) def post(self, app_model, end_user, task_id): if app_model.mode != "completion": raise NotCompletionAppError() @@ -91,6 +130,34 @@ class CompletionStopApi(WebApiResource): class ChatApi(WebApiResource): + @api.doc("Create Chat Message") + @api.doc(description="Create a chat message for conversational applications.") + @api.doc( + params={ + "inputs": {"description": "Input variables for the chat", "type": "object", "required": True}, + "query": {"description": "User query/message", "type": "string", "required": True}, + "files": {"description": "Files to be processed", "type": "array", "required": False}, + "response_mode": { + "description": "Response mode: blocking or streaming", + "type": "string", + "enum": ["blocking", "streaming"], + "required": False, + }, + "conversation_id": {"description": "Conversation UUID", "type": "string", "required": False}, + "parent_message_id": {"description": "Parent message UUID", "type": "string", "required": False}, + "retriever_from": {"description": "Source of retriever", "type": "string", "required": False}, + } + ) + @api.doc( + responses={ + 200: "Success", + 400: "Bad Request", + 401: "Unauthorized", + 403: "Forbidden", + 404: "App Not Found", + 500: "Internal Server Error", + } + ) def post(self, app_model, end_user): app_mode = AppMode.value_of(app_model.mode) if app_mode not in {AppMode.CHAT, AppMode.AGENT_CHAT, AppMode.ADVANCED_CHAT}: @@ -141,6 +208,19 @@ class ChatApi(WebApiResource): class ChatStopApi(WebApiResource): + @api.doc("Stop Chat Message") + @api.doc(description="Stop a running chat message task.") + @api.doc(params={"task_id": {"description": "Task ID to stop", "type": "string", "required": True}}) + @api.doc( + responses={ + 200: "Success", + 400: "Bad Request", + 401: "Unauthorized", + 403: "Forbidden", + 404: "Task Not Found", + 500: "Internal Server Error", + } + ) def post(self, app_model, end_user, task_id): app_mode = AppMode.value_of(app_model.mode) if app_mode not in {AppMode.CHAT, AppMode.AGENT_CHAT, AppMode.ADVANCED_CHAT}: diff --git a/api/controllers/web/site.py b/api/controllers/web/site.py index b2a887a0d..91d67bf9d 100644 --- a/api/controllers/web/site.py +++ b/api/controllers/web/site.py @@ -53,6 +53,18 @@ class AppSiteApi(WebApiResource): "custom_config": fields.Raw(attribute="custom_config"), } + @api.doc("Get App Site Info") + @api.doc(description="Retrieve app site information and configuration.") + @api.doc( + responses={ + 200: "Success", + 400: "Bad Request", + 401: "Unauthorized", + 403: "Forbidden", + 404: "App Not Found", + 500: "Internal Server Error", + } + ) @marshal_with(app_fields) def get(self, app_model, end_user): """Retrieve app site info.""" diff --git a/api/controllers/web/workflow.py b/api/controllers/web/workflow.py index d64ccc7d0..3566cfae3 100644 --- a/api/controllers/web/workflow.py +++ b/api/controllers/web/workflow.py @@ -30,6 +30,24 @@ logger = logging.getLogger(__name__) class WorkflowRunApi(WebApiResource): + @api.doc("Run Workflow") + @api.doc(description="Execute a workflow with provided inputs and files.") + @api.doc( + params={ + "inputs": {"description": "Input variables for the workflow", "type": "object", "required": True}, + "files": {"description": "Files to be processed by the workflow", "type": "array", "required": False}, + } + ) + @api.doc( + responses={ + 200: "Success", + 400: "Bad Request", + 401: "Unauthorized", + 403: "Forbidden", + 404: "App Not Found", + 500: "Internal Server Error", + } + ) def post(self, app_model: App, end_user: EndUser): """ Run workflow @@ -67,6 +85,23 @@ class WorkflowRunApi(WebApiResource): class WorkflowTaskStopApi(WebApiResource): + @api.doc("Stop Workflow Task") + @api.doc(description="Stop a running workflow task.") + @api.doc( + params={ + "task_id": {"description": "Task ID to stop", "type": "string", "required": True}, + } + ) + @api.doc( + responses={ + 200: "Success", + 400: "Bad Request", + 401: "Unauthorized", + 403: "Forbidden", + 404: "Task Not Found", + 500: "Internal Server Error", + } + ) def post(self, app_model: App, end_user: EndUser, task_id: str): """ Stop workflow task