This commit is contained in:
chariri 2026-06-25 18:39:38 +00:00 committed by GitHub
commit 80434bef9d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
22 changed files with 4985 additions and 576 deletions

View File

@ -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

View File

@ -167,12 +167,16 @@ register_schema_models(
ChatMessagesQuery,
MessageFeedbackPayload,
FeedbackExportQuery,
)
register_response_schema_models(
console_ns,
AnnotationCountResponse,
SuggestedQuestionsResponse,
MessageDetailResponse,
MessageInfiniteScrollPaginationResponse,
SimpleResultResponse,
TextFileResponse,
)
register_response_schema_models(console_ns, SimpleResultResponse, TextFileResponse)
@console_ns.route("/apps/<uuid:app_id>/chat-messages")

View File

@ -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/<path:provider>/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/<path:provider>/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/<string:tenant_id>/model-providers/<path:provider>/<string:icon_type>/<string:lang>")
@ -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/<path:provider>/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)

View File

@ -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/<path:provider>/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/<path:provider>/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/<path:provider>/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/<string:model_type>")
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")

View File

@ -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

File diff suppressed because it is too large Load Diff

View File

@ -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("/"),

View File

@ -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")

View File

@ -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&parameter=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()

View File

@ -269,6 +269,7 @@ export type MessageDetailResponse = {
agent_thoughts?: Array<AgentThought>
annotation?: ConversationAnnotation | null
annotation_hit_history?: ConversationAnnotationHitHistory | null
answer: string
answer_tokens?: number | null
conversation_id: string
created_at?: number | null
@ -284,12 +285,11 @@ export type MessageDetailResponse = {
}
message?: JsonValue | null
message_files?: Array<MessageFile>
message_metadata_dict?: JsonValue | null
message_tokens?: number | null
metadata?: JsonValue | null
parent_message_id?: string | null
provider_response_latency?: number | null
query: string
re_sign_file_url_answer: string
status: string
workflow_run_id?: string | null
}
@ -723,7 +723,6 @@ export type AgentThought = {
created_at?: number | null
files: Array<string>
id: string
message_chain_id?: string | null
message_id: string
observation?: string | null
position: number
@ -743,8 +742,8 @@ export type ConversationAnnotation = {
export type ConversationAnnotationHitHistory = {
annotation_create_account?: SimpleAccount | null
annotation_id: string
created_at?: number | null
id: string
}
export type HumanInputContent = {

View File

@ -570,7 +570,6 @@ export const zAgentThought = z.object({
created_at: z.int().nullish(),
files: z.array(z.string()),
id: z.string(),
message_chain_id: z.string().nullish(),
message_id: z.string(),
observation: z.string().nullish(),
position: z.int(),
@ -1056,8 +1055,8 @@ export const zConversationAnnotation = z.object({
*/
export const zConversationAnnotationHitHistory = z.object({
annotation_create_account: zSimpleAccount.nullish(),
annotation_id: z.string(),
created_at: z.int().nullish(),
id: z.string(),
})
/**
@ -2035,6 +2034,7 @@ export const zMessageDetailResponse = z.object({
agent_thoughts: z.array(zAgentThought).optional(),
annotation: zConversationAnnotation.nullish(),
annotation_hit_history: zConversationAnnotationHitHistory.nullish(),
answer: z.string(),
answer_tokens: z.int().nullish(),
conversation_id: z.string(),
created_at: z.int().nullish(),
@ -2048,12 +2048,11 @@ export const zMessageDetailResponse = z.object({
inputs: z.record(z.string(), zJsonValue),
message: zJsonValue.nullish(),
message_files: z.array(zMessageFile).optional(),
message_metadata_dict: zJsonValue.nullish(),
message_tokens: z.int().nullish(),
metadata: zJsonValue.nullish(),
parent_message_id: z.string().nullish(),
provider_response_latency: z.number().nullish(),
query: z.string(),
re_sign_file_url_answer: z.string(),
status: z.string(),
workflow_run_id: z.string().nullish(),
})

View File

@ -472,6 +472,7 @@ export type MessageDetailResponse = {
agent_thoughts?: Array<AgentThought>
annotation?: ConversationAnnotation | null
annotation_hit_history?: ConversationAnnotationHitHistory | null
answer: string
answer_tokens?: number | null
conversation_id: string
created_at?: number | null
@ -487,12 +488,11 @@ export type MessageDetailResponse = {
}
message?: JsonValue | null
message_files?: Array<MessageFile>
message_metadata_dict?: JsonValue | null
message_tokens?: number | null
metadata?: JsonValue | null
parent_message_id?: string | null
provider_response_latency?: number | null
query: string
re_sign_file_url_answer: string
status: string
workflow_run_id?: string | null
}
@ -1498,7 +1498,6 @@ export type AgentThought = {
created_at?: number | null
files: Array<string>
id: string
message_chain_id?: string | null
message_id: string
observation?: string | null
position: number
@ -1518,8 +1517,8 @@ export type ConversationAnnotation = {
export type ConversationAnnotationHitHistory = {
annotation_create_account?: SimpleAccount | null
annotation_id: string
created_at?: number | null
id: string
}
export type HumanInputContent = {
@ -1987,20 +1986,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 +2303,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<string>
tool?: ToolProviderEntity | null
trigger?: TriggerProviderEntity | null
verified?: boolean
version: string
}
export type UserActionConfig = {
button_style?: ButtonStyle
id: string
@ -2519,6 +2543,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<ProviderConfig>
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<EndpointDeclaration> | null
settings?: Array<ProviderConfig>
}
export type Meta = {
minimum_dify_version?: string | null
version?: string | null
}
export type ProviderEntity = {
background?: string | null
configurate_methods: Array<ConfigurateMethod>
description?: GraphonModelRuntimeEntitiesCommonEntitiesI18nObject | null
help?: ProviderHelpEntity | null
icon_small?: GraphonModelRuntimeEntitiesCommonEntitiesI18nObject | null
icon_small_dark?: GraphonModelRuntimeEntitiesCommonEntitiesI18nObject | null
label: GraphonModelRuntimeEntitiesCommonEntitiesI18nObject
model_credential_schema?: ModelCredentialSchema | null
models?: Array<AiModelEntity>
position?: {
[key: string]: Array<string>
} | null
provider: string
provider_credential_schema?: ProviderCredentialSchema | null
provider_name?: string
supported_model_types: Array<ModelType>
}
export type Plugins = {
datasources?: Array<string> | null
endpoints?: Array<string> | null
models?: Array<string> | null
tools?: Array<string> | null
triggers?: Array<string> | null
}
export type PluginResourceRequirements = {
memory: number
permission?: Permission | null
}
export type ToolProviderEntity = {
credentials_schema?: Array<ProviderConfig>
identity: ToolProviderIdentity
oauth_schema?: OAuthSchema | null
plugin_id?: string | null
}
export type TriggerProviderEntity = {
events?: Array<EventEntity>
identity: TriggerProviderIdentity
subscription_constructor?: SubscriptionConstructor | null
subscription_schema?: Array<ProviderConfig>
}
export type ButtonStyle = 'accent' | 'default' | 'ghost' | 'primary'
export type ParagraphInputConfig = {
@ -2569,6 +2676,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<ToolLabelEnum> | null
}
export type ProviderConfig = {
default?: number | string | number | boolean | null
help?: CoreToolsEntitiesCommonEntitiesI18nObject | null
label?: CoreToolsEntitiesCommonEntitiesI18nObject | null
multiple?: boolean
name: string
options?: Array<Option> | null
placeholder?: CoreToolsEntitiesCommonEntitiesI18nObject | null
required?: boolean
scope?: AppSelectorScope | ModelSelectorScope | ToolSelectorScope | null
type: CoreEntitiesProviderEntitiesBasicProviderConfigType
url?: string | null
}
export type DatasourceProviderIdentity = {
author: string
description: CoreToolsEntitiesCommonEntitiesI18nObject
icon: string
label: CoreToolsEntitiesCommonEntitiesI18nObject
name: string
tags?: Array<ToolLabelEnum> | null
}
export type OAuthSchema = {
client_schema?: Array<ProviderConfig>
credentials_schema?: Array<ProviderConfig>
}
export type DatasourceProviderType
= | 'local_file'
| 'online_document'
| 'online_drive'
| 'website_crawl'
export type EndpointDeclaration = {
hidden?: boolean
method: string
path: string
}
export type ConfigurateMethod = 'customizable-model' | 'predefined-model'
export type GraphonModelRuntimeEntitiesCommonEntitiesI18nObject = {
en_US: string
zh_Hans?: string | null
}
export type ProviderHelpEntity = {
title: GraphonModelRuntimeEntitiesCommonEntitiesI18nObject
url: GraphonModelRuntimeEntitiesCommonEntitiesI18nObject
}
export type ModelCredentialSchema = {
credential_form_schemas: Array<CredentialFormSchema>
model: FieldModelSchema
}
export type AiModelEntity = {
deprecated?: boolean
features?: Array<ModelFeature> | null
fetch_from: FetchFrom
label: GraphonModelRuntimeEntitiesCommonEntitiesI18nObject
model: string
model_properties: {
[key in ModelPropertyKey]?: unknown
}
model_type: ModelType
parameter_rules?: Array<ParameterRule>
pricing?: PriceConfig | null
}
export type ProviderCredentialSchema = {
credential_form_schemas: Array<CredentialFormSchema>
}
export type ModelType = 'llm' | 'moderation' | 'rerank' | 'speech2text' | 'text-embedding' | 'tts'
export type Permission = {
endpoint?: Endpoint | null
model?: Model | null
node?: Node | null
storage?: Storage | null
tool?: Tool | null
}
export type ToolProviderIdentity = {
author: string
description: CoreToolsEntitiesCommonEntitiesI18nObject
icon: string
icon_dark?: string | null
label: CoreToolsEntitiesCommonEntitiesI18nObject
name: string
tags?: Array<ToolLabelEnum> | null
}
export type EventEntity = {
description: CoreToolsEntitiesCommonEntitiesI18nObject
identity: EventIdentity
output_schema?: {
[key: string]: unknown
} | null
parameters?: Array<EventParameter>
}
export type TriggerProviderIdentity = {
author: string
description: CoreToolsEntitiesCommonEntitiesI18nObject
icon?: string | null
icon_dark?: string | null
label: CoreToolsEntitiesCommonEntitiesI18nObject
name: string
tags?: Array<string>
}
export type SubscriptionConstructor = {
credentials_schema?: Array<ProviderConfig>
oauth_schema?: OAuthSchema | null
parameters?: Array<EventParameter>
}
export type StringSource = {
selector?: Array<string>
type: ValueSourceType
@ -2591,8 +2828,215 @@ export type AgentModerationIoConfig = {
[key: string]: unknown
}
export type ToolLabelEnum
= | 'business'
| 'design'
| 'education'
| 'entertainment'
| 'finance'
| 'image'
| 'medical'
| 'news'
| 'other'
| 'productivity'
| 'rag'
| 'search'
| 'social'
| 'travel'
| 'utilities'
| 'videos'
| 'weather'
export type Option = {
label: CoreToolsEntitiesCommonEntitiesI18nObject
value: string
}
export type AppSelectorScope = 'all' | 'chat' | 'completion' | 'workflow'
export type ModelSelectorScope
= | 'llm'
| 'moderation'
| 'rerank'
| 'speech2text'
| 'text-embedding'
| 'tts'
| 'vision'
export type ToolSelectorScope = 'all' | 'builtin' | 'custom' | 'workflow'
export type CoreEntitiesProviderEntitiesBasicProviderConfigType
= | 'app-selector'
| 'array[tools]'
| 'boolean'
| 'model-selector'
| 'secret-input'
| 'select'
| 'text-input'
export type CredentialFormSchema = {
default?: string | null
label: GraphonModelRuntimeEntitiesCommonEntitiesI18nObject
max_length?: number
options?: Array<FormOption> | null
placeholder?: GraphonModelRuntimeEntitiesCommonEntitiesI18nObject | null
required?: boolean
show_on?: Array<FormShowOnObject>
type: FormType
variable: string
}
export type FieldModelSchema = {
label: GraphonModelRuntimeEntitiesCommonEntitiesI18nObject
placeholder?: GraphonModelRuntimeEntitiesCommonEntitiesI18nObject | null
}
export type ModelFeature
= | 'agent-thought'
| 'audio'
| 'document'
| 'multi-tool-call'
| 'polling'
| 'stream-tool-call'
| 'structured-output'
| 'tool-call'
| 'video'
| 'vision'
export type FetchFrom = 'customizable-model' | 'predefined-model'
export type ModelPropertyKey
= | 'audio_type'
| 'context_size'
| 'default_voice'
| 'file_upload_limit'
| 'max_characters_per_chunk'
| 'max_chunks'
| 'max_workers'
| 'mode'
| 'supported_file_extensions'
| 'voices'
| 'word_limit'
export type ParameterRule = {
default?: unknown | null
help?: GraphonModelRuntimeEntitiesCommonEntitiesI18nObject | null
label: GraphonModelRuntimeEntitiesCommonEntitiesI18nObject
max?: number | null
min?: number | null
name: string
options?: Array<string>
precision?: number | null
required?: boolean
type: ParameterType
use_template?: string | null
}
export type PriceConfig = {
currency: string
input: string
output?: string | null
unit: string
}
export type Endpoint = {
enabled?: boolean | null
}
export type Model = {
enabled?: boolean | null
llm?: boolean | null
moderation?: boolean | null
rerank?: boolean | null
speech2text?: boolean | null
text_embedding?: boolean | null
tts?: boolean | null
}
export type Node = {
enabled?: boolean | null
}
export type Storage = {
enabled?: boolean | null
size?: number
}
export type Tool = {
enabled?: boolean | null
}
export type EventIdentity = {
author: string
label: CoreToolsEntitiesCommonEntitiesI18nObject
name: string
provider?: string | null
}
export type EventParameter = {
auto_generate?: PluginParameterAutoGenerate | null
default?: number | number | string | Array<unknown> | null
description?: CoreToolsEntitiesCommonEntitiesI18nObject | null
label: CoreToolsEntitiesCommonEntitiesI18nObject
max?: number | number | null
min?: number | number | null
multiple?: boolean
name: string
options?: Array<PluginParameterOption> | null
precision?: number | null
required?: boolean
scope?: string | null
template?: PluginParameterTemplate | null
type: EventParameterType
}
export type ValueSourceType = 'constant' | 'variable'
export type FormOption = {
label: GraphonModelRuntimeEntitiesCommonEntitiesI18nObject
show_on?: Array<FormShowOnObject>
value: string
}
export type FormShowOnObject = {
value: string
variable: string
}
export type FormType = 'radio' | 'secret-input' | 'select' | 'switch' | 'text-input'
export type ParameterType = 'boolean' | 'float' | 'int' | 'string' | 'text'
export type PluginParameterAutoGenerate = {
type: CorePluginEntitiesParametersPluginParameterAutoGenerateType
}
export type PluginParameterOption = {
icon?: string | null
label: CoreToolsEntitiesCommonEntitiesI18nObject
value: string
}
export type PluginParameterTemplate = {
enabled?: boolean
}
export type EventParameterType
= | 'app-selector'
| 'array'
| 'boolean'
| 'checkbox'
| 'dynamic-select'
| 'file'
| 'files'
| 'model-selector'
| 'number'
| 'object'
| 'select'
| 'string'
export type CorePluginEntitiesParametersPluginParameterAutoGenerateType = 'prompt_instruction'
export type AppPaginationWritable = {
data: Array<AppPartialWritable>
has_more: boolean

View File

@ -1150,7 +1150,6 @@ export const zAgentThought = z.object({
created_at: z.int().nullish(),
files: z.array(z.string()),
id: z.string(),
message_chain_id: z.string().nullish(),
message_id: z.string(),
observation: z.string().nullish(),
position: z.int(),
@ -1371,8 +1370,8 @@ export const zConversationAnnotation = z.object({
*/
export const zConversationAnnotationHitHistory = z.object({
annotation_create_account: zSimpleAccount.nullish(),
annotation_id: z.string(),
created_at: z.int().nullish(),
id: z.string(),
})
/**
@ -2175,42 +2174,19 @@ export const zType = z.enum(['github', 'marketplace', 'package'])
* Github
*/
export const zGithub = z.object({
github_plugin_unique_identifier: z.string(),
package: z.string(),
packages: z.string(),
release: z.string(),
repo: z.string(),
version: z.string(),
repo_address: z.string(),
})
/**
* Marketplace
*/
export const zMarketplace = z.object({
marketplace_plugin_unique_identifier: z.string(),
version: z.string().nullish(),
})
/**
* Package
*/
export const zPackage = z.object({
plugin_unique_identifier: z.string(),
version: z.string().nullish(),
})
/**
* PluginDependency
*/
export const zPluginDependency = z.object({
current_identifier: z.string().nullish(),
type: zType,
value: z.union([zGithub, zMarketplace, zPackage]),
})
/**
* CheckDependenciesResult
*/
export const zCheckDependenciesResult = z.object({
leaked_dependencies: z.array(zPluginDependency).optional(),
organization: z.string(),
plugin: z.string(),
version: z.string(),
})
/**
@ -3039,6 +3015,49 @@ export const zAgentComposerCandidatesResponse = z.object({
variant: zComposerVariant,
})
/**
* PluginCategory
*/
export const zPluginCategory = z.enum([
'agent-strategy',
'datasource',
'extension',
'model',
'tool',
'trigger',
])
/**
* I18nObject
*
* Model class for i18n object.
*/
export const zCoreToolsEntitiesCommonEntitiesI18nObject = z.object({
en_US: z.string(),
ja_JP: z.string().nullish(),
pt_BR: z.string().nullish(),
zh_Hans: z.string().nullish(),
})
/**
* Meta
*/
export const zMeta = z.object({
minimum_dify_version: z.string().nullish(),
version: z.string().nullish(),
})
/**
* Plugins
*/
export const zPlugins = z.object({
datasources: z.array(z.string()).nullish(),
endpoints: z.array(z.string()).nullish(),
models: z.array(z.string()).nullish(),
tools: z.array(z.string()).nullish(),
triggers: z.array(z.string()).nullish(),
})
/**
* ButtonStyle
*
@ -3229,6 +3248,85 @@ export const zAgentSoulToolsConfig = z.object({
dify_tools: z.array(zAgentSoulDifyToolConfig).optional(),
})
/**
* DatasourceProviderType
*
* Enum class for datasource provider
*/
export const zDatasourceProviderType = z.enum([
'local_file',
'online_document',
'online_drive',
'website_crawl',
])
/**
* EndpointDeclaration
*
* declaration of an endpoint
*/
export const zEndpointDeclaration = z.object({
hidden: z.boolean().optional().default(false),
method: z.string(),
path: z.string(),
})
/**
* ConfigurateMethod
*
* Enum class for configurate method of provider model.
*/
export const zConfigurateMethod = z.enum(['customizable-model', 'predefined-model'])
/**
* I18nObject
*
* Model class for i18n object.
*/
export const zGraphonModelRuntimeEntitiesCommonEntitiesI18nObject = z.object({
en_US: z.string(),
zh_Hans: z.string().nullish(),
})
/**
* ProviderHelpEntity
*
* Model class for provider help.
*/
export const zProviderHelpEntity = z.object({
title: zGraphonModelRuntimeEntitiesCommonEntitiesI18nObject,
url: zGraphonModelRuntimeEntitiesCommonEntitiesI18nObject,
})
/**
* ModelType
*
* Enum class for model type.
*/
export const zModelType = z.enum([
'llm',
'moderation',
'rerank',
'speech2text',
'text-embedding',
'tts',
])
/**
* TriggerProviderIdentity
*
* The identity of the trigger provider
*/
export const zTriggerProviderIdentity = z.object({
author: z.string(),
description: zCoreToolsEntitiesCommonEntitiesI18nObject,
icon: z.string().nullish(),
icon_dark: z.string().nullish(),
label: zCoreToolsEntitiesCommonEntitiesI18nObject,
name: z.string(),
tags: z.array(z.string()).optional(),
})
/**
* FileType
*/
@ -3366,6 +3464,322 @@ export const zComposerSavePayload = z.object({
version_note: z.string().nullish(),
})
/**
* ToolLabelEnum
*/
export const zToolLabelEnum = z.enum([
'business',
'design',
'education',
'entertainment',
'finance',
'image',
'medical',
'news',
'other',
'productivity',
'rag',
'search',
'social',
'travel',
'utilities',
'videos',
'weather',
])
/**
* AgentStrategyProviderIdentity
*
* Inherits from ToolProviderIdentity, without any additional fields.
*/
export const zAgentStrategyProviderIdentity = z.object({
author: z.string(),
description: zCoreToolsEntitiesCommonEntitiesI18nObject,
icon: z.string(),
icon_dark: z.string().nullish(),
label: zCoreToolsEntitiesCommonEntitiesI18nObject,
name: z.string(),
tags: z.array(zToolLabelEnum).nullish().default([]),
})
/**
* AgentStrategyProviderEntity
*/
export const zAgentStrategyProviderEntity = z.object({
identity: zAgentStrategyProviderIdentity,
plugin_id: z.string().nullish(),
})
/**
* DatasourceProviderIdentity
*/
export const zDatasourceProviderIdentity = z.object({
author: z.string(),
description: zCoreToolsEntitiesCommonEntitiesI18nObject,
icon: z.string(),
label: zCoreToolsEntitiesCommonEntitiesI18nObject,
name: z.string(),
tags: z.array(zToolLabelEnum).nullish().default([]),
})
/**
* ToolProviderIdentity
*/
export const zToolProviderIdentity = z.object({
author: z.string(),
description: zCoreToolsEntitiesCommonEntitiesI18nObject,
icon: z.string(),
icon_dark: z.string().nullish(),
label: zCoreToolsEntitiesCommonEntitiesI18nObject,
name: z.string(),
tags: z.array(zToolLabelEnum).nullish().default([]),
})
/**
* Option
*/
export const zOption = z.object({
label: zCoreToolsEntitiesCommonEntitiesI18nObject,
value: z.string(),
})
/**
* AppSelectorScope
*/
export const zAppSelectorScope = z.enum(['all', 'chat', 'completion', 'workflow'])
/**
* ModelSelectorScope
*/
export const zModelSelectorScope = z.enum([
'llm',
'moderation',
'rerank',
'speech2text',
'text-embedding',
'tts',
'vision',
])
/**
* ToolSelectorScope
*/
export const zToolSelectorScope = z.enum(['all', 'builtin', 'custom', 'workflow'])
/**
* Type
*/
export const zCoreEntitiesProviderEntitiesBasicProviderConfigType = z.enum([
'app-selector',
'array[tools]',
'boolean',
'model-selector',
'secret-input',
'select',
'text-input',
])
/**
* ProviderConfig
*
* Model class for common provider settings like credentials
*/
export const zProviderConfig = z.object({
default: z.union([z.int(), z.string(), z.number(), z.boolean()]).nullish(),
help: zCoreToolsEntitiesCommonEntitiesI18nObject.nullish(),
label: zCoreToolsEntitiesCommonEntitiesI18nObject.nullish(),
multiple: z.boolean().optional().default(false),
name: z.string(),
options: z.array(zOption).nullish(),
placeholder: zCoreToolsEntitiesCommonEntitiesI18nObject.nullish(),
required: z.boolean().optional().default(false),
scope: z.union([zAppSelectorScope, zModelSelectorScope, zToolSelectorScope]).nullish(),
type: zCoreEntitiesProviderEntitiesBasicProviderConfigType,
url: z.string().nullish(),
})
/**
* EndpointProviderDeclaration
*
* declaration of an endpoint group
*/
export const zEndpointProviderDeclaration = z.object({
endpoints: z.array(zEndpointDeclaration).nullish(),
settings: z.array(zProviderConfig).optional(),
})
/**
* OAuthSchema
*
* OAuth schema
*/
export const zOAuthSchema = z.object({
client_schema: z.array(zProviderConfig).optional(),
credentials_schema: z.array(zProviderConfig).optional(),
})
/**
* DatasourceProviderEntity
*
* Datasource provider entity
*/
export const zDatasourceProviderEntity = z.object({
credentials_schema: z.array(zProviderConfig).optional(),
identity: zDatasourceProviderIdentity,
oauth_schema: zOAuthSchema.nullish(),
provider_type: zDatasourceProviderType,
})
/**
* ToolProviderEntity
*/
export const zToolProviderEntity = z.object({
credentials_schema: z.array(zProviderConfig).optional(),
identity: zToolProviderIdentity,
oauth_schema: zOAuthSchema.nullish(),
plugin_id: z.string().nullish(),
})
/**
* FieldModelSchema
*/
export const zFieldModelSchema = z.object({
label: zGraphonModelRuntimeEntitiesCommonEntitiesI18nObject,
placeholder: zGraphonModelRuntimeEntitiesCommonEntitiesI18nObject.nullish(),
})
/**
* ModelFeature
*
* Enum class for llm feature.
*/
export const zModelFeature = z.enum([
'agent-thought',
'audio',
'document',
'multi-tool-call',
'polling',
'stream-tool-call',
'structured-output',
'tool-call',
'video',
'vision',
])
/**
* FetchFrom
*
* Enum class for fetch from.
*/
export const zFetchFrom = z.enum(['customizable-model', 'predefined-model'])
/**
* ModelPropertyKey
*
* Enum class for model property key.
*/
export const zModelPropertyKey = z.enum([
'audio_type',
'context_size',
'default_voice',
'file_upload_limit',
'max_characters_per_chunk',
'max_chunks',
'max_workers',
'mode',
'supported_file_extensions',
'voices',
'word_limit',
])
/**
* PriceConfig
*
* Model class for pricing info.
*/
export const zPriceConfig = z.object({
currency: z.string(),
input: z.string().regex(/^(?![-+.]*$)[+-]?\d*(?:\.\d*)?$/),
output: z
.string()
.regex(/^(?![-+.]*$)[+-]?\d*(?:\.\d*)?$/)
.nullish(),
unit: z.string().regex(/^(?![-+.]*$)[+-]?\d*(?:\.\d*)?$/),
})
/**
* Endpoint
*/
export const zEndpoint = z.object({
enabled: z.boolean().nullish().default(false),
})
/**
* Model
*/
export const zModel = z.object({
enabled: z.boolean().nullish().default(false),
llm: z.boolean().nullish().default(false),
moderation: z.boolean().nullish().default(false),
rerank: z.boolean().nullish().default(false),
speech2text: z.boolean().nullish().default(false),
text_embedding: z.boolean().nullish().default(false),
tts: z.boolean().nullish().default(false),
})
/**
* Node
*/
export const zNode = z.object({
enabled: z.boolean().nullish().default(false),
})
/**
* Storage
*/
export const zStorage = z.object({
enabled: z.boolean().nullish().default(false),
size: z.int().gte(1024).lte(1073741824).optional().default(1048576),
})
/**
* Tool
*/
export const zTool = z.object({
enabled: z.boolean().nullish().default(false),
})
/**
* Permission
*/
export const zPermission = z.object({
endpoint: zEndpoint.nullish(),
model: zModel.nullish(),
node: zNode.nullish(),
storage: zStorage.nullish(),
tool: zTool.nullish(),
})
/**
* PluginResourceRequirements
*/
export const zPluginResourceRequirements = z.object({
memory: z.int(),
permission: zPermission.nullish(),
})
/**
* EventIdentity
*
* The identity of the event
*/
export const zEventIdentity = z.object({
author: z.string(),
label: zCoreToolsEntitiesCommonEntitiesI18nObject,
name: z.string(),
provider: z.string().nullish(),
})
/**
* ValueSourceType
*
@ -3455,6 +3869,7 @@ export const zMessageDetailResponse = z.object({
agent_thoughts: z.array(zAgentThought).optional(),
annotation: zConversationAnnotation.nullish(),
annotation_hit_history: zConversationAnnotationHitHistory.nullish(),
answer: z.string(),
answer_tokens: z.int().nullish(),
conversation_id: z.string(),
created_at: z.int().nullish(),
@ -3468,12 +3883,11 @@ export const zMessageDetailResponse = z.object({
inputs: z.record(z.string(), zJsonValue),
message: zJsonValue.nullish(),
message_files: z.array(zMessageFile).optional(),
message_metadata_dict: zJsonValue.nullish(),
message_tokens: z.int().nullish(),
metadata: zJsonValue.nullish(),
parent_message_id: z.string().nullish(),
provider_response_latency: z.number().nullish(),
query: z.string(),
re_sign_file_url_answer: z.string(),
status: z.string(),
workflow_run_id: z.string().nullish(),
})
@ -3487,6 +3901,300 @@ export const zMessageInfiniteScrollPaginationResponse = z.object({
limit: z.int(),
})
/**
* FormShowOnObject
*
* Model class for form show on.
*/
export const zFormShowOnObject = z.object({
value: z.string(),
variable: z.string(),
})
/**
* FormOption
*
* Model class for form option.
*/
export const zFormOption = z.object({
label: zGraphonModelRuntimeEntitiesCommonEntitiesI18nObject,
show_on: z.array(zFormShowOnObject).optional().default([]),
value: z.string(),
})
/**
* FormType
*
* Enum class for form type.
*/
export const zFormType = z.enum(['radio', 'secret-input', 'select', 'switch', 'text-input'])
/**
* CredentialFormSchema
*
* Model class for credential form schema.
*/
export const zCredentialFormSchema = z.object({
default: z.string().nullish(),
label: zGraphonModelRuntimeEntitiesCommonEntitiesI18nObject,
max_length: z.int().optional().default(0),
options: z.array(zFormOption).nullish(),
placeholder: zGraphonModelRuntimeEntitiesCommonEntitiesI18nObject.nullish(),
required: z.boolean().optional().default(true),
show_on: z.array(zFormShowOnObject).optional().default([]),
type: zFormType,
variable: z.string(),
})
/**
* ModelCredentialSchema
*
* Model class for model credential schema.
*/
export const zModelCredentialSchema = z.object({
credential_form_schemas: z.array(zCredentialFormSchema),
model: zFieldModelSchema,
})
/**
* ProviderCredentialSchema
*
* Model class for provider credential schema.
*/
export const zProviderCredentialSchema = z.object({
credential_form_schemas: z.array(zCredentialFormSchema),
})
/**
* ParameterType
*
* Enum class for parameter type.
*/
export const zParameterType = z.enum(['boolean', 'float', 'int', 'string', 'text'])
/**
* ParameterRule
*
* Model class for parameter rule.
*/
export const zParameterRule = z.object({
default: z.unknown().nullish(),
help: zGraphonModelRuntimeEntitiesCommonEntitiesI18nObject.nullish(),
label: zGraphonModelRuntimeEntitiesCommonEntitiesI18nObject,
max: z.number().nullish(),
min: z.number().nullish(),
name: z.string(),
options: z.array(z.string()).optional().default([]),
precision: z.int().nullish(),
required: z.boolean().optional().default(false),
type: zParameterType,
use_template: z.string().nullish(),
})
/**
* AIModelEntity
*
* Model class for AI model.
*/
export const zAiModelEntity = z.object({
deprecated: z.boolean().optional().default(false),
features: z.array(zModelFeature).nullish(),
fetch_from: zFetchFrom,
label: zGraphonModelRuntimeEntitiesCommonEntitiesI18nObject,
model: z.string(),
model_properties: z.record(z.string(), z.unknown()),
model_type: zModelType,
parameter_rules: z.array(zParameterRule).optional().default([]),
pricing: zPriceConfig.nullish(),
})
/**
* 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.
*/
export const zProviderEntity = z.object({
background: z.string().nullish(),
configurate_methods: z.array(zConfigurateMethod),
description: zGraphonModelRuntimeEntitiesCommonEntitiesI18nObject.nullish(),
help: zProviderHelpEntity.nullish(),
icon_small: zGraphonModelRuntimeEntitiesCommonEntitiesI18nObject.nullish(),
icon_small_dark: zGraphonModelRuntimeEntitiesCommonEntitiesI18nObject.nullish(),
label: zGraphonModelRuntimeEntitiesCommonEntitiesI18nObject,
model_credential_schema: zModelCredentialSchema.nullish(),
models: z.array(zAiModelEntity).optional(),
position: z.record(z.string(), z.array(z.string())).nullish().default({}),
provider: z.string(),
provider_credential_schema: zProviderCredentialSchema.nullish(),
provider_name: z.string().optional().default(''),
supported_model_types: z.array(zModelType),
})
/**
* PluginParameterOption
*/
export const zPluginParameterOption = z.object({
icon: z.string().nullish(),
label: zCoreToolsEntitiesCommonEntitiesI18nObject,
value: z.string(),
})
/**
* PluginParameterTemplate
*/
export const zPluginParameterTemplate = z.object({
enabled: z.boolean().optional().default(false),
})
/**
* EventParameterType
*
* The type of the parameter
*/
export const zEventParameterType = z.enum([
'app-selector',
'array',
'boolean',
'checkbox',
'dynamic-select',
'file',
'files',
'model-selector',
'number',
'object',
'select',
'string',
])
/**
* Type
*/
export const zCorePluginEntitiesParametersPluginParameterAutoGenerateType = z.enum([
'prompt_instruction',
])
/**
* PluginParameterAutoGenerate
*/
export const zPluginParameterAutoGenerate = z.object({
type: zCorePluginEntitiesParametersPluginParameterAutoGenerateType,
})
/**
* EventParameter
*
* The parameter of the event
*/
export const zEventParameter = z.object({
auto_generate: zPluginParameterAutoGenerate.nullish(),
default: z.union([z.int(), z.number(), z.string(), z.array(z.unknown())]).nullish(),
description: zCoreToolsEntitiesCommonEntitiesI18nObject.nullish(),
label: zCoreToolsEntitiesCommonEntitiesI18nObject,
max: z.union([z.number(), z.int()]).nullish(),
min: z.union([z.number(), z.int()]).nullish(),
multiple: z.boolean().optional().default(false),
name: z.string(),
options: z.array(zPluginParameterOption).nullish(),
precision: z.int().nullish(),
required: z.boolean().optional().default(false),
scope: z.string().nullish(),
template: zPluginParameterTemplate.nullish(),
type: zEventParameterType,
})
/**
* EventEntity
*
* The configuration of an event
*/
export const zEventEntity = z.object({
description: zCoreToolsEntitiesCommonEntitiesI18nObject,
identity: zEventIdentity,
output_schema: z.record(z.string(), z.unknown()).nullish(),
parameters: z.array(zEventParameter).optional(),
})
/**
* SubscriptionConstructor
*
* The subscription constructor of the trigger provider
*/
export const zSubscriptionConstructor = z.object({
credentials_schema: z.array(zProviderConfig).optional(),
oauth_schema: zOAuthSchema.nullish(),
parameters: z.array(zEventParameter).optional(),
})
/**
* TriggerProviderEntity
*
* The configuration of a trigger provider
*/
export const zTriggerProviderEntity = z.object({
events: z.array(zEventEntity).optional(),
identity: zTriggerProviderIdentity,
subscription_constructor: zSubscriptionConstructor.nullish(),
subscription_schema: z.array(zProviderConfig).optional(),
})
/**
* PluginDeclaration
*/
export const zPluginDeclaration = z.object({
agent_strategy: zAgentStrategyProviderEntity.nullish(),
author: z
.string()
.regex(/^[\w-]{1,64}$/)
.nullable(),
category: zPluginCategory,
created_at: z.iso.datetime(),
datasource: zDatasourceProviderEntity.nullish(),
description: zCoreToolsEntitiesCommonEntitiesI18nObject,
endpoint: zEndpointProviderDeclaration.nullish(),
icon: z.string(),
icon_dark: z.string().nullish(),
label: zCoreToolsEntitiesCommonEntitiesI18nObject,
meta: zMeta,
model: zProviderEntity.nullish(),
name: z.string().regex(/^[a-z0-9_-]{1,128}$/),
plugins: zPlugins,
repo: z.string().nullish(),
resource: zPluginResourceRequirements,
tags: z.array(z.string()).optional(),
tool: zToolProviderEntity.nullish(),
trigger: zTriggerProviderEntity.nullish(),
verified: z.boolean().optional().default(false),
version: z.string(),
})
/**
* Package
*/
export const zPackage = z.object({
manifest: zPluginDeclaration,
unique_identifier: z.string(),
})
/**
* PluginDependency
*/
export const zPluginDependency = z.object({
current_identifier: z.string().nullish(),
type: zType,
value: z.union([zGithub, zMarketplace, zPackage]),
})
/**
* CheckDependenciesResult
*/
export const zCheckDependenciesResult = z.object({
leaked_dependencies: z.array(zPluginDependency).optional(),
})
/**
* GeneratedAppResponse
*/

View File

@ -246,7 +246,6 @@ export type AgentThought = {
created_at?: number | null
files: Array<string>
id: string
message_chain_id?: string | null
message_id: string
observation?: string | null
position: number

View File

@ -266,7 +266,6 @@ export const zAgentThought = z.object({
created_at: z.int().nullish(),
files: z.array(z.string()),
id: z.string(),
message_chain_id: z.string().nullish(),
message_id: z.string(),
observation: z.string().nullish(),
position: z.int(),

View File

@ -518,20 +518,21 @@ export type DatasetWeightedScoreResponse = {
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 DatasetKeywordSettingResponse = {
@ -544,6 +545,450 @@ export type DatasetVectorSettingResponse = {
vector_weight?: number | 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<string>
tool?: ToolProviderEntity | null
trigger?: TriggerProviderEntity | null
verified?: boolean
version: string
}
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<ProviderConfig>
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<EndpointDeclaration> | null
settings?: Array<ProviderConfig>
}
export type Meta = {
minimum_dify_version?: string | null
version?: string | null
}
export type ProviderEntity = {
background?: string | null
configurate_methods: Array<ConfigurateMethod>
description?: GraphonModelRuntimeEntitiesCommonEntitiesI18nObject | null
help?: ProviderHelpEntity | null
icon_small?: GraphonModelRuntimeEntitiesCommonEntitiesI18nObject | null
icon_small_dark?: GraphonModelRuntimeEntitiesCommonEntitiesI18nObject | null
label: GraphonModelRuntimeEntitiesCommonEntitiesI18nObject
model_credential_schema?: ModelCredentialSchema | null
models?: Array<AiModelEntity>
position?: {
[key: string]: Array<string>
} | null
provider: string
provider_credential_schema?: ProviderCredentialSchema | null
provider_name?: string
supported_model_types: Array<ModelType>
}
export type Plugins = {
datasources?: Array<string> | null
endpoints?: Array<string> | null
models?: Array<string> | null
tools?: Array<string> | null
triggers?: Array<string> | null
}
export type PluginResourceRequirements = {
memory: number
permission?: Permission | null
}
export type ToolProviderEntity = {
credentials_schema?: Array<ProviderConfig>
identity: ToolProviderIdentity
oauth_schema?: OAuthSchema | null
plugin_id?: string | null
}
export type TriggerProviderEntity = {
events?: Array<EventEntity>
identity: TriggerProviderIdentity
subscription_constructor?: SubscriptionConstructor | null
subscription_schema?: Array<ProviderConfig>
}
export type AgentStrategyProviderIdentity = {
author: string
description: CoreToolsEntitiesCommonEntitiesI18nObject
icon: string
icon_dark?: string | null
label: CoreToolsEntitiesCommonEntitiesI18nObject
name: string
tags?: Array<ToolLabelEnum> | null
}
export type ProviderConfig = {
default?: number | string | number | boolean | null
help?: CoreToolsEntitiesCommonEntitiesI18nObject | null
label?: CoreToolsEntitiesCommonEntitiesI18nObject | null
multiple?: boolean
name: string
options?: Array<Option> | null
placeholder?: CoreToolsEntitiesCommonEntitiesI18nObject | null
required?: boolean
scope?: AppSelectorScope | ModelSelectorScope | ToolSelectorScope | null
type: CoreEntitiesProviderEntitiesBasicProviderConfigType
url?: string | null
}
export type DatasourceProviderIdentity = {
author: string
description: CoreToolsEntitiesCommonEntitiesI18nObject
icon: string
label: CoreToolsEntitiesCommonEntitiesI18nObject
name: string
tags?: Array<ToolLabelEnum> | null
}
export type OAuthSchema = {
client_schema?: Array<ProviderConfig>
credentials_schema?: Array<ProviderConfig>
}
export type DatasourceProviderType
= | 'local_file'
| 'online_document'
| 'online_drive'
| 'website_crawl'
export type EndpointDeclaration = {
hidden?: boolean
method: string
path: string
}
export type ConfigurateMethod = 'customizable-model' | 'predefined-model'
export type GraphonModelRuntimeEntitiesCommonEntitiesI18nObject = {
en_US: string
zh_Hans?: string | null
}
export type ProviderHelpEntity = {
title: GraphonModelRuntimeEntitiesCommonEntitiesI18nObject
url: GraphonModelRuntimeEntitiesCommonEntitiesI18nObject
}
export type ModelCredentialSchema = {
credential_form_schemas: Array<CredentialFormSchema>
model: FieldModelSchema
}
export type AiModelEntity = {
deprecated?: boolean
features?: Array<ModelFeature> | null
fetch_from: FetchFrom
label: GraphonModelRuntimeEntitiesCommonEntitiesI18nObject
model: string
model_properties: {
[key in ModelPropertyKey]?: unknown
}
model_type: ModelType
parameter_rules?: Array<ParameterRule>
pricing?: PriceConfig | null
}
export type ProviderCredentialSchema = {
credential_form_schemas: Array<CredentialFormSchema>
}
export type ModelType = 'llm' | 'moderation' | 'rerank' | 'speech2text' | 'text-embedding' | 'tts'
export type Permission = {
endpoint?: Endpoint | null
model?: Model | null
node?: Node | null
storage?: Storage | null
tool?: Tool | null
}
export type ToolProviderIdentity = {
author: string
description: CoreToolsEntitiesCommonEntitiesI18nObject
icon: string
icon_dark?: string | null
label: CoreToolsEntitiesCommonEntitiesI18nObject
name: string
tags?: Array<ToolLabelEnum> | null
}
export type EventEntity = {
description: CoreToolsEntitiesCommonEntitiesI18nObject
identity: EventIdentity
output_schema?: {
[key: string]: unknown
} | null
parameters?: Array<EventParameter>
}
export type TriggerProviderIdentity = {
author: string
description: CoreToolsEntitiesCommonEntitiesI18nObject
icon?: string | null
icon_dark?: string | null
label: CoreToolsEntitiesCommonEntitiesI18nObject
name: string
tags?: Array<string>
}
export type SubscriptionConstructor = {
credentials_schema?: Array<ProviderConfig>
oauth_schema?: OAuthSchema | null
parameters?: Array<EventParameter>
}
export type ToolLabelEnum
= | 'business'
| 'design'
| 'education'
| 'entertainment'
| 'finance'
| 'image'
| 'medical'
| 'news'
| 'other'
| 'productivity'
| 'rag'
| 'search'
| 'social'
| 'travel'
| 'utilities'
| 'videos'
| 'weather'
export type Option = {
label: CoreToolsEntitiesCommonEntitiesI18nObject
value: string
}
export type AppSelectorScope = 'all' | 'chat' | 'completion' | 'workflow'
export type ModelSelectorScope
= | 'llm'
| 'moderation'
| 'rerank'
| 'speech2text'
| 'text-embedding'
| 'tts'
| 'vision'
export type ToolSelectorScope = 'all' | 'builtin' | 'custom' | 'workflow'
export type CoreEntitiesProviderEntitiesBasicProviderConfigType
= | 'app-selector'
| 'array[tools]'
| 'boolean'
| 'model-selector'
| 'secret-input'
| 'select'
| 'text-input'
export type CredentialFormSchema = {
default?: string | null
label: GraphonModelRuntimeEntitiesCommonEntitiesI18nObject
max_length?: number
options?: Array<FormOption> | null
placeholder?: GraphonModelRuntimeEntitiesCommonEntitiesI18nObject | null
required?: boolean
show_on?: Array<FormShowOnObject>
type: FormType
variable: string
}
export type FieldModelSchema = {
label: GraphonModelRuntimeEntitiesCommonEntitiesI18nObject
placeholder?: GraphonModelRuntimeEntitiesCommonEntitiesI18nObject | null
}
export type ModelFeature
= | 'agent-thought'
| 'audio'
| 'document'
| 'multi-tool-call'
| 'polling'
| 'stream-tool-call'
| 'structured-output'
| 'tool-call'
| 'video'
| 'vision'
export type FetchFrom = 'customizable-model' | 'predefined-model'
export type ModelPropertyKey
= | 'audio_type'
| 'context_size'
| 'default_voice'
| 'file_upload_limit'
| 'max_characters_per_chunk'
| 'max_chunks'
| 'max_workers'
| 'mode'
| 'supported_file_extensions'
| 'voices'
| 'word_limit'
export type ParameterRule = {
default?: unknown | null
help?: GraphonModelRuntimeEntitiesCommonEntitiesI18nObject | null
label: GraphonModelRuntimeEntitiesCommonEntitiesI18nObject
max?: number | null
min?: number | null
name: string
options?: Array<string>
precision?: number | null
required?: boolean
type: ParameterType
use_template?: string | null
}
export type PriceConfig = {
currency: string
input: string
output?: string | null
unit: string
}
export type Endpoint = {
enabled?: boolean | null
}
export type Model = {
enabled?: boolean | null
llm?: boolean | null
moderation?: boolean | null
rerank?: boolean | null
speech2text?: boolean | null
text_embedding?: boolean | null
tts?: boolean | null
}
export type Node = {
enabled?: boolean | null
}
export type Storage = {
enabled?: boolean | null
size?: number
}
export type Tool = {
enabled?: boolean | null
}
export type EventIdentity = {
author: string
label: CoreToolsEntitiesCommonEntitiesI18nObject
name: string
provider?: string | null
}
export type EventParameter = {
auto_generate?: PluginParameterAutoGenerate | null
default?: number | number | string | Array<unknown> | null
description?: CoreToolsEntitiesCommonEntitiesI18nObject | null
label: CoreToolsEntitiesCommonEntitiesI18nObject
max?: number | number | null
min?: number | number | null
multiple?: boolean
name: string
options?: Array<PluginParameterOption> | null
precision?: number | null
required?: boolean
scope?: string | null
template?: PluginParameterTemplate | null
type: EventParameterType
}
export type FormOption = {
label: GraphonModelRuntimeEntitiesCommonEntitiesI18nObject
show_on?: Array<FormShowOnObject>
value: string
}
export type FormShowOnObject = {
value: string
variable: string
}
export type FormType = 'radio' | 'secret-input' | 'select' | 'switch' | 'text-input'
export type ParameterType = 'boolean' | 'float' | 'int' | 'string' | 'text'
export type PluginParameterAutoGenerate = {
type: CorePluginEntitiesParametersPluginParameterAutoGenerateType
}
export type PluginParameterOption = {
icon?: string | null
label: CoreToolsEntitiesCommonEntitiesI18nObject
value: string
}
export type PluginParameterTemplate = {
enabled?: boolean
}
export type EventParameterType
= | 'app-selector'
| 'array'
| 'boolean'
| 'checkbox'
| 'dynamic-select'
| 'file'
| 'files'
| 'model-selector'
| 'number'
| 'object'
| 'select'
| 'string'
export type CorePluginEntitiesParametersPluginParameterAutoGenerateType = 'prompt_instruction'
export type DeleteRagPipelineCustomizedTemplatesByTemplateIdData = {
body?: never
path: {

View File

@ -553,42 +553,19 @@ export const zType = z.enum(['github', 'marketplace', 'package'])
* Github
*/
export const zGithub = z.object({
github_plugin_unique_identifier: z.string(),
package: z.string(),
packages: z.string(),
release: z.string(),
repo: z.string(),
version: z.string(),
repo_address: z.string(),
})
/**
* Marketplace
*/
export const zMarketplace = z.object({
marketplace_plugin_unique_identifier: z.string(),
version: z.string().nullish(),
})
/**
* Package
*/
export const zPackage = z.object({
plugin_unique_identifier: z.string(),
version: z.string().nullish(),
})
/**
* PluginDependency
*/
export const zPluginDependency = z.object({
current_identifier: z.string().nullish(),
type: zType,
value: z.union([zGithub, zMarketplace, zPackage]),
})
/**
* RagPipelineImportCheckDependenciesResponse
*/
export const zRagPipelineImportCheckDependenciesResponse = z.object({
leaked_dependencies: z.array(zPluginDependency).optional(),
organization: z.string(),
plugin: z.string(),
version: z.string(),
})
/**
@ -673,6 +650,738 @@ export const zDatasetDetailResponse = z.object({
word_count: z.int(),
})
/**
* PluginCategory
*/
export const zPluginCategory = z.enum([
'agent-strategy',
'datasource',
'extension',
'model',
'tool',
'trigger',
])
/**
* I18nObject
*
* Model class for i18n object.
*/
export const zCoreToolsEntitiesCommonEntitiesI18nObject = z.object({
en_US: z.string(),
ja_JP: z.string().nullish(),
pt_BR: z.string().nullish(),
zh_Hans: z.string().nullish(),
})
/**
* Meta
*/
export const zMeta = z.object({
minimum_dify_version: z.string().nullish(),
version: z.string().nullish(),
})
/**
* Plugins
*/
export const zPlugins = z.object({
datasources: z.array(z.string()).nullish(),
endpoints: z.array(z.string()).nullish(),
models: z.array(z.string()).nullish(),
tools: z.array(z.string()).nullish(),
triggers: z.array(z.string()).nullish(),
})
/**
* DatasourceProviderType
*
* Enum class for datasource provider
*/
export const zDatasourceProviderType = z.enum([
'local_file',
'online_document',
'online_drive',
'website_crawl',
])
/**
* EndpointDeclaration
*
* declaration of an endpoint
*/
export const zEndpointDeclaration = z.object({
hidden: z.boolean().optional().default(false),
method: z.string(),
path: z.string(),
})
/**
* ConfigurateMethod
*
* Enum class for configurate method of provider model.
*/
export const zConfigurateMethod = z.enum(['customizable-model', 'predefined-model'])
/**
* I18nObject
*
* Model class for i18n object.
*/
export const zGraphonModelRuntimeEntitiesCommonEntitiesI18nObject = z.object({
en_US: z.string(),
zh_Hans: z.string().nullish(),
})
/**
* ProviderHelpEntity
*
* Model class for provider help.
*/
export const zProviderHelpEntity = z.object({
title: zGraphonModelRuntimeEntitiesCommonEntitiesI18nObject,
url: zGraphonModelRuntimeEntitiesCommonEntitiesI18nObject,
})
/**
* ModelType
*
* Enum class for model type.
*/
export const zModelType = z.enum([
'llm',
'moderation',
'rerank',
'speech2text',
'text-embedding',
'tts',
])
/**
* TriggerProviderIdentity
*
* The identity of the trigger provider
*/
export const zTriggerProviderIdentity = z.object({
author: z.string(),
description: zCoreToolsEntitiesCommonEntitiesI18nObject,
icon: z.string().nullish(),
icon_dark: z.string().nullish(),
label: zCoreToolsEntitiesCommonEntitiesI18nObject,
name: z.string(),
tags: z.array(z.string()).optional(),
})
/**
* ToolLabelEnum
*/
export const zToolLabelEnum = z.enum([
'business',
'design',
'education',
'entertainment',
'finance',
'image',
'medical',
'news',
'other',
'productivity',
'rag',
'search',
'social',
'travel',
'utilities',
'videos',
'weather',
])
/**
* AgentStrategyProviderIdentity
*
* Inherits from ToolProviderIdentity, without any additional fields.
*/
export const zAgentStrategyProviderIdentity = z.object({
author: z.string(),
description: zCoreToolsEntitiesCommonEntitiesI18nObject,
icon: z.string(),
icon_dark: z.string().nullish(),
label: zCoreToolsEntitiesCommonEntitiesI18nObject,
name: z.string(),
tags: z.array(zToolLabelEnum).nullish().default([]),
})
/**
* AgentStrategyProviderEntity
*/
export const zAgentStrategyProviderEntity = z.object({
identity: zAgentStrategyProviderIdentity,
plugin_id: z.string().nullish(),
})
/**
* DatasourceProviderIdentity
*/
export const zDatasourceProviderIdentity = z.object({
author: z.string(),
description: zCoreToolsEntitiesCommonEntitiesI18nObject,
icon: z.string(),
label: zCoreToolsEntitiesCommonEntitiesI18nObject,
name: z.string(),
tags: z.array(zToolLabelEnum).nullish().default([]),
})
/**
* ToolProviderIdentity
*/
export const zToolProviderIdentity = z.object({
author: z.string(),
description: zCoreToolsEntitiesCommonEntitiesI18nObject,
icon: z.string(),
icon_dark: z.string().nullish(),
label: zCoreToolsEntitiesCommonEntitiesI18nObject,
name: z.string(),
tags: z.array(zToolLabelEnum).nullish().default([]),
})
/**
* Option
*/
export const zOption = z.object({
label: zCoreToolsEntitiesCommonEntitiesI18nObject,
value: z.string(),
})
/**
* AppSelectorScope
*/
export const zAppSelectorScope = z.enum(['all', 'chat', 'completion', 'workflow'])
/**
* ModelSelectorScope
*/
export const zModelSelectorScope = z.enum([
'llm',
'moderation',
'rerank',
'speech2text',
'text-embedding',
'tts',
'vision',
])
/**
* ToolSelectorScope
*/
export const zToolSelectorScope = z.enum(['all', 'builtin', 'custom', 'workflow'])
/**
* Type
*/
export const zCoreEntitiesProviderEntitiesBasicProviderConfigType = z.enum([
'app-selector',
'array[tools]',
'boolean',
'model-selector',
'secret-input',
'select',
'text-input',
])
/**
* ProviderConfig
*
* Model class for common provider settings like credentials
*/
export const zProviderConfig = z.object({
default: z.union([z.int(), z.string(), z.number(), z.boolean()]).nullish(),
help: zCoreToolsEntitiesCommonEntitiesI18nObject.nullish(),
label: zCoreToolsEntitiesCommonEntitiesI18nObject.nullish(),
multiple: z.boolean().optional().default(false),
name: z.string(),
options: z.array(zOption).nullish(),
placeholder: zCoreToolsEntitiesCommonEntitiesI18nObject.nullish(),
required: z.boolean().optional().default(false),
scope: z.union([zAppSelectorScope, zModelSelectorScope, zToolSelectorScope]).nullish(),
type: zCoreEntitiesProviderEntitiesBasicProviderConfigType,
url: z.string().nullish(),
})
/**
* EndpointProviderDeclaration
*
* declaration of an endpoint group
*/
export const zEndpointProviderDeclaration = z.object({
endpoints: z.array(zEndpointDeclaration).nullish(),
settings: z.array(zProviderConfig).optional(),
})
/**
* OAuthSchema
*
* OAuth schema
*/
export const zOAuthSchema = z.object({
client_schema: z.array(zProviderConfig).optional(),
credentials_schema: z.array(zProviderConfig).optional(),
})
/**
* DatasourceProviderEntity
*
* Datasource provider entity
*/
export const zDatasourceProviderEntity = z.object({
credentials_schema: z.array(zProviderConfig).optional(),
identity: zDatasourceProviderIdentity,
oauth_schema: zOAuthSchema.nullish(),
provider_type: zDatasourceProviderType,
})
/**
* ToolProviderEntity
*/
export const zToolProviderEntity = z.object({
credentials_schema: z.array(zProviderConfig).optional(),
identity: zToolProviderIdentity,
oauth_schema: zOAuthSchema.nullish(),
plugin_id: z.string().nullish(),
})
/**
* FieldModelSchema
*/
export const zFieldModelSchema = z.object({
label: zGraphonModelRuntimeEntitiesCommonEntitiesI18nObject,
placeholder: zGraphonModelRuntimeEntitiesCommonEntitiesI18nObject.nullish(),
})
/**
* ModelFeature
*
* Enum class for llm feature.
*/
export const zModelFeature = z.enum([
'agent-thought',
'audio',
'document',
'multi-tool-call',
'polling',
'stream-tool-call',
'structured-output',
'tool-call',
'video',
'vision',
])
/**
* FetchFrom
*
* Enum class for fetch from.
*/
export const zFetchFrom = z.enum(['customizable-model', 'predefined-model'])
/**
* ModelPropertyKey
*
* Enum class for model property key.
*/
export const zModelPropertyKey = z.enum([
'audio_type',
'context_size',
'default_voice',
'file_upload_limit',
'max_characters_per_chunk',
'max_chunks',
'max_workers',
'mode',
'supported_file_extensions',
'voices',
'word_limit',
])
/**
* PriceConfig
*
* Model class for pricing info.
*/
export const zPriceConfig = z.object({
currency: z.string(),
input: z.string().regex(/^(?![-+.]*$)[+-]?\d*(?:\.\d*)?$/),
output: z
.string()
.regex(/^(?![-+.]*$)[+-]?\d*(?:\.\d*)?$/)
.nullish(),
unit: z.string().regex(/^(?![-+.]*$)[+-]?\d*(?:\.\d*)?$/),
})
/**
* Endpoint
*/
export const zEndpoint = z.object({
enabled: z.boolean().nullish().default(false),
})
/**
* Model
*/
export const zModel = z.object({
enabled: z.boolean().nullish().default(false),
llm: z.boolean().nullish().default(false),
moderation: z.boolean().nullish().default(false),
rerank: z.boolean().nullish().default(false),
speech2text: z.boolean().nullish().default(false),
text_embedding: z.boolean().nullish().default(false),
tts: z.boolean().nullish().default(false),
})
/**
* Node
*/
export const zNode = z.object({
enabled: z.boolean().nullish().default(false),
})
/**
* Storage
*/
export const zStorage = z.object({
enabled: z.boolean().nullish().default(false),
size: z.int().gte(1024).lte(1073741824).optional().default(1048576),
})
/**
* Tool
*/
export const zTool = z.object({
enabled: z.boolean().nullish().default(false),
})
/**
* Permission
*/
export const zPermission = z.object({
endpoint: zEndpoint.nullish(),
model: zModel.nullish(),
node: zNode.nullish(),
storage: zStorage.nullish(),
tool: zTool.nullish(),
})
/**
* PluginResourceRequirements
*/
export const zPluginResourceRequirements = z.object({
memory: z.int(),
permission: zPermission.nullish(),
})
/**
* EventIdentity
*
* The identity of the event
*/
export const zEventIdentity = z.object({
author: z.string(),
label: zCoreToolsEntitiesCommonEntitiesI18nObject,
name: z.string(),
provider: z.string().nullish(),
})
/**
* FormShowOnObject
*
* Model class for form show on.
*/
export const zFormShowOnObject = z.object({
value: z.string(),
variable: z.string(),
})
/**
* FormOption
*
* Model class for form option.
*/
export const zFormOption = z.object({
label: zGraphonModelRuntimeEntitiesCommonEntitiesI18nObject,
show_on: z.array(zFormShowOnObject).optional().default([]),
value: z.string(),
})
/**
* FormType
*
* Enum class for form type.
*/
export const zFormType = z.enum(['radio', 'secret-input', 'select', 'switch', 'text-input'])
/**
* CredentialFormSchema
*
* Model class for credential form schema.
*/
export const zCredentialFormSchema = z.object({
default: z.string().nullish(),
label: zGraphonModelRuntimeEntitiesCommonEntitiesI18nObject,
max_length: z.int().optional().default(0),
options: z.array(zFormOption).nullish(),
placeholder: zGraphonModelRuntimeEntitiesCommonEntitiesI18nObject.nullish(),
required: z.boolean().optional().default(true),
show_on: z.array(zFormShowOnObject).optional().default([]),
type: zFormType,
variable: z.string(),
})
/**
* ModelCredentialSchema
*
* Model class for model credential schema.
*/
export const zModelCredentialSchema = z.object({
credential_form_schemas: z.array(zCredentialFormSchema),
model: zFieldModelSchema,
})
/**
* ProviderCredentialSchema
*
* Model class for provider credential schema.
*/
export const zProviderCredentialSchema = z.object({
credential_form_schemas: z.array(zCredentialFormSchema),
})
/**
* ParameterType
*
* Enum class for parameter type.
*/
export const zParameterType = z.enum(['boolean', 'float', 'int', 'string', 'text'])
/**
* ParameterRule
*
* Model class for parameter rule.
*/
export const zParameterRule = z.object({
default: z.unknown().nullish(),
help: zGraphonModelRuntimeEntitiesCommonEntitiesI18nObject.nullish(),
label: zGraphonModelRuntimeEntitiesCommonEntitiesI18nObject,
max: z.number().nullish(),
min: z.number().nullish(),
name: z.string(),
options: z.array(z.string()).optional().default([]),
precision: z.int().nullish(),
required: z.boolean().optional().default(false),
type: zParameterType,
use_template: z.string().nullish(),
})
/**
* AIModelEntity
*
* Model class for AI model.
*/
export const zAiModelEntity = z.object({
deprecated: z.boolean().optional().default(false),
features: z.array(zModelFeature).nullish(),
fetch_from: zFetchFrom,
label: zGraphonModelRuntimeEntitiesCommonEntitiesI18nObject,
model: z.string(),
model_properties: z.record(z.string(), z.unknown()),
model_type: zModelType,
parameter_rules: z.array(zParameterRule).optional().default([]),
pricing: zPriceConfig.nullish(),
})
/**
* 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.
*/
export const zProviderEntity = z.object({
background: z.string().nullish(),
configurate_methods: z.array(zConfigurateMethod),
description: zGraphonModelRuntimeEntitiesCommonEntitiesI18nObject.nullish(),
help: zProviderHelpEntity.nullish(),
icon_small: zGraphonModelRuntimeEntitiesCommonEntitiesI18nObject.nullish(),
icon_small_dark: zGraphonModelRuntimeEntitiesCommonEntitiesI18nObject.nullish(),
label: zGraphonModelRuntimeEntitiesCommonEntitiesI18nObject,
model_credential_schema: zModelCredentialSchema.nullish(),
models: z.array(zAiModelEntity).optional(),
position: z.record(z.string(), z.array(z.string())).nullish().default({}),
provider: z.string(),
provider_credential_schema: zProviderCredentialSchema.nullish(),
provider_name: z.string().optional().default(''),
supported_model_types: z.array(zModelType),
})
/**
* PluginParameterOption
*/
export const zPluginParameterOption = z.object({
icon: z.string().nullish(),
label: zCoreToolsEntitiesCommonEntitiesI18nObject,
value: z.string(),
})
/**
* PluginParameterTemplate
*/
export const zPluginParameterTemplate = z.object({
enabled: z.boolean().optional().default(false),
})
/**
* EventParameterType
*
* The type of the parameter
*/
export const zEventParameterType = z.enum([
'app-selector',
'array',
'boolean',
'checkbox',
'dynamic-select',
'file',
'files',
'model-selector',
'number',
'object',
'select',
'string',
])
/**
* Type
*/
export const zCorePluginEntitiesParametersPluginParameterAutoGenerateType = z.enum([
'prompt_instruction',
])
/**
* PluginParameterAutoGenerate
*/
export const zPluginParameterAutoGenerate = z.object({
type: zCorePluginEntitiesParametersPluginParameterAutoGenerateType,
})
/**
* EventParameter
*
* The parameter of the event
*/
export const zEventParameter = z.object({
auto_generate: zPluginParameterAutoGenerate.nullish(),
default: z.union([z.int(), z.number(), z.string(), z.array(z.unknown())]).nullish(),
description: zCoreToolsEntitiesCommonEntitiesI18nObject.nullish(),
label: zCoreToolsEntitiesCommonEntitiesI18nObject,
max: z.union([z.number(), z.int()]).nullish(),
min: z.union([z.number(), z.int()]).nullish(),
multiple: z.boolean().optional().default(false),
name: z.string(),
options: z.array(zPluginParameterOption).nullish(),
precision: z.int().nullish(),
required: z.boolean().optional().default(false),
scope: z.string().nullish(),
template: zPluginParameterTemplate.nullish(),
type: zEventParameterType,
})
/**
* EventEntity
*
* The configuration of an event
*/
export const zEventEntity = z.object({
description: zCoreToolsEntitiesCommonEntitiesI18nObject,
identity: zEventIdentity,
output_schema: z.record(z.string(), z.unknown()).nullish(),
parameters: z.array(zEventParameter).optional(),
})
/**
* SubscriptionConstructor
*
* The subscription constructor of the trigger provider
*/
export const zSubscriptionConstructor = z.object({
credentials_schema: z.array(zProviderConfig).optional(),
oauth_schema: zOAuthSchema.nullish(),
parameters: z.array(zEventParameter).optional(),
})
/**
* TriggerProviderEntity
*
* The configuration of a trigger provider
*/
export const zTriggerProviderEntity = z.object({
events: z.array(zEventEntity).optional(),
identity: zTriggerProviderIdentity,
subscription_constructor: zSubscriptionConstructor.nullish(),
subscription_schema: z.array(zProviderConfig).optional(),
})
/**
* PluginDeclaration
*/
export const zPluginDeclaration = z.object({
agent_strategy: zAgentStrategyProviderEntity.nullish(),
author: z
.string()
.regex(/^[\w-]{1,64}$/)
.nullable(),
category: zPluginCategory,
created_at: z.iso.datetime(),
datasource: zDatasourceProviderEntity.nullish(),
description: zCoreToolsEntitiesCommonEntitiesI18nObject,
endpoint: zEndpointProviderDeclaration.nullish(),
icon: z.string(),
icon_dark: z.string().nullish(),
label: zCoreToolsEntitiesCommonEntitiesI18nObject,
meta: zMeta,
model: zProviderEntity.nullish(),
name: z.string().regex(/^[a-z0-9_-]{1,128}$/),
plugins: zPlugins,
repo: z.string().nullish(),
resource: zPluginResourceRequirements,
tags: z.array(z.string()).optional(),
tool: zToolProviderEntity.nullish(),
trigger: zTriggerProviderEntity.nullish(),
verified: z.boolean().optional().default(false),
version: z.string(),
})
/**
* Package
*/
export const zPackage = z.object({
manifest: zPluginDeclaration,
unique_identifier: z.string(),
})
/**
* PluginDependency
*/
export const zPluginDependency = z.object({
current_identifier: z.string().nullish(),
type: zType,
value: z.union([zGithub, zMarketplace, zPackage]),
})
/**
* RagPipelineImportCheckDependenciesResponse
*/
export const zRagPipelineImportCheckDependenciesResponse = z.object({
leaked_dependencies: z.array(zPluginDependency).optional(),
})
export const zDeleteRagPipelineCustomizedTemplatesByTemplateIdPath = z.object({
template_id: z.string(),
})

View File

@ -33,8 +33,6 @@ import {
zDeleteWorkspacesCurrentToolProviderMcpResponse,
zDeleteWorkspacesCurrentTriggerProviderByProviderOauthClientPath,
zDeleteWorkspacesCurrentTriggerProviderByProviderOauthClientResponse,
zGetWorkspacesByTenantIdModelProvidersByProviderByIconTypeByLangPath,
zGetWorkspacesByTenantIdModelProvidersByProviderByIconTypeByLangResponse,
zGetWorkspacesCurrentAgentProviderByProviderNamePath,
zGetWorkspacesCurrentAgentProviderByProviderNameResponse,
zGetWorkspacesCurrentAgentProvidersResponse,
@ -4178,37 +4176,6 @@ export const switch3 = {
}
export const get90 = oc
.route({
inputStructure: 'detailed',
method: 'GET',
operationId: 'getWorkspacesByTenantIdModelProvidersByProviderByIconTypeByLang',
path: '/workspaces/{tenant_id}/model-providers/{provider}/{icon_type}/{lang}',
tags: ['console'],
})
.input(z.object({ params: zGetWorkspacesByTenantIdModelProvidersByProviderByIconTypeByLangPath }))
.output(zGetWorkspacesByTenantIdModelProvidersByProviderByIconTypeByLangResponse)
export const byLang = {
get: get90,
}
export const byIconType = {
byLang,
}
export const byProvider4 = {
byIconType,
}
export const modelProviders2 = {
byProvider: byProvider4,
}
export const byTenantId = {
modelProviders: modelProviders2,
}
export const get91 = oc
.route({
inputStructure: 'detailed',
method: 'GET',
@ -4219,12 +4186,11 @@ export const get91 = oc
.output(zGetWorkspacesResponse)
export const workspaces = {
get: get91,
get: get90,
current,
customConfig,
info: info4,
switch: switch3,
byTenantId,
}
export const contract = {

View File

@ -236,7 +236,7 @@ export type ParserCredentialDelete = {
credential_id: string
}
export type ProviderCredentialResponse = {
export type ProviderCredentialsResponse = {
credentials?: {
[key: string]: unknown
} | null
@ -267,7 +267,7 @@ export type ParserCredentialValidate = {
}
}
export type ProviderCredentialValidateResponse = {
export type ValidationResultResponse = {
error?: string | null
result: 'error' | 'success'
}
@ -277,7 +277,7 @@ export type ParserDeleteModels = {
model_type: ModelType
}
export type ModelWithProviderListResponse = {
export type ProviderModelListResponse = {
data: Array<ModelWithProviderEntityResponse>
}
@ -297,12 +297,12 @@ export type ParserDeleteCredential = {
export type ModelCredentialResponse = {
available_credentials: Array<CredentialConfiguration>
credentials?: {
credentials: {
[key: string]: unknown
}
current_credential_id?: string | null
current_credential_name?: string | null
load_balancing: ModelCredentialLoadBalancingResponse
load_balancing: ModelLoadBalancingResponse
}
export type ParserCreateCredential = {
@ -338,11 +338,6 @@ export type ParserValidate = {
model_type: ModelType
}
export type ModelCredentialValidateResponse = {
error?: string | null
result: string
}
export type LoadBalancingCredentialPayload = {
credentials: {
[key: string]: unknown
@ -356,7 +351,7 @@ export type LoadBalancingCredentialValidateResponse = {
result: string
}
export type ModelParameterRulesResponse = {
export type ModelParameterRuleListResponse = {
data: Array<ParameterRule>
}
@ -364,7 +359,7 @@ export type ParserPreferredProviderType = {
preferred_provider_type: 'custom' | 'system'
}
export type ProviderWithModelsDataResponse = {
export type AvailableModelListResponse = {
data: Array<ProviderWithModelsResponse>
}
@ -407,7 +402,7 @@ export type PluginDebuggingKeyResponse = {
}
export type PluginManifestResponse = {
manifest: unknown
manifest: PluginDeclaration
}
export type ParserGithubInstall = {
@ -417,14 +412,18 @@ export type ParserGithubInstall = {
version: string
}
export type PluginDaemonOperationResponse = unknown
export type PluginInstallTaskStartResponse = {
all_installed: boolean
task?: PluginInstallTask | null
task_id: string
}
export type ParserPluginIdentifiers = {
plugin_unique_identifiers: Array<string>
}
export type PluginListResponse = {
plugins: unknown
plugins: Array<PluginEntity>
total: number
}
@ -433,15 +432,17 @@ export type ParserLatest = {
}
export type PluginInstallationsResponse = {
plugins: unknown
plugins: Array<PluginInstallation>
}
export type PluginVersionsResponse = {
versions: unknown
versions: {
[key: string]: LatestPluginCache | null
}
}
export type PluginDynamicOptionsResponse = {
options: unknown
options: Array<PluginParameterOption>
}
export type ParserDynamicOptionsWithCredentials = {
@ -470,11 +471,11 @@ export type PluginReadmeResponse = {
}
export type PluginTasksResponse = {
tasks: unknown
tasks: Array<PluginInstallTask>
}
export type PluginTaskResponse = {
task: unknown
task: PluginInstallTask
}
export type ParserUninstall = {
@ -494,12 +495,20 @@ export type ParserMarketplaceUpgrade = {
original_plugin_unique_identifier: string
}
export type PluginBundleUploadResponse = Array<PluginBundleDependency>
export type ParserGithubUpload = {
package: string
repo: string
version: string
}
export type PluginDecodeResponse = {
manifest: PluginDeclaration
unique_identifier: string
verification?: PluginVerification | null
}
export type PluginCategoryListResponse = {
builtin_tools: Array<PluginCategoryBuiltinToolProviderResponse>
has_more: boolean
@ -1003,10 +1012,8 @@ export type CredentialConfiguration = {
credential_name: string
}
export type ModelCredentialLoadBalancingResponse = {
configs?: Array<{
[key: string]: unknown
}>
export type ModelLoadBalancingResponse = {
configs: Array<ModelLoadBalancingConfigResponse>
enabled: boolean
}
@ -1058,10 +1065,108 @@ export type PluginAutoUpgradeSettingsResponseModel = {
upgrade_time_of_day: number
}
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<string>
tool?: ToolProviderEntity | null
trigger?: TriggerProviderEntity | null
verified?: boolean
version: string
}
export type PluginInstallTask = {
completed_plugins: number
created_at: string
id: string
plugins: Array<PluginInstallTaskPluginStatus>
status: PluginInstallTaskStatus
total_plugins: number
updated_at: string
}
export type PluginEntity = {
checksum: string
created_at: string
declaration: PluginDeclaration
endpoints_active: number
endpoints_setups: number
id: string
installation_id: string
meta: {
[key: string]: unknown
}
name: string
plugin_id: string
plugin_unique_identifier: string
runtime_type: string
source: PluginInstallationSource
tenant_id: string
updated_at: string
version: string
}
export type PluginInstallation = {
checksum: string
created_at: string
declaration: PluginDeclaration
endpoints_active: number
endpoints_setups: number
id: string
meta: {
[key: string]: unknown
}
plugin_id: string
plugin_unique_identifier: string
runtime_type: string
source: PluginInstallationSource
tenant_id: string
updated_at: string
version: string
}
export type LatestPluginCache = {
alternative_plugin_id: string
deprecated_reason: string
plugin_id: string
status: string
unique_identifier: string
version: string
}
export type PluginParameterOption = {
icon?: string | null
label: CoreToolsEntitiesCommonEntitiesI18nObject
value: string
}
export type DebugPermission = 'admins' | 'everyone' | 'noone'
export type InstallPermission = 'admins' | 'everyone' | 'noone'
export type PluginBundleDependency = {
type: CorePluginEntitiesBundlePluginBundleDependencyType
value: Github | Marketplace | Package
}
export type PluginVerification = {
authorized_category: AuthorizedCategory
}
export type PluginCategoryBuiltinToolProviderResponse = {
allow_delete: boolean
author: string
@ -1284,6 +1389,18 @@ export type ModelStatus
| 'no-permission'
| 'quota-exceeded'
export type ModelLoadBalancingConfigResponse = {
credential_id?: string | null
credentials: {
[key: string]: unknown
}
enabled: boolean
id: string
in_cooldown: boolean
name: string
ttl: number
}
export type GraphonModelRuntimeEntitiesCommonEntitiesI18nObject = {
en_US: string
zh_Hans?: string | null
@ -1312,6 +1429,18 @@ export type StrategySetting = 'disabled' | 'fix_only' | 'latest'
export type UpgradeMode = 'all' | 'exclude' | 'partial'
export type AgentStrategyProviderEntity = {
identity: AgentStrategyProviderIdentity
plugin_id?: string | null
}
export type DatasourceProviderEntity = {
credentials_schema?: Array<ProviderConfig>
identity: DatasourceProviderIdentity
oauth_schema?: OAuthSchema | null
provider_type: DatasourceProviderType
}
export type CoreToolsEntitiesCommonEntitiesI18nObject = {
en_US: string
ja_JP?: string | null
@ -1319,6 +1448,101 @@ export type CoreToolsEntitiesCommonEntitiesI18nObject = {
zh_Hans?: string | null
}
export type EndpointProviderDeclaration = {
endpoints?: Array<EndpointDeclaration> | null
settings?: Array<ProviderConfig>
}
export type Meta = {
minimum_dify_version?: string | null
version?: string | null
}
export type ProviderEntity = {
background?: string | null
configurate_methods: Array<ConfigurateMethod>
description?: GraphonModelRuntimeEntitiesCommonEntitiesI18nObject | null
help?: ProviderHelpEntity | null
icon_small?: GraphonModelRuntimeEntitiesCommonEntitiesI18nObject | null
icon_small_dark?: GraphonModelRuntimeEntitiesCommonEntitiesI18nObject | null
label: GraphonModelRuntimeEntitiesCommonEntitiesI18nObject
model_credential_schema?: ModelCredentialSchema | null
models?: Array<AiModelEntity>
position?: {
[key: string]: Array<string>
} | null
provider: string
provider_credential_schema?: ProviderCredentialSchema | null
provider_name?: string
supported_model_types: Array<ModelType>
}
export type Plugins = {
datasources?: Array<string> | null
endpoints?: Array<string> | null
models?: Array<string> | null
tools?: Array<string> | null
triggers?: Array<string> | null
}
export type PluginResourceRequirements = {
memory: number
permission?: Permission | null
}
export type ToolProviderEntity = {
credentials_schema?: Array<ProviderConfig>
identity: ToolProviderIdentity
oauth_schema?: OAuthSchema | null
plugin_id?: string | null
}
export type TriggerProviderEntity = {
events?: Array<EventEntity>
identity: TriggerProviderIdentity
subscription_constructor?: SubscriptionConstructor | null
subscription_schema?: Array<ProviderConfig>
}
export type PluginInstallTaskPluginStatus = {
icon: string
labels: I18nObject
message: string
plugin_id: string
plugin_unique_identifier: string
source?: string | null
status: PluginInstallTaskStatus
}
export type PluginInstallTaskStatus = 'failed' | 'pending' | 'running' | 'success'
export type PluginInstallationSource = 'github' | 'marketplace' | 'package' | 'remote'
export type CorePluginEntitiesBundlePluginBundleDependencyType
= | 'github'
| 'marketplace'
| 'package'
export type Github = {
packages: string
release: string
repo: string
repo_address: string
}
export type Marketplace = {
organization: string
plugin: string
version: string
}
export type Package = {
manifest: PluginDeclaration
unique_identifier: string
}
export type AuthorizedCategory = 'community' | 'langgenius' | 'partner'
export type PluginCategoryBuiltinToolResponse = {
author: string
description: CoreToolsEntitiesCommonEntitiesI18nObject
@ -1383,8 +1607,6 @@ export type PluginDeclarationResponse = {
version: string
}
export type PluginInstallationSource = 'github' | 'marketplace' | 'package' | 'remote'
export type RbacRoleAccount = {
account_id: string
account_name?: string
@ -1464,6 +1686,113 @@ export type QuotaConfiguration = {
restrict_models?: Array<RestrictModel>
}
export type AgentStrategyProviderIdentity = {
author: string
description: CoreToolsEntitiesCommonEntitiesI18nObject
icon: string
icon_dark?: string | null
label: CoreToolsEntitiesCommonEntitiesI18nObject
name: string
tags?: Array<ToolLabelEnum> | null
}
export type ProviderConfig = {
default?: number | string | number | boolean | null
help?: CoreToolsEntitiesCommonEntitiesI18nObject | null
label?: CoreToolsEntitiesCommonEntitiesI18nObject | null
multiple?: boolean
name: string
options?: Array<Option> | null
placeholder?: CoreToolsEntitiesCommonEntitiesI18nObject | null
required?: boolean
scope?: AppSelectorScope | ModelSelectorScope | ToolSelectorScope | null
type: CoreEntitiesProviderEntitiesBasicProviderConfigType
url?: string | null
}
export type DatasourceProviderIdentity = {
author: string
description: CoreToolsEntitiesCommonEntitiesI18nObject
icon: string
label: CoreToolsEntitiesCommonEntitiesI18nObject
name: string
tags?: Array<ToolLabelEnum> | null
}
export type OAuthSchema = {
client_schema?: Array<ProviderConfig>
credentials_schema?: Array<ProviderConfig>
}
export type DatasourceProviderType
= | 'local_file'
| 'online_document'
| 'online_drive'
| 'website_crawl'
export type EndpointDeclaration = {
hidden?: boolean
method: string
path: string
}
export type AiModelEntity = {
deprecated?: boolean
features?: Array<ModelFeature> | null
fetch_from: FetchFrom
label: GraphonModelRuntimeEntitiesCommonEntitiesI18nObject
model: string
model_properties: {
[key in ModelPropertyKey]?: unknown
}
model_type: ModelType
parameter_rules?: Array<ParameterRule>
pricing?: PriceConfig | null
}
export type Permission = {
endpoint?: Endpoint | null
model?: Model | null
node?: Node | null
storage?: Storage | null
tool?: Tool | null
}
export type ToolProviderIdentity = {
author: string
description: CoreToolsEntitiesCommonEntitiesI18nObject
icon: string
icon_dark?: string | null
label: CoreToolsEntitiesCommonEntitiesI18nObject
name: string
tags?: Array<ToolLabelEnum> | null
}
export type EventEntity = {
description: CoreToolsEntitiesCommonEntitiesI18nObject
identity: EventIdentity
output_schema?: {
[key: string]: unknown
} | null
parameters?: Array<EventParameter>
}
export type TriggerProviderIdentity = {
author: string
description: CoreToolsEntitiesCommonEntitiesI18nObject
icon?: string | null
icon_dark?: string | null
label: CoreToolsEntitiesCommonEntitiesI18nObject
name: string
tags?: Array<string>
}
export type SubscriptionConstructor = {
credentials_schema?: Array<ProviderConfig>
oauth_schema?: OAuthSchema | null
parameters?: Array<EventParameter>
}
export type ProviderEntityResponse = {
background?: string | null
configurate_methods: Array<ConfigurateMethod>
@ -1511,6 +1840,134 @@ export type RestrictModel = {
model_type: ModelType
}
export type ToolLabelEnum
= | 'business'
| 'design'
| 'education'
| 'entertainment'
| 'finance'
| 'image'
| 'medical'
| 'news'
| 'other'
| 'productivity'
| 'rag'
| 'search'
| 'social'
| 'travel'
| 'utilities'
| 'videos'
| 'weather'
export type Option = {
label: CoreToolsEntitiesCommonEntitiesI18nObject
value: string
}
export type AppSelectorScope = 'all' | 'chat' | 'completion' | 'workflow'
export type ModelSelectorScope
= | 'llm'
| 'moderation'
| 'rerank'
| 'speech2text'
| 'text-embedding'
| 'tts'
| 'vision'
export type ToolSelectorScope = 'all' | 'builtin' | 'custom' | 'workflow'
export type CoreEntitiesProviderEntitiesBasicProviderConfigType
= | 'app-selector'
| 'array[tools]'
| 'boolean'
| 'model-selector'
| 'secret-input'
| 'select'
| 'text-input'
export type PriceConfig = {
currency: string
input: string
output?: string | null
unit: string
}
export type Endpoint = {
enabled?: boolean | null
}
export type Model = {
enabled?: boolean | null
llm?: boolean | null
moderation?: boolean | null
rerank?: boolean | null
speech2text?: boolean | null
text_embedding?: boolean | null
tts?: boolean | null
}
export type Node = {
enabled?: boolean | null
}
export type Storage = {
enabled?: boolean | null
size?: number
}
export type Tool = {
enabled?: boolean | null
}
export type EventIdentity = {
author: string
label: CoreToolsEntitiesCommonEntitiesI18nObject
name: string
provider?: string | null
}
export type EventParameter = {
auto_generate?: PluginParameterAutoGenerate | null
default?: number | number | string | Array<unknown> | null
description?: CoreToolsEntitiesCommonEntitiesI18nObject | null
label: CoreToolsEntitiesCommonEntitiesI18nObject
max?: number | number | null
min?: number | number | null
multiple?: boolean
name: string
options?: Array<PluginParameterOption> | null
precision?: number | null
required?: boolean
scope?: string | null
template?: PluginParameterTemplate | null
type: EventParameterType
}
export type PluginParameterAutoGenerate = {
type: CorePluginEntitiesParametersPluginParameterAutoGenerateType
}
export type PluginParameterTemplate = {
enabled?: boolean
}
export type EventParameterType
= | 'app-selector'
| 'array'
| 'boolean'
| 'checkbox'
| 'dynamic-select'
| 'file'
| 'files'
| 'model-selector'
| 'number'
| 'object'
| 'select'
| 'string'
export type CorePluginEntitiesParametersPluginParameterAutoGenerateType = 'prompt_instruction'
export type GetWorkspacesData = {
body?: never
path?: never
@ -2160,7 +2617,7 @@ export type GetWorkspacesCurrentModelProvidersByProviderCredentialsData = {
}
export type GetWorkspacesCurrentModelProvidersByProviderCredentialsResponses = {
200: ProviderCredentialResponse
200: ProviderCredentialsResponse
}
export type GetWorkspacesCurrentModelProvidersByProviderCredentialsResponse
@ -2224,7 +2681,7 @@ export type PostWorkspacesCurrentModelProvidersByProviderCredentialsValidateData
}
export type PostWorkspacesCurrentModelProvidersByProviderCredentialsValidateResponses = {
200: ProviderCredentialValidateResponse
200: ValidationResultResponse
}
export type PostWorkspacesCurrentModelProvidersByProviderCredentialsValidateResponse
@ -2256,7 +2713,7 @@ export type GetWorkspacesCurrentModelProvidersByProviderModelsData = {
}
export type GetWorkspacesCurrentModelProvidersByProviderModelsResponses = {
200: ModelWithProviderListResponse
200: ProviderModelListResponse
}
export type GetWorkspacesCurrentModelProvidersByProviderModelsResponse
@ -2373,7 +2830,7 @@ export type PostWorkspacesCurrentModelProvidersByProviderModelsCredentialsValida
}
export type PostWorkspacesCurrentModelProvidersByProviderModelsCredentialsValidateResponses = {
200: ModelCredentialValidateResponse
200: ValidationResultResponse
}
export type PostWorkspacesCurrentModelProvidersByProviderModelsCredentialsValidateResponse
@ -2460,7 +2917,7 @@ export type GetWorkspacesCurrentModelProvidersByProviderModelsParameterRulesData
}
export type GetWorkspacesCurrentModelProvidersByProviderModelsParameterRulesResponses = {
200: ModelParameterRulesResponse
200: ModelParameterRuleListResponse
}
export type GetWorkspacesCurrentModelProvidersByProviderModelsParameterRulesResponse
@ -2492,7 +2949,7 @@ export type GetWorkspacesCurrentModelsModelTypesByModelTypeData = {
}
export type GetWorkspacesCurrentModelsModelTypesByModelTypeResponses = {
200: ProviderWithModelsDataResponse
200: AvailableModelListResponse
}
export type GetWorkspacesCurrentModelsModelTypesByModelTypeResponse
@ -2628,7 +3085,7 @@ export type PostWorkspacesCurrentPluginInstallGithubData = {
}
export type PostWorkspacesCurrentPluginInstallGithubResponses = {
200: PluginDaemonOperationResponse
200: PluginInstallTaskStartResponse
}
export type PostWorkspacesCurrentPluginInstallGithubResponse
@ -2642,7 +3099,7 @@ export type PostWorkspacesCurrentPluginInstallMarketplaceData = {
}
export type PostWorkspacesCurrentPluginInstallMarketplaceResponses = {
200: PluginDaemonOperationResponse
200: PluginInstallTaskStartResponse
}
export type PostWorkspacesCurrentPluginInstallMarketplaceResponse
@ -2656,7 +3113,7 @@ export type PostWorkspacesCurrentPluginInstallPkgData = {
}
export type PostWorkspacesCurrentPluginInstallPkgResponses = {
200: PluginDaemonOperationResponse
200: PluginInstallTaskStartResponse
}
export type PostWorkspacesCurrentPluginInstallPkgResponse
@ -2905,7 +3362,7 @@ export type PostWorkspacesCurrentPluginUpgradeGithubData = {
}
export type PostWorkspacesCurrentPluginUpgradeGithubResponses = {
200: PluginDaemonOperationResponse
200: PluginInstallTaskStartResponse
}
export type PostWorkspacesCurrentPluginUpgradeGithubResponse
@ -2919,7 +3376,7 @@ export type PostWorkspacesCurrentPluginUpgradeMarketplaceData = {
}
export type PostWorkspacesCurrentPluginUpgradeMarketplaceResponses = {
200: PluginDaemonOperationResponse
200: PluginInstallTaskStartResponse
}
export type PostWorkspacesCurrentPluginUpgradeMarketplaceResponse
@ -2933,7 +3390,7 @@ export type PostWorkspacesCurrentPluginUploadBundleData = {
}
export type PostWorkspacesCurrentPluginUploadBundleResponses = {
200: PluginDaemonOperationResponse
200: PluginBundleUploadResponse
}
export type PostWorkspacesCurrentPluginUploadBundleResponse
@ -2947,7 +3404,7 @@ export type PostWorkspacesCurrentPluginUploadGithubData = {
}
export type PostWorkspacesCurrentPluginUploadGithubResponses = {
200: PluginDaemonOperationResponse
200: PluginDecodeResponse
}
export type PostWorkspacesCurrentPluginUploadGithubResponse
@ -2961,7 +3418,7 @@ export type PostWorkspacesCurrentPluginUploadPkgData = {
}
export type PostWorkspacesCurrentPluginUploadPkgResponses = {
200: PluginDaemonOperationResponse
200: PluginDecodeResponse
}
export type PostWorkspacesCurrentPluginUploadPkgResponse
@ -4644,22 +5101,3 @@ export type PostWorkspacesSwitchResponses = {
export type PostWorkspacesSwitchResponse
= PostWorkspacesSwitchResponses[keyof PostWorkspacesSwitchResponses]
export type GetWorkspacesByTenantIdModelProvidersByProviderByIconTypeByLangData = {
body?: never
path: {
icon_type: string
lang: string
provider: string
tenant_id: string
}
query?: never
url: '/workspaces/{tenant_id}/model-providers/{provider}/{icon_type}/{lang}'
}
export type GetWorkspacesByTenantIdModelProvidersByProviderByIconTypeByLangResponses = {
200: BinaryFileResponse
}
export type GetWorkspacesByTenantIdModelProvidersByProviderByIconTypeByLangResponse
= GetWorkspacesByTenantIdModelProvidersByProviderByIconTypeByLangResponses[keyof GetWorkspacesByTenantIdModelProvidersByProviderByIconTypeByLangResponses]

View File

@ -10,13 +10,21 @@ type SwaggerSchema = JsonObject & {
$ref?: string
}
type OpenApiMediaType = JsonObject & {
schema?: SwaggerSchema
}
type OpenApiResponse = JsonObject & {
content?: Record<string, OpenApiMediaType>
}
type OpenApiComponents = JsonObject & {
schemas?: Record<string, SwaggerSchema>
}
type SwaggerOperation = JsonObject & {
operationId?: string
responses?: Record<string, unknown>
responses?: Record<string, OpenApiResponse>
}
type SwaggerDocument = JsonObject & {
@ -52,6 +60,17 @@ const currentDir = path.dirname(fileURLToPath(import.meta.url))
const apiOpenApiDir = path.resolve(currentDir, 'openapi')
const operationMethods = new Set(['delete', 'get', 'patch', 'post', 'put'])
const pydanticDecimalStringPattern = '^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$'
const codegenSafeDecimalStringPattern = '^(?![-+.]*$)[+-]?0*\\d*\\.?\\d*$'
const opaqueJsonContent = (): Record<string, OpenApiMediaType> => ({
'application/json': {
schema: {
additionalProperties: true,
type: 'object',
},
},
})
const apiSpecs: ApiSpec[] = [
{ filename: 'console-openapi.json', name: 'console' },
@ -182,6 +201,46 @@ const addOperationIds = (document: SwaggerDocument) => {
}
}
const isOpaqueContractResponse = (response: OpenApiResponse) => {
const content = response.content
if (!isObject(content))
return false
return Object.entries(content).some(([mediaType, media]) => {
if (!isObject(media))
return false
return (mediaType === 'application/json' || mediaType === 'text/event-stream') && !('schema' in media)
})
}
const hasOpaqueContractSuccessResponse = (operation: SwaggerOperation) => {
return Object.entries(operation.responses ?? {}).some(([status, response]) => {
return /^2\d\d$/.test(status) && isObject(response) && isOpaqueContractResponse(response)
})
}
const normalizeOpaqueContractResponses = (document: SwaggerDocument) => {
// Some backend endpoints has no schema (e.g. external) and will trap heyapi here
// So we forge an opaque schema here
for (const pathItem of Object.values(document.paths ?? {})) {
for (const [method, operation] of Object.entries(pathItem)) {
if (!operationMethods.has(method) || !isObject(operation))
continue
const swaggerOperation = operation as SwaggerOperation
if (!hasOpaqueContractSuccessResponse(swaggerOperation))
continue
Object.values(swaggerOperation.responses ?? {})
.filter(response => isObject(response) && isOpaqueContractResponse(response))
.forEach((response) => {
response.content = opaqueJsonContent()
})
}
}
}
const hasSuccessResponse = (operation: SwaggerOperation) => {
return Object.entries(operation.responses ?? {}).some(([status, response]) => {
if (!/^2\d\d$/.test(status))
@ -215,6 +274,7 @@ const filterContractOperations = (document: SwaggerDocument) => {
}
const normalizeApiSwagger = (document: SwaggerDocument) => {
normalizeOpaqueContractResponses(document)
filterContractOperations(document)
addOperationIds(document)
@ -380,10 +440,20 @@ const createApiConfig = (job: ApiJob): UserConfig => ({
'name': 'zod',
'~resolvers': {
string: (ctx) => {
if (ctx.schema.format !== 'binary')
return undefined
if (ctx.schema.format === 'binary')
return $(ctx.symbols.z).attr('custom').call().generic($.type.or($.type('Blob'), $.type('File')))
return $(ctx.symbols.z).attr('custom').call().generic($.type.or($.type('Blob'), $.type('File')))
if (ctx.schema.pattern === pydanticDecimalStringPattern) {
// the pydantic generated regex will emit error like
// regexp/no-useless-assertions, so patch the regex here
return $(ctx.symbols.z)
.attr('string')
.call()
.attr('regex')
.call($.regexp(codegenSafeDecimalStringPattern))
}
return undefined
},
},
},

View File

@ -217,14 +217,8 @@ const toFeedback = (feedback: NonNullable<MessageDetailResponse['feedbacks']>[nu
}
}
type AgentDebugMessageWithLegacyAnswer = MessageDetailResponse & {
answer?: string | null
}
const getAgentDebugMessageAnswer = (message: MessageDetailResponse) => {
const legacyAnswer = (message as AgentDebugMessageWithLegacyAnswer).answer
return message.re_sign_file_url_answer ?? legacyAnswer ?? ''
return message.answer ?? ''
}
function getFormattedAgentDebugChatTree(messages: MessageDetailResponse[]): ChatItemInTree[] {