Underground-Digital/Workflow-Engine
0
1import uuid2 3from flask_login import current_user4from flask_restful import Resource, inputs, marshal, marshal_with, reqparse5from werkzeug.exceptions import BadRequest, Forbidden, abort6 7from controllers.console import api8from controllers.console.app.wraps import get_app_model9from controllers.console.wraps import (10 account_initialization_required,11 cloud_edition_billing_resource_check,12 setup_required,13)14from core.ops.ops_trace_manager import OpsTraceManager15from fields.app_fields import (16 app_detail_fields,17 app_detail_fields_with_site,18 app_pagination_fields,19)20from libs.login import login_required21from services.app_dsl_service import AppDslService22from services.app_service import AppService23 24ALLOW_CREATE_APP_MODES = ["chat", "agent-chat", "advanced-chat", "workflow", "completion"]25 26 27class AppListApi(Resource):28 @setup_required29 @login_required30 @account_initialization_required31 def get(self):32 """Get app list"""33 34 def uuid_list(value):35 try:36 return [str(uuid.UUID(v)) for v in value.split(",")]37 except ValueError:38 abort(400, message="Invalid UUID format in tag_ids.")39 40 parser = reqparse.RequestParser()41 parser.add_argument("page", type=inputs.int_range(1, 99999), required=False, default=1, location="args")42 parser.add_argument("limit", type=inputs.int_range(1, 100), required=False, default=20, location="args")43 parser.add_argument(44 "mode",45 type=str,46 choices=["chat", "workflow", "agent-chat", "channel", "all"],47 default="all",48 location="args",49 required=False,50 )51 parser.add_argument("name", type=str, location="args", required=False)52 parser.add_argument("tag_ids", type=uuid_list, location="args", required=False)53 54 args = parser.parse_args()55 56 # get app list57 app_service = AppService()58 app_pagination = app_service.get_paginate_apps(current_user.current_tenant_id, args)59 if not app_pagination:60 return {"data": [], "total": 0, "page": 1, "limit": 20, "has_more": False}61 62 return marshal(app_pagination, app_pagination_fields)63 64 @setup_required65 @login_required66 @account_initialization_required67 @marshal_with(app_detail_fields)68 @cloud_edition_billing_resource_check("apps")69 def post(self):70 """Create app"""71 parser = reqparse.RequestParser()72 parser.add_argument("name", type=str, required=True, location="json")73 parser.add_argument("description", type=str, location="json")74 parser.add_argument("mode", type=str, choices=ALLOW_CREATE_APP_MODES, location="json")75 parser.add_argument("icon_type", type=str, location="json")76 parser.add_argument("icon", type=str, location="json")77 parser.add_argument("icon_background", type=str, location="json")78 args = parser.parse_args()79 80 # The role of the current user in the ta table must be admin, owner, or editor81 if not current_user.is_editor:82 raise Forbidden()83 84 if "mode" not in args or args["mode"] is None:85 raise BadRequest("mode is required")86 87 app_service = AppService()88 app = app_service.create_app(current_user.current_tenant_id, args, current_user)89 90 return app, 20191 92 93class AppImportApi(Resource):94 @setup_required95 @login_required96 @account_initialization_required97 @marshal_with(app_detail_fields_with_site)98 @cloud_edition_billing_resource_check("apps")99 def post(self):100 """Import app"""101 # The role of the current user in the ta table must be admin, owner, or editor102 if not current_user.is_editor:103 raise Forbidden()104 105 parser = reqparse.RequestParser()106 parser.add_argument("data", type=str, required=True, nullable=False, location="json")107 parser.add_argument("name", type=str, location="json")108 parser.add_argument("description", type=str, location="json")109 parser.add_argument("icon_type", type=str, location="json")110 parser.add_argument("icon", type=str, location="json")111 parser.add_argument("icon_background", type=str, location="json")112 args = parser.parse_args()113 114 app = AppDslService.import_and_create_new_app(115 tenant_id=current_user.current_tenant_id, data=args["data"], args=args, account=current_user116 )117 118 return app, 201119 120 121class AppImportFromUrlApi(Resource):122 @setup_required123 @login_required124 @account_initialization_required125 @marshal_with(app_detail_fields_with_site)126 @cloud_edition_billing_resource_check("apps")127 def post(self):128 """Import app from url"""129 # The role of the current user in the ta table must be admin, owner, or editor130 if not current_user.is_editor:131 raise Forbidden()132 133 parser = reqparse.RequestParser()134 parser.add_argument("url", type=str, required=True, nullable=False, location="json")135 parser.add_argument("name", type=str, location="json")136 parser.add_argument("description", type=str, location="json")137 parser.add_argument("icon", type=str, location="json")138 parser.add_argument("icon_background", type=str, location="json")139 args = parser.parse_args()140 141 app = AppDslService.import_and_create_new_app_from_url(142 tenant_id=current_user.current_tenant_id, url=args["url"], args=args, account=current_user143 )144 145 return app, 201146 147 148class AppApi(Resource):149 @setup_required150 @login_required151 @account_initialization_required152 @get_app_model153 @marshal_with(app_detail_fields_with_site)154 def get(self, app_model):155 """Get app detail"""156 app_service = AppService()157 158 app_model = app_service.get_app(app_model)159 160 return app_model161 162 @setup_required163 @login_required164 @account_initialization_required165 @get_app_model166 @marshal_with(app_detail_fields_with_site)167 def put(self, app_model):168 """Update app"""169 # The role of the current user in the ta table must be admin, owner, or editor170 if not current_user.is_editor:171 raise Forbidden()172 173 parser = reqparse.RequestParser()174 parser.add_argument("name", type=str, required=True, nullable=False, location="json")175 parser.add_argument("description", type=str, location="json")176 parser.add_argument("icon_type", type=str, location="json")177 parser.add_argument("icon", type=str, location="json")178 parser.add_argument("icon_background", type=str, location="json")179 parser.add_argument("max_active_requests", type=int, location="json")180 parser.add_argument("use_icon_as_answer_icon", type=bool, location="json")181 args = parser.parse_args()182 183 app_service = AppService()184 app_model = app_service.update_app(app_model, args)185 186 return app_model187 188 @setup_required189 @login_required190 @account_initialization_required191 @get_app_model192 def delete(self, app_model):193 """Delete app"""194 # The role of the current user in the ta table must be admin, owner, or editor195 if not current_user.is_editor:196 raise Forbidden()197 198 app_service = AppService()199 app_service.delete_app(app_model)200 201 return {"result": "success"}, 204202 203 204class AppCopyApi(Resource):205 @setup_required206 @login_required207 @account_initialization_required208 @get_app_model209 @marshal_with(app_detail_fields_with_site)210 def post(self, app_model):211 """Copy app"""212 # The role of the current user in the ta table must be admin, owner, or editor213 if not current_user.is_editor:214 raise Forbidden()215 216 parser = reqparse.RequestParser()217 parser.add_argument("name", type=str, location="json")218 parser.add_argument("description", type=str, location="json")219 parser.add_argument("icon_type", type=str, location="json")220 parser.add_argument("icon", type=str, location="json")221 parser.add_argument("icon_background", type=str, location="json")222 args = parser.parse_args()223 224 data = AppDslService.export_dsl(app_model=app_model, include_secret=True)225 app = AppDslService.import_and_create_new_app(226 tenant_id=current_user.current_tenant_id, data=data, args=args, account=current_user227 )228 229 return app, 201230 231 232class AppExportApi(Resource):233 @setup_required234 @login_required235 @account_initialization_required236 @get_app_model237 def get(self, app_model):238 """Export app"""239 # The role of the current user in the ta table must be admin, owner, or editor240 if not current_user.is_editor:241 raise Forbidden()242 243 # Add include_secret params244 parser = reqparse.RequestParser()245 parser.add_argument("include_secret", type=inputs.boolean, default=False, location="args")246 args = parser.parse_args()247 248 return {"data": AppDslService.export_dsl(app_model=app_model, include_secret=args["include_secret"])}249 250 251class AppNameApi(Resource):252 @setup_required253 @login_required254 @account_initialization_required255 @get_app_model256 @marshal_with(app_detail_fields)257 def post(self, app_model):258 # The role of the current user in the ta table must be admin, owner, or editor259 if not current_user.is_editor:260 raise Forbidden()261 262 parser = reqparse.RequestParser()263 parser.add_argument("name", type=str, required=True, location="json")264 args = parser.parse_args()265 266 app_service = AppService()267 app_model = app_service.update_app_name(app_model, args.get("name"))268 269 return app_model270 271 272class AppIconApi(Resource):273 @setup_required274 @login_required275 @account_initialization_required276 @get_app_model277 @marshal_with(app_detail_fields)278 def post(self, app_model):279 # The role of the current user in the ta table must be admin, owner, or editor280 if not current_user.is_editor:281 raise Forbidden()282 283 parser = reqparse.RequestParser()284 parser.add_argument("icon", type=str, location="json")285 parser.add_argument("icon_background", type=str, location="json")286 args = parser.parse_args()287 288 app_service = AppService()289 app_model = app_service.update_app_icon(app_model, args.get("icon"), args.get("icon_background"))290 291 return app_model292 293 294class AppSiteStatus(Resource):295 @setup_required296 @login_required297 @account_initialization_required298 @get_app_model299 @marshal_with(app_detail_fields)300 def post(self, app_model):301 # The role of the current user in the ta table must be admin, owner, or editor302 if not current_user.is_editor:303 raise Forbidden()304 305 parser = reqparse.RequestParser()306 parser.add_argument("enable_site", type=bool, required=True, location="json")307 args = parser.parse_args()308 309 app_service = AppService()310 app_model = app_service.update_app_site_status(app_model, args.get("enable_site"))311 312 return app_model313 314 315class AppApiStatus(Resource):316 @setup_required317 @login_required318 @account_initialization_required319 @get_app_model320 @marshal_with(app_detail_fields)321 def post(self, app_model):322 # The role of the current user in the ta table must be admin or owner323 if not current_user.is_admin_or_owner:324 raise Forbidden()325 326 parser = reqparse.RequestParser()327 parser.add_argument("enable_api", type=bool, required=True, location="json")328 args = parser.parse_args()329 330 app_service = AppService()331 app_model = app_service.update_app_api_status(app_model, args.get("enable_api"))332 333 return app_model334 335 336class AppTraceApi(Resource):337 @setup_required338 @login_required339 @account_initialization_required340 def get(self, app_id):341 """Get app trace"""342 app_trace_config = OpsTraceManager.get_app_tracing_config(app_id=app_id)343 344 return app_trace_config345 346 @setup_required347 @login_required348 @account_initialization_required349 def post(self, app_id):350 # add app trace351 if not current_user.is_admin_or_owner:352 raise Forbidden()353 parser = reqparse.RequestParser()354 parser.add_argument("enabled", type=bool, required=True, location="json")355 parser.add_argument("tracing_provider", type=str, required=True, location="json")356 args = parser.parse_args()357 358 OpsTraceManager.update_app_tracing_config(359 app_id=app_id,360 enabled=args["enabled"],361 tracing_provider=args["tracing_provider"],362 )363 364 return {"result": "success"}365 366 367api.add_resource(AppListApi, "/apps")368api.add_resource(AppImportApi, "/apps/import")369api.add_resource(AppImportFromUrlApi, "/apps/import/url")370api.add_resource(AppApi, "/apps/<uuid:app_id>")371api.add_resource(AppCopyApi, "/apps/<uuid:app_id>/copy")372api.add_resource(AppExportApi, "/apps/<uuid:app_id>/export")373api.add_resource(AppNameApi, "/apps/<uuid:app_id>/name")374api.add_resource(AppIconApi, "/apps/<uuid:app_id>/icon")375api.add_resource(AppSiteStatus, "/apps/<uuid:app_id>/site-enable")376api.add_resource(AppApiStatus, "/apps/<uuid:app_id>/api-enable")377api.add_resource(AppTraceApi, "/apps/<uuid:app_id>/trace")378 