From 6eac228dd8a4557a5e089930dbdc30bd688de5e8 Mon Sep 17 00:00:00 2001 From: chariri Date: Fri, 26 Jun 2026 03:25:27 +0900 Subject: [PATCH 1/2] refactor(api): migrate workspace model endpoints to BaseModel --- api/controllers/common/fields.py | 7 +- .../console/workspace/model_providers.py | 62 +- api/controllers/console/workspace/models.py | 131 +-- api/controllers/console/workspace/plugin.py | 49 +- api/openapi/markdown/console-openapi.md | 702 +++++++++++-- .../console/workspace/test_model_providers.py | 222 ++++- .../console/workspace/test_models.py | 11 +- .../console/workspace/test_plugin.py | 273 ++++- .../generated/api/console/apps/types.gen.ts | 459 ++++++++- .../generated/api/console/apps/zod.gen.ts | 767 ++++++++++++++- .../generated/api/console/rag/types.gen.ts | 459 ++++++++- .../generated/api/console/rag/zod.gen.ts | 767 ++++++++++++++- .../api/console/workspaces/orpc.gen.ts | 36 +- .../api/console/workspaces/types.gen.ts | 556 +++++++++-- .../api/console/workspaces/zod.gen.ts | 931 +++++++++++++++--- packages/contracts/openapi-ts.api.config.ts | 78 +- 16 files changed, 4964 insertions(+), 546 deletions(-) diff --git a/api/controllers/common/fields.py b/api/controllers/common/fields.py index 6a0b35aa633..2ea61ca1eca 100644 --- a/api/controllers/common/fields.py +++ b/api/controllers/common/fields.py @@ -1,6 +1,6 @@ from __future__ import annotations -from typing import Any +from typing import Any, Literal from pydantic import BaseModel, ConfigDict, Field, RootModel, computed_field @@ -52,6 +52,11 @@ class AudioTranscriptResponse(ResponseModel): text: str +class ValidationResultResponse(ResponseModel): + result: Literal["success", "error"] + error: str | None = None + + class SimpleResultMessageResponse(ResponseModel): result: str message: str diff --git a/api/controllers/console/workspace/model_providers.py b/api/controllers/console/workspace/model_providers.py index 3ce7211703e..761c6f03269 100644 --- a/api/controllers/console/workspace/model_providers.py +++ b/api/controllers/console/workspace/model_providers.py @@ -5,7 +5,7 @@ from flask import request, send_file from flask_restx import Resource from pydantic import BaseModel, Field, field_validator -from controllers.common.fields import BinaryFileResponse, SimpleResultResponse +from controllers.common.fields import SimpleResultResponse, ValidationResultResponse from controllers.common.schema import query_params_from_model, register_response_schema_models, register_schema_models from controllers.console import console_ns from controllers.console.wraps import ( @@ -21,8 +21,7 @@ from controllers.console.wraps import ( from fields.base import ResponseModel from graphon.model_runtime.entities.model_entities import ModelType from graphon.model_runtime.errors.validate import CredentialsValidateFailedError -from graphon.model_runtime.utils.encoders import jsonable_encoder -from libs.helper import uuid_value +from libs.helper import dump_response, uuid_value from libs.login import login_required from models import Account from services.billing_service import BillingService @@ -91,13 +90,8 @@ class ModelProviderListResponse(ResponseModel): data: list[ProviderResponse] -class ProviderCredentialResponse(ResponseModel): - credentials: dict[str, Any] | None = Field(default=None) - - -class ProviderCredentialValidateResponse(ResponseModel): - result: Literal["success", "error"] - error: str | None = None +class ProviderCredentialsResponse(ResponseModel): + credentials: dict[str, Any] | None = None class ModelProviderPaymentCheckoutUrlResponse(ResponseModel): @@ -117,19 +111,20 @@ register_schema_models( ) register_response_schema_models( console_ns, - BinaryFileResponse, SimpleResultResponse, ModelProviderListResponse, + ProviderCredentialsResponse, + ValidationResultResponse, ModelProviderPaymentCheckoutUrlResponse, - ProviderCredentialResponse, - ProviderCredentialValidateResponse, ) @console_ns.route("/workspaces/current/model-providers") class ModelProviderListApi(Resource): @console_ns.doc(params=query_params_from_model(ParserModelList)) - @console_ns.response(200, "Success", console_ns.models[ModelProviderListResponse.__name__]) + @console_ns.response( + 200, "Model providers retrieved successfully", console_ns.models[ModelProviderListResponse.__name__] + ) @setup_required @login_required @account_initialization_required @@ -141,13 +136,17 @@ class ModelProviderListApi(Resource): model_provider_service = ModelProviderService() provider_list = model_provider_service.get_provider_list(tenant_id=tenant_id, model_type=args.model_type) - return jsonable_encoder({"data": provider_list}) + return ModelProviderListResponse(data=provider_list).model_dump(mode="json") @console_ns.route("/workspaces/current/model-providers//credentials") class ModelProviderCredentialApi(Resource): @console_ns.doc(params=query_params_from_model(ParserCredentialId)) - @console_ns.response(200, "Success", console_ns.models[ProviderCredentialResponse.__name__]) + @console_ns.response( + 200, + "Provider credentials retrieved successfully", + console_ns.models[ProviderCredentialsResponse.__name__], + ) @setup_required @login_required @account_initialization_required @@ -162,7 +161,7 @@ class ModelProviderCredentialApi(Resource): tenant_id=tenant_id, provider=provider, credential_id=args.credential_id ) - return {"credentials": credentials} + return ProviderCredentialsResponse(credentials=credentials).model_dump(mode="json") @console_ns.expect(console_ns.models[ParserCredentialCreate.__name__]) @console_ns.response(201, "Credential created successfully", console_ns.models[SimpleResultResponse.__name__]) @@ -188,7 +187,7 @@ class ModelProviderCredentialApi(Resource): except CredentialsValidateFailedError as ex: raise ValueError(str(ex)) - return {"result": "success"}, 201 + return SimpleResultResponse(result="success").model_dump(mode="json"), 201 @console_ns.expect(console_ns.models[ParserCredentialUpdate.__name__]) @console_ns.response(200, "Credential updated successfully", console_ns.models[SimpleResultResponse.__name__]) @@ -215,7 +214,7 @@ class ModelProviderCredentialApi(Resource): except CredentialsValidateFailedError as ex: raise ValueError(str(ex)) - return {"result": "success"} + return SimpleResultResponse(result="success").model_dump(mode="json") @console_ns.expect(console_ns.models[ParserCredentialDelete.__name__]) @console_ns.response(204, "Credential deleted successfully") @@ -257,7 +256,7 @@ class ModelProviderCredentialSwitchApi(Resource): provider=provider, credential_id=args.credential_id, ) - return {"result": "success"} + return SimpleResultResponse(result="success").model_dump(mode="json") @console_ns.route("/workspaces/current/model-providers//credentials/validate") @@ -265,8 +264,8 @@ class ModelProviderValidateApi(Resource): @console_ns.expect(console_ns.models[ParserCredentialValidate.__name__]) @console_ns.response( 200, - "Credential validation result", - console_ns.models[ProviderCredentialValidateResponse.__name__], + "Provider credentials validated successfully", + console_ns.models[ValidationResultResponse.__name__], ) @setup_required @login_required @@ -291,12 +290,10 @@ class ModelProviderValidateApi(Resource): result = False error = str(ex) - response = {"result": "success" if result else "error"} - if not result: - response["error"] = error or "Unknown error" + return ValidationResultResponse(result="error", error=error or "Unknown error").model_dump(mode="json") - return response + return ValidationResultResponse(result="success").model_dump(mode="json") @console_ns.route("/workspaces//model-providers///") @@ -305,8 +302,9 @@ class ModelProviderIconApi(Resource): Get model provider icon """ - @console_ns.response(200, "Success", console_ns.models[BinaryFileResponse.__name__]) + @console_ns.response(200, "Model provider icon") def get(self, tenant_id: str, provider: str, icon_type: str, lang: str): + # response-contract:ignore binary send_file response model_provider_service = ModelProviderService() icon, mimetype = model_provider_service.get_model_provider_icon( tenant_id=tenant_id, @@ -338,12 +336,16 @@ class PreferredProviderTypeUpdateApi(Resource): tenant_id=tenant_id, provider=provider, preferred_provider_type=args.preferred_provider_type ) - return {"result": "success"} + return SimpleResultResponse(result="success").model_dump(mode="json") @console_ns.route("/workspaces/current/model-providers//checkout-url") class ModelProviderPaymentCheckoutUrlApi(Resource): - @console_ns.response(200, "Success", console_ns.models[ModelProviderPaymentCheckoutUrlResponse.__name__]) + @console_ns.response( + 200, + "Model provider checkout URL retrieved successfully", + console_ns.models[ModelProviderPaymentCheckoutUrlResponse.__name__], + ) @setup_required @login_required @account_initialization_required @@ -359,4 +361,4 @@ class ModelProviderPaymentCheckoutUrlApi(Resource): account_id=current_user.id, prefilled_email=current_user.email, ) - return data + return dump_response(ModelProviderPaymentCheckoutUrlResponse, data) diff --git a/api/controllers/console/workspace/models.py b/api/controllers/console/workspace/models.py index 1da72ef4362..52f86560de6 100644 --- a/api/controllers/console/workspace/models.py +++ b/api/controllers/console/workspace/models.py @@ -5,7 +5,7 @@ from flask import request from flask_restx import Resource from pydantic import BaseModel, Field, field_validator -from controllers.common.fields import SimpleResultResponse +from controllers.common.fields import SimpleResultResponse, ValidationResultResponse from controllers.common.schema import ( query_params_from_model, register_enum_models, @@ -27,7 +27,6 @@ from core.entities.provider_entities import CredentialConfiguration from fields.base import ResponseModel from graphon.model_runtime.entities.model_entities import ModelType, ParameterRule from graphon.model_runtime.errors.validate import CredentialsValidateFailedError -from graphon.model_runtime.utils.encoders import jsonable_encoder from libs.helper import uuid_value from libs.login import login_required from models import Account @@ -62,7 +61,7 @@ class ParserDeleteModels(BaseModel): class LoadBalancingPayload(BaseModel): - configs: list[dict[str, Any]] | None = Field(default=None) + configs: list[dict[str, Any]] | None = None enabled: bool | None = None @@ -139,33 +138,38 @@ class DefaultModelDataResponse(ResponseModel): data: DefaultModelResponse | None = None -class ModelWithProviderListResponse(ResponseModel): +class ProviderModelListResponse(ResponseModel): data: list[ModelWithProviderEntityResponse] -class ProviderWithModelsDataResponse(ResponseModel): +class AvailableModelListResponse(ResponseModel): data: list[ProviderWithModelsResponse] -class ModelCredentialLoadBalancingResponse(ResponseModel): +class ModelLoadBalancingConfigResponse(ResponseModel): + id: str + name: str + credentials: dict[str, Any] + credential_id: str | None = None enabled: bool - configs: list[dict[str, Any]] = Field(default_factory=list) + in_cooldown: bool + ttl: int + + +class ModelLoadBalancingResponse(ResponseModel): + enabled: bool + configs: list[ModelLoadBalancingConfigResponse] class ModelCredentialResponse(ResponseModel): - credentials: dict[str, Any] = Field(default_factory=dict) + credentials: dict[str, Any] current_credential_id: str | None = None current_credential_name: str | None = None - load_balancing: ModelCredentialLoadBalancingResponse + load_balancing: ModelLoadBalancingResponse available_credentials: list[CredentialConfiguration] -class ModelCredentialValidateResponse(ResponseModel): - result: str - error: str | None = None - - -class ModelParameterRulesResponse(ResponseModel): +class ModelParameterRuleListResponse(ResponseModel): data: list[ParameterRule] @@ -186,12 +190,12 @@ register_schema_models( register_response_schema_models( console_ns, SimpleResultResponse, + ValidationResultResponse, DefaultModelDataResponse, - ModelWithProviderListResponse, - ProviderWithModelsDataResponse, + ProviderModelListResponse, ModelCredentialResponse, - ModelCredentialValidateResponse, - ModelParameterRulesResponse, + ModelParameterRuleListResponse, + AvailableModelListResponse, ) register_enum_models(console_ns, ModelType) @@ -200,7 +204,9 @@ register_enum_models(console_ns, ModelType) @console_ns.route("/workspaces/current/default-model") class DefaultModelApi(Resource): @console_ns.doc(params=query_params_from_model(ParserGetDefault)) - @console_ns.response(200, "Success", console_ns.models[DefaultModelDataResponse.__name__]) + @console_ns.response( + 200, "Default model retrieved successfully", console_ns.models[DefaultModelDataResponse.__name__] + ) @setup_required @login_required @account_initialization_required @@ -213,7 +219,7 @@ class DefaultModelApi(Resource): tenant_id=tenant_id, model_type=args.model_type ) - return jsonable_encoder({"data": default_model_entity}) + return DefaultModelDataResponse(data=default_model_entity).model_dump(mode="json") @console_ns.expect(console_ns.models[ParserPostDefault.__name__]) @console_ns.response(200, "Success", console_ns.models[SimpleResultResponse.__name__]) @@ -246,12 +252,14 @@ class DefaultModelApi(Resource): ) raise ex - return {"result": "success"} + return SimpleResultResponse(result="success").model_dump(mode="json") @console_ns.route("/workspaces/current/model-providers//models") class ModelProviderModelApi(Resource): - @console_ns.response(200, "Success", console_ns.models[ModelWithProviderListResponse.__name__]) + @console_ns.response( + 200, "Provider models retrieved successfully", console_ns.models[ProviderModelListResponse.__name__] + ) @setup_required @login_required @account_initialization_required @@ -260,10 +268,10 @@ class ModelProviderModelApi(Resource): model_provider_service = ModelProviderService() models = model_provider_service.get_models_by_provider(tenant_id=tenant_id, provider=provider) - return jsonable_encoder({"data": models}) + return ProviderModelListResponse(data=models).model_dump(mode="json") @console_ns.expect(console_ns.models[ParserPostModels.__name__]) - @console_ns.response(200, "Success", console_ns.models[SimpleResultResponse.__name__]) + @console_ns.response(200, "Model updated successfully", console_ns.models[SimpleResultResponse.__name__]) @setup_required @login_required @is_admin_or_owner_required @@ -308,7 +316,7 @@ class ModelProviderModelApi(Resource): tenant_id=tenant_id, provider=provider, model=args.model, model_type=args.model_type ) - return {"result": "success"}, 200 + return SimpleResultResponse(result="success").model_dump(mode="json"), 200 @console_ns.expect(console_ns.models[ParserDeleteModels.__name__]) @console_ns.response(204, "Model deleted successfully") @@ -332,7 +340,11 @@ class ModelProviderModelApi(Resource): @console_ns.route("/workspaces/current/model-providers//models/credentials") class ModelProviderModelCredentialApi(Resource): @console_ns.doc(params=query_params_from_model(ParserGetCredentials)) - @console_ns.response(200, "Success", console_ns.models[ModelCredentialResponse.__name__]) + @console_ns.response( + 200, + "Model credentials retrieved successfully", + console_ns.models[ModelCredentialResponse.__name__], + ) @setup_required @login_required @account_initialization_required @@ -376,22 +388,23 @@ class ModelProviderModelCredentialApi(Resource): model=args.model, ) - return jsonable_encoder( - { - "credentials": current_credential.get("credentials") if current_credential else {}, - "current_credential_id": current_credential.get("current_credential_id") - if current_credential - else None, - "current_credential_name": current_credential.get("current_credential_name") - if current_credential - else None, - "load_balancing": {"enabled": is_load_balancing_enabled, "configs": load_balancing_configs}, - "available_credentials": available_credentials, - } - ) + credentials: dict[str, Any] = {} + # TODO: make this throw error when type mismatches? + if current_credential and isinstance(current_credential.get("credentials"), dict): + credentials = cast(dict[str, Any], current_credential["credentials"]) + + return ModelCredentialResponse( + credentials=credentials, + current_credential_id=current_credential.get("current_credential_id") if current_credential else None, + current_credential_name=current_credential.get("current_credential_name") if current_credential else None, + load_balancing=ModelLoadBalancingResponse.model_validate( + {"enabled": is_load_balancing_enabled, "configs": load_balancing_configs} + ), + available_credentials=available_credentials, + ).model_dump(mode="json") @console_ns.expect(console_ns.models[ParserCreateCredential.__name__]) - @console_ns.response(201, "Credential created successfully", console_ns.models[SimpleResultResponse.__name__]) + @console_ns.response(201, "Model credential created successfully", console_ns.models[SimpleResultResponse.__name__]) @setup_required @login_required @is_admin_or_owner_required @@ -421,10 +434,10 @@ class ModelProviderModelCredentialApi(Resource): ) raise ValueError(str(ex)) - return {"result": "success"}, 201 + return SimpleResultResponse(result="success").model_dump(mode="json"), 201 @console_ns.expect(console_ns.models[ParserUpdateCredential.__name__]) - @console_ns.response(200, "Credential updated successfully", console_ns.models[SimpleResultResponse.__name__]) + @console_ns.response(200, "Model credential updated successfully", console_ns.models[SimpleResultResponse.__name__]) @setup_required @login_required @is_admin_or_owner_required @@ -449,7 +462,7 @@ class ModelProviderModelCredentialApi(Resource): except CredentialsValidateFailedError as ex: raise ValueError(str(ex)) - return {"result": "success"} + return SimpleResultResponse(result="success").model_dump(mode="json") @console_ns.expect(console_ns.models[ParserDeleteCredential.__name__]) @console_ns.response(204, "Credential deleted successfully") @@ -495,7 +508,7 @@ class ModelProviderModelCredentialSwitchApi(Resource): model=args.model, credential_id=args.credential_id, ) - return {"result": "success"} + return SimpleResultResponse(result="success").model_dump(mode="json") @console_ns.route( @@ -517,7 +530,7 @@ class ModelProviderModelEnableApi(Resource): tenant_id=tenant_id, provider=provider, model=args.model, model_type=args.model_type ) - return {"result": "success"} + return SimpleResultResponse(result="success").model_dump(mode="json") @console_ns.route( @@ -539,7 +552,7 @@ class ModelProviderModelDisableApi(Resource): tenant_id=tenant_id, provider=provider, model=args.model, model_type=args.model_type ) - return {"result": "success"} + return SimpleResultResponse(result="success").model_dump(mode="json") class ParserValidate(BaseModel): @@ -556,8 +569,8 @@ class ModelProviderModelValidateApi(Resource): @console_ns.expect(console_ns.models[ParserValidate.__name__]) @console_ns.response( 200, - "Credential validation result", - console_ns.models[ModelCredentialValidateResponse.__name__], + "Model credentials validated successfully", + console_ns.models[ValidationResultResponse.__name__], ) @setup_required @login_required @@ -583,18 +596,20 @@ class ModelProviderModelValidateApi(Resource): result = False error = str(ex) - response = {"result": "success" if result else "error"} - if not result: - response["error"] = error or "" + return ValidationResultResponse(result="error", error=error or "").model_dump(mode="json") - return response + return ValidationResultResponse(result="success").model_dump(mode="json") @console_ns.route("/workspaces/current/model-providers//models/parameter-rules") class ModelProviderModelParameterRuleApi(Resource): @console_ns.doc(params=query_params_from_model(ParserParameter)) - @console_ns.response(200, "Success", console_ns.models[ModelParameterRulesResponse.__name__]) + @console_ns.response( + 200, + "Model parameter rules retrieved successfully", + console_ns.models[ModelParameterRuleListResponse.__name__], + ) @setup_required @login_required @account_initialization_required @@ -607,12 +622,14 @@ class ModelProviderModelParameterRuleApi(Resource): tenant_id=tenant_id, provider=provider, model=args.model ) - return jsonable_encoder({"data": parameter_rules}) + return ModelParameterRuleListResponse(data=parameter_rules).model_dump(mode="json") @console_ns.route("/workspaces/current/models/model-types/") class ModelProviderAvailableModelApi(Resource): - @console_ns.response(200, "Success", console_ns.models[ProviderWithModelsDataResponse.__name__]) + @console_ns.response( + 200, "Available models retrieved successfully", console_ns.models[AvailableModelListResponse.__name__] + ) @setup_required @login_required @account_initialization_required @@ -621,4 +638,4 @@ class ModelProviderAvailableModelApi(Resource): model_provider_service = ModelProviderService() models = model_provider_service.get_models_by_model_type(tenant_id=tenant_id, model_type=model_type) - return jsonable_encoder({"data": models}) + return AvailableModelListResponse(data=models).model_dump(mode="json") diff --git a/api/controllers/console/workspace/plugin.py b/api/controllers/console/workspace/plugin.py index bcc1bb67459..161fc3ecd92 100644 --- a/api/controllers/console/workspace/plugin.py +++ b/api/controllers/console/workspace/plugin.py @@ -31,7 +31,16 @@ from controllers.console.wraps import ( with_current_user_id, ) from core.helper.position_helper import is_filtered -from core.plugin.entities.plugin import PluginCategory, PluginInstallationSource +from core.plugin.entities.bundle import PluginBundleDependency +from core.plugin.entities.parameters import PluginParameterOption +from core.plugin.entities.plugin import ( + PluginCategory, + PluginDeclaration, + PluginEntity, + PluginInstallation, + PluginInstallationSource, +) +from core.plugin.entities.plugin_daemon import PluginDecodeResponse, PluginInstallTask, PluginInstallTaskStartResponse from core.plugin.impl.exc import PluginDaemonClientSideError from core.plugin.plugin_service import PluginService from core.tools.builtin_tool.providers._positions import BuiltinToolProviderSort @@ -292,33 +301,33 @@ class PluginCategoryListResponse(ResponseModel): has_more: bool -class PluginDaemonOperationResponse(RootModel[Any]): - root: Any +class PluginBundleUploadResponse(RootModel[list[PluginBundleDependency]]): + pass class PluginListResponse(ResponseModel): - plugins: Any + plugins: list[PluginEntity] total: int class PluginVersionsResponse(ResponseModel): - versions: Any + versions: Mapping[str, PluginService.LatestPluginCache | None] class PluginInstallationsResponse(ResponseModel): - plugins: Any + plugins: list[PluginInstallation] class PluginManifestResponse(ResponseModel): - manifest: Any + manifest: PluginDeclaration class PluginTasksResponse(ResponseModel): - tasks: Any + tasks: list[PluginInstallTask] class PluginTaskResponse(ResponseModel): - task: Any + task: PluginInstallTask class PluginPermissionResponse(ResponseModel): @@ -327,7 +336,7 @@ class PluginPermissionResponse(ResponseModel): class PluginDynamicOptionsResponse(ResponseModel): - options: Any + options: list[PluginParameterOption] class PluginOperationSuccessResponse(ResponseModel): @@ -374,10 +383,12 @@ register_response_schema_models( PluginCategoryBuiltinToolResponse, PluginCategoryInstalledPluginResponse, PluginCategoryListResponse, - PluginDaemonOperationResponse, + PluginBundleUploadResponse, + PluginDecodeResponse, PluginDebuggingKeyResponse, PluginDynamicOptionsResponse, PluginInstallationsResponse, + PluginInstallTaskStartResponse, PluginListResponse, PluginManifestResponse, PluginOperationSuccessResponse, @@ -611,7 +622,7 @@ class PluginAssetApi(Resource): @console_ns.route("/workspaces/current/plugin/upload/pkg") class PluginUploadFromPkgApi(Resource): - @console_ns.response(200, "Success", console_ns.models[PluginDaemonOperationResponse.__name__]) + @console_ns.response(200, "Success", console_ns.models[PluginDecodeResponse.__name__]) @setup_required @login_required @account_initialization_required @@ -632,7 +643,7 @@ class PluginUploadFromPkgApi(Resource): @console_ns.route("/workspaces/current/plugin/upload/github") class PluginUploadFromGithubApi(Resource): @console_ns.expect(console_ns.models[ParserGithubUpload.__name__]) - @console_ns.response(200, "Success", console_ns.models[PluginDaemonOperationResponse.__name__]) + @console_ns.response(200, "Success", console_ns.models[PluginDecodeResponse.__name__]) @setup_required @login_required @account_initialization_required @@ -652,7 +663,7 @@ class PluginUploadFromGithubApi(Resource): @console_ns.route("/workspaces/current/plugin/upload/bundle") class PluginUploadFromBundleApi(Resource): - @console_ns.response(200, "Success", console_ns.models[PluginDaemonOperationResponse.__name__]) + @console_ns.response(200, "Success", console_ns.models[PluginBundleUploadResponse.__name__]) @setup_required @login_required @account_initialization_required @@ -673,7 +684,7 @@ class PluginUploadFromBundleApi(Resource): @console_ns.route("/workspaces/current/plugin/install/pkg") class PluginInstallFromPkgApi(Resource): @console_ns.expect(console_ns.models[ParserPluginIdentifiers.__name__]) - @console_ns.response(200, "Success", console_ns.models[PluginDaemonOperationResponse.__name__]) + @console_ns.response(200, "Success", console_ns.models[PluginInstallTaskStartResponse.__name__]) @setup_required @login_required @account_initialization_required @@ -694,7 +705,7 @@ class PluginInstallFromPkgApi(Resource): @console_ns.route("/workspaces/current/plugin/install/github") class PluginInstallFromGithubApi(Resource): @console_ns.expect(console_ns.models[ParserGithubInstall.__name__]) - @console_ns.response(200, "Success", console_ns.models[PluginDaemonOperationResponse.__name__]) + @console_ns.response(200, "Success", console_ns.models[PluginInstallTaskStartResponse.__name__]) @setup_required @login_required @account_initialization_required @@ -721,7 +732,7 @@ class PluginInstallFromGithubApi(Resource): @console_ns.route("/workspaces/current/plugin/install/marketplace") class PluginInstallFromMarketplaceApi(Resource): @console_ns.expect(console_ns.models[ParserPluginIdentifiers.__name__]) - @console_ns.response(200, "Success", console_ns.models[PluginDaemonOperationResponse.__name__]) + @console_ns.response(200, "Success", console_ns.models[PluginInstallTaskStartResponse.__name__]) @setup_required @login_required @account_initialization_required @@ -867,7 +878,7 @@ class PluginDeleteInstallTaskItemApi(Resource): @console_ns.route("/workspaces/current/plugin/upgrade/marketplace") class PluginUpgradeFromMarketplaceApi(Resource): @console_ns.expect(console_ns.models[ParserMarketplaceUpgrade.__name__]) - @console_ns.response(200, "Success", console_ns.models[PluginDaemonOperationResponse.__name__]) + @console_ns.response(200, "Success", console_ns.models[PluginInstallTaskStartResponse.__name__]) @setup_required @login_required @account_initialization_required @@ -890,7 +901,7 @@ class PluginUpgradeFromMarketplaceApi(Resource): @console_ns.route("/workspaces/current/plugin/upgrade/github") class PluginUpgradeFromGithubApi(Resource): @console_ns.expect(console_ns.models[ParserGithubUpgrade.__name__]) - @console_ns.response(200, "Success", console_ns.models[PluginDaemonOperationResponse.__name__]) + @console_ns.response(200, "Success", console_ns.models[PluginInstallTaskStartResponse.__name__]) @setup_required @login_required @account_initialization_required diff --git a/api/openapi/markdown/console-openapi.md b/api/openapi/markdown/console-openapi.md index b3a0b8a6a71..ed00df1f8ea 100644 --- a/api/openapi/markdown/console-openapi.md +++ b/api/openapi/markdown/console-openapi.md @@ -9281,7 +9281,7 @@ Increment snippet use count by 1 | Code | Description | Schema | | ---- | ----------- | ------ | -| 200 | Success | **application/json**: [DefaultModelDataResponse](#defaultmodeldataresponse)
| +| 200 | Default model retrieved successfully | **application/json**: [DefaultModelDataResponse](#defaultmodeldataresponse)
| ### [POST] /workspaces/current/default-model #### Request Body @@ -9580,7 +9580,7 @@ Update a plugin endpoint | Code | Description | Schema | | ---- | ----------- | ------ | -| 200 | Success | **application/json**: [ModelProviderListResponse](#modelproviderlistresponse)
| +| 200 | Model providers retrieved successfully | **application/json**: [ModelProviderListResponse](#modelproviderlistresponse)
| ### [GET] /workspaces/current/model-providers/{provider}/checkout-url #### Parameters @@ -9593,7 +9593,7 @@ Update a plugin endpoint | Code | Description | Schema | | ---- | ----------- | ------ | -| 200 | Success | **application/json**: [ModelProviderPaymentCheckoutUrlResponse](#modelproviderpaymentcheckouturlresponse)
| +| 200 | Model provider checkout URL retrieved successfully | **application/json**: [ModelProviderPaymentCheckoutUrlResponse](#modelproviderpaymentcheckouturlresponse)
| ### [DELETE] /workspaces/current/model-providers/{provider}/credentials #### Parameters @@ -9626,7 +9626,7 @@ Update a plugin endpoint | Code | Description | Schema | | ---- | ----------- | ------ | -| 200 | Success | **application/json**: [ProviderCredentialResponse](#providercredentialresponse)
| +| 200 | Provider credentials retrieved successfully | **application/json**: [ProviderCredentialsResponse](#providercredentialsresponse)
| ### [POST] /workspaces/current/model-providers/{provider}/credentials #### Parameters @@ -9702,7 +9702,7 @@ Update a plugin endpoint | Code | Description | Schema | | ---- | ----------- | ------ | -| 200 | Credential validation result | **application/json**: [ProviderCredentialValidateResponse](#providercredentialvalidateresponse)
| +| 200 | Provider credentials validated successfully | **application/json**: [ValidationResultResponse](#validationresultresponse)
| ### [DELETE] /workspaces/current/model-providers/{provider}/models #### Parameters @@ -9734,7 +9734,7 @@ Update a plugin endpoint | Code | Description | Schema | | ---- | ----------- | ------ | -| 200 | Success | **application/json**: [ModelWithProviderListResponse](#modelwithproviderlistresponse)
| +| 200 | Provider models retrieved successfully | **application/json**: [ProviderModelListResponse](#providermodellistresponse)
| ### [POST] /workspaces/current/model-providers/{provider}/models #### Parameters @@ -9753,7 +9753,7 @@ Update a plugin endpoint | Code | Description | Schema | | ---- | ----------- | ------ | -| 200 | Success | **application/json**: [SimpleResultResponse](#simpleresultresponse)
| +| 200 | Model updated successfully | **application/json**: [SimpleResultResponse](#simpleresultresponse)
| ### [DELETE] /workspaces/current/model-providers/{provider}/models/credentials #### Parameters @@ -9789,7 +9789,7 @@ Update a plugin endpoint | Code | Description | Schema | | ---- | ----------- | ------ | -| 200 | Success | **application/json**: [ModelCredentialResponse](#modelcredentialresponse)
| +| 200 | Model credentials retrieved successfully | **application/json**: [ModelCredentialResponse](#modelcredentialresponse)
| ### [POST] /workspaces/current/model-providers/{provider}/models/credentials #### Parameters @@ -9808,7 +9808,7 @@ Update a plugin endpoint | Code | Description | Schema | | ---- | ----------- | ------ | -| 201 | Credential created successfully | **application/json**: [SimpleResultResponse](#simpleresultresponse)
| +| 201 | Model credential created successfully | **application/json**: [SimpleResultResponse](#simpleresultresponse)
| ### [PUT] /workspaces/current/model-providers/{provider}/models/credentials #### Parameters @@ -9827,7 +9827,7 @@ Update a plugin endpoint | Code | Description | Schema | | ---- | ----------- | ------ | -| 200 | Credential updated successfully | **application/json**: [SimpleResultResponse](#simpleresultresponse)
| +| 200 | Model credential updated successfully | **application/json**: [SimpleResultResponse](#simpleresultresponse)
| ### [POST] /workspaces/current/model-providers/{provider}/models/credentials/switch #### Parameters @@ -9865,7 +9865,7 @@ Update a plugin endpoint | Code | Description | Schema | | ---- | ----------- | ------ | -| 200 | Credential validation result | **application/json**: [ModelCredentialValidateResponse](#modelcredentialvalidateresponse)
| +| 200 | Model credentials validated successfully | **application/json**: [ValidationResultResponse](#validationresultresponse)
| ### [PATCH] /workspaces/current/model-providers/{provider}/models/disable #### Parameters @@ -9956,7 +9956,7 @@ Update a plugin endpoint | Code | Description | Schema | | ---- | ----------- | ------ | -| 200 | Success | **application/json**: [ModelParameterRulesResponse](#modelparameterrulesresponse)
| +| 200 | Model parameter rules retrieved successfully | **application/json**: [ModelParameterRuleListResponse](#modelparameterrulelistresponse)
| ### [POST] /workspaces/current/model-providers/{provider}/preferred-provider-type #### Parameters @@ -9988,7 +9988,7 @@ Update a plugin endpoint | Code | Description | Schema | | ---- | ----------- | ------ | -| 200 | Success | **application/json**: [ProviderWithModelsDataResponse](#providerwithmodelsdataresponse)
| +| 200 | Available models retrieved successfully | **application/json**: [AvailableModelListResponse](#availablemodellistresponse)
| ### [GET] /workspaces/current/permission **Get workspace permission settings** @@ -10099,7 +10099,7 @@ Returns permission flags that control workspace features like member invitations | Code | Description | Schema | | ---- | ----------- | ------ | -| 200 | Success | **application/json**: [PluginDaemonOperationResponse](#plugindaemonoperationresponse)
| +| 200 | Success | **application/json**: [PluginInstallTaskStartResponse](#plugininstalltaskstartresponse)
| ### [POST] /workspaces/current/plugin/install/marketplace #### Request Body @@ -10112,7 +10112,7 @@ Returns permission flags that control workspace features like member invitations | Code | Description | Schema | | ---- | ----------- | ------ | -| 200 | Success | **application/json**: [PluginDaemonOperationResponse](#plugindaemonoperationresponse)
| +| 200 | Success | **application/json**: [PluginInstallTaskStartResponse](#plugininstalltaskstartresponse)
| ### [POST] /workspaces/current/plugin/install/pkg #### Request Body @@ -10125,7 +10125,7 @@ Returns permission flags that control workspace features like member invitations | Code | Description | Schema | | ---- | ----------- | ------ | -| 200 | Success | **application/json**: [PluginDaemonOperationResponse](#plugindaemonoperationresponse)
| +| 200 | Success | **application/json**: [PluginInstallTaskStartResponse](#plugininstalltaskstartresponse)
| ### [GET] /workspaces/current/plugin/list #### Parameters @@ -10332,7 +10332,7 @@ Returns permission flags that control workspace features like member invitations | Code | Description | Schema | | ---- | ----------- | ------ | -| 200 | Success | **application/json**: [PluginDaemonOperationResponse](#plugindaemonoperationresponse)
| +| 200 | Success | **application/json**: [PluginInstallTaskStartResponse](#plugininstalltaskstartresponse)
| ### [POST] /workspaces/current/plugin/upgrade/marketplace #### Request Body @@ -10345,14 +10345,14 @@ Returns permission flags that control workspace features like member invitations | Code | Description | Schema | | ---- | ----------- | ------ | -| 200 | Success | **application/json**: [PluginDaemonOperationResponse](#plugindaemonoperationresponse)
| +| 200 | Success | **application/json**: [PluginInstallTaskStartResponse](#plugininstalltaskstartresponse)
| ### [POST] /workspaces/current/plugin/upload/bundle #### Responses | Code | Description | Schema | | ---- | ----------- | ------ | -| 200 | Success | **application/json**: [PluginDaemonOperationResponse](#plugindaemonoperationresponse)
| +| 200 | Success | **application/json**: [PluginBundleUploadResponse](#pluginbundleuploadresponse)
| ### [POST] /workspaces/current/plugin/upload/github #### Request Body @@ -10365,14 +10365,14 @@ Returns permission flags that control workspace features like member invitations | Code | Description | Schema | | ---- | ----------- | ------ | -| 200 | Success | **application/json**: [PluginDaemonOperationResponse](#plugindaemonoperationresponse)
| +| 200 | Success | **application/json**: [PluginDecodeResponse](#plugindecoderesponse)
| ### [POST] /workspaces/current/plugin/upload/pkg #### Responses | Code | Description | Schema | | ---- | ----------- | ------ | -| 200 | Success | **application/json**: [PluginDaemonOperationResponse](#plugindaemonoperationresponse)
| +| 200 | Success | **application/json**: [PluginDecodeResponse](#plugindecoderesponse)
| ### [GET] /workspaces/current/plugin/{category}/list #### Parameters @@ -11786,9 +11786,9 @@ Returns permission flags that control workspace features like member invitations #### Responses -| Code | Description | Schema | -| ---- | ----------- | ------ | -| 200 | Success | **application/json**: [BinaryFileResponse](#binaryfileresponse)
| +| Code | Description | +| ---- | ----------- | +| 200 | Model provider icon | --- ## default @@ -11812,6 +11812,22 @@ Default namespace --- ### Schemas +#### AIModelEntity + +Model class for AI model. + +| Name | Type | Description | Required | +| ---- | ---- | ----------- | -------- | +| deprecated | boolean | | No | +| features | [ [ModelFeature](#modelfeature) ] | | No | +| fetch_from | [FetchFrom](#fetchfrom) | | Yes | +| label | [graphon__model_runtime__entities__common_entities__I18nObject](#graphon__model_runtime__entities__common_entities__i18nobject) | | Yes | +| model | string | | Yes | +| model_properties | object | | Yes | +| model_type | [ModelType](#modeltype) | | Yes | +| parameter_rules | [ [ParameterRule](#parameterrule) ],
**Default:** | | No | +| pricing | [PriceConfig](#priceconfig) | | No | + #### AIModelEntityResponse | Name | Type | Description | Required | @@ -13404,6 +13420,27 @@ Soft lifecycle state for Agent records. | ---- | ---- | ----------- | -------- | | AgentStatus | string | Soft lifecycle state for Agent records. | | +#### AgentStrategyProviderEntity + +| Name | Type | Description | Required | +| ---- | ---- | ----------- | -------- | +| identity | [AgentStrategyProviderIdentity](#agentstrategyprovideridentity) | | Yes | +| plugin_id | string | The id of the plugin | No | + +#### AgentStrategyProviderIdentity + +Inherits from ToolProviderIdentity, without any additional fields. + +| Name | Type | Description | Required | +| ---- | ---- | ----------- | -------- | +| author | string | The author of the tool | Yes | +| description | [core__tools__entities__common_entities__I18nObject](#core__tools__entities__common_entities__i18nobject) | The description of the tool | Yes | +| icon | string | The icon of the tool | Yes | +| icon_dark | string | The dark icon of the tool | No | +| label | [core__tools__entities__common_entities__I18nObject](#core__tools__entities__common_entities__i18nobject) | The label of the tool | Yes | +| name | string | The name of the tool | Yes | +| tags | [ [ToolLabelEnum](#toollabelenum) ] | The tags of the tool | No | + #### AgentSuggestedQuestionsAfterAnswerFeatureConfig | Name | Type | Description | Required | @@ -13909,6 +13946,12 @@ AppMCPServer Status Enum | use_icon_as_answer_icon | boolean | | No | | workflow | [WorkflowPartial](#workflowpartial) | | No | +#### AppSelectorScope + +| Name | Type | Description | Required | +| ---- | ---- | ----------- | -------- | +| AppSelectorScope | string | | | + #### AppSiteResponse | Name | Type | Description | Required | @@ -13991,6 +14034,12 @@ AppMCPServer Status Enum | ---- | ---- | ----------- | -------- | | text | string | | Yes | +#### AuthorizedCategory + +| Name | Type | Description | Required | +| ---- | ---- | ----------- | -------- | +| AuthorizedCategory | string | | | + #### AutoDisableLogsResponse | Name | Type | Description | Required | @@ -13998,6 +14047,12 @@ AppMCPServer Status Enum | count | integer | | Yes | | document_ids | [ string ] | | Yes | +#### AvailableModelListResponse + +| Name | Type | Description | Required | +| ---- | ---- | ----------- | -------- | +| data | [ [ProviderWithModelsResponse](#providerwithmodelsresponse) ] | | Yes | + #### AvatarUrlResponse | Name | Type | Description | Required | @@ -15434,6 +15489,36 @@ Model class for provider custom model configuration. | error | string | Error message from OAuth provider | No | | state | string | OAuth state parameter | No | +#### DatasourceProviderEntity + +Datasource provider entity + +| Name | Type | Description | Required | +| ---- | ---- | ----------- | -------- | +| credentials_schema | [ [ProviderConfig](#providerconfig) ] | | No | +| identity | [DatasourceProviderIdentity](#datasourceprovideridentity) | | Yes | +| oauth_schema | [OAuthSchema](#oauthschema) | | No | +| provider_type | [DatasourceProviderType](#datasourceprovidertype) | | Yes | + +#### DatasourceProviderIdentity + +| Name | Type | Description | Required | +| ---- | ---- | ----------- | -------- | +| author | string | The author of the tool | Yes | +| description | [core__tools__entities__common_entities__I18nObject](#core__tools__entities__common_entities__i18nobject) | The description of the tool | Yes | +| icon | string | The icon of the tool | Yes | +| label | [core__tools__entities__common_entities__I18nObject](#core__tools__entities__common_entities__i18nobject) | The label of the tool | Yes | +| name | string | The name of the tool | Yes | +| tags | [ [ToolLabelEnum](#toollabelenum) ] | The tags of the tool | No | + +#### DatasourceProviderType + +Enum class for datasource provider + +| Name | Type | Description | Required | +| ---- | ---- | ----------- | -------- | +| DatasourceProviderType | string | Enum class for datasource provider | | + #### DatasourceUpdateNamePayload | Name | Type | Description | Required | @@ -15889,6 +15974,12 @@ Request payload for bulk downloading documents as a zip archive. | ---- | ---- | ----------- | -------- | | EmptyObjectResponse | object | | | +#### Endpoint + +| Name | Type | Description | Required | +| ---- | ---- | ----------- | -------- | +| enabled | boolean | | No | + #### EndpointCreatePayload | Name | Type | Description | Required | @@ -15903,6 +15994,16 @@ Request payload for bulk downloading documents as a zip archive. | ---- | ---- | ----------- | -------- | | success | boolean | Operation success | Yes | +#### EndpointDeclaration + +declaration of an endpoint + +| Name | Type | Description | Required | +| ---- | ---- | ----------- | -------- | +| hidden | boolean | | No | +| method | string | | Yes | +| path | string | | Yes | + #### EndpointDeleteResponse | Name | Type | Description | Required | @@ -15948,6 +16049,15 @@ Request payload for bulk downloading documents as a zip archive. | ---- | ---- | ----------- | -------- | | endpoints | [ object ] | Endpoint information | Yes | +#### EndpointProviderDeclaration + +declaration of an endpoint group + +| Name | Type | Description | Required | +| ---- | ---- | ----------- | -------- | +| endpoints | [ [EndpointDeclaration](#endpointdeclaration) ] | | No | +| settings | [ [ProviderConfig](#providerconfig) ] | | No | + #### EndpointUpdatePayload | Name | Type | Description | Required | @@ -16003,6 +16113,57 @@ Request payload for bulk downloading documents as a zip archive. | data | [ [DocumentStatusResponse](#documentstatusresponse) ] | | Yes | | total | integer | | Yes | +#### EventEntity + +The configuration of an event + +| Name | Type | Description | Required | +| ---- | ---- | ----------- | -------- | +| description | [core__tools__entities__common_entities__I18nObject](#core__tools__entities__common_entities__i18nobject) | The description of the event | Yes | +| identity | [EventIdentity](#eventidentity) | | Yes | +| output_schema | object | The output schema that this event produces | No | +| parameters | [ [EventParameter](#eventparameter) ] | The parameters of the event | No | + +#### EventIdentity + +The identity of the event + +| Name | Type | Description | Required | +| ---- | ---- | ----------- | -------- | +| author | string | The author of the event | Yes | +| label | [core__tools__entities__common_entities__I18nObject](#core__tools__entities__common_entities__i18nobject) | The label of the event | Yes | +| name | string | The name of the event | Yes | +| provider | string | The provider of the event | No | + +#### EventParameter + +The parameter of the event + +| Name | Type | Description | Required | +| ---- | ---- | ----------- | -------- | +| auto_generate | [PluginParameterAutoGenerate](#pluginparameterautogenerate) | The auto generate of the parameter | No | +| default | integer
number
string
[ object ] | | No | +| description | [core__tools__entities__common_entities__I18nObject](#core__tools__entities__common_entities__i18nobject) | | No | +| label | [core__tools__entities__common_entities__I18nObject](#core__tools__entities__common_entities__i18nobject) | The label presented to the user | Yes | +| max | number
integer | | No | +| min | number
integer | | No | +| multiple | boolean | Whether the parameter is multiple select, only valid for select or dynamic-select type | No | +| name | string | The name of the parameter | Yes | +| options | [ [PluginParameterOption](#pluginparameteroption) ] | | No | +| precision | integer | | No | +| required | boolean | | No | +| scope | string | | No | +| template | [PluginParameterTemplate](#pluginparametertemplate) | The template of the parameter | No | +| type | [EventParameterType](#eventparametertype) | | Yes | + +#### EventParameterType + +The type of the parameter + +| Name | Type | Description | Required | +| ---- | ---- | ----------- | -------- | +| EventParameterType | string | The type of the parameter | | + #### EventStreamResponse | Name | Type | Description | Required | @@ -16375,10 +16536,10 @@ Enum class for form type. | Name | Type | Description | Required | | ---- | ---- | ----------- | -------- | -| github_plugin_unique_identifier | string | | Yes | -| package | string | | Yes | +| packages | string | | Yes | +| release | string | | Yes | | repo | string | | Yes | -| version | string | | Yes | +| repo_address | string | | Yes | #### HitTestingChildChunk @@ -16828,6 +16989,17 @@ Enum class for large language model mode. | ---- | ---- | ----------- | -------- | | LLMMode | string | Enum class for large language model mode. | | +#### LatestPluginCache + +| Name | Type | Description | Required | +| ---- | ---- | ----------- | -------- | +| alternative_plugin_id | string | | Yes | +| deprecated_reason | string | | Yes | +| plugin_id | string | | Yes | +| status | string | | Yes | +| unique_identifier | string | | Yes | +| version | string | | Yes | + #### LearnDifyAppListResponse | Name | Type | Description | Required | @@ -16983,8 +17155,9 @@ Enum class for large language model mode. | Name | Type | Description | Required | | ---- | ---- | ----------- | -------- | -| marketplace_plugin_unique_identifier | string | | Yes | -| version | string | | No | +| organization | string | | Yes | +| plugin | string | | Yes | +| version | string | | Yes | #### MemberActionTenantResponse @@ -17139,6 +17312,13 @@ Enum class for large language model mode. | first_id | string | The ID of the first chat record on the current page. Omit this value to fetch the latest messages; for subsequent pages, use the first message ID from the current list to fetch older messages. | No | | limit | integer,
**Default:** 20 | Number of chat history messages to return per request. | No | +#### Meta + +| Name | Type | Description | Required | +| ---- | ---- | ----------- | -------- | +| minimum_dify_version | string | | No | +| version | string | | No | + #### MetadataArgs | Name | Type | Description | Required | @@ -17177,6 +17357,18 @@ Metadata operation data | ---- | ---- | ----------- | -------- | | name | string | New metadata field name. | Yes | +#### Model + +| Name | Type | Description | Required | +| ---- | ---- | ----------- | -------- | +| enabled | boolean | | No | +| llm | boolean | | No | +| moderation | boolean | | No | +| rerank | boolean | | No | +| speech2text | boolean | | No | +| text_embedding | boolean | | No | +| tts | boolean | | No | + #### ModelConfig | Name | Type | Description | Required | @@ -17214,22 +17406,15 @@ Metadata operation data | text_to_speech | object | Text to speech configuration | No | | tools | [ object ] | Available tools | No | -#### ModelCredentialLoadBalancingResponse - -| Name | Type | Description | Required | -| ---- | ---- | ----------- | -------- | -| configs | [ object ] | | No | -| enabled | boolean | | Yes | - #### ModelCredentialResponse | Name | Type | Description | Required | | ---- | ---- | ----------- | -------- | | available_credentials | [ [CredentialConfiguration](#credentialconfiguration) ] | | Yes | -| credentials | object | | No | +| credentials | object | | Yes | | current_credential_id | string | | No | | current_credential_name | string | | No | -| load_balancing | [ModelCredentialLoadBalancingResponse](#modelcredentialloadbalancingresponse) | | Yes | +| load_balancing | [ModelLoadBalancingResponse](#modelloadbalancingresponse) | | Yes | #### ModelCredentialSchema @@ -17240,13 +17425,6 @@ Model class for model credential schema. | credential_form_schemas | [ [CredentialFormSchema](#credentialformschema) ] | | Yes | | model | [FieldModelSchema](#fieldmodelschema) | | Yes | -#### ModelCredentialValidateResponse - -| Name | Type | Description | Required | -| ---- | ---- | ----------- | -------- | -| error | string | | No | -| result | string | | Yes | - #### ModelFeature Enum class for llm feature. @@ -17255,7 +17433,26 @@ Enum class for llm feature. | ---- | ---- | ----------- | -------- | | ModelFeature | string | Enum class for llm feature. | | -#### ModelParameterRulesResponse +#### ModelLoadBalancingConfigResponse + +| Name | Type | Description | Required | +| ---- | ---- | ----------- | -------- | +| credential_id | string | | No | +| credentials | object | | Yes | +| enabled | boolean | | Yes | +| id | string | | Yes | +| in_cooldown | boolean | | Yes | +| name | string | | Yes | +| ttl | integer | | Yes | + +#### ModelLoadBalancingResponse + +| Name | Type | Description | Required | +| ---- | ---- | ----------- | -------- | +| configs | [ [ModelLoadBalancingConfigResponse](#modelloadbalancingconfigresponse) ] | | Yes | +| enabled | boolean | | Yes | + +#### ModelParameterRuleListResponse | Name | Type | Description | Required | | ---- | ---- | ----------- | -------- | @@ -17281,6 +17478,12 @@ Enum class for model property key. | ---- | ---- | ----------- | -------- | | payment_link | string | | Yes | +#### ModelSelectorScope + +| Name | Type | Description | Required | +| ---- | ---- | ----------- | -------- | +| ModelSelectorScope | string | | | + #### ModelStatus Enum class for model status. @@ -17315,12 +17518,6 @@ Model with provider entity. | provider | [SimpleProviderEntityResponse](#simpleproviderentityresponse) | | Yes | | status | [ModelStatus](#modelstatus) | | Yes | -#### ModelWithProviderListResponse - -| Name | Type | Description | Required | -| ---- | ---- | ----------- | -------- | -| data | [ [ModelWithProviderEntityResponse](#modelwithproviderentityresponse) ] | | Yes | - #### MoreLikeThisQuery | Name | Type | Description | Required | @@ -17342,6 +17539,12 @@ Model with provider entity. | new_app_id | string | | Yes | | permission_keys | [ string ] | | No | +#### Node + +| Name | Type | Description | Required | +| ---- | ---- | ----------- | -------- | +| enabled | boolean | | No | + #### NodeIdQuery | Name | Type | Description | Required | @@ -17571,6 +17774,15 @@ Coarse node-level status used by Inspector to pick a banner. | refresh_token | string | | Yes | | token_type | string | | Yes | +#### OAuthSchema + +OAuth schema + +| Name | Type | Description | Required | +| ---- | ---- | ----------- | -------- | +| client_schema | [ [ProviderConfig](#providerconfig) ] | client schema like client_id, client_secret, etc. | No | +| credentials_schema | [ [ProviderConfig](#providerconfig) ] | credentials schema like access_token, refresh_token, etc. | No | + #### OAuthTokenRequest | Name | Type | Description | Required | @@ -17588,6 +17800,13 @@ Coarse node-level status used by Inspector to pick a banner. | ---- | ---- | ----------- | -------- | | OpaqueObjectResponse | object | | | +#### Option + +| Name | Type | Description | Required | +| ---- | ---- | ----------- | -------- | +| label | [core__tools__entities__common_entities__I18nObject](#core__tools__entities__common_entities__i18nobject) | The label of the option | Yes | +| value | string | The value of the option | Yes | + #### OutputErrorStrategy Per-output failure handling strategy. @@ -17633,8 +17852,8 @@ output check fails and any configured retry attempts have been exhausted. | Name | Type | Description | Required | | ---- | ---- | ----------- | -------- | -| plugin_unique_identifier | string | | Yes | -| version | string | | No | +| manifest | [PluginDeclaration](#plugindeclaration) | | Yes | +| unique_identifier | string | | Yes | #### PaginatedConversationVariableResponse @@ -18030,6 +18249,16 @@ Enum class for parameter type. | node_title | string | | Yes | | pause_type | [HumanInputPauseTypeResponse](#humaninputpausetyperesponse) | | Yes | +#### Permission + +| Name | Type | Description | Required | +| ---- | ---- | ----------- | -------- | +| endpoint | [Endpoint](#endpoint) | | No | +| model | [Model](#model) | | No | +| node | [Node](#node) | | No | +| storage | [Storage](#storage) | | No | +| tool | [Tool](#tool) | | No | + #### PermissionCatalogGroup | Name | Type | Description | Required | @@ -18159,6 +18388,19 @@ Shared permission levels for resources (datasets, credentials, etc.) | upgrade_mode | [UpgradeMode](#upgrademode) | | Yes | | upgrade_time_of_day | integer | | Yes | +#### PluginBundleDependency + +| Name | Type | Description | Required | +| ---- | ---- | ----------- | -------- | +| type | [core__plugin__entities__bundle__PluginBundleDependency__Type](#core__plugin__entities__bundle__pluginbundledependency__type) | | Yes | +| value | [Github](#github)
[Marketplace](#marketplace)
[Package](#package) | | Yes | + +#### PluginBundleUploadResponse + +| Name | Type | Description | Required | +| ---- | ---- | ----------- | -------- | +| PluginBundleUploadResponse | array | | | + #### PluginCategory | Name | Type | Description | Required | @@ -18233,12 +18475,6 @@ Shared permission levels for resources (datasets, credentials, etc.) | has_more | boolean | | Yes | | plugins | [ [PluginCategoryInstalledPluginResponse](#plugincategoryinstalledpluginresponse) ] | | Yes | -#### PluginDaemonOperationResponse - -| Name | Type | Description | Required | -| ---- | ---- | ----------- | -------- | -| PluginDaemonOperationResponse | | | | - #### PluginDebuggingKeyResponse | Name | Type | Description | Required | @@ -18247,6 +18483,32 @@ Shared permission levels for resources (datasets, credentials, etc.) | key | string | | Yes | | port | integer | | Yes | +#### PluginDeclaration + +| Name | Type | Description | Required | +| ---- | ---- | ----------- | -------- | +| agent_strategy | [AgentStrategyProviderEntity](#agentstrategyproviderentity) | | No | +| author | string | | Yes | +| category | [PluginCategory](#plugincategory) | | Yes | +| created_at | dateTime | | Yes | +| datasource | [DatasourceProviderEntity](#datasourceproviderentity) | | No | +| description | [core__tools__entities__common_entities__I18nObject](#core__tools__entities__common_entities__i18nobject) | | Yes | +| endpoint | [EndpointProviderDeclaration](#endpointproviderdeclaration) | | No | +| icon | string | | Yes | +| icon_dark | string | | No | +| label | [core__tools__entities__common_entities__I18nObject](#core__tools__entities__common_entities__i18nobject) | | Yes | +| meta | [Meta](#meta) | | Yes | +| model | [ProviderEntity](#providerentity) | | No | +| name | string | | Yes | +| plugins | [Plugins](#plugins) | | Yes | +| repo | string | | No | +| resource | [PluginResourceRequirements](#pluginresourcerequirements) | | Yes | +| tags | [ string ] | | No | +| tool | [ToolProviderEntity](#toolproviderentity) | | No | +| trigger | [TriggerProviderEntity](#triggerproviderentity) | | No | +| verified | boolean | | No | +| version | string | | Yes | + #### PluginDeclarationResponse | Name | Type | Description | Required | @@ -18273,6 +18535,14 @@ Shared permission levels for resources (datasets, credentials, etc.) | verified | boolean | | No | | version | string | | Yes | +#### PluginDecodeResponse + +| Name | Type | Description | Required | +| ---- | ---- | ----------- | -------- | +| manifest | [PluginDeclaration](#plugindeclaration) | | Yes | +| unique_identifier | string | The unique identifier of the plugin. | Yes | +| verification | [PluginVerification](#pluginverification) | Basic verification information | No | + #### PluginDependency | Name | Type | Description | Required | @@ -18285,7 +18555,7 @@ Shared permission levels for resources (datasets, credentials, etc.) | Name | Type | Description | Required | | ---- | ---- | ----------- | -------- | -| options | | | Yes | +| options | [ [PluginParameterOption](#pluginparameteroption) ] | | Yes | #### PluginEndpointListResponse @@ -18293,6 +18563,84 @@ Shared permission levels for resources (datasets, credentials, etc.) | ---- | ---- | ----------- | -------- | | endpoints | [ object ] | Endpoint information | Yes | +#### PluginEntity + +| Name | Type | Description | Required | +| ---- | ---- | ----------- | -------- | +| checksum | string | | Yes | +| created_at | dateTime | | Yes | +| declaration | [PluginDeclaration](#plugindeclaration) | | Yes | +| endpoints_active | integer | | Yes | +| endpoints_setups | integer | | Yes | +| id | string | | Yes | +| installation_id | string | | Yes | +| meta | object | | Yes | +| name | string | | Yes | +| plugin_id | string | | Yes | +| plugin_unique_identifier | string | | Yes | +| runtime_type | string | | Yes | +| source | [PluginInstallationSource](#plugininstallationsource) | | Yes | +| tenant_id | string | | Yes | +| updated_at | dateTime | | Yes | +| version | string | | Yes | + +#### PluginInstallTask + +| Name | Type | Description | Required | +| ---- | ---- | ----------- | -------- | +| completed_plugins | integer | The number of plugins that have been installed. | Yes | +| created_at | dateTime | | Yes | +| id | string | | Yes | +| plugins | [ [PluginInstallTaskPluginStatus](#plugininstalltaskpluginstatus) ] | The status of the plugins. | Yes | +| status | [PluginInstallTaskStatus](#plugininstalltaskstatus) | The status of the install task. | Yes | +| total_plugins | integer | The total number of plugins to be installed. | Yes | +| updated_at | dateTime | | Yes | + +#### PluginInstallTaskPluginStatus + +| Name | Type | Description | Required | +| ---- | ---- | ----------- | -------- | +| icon | string | The icon of the plugin. | Yes | +| labels | [I18nObject](#i18nobject) | The labels of the plugin. | Yes | +| message | string | The message of the install task. | Yes | +| plugin_id | string | The plugin ID of the install task. | Yes | +| plugin_unique_identifier | string | The plugin unique identifier of the install task. | Yes | +| source | string | The installation source of the plugin | No | +| status | [PluginInstallTaskStatus](#plugininstalltaskstatus) | The status of the install task. | Yes | + +#### PluginInstallTaskStartResponse + +| Name | Type | Description | Required | +| ---- | ---- | ----------- | -------- | +| all_installed | boolean | Whether all plugins are installed. | Yes | +| task | [PluginInstallTask](#plugininstalltask) | The install task. | No | +| task_id | string | The ID of the install task. | Yes | + +#### PluginInstallTaskStatus + +| Name | Type | Description | Required | +| ---- | ---- | ----------- | -------- | +| PluginInstallTaskStatus | string | | | + +#### PluginInstallation + +| Name | Type | Description | Required | +| ---- | ---- | ----------- | -------- | +| checksum | string | | Yes | +| created_at | dateTime | | Yes | +| declaration | [PluginDeclaration](#plugindeclaration) | | Yes | +| endpoints_active | integer | | Yes | +| endpoints_setups | integer | | Yes | +| id | string | | Yes | +| meta | object | | Yes | +| plugin_id | string | | Yes | +| plugin_unique_identifier | string | | Yes | +| runtime_type | string | | Yes | +| source | [PluginInstallationSource](#plugininstallationsource) | | Yes | +| tenant_id | string | | Yes | +| updated_at | dateTime | | Yes | +| version | string | | Yes | + #### PluginInstallationPermissionModel | Name | Type | Description | Required | @@ -18316,13 +18664,13 @@ Shared permission levels for resources (datasets, credentials, etc.) | Name | Type | Description | Required | | ---- | ---- | ----------- | -------- | -| plugins | | | Yes | +| plugins | [ [PluginInstallation](#plugininstallation) ] | | Yes | #### PluginListResponse | Name | Type | Description | Required | | ---- | ---- | ----------- | -------- | -| plugins | | | Yes | +| plugins | [ [PluginEntity](#pluginentity) ] | | Yes | | total | integer | | Yes | #### PluginManagerModel @@ -18335,7 +18683,7 @@ Shared permission levels for resources (datasets, credentials, etc.) | Name | Type | Description | Required | | ---- | ---- | ----------- | -------- | -| manifest | | | Yes | +| manifest | [PluginDeclaration](#plugindeclaration) | | Yes | #### PluginOAuthAuthorizationUrlResponse @@ -18350,6 +18698,26 @@ Shared permission levels for resources (datasets, credentials, etc.) | message | string | | No | | success | boolean | | Yes | +#### PluginParameterAutoGenerate + +| Name | Type | Description | Required | +| ---- | ---- | ----------- | -------- | +| type | [core__plugin__entities__parameters__PluginParameterAutoGenerate__Type](#core__plugin__entities__parameters__pluginparameterautogenerate__type) | | Yes | + +#### PluginParameterOption + +| Name | Type | Description | Required | +| ---- | ---- | ----------- | -------- | +| icon | string | The icon of the option, can be a url or a base64 encoded image | No | +| label | [core__tools__entities__common_entities__I18nObject](#core__tools__entities__common_entities__i18nobject) | The label of the option | Yes | +| value | string | The value of the option | Yes | + +#### PluginParameterTemplate + +| Name | Type | Description | Required | +| ---- | ---- | ----------- | -------- | +| enabled | boolean | Whether the parameter is jinja enabled | No | + #### PluginPermissionResponse | Name | Type | Description | Required | @@ -18370,23 +18738,48 @@ Shared permission levels for resources (datasets, credentials, etc.) | ---- | ---- | ----------- | -------- | | readme | string | | Yes | +#### PluginResourceRequirements + +| Name | Type | Description | Required | +| ---- | ---- | ----------- | -------- | +| memory | integer | | Yes | +| permission | [Permission](#permission) | | No | + #### PluginTaskResponse | Name | Type | Description | Required | | ---- | ---- | ----------- | -------- | -| task | | | Yes | +| task | [PluginInstallTask](#plugininstalltask) | | Yes | #### PluginTasksResponse | Name | Type | Description | Required | | ---- | ---- | ----------- | -------- | -| tasks | | | Yes | +| tasks | [ [PluginInstallTask](#plugininstalltask) ] | | Yes | + +#### PluginVerification + +Verification of the plugin. + +| Name | Type | Description | Required | +| ---- | ---- | ----------- | -------- | +| authorized_category | [AuthorizedCategory](#authorizedcategory) | The authorized category of the plugin. | Yes | #### PluginVersionsResponse | Name | Type | Description | Required | | ---- | ---- | ----------- | -------- | -| versions | | | Yes | +| versions | object | | Yes | + +#### Plugins + +| Name | Type | Description | Required | +| ---- | ---- | ----------- | -------- | +| datasources | [ string ] | | No | +| endpoints | [ string ] | | No | +| models | [ string ] | | No | +| tools | [ string ] | | No | +| triggers | [ string ] | | No | #### PreProcessingRule @@ -18403,6 +18796,17 @@ Shared permission levels for resources (datasets, credentials, etc.) | content | string | | Yes | | summary | string | | No | +#### PriceConfig + +Model class for pricing info. + +| Name | Type | Description | Required | +| ---- | ---- | ----------- | -------- | +| currency | string | | Yes | +| input | string | | Yes | +| output | string | | No | +| unit | string | | Yes | + #### PriceConfigResponse Serialized pricing info with codegen-safe decimal string patterns. @@ -18429,11 +18833,23 @@ Dataset Process Rule Mode | ---- | ---- | ----------- | -------- | | ProcessRuleMode | string | Dataset Process Rule Mode | | -#### ProviderCredentialResponse +#### ProviderConfig + +Model class for common provider settings like credentials | Name | Type | Description | Required | | ---- | ---- | ----------- | -------- | -| credentials | object | | No | +| default | integer
string
number
boolean | | No | +| help | [core__tools__entities__common_entities__I18nObject](#core__tools__entities__common_entities__i18nobject) | | No | +| label | [core__tools__entities__common_entities__I18nObject](#core__tools__entities__common_entities__i18nobject) | | No | +| multiple | boolean | | No | +| name | string | The name of the credentials | Yes | +| options | [ [Option](#option) ] | | No | +| placeholder | [core__tools__entities__common_entities__I18nObject](#core__tools__entities__common_entities__i18nobject) | | No | +| required | boolean | | No | +| scope | [AppSelectorScope](#appselectorscope)
[ModelSelectorScope](#modelselectorscope)
[ToolSelectorScope](#toolselectorscope) | | No | +| type | [core__entities__provider_entities__BasicProviderConfig__Type](#core__entities__provider_entities__basicproviderconfig__type) | The type of the credentials | Yes | +| url | string | | No | #### ProviderCredentialSchema @@ -18443,12 +18859,36 @@ Model class for provider credential schema. | ---- | ---- | ----------- | -------- | | credential_form_schemas | [ [CredentialFormSchema](#credentialformschema) ] | | Yes | -#### ProviderCredentialValidateResponse +#### ProviderCredentialsResponse | Name | Type | Description | Required | | ---- | ---- | ----------- | -------- | -| error | string | | No | -| result | string,
**Available values:** "error", "success" | *Enum:* `"error"`, `"success"` | Yes | +| credentials | object | | No | + +#### ProviderEntity + +Runtime-native provider schema. + +`provider` is the canonical runtime identifier. `provider_name` is a +compatibility alias for callers that still resolve providers by short name and +is empty when no alias exists. + +| Name | Type | Description | Required | +| ---- | ---- | ----------- | -------- | +| background | string | | No | +| configurate_methods | [ [ConfigurateMethod](#configuratemethod) ] | | Yes | +| description | [graphon__model_runtime__entities__common_entities__I18nObject](#graphon__model_runtime__entities__common_entities__i18nobject) | | No | +| help | [ProviderHelpEntity](#providerhelpentity) | | No | +| icon_small | [graphon__model_runtime__entities__common_entities__I18nObject](#graphon__model_runtime__entities__common_entities__i18nobject) | | No | +| icon_small_dark | [graphon__model_runtime__entities__common_entities__I18nObject](#graphon__model_runtime__entities__common_entities__i18nobject) | | No | +| label | [graphon__model_runtime__entities__common_entities__I18nObject](#graphon__model_runtime__entities__common_entities__i18nobject) | | Yes | +| model_credential_schema | [ModelCredentialSchema](#modelcredentialschema) | | No | +| models | [ [AIModelEntity](#aimodelentity) ] | | No | +| position | object | | No | +| provider | string | | Yes | +| provider_credential_schema | [ProviderCredentialSchema](#providercredentialschema) | | No | +| provider_name | string | | No | +| supported_model_types | [ [ModelType](#modeltype) ] | | Yes | #### ProviderEntityResponse @@ -18480,6 +18920,12 @@ Model class for provider help. | title | [graphon__model_runtime__entities__common_entities__I18nObject](#graphon__model_runtime__entities__common_entities__i18nobject) | | Yes | | url | [graphon__model_runtime__entities__common_entities__I18nObject](#graphon__model_runtime__entities__common_entities__i18nobject) | | Yes | +#### ProviderModelListResponse + +| Name | Type | Description | Required | +| ---- | ---- | ----------- | -------- | +| data | [ [ModelWithProviderEntityResponse](#modelwithproviderentityresponse) ] | | Yes | + #### ProviderModelWithStatusEntity Model class for model response. @@ -18537,12 +18983,6 @@ Model class for provider response. | ---- | ---- | ----------- | -------- | | ProviderType | string | | | -#### ProviderWithModelsDataResponse - -| Name | Type | Description | Required | -| ---- | ---- | ----------- | -------- | -| data | [ [ProviderWithModelsResponse](#providerwithmodelsresponse) ] | | Yes | - #### ProviderWithModelsResponse Model class for provider with models response. @@ -19502,6 +19942,13 @@ Query parameters for listing snippet published workflows. | paused | integer | | Yes | | success | integer | | Yes | +#### Storage + +| Name | Type | Description | Required | +| ---- | ---- | ----------- | -------- | +| enabled | boolean | | No | +| size | integer,
**Default:** 1048576 | | No | + #### StrategySetting | Name | Type | Description | Required | @@ -19526,6 +19973,16 @@ Default configuration for form inputs. | type | [ValueSourceType](#valuesourcetype) | | Yes | | value | string | | No | +#### SubscriptionConstructor + +The subscription constructor of the trigger provider + +| Name | Type | Description | Required | +| ---- | ---- | ----------- | -------- | +| credentials_schema | [ [ProviderConfig](#providerconfig) ] | The credentials schema of the subscription constructor | No | +| oauth_schema | [OAuthSchema](#oauthschema) | The OAuth schema of the subscription constructor if OAuth is supported | No | +| parameters | [ [EventParameter](#eventparameter) ] | The parameters schema of the subscription constructor | No | + #### SubscriptionModel | Name | Type | Description | Required | @@ -19796,6 +20253,18 @@ Tag type | ---- | ---- | ----------- | -------- | | data | [ [TokensPerSecondStatisticItem](#tokenspersecondstatisticitem) ] | | Yes | +#### Tool + +| Name | Type | Description | Required | +| ---- | ---- | ----------- | -------- | +| enabled | boolean | | No | + +#### ToolLabelEnum + +| Name | Type | Description | Required | +| ---- | ---- | ----------- | -------- | +| ToolLabelEnum | string | | | + #### ToolOAuthClientSchemaResponse | Name | Type | Description | Required | @@ -19821,6 +20290,27 @@ Tag type | ---- | ---- | ----------- | -------- | | ToolParameterForm | string | | | +#### ToolProviderEntity + +| Name | Type | Description | Required | +| ---- | ---- | ----------- | -------- | +| credentials_schema | [ [ProviderConfig](#providerconfig) ] | | No | +| identity | [ToolProviderIdentity](#toolprovideridentity) | | Yes | +| oauth_schema | [OAuthSchema](#oauthschema) | | No | +| plugin_id | string | | No | + +#### ToolProviderIdentity + +| Name | Type | Description | Required | +| ---- | ---- | ----------- | -------- | +| author | string | The author of the tool | Yes | +| description | [core__tools__entities__common_entities__I18nObject](#core__tools__entities__common_entities__i18nobject) | The description of the tool | Yes | +| icon | string | The icon of the tool | Yes | +| icon_dark | string | The dark icon of the tool | No | +| label | [core__tools__entities__common_entities__I18nObject](#core__tools__entities__common_entities__i18nobject) | The label of the tool | Yes | +| name | string | The name of the tool | Yes | +| tags | [ [ToolLabelEnum](#toollabelenum) ] | The tags of the tool | No | + #### ToolProviderListQuery | Name | Type | Description | Required | @@ -19841,6 +20331,12 @@ Enum class for tool provider | ---- | ---- | ----------- | -------- | | ToolProviderType | string | Enum class for tool provider | | +#### ToolSelectorScope + +| Name | Type | Description | Required | +| ---- | ---- | ----------- | -------- | +| ToolSelectorScope | string | | | + #### TraceAppConfigResponse | Name | Type | Description | Required | @@ -20104,6 +20600,31 @@ Enum class for tool provider | redirect_uri | string | | Yes | | system_configured | boolean | | Yes | +#### TriggerProviderEntity + +The configuration of a trigger provider + +| Name | Type | Description | Required | +| ---- | ---- | ----------- | -------- | +| events | [ [EventEntity](#evententity) ] | The events of the trigger provider | No | +| identity | [TriggerProviderIdentity](#triggerprovideridentity) | | Yes | +| subscription_constructor | [SubscriptionConstructor](#subscriptionconstructor) | The subscription constructor of the trigger provider | No | +| subscription_schema | [ [ProviderConfig](#providerconfig) ] | The configuration schema stored in the subscription entity | No | + +#### TriggerProviderIdentity + +The identity of the trigger provider + +| Name | Type | Description | Required | +| ---- | ---- | ----------- | -------- | +| author | string | The author of the trigger provider | Yes | +| description | [core__tools__entities__common_entities__I18nObject](#core__tools__entities__common_entities__i18nobject) | The description of the trigger provider | Yes | +| icon | string | The icon of the trigger provider | No | +| icon_dark | string | The dark icon of the trigger provider | No | +| label | [core__tools__entities__common_entities__I18nObject](#core__tools__entities__common_entities__i18nobject) | The label of the trigger provider | Yes | +| name | string | The name of the trigger provider | Yes | +| tags | [ string ] | The tags of the trigger provider | No | + #### TriggerProviderOpaqueResponse | Name | Type | Description | Required | @@ -20246,6 +20767,13 @@ User action configuration. | ---- | ---- | ----------- | -------- | | data | [ [UserSatisfactionRateStatisticItem](#usersatisfactionratestatisticitem) ] | | Yes | +#### ValidationResultResponse + +| Name | Type | Description | Required | +| ---- | ---- | ----------- | -------- | +| error | string | | No | +| result | string,
**Available values:** "error", "success" | *Enum:* `"error"`, `"success"` | Yes | + #### ValueSourceType ValueSourceType records whether the value comes from a static setting @@ -21311,6 +21839,24 @@ Workflow tool configuration | data | [ [RBACRole](#rbacrole) ] | | No | | pagination | [Pagination](#pagination) | | No | +#### core__entities__provider_entities__BasicProviderConfig__Type + +| Name | Type | Description | Required | +| ---- | ---- | ----------- | -------- | +| core__entities__provider_entities__BasicProviderConfig__Type | string | | | + +#### core__plugin__entities__bundle__PluginBundleDependency__Type + +| Name | Type | Description | Required | +| ---- | ---- | ----------- | -------- | +| core__plugin__entities__bundle__PluginBundleDependency__Type | string | | | + +#### core__plugin__entities__parameters__PluginParameterAutoGenerate__Type + +| Name | Type | Description | Required | +| ---- | ---- | ----------- | -------- | +| core__plugin__entities__parameters__PluginParameterAutoGenerate__Type | string | | | + #### core__tools__entities__common_entities__I18nObject Model class for i18n object. diff --git a/api/tests/unit_tests/controllers/console/workspace/test_model_providers.py b/api/tests/unit_tests/controllers/console/workspace/test_model_providers.py index 21055390362..088ceea8348 100644 --- a/api/tests/unit_tests/controllers/console/workspace/test_model_providers.py +++ b/api/tests/unit_tests/controllers/console/workspace/test_model_providers.py @@ -1,10 +1,14 @@ -from unittest.mock import MagicMock, patch +from inspect import unwrap +from types import SimpleNamespace +from typing import cast +from unittest.mock import patch import pytest from flask import Flask from pydantic_core import ValidationError from werkzeug.exceptions import Forbidden +from configs import dify_config from controllers.console.workspace.model_providers import ( ModelProviderCredentialApi, ModelProviderCredentialSwitchApi, @@ -14,30 +18,126 @@ from controllers.console.workspace.model_providers import ( ModelProviderValidateApi, PreferredProviderTypeUpdateApi, ) +from graphon.model_runtime.entities.common_entities import I18nObject +from graphon.model_runtime.entities.model_entities import ModelType +from graphon.model_runtime.entities.provider_entities import ConfigurateMethod from graphon.model_runtime.errors.validate import CredentialsValidateFailedError +from models import Account +from models.provider import ProviderType +from services.entities.model_provider_entities import ( + CustomConfigurationResponse, + CustomConfigurationStatus, + ProviderResponse, + SystemConfigurationResponse, +) VALID_UUID = "123e4567-e89b-12d3-a456-426614174000" INVALID_UUID = "123" -from inspect import unwrap +def make_account() -> Account: + return cast(Account, SimpleNamespace(id="account-1", email="owner@example.com")) + + +def make_provider_response() -> ProviderResponse: + return ProviderResponse( + tenant_id="tenant1", + provider="openai", + label=I18nObject(en_US="OpenAI", zh_Hans="OpenAI"), + description=I18nObject(en_US="OpenAI models", zh_Hans="OpenAI models zh"), + icon_small=I18nObject(en_US="icon.svg", zh_Hans="icon.svg"), + icon_small_dark=I18nObject(en_US="icon-dark.svg", zh_Hans="icon-dark.svg"), + background="#ffffff", + supported_model_types=[ModelType.LLM, ModelType.TEXT_EMBEDDING], + configurate_methods=[ConfigurateMethod.PREDEFINED_MODEL, ConfigurateMethod.CUSTOMIZABLE_MODEL], + preferred_provider_type=ProviderType.CUSTOM, + custom_configuration=CustomConfigurationResponse( + status=CustomConfigurationStatus.ACTIVE, + current_credential_id=VALID_UUID, + current_credential_name="production", + available_credentials=[], + custom_models=[], + can_added_models=[], + ), + system_configuration=SystemConfigurationResponse( + enabled=True, + current_quota_type=None, + quota_configurations=[], + ), + ) + + +def expected_provider_payload() -> dict[str, object]: + icon_url_prefix = f"{dify_config.CONSOLE_API_URL}/console/api/workspaces/tenant1/model-providers/openai" + return { + "tenant_id": "tenant1", + "provider": "openai", + "label": {"zh_Hans": "OpenAI", "en_US": "OpenAI"}, + "description": {"zh_Hans": "OpenAI models zh", "en_US": "OpenAI models"}, + "icon_small": { + "zh_Hans": f"{icon_url_prefix}/icon_small/zh_Hans", + "en_US": f"{icon_url_prefix}/icon_small/en_US", + }, + "icon_small_dark": { + "zh_Hans": f"{icon_url_prefix}/icon_small_dark/zh_Hans", + "en_US": f"{icon_url_prefix}/icon_small_dark/en_US", + }, + "background": "#ffffff", + "help": None, + "supported_model_types": ["llm", "text-embedding"], + "configurate_methods": ["predefined-model", "customizable-model"], + "provider_credential_schema": None, + "model_credential_schema": None, + "preferred_provider_type": "custom", + "custom_configuration": { + "status": "active", + "current_credential_id": VALID_UUID, + "current_credential_name": "production", + "available_credentials": [], + "custom_models": [], + "can_added_models": [], + }, + "system_configuration": { + "enabled": True, + "current_quota_type": None, + "quota_configurations": [], + }, + } class TestModelProviderListApi: def test_get_success(self, app: Flask): api = ModelProviderListApi() method = unwrap(api.get) + provider = make_provider_response() with ( app.test_request_context("/?model_type=llm"), patch( "controllers.console.workspace.model_providers.ModelProviderService.get_provider_list", - return_value=[{"name": "openai"}], - ), + return_value=[provider], + ) as get_provider_list, ): result = method(api, "tenant1") - assert "data" in result + get_provider_list.assert_called_once_with(tenant_id="tenant1", model_type=ModelType.LLM) + assert result == {"data": [expected_provider_payload()]} + + def test_get_without_model_type_passes_none(self, app: Flask): + api = ModelProviderListApi() + method = unwrap(api.get) + + with ( + app.test_request_context("/"), + patch( + "controllers.console.workspace.model_providers.ModelProviderService.get_provider_list", + return_value=[], + ) as get_provider_list, + ): + result = method(api, "tenant1") + + get_provider_list.assert_called_once_with(tenant_id="tenant1", model_type=None) + assert result == {"data": []} class TestModelProviderCredentialApi: @@ -49,12 +149,41 @@ class TestModelProviderCredentialApi: app.test_request_context(f"/?credential_id={VALID_UUID}"), patch( "controllers.console.workspace.model_providers.ModelProviderService.get_provider_credential", - return_value={"key": "value"}, - ), + return_value={ + "api_key": "sk-test", + "endpoint": "https://api.example.com", + "nested": {"region": "us-east-1"}, + }, + ) as get_provider_credential, ): result = method(api, "tenant1", provider="openai") - assert "credentials" in result + get_provider_credential.assert_called_once_with( + tenant_id="tenant1", provider="openai", credential_id=VALID_UUID + ) + assert result == { + "credentials": { + "api_key": "sk-test", + "endpoint": "https://api.example.com", + "nested": {"region": "us-east-1"}, + } + } + + def test_get_current_credential_without_id(self, app: Flask): + api = ModelProviderCredentialApi() + method = unwrap(api.get) + + with ( + app.test_request_context("/"), + patch( + "controllers.console.workspace.model_providers.ModelProviderService.get_provider_credential", + return_value=None, + ) as get_provider_credential, + ): + result = method(api, "tenant1", provider="openai") + + get_provider_credential.assert_called_once_with(tenant_id="tenant1", provider="openai", credential_id=None) + assert result == {"credentials": None} def test_get_invalid_uuid(self, app: Flask): api = ModelProviderCredentialApi() @@ -75,11 +204,17 @@ class TestModelProviderCredentialApi: patch( "controllers.console.workspace.model_providers.ModelProviderService.create_provider_credential", return_value=None, - ), + ) as create_provider_credential, ): result, status = method(api, "tenant1", provider="openai") - assert result["result"] == "success" + create_provider_credential.assert_called_once_with( + tenant_id="tenant1", + provider="openai", + credentials={"a": "b"}, + credential_name="test", + ) + assert result == {"result": "success"} assert status == 201 def test_post_create_validation_error(self, app: Flask): @@ -109,11 +244,18 @@ class TestModelProviderCredentialApi: patch( "controllers.console.workspace.model_providers.ModelProviderService.update_provider_credential", return_value=None, - ), + ) as update_provider_credential, ): result = method(api, "tenant1", provider="openai") - assert result["result"] == "success" + update_provider_credential.assert_called_once_with( + tenant_id="tenant1", + provider="openai", + credentials={"a": "b"}, + credential_id=VALID_UUID, + credential_name=None, + ) + assert result == {"result": "success"} def test_put_invalid_uuid(self, app: Flask): api = ModelProviderCredentialApi() @@ -136,10 +278,13 @@ class TestModelProviderCredentialApi: patch( "controllers.console.workspace.model_providers.ModelProviderService.remove_provider_credential", return_value=None, - ), + ) as remove_provider_credential, ): result, status = method(api, "tenant1", provider="openai") + remove_provider_credential.assert_called_once_with( + tenant_id="tenant1", provider="openai", credential_id=VALID_UUID + ) assert status == 204 assert result == "" @@ -156,11 +301,16 @@ class TestModelProviderCredentialSwitchApi: patch( "controllers.console.workspace.model_providers.ModelProviderService.switch_active_provider_credential", return_value=None, - ), + ) as switch_active_provider_credential, ): result = method(api, "tenant1", provider="openai") - assert result["result"] == "success" + switch_active_provider_credential.assert_called_once_with( + tenant_id="tenant1", + provider="openai", + credential_id=VALID_UUID, + ) + assert result == {"result": "success"} def test_switch_invalid_uuid(self, app: Flask): api = ModelProviderCredentialSwitchApi() @@ -185,11 +335,14 @@ class TestModelProviderValidateApi: patch( "controllers.console.workspace.model_providers.ModelProviderService.validate_provider_credentials", return_value=None, - ), + ) as validate_provider_credentials, ): result = method(api, "tenant1", provider="openai") - assert result["result"] == "success" + validate_provider_credentials.assert_called_once_with( + tenant_id="tenant1", provider="openai", credentials={"a": "b"} + ) + assert result == {"result": "success", "error": None} def test_validate_failure(self, app: Flask): api = ModelProviderValidateApi() @@ -206,7 +359,7 @@ class TestModelProviderValidateApi: ): result = method(api, "tenant1", provider="openai") - assert result["result"] == "error" + assert result == {"result": "error", "error": "bad"} class TestModelProviderIconApi: @@ -218,11 +371,14 @@ class TestModelProviderIconApi: patch( "controllers.console.workspace.model_providers.ModelProviderService.get_model_provider_icon", return_value=(b"123", "image/png"), - ), + ) as get_model_provider_icon, ): response = api.get("t1", "openai", "logo", "en") + get_model_provider_icon.assert_called_once_with(tenant_id="t1", provider="openai", icon_type="logo", lang="en") assert response.mimetype == "image/png" + response.direct_passthrough = False + assert response.get_data() == b"123" def test_icon_not_found(self, app: Flask): api = ModelProviderIconApi() @@ -250,11 +406,14 @@ class TestPreferredProviderTypeUpdateApi: patch( "controllers.console.workspace.model_providers.ModelProviderService.switch_preferred_provider", return_value=None, - ), + ) as switch_preferred_provider, ): result = method(api, "tenant1", provider="openai") - assert result["result"] == "success" + switch_preferred_provider.assert_called_once_with( + tenant_id="tenant1", provider="openai", preferred_provider_type="custom" + ) + assert result == {"result": "success"} def test_invalid_enum(self, app: Flask): api = PreferredProviderTypeUpdateApi() @@ -272,22 +431,29 @@ class TestModelProviderPaymentCheckoutUrlApi: api = ModelProviderPaymentCheckoutUrlApi() method = unwrap(api.get) - user = MagicMock(id="u1", email="x@test.com") + user = make_account() with ( app.test_request_context("/"), patch( "controllers.console.workspace.model_providers.BillingService.is_tenant_owner_or_admin", return_value=None, - ), + ) as is_tenant_owner_or_admin, patch( "controllers.console.workspace.model_providers.BillingService.get_model_provider_payment_link", - return_value={"url": "x"}, - ), + return_value={"payment_link": "https://payment.example.com/provider"}, + ) as get_model_provider_payment_link, ): result = method(api, "tenant1", user, provider="anthropic") - assert "url" in result + is_tenant_owner_or_admin.assert_called_once_with(user) + get_model_provider_payment_link.assert_called_once_with( + provider_name="anthropic", + tenant_id="tenant1", + account_id="account-1", + prefilled_email="owner@example.com", + ) + assert result == {"payment_link": "https://payment.example.com/provider"} def test_invalid_provider(self, app: Flask): api = ModelProviderPaymentCheckoutUrlApi() @@ -295,13 +461,13 @@ class TestModelProviderPaymentCheckoutUrlApi: with app.test_request_context("/"): with pytest.raises(ValueError): - method(api, "tenant1", MagicMock(), provider="openai") + method(api, "tenant1", make_account(), provider="openai") def test_permission_denied(self, app: Flask): api = ModelProviderPaymentCheckoutUrlApi() method = unwrap(api.get) - user = MagicMock(id="u1", email="x@test.com") + user = make_account() with ( app.test_request_context("/"), diff --git a/api/tests/unit_tests/controllers/console/workspace/test_models.py b/api/tests/unit_tests/controllers/console/workspace/test_models.py index 3374c49caff..424c1ef1d75 100644 --- a/api/tests/unit_tests/controllers/console/workspace/test_models.py +++ b/api/tests/unit_tests/controllers/console/workspace/test_models.py @@ -32,7 +32,16 @@ class TestDefaultModelApi: ), patch("controllers.console.workspace.models.ModelProviderService") as service_mock, ): - service_mock.return_value.get_default_model_of_model_type.return_value = {"model": "gpt-4"} + service_mock.return_value.get_default_model_of_model_type.return_value = { + "model": "gpt-4", + "model_type": ModelType.LLM, + "provider": { + "tenant_id": "tenant1", + "provider": "openai", + "label": {"en_US": "OpenAI", "zh_Hans": "OpenAI"}, + "supported_model_types": [ModelType.LLM], + }, + } result = method(api, "tenant1") diff --git a/api/tests/unit_tests/controllers/console/workspace/test_plugin.py b/api/tests/unit_tests/controllers/console/workspace/test_plugin.py index bc76560dcac..c4df3c41546 100644 --- a/api/tests/unit_tests/controllers/console/workspace/test_plugin.py +++ b/api/tests/unit_tests/controllers/console/workspace/test_plugin.py @@ -42,7 +42,11 @@ from controllers.console.workspace.plugin import ( PluginUploadFromGithubApi, PluginUploadFromPkgApi, ) +from core.plugin.entities.parameters import PluginParameterOption +from core.plugin.entities.plugin import PluginDeclaration, PluginEntity, PluginInstallation +from core.plugin.entities.plugin_daemon import PluginInstallTask from core.plugin.impl.exc import PluginDaemonClientSideError +from core.plugin.plugin_service import PluginService from models.account import Account, TenantAccountRole, TenantPluginAutoUpgradeStrategy, TenantPluginPermission @@ -109,6 +113,215 @@ def _builtin_tool_provider_item() -> dict[str, Any]: } +def _plugin_declaration_payload() -> dict[str, Any]: + return { + "version": "1.2.3", + "author": "langgenius", + "name": "demo_plugin", + "description": {"en_US": "Demo plugin"}, + "icon": "icon.svg", + "icon_dark": None, + "label": {"en_US": "Demo Plugin"}, + "created_at": "2024-01-02T03:04:05", + "resource": {"memory": 268435456, "permission": None}, + "plugins": {"tools": ["provider/demo.yaml"]}, + "tags": ["search", "demo"], + "repo": "https://github.com/langgenius/demo", + "verified": True, + "meta": {"minimum_dify_version": "0.15.0", "version": "1.2.3"}, + } + + +def _expected_i18n(en_us: str) -> dict[str, str]: + return {"en_US": en_us, "zh_Hans": en_us, "pt_BR": en_us, "ja_JP": en_us} + + +def _expected_plugin_declaration_dump() -> dict[str, Any]: + return { + "version": "1.2.3", + "author": "langgenius", + "name": "demo_plugin", + "description": _expected_i18n("Demo plugin"), + "icon": "icon.svg", + "icon_dark": None, + "label": _expected_i18n("Demo Plugin"), + "category": "extension", + "created_at": "2024-01-02T03:04:05", + "resource": {"memory": 268435456, "permission": None}, + "plugins": { + "tools": ["provider/demo.yaml"], + "models": [], + "endpoints": [], + "datasources": [], + "triggers": [], + }, + "tags": ["search", "demo"], + "repo": "https://github.com/langgenius/demo", + "verified": True, + "tool": None, + "model": None, + "endpoint": None, + "agent_strategy": None, + "datasource": None, + "trigger": None, + "meta": {"minimum_dify_version": "0.15.0", "version": "1.2.3"}, + } + + +def _plugin_installation_payload() -> dict[str, Any]: + return { + "id": "installation-row-1", + "created_at": "2024-01-02T03:04:05", + "updated_at": "2024-01-03T04:05:06", + "tenant_id": "tenant-1", + "endpoints_setups": 2, + "endpoints_active": 1, + "runtime_type": "remote", + "source": "marketplace", + "meta": {"from": "marketplace"}, + "plugin_id": "langgenius/demo_plugin", + "plugin_unique_identifier": "langgenius/demo_plugin:1.2.3@sha256:abc", + "version": "1.2.3", + "checksum": "sha256:abc", + "declaration": _plugin_declaration_payload(), + } + + +def _plugin_entity_payload() -> dict[str, Any]: + return { + **_plugin_installation_payload(), + "name": "demo_plugin", + "installation_id": "installation-row-1", + } + + +def _plugin_declaration() -> PluginDeclaration: + return PluginDeclaration.model_validate(_plugin_declaration_payload()) + + +def _plugin_installation() -> PluginInstallation: + return PluginInstallation.model_validate(_plugin_installation_payload()) + + +def _plugin_entity() -> PluginEntity: + return PluginEntity.model_validate(_plugin_entity_payload()) + + +def _expected_plugin_installation_dump() -> dict[str, Any]: + return { + "id": "installation-row-1", + "created_at": "2024-01-02T03:04:05", + "updated_at": "2024-01-03T04:05:06", + "tenant_id": "tenant-1", + "endpoints_setups": 2, + "endpoints_active": 1, + "runtime_type": "remote", + "source": "marketplace", + "meta": {"from": "marketplace"}, + "plugin_id": "langgenius/demo_plugin", + "plugin_unique_identifier": "langgenius/demo_plugin:1.2.3@sha256:abc", + "version": "1.2.3", + "checksum": "sha256:abc", + "declaration": _expected_plugin_declaration_dump(), + } + + +def _expected_plugin_entity_dump() -> dict[str, Any]: + return { + **_expected_plugin_installation_dump(), + "name": "demo_plugin", + "installation_id": "installation-row-1", + } + + +def _plugin_task_payload() -> dict[str, Any]: + return { + "id": "task-1", + "created_at": "2024-02-03T04:05:06", + "updated_at": "2024-02-03T04:06:07", + "status": "running", + "total_plugins": 2, + "completed_plugins": 1, + "plugins": [ + { + "plugin_unique_identifier": "langgenius/demo_plugin:1.2.3@sha256:abc", + "plugin_id": "langgenius/demo_plugin", + "status": "success", + "message": "installed", + "icon": "icon.svg", + "labels": {"en_US": "Demo Plugin"}, + "source": "marketplace", + } + ], + } + + +def _plugin_task() -> PluginInstallTask: + return PluginInstallTask.model_validate(_plugin_task_payload()) + + +def _expected_plugin_task_dump() -> dict[str, Any]: + return { + "id": "task-1", + "created_at": "2024-02-03T04:05:06", + "updated_at": "2024-02-03T04:06:07", + "status": "running", + "total_plugins": 2, + "completed_plugins": 1, + "plugins": [ + { + "plugin_unique_identifier": "langgenius/demo_plugin:1.2.3@sha256:abc", + "plugin_id": "langgenius/demo_plugin", + "status": "success", + "message": "installed", + "icon": "icon.svg", + "labels": _expected_i18n("Demo Plugin"), + "source": "marketplace", + } + ], + } + + +def _latest_plugin_cache() -> PluginService.LatestPluginCache: + return PluginService.LatestPluginCache( + plugin_id="langgenius/demo_plugin", + version="1.3.0", + unique_identifier="langgenius/demo_plugin:1.3.0@sha256:def", + status="active", + deprecated_reason="", + alternative_plugin_id="", + ) + + +def _expected_latest_plugin_cache_dump() -> dict[str, str]: + return { + "plugin_id": "langgenius/demo_plugin", + "version": "1.3.0", + "unique_identifier": "langgenius/demo_plugin:1.3.0@sha256:def", + "status": "active", + "deprecated_reason": "", + "alternative_plugin_id": "", + } + + +def _dynamic_option() -> PluginParameterOption: + return PluginParameterOption.model_validate( + { + "value": 101, + "label": {"en_US": "Dataset 101"}, + "icon": None, + } + ) + + +def _expected_dynamic_option_dump() -> dict[str, Any]: + return { + "value": "101", + "label": _expected_i18n("Dataset 101"), + "icon": None, + } + + def _account(role: TenantAccountRole = TenantAccountRole.OWNER) -> Account: account = Account(name="Test User", email="u1@example.com") account.id = "u1" @@ -131,17 +344,24 @@ class TestPluginListLatestVersionsApi: api = PluginListLatestVersionsApi() method = unwrap(api.post) - payload = {"plugin_ids": ["p1"]} + payload = {"plugin_ids": ["langgenius/demo_plugin", "langgenius/missing_plugin"]} + versions = { + "langgenius/demo_plugin": _latest_plugin_cache(), + "langgenius/missing_plugin": None, + } with ( app.test_request_context("/", json=payload), - patch( - "controllers.console.workspace.plugin.PluginService.list_latest_versions", return_value={"p1": "1.0"} - ), + patch("controllers.console.workspace.plugin.PluginService.list_latest_versions", return_value=versions), ): result = method(api) - assert "versions" in result + assert result == { + "versions": { + "langgenius/demo_plugin": _expected_latest_plugin_cache_dump(), + "langgenius/missing_plugin": None, + } + } def test_daemon_error(self, app: Flask): api = PluginListLatestVersionsApi() @@ -193,18 +413,18 @@ class TestPluginListApi: api = PluginListApi() method = unwrap(api.get) - mock_list = MagicMock(list=[{"id": 1}], total=1) + plugins_with_total = MagicMock(list=[_plugin_entity()], total=1) with ( app.test_request_context("/?page=1&page_size=10"), patch( "controllers.console.workspace.plugin.PluginService.list_with_total", - return_value=mock_list, + return_value=plugins_with_total, ) as mock_list_with_total, ): result = method(api, "t1", "u1") - assert result["total"] == 1 + assert result == {"plugins": [_expected_plugin_entity_dump()], "total": 1} mock_list_with_total.assert_called_once_with("t1", "u1", 1, 10) @@ -445,12 +665,12 @@ class TestPluginFetchDynamicSelectOptionsApi: app.test_request_context("/?plugin_id=p&provider=x&action=y¶meter=z&provider_type=tool"), patch( "controllers.console.workspace.plugin.PluginParameterService.get_dynamic_select_options", - return_value=[1, 2], + return_value=[_dynamic_option()], ), ): result = method(api, "t1", user) - assert result["options"] == [1, 2] + assert result == {"options": [_expected_dynamic_option_dump()]} class TestPluginReadmeApi: @@ -472,18 +692,18 @@ class TestPluginListInstallationsFromIdsApi: api = PluginListInstallationsFromIdsApi() method = unwrap(api.post) - payload = {"plugin_ids": ["p1", "p2"]} + payload = {"plugin_ids": ["langgenius/demo_plugin"]} with ( app.test_request_context("/", json=payload), patch( "controllers.console.workspace.plugin.PluginService.list_installations_from_ids", - return_value=[{"id": "p1"}], + return_value=[_plugin_installation()], ), ): result = method(api, "t1") - assert "plugins" in result + assert result == {"plugins": [_expected_plugin_installation_dump()]} def test_daemon_error(self, app: Flask): api = PluginListInstallationsFromIdsApi() @@ -669,11 +889,14 @@ class TestPluginFetchMarketplacePkgApi: with ( app.test_request_context("/?plugin_unique_identifier=p"), - patch("controllers.console.workspace.plugin.PluginService.fetch_marketplace_pkg", return_value={"m": 1}), + patch( + "controllers.console.workspace.plugin.PluginService.fetch_marketplace_pkg", + return_value=_plugin_declaration(), + ), ): result = method(api, "t1") - assert "manifest" in result + assert result == {"manifest": _expected_plugin_declaration_dump()} def test_daemon_error(self, app: Flask): api = PluginFetchMarketplacePkgApi() @@ -695,8 +918,7 @@ class TestPluginFetchManifestApi: api = PluginFetchManifestApi() method = unwrap(api.get) - manifest = MagicMock() - manifest.model_dump.return_value = {"x": 1} + manifest = _plugin_declaration() with ( app.test_request_context("/?plugin_unique_identifier=p"), @@ -704,7 +926,7 @@ class TestPluginFetchManifestApi: ): result = method(api, "t1") - assert "manifest" in result + assert result == {"manifest": _expected_plugin_declaration_dump()} def test_daemon_error(self, app: Flask): api = PluginFetchManifestApi() @@ -728,11 +950,14 @@ class TestPluginFetchInstallTasksApi: with ( app.test_request_context("/?page=1&page_size=10"), - patch("controllers.console.workspace.plugin.PluginService.fetch_install_tasks", return_value=[{"id": 1}]), + patch( + "controllers.console.workspace.plugin.PluginService.fetch_install_tasks", + return_value=[_plugin_task()], + ), ): result = method(api, "t1") - assert "tasks" in result + assert result == {"tasks": [_expected_plugin_task_dump()]} def test_daemon_error(self, app: Flask): api = PluginFetchInstallTasksApi() @@ -756,11 +981,11 @@ class TestPluginFetchInstallTaskApi: with ( app.test_request_context("/"), - patch("controllers.console.workspace.plugin.PluginService.fetch_install_task", return_value={"id": "x"}), + patch("controllers.console.workspace.plugin.PluginService.fetch_install_task", return_value=_plugin_task()), ): result = method(api, "t1", "x") - assert "task" in result + assert result == {"task": _expected_plugin_task_dump()} def test_daemon_error(self, app: Flask): api = PluginFetchInstallTaskApi() @@ -969,12 +1194,12 @@ class TestPluginFetchDynamicSelectOptionsWithCredentialsApi: app.test_request_context("/", json=payload), patch( "controllers.console.workspace.plugin.PluginParameterService.get_dynamic_select_options_with_credentials", - return_value=[1], + return_value=[_dynamic_option()], ), ): result = method(api, "t1", user) - assert result["options"] == [1] + assert result == {"options": [_expected_dynamic_option_dump()]} def test_daemon_error(self, app: Flask, user): api = PluginFetchDynamicSelectOptionsWithCredentialsApi() diff --git a/packages/contracts/generated/api/console/apps/types.gen.ts b/packages/contracts/generated/api/console/apps/types.gen.ts index 9e79518f3cd..6451c741f4d 100644 --- a/packages/contracts/generated/api/console/apps/types.gen.ts +++ b/packages/contracts/generated/api/console/apps/types.gen.ts @@ -1987,20 +1987,21 @@ export type LlmMode = 'chat' | 'completion' export type Type = 'github' | 'marketplace' | 'package' export type Github = { - github_plugin_unique_identifier: string - package: string + packages: string + release: string repo: string - version: string + repo_address: string } export type Marketplace = { - marketplace_plugin_unique_identifier: string - version?: string | null + organization: string + plugin: string + version: string } export type Package = { - plugin_unique_identifier: string - version?: string | null + manifest: PluginDeclaration + unique_identifier: string } export type WorkflowOnlineUser = { @@ -2303,6 +2304,30 @@ export type CheckResultView = { reason?: string | null } +export type PluginDeclaration = { + agent_strategy?: AgentStrategyProviderEntity | null + author: string | null + category: PluginCategory + created_at: string + datasource?: DatasourceProviderEntity | null + description: CoreToolsEntitiesCommonEntitiesI18nObject + endpoint?: EndpointProviderDeclaration | null + icon: string + icon_dark?: string | null + label: CoreToolsEntitiesCommonEntitiesI18nObject + meta: Meta + model?: ProviderEntity | null + name: string + plugins: Plugins + repo?: string | null + resource: PluginResourceRequirements + tags?: Array + tool?: ToolProviderEntity | null + trigger?: TriggerProviderEntity | null + verified?: boolean + version: string +} + export type UserActionConfig = { button_style?: ButtonStyle id: string @@ -2519,6 +2544,89 @@ export type AgentPermissionConfig = { export type AgentCliToolRiskLevel = 'dangerous' | 'safe' | 'unknown' +export type AgentStrategyProviderEntity = { + identity: AgentStrategyProviderIdentity + plugin_id?: string | null +} + +export type PluginCategory + = | 'agent-strategy' + | 'datasource' + | 'extension' + | 'model' + | 'tool' + | 'trigger' + +export type DatasourceProviderEntity = { + credentials_schema?: Array + identity: DatasourceProviderIdentity + oauth_schema?: OAuthSchema | null + provider_type: DatasourceProviderType +} + +export type CoreToolsEntitiesCommonEntitiesI18nObject = { + en_US: string + ja_JP?: string | null + pt_BR?: string | null + zh_Hans?: string | null +} + +export type EndpointProviderDeclaration = { + endpoints?: Array | null + settings?: Array +} + +export type Meta = { + minimum_dify_version?: string | null + version?: string | null +} + +export type ProviderEntity = { + background?: string | null + configurate_methods: Array + description?: GraphonModelRuntimeEntitiesCommonEntitiesI18nObject | null + help?: ProviderHelpEntity | null + icon_small?: GraphonModelRuntimeEntitiesCommonEntitiesI18nObject | null + icon_small_dark?: GraphonModelRuntimeEntitiesCommonEntitiesI18nObject | null + label: GraphonModelRuntimeEntitiesCommonEntitiesI18nObject + model_credential_schema?: ModelCredentialSchema | null + models?: Array + position?: { + [key: string]: Array + } | null + provider: string + provider_credential_schema?: ProviderCredentialSchema | null + provider_name?: string + supported_model_types: Array +} + +export type Plugins = { + datasources?: Array | null + endpoints?: Array | null + models?: Array | null + tools?: Array | null + triggers?: Array | null +} + +export type PluginResourceRequirements = { + memory: number + permission?: Permission | null +} + +export type ToolProviderEntity = { + credentials_schema?: Array + identity: ToolProviderIdentity + oauth_schema?: OAuthSchema | null + plugin_id?: string | null +} + +export type TriggerProviderEntity = { + events?: Array + identity: TriggerProviderIdentity + subscription_constructor?: SubscriptionConstructor | null + subscription_schema?: Array +} + export type ButtonStyle = 'accent' | 'default' | 'ghost' | 'primary' export type ParagraphInputConfig = { @@ -2569,6 +2677,136 @@ export type AgentSoulDifyToolCredentialRef = { type?: 'provider' | 'tool' } +export type AgentStrategyProviderIdentity = { + author: string + description: CoreToolsEntitiesCommonEntitiesI18nObject + icon: string + icon_dark?: string | null + label: CoreToolsEntitiesCommonEntitiesI18nObject + name: string + tags?: Array | null +} + +export type ProviderConfig = { + default?: number | string | number | boolean | null + help?: CoreToolsEntitiesCommonEntitiesI18nObject | null + label?: CoreToolsEntitiesCommonEntitiesI18nObject | null + multiple?: boolean + name: string + options?: Array