mirror of
https://github.com/langgenius/dify.git
synced 2026-10-04 13:47:55 +08:00
feat(openapi): publish the op catalog, per-mode run ops and server-built hints on /openapi/v1 (#42487)
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
This commit is contained in:
1 parent
dced031c95
commit
dfc3bbe513
75 files changed
+3324
-803
No files matched your search
@@ -6,8 +6,14 @@ from werkzeug.exceptions import Forbidden
|
||||
|
||||
from controllers.common.rbac import PlainApp, RBACCheck, RBACPermission, Workspace
|
||||
from controllers.openapi import openapi_ns
|
||||
from controllers.openapi._contract import endpoint
|
||||
from controllers.openapi._models import AppDslExportQuery, AppDslExportResponse, AppDslImportPayload
|
||||
from controllers.openapi._contract import Example, Kind, endpoint, op_of
|
||||
from controllers.openapi._models import (
|
||||
AppDslExportQuery,
|
||||
AppDslExportResponse,
|
||||
AppDslImportPayload,
|
||||
AppDslImportResponse,
|
||||
Hint,
|
||||
)
|
||||
from controllers.openapi.auth.context import Context
|
||||
from controllers.openapi.auth.requirements import (
|
||||
CheckAppApiEnabled,
|
||||
@@ -27,6 +33,19 @@ from services.errors.account import NoPermissionError
|
||||
from services.errors.app import WorkflowNotFoundError
|
||||
|
||||
|
||||
def _import_response(result: Import, *, workspace_id: str) -> AppDslImportResponse:
|
||||
hints: list[Hint] = []
|
||||
if result.status == ImportStatus.PENDING:
|
||||
hints.append(
|
||||
Hint(
|
||||
summary="Confirm the pending import",
|
||||
op=op_of(AppDslImportConfirmApi.post),
|
||||
input={"workspace_id": workspace_id, "import_id": result.id},
|
||||
)
|
||||
)
|
||||
return AppDslImportResponse(**result.model_dump(), hints=hints)
|
||||
|
||||
|
||||
@openapi_ns.route("/workspaces/<string:workspace_id>/apps/imports")
|
||||
class AppDslImportApi(Resource):
|
||||
"""Import a DSL YAML string into the specified workspace.
|
||||
@@ -42,6 +61,23 @@ class AppDslImportApi(Resource):
|
||||
"""
|
||||
|
||||
@endpoint(
|
||||
op="console_app.dsl.import",
|
||||
kind=Kind.OBJECT,
|
||||
summary="Import an app from DSL text or URL",
|
||||
examples=(
|
||||
Example(
|
||||
title="Import an app from inline YAML",
|
||||
input={"mode": "yaml-content", "yaml_content": "<yaml text of the app DSL>"},
|
||||
),
|
||||
Example(
|
||||
title="Import an app from a URL",
|
||||
input={"mode": "yaml-url", "yaml_url": "https://example.com/apps/release-summary.yml"},
|
||||
),
|
||||
Example(
|
||||
title="Overwrite an existing workflow app from YAML",
|
||||
input={"mode": "yaml-content", "yaml_content": "<yaml text of the app DSL>", "app_id": "<app_id>"},
|
||||
),
|
||||
),
|
||||
requirements=(
|
||||
CheckSubject(allowed=(AccountSubject,)),
|
||||
CheckScope(Scope.WORKSPACE_WRITE),
|
||||
@@ -51,9 +87,9 @@ class AppDslImportApi(Resource):
|
||||
),
|
||||
body=AppDslImportPayload,
|
||||
returns=(
|
||||
(200, Import, "Import completed"),
|
||||
(202, Import, "Import pending confirmation"),
|
||||
(400, Import, "Import failed"),
|
||||
(200, AppDslImportResponse, "Import completed"),
|
||||
(202, AppDslImportResponse, "Import pending confirmation"),
|
||||
(400, AppDslImportResponse, "Import failed"),
|
||||
),
|
||||
)
|
||||
def post(self, ctx: Context, workspace_id: str, *, body: AppDslImportPayload):
|
||||
@@ -81,13 +117,14 @@ class AppDslImportApi(Resource):
|
||||
else:
|
||||
session.commit()
|
||||
|
||||
response = _import_response(result, workspace_id=workspace_id)
|
||||
match result.status:
|
||||
case ImportStatus.FAILED:
|
||||
return result, 400
|
||||
return response, 400
|
||||
case ImportStatus.PENDING:
|
||||
return result, 202
|
||||
return response, 202
|
||||
case _:
|
||||
return result, 200
|
||||
return response, 200
|
||||
|
||||
|
||||
@openapi_ns.route("/workspaces/<string:workspace_id>/apps/imports/<string:import_id>:confirm")
|
||||
@@ -103,6 +140,10 @@ class AppDslImportConfirmApi(Resource):
|
||||
"""
|
||||
|
||||
@endpoint(
|
||||
op="console_app.dsl.import_confirm",
|
||||
kind=Kind.OBJECT,
|
||||
summary="Confirm a pending DSL import",
|
||||
examples=(Example(title="Confirm an import that is pending confirmation", input={"import_id": "<import_id>"}),),
|
||||
requirements=(
|
||||
CheckSubject(allowed=(AccountSubject,)),
|
||||
CheckScope(Scope.WORKSPACE_WRITE),
|
||||
@@ -145,6 +186,16 @@ class AppDslExportApi(Resource):
|
||||
"""
|
||||
|
||||
@endpoint(
|
||||
op="console_app.dsl.export",
|
||||
kind=Kind.OBJECT,
|
||||
summary="Export app DSL as YAML text inside a JSON object",
|
||||
examples=(
|
||||
Example(title="Export the current draft as YAML", input={"app_id": "<app_id>"}),
|
||||
Example(
|
||||
title="Export a published version including secrets",
|
||||
input={"app_id": "<app_id>", "workflow_id": "<workflow_id>", "include_secret": True},
|
||||
),
|
||||
),
|
||||
requirements=(
|
||||
CheckSubject(allowed=(AccountSubject,)),
|
||||
CheckAppApiEnabled(),
|
||||
@@ -180,6 +231,10 @@ class AppDslCheckDependenciesApi(Resource):
|
||||
"""
|
||||
|
||||
@endpoint(
|
||||
op="console_app.dependencies.check",
|
||||
kind=Kind.OBJECT,
|
||||
summary="Check plugin dependencies of an app",
|
||||
examples=(Example(title="Check which plugins an app needs", input={"app_id": "<app_id>"}),),
|
||||
requirements=(
|
||||
CheckSubject(allowed=(AccountSubject,)),
|
||||
CheckAppApiEnabled(),
|
||||
|
||||
Reference in new issue
Block a user