mirror of
https://github.com/langgenius/dify.git
synced 2026-07-14 17:07:03 +08:00
Merge branch 'main' into feat/agent-v2
This commit is contained in:
@ -27,6 +27,7 @@ from controllers.console.wraps import (
|
||||
)
|
||||
from extensions.ext_database import db
|
||||
from fields.file_fields import FileResponse, UploadConfig
|
||||
from libs.helper import dump_response
|
||||
from libs.login import login_required
|
||||
from models import Account
|
||||
from services.file_service import FileService
|
||||
@ -117,8 +118,7 @@ class FileApi(Resource):
|
||||
except services.errors.file.BlockedFileExtensionError as blocked_extension_error:
|
||||
raise BlockedFileExtensionError(blocked_extension_error.description)
|
||||
|
||||
response = FileResponse.model_validate(upload_file, from_attributes=True)
|
||||
return response.model_dump(mode="json"), 201
|
||||
return dump_response(FileResponse, upload_file), 201
|
||||
|
||||
|
||||
@console_ns.route("/files/<uuid:file_id>/preview")
|
||||
@ -131,7 +131,7 @@ class FilePreviewApi(Resource):
|
||||
def get(self, current_tenant_id: str, file_id: UUID):
|
||||
file_id_str = str(file_id)
|
||||
text = FileService(db.engine).get_file_preview(file_id_str, current_tenant_id)
|
||||
return {"content": text}
|
||||
return TextContentResponse(content=text).model_dump(mode="json")
|
||||
|
||||
|
||||
@console_ns.route("/files/support-type")
|
||||
@ -141,4 +141,4 @@ class FileSupportTypeApi(Resource):
|
||||
@account_initialization_required
|
||||
@console_ns.response(200, "Success", console_ns.models[AllowedExtensionsResponse.__name__])
|
||||
def get(self):
|
||||
return {"allowed_extensions": list(DOCUMENT_EXTENSIONS)}
|
||||
return AllowedExtensionsResponse(allowed_extensions=list(DOCUMENT_EXTENSIONS)).model_dump(mode="json")
|
||||
|
||||
@ -1,8 +1,9 @@
|
||||
import logging
|
||||
from collections.abc import Mapping
|
||||
from typing import Any
|
||||
|
||||
from flask_restx import Resource
|
||||
from pydantic import RootModel
|
||||
from pydantic import Field, RootModel
|
||||
|
||||
from controllers.common.schema import register_response_schema_models
|
||||
from controllers.console.wraps import (
|
||||
@ -10,6 +11,7 @@ from controllers.console.wraps import (
|
||||
setup_required,
|
||||
)
|
||||
from core.schemas.schema_manager import SchemaManager
|
||||
from fields.base import ResponseModel
|
||||
from libs.login import login_required
|
||||
|
||||
from . import console_ns
|
||||
@ -17,11 +19,17 @@ from . import console_ns
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class SchemaDefinitionsResponse(RootModel[Any]):
|
||||
root: Any
|
||||
class SchemaDefinitionItemResponse(ResponseModel):
|
||||
name: str
|
||||
label: str
|
||||
schema_: Mapping[str, Any] = Field(alias="schema")
|
||||
|
||||
|
||||
register_response_schema_models(console_ns, SchemaDefinitionsResponse)
|
||||
class SchemaDefinitionsResponse(RootModel[list[SchemaDefinitionItemResponse]]):
|
||||
pass
|
||||
|
||||
|
||||
register_response_schema_models(console_ns, SchemaDefinitionItemResponse, SchemaDefinitionsResponse)
|
||||
|
||||
|
||||
@console_ns.route("/spec/schema-definitions")
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -1,20 +1,19 @@
|
||||
import logging
|
||||
from typing import Any, Literal
|
||||
from typing import Any
|
||||
|
||||
from flask import make_response, redirect, request
|
||||
from flask_restx import Resource
|
||||
from pydantic import BaseModel, Field, RootModel, model_validator
|
||||
from pydantic import BaseModel, RootModel, model_validator
|
||||
from sqlalchemy.orm import sessionmaker
|
||||
from werkzeug.exceptions import BadRequest, Forbidden
|
||||
|
||||
from configs import dify_config
|
||||
from controllers.common.errors import NotFoundError
|
||||
from controllers.common.fields import BinaryFileResponse, RedirectResponse, SimpleResultResponse
|
||||
from controllers.common.fields import SimpleResultResponse
|
||||
from controllers.common.schema import register_response_schema_models, register_schema_models
|
||||
from core.entities.parameter_entities import AppSelectorScope, ModelSelectorScope, ToolSelectorScope
|
||||
from core.entities.provider_entities import ProviderConfig
|
||||
from core.plugin.entities.plugin_daemon import CredentialType
|
||||
from core.plugin.impl.oauth import OAuthHandler
|
||||
from core.tools.entities.common_entities import I18nObject
|
||||
from core.trigger.entities.api_entities import (
|
||||
SubscriptionBuilderApiEntity,
|
||||
TriggerProviderApiEntity,
|
||||
@ -24,7 +23,7 @@ from core.trigger.entities.entities import RequestLog, SubscriptionBuilderUpdate
|
||||
from core.trigger.trigger_manager import TriggerManager
|
||||
from extensions.ext_database import db
|
||||
from fields.base import ResponseModel
|
||||
from graphon.model_runtime.utils.encoders import jsonable_encoder
|
||||
from libs.helper import dump_response
|
||||
from libs.login import login_required
|
||||
from models.account import Account
|
||||
from models.provider_ids import TriggerProviderID
|
||||
@ -59,9 +58,9 @@ class TriggerSubscriptionBuilderVerifyPayload(BaseModel):
|
||||
|
||||
class TriggerSubscriptionBuilderUpdatePayload(BaseModel):
|
||||
name: str | None = None
|
||||
parameters: dict[str, Any] | None = Field(default=None)
|
||||
properties: dict[str, Any] | None = Field(default=None)
|
||||
credentials: dict[str, Any] | None = Field(default=None)
|
||||
parameters: dict[str, Any] | None = None
|
||||
properties: dict[str, Any] | None = None
|
||||
credentials: dict[str, Any] | None = None
|
||||
|
||||
@model_validator(mode="after")
|
||||
def check_at_least_one_field(self):
|
||||
@ -71,70 +70,23 @@ class TriggerSubscriptionBuilderUpdatePayload(BaseModel):
|
||||
|
||||
|
||||
class TriggerOAuthClientPayload(BaseModel):
|
||||
client_params: dict[str, Any] | None = Field(default=None)
|
||||
client_params: dict[str, Any] | None = None
|
||||
enabled: bool | None = None
|
||||
|
||||
|
||||
class TriggerOAuthAuthorizeResponse(BaseModel):
|
||||
authorization_url: str
|
||||
subscription_builder_id: str
|
||||
subscription_builder: SubscriptionBuilderApiEntity
|
||||
|
||||
|
||||
class TriggerProviderConfigOptionResponse(BaseModel):
|
||||
value: str = Field(..., description="The value of the option")
|
||||
label: I18nObject = Field(..., description="The label of the option")
|
||||
|
||||
|
||||
class TriggerProviderConfigResponse(BaseModel):
|
||||
type: Literal[
|
||||
"secret-input",
|
||||
"text-input",
|
||||
"select",
|
||||
"boolean",
|
||||
"app-selector",
|
||||
"model-selector",
|
||||
"array[tools]",
|
||||
] = Field(..., description="The type of the credentials")
|
||||
name: str = Field(..., description="The name of the credentials")
|
||||
scope: AppSelectorScope | ModelSelectorScope | ToolSelectorScope | None = None
|
||||
required: bool = False
|
||||
default: int | str | float | bool | None = None
|
||||
options: list[TriggerProviderConfigOptionResponse] | None = None
|
||||
multiple: bool = False
|
||||
label: I18nObject | None = None
|
||||
help: I18nObject | None = None
|
||||
url: str | None = None
|
||||
placeholder: I18nObject | None = None
|
||||
|
||||
|
||||
class TriggerOAuthClientResponse(BaseModel):
|
||||
configured: bool
|
||||
system_configured: bool
|
||||
custom_configured: bool
|
||||
oauth_client_schema: list[TriggerProviderConfigResponse]
|
||||
custom_enabled: bool
|
||||
redirect_uri: str
|
||||
params: dict[str, Any]
|
||||
|
||||
|
||||
class TriggerProviderOpaqueResponse(RootModel[Any]):
|
||||
root: Any
|
||||
|
||||
|
||||
class TriggerProviderListResponse(RootModel[list[TriggerProviderApiEntity]]):
|
||||
root: list[TriggerProviderApiEntity]
|
||||
pass
|
||||
|
||||
|
||||
class TriggerSubscriptionListResponse(RootModel[list[TriggerProviderSubscriptionApiEntity]]):
|
||||
root: list[TriggerProviderSubscriptionApiEntity]
|
||||
class TriggerProviderSubscriptionListResponse(RootModel[list[TriggerProviderSubscriptionApiEntity]]):
|
||||
pass
|
||||
|
||||
|
||||
class TriggerSubscriptionBuilderCreateResponse(ResponseModel):
|
||||
subscription_builder: SubscriptionBuilderApiEntity
|
||||
|
||||
|
||||
class TriggerSubscriptionBuilderVerifyResponse(ResponseModel):
|
||||
class TriggerVerificationResponse(ResponseModel):
|
||||
verified: bool
|
||||
|
||||
|
||||
@ -142,6 +94,26 @@ class TriggerSubscriptionBuilderLogsResponse(ResponseModel):
|
||||
logs: list[RequestLog]
|
||||
|
||||
|
||||
class TriggerOAuthAuthorizeResponse(ResponseModel):
|
||||
authorization_url: str
|
||||
subscription_builder_id: str
|
||||
subscription_builder: SubscriptionBuilderApiEntity
|
||||
|
||||
|
||||
class TriggerOAuthClientResponse(ResponseModel):
|
||||
configured: bool
|
||||
system_configured: bool
|
||||
custom_configured: bool
|
||||
oauth_client_schema: list[ProviderConfig]
|
||||
custom_enabled: bool
|
||||
redirect_uri: str
|
||||
params: dict[str, Any]
|
||||
|
||||
|
||||
class TriggerProviderErrorResponse(ResponseModel):
|
||||
error: str
|
||||
|
||||
|
||||
register_schema_models(
|
||||
console_ns,
|
||||
TriggerSubscriptionBuilderCreatePayload,
|
||||
@ -151,27 +123,24 @@ register_schema_models(
|
||||
)
|
||||
register_response_schema_models(
|
||||
console_ns,
|
||||
BinaryFileResponse,
|
||||
RedirectResponse,
|
||||
SimpleResultResponse,
|
||||
TriggerOAuthAuthorizeResponse,
|
||||
TriggerOAuthClientResponse,
|
||||
TriggerProviderOpaqueResponse,
|
||||
TriggerProviderApiEntity,
|
||||
TriggerProviderErrorResponse,
|
||||
TriggerProviderListResponse,
|
||||
TriggerProviderSubscriptionApiEntity,
|
||||
TriggerSubscriptionListResponse,
|
||||
SubscriptionBuilderApiEntity,
|
||||
TriggerProviderSubscriptionListResponse,
|
||||
TriggerSubscriptionBuilderCreateResponse,
|
||||
TriggerSubscriptionBuilderVerifyResponse,
|
||||
RequestLog,
|
||||
TriggerSubscriptionBuilderLogsResponse,
|
||||
SubscriptionBuilderApiEntity,
|
||||
TriggerVerificationResponse,
|
||||
)
|
||||
|
||||
|
||||
@console_ns.route("/workspaces/current/trigger-provider/<path:provider>/icon")
|
||||
class TriggerProviderIconApi(Resource):
|
||||
@console_ns.response(200, "Success", console_ns.models[BinaryFileResponse.__name__])
|
||||
# response-contract:ignore binary trigger provider icon
|
||||
@console_ns.response(200, "Trigger provider icon")
|
||||
@setup_required
|
||||
@login_required
|
||||
@account_initialization_required
|
||||
@ -182,31 +151,45 @@ class TriggerProviderIconApi(Resource):
|
||||
|
||||
@console_ns.route("/workspaces/current/triggers")
|
||||
class TriggerProviderListApi(Resource):
|
||||
@console_ns.response(200, "Success", console_ns.models[TriggerProviderListResponse.__name__])
|
||||
@console_ns.response(
|
||||
200,
|
||||
"Trigger providers retrieved successfully",
|
||||
console_ns.models[TriggerProviderListResponse.__name__],
|
||||
)
|
||||
@setup_required
|
||||
@login_required
|
||||
@account_initialization_required
|
||||
@with_current_tenant_id
|
||||
def get(self, tenant_id: str):
|
||||
"""List all trigger providers for the current tenant"""
|
||||
return jsonable_encoder(TriggerProviderService.list_trigger_providers(tenant_id))
|
||||
return dump_response(TriggerProviderListResponse, TriggerProviderService.list_trigger_providers(tenant_id))
|
||||
|
||||
|
||||
@console_ns.route("/workspaces/current/trigger-provider/<path:provider>/info")
|
||||
class TriggerProviderInfoApi(Resource):
|
||||
@console_ns.response(200, "Success", console_ns.models[TriggerProviderApiEntity.__name__])
|
||||
@console_ns.response(
|
||||
200,
|
||||
"Trigger provider retrieved successfully",
|
||||
console_ns.models[TriggerProviderApiEntity.__name__],
|
||||
)
|
||||
@setup_required
|
||||
@login_required
|
||||
@account_initialization_required
|
||||
@with_current_tenant_id
|
||||
def get(self, tenant_id: str, provider: str):
|
||||
"""Get info for a trigger provider"""
|
||||
return jsonable_encoder(TriggerProviderService.get_trigger_provider(tenant_id, TriggerProviderID(provider)))
|
||||
provider_entity = TriggerProviderService.get_trigger_provider(tenant_id, TriggerProviderID(provider))
|
||||
return provider_entity.model_dump(mode="json")
|
||||
|
||||
|
||||
@console_ns.route("/workspaces/current/trigger-provider/<path:provider>/subscriptions/list")
|
||||
class TriggerSubscriptionListApi(Resource):
|
||||
@console_ns.response(200, "Success", console_ns.models[TriggerSubscriptionListResponse.__name__])
|
||||
@console_ns.response(
|
||||
200,
|
||||
"Trigger subscriptions retrieved successfully",
|
||||
console_ns.models[TriggerProviderSubscriptionListResponse.__name__],
|
||||
)
|
||||
@console_ns.response(404, "Trigger provider not found", console_ns.models[TriggerProviderErrorResponse.__name__])
|
||||
@setup_required
|
||||
@login_required
|
||||
@edit_permission_required
|
||||
@ -216,16 +199,18 @@ class TriggerSubscriptionListApi(Resource):
|
||||
@with_current_tenant_id
|
||||
def get(self, tenant_id: str, user: Account, provider: str):
|
||||
"""List all trigger subscriptions for the current tenant's provider"""
|
||||
|
||||
try:
|
||||
return jsonable_encoder(
|
||||
return dump_response(
|
||||
TriggerProviderSubscriptionListResponse,
|
||||
TriggerProviderService.list_trigger_provider_subscriptions(
|
||||
tenant_id=tenant_id,
|
||||
provider_id=TriggerProviderID(provider),
|
||||
user=user,
|
||||
)
|
||||
),
|
||||
)
|
||||
except ValueError as e:
|
||||
return jsonable_encoder({"error": str(e)}), 404
|
||||
return TriggerProviderErrorResponse(error=str(e)).model_dump(mode="json"), 404
|
||||
except Exception as e:
|
||||
logger.exception("Error listing trigger providers", exc_info=e)
|
||||
raise
|
||||
@ -236,7 +221,11 @@ class TriggerSubscriptionListApi(Resource):
|
||||
)
|
||||
class TriggerSubscriptionBuilderCreateApi(Resource):
|
||||
@console_ns.expect(console_ns.models[TriggerSubscriptionBuilderCreatePayload.__name__])
|
||||
@console_ns.response(200, "Success", console_ns.models[TriggerSubscriptionBuilderCreateResponse.__name__])
|
||||
@console_ns.response(
|
||||
200,
|
||||
"Trigger subscription builder created successfully",
|
||||
console_ns.models[TriggerSubscriptionBuilderCreateResponse.__name__],
|
||||
)
|
||||
@setup_required
|
||||
@login_required
|
||||
@edit_permission_required
|
||||
@ -246,6 +235,7 @@ class TriggerSubscriptionBuilderCreateApi(Resource):
|
||||
@with_current_tenant_id
|
||||
def post(self, tenant_id: str, user: Account, provider: str):
|
||||
"""Add a new subscription instance for a trigger provider"""
|
||||
|
||||
payload = TriggerSubscriptionBuilderCreatePayload.model_validate(console_ns.payload or {})
|
||||
|
||||
try:
|
||||
@ -256,7 +246,9 @@ class TriggerSubscriptionBuilderCreateApi(Resource):
|
||||
provider_id=TriggerProviderID(provider),
|
||||
credential_type=credential_type,
|
||||
)
|
||||
return jsonable_encoder({"subscription_builder": subscription_builder})
|
||||
return TriggerSubscriptionBuilderCreateResponse(subscription_builder=subscription_builder).model_dump(
|
||||
mode="json"
|
||||
)
|
||||
except Exception as e:
|
||||
logger.exception("Error adding provider credential", exc_info=e)
|
||||
raise
|
||||
@ -266,7 +258,11 @@ class TriggerSubscriptionBuilderCreateApi(Resource):
|
||||
"/workspaces/current/trigger-provider/<path:provider>/subscriptions/builder/<path:subscription_builder_id>",
|
||||
)
|
||||
class TriggerSubscriptionBuilderGetApi(Resource):
|
||||
@console_ns.response(200, "Success", console_ns.models[SubscriptionBuilderApiEntity.__name__])
|
||||
@console_ns.response(
|
||||
200,
|
||||
"Trigger subscription builder retrieved successfully",
|
||||
console_ns.models[SubscriptionBuilderApiEntity.__name__],
|
||||
)
|
||||
@setup_required
|
||||
@login_required
|
||||
@edit_permission_required
|
||||
@ -274,9 +270,8 @@ class TriggerSubscriptionBuilderGetApi(Resource):
|
||||
@account_initialization_required
|
||||
def get(self, provider: str, subscription_builder_id: str):
|
||||
"""Get a subscription instance for a trigger provider"""
|
||||
return jsonable_encoder(
|
||||
TriggerSubscriptionBuilderService.get_subscription_builder_by_id(subscription_builder_id)
|
||||
)
|
||||
subscription_builder = TriggerSubscriptionBuilderService.get_subscription_builder_by_id(subscription_builder_id)
|
||||
return subscription_builder.model_dump(mode="json")
|
||||
|
||||
|
||||
@console_ns.route(
|
||||
@ -284,7 +279,11 @@ class TriggerSubscriptionBuilderGetApi(Resource):
|
||||
)
|
||||
class TriggerSubscriptionBuilderVerifyApi(Resource):
|
||||
@console_ns.expect(console_ns.models[TriggerSubscriptionBuilderVerifyPayload.__name__])
|
||||
@console_ns.response(200, "Success", console_ns.models[TriggerSubscriptionBuilderVerifyResponse.__name__])
|
||||
@console_ns.response(
|
||||
200,
|
||||
"Trigger subscription builder verified successfully",
|
||||
console_ns.models[TriggerVerificationResponse.__name__],
|
||||
)
|
||||
@setup_required
|
||||
@login_required
|
||||
@edit_permission_required
|
||||
@ -294,11 +293,12 @@ class TriggerSubscriptionBuilderVerifyApi(Resource):
|
||||
@with_current_tenant_id
|
||||
def post(self, tenant_id: str, user: Account, provider: str, subscription_builder_id: str):
|
||||
"""Verify and update a subscription instance for a trigger provider"""
|
||||
|
||||
payload = TriggerSubscriptionBuilderVerifyPayload.model_validate(console_ns.payload or {})
|
||||
|
||||
try:
|
||||
# Use atomic update_and_verify to prevent race conditions
|
||||
return TriggerSubscriptionBuilderService.update_and_verify_builder(
|
||||
result = TriggerSubscriptionBuilderService.update_and_verify_builder(
|
||||
tenant_id=tenant_id,
|
||||
user_id=user.id,
|
||||
provider_id=TriggerProviderID(provider),
|
||||
@ -307,6 +307,7 @@ class TriggerSubscriptionBuilderVerifyApi(Resource):
|
||||
credentials=payload.credentials,
|
||||
),
|
||||
)
|
||||
return dump_response(TriggerVerificationResponse, result)
|
||||
except Exception as e:
|
||||
logger.exception("Error verifying provider credential", exc_info=e)
|
||||
raise ValueError(str(e)) from e
|
||||
@ -317,7 +318,11 @@ class TriggerSubscriptionBuilderVerifyApi(Resource):
|
||||
)
|
||||
class TriggerSubscriptionBuilderUpdateApi(Resource):
|
||||
@console_ns.expect(console_ns.models[TriggerSubscriptionBuilderUpdatePayload.__name__])
|
||||
@console_ns.response(200, "Success", console_ns.models[SubscriptionBuilderApiEntity.__name__])
|
||||
@console_ns.response(
|
||||
200,
|
||||
"Trigger subscription builder updated successfully",
|
||||
console_ns.models[SubscriptionBuilderApiEntity.__name__],
|
||||
)
|
||||
@setup_required
|
||||
@login_required
|
||||
@edit_permission_required
|
||||
@ -326,21 +331,20 @@ class TriggerSubscriptionBuilderUpdateApi(Resource):
|
||||
@with_current_tenant_id
|
||||
def post(self, tenant_id: str, provider: str, subscription_builder_id: str):
|
||||
"""Update a subscription instance for a trigger provider"""
|
||||
|
||||
payload = TriggerSubscriptionBuilderUpdatePayload.model_validate(console_ns.payload or {})
|
||||
try:
|
||||
return jsonable_encoder(
|
||||
TriggerSubscriptionBuilderService.update_trigger_subscription_builder(
|
||||
tenant_id=tenant_id,
|
||||
provider_id=TriggerProviderID(provider),
|
||||
subscription_builder_id=subscription_builder_id,
|
||||
subscription_builder_updater=SubscriptionBuilderUpdater(
|
||||
name=payload.name,
|
||||
parameters=payload.parameters,
|
||||
properties=payload.properties,
|
||||
credentials=payload.credentials,
|
||||
),
|
||||
)
|
||||
)
|
||||
return TriggerSubscriptionBuilderService.update_trigger_subscription_builder(
|
||||
tenant_id=tenant_id,
|
||||
provider_id=TriggerProviderID(provider),
|
||||
subscription_builder_id=subscription_builder_id,
|
||||
subscription_builder_updater=SubscriptionBuilderUpdater(
|
||||
name=payload.name,
|
||||
parameters=payload.parameters,
|
||||
properties=payload.properties,
|
||||
credentials=payload.credentials,
|
||||
),
|
||||
).model_dump(mode="json")
|
||||
except Exception as e:
|
||||
logger.exception("Error updating provider credential", exc_info=e)
|
||||
raise
|
||||
@ -350,7 +354,11 @@ class TriggerSubscriptionBuilderUpdateApi(Resource):
|
||||
"/workspaces/current/trigger-provider/<path:provider>/subscriptions/builder/logs/<path:subscription_builder_id>",
|
||||
)
|
||||
class TriggerSubscriptionBuilderLogsApi(Resource):
|
||||
@console_ns.response(200, "Success", console_ns.models[TriggerSubscriptionBuilderLogsResponse.__name__])
|
||||
@console_ns.response(
|
||||
200,
|
||||
"Trigger subscription builder logs retrieved successfully",
|
||||
console_ns.models[TriggerSubscriptionBuilderLogsResponse.__name__],
|
||||
)
|
||||
@setup_required
|
||||
@login_required
|
||||
@edit_permission_required
|
||||
@ -358,9 +366,10 @@ class TriggerSubscriptionBuilderLogsApi(Resource):
|
||||
@account_initialization_required
|
||||
def get(self, provider: str, subscription_builder_id: str):
|
||||
"""Get the request logs for a subscription instance for a trigger provider"""
|
||||
|
||||
try:
|
||||
logs = TriggerSubscriptionBuilderService.list_logs(subscription_builder_id)
|
||||
return jsonable_encoder({"logs": [log.model_dump(mode="json") for log in logs]})
|
||||
return dump_response(TriggerSubscriptionBuilderLogsResponse, {"logs": logs})
|
||||
except Exception as e:
|
||||
logger.exception("Error getting request logs for subscription builder", exc_info=e)
|
||||
raise
|
||||
@ -371,7 +380,9 @@ class TriggerSubscriptionBuilderLogsApi(Resource):
|
||||
)
|
||||
class TriggerSubscriptionBuilderBuildApi(Resource):
|
||||
@console_ns.expect(console_ns.models[TriggerSubscriptionBuilderUpdatePayload.__name__])
|
||||
@console_ns.response(200, "Success", console_ns.models[TriggerProviderOpaqueResponse.__name__])
|
||||
@console_ns.response(
|
||||
200, "Trigger subscription builder built successfully", console_ns.models[SimpleResultResponse.__name__]
|
||||
)
|
||||
@setup_required
|
||||
@login_required
|
||||
@edit_permission_required
|
||||
@ -395,7 +406,7 @@ class TriggerSubscriptionBuilderBuildApi(Resource):
|
||||
properties=payload.properties,
|
||||
),
|
||||
)
|
||||
return 200
|
||||
return SimpleResultResponse(result="success").model_dump(mode="json")
|
||||
except Exception as e:
|
||||
logger.exception("Error building provider credential", exc_info=e)
|
||||
raise ValueError(str(e)) from e
|
||||
@ -406,7 +417,9 @@ class TriggerSubscriptionBuilderBuildApi(Resource):
|
||||
)
|
||||
class TriggerSubscriptionUpdateApi(Resource):
|
||||
@console_ns.expect(console_ns.models[TriggerSubscriptionBuilderUpdatePayload.__name__])
|
||||
@console_ns.response(200, "Success", console_ns.models[TriggerProviderOpaqueResponse.__name__])
|
||||
@console_ns.response(
|
||||
200, "Trigger subscription updated successfully", console_ns.models[SimpleResultResponse.__name__]
|
||||
)
|
||||
@setup_required
|
||||
@login_required
|
||||
@edit_permission_required
|
||||
@ -415,6 +428,7 @@ class TriggerSubscriptionUpdateApi(Resource):
|
||||
@with_current_tenant_id
|
||||
def post(self, tenant_id: str, subscription_id: str):
|
||||
"""Update a subscription instance"""
|
||||
|
||||
request = TriggerSubscriptionBuilderUpdatePayload.model_validate(console_ns.payload or {})
|
||||
|
||||
subscription = TriggerProviderService.get_subscription_by_id(
|
||||
@ -440,7 +454,7 @@ class TriggerSubscriptionUpdateApi(Resource):
|
||||
name=request.name,
|
||||
properties=request.properties,
|
||||
)
|
||||
return 200
|
||||
return SimpleResultResponse(result="success").model_dump(mode="json")
|
||||
|
||||
# For the rest cases(API_KEY, OAUTH2)
|
||||
# we need to call third party provider(e.g. GitHub) to rebuild the subscription
|
||||
@ -452,7 +466,7 @@ class TriggerSubscriptionUpdateApi(Resource):
|
||||
credentials=request.credentials or subscription.credentials,
|
||||
parameters=request.parameters or subscription.parameters,
|
||||
)
|
||||
return 200
|
||||
return SimpleResultResponse(result="success").model_dump(mode="json")
|
||||
except ValueError as e:
|
||||
raise BadRequest(str(e))
|
||||
except Exception as e:
|
||||
@ -473,6 +487,7 @@ class TriggerSubscriptionDeleteApi(Resource):
|
||||
@with_current_tenant_id
|
||||
def post(self, tenant_id: str, subscription_id: str):
|
||||
"""Delete a subscription instance"""
|
||||
|
||||
try:
|
||||
with sessionmaker(db.engine).begin() as session:
|
||||
# Delete trigger provider subscription
|
||||
@ -487,7 +502,7 @@ class TriggerSubscriptionDeleteApi(Resource):
|
||||
tenant_id=tenant_id,
|
||||
subscription_id=subscription_id,
|
||||
)
|
||||
return {"result": "success"}
|
||||
return SimpleResultResponse(result="success").model_dump(mode="json")
|
||||
except ValueError as e:
|
||||
raise BadRequest(str(e))
|
||||
except Exception as e:
|
||||
@ -497,9 +512,10 @@ class TriggerSubscriptionDeleteApi(Resource):
|
||||
|
||||
@console_ns.route("/workspaces/current/trigger-provider/<path:provider>/subscriptions/oauth/authorize")
|
||||
class TriggerOAuthAuthorizeApi(Resource):
|
||||
# response-contract:ignore cookie-bearing Flask response
|
||||
@console_ns.response(
|
||||
200,
|
||||
"Authorization URL retrieved successfully",
|
||||
"Trigger OAuth authorization URL generated successfully",
|
||||
console_ns.models[TriggerOAuthAuthorizeResponse.__name__],
|
||||
)
|
||||
@setup_required
|
||||
@ -509,10 +525,12 @@ class TriggerOAuthAuthorizeApi(Resource):
|
||||
@with_current_tenant_id
|
||||
def get(self, tenant_id: str, user: Account, provider: str):
|
||||
"""Initiate OAuth authorization flow for a trigger provider"""
|
||||
|
||||
try:
|
||||
provider_id = TriggerProviderID(provider)
|
||||
plugin_id = provider_id.plugin_id
|
||||
provider_name = provider_id.provider_name
|
||||
tenant_id = tenant_id
|
||||
|
||||
# Get OAuth client configuration
|
||||
oauth_client_params = TriggerProviderService.get_oauth_client(
|
||||
@ -556,15 +574,12 @@ class TriggerOAuthAuthorizeApi(Resource):
|
||||
system_credentials=oauth_client_params,
|
||||
)
|
||||
|
||||
# Create response with cookie
|
||||
response = make_response(
|
||||
jsonable_encoder(
|
||||
{
|
||||
"authorization_url": authorization_url_response.authorization_url,
|
||||
"subscription_builder_id": subscription_builder.id,
|
||||
"subscription_builder": subscription_builder,
|
||||
}
|
||||
)
|
||||
TriggerOAuthAuthorizeResponse(
|
||||
authorization_url=authorization_url_response.authorization_url,
|
||||
subscription_builder_id=subscription_builder.id,
|
||||
subscription_builder=subscription_builder,
|
||||
).model_dump(mode="json")
|
||||
)
|
||||
response.set_cookie(
|
||||
"context_id",
|
||||
@ -583,11 +598,8 @@ class TriggerOAuthAuthorizeApi(Resource):
|
||||
|
||||
@console_ns.route("/oauth/plugin/<path:provider>/trigger/callback")
|
||||
class TriggerOAuthCallbackApi(Resource):
|
||||
@console_ns.response(
|
||||
302,
|
||||
"Redirect to console OAuth callback page",
|
||||
console_ns.models[RedirectResponse.__name__],
|
||||
)
|
||||
# response-contract:ignore redirect response
|
||||
@console_ns.response(302, "Redirect to OAuth callback page")
|
||||
@setup_required
|
||||
def get(self, provider: str):
|
||||
"""Handle OAuth callback for trigger provider"""
|
||||
@ -653,7 +665,11 @@ class TriggerOAuthCallbackApi(Resource):
|
||||
|
||||
@console_ns.route("/workspaces/current/trigger-provider/<path:provider>/oauth/client")
|
||||
class TriggerOAuthClientManageApi(Resource):
|
||||
@console_ns.response(200, "Success", console_ns.models[TriggerOAuthClientResponse.__name__])
|
||||
@console_ns.response(
|
||||
200,
|
||||
"Trigger OAuth client retrieved successfully",
|
||||
console_ns.models[TriggerOAuthClientResponse.__name__],
|
||||
)
|
||||
@setup_required
|
||||
@login_required
|
||||
@is_admin_or_owner_required
|
||||
@ -662,6 +678,7 @@ class TriggerOAuthClientManageApi(Resource):
|
||||
@with_current_tenant_id
|
||||
def get(self, tenant_id: str, provider: str):
|
||||
"""Get OAuth client configuration for a provider"""
|
||||
|
||||
try:
|
||||
provider_id = TriggerProviderID(provider)
|
||||
|
||||
@ -682,24 +699,24 @@ class TriggerOAuthClientManageApi(Resource):
|
||||
)
|
||||
provider_controller = TriggerManager.get_trigger_provider(tenant_id, provider_id)
|
||||
redirect_uri = f"{dify_config.CONSOLE_API_URL}/console/api/oauth/plugin/{provider}/trigger/callback"
|
||||
return jsonable_encoder(
|
||||
{
|
||||
"configured": bool(custom_params or system_client_exists),
|
||||
"system_configured": system_client_exists,
|
||||
"custom_configured": bool(custom_params),
|
||||
"oauth_client_schema": provider_controller.get_oauth_client_schema(),
|
||||
"custom_enabled": is_custom_enabled,
|
||||
"redirect_uri": redirect_uri,
|
||||
"params": custom_params or {},
|
||||
}
|
||||
)
|
||||
return TriggerOAuthClientResponse(
|
||||
configured=bool(custom_params or system_client_exists),
|
||||
system_configured=system_client_exists,
|
||||
custom_configured=bool(custom_params),
|
||||
oauth_client_schema=provider_controller.get_oauth_client_schema(),
|
||||
custom_enabled=is_custom_enabled,
|
||||
redirect_uri=redirect_uri,
|
||||
params=dict(custom_params or {}),
|
||||
).model_dump(mode="json")
|
||||
|
||||
except Exception as e:
|
||||
logger.exception("Error getting OAuth client", exc_info=e)
|
||||
raise
|
||||
|
||||
@console_ns.expect(console_ns.models[TriggerOAuthClientPayload.__name__])
|
||||
@console_ns.response(200, "Success", console_ns.models[SimpleResultResponse.__name__])
|
||||
@console_ns.response(
|
||||
200, "Trigger OAuth client saved successfully", console_ns.models[SimpleResultResponse.__name__]
|
||||
)
|
||||
@setup_required
|
||||
@login_required
|
||||
@is_admin_or_owner_required
|
||||
@ -708,16 +725,18 @@ class TriggerOAuthClientManageApi(Resource):
|
||||
@with_current_tenant_id
|
||||
def post(self, tenant_id: str, provider: str):
|
||||
"""Configure custom OAuth client for a provider"""
|
||||
|
||||
payload = TriggerOAuthClientPayload.model_validate(console_ns.payload or {})
|
||||
|
||||
try:
|
||||
provider_id = TriggerProviderID(provider)
|
||||
return TriggerProviderService.save_custom_oauth_client_params(
|
||||
result = TriggerProviderService.save_custom_oauth_client_params(
|
||||
tenant_id=tenant_id,
|
||||
provider_id=provider_id,
|
||||
client_params=payload.client_params,
|
||||
enabled=payload.enabled,
|
||||
)
|
||||
return dump_response(SimpleResultResponse, result)
|
||||
|
||||
except ValueError as e:
|
||||
raise BadRequest(str(e))
|
||||
@ -725,22 +744,26 @@ class TriggerOAuthClientManageApi(Resource):
|
||||
logger.exception("Error configuring OAuth client", exc_info=e)
|
||||
raise
|
||||
|
||||
@console_ns.response(
|
||||
200, "Trigger OAuth client deleted successfully", console_ns.models[SimpleResultResponse.__name__]
|
||||
)
|
||||
@setup_required
|
||||
@login_required
|
||||
@is_admin_or_owner_required
|
||||
@rbac_permission_required(RBACResourceScope.WORKSPACE, RBACPermission.PLUGIN_PREFERENCES, resource_required=False)
|
||||
@account_initialization_required
|
||||
@console_ns.response(200, "Success", console_ns.models[SimpleResultResponse.__name__])
|
||||
@with_current_tenant_id
|
||||
def delete(self, tenant_id: str, provider: str):
|
||||
"""Remove custom OAuth client configuration"""
|
||||
|
||||
try:
|
||||
provider_id = TriggerProviderID(provider)
|
||||
|
||||
return TriggerProviderService.delete_custom_oauth_client_params(
|
||||
result = TriggerProviderService.delete_custom_oauth_client_params(
|
||||
tenant_id=tenant_id,
|
||||
provider_id=provider_id,
|
||||
)
|
||||
return dump_response(SimpleResultResponse, result)
|
||||
except ValueError as e:
|
||||
raise BadRequest(str(e))
|
||||
except Exception as e:
|
||||
@ -753,7 +776,11 @@ class TriggerOAuthClientManageApi(Resource):
|
||||
)
|
||||
class TriggerSubscriptionVerifyApi(Resource):
|
||||
@console_ns.expect(console_ns.models[TriggerSubscriptionBuilderVerifyPayload.__name__])
|
||||
@console_ns.response(200, "Success", console_ns.models[TriggerSubscriptionBuilderVerifyResponse.__name__])
|
||||
@console_ns.response(
|
||||
200,
|
||||
"Trigger subscription verified successfully",
|
||||
console_ns.models[TriggerVerificationResponse.__name__],
|
||||
)
|
||||
@setup_required
|
||||
@login_required
|
||||
@edit_permission_required
|
||||
@ -763,6 +790,7 @@ class TriggerSubscriptionVerifyApi(Resource):
|
||||
@with_current_tenant_id
|
||||
def post(self, tenant_id: str, user: Account, provider: str, subscription_id: str):
|
||||
"""Verify credentials for an existing subscription (edit mode only)"""
|
||||
|
||||
verify_request = TriggerSubscriptionBuilderVerifyPayload.model_validate(console_ns.payload or {})
|
||||
|
||||
try:
|
||||
@ -773,7 +801,7 @@ class TriggerSubscriptionVerifyApi(Resource):
|
||||
subscription_id=subscription_id,
|
||||
credentials=verify_request.credentials,
|
||||
)
|
||||
return result
|
||||
return dump_response(TriggerVerificationResponse, result)
|
||||
except ValueError as e:
|
||||
logger.warning("Credential verification failed", exc_info=e)
|
||||
raise BadRequest(str(e)) from e
|
||||
|
||||
@ -2,11 +2,11 @@ from typing import Any, Union
|
||||
|
||||
from flask import Response, request
|
||||
from flask_restx import Resource
|
||||
from pydantic import BaseModel, Field, ValidationError
|
||||
from pydantic import BaseModel, Field, RootModel, ValidationError
|
||||
from sqlalchemy import select
|
||||
from sqlalchemy.orm import Session, sessionmaker
|
||||
|
||||
from controllers.common.schema import register_schema_model
|
||||
from controllers.common.schema import register_response_schema_models, register_schema_model
|
||||
from controllers.mcp import mcp_ns
|
||||
from core.mcp import types as mcp_types
|
||||
from core.mcp.server.streamable_http import handle_mcp_request, negotiate_protocol_version
|
||||
@ -33,7 +33,12 @@ class MCPRequestPayload(BaseModel):
|
||||
id: int | str | None = Field(default=None, description="Request ID for tracking responses")
|
||||
|
||||
|
||||
class MCPJSONRPCResponse(RootModel[mcp_types.JSONRPCResponse | mcp_types.JSONRPCError]):
|
||||
pass
|
||||
|
||||
|
||||
register_schema_model(mcp_ns, MCPRequestPayload)
|
||||
register_response_schema_models(mcp_ns, MCPJSONRPCResponse)
|
||||
|
||||
|
||||
@mcp_ns.route("/server/<string:server_code>/mcp")
|
||||
@ -42,13 +47,10 @@ class MCPAppApi(Resource):
|
||||
@mcp_ns.doc("handle_mcp_request")
|
||||
@mcp_ns.doc(description="Handle Model Context Protocol (MCP) requests for a specific server")
|
||||
@mcp_ns.doc(params={"server_code": "Unique identifier for the MCP server"})
|
||||
@mcp_ns.doc(
|
||||
responses={
|
||||
200: "MCP response successfully processed",
|
||||
400: "Invalid MCP request or parameters",
|
||||
404: "Server or app not found",
|
||||
}
|
||||
)
|
||||
@mcp_ns.response(200, "MCP JSON-RPC response", mcp_ns.models[MCPJSONRPCResponse.__name__])
|
||||
@mcp_ns.response(202, "MCP notification accepted")
|
||||
@mcp_ns.response(400, "Invalid MCP request or parameters")
|
||||
@mcp_ns.response(404, "Server or app not found")
|
||||
def post(self, server_code: str):
|
||||
"""Handle MCP requests for a specific server.
|
||||
|
||||
@ -64,6 +66,7 @@ class MCPAppApi(Resource):
|
||||
Raises:
|
||||
ValidationError: Invalid request format or parameters
|
||||
"""
|
||||
# response-contract:ignore MCP route returns Flask Response from JSON-RPC handler
|
||||
args = MCPRequestPayload.model_validate(mcp_ns.payload or {})
|
||||
request_id: Union[int, str] | None = args.id
|
||||
mcp_request = self._parse_mcp_request(args.model_dump(exclude_none=True))
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
import re
|
||||
import tempfile
|
||||
from pathlib import Path
|
||||
from typing import Union
|
||||
from typing import Literal, overload
|
||||
from urllib.parse import unquote
|
||||
|
||||
from configs import dify_config
|
||||
@ -40,10 +40,22 @@ USER_AGENT = (
|
||||
|
||||
|
||||
class ExtractProcessor:
|
||||
@overload
|
||||
@classmethod
|
||||
def load_from_upload_file(
|
||||
cls, upload_file: UploadFile, return_text: Literal[True], is_automatic: bool = False
|
||||
) -> str: ...
|
||||
|
||||
@overload
|
||||
@classmethod
|
||||
def load_from_upload_file(
|
||||
cls, upload_file: UploadFile, return_text: Literal[False] = False, is_automatic: bool = False
|
||||
) -> list[Document]: ...
|
||||
|
||||
@classmethod
|
||||
def load_from_upload_file(
|
||||
cls, upload_file: UploadFile, return_text: bool = False, is_automatic: bool = False
|
||||
) -> Union[list[Document], str]:
|
||||
) -> list[Document] | str:
|
||||
extract_setting = ExtractSetting(
|
||||
datasource_type=DatasourceType.FILE, upload_file=upload_file, document_model="text_model"
|
||||
)
|
||||
@ -53,8 +65,16 @@ class ExtractProcessor:
|
||||
else:
|
||||
return cls.extract(extract_setting, is_automatic)
|
||||
|
||||
@overload
|
||||
@classmethod
|
||||
def load_from_url(cls, url: str, return_text: bool = False) -> Union[list[Document], str]:
|
||||
def load_from_url(cls, url: str, return_text: Literal[True]) -> str: ...
|
||||
|
||||
@overload
|
||||
@classmethod
|
||||
def load_from_url(cls, url: str, return_text: Literal[False] = False) -> list[Document]: ...
|
||||
|
||||
@classmethod
|
||||
def load_from_url(cls, url: str, return_text: bool = False) -> list[Document] | str:
|
||||
response = remote_fetcher.make_request("GET", url, headers={"User-Agent": USER_AGENT})
|
||||
|
||||
with tempfile.TemporaryDirectory() as temp_dir:
|
||||
|
||||
@ -74,8 +74,6 @@ class ToolProviderApiEntity(BaseModel):
|
||||
for parameter in tool.get("parameters"):
|
||||
if parameter.get("type") == ToolParameter.ToolParameterType.SYSTEM_FILES:
|
||||
parameter["type"] = "files"
|
||||
if parameter.get("input_schema") is None:
|
||||
parameter.pop("input_schema", None)
|
||||
# -------------
|
||||
optional_fields = self.optional_field("server_url", self.server_url)
|
||||
match self.type:
|
||||
|
||||
@ -16,30 +16,16 @@ from yarl import URL
|
||||
|
||||
import contexts
|
||||
from configs import dify_config
|
||||
from core.entities import PluginCredentialType
|
||||
from core.helper.provider_cache import ToolProviderCredentialsCache
|
||||
from core.plugin.impl.tool import PluginToolManager
|
||||
from core.tools.__base.tool_provider import ToolProviderController
|
||||
from core.tools.__base.tool_runtime import ToolRuntime
|
||||
from core.tools.mcp_tool.provider import MCPToolProviderController
|
||||
from core.tools.mcp_tool.tool import MCPTool
|
||||
from core.tools.plugin_tool.provider import PluginToolProviderController
|
||||
from core.tools.plugin_tool.tool import PluginTool
|
||||
from core.tools.utils.uuid_utils import is_valid_uuid
|
||||
from core.tools.workflow_as_tool.provider import WorkflowToolProviderController
|
||||
from extensions.ext_database import db
|
||||
from graphon.runtime import VariablePool
|
||||
from models.provider_ids import ToolProviderID
|
||||
from services.tools.mcp_tools_manage_service import MCPToolManageService
|
||||
|
||||
if TYPE_CHECKING:
|
||||
pass
|
||||
|
||||
from core.agent.entities import AgentToolEntity
|
||||
from core.app.entities.app_invoke_entities import InvokeFrom
|
||||
from core.entities import PluginCredentialType
|
||||
from core.helper.module_import_helper import load_single_subclass_from_source
|
||||
from core.helper.position_helper import is_filtered
|
||||
from core.helper.provider_cache import ToolProviderCredentialsCache
|
||||
from core.plugin.impl.tool import PluginToolManager
|
||||
from core.tools.__base.tool import Tool
|
||||
from core.tools.__base.tool_provider import ToolProviderController
|
||||
from core.tools.__base.tool_runtime import ToolRuntime
|
||||
from core.tools.builtin_tool.provider import BuiltinToolProviderController
|
||||
from core.tools.builtin_tool.providers._positions import BuiltinToolProviderSort
|
||||
from core.tools.builtin_tool.tool import BuiltinTool
|
||||
@ -49,6 +35,7 @@ from core.tools.entities.api_entities import ToolProviderApiEntity, ToolProvider
|
||||
from core.tools.entities.common_entities import I18nObject
|
||||
from core.tools.entities.tool_entities import (
|
||||
ApiProviderAuthType,
|
||||
ApiProviderSchemaType,
|
||||
EmojiIconDict,
|
||||
ToolInvokeFrom,
|
||||
ToolParameter,
|
||||
@ -56,12 +43,21 @@ from core.tools.entities.tool_entities import (
|
||||
emoji_icon_adapter,
|
||||
)
|
||||
from core.tools.errors import ToolProviderNotFoundError
|
||||
from core.tools.mcp_tool.provider import MCPToolProviderController
|
||||
from core.tools.mcp_tool.tool import MCPTool
|
||||
from core.tools.plugin_tool.provider import PluginToolProviderController
|
||||
from core.tools.plugin_tool.tool import PluginTool
|
||||
from core.tools.tool_label_manager import ToolLabelManager
|
||||
from core.tools.utils.configuration import ToolParameterConfigurationManager
|
||||
from core.tools.utils.encryption import create_provider_encrypter, create_tool_provider_encrypter
|
||||
from core.tools.utils.uuid_utils import is_valid_uuid
|
||||
from core.tools.workflow_as_tool.provider import WorkflowToolProviderController
|
||||
from core.tools.workflow_as_tool.tool import WorkflowTool
|
||||
from graphon.model_runtime.utils.encoders import jsonable_encoder
|
||||
from extensions.ext_database import db
|
||||
from graphon.runtime import VariablePool
|
||||
from models.provider_ids import ToolProviderID
|
||||
from models.tools import ApiToolProvider, BuiltinToolProvider, WorkflowToolProvider
|
||||
from services.tools.mcp_tools_manage_service import MCPToolManageService
|
||||
from services.tools.tools_transform_service import ToolTransformService
|
||||
|
||||
if TYPE_CHECKING:
|
||||
@ -921,23 +917,20 @@ class ToolManager:
|
||||
|
||||
# add tool labels
|
||||
labels = ToolLabelManager.get_tool_labels(controller)
|
||||
schema_type = provider_obj.schema_type
|
||||
schema_type_value = schema_type.value if isinstance(schema_type, ApiProviderSchemaType) else schema_type
|
||||
|
||||
return cast(
|
||||
dict,
|
||||
jsonable_encoder(
|
||||
{
|
||||
"schema_type": provider_obj.schema_type,
|
||||
"schema": provider_obj.schema,
|
||||
"tools": provider_obj.tools,
|
||||
"icon": icon,
|
||||
"description": provider_obj.description,
|
||||
"credentials": masked_credentials,
|
||||
"privacy_policy": provider_obj.privacy_policy,
|
||||
"custom_disclaimer": provider_obj.custom_disclaimer,
|
||||
"labels": labels,
|
||||
}
|
||||
),
|
||||
)
|
||||
return {
|
||||
"schema_type": schema_type_value,
|
||||
"schema": provider_obj.schema,
|
||||
"tools": [tool.model_dump(mode="json") for tool in provider_obj.tools],
|
||||
"icon": icon,
|
||||
"description": provider_obj.description,
|
||||
"credentials": masked_credentials,
|
||||
"privacy_policy": provider_obj.privacy_policy,
|
||||
"custom_disclaimer": provider_obj.custom_disclaimer,
|
||||
"labels": labels,
|
||||
}
|
||||
|
||||
@classmethod
|
||||
def generate_builtin_tool_icon_url(cls, provider_id: str) -> str:
|
||||
|
||||
@ -1,20 +0,0 @@
|
||||
from typing import override
|
||||
|
||||
from flask_restx import fields
|
||||
|
||||
from graphon.file import File
|
||||
|
||||
|
||||
class FilesContainedField(fields.Raw):
|
||||
@override
|
||||
def format(self, value):
|
||||
return self._format_file_object(value)
|
||||
|
||||
def _format_file_object(self, v):
|
||||
if isinstance(v, File):
|
||||
return v.model_dump()
|
||||
if isinstance(v, dict):
|
||||
return {k: self._format_file_object(vv) for k, vv in v.items()}
|
||||
if isinstance(v, list):
|
||||
return [self._format_file_object(vv) for vv in v]
|
||||
return v
|
||||
@ -7460,9 +7460,9 @@ Get instruction generation template
|
||||
|
||||
#### Responses
|
||||
|
||||
| Code | Description | Schema |
|
||||
| ---- | ----------- | ------ |
|
||||
| 302 | Redirect to console OAuth callback page | **application/json**: [RedirectResponse](#redirectresponse)<br> |
|
||||
| Code | Description |
|
||||
| ---- | ----------- |
|
||||
| 302 | Redirect to OAuth callback page |
|
||||
|
||||
### [GET] /notification
|
||||
Return the active in-product notification for the current user in their interface language (falls back to English if unavailable). The notification is NOT marked as seen here; call POST /notification/dismiss when the user explicitly closes the modal.
|
||||
@ -7667,7 +7667,7 @@ Initiate OAuth login process
|
||||
|
||||
| Code | Description | Schema |
|
||||
| ---- | ----------- | ------ |
|
||||
| 200 | Authorization URL retrieved successfully | **application/json**: [PluginOAuthAuthorizationUrlResponse](#pluginoauthauthorizationurlresponse)<br> |
|
||||
| 200 | Tool OAuth authorization URL generated successfully | **application/json**: [PluginOAuthAuthorizationUrlResponse](#pluginoauthauthorizationurlresponse)<br> |
|
||||
|
||||
### [GET] /oauth/plugin/{provider}/tool/callback
|
||||
#### Parameters
|
||||
@ -7678,9 +7678,9 @@ Initiate OAuth login process
|
||||
|
||||
#### Responses
|
||||
|
||||
| Code | Description | Schema |
|
||||
| ---- | ----------- | ------ |
|
||||
| 302 | Redirect to console OAuth callback page | **application/json**: [RedirectResponse](#redirectresponse)<br> |
|
||||
| Code | Description |
|
||||
| ---- | ----------- |
|
||||
| 302 | Redirect to OAuth callback page |
|
||||
|
||||
### [GET] /oauth/plugin/{provider}/trigger/callback
|
||||
**Handle OAuth callback for trigger provider**
|
||||
@ -7693,9 +7693,9 @@ Initiate OAuth login process
|
||||
|
||||
#### Responses
|
||||
|
||||
| Code | Description | Schema |
|
||||
| ---- | ----------- | ------ |
|
||||
| 302 | Redirect to console OAuth callback page | **application/json**: [RedirectResponse](#redirectresponse)<br> |
|
||||
| Code | Description |
|
||||
| ---- | ----------- |
|
||||
| 302 | Redirect to OAuth callback page |
|
||||
|
||||
### [POST] /oauth/provider
|
||||
#### Request Body
|
||||
@ -11660,7 +11660,7 @@ Returns permission flags that control workspace features like member invitations
|
||||
|
||||
| Code | Description | Schema |
|
||||
| ---- | ----------- | ------ |
|
||||
| 200 | Success | **application/json**: [ToolProviderOpaqueResponse](#toolprovideropaqueresponse)<br> |
|
||||
| 200 | Tool labels retrieved successfully | **application/json**: [ToolLabelListResponse](#toollabellistresponse)<br> |
|
||||
|
||||
### [POST] /workspaces/current/tool-provider/api/add
|
||||
#### Request Body
|
||||
@ -11673,7 +11673,7 @@ Returns permission flags that control workspace features like member invitations
|
||||
|
||||
| Code | Description | Schema |
|
||||
| ---- | ----------- | ------ |
|
||||
| 200 | Success | **application/json**: [ToolProviderOpaqueResponse](#toolprovideropaqueresponse)<br> |
|
||||
| 200 | API provider added successfully | **application/json**: [SimpleResultResponse](#simpleresultresponse)<br> |
|
||||
|
||||
### [POST] /workspaces/current/tool-provider/api/delete
|
||||
#### Request Body
|
||||
@ -11686,7 +11686,7 @@ Returns permission flags that control workspace features like member invitations
|
||||
|
||||
| Code | Description | Schema |
|
||||
| ---- | ----------- | ------ |
|
||||
| 200 | Success | **application/json**: [ToolProviderOpaqueResponse](#toolprovideropaqueresponse)<br> |
|
||||
| 200 | API provider deleted successfully | **application/json**: [SimpleResultResponse](#simpleresultresponse)<br> |
|
||||
|
||||
### [GET] /workspaces/current/tool-provider/api/get
|
||||
#### Parameters
|
||||
@ -11699,7 +11699,7 @@ Returns permission flags that control workspace features like member invitations
|
||||
|
||||
| Code | Description | Schema |
|
||||
| ---- | ----------- | ------ |
|
||||
| 200 | Success | **application/json**: [ToolProviderOpaqueResponse](#toolprovideropaqueresponse)<br> |
|
||||
| 200 | API provider retrieved successfully | **application/json**: [ApiProviderDetailResponse](#apiproviderdetailresponse)<br> |
|
||||
|
||||
### [GET] /workspaces/current/tool-provider/api/remote
|
||||
#### Parameters
|
||||
@ -11712,7 +11712,7 @@ Returns permission flags that control workspace features like member invitations
|
||||
|
||||
| Code | Description | Schema |
|
||||
| ---- | ----------- | ------ |
|
||||
| 200 | Success | **application/json**: [ToolProviderOpaqueResponse](#toolprovideropaqueresponse)<br> |
|
||||
| 200 | Remote API provider schema retrieved successfully | **application/json**: [ApiProviderRemoteSchemaResponse](#apiproviderremoteschemaresponse)<br> |
|
||||
|
||||
### [POST] /workspaces/current/tool-provider/api/schema
|
||||
#### Request Body
|
||||
@ -11725,7 +11725,7 @@ Returns permission flags that control workspace features like member invitations
|
||||
|
||||
| Code | Description | Schema |
|
||||
| ---- | ----------- | ------ |
|
||||
| 200 | Success | **application/json**: [ToolProviderOpaqueResponse](#toolprovideropaqueresponse)<br> |
|
||||
| 200 | API schema parsed successfully | **application/json**: [ApiSchemaParseResponse](#apischemaparseresponse)<br> |
|
||||
|
||||
### [POST] /workspaces/current/tool-provider/api/test/pre
|
||||
#### Request Body
|
||||
@ -11738,7 +11738,7 @@ Returns permission flags that control workspace features like member invitations
|
||||
|
||||
| Code | Description | Schema |
|
||||
| ---- | ----------- | ------ |
|
||||
| 200 | Success | **application/json**: [ToolProviderOpaqueResponse](#toolprovideropaqueresponse)<br> |
|
||||
| 200 | API tool test preview completed successfully | **application/json**: [ApiToolPreviewResponse](#apitoolpreviewresponse)<br> |
|
||||
|
||||
### [GET] /workspaces/current/tool-provider/api/tools
|
||||
#### Parameters
|
||||
@ -11751,7 +11751,7 @@ Returns permission flags that control workspace features like member invitations
|
||||
|
||||
| Code | Description | Schema |
|
||||
| ---- | ----------- | ------ |
|
||||
| 200 | Success | **application/json**: [ToolProviderOpaqueResponse](#toolprovideropaqueresponse)<br> |
|
||||
| 200 | API provider tools retrieved successfully | **application/json**: [ToolApiListResponse](#toolapilistresponse)<br> |
|
||||
|
||||
### [POST] /workspaces/current/tool-provider/api/update
|
||||
#### Request Body
|
||||
@ -11764,7 +11764,7 @@ Returns permission flags that control workspace features like member invitations
|
||||
|
||||
| Code | Description | Schema |
|
||||
| ---- | ----------- | ------ |
|
||||
| 200 | Success | **application/json**: [ToolProviderOpaqueResponse](#toolprovideropaqueresponse)<br> |
|
||||
| 200 | API provider updated successfully | **application/json**: [SimpleResultResponse](#simpleresultresponse)<br> |
|
||||
|
||||
### [POST] /workspaces/current/tool-provider/builtin/{provider}/add
|
||||
#### Parameters
|
||||
@ -11783,7 +11783,7 @@ Returns permission flags that control workspace features like member invitations
|
||||
|
||||
| Code | Description | Schema |
|
||||
| ---- | ----------- | ------ |
|
||||
| 200 | Success | **application/json**: [ToolProviderOpaqueResponse](#toolprovideropaqueresponse)<br> |
|
||||
| 200 | Builtin provider added successfully | **application/json**: [SimpleResultResponse](#simpleresultresponse)<br> |
|
||||
|
||||
### [GET] /workspaces/current/tool-provider/builtin/{provider}/credential/info
|
||||
#### Parameters
|
||||
@ -11797,7 +11797,7 @@ Returns permission flags that control workspace features like member invitations
|
||||
|
||||
| Code | Description | Schema |
|
||||
| ---- | ----------- | ------ |
|
||||
| 200 | Success | **application/json**: [ToolProviderOpaqueResponse](#toolprovideropaqueresponse)<br> |
|
||||
| 200 | Builtin provider credential info retrieved successfully | **application/json**: [ToolProviderCredentialInfoApiEntity](#toolprovidercredentialinfoapientity)<br> |
|
||||
|
||||
### [GET] /workspaces/current/tool-provider/builtin/{provider}/credential/schema/{credential_type}
|
||||
#### Parameters
|
||||
@ -11811,7 +11811,7 @@ Returns permission flags that control workspace features like member invitations
|
||||
|
||||
| Code | Description | Schema |
|
||||
| ---- | ----------- | ------ |
|
||||
| 200 | Success | **application/json**: [ToolProviderOpaqueResponse](#toolprovideropaqueresponse)<br> |
|
||||
| 200 | Builtin provider credential schema retrieved successfully | **application/json**: [ProviderConfigListResponse](#providerconfiglistresponse)<br> |
|
||||
|
||||
### [GET] /workspaces/current/tool-provider/builtin/{provider}/credentials
|
||||
#### Parameters
|
||||
@ -11825,7 +11825,7 @@ Returns permission flags that control workspace features like member invitations
|
||||
|
||||
| Code | Description | Schema |
|
||||
| ---- | ----------- | ------ |
|
||||
| 200 | Success | **application/json**: [ToolProviderOpaqueResponse](#toolprovideropaqueresponse)<br> |
|
||||
| 200 | Builtin provider credentials retrieved successfully | **application/json**: [ToolProviderCredentialListResponse](#toolprovidercredentiallistresponse)<br> |
|
||||
|
||||
### [POST] /workspaces/current/tool-provider/builtin/{provider}/default-credential
|
||||
#### Parameters
|
||||
@ -11844,7 +11844,7 @@ Returns permission flags that control workspace features like member invitations
|
||||
|
||||
| Code | Description | Schema |
|
||||
| ---- | ----------- | ------ |
|
||||
| 200 | Success | **application/json**: [ToolProviderOpaqueResponse](#toolprovideropaqueresponse)<br> |
|
||||
| 200 | Default credential set successfully | **application/json**: [SimpleResultResponse](#simpleresultresponse)<br> |
|
||||
|
||||
### [POST] /workspaces/current/tool-provider/builtin/{provider}/delete
|
||||
#### Parameters
|
||||
@ -11863,7 +11863,7 @@ Returns permission flags that control workspace features like member invitations
|
||||
|
||||
| Code | Description | Schema |
|
||||
| ---- | ----------- | ------ |
|
||||
| 200 | Success | **application/json**: [ToolProviderOpaqueResponse](#toolprovideropaqueresponse)<br> |
|
||||
| 200 | Builtin provider credential deleted successfully | **application/json**: [SimpleResultResponse](#simpleresultresponse)<br> |
|
||||
|
||||
### [GET] /workspaces/current/tool-provider/builtin/{provider}/icon
|
||||
#### Parameters
|
||||
@ -11874,9 +11874,9 @@ Returns permission flags that control workspace features like member invitations
|
||||
|
||||
#### Responses
|
||||
|
||||
| Code | Description | Schema |
|
||||
| ---- | ----------- | ------ |
|
||||
| 200 | Success | **application/json**: [BinaryFileResponse](#binaryfileresponse)<br> |
|
||||
| Code | Description |
|
||||
| ---- | ----------- |
|
||||
| 200 | Builtin provider icon |
|
||||
|
||||
### [GET] /workspaces/current/tool-provider/builtin/{provider}/info
|
||||
#### Parameters
|
||||
@ -11889,7 +11889,7 @@ Returns permission flags that control workspace features like member invitations
|
||||
|
||||
| Code | Description | Schema |
|
||||
| ---- | ----------- | ------ |
|
||||
| 200 | Success | **application/json**: [ToolProviderOpaqueResponse](#toolprovideropaqueresponse)<br> |
|
||||
| 200 | Builtin provider info retrieved successfully | **application/json**: [ToolProviderApiEntityResponse](#toolproviderapientityresponse)<br> |
|
||||
|
||||
### [GET] /workspaces/current/tool-provider/builtin/{provider}/oauth/client-schema
|
||||
#### Parameters
|
||||
@ -11902,7 +11902,7 @@ Returns permission flags that control workspace features like member invitations
|
||||
|
||||
| Code | Description | Schema |
|
||||
| ---- | ----------- | ------ |
|
||||
| 200 | Success | **application/json**: [ToolOAuthClientSchemaResponse](#tooloauthclientschemaresponse)<br> |
|
||||
| 200 | Builtin provider OAuth client schema retrieved successfully | **application/json**: [BuiltinProviderOAuthClientSchemaResponse](#builtinprovideroauthclientschemaresponse)<br> |
|
||||
|
||||
### [DELETE] /workspaces/current/tool-provider/builtin/{provider}/oauth/custom-client
|
||||
#### Parameters
|
||||
@ -11915,7 +11915,7 @@ Returns permission flags that control workspace features like member invitations
|
||||
|
||||
| Code | Description | Schema |
|
||||
| ---- | ----------- | ------ |
|
||||
| 200 | Success | **application/json**: [SimpleResultResponse](#simpleresultresponse)<br> |
|
||||
| 200 | Custom OAuth client deleted successfully | **application/json**: [SimpleResultResponse](#simpleresultresponse)<br> |
|
||||
|
||||
### [GET] /workspaces/current/tool-provider/builtin/{provider}/oauth/custom-client
|
||||
#### Parameters
|
||||
@ -11926,9 +11926,9 @@ Returns permission flags that control workspace features like member invitations
|
||||
|
||||
#### Responses
|
||||
|
||||
| Code | Description | Schema |
|
||||
| ---- | ----------- | ------ |
|
||||
| 200 | Success | **application/json**: [ToolOAuthCustomClientResponse](#tooloauthcustomclientresponse)<br> |
|
||||
| Code | Description |
|
||||
| ---- | ----------- |
|
||||
| 200 | Custom OAuth client retrieved successfully |
|
||||
|
||||
### [POST] /workspaces/current/tool-provider/builtin/{provider}/oauth/custom-client
|
||||
#### Parameters
|
||||
@ -11947,7 +11947,7 @@ Returns permission flags that control workspace features like member invitations
|
||||
|
||||
| Code | Description | Schema |
|
||||
| ---- | ----------- | ------ |
|
||||
| 200 | Success | **application/json**: [SimpleResultResponse](#simpleresultresponse)<br> |
|
||||
| 200 | Custom OAuth client saved successfully | **application/json**: [SimpleResultResponse](#simpleresultresponse)<br> |
|
||||
|
||||
### [GET] /workspaces/current/tool-provider/builtin/{provider}/tools
|
||||
#### Parameters
|
||||
@ -11960,7 +11960,7 @@ Returns permission flags that control workspace features like member invitations
|
||||
|
||||
| Code | Description | Schema |
|
||||
| ---- | ----------- | ------ |
|
||||
| 200 | Success | **application/json**: [ToolProviderOpaqueResponse](#toolprovideropaqueresponse)<br> |
|
||||
| 200 | Builtin provider tools retrieved successfully | **application/json**: [ToolApiListResponse](#toolapilistresponse)<br> |
|
||||
|
||||
### [POST] /workspaces/current/tool-provider/builtin/{provider}/update
|
||||
#### Parameters
|
||||
@ -11979,7 +11979,7 @@ Returns permission flags that control workspace features like member invitations
|
||||
|
||||
| Code | Description | Schema |
|
||||
| ---- | ----------- | ------ |
|
||||
| 200 | Success | **application/json**: [ToolProviderOpaqueResponse](#toolprovideropaqueresponse)<br> |
|
||||
| 200 | Builtin provider updated successfully | **application/json**: [SimpleResultResponse](#simpleresultresponse)<br> |
|
||||
|
||||
### [DELETE] /workspaces/current/tool-provider/mcp
|
||||
#### Request Body
|
||||
@ -12005,7 +12005,7 @@ Returns permission flags that control workspace features like member invitations
|
||||
|
||||
| Code | Description | Schema |
|
||||
| ---- | ----------- | ------ |
|
||||
| 200 | Success | **application/json**: [ToolProviderOpaqueResponse](#toolprovideropaqueresponse)<br> |
|
||||
| 200 | MCP provider created successfully | **application/json**: [ToolProviderApiEntityResponse](#toolproviderapientityresponse)<br> |
|
||||
|
||||
### [PUT] /workspaces/current/tool-provider/mcp
|
||||
#### Request Body
|
||||
@ -12018,7 +12018,7 @@ Returns permission flags that control workspace features like member invitations
|
||||
|
||||
| Code | Description | Schema |
|
||||
| ---- | ----------- | ------ |
|
||||
| 200 | Success | **application/json**: [SimpleResultResponse](#simpleresultresponse)<br> |
|
||||
| 200 | MCP provider updated successfully | **application/json**: [SimpleResultResponse](#simpleresultresponse)<br> |
|
||||
|
||||
### [POST] /workspaces/current/tool-provider/mcp/auth
|
||||
#### Request Body
|
||||
@ -12031,7 +12031,7 @@ Returns permission flags that control workspace features like member invitations
|
||||
|
||||
| Code | Description | Schema |
|
||||
| ---- | ----------- | ------ |
|
||||
| 200 | Success | **application/json**: [ToolProviderOpaqueResponse](#toolprovideropaqueresponse)<br> |
|
||||
| 200 | MCP provider authorized successfully | **application/json**: [MCPAuthResponse](#mcpauthresponse)<br> |
|
||||
|
||||
### [GET] /workspaces/current/tool-provider/mcp/tools/{provider_id}
|
||||
#### Parameters
|
||||
@ -12044,7 +12044,7 @@ Returns permission flags that control workspace features like member invitations
|
||||
|
||||
| Code | Description | Schema |
|
||||
| ---- | ----------- | ------ |
|
||||
| 200 | Success | **application/json**: [ToolProviderOpaqueResponse](#toolprovideropaqueresponse)<br> |
|
||||
| 200 | MCP provider retrieved successfully | **application/json**: [ToolProviderApiEntityResponse](#toolproviderapientityresponse)<br> |
|
||||
|
||||
### [GET] /workspaces/current/tool-provider/mcp/update/{provider_id}
|
||||
#### Parameters
|
||||
@ -12057,7 +12057,7 @@ Returns permission flags that control workspace features like member invitations
|
||||
|
||||
| Code | Description | Schema |
|
||||
| ---- | ----------- | ------ |
|
||||
| 200 | Success | **application/json**: [ToolProviderOpaqueResponse](#toolprovideropaqueresponse)<br> |
|
||||
| 200 | MCP provider tools refreshed successfully | **application/json**: [ToolProviderApiEntityResponse](#toolproviderapientityresponse)<br> |
|
||||
|
||||
### [POST] /workspaces/current/tool-provider/workflow/create
|
||||
#### Request Body
|
||||
@ -12070,7 +12070,7 @@ Returns permission flags that control workspace features like member invitations
|
||||
|
||||
| Code | Description | Schema |
|
||||
| ---- | ----------- | ------ |
|
||||
| 200 | Success | **application/json**: [ToolProviderOpaqueResponse](#toolprovideropaqueresponse)<br> |
|
||||
| 200 | Workflow tool created successfully | **application/json**: [SimpleResultResponse](#simpleresultresponse)<br> |
|
||||
|
||||
### [POST] /workspaces/current/tool-provider/workflow/delete
|
||||
#### Request Body
|
||||
@ -12083,7 +12083,7 @@ Returns permission flags that control workspace features like member invitations
|
||||
|
||||
| Code | Description | Schema |
|
||||
| ---- | ----------- | ------ |
|
||||
| 200 | Success | **application/json**: [ToolProviderOpaqueResponse](#toolprovideropaqueresponse)<br> |
|
||||
| 200 | Workflow tool deleted successfully | **application/json**: [SimpleResultResponse](#simpleresultresponse)<br> |
|
||||
|
||||
### [GET] /workspaces/current/tool-provider/workflow/get
|
||||
#### Parameters
|
||||
@ -12097,7 +12097,7 @@ Returns permission flags that control workspace features like member invitations
|
||||
|
||||
| Code | Description | Schema |
|
||||
| ---- | ----------- | ------ |
|
||||
| 200 | Success | **application/json**: [ToolProviderOpaqueResponse](#toolprovideropaqueresponse)<br> |
|
||||
| 200 | Workflow tool retrieved successfully | **application/json**: [WorkflowToolDetailResponse](#workflowtooldetailresponse)<br> |
|
||||
|
||||
### [GET] /workspaces/current/tool-provider/workflow/tools
|
||||
#### Parameters
|
||||
@ -12110,7 +12110,7 @@ Returns permission flags that control workspace features like member invitations
|
||||
|
||||
| Code | Description | Schema |
|
||||
| ---- | ----------- | ------ |
|
||||
| 200 | Success | **application/json**: [ToolProviderOpaqueResponse](#toolprovideropaqueresponse)<br> |
|
||||
| 200 | Workflow provider tools retrieved successfully | **application/json**: [ToolApiListResponse](#toolapilistresponse)<br> |
|
||||
|
||||
### [POST] /workspaces/current/tool-provider/workflow/update
|
||||
#### Request Body
|
||||
@ -12123,7 +12123,7 @@ Returns permission flags that control workspace features like member invitations
|
||||
|
||||
| Code | Description | Schema |
|
||||
| ---- | ----------- | ------ |
|
||||
| 200 | Success | **application/json**: [ToolProviderOpaqueResponse](#toolprovideropaqueresponse)<br> |
|
||||
| 200 | Workflow tool updated successfully | **application/json**: [SimpleResultResponse](#simpleresultresponse)<br> |
|
||||
|
||||
### [GET] /workspaces/current/tool-providers
|
||||
#### Parameters
|
||||
@ -12136,35 +12136,35 @@ Returns permission flags that control workspace features like member invitations
|
||||
|
||||
| Code | Description | Schema |
|
||||
| ---- | ----------- | ------ |
|
||||
| 200 | Success | **application/json**: [ToolProviderOpaqueResponse](#toolprovideropaqueresponse)<br> |
|
||||
| 200 | Tool providers retrieved successfully | **application/json**: [ToolProviderListResponse](#toolproviderlistresponse)<br> |
|
||||
|
||||
### [GET] /workspaces/current/tools/api
|
||||
#### Responses
|
||||
|
||||
| Code | Description | Schema |
|
||||
| ---- | ----------- | ------ |
|
||||
| 200 | Success | **application/json**: [ToolProviderOpaqueResponse](#toolprovideropaqueresponse)<br> |
|
||||
| 200 | API tools retrieved successfully | **application/json**: [ToolProviderListResponse](#toolproviderlistresponse)<br> |
|
||||
|
||||
### [GET] /workspaces/current/tools/builtin
|
||||
#### Responses
|
||||
|
||||
| Code | Description | Schema |
|
||||
| ---- | ----------- | ------ |
|
||||
| 200 | Success | **application/json**: [ToolProviderOpaqueResponse](#toolprovideropaqueresponse)<br> |
|
||||
| 200 | Builtin tools retrieved successfully | **application/json**: [ToolProviderListResponse](#toolproviderlistresponse)<br> |
|
||||
|
||||
### [GET] /workspaces/current/tools/mcp
|
||||
#### Responses
|
||||
|
||||
| Code | Description | Schema |
|
||||
| ---- | ----------- | ------ |
|
||||
| 200 | Success | **application/json**: [ToolProviderOpaqueResponse](#toolprovideropaqueresponse)<br> |
|
||||
| 200 | MCP tools retrieved successfully | **application/json**: [ToolProviderListResponse](#toolproviderlistresponse)<br> |
|
||||
|
||||
### [GET] /workspaces/current/tools/workflow
|
||||
#### Responses
|
||||
|
||||
| Code | Description | Schema |
|
||||
| ---- | ----------- | ------ |
|
||||
| 200 | Success | **application/json**: [ToolProviderOpaqueResponse](#toolprovideropaqueresponse)<br> |
|
||||
| 200 | Workflow tools retrieved successfully | **application/json**: [ToolProviderListResponse](#toolproviderlistresponse)<br> |
|
||||
|
||||
### [GET] /workspaces/current/trigger-provider/{provider}/icon
|
||||
#### Parameters
|
||||
@ -12175,9 +12175,9 @@ Returns permission flags that control workspace features like member invitations
|
||||
|
||||
#### Responses
|
||||
|
||||
| Code | Description | Schema |
|
||||
| ---- | ----------- | ------ |
|
||||
| 200 | Success | **application/json**: [BinaryFileResponse](#binaryfileresponse)<br> |
|
||||
| Code | Description |
|
||||
| ---- | ----------- |
|
||||
| 200 | Trigger provider icon |
|
||||
|
||||
### [GET] /workspaces/current/trigger-provider/{provider}/info
|
||||
**Get info for a trigger provider**
|
||||
@ -12192,7 +12192,7 @@ Returns permission flags that control workspace features like member invitations
|
||||
|
||||
| Code | Description | Schema |
|
||||
| ---- | ----------- | ------ |
|
||||
| 200 | Success | **application/json**: [TriggerProviderApiEntity](#triggerproviderapientity)<br> |
|
||||
| 200 | Trigger provider retrieved successfully | **application/json**: [TriggerProviderApiEntity](#triggerproviderapientity)<br> |
|
||||
|
||||
### [DELETE] /workspaces/current/trigger-provider/{provider}/oauth/client
|
||||
**Remove custom OAuth client configuration**
|
||||
@ -12207,7 +12207,7 @@ Returns permission flags that control workspace features like member invitations
|
||||
|
||||
| Code | Description | Schema |
|
||||
| ---- | ----------- | ------ |
|
||||
| 200 | Success | **application/json**: [SimpleResultResponse](#simpleresultresponse)<br> |
|
||||
| 200 | Trigger OAuth client deleted successfully | **application/json**: [SimpleResultResponse](#simpleresultresponse)<br> |
|
||||
|
||||
### [GET] /workspaces/current/trigger-provider/{provider}/oauth/client
|
||||
**Get OAuth client configuration for a provider**
|
||||
@ -12222,7 +12222,7 @@ Returns permission flags that control workspace features like member invitations
|
||||
|
||||
| Code | Description | Schema |
|
||||
| ---- | ----------- | ------ |
|
||||
| 200 | Success | **application/json**: [TriggerOAuthClientResponse](#triggeroauthclientresponse)<br> |
|
||||
| 200 | Trigger OAuth client retrieved successfully | **application/json**: [TriggerOAuthClientResponse](#triggeroauthclientresponse)<br> |
|
||||
|
||||
### [POST] /workspaces/current/trigger-provider/{provider}/oauth/client
|
||||
**Configure custom OAuth client for a provider**
|
||||
@ -12243,7 +12243,7 @@ Returns permission flags that control workspace features like member invitations
|
||||
|
||||
| Code | Description | Schema |
|
||||
| ---- | ----------- | ------ |
|
||||
| 200 | Success | **application/json**: [SimpleResultResponse](#simpleresultresponse)<br> |
|
||||
| 200 | Trigger OAuth client saved successfully | **application/json**: [SimpleResultResponse](#simpleresultresponse)<br> |
|
||||
|
||||
### [POST] /workspaces/current/trigger-provider/{provider}/subscriptions/builder/build/{subscription_builder_id}
|
||||
**Build a subscription instance for a trigger provider**
|
||||
@ -12265,7 +12265,7 @@ Returns permission flags that control workspace features like member invitations
|
||||
|
||||
| Code | Description | Schema |
|
||||
| ---- | ----------- | ------ |
|
||||
| 200 | Success | **application/json**: [TriggerProviderOpaqueResponse](#triggerprovideropaqueresponse)<br> |
|
||||
| 200 | Trigger subscription builder built successfully | **application/json**: [SimpleResultResponse](#simpleresultresponse)<br> |
|
||||
|
||||
### [POST] /workspaces/current/trigger-provider/{provider}/subscriptions/builder/create
|
||||
**Add a new subscription instance for a trigger provider**
|
||||
@ -12286,7 +12286,7 @@ Returns permission flags that control workspace features like member invitations
|
||||
|
||||
| Code | Description | Schema |
|
||||
| ---- | ----------- | ------ |
|
||||
| 200 | Success | **application/json**: [TriggerSubscriptionBuilderCreateResponse](#triggersubscriptionbuildercreateresponse)<br> |
|
||||
| 200 | Trigger subscription builder created successfully | **application/json**: [TriggerSubscriptionBuilderCreateResponse](#triggersubscriptionbuildercreateresponse)<br> |
|
||||
|
||||
### [GET] /workspaces/current/trigger-provider/{provider}/subscriptions/builder/logs/{subscription_builder_id}
|
||||
**Get the request logs for a subscription instance for a trigger provider**
|
||||
@ -12302,7 +12302,7 @@ Returns permission flags that control workspace features like member invitations
|
||||
|
||||
| Code | Description | Schema |
|
||||
| ---- | ----------- | ------ |
|
||||
| 200 | Success | **application/json**: [TriggerSubscriptionBuilderLogsResponse](#triggersubscriptionbuilderlogsresponse)<br> |
|
||||
| 200 | Trigger subscription builder logs retrieved successfully | **application/json**: [TriggerSubscriptionBuilderLogsResponse](#triggersubscriptionbuilderlogsresponse)<br> |
|
||||
|
||||
### [POST] /workspaces/current/trigger-provider/{provider}/subscriptions/builder/update/{subscription_builder_id}
|
||||
**Update a subscription instance for a trigger provider**
|
||||
@ -12324,7 +12324,7 @@ Returns permission flags that control workspace features like member invitations
|
||||
|
||||
| Code | Description | Schema |
|
||||
| ---- | ----------- | ------ |
|
||||
| 200 | Success | **application/json**: [SubscriptionBuilderApiEntity](#subscriptionbuilderapientity)<br> |
|
||||
| 200 | Trigger subscription builder updated successfully | **application/json**: [SubscriptionBuilderApiEntity](#subscriptionbuilderapientity)<br> |
|
||||
|
||||
### [POST] /workspaces/current/trigger-provider/{provider}/subscriptions/builder/verify-and-update/{subscription_builder_id}
|
||||
**Verify and update a subscription instance for a trigger provider**
|
||||
@ -12346,7 +12346,7 @@ Returns permission flags that control workspace features like member invitations
|
||||
|
||||
| Code | Description | Schema |
|
||||
| ---- | ----------- | ------ |
|
||||
| 200 | Success | **application/json**: [TriggerSubscriptionBuilderVerifyResponse](#triggersubscriptionbuilderverifyresponse)<br> |
|
||||
| 200 | Trigger subscription builder verified successfully | **application/json**: [TriggerVerificationResponse](#triggerverificationresponse)<br> |
|
||||
|
||||
### [GET] /workspaces/current/trigger-provider/{provider}/subscriptions/builder/{subscription_builder_id}
|
||||
**Get a subscription instance for a trigger provider**
|
||||
@ -12362,7 +12362,7 @@ Returns permission flags that control workspace features like member invitations
|
||||
|
||||
| Code | Description | Schema |
|
||||
| ---- | ----------- | ------ |
|
||||
| 200 | Success | **application/json**: [SubscriptionBuilderApiEntity](#subscriptionbuilderapientity)<br> |
|
||||
| 200 | Trigger subscription builder retrieved successfully | **application/json**: [SubscriptionBuilderApiEntity](#subscriptionbuilderapientity)<br> |
|
||||
|
||||
### [GET] /workspaces/current/trigger-provider/{provider}/subscriptions/list
|
||||
**List all trigger subscriptions for the current tenant's provider**
|
||||
@ -12377,7 +12377,8 @@ Returns permission flags that control workspace features like member invitations
|
||||
|
||||
| Code | Description | Schema |
|
||||
| ---- | ----------- | ------ |
|
||||
| 200 | Success | **application/json**: [TriggerSubscriptionListResponse](#triggersubscriptionlistresponse)<br> |
|
||||
| 200 | Trigger subscriptions retrieved successfully | **application/json**: [TriggerProviderSubscriptionListResponse](#triggerprovidersubscriptionlistresponse)<br> |
|
||||
| 404 | Trigger provider not found | **application/json**: [TriggerProviderErrorResponse](#triggerprovidererrorresponse)<br> |
|
||||
|
||||
### [GET] /workspaces/current/trigger-provider/{provider}/subscriptions/oauth/authorize
|
||||
**Initiate OAuth authorization flow for a trigger provider**
|
||||
@ -12392,7 +12393,7 @@ Returns permission flags that control workspace features like member invitations
|
||||
|
||||
| Code | Description | Schema |
|
||||
| ---- | ----------- | ------ |
|
||||
| 200 | Authorization URL retrieved successfully | **application/json**: [TriggerOAuthAuthorizeResponse](#triggeroauthauthorizeresponse)<br> |
|
||||
| 200 | Trigger OAuth authorization URL generated successfully | **application/json**: [TriggerOAuthAuthorizeResponse](#triggeroauthauthorizeresponse)<br> |
|
||||
|
||||
### [POST] /workspaces/current/trigger-provider/{provider}/subscriptions/verify/{subscription_id}
|
||||
**Verify credentials for an existing subscription (edit mode only)**
|
||||
@ -12414,7 +12415,7 @@ Returns permission flags that control workspace features like member invitations
|
||||
|
||||
| Code | Description | Schema |
|
||||
| ---- | ----------- | ------ |
|
||||
| 200 | Success | **application/json**: [TriggerSubscriptionBuilderVerifyResponse](#triggersubscriptionbuilderverifyresponse)<br> |
|
||||
| 200 | Trigger subscription verified successfully | **application/json**: [TriggerVerificationResponse](#triggerverificationresponse)<br> |
|
||||
|
||||
### [POST] /workspaces/current/trigger-provider/{subscription_id}/subscriptions/delete
|
||||
**Delete a subscription instance**
|
||||
@ -12450,7 +12451,7 @@ Returns permission flags that control workspace features like member invitations
|
||||
|
||||
| Code | Description | Schema |
|
||||
| ---- | ----------- | ------ |
|
||||
| 200 | Success | **application/json**: [TriggerProviderOpaqueResponse](#triggerprovideropaqueresponse)<br> |
|
||||
| 200 | Trigger subscription updated successfully | **application/json**: [SimpleResultResponse](#simpleresultresponse)<br> |
|
||||
|
||||
### [GET] /workspaces/current/triggers
|
||||
**List all trigger providers for the current tenant**
|
||||
@ -12459,7 +12460,7 @@ Returns permission flags that control workspace features like member invitations
|
||||
|
||||
| Code | Description | Schema |
|
||||
| ---- | ----------- | ------ |
|
||||
| 200 | Success | **application/json**: [TriggerProviderListResponse](#triggerproviderlistresponse)<br> |
|
||||
| 200 | Trigger providers retrieved successfully | **application/json**: [TriggerProviderListResponse](#triggerproviderlistresponse)<br> |
|
||||
|
||||
### [POST] /workspaces/custom-config
|
||||
#### Request Body
|
||||
@ -14873,6 +14874,26 @@ Legacy Chat App model config used only for follow-up question generation.
|
||||
| ---- | ---- | ----------- | -------- |
|
||||
| data | [ [ApiKeyItem](#apikeyitem) ] | | Yes |
|
||||
|
||||
#### ApiProviderDetailResponse
|
||||
|
||||
| Name | Type | Description | Required |
|
||||
| ---- | ---- | ----------- | -------- |
|
||||
| credentials | object | | No |
|
||||
| custom_disclaimer | string | | No |
|
||||
| description | string | | No |
|
||||
| icon | [ToolEmojiIcon](#toolemojiicon) | | Yes |
|
||||
| labels | [ string ] | | No |
|
||||
| privacy_policy | string | | No |
|
||||
| schema | string | | Yes |
|
||||
| schema_type | [ApiProviderSchemaType](#apiproviderschematype) | | Yes |
|
||||
| tools | [ [ApiToolBundle](#apitoolbundle) ] | | Yes |
|
||||
|
||||
#### ApiProviderRemoteSchemaResponse
|
||||
|
||||
| Name | Type | Description | Required |
|
||||
| ---- | ---- | ----------- | -------- |
|
||||
| schema | string | | Yes |
|
||||
|
||||
#### ApiProviderSchemaType
|
||||
|
||||
Enum class for api provider schema type.
|
||||
@ -14881,13 +14902,52 @@ Enum class for api provider schema type.
|
||||
| ---- | ---- | ----------- | -------- |
|
||||
| ApiProviderSchemaType | string | Enum class for api provider schema type. | |
|
||||
|
||||
#### ApiSchemaParseResponse
|
||||
|
||||
| Name | Type | Description | Required |
|
||||
| ---- | ---- | ----------- | -------- |
|
||||
| credentials_schema | [ [ProviderConfig](#providerconfig) ] | | Yes |
|
||||
| parameters_schema | [ [ApiToolBundle](#apitoolbundle) ] | | Yes |
|
||||
| schema_type | [ApiProviderSchemaType](#apiproviderschematype) | | Yes |
|
||||
| warning | object | | Yes |
|
||||
|
||||
#### ApiToolBundle
|
||||
|
||||
This class is used to store the schema information of an api based tool.
|
||||
such as the url, the method, the parameters, etc.
|
||||
|
||||
| Name | Type | Description | Required |
|
||||
| ---- | ---- | ----------- | -------- |
|
||||
| author | string | | Yes |
|
||||
| icon | string | | No |
|
||||
| method | string | | Yes |
|
||||
| openapi | object | | Yes |
|
||||
| operation_id | string | | No |
|
||||
| output_schema | object | | No |
|
||||
| parameters | [ [ToolParameter](#toolparameter) ] | | No |
|
||||
| server_url | string | | Yes |
|
||||
| summary | string | | No |
|
||||
|
||||
#### ApiToolPreviewResponse
|
||||
|
||||
| Name | Type | Description | Required |
|
||||
| ---- | ---- | ----------- | -------- |
|
||||
| ApiToolPreviewResponse | | | |
|
||||
|
||||
#### ApiToolPreviewResult
|
||||
|
||||
| Name | Type | Description | Required |
|
||||
| ---- | ---- | ----------- | -------- |
|
||||
| error | string | | No |
|
||||
| result | string | | No |
|
||||
|
||||
#### ApiToolProviderAddPayload
|
||||
|
||||
| Name | Type | Description | Required |
|
||||
| ---- | ---- | ----------- | -------- |
|
||||
| credentials | object | | Yes |
|
||||
| custom_disclaimer | string | | No |
|
||||
| icon | object | | Yes |
|
||||
| icon | [ToolEmojiIcon](#toolemojiicon) | | Yes |
|
||||
| labels | [ string ] | | No |
|
||||
| privacy_policy | string | | No |
|
||||
| provider | string | | Yes |
|
||||
@ -14906,7 +14966,7 @@ Enum class for api provider schema type.
|
||||
| ---- | ---- | ----------- | -------- |
|
||||
| credentials | object | | Yes |
|
||||
| custom_disclaimer | string | | No |
|
||||
| icon | object | | Yes |
|
||||
| icon | [ToolEmojiIcon](#toolemojiicon) | | Yes |
|
||||
| labels | [ string ] | | No |
|
||||
| original_provider | string | | Yes |
|
||||
| privacy_policy | string | | No |
|
||||
@ -15382,6 +15442,16 @@ Retrieval settings for Amazon Bedrock knowledge base queries.
|
||||
| ---- | ---- | ----------- | -------- |
|
||||
| id | string | | Yes |
|
||||
|
||||
#### BuiltinProviderOAuthClientSchemaResponse
|
||||
|
||||
| Name | Type | Description | Required |
|
||||
| ---- | ---- | ----------- | -------- |
|
||||
| client_params | object | | No |
|
||||
| is_oauth_custom_client_enabled | boolean | | Yes |
|
||||
| is_system_oauth_params_exists | boolean | | Yes |
|
||||
| redirect_uri | string | | Yes |
|
||||
| schema | [ [ProviderConfig](#providerconfig) ] | | Yes |
|
||||
|
||||
#### BuiltinToolAddPayload
|
||||
|
||||
| Name | Type | Description | Required |
|
||||
@ -18351,6 +18421,20 @@ Enum class for large language model mode.
|
||||
| authorization_code | string | | No |
|
||||
| provider_id | string | | Yes |
|
||||
|
||||
#### MCPAuthResponse
|
||||
|
||||
| Name | Type | Description | Required |
|
||||
| ---- | ---- | ----------- | -------- |
|
||||
| authorization_url | string | | No |
|
||||
| result | string | | No |
|
||||
|
||||
#### MCPAuthentication
|
||||
|
||||
| Name | Type | Description | Required |
|
||||
| ---- | ---- | ----------- | -------- |
|
||||
| client_id | string | | Yes |
|
||||
| client_secret | string | | No |
|
||||
|
||||
#### MCPCallbackQuery
|
||||
|
||||
| Name | Type | Description | Required |
|
||||
@ -18358,12 +18442,19 @@ Enum class for large language model mode.
|
||||
| code | string | | Yes |
|
||||
| state | string | | Yes |
|
||||
|
||||
#### MCPConfiguration
|
||||
|
||||
| Name | Type | Description | Required |
|
||||
| ---- | ---- | ----------- | -------- |
|
||||
| sse_read_timeout | number, <br>**Default:** 300 | | No |
|
||||
| timeout | number, <br>**Default:** 30 | | No |
|
||||
|
||||
#### MCPProviderCreatePayload
|
||||
|
||||
| Name | Type | Description | Required |
|
||||
| ---- | ---- | ----------- | -------- |
|
||||
| authentication | object | | No |
|
||||
| configuration | object | | No |
|
||||
| authentication | [MCPAuthentication](#mcpauthentication) | | No |
|
||||
| configuration | [MCPConfiguration](#mcpconfiguration) | | No |
|
||||
| headers | object | | No |
|
||||
| icon | string | | Yes |
|
||||
| icon_background | string | | No |
|
||||
@ -18383,8 +18474,8 @@ Enum class for large language model mode.
|
||||
|
||||
| Name | Type | Description | Required |
|
||||
| ---- | ---- | ----------- | -------- |
|
||||
| authentication | object | | No |
|
||||
| configuration | object | | No |
|
||||
| authentication | [MCPAuthentication](#mcpauthentication) | | No |
|
||||
| configuration | [MCPConfiguration](#mcpconfiguration) | | No |
|
||||
| headers | object | | No |
|
||||
| icon | string | | Yes |
|
||||
| icon_background | string | | No |
|
||||
@ -19946,6 +20037,12 @@ Model class for common provider settings like credentials
|
||||
| type | [ProviderConfigType](#providerconfigtype) | The type of the credentials | Yes |
|
||||
| url | string | | No |
|
||||
|
||||
#### ProviderConfigListResponse
|
||||
|
||||
| Name | Type | Description | Required |
|
||||
| ---- | ---- | ----------- | -------- |
|
||||
| ProviderConfigListResponse | array | | |
|
||||
|
||||
#### ProviderConfigType
|
||||
|
||||
| Name | Type | Description | Required |
|
||||
@ -20585,11 +20682,19 @@ Whitelist scopes accepted by RBAC app and dataset access config APIs.
|
||||
| last_id | string | | No |
|
||||
| limit | integer, <br>**Default:** 20 | | No |
|
||||
|
||||
#### SchemaDefinitionItemResponse
|
||||
|
||||
| Name | Type | Description | Required |
|
||||
| ---- | ---- | ----------- | -------- |
|
||||
| label | string | | Yes |
|
||||
| name | string | | Yes |
|
||||
| schema | object | | Yes |
|
||||
|
||||
#### SchemaDefinitionsResponse
|
||||
|
||||
| Name | Type | Description | Required |
|
||||
| ---- | ---- | ----------- | -------- |
|
||||
| SchemaDefinitionsResponse | | | |
|
||||
| SchemaDefinitionsResponse | array | | |
|
||||
|
||||
#### SegmentAttachmentResponse
|
||||
|
||||
@ -21456,11 +21561,46 @@ Available voices
|
||||
| ---- | ---- | ----------- | -------- |
|
||||
| data | [ [TokensPerSecondStatisticItem](#tokenspersecondstatisticitem) ] | | Yes |
|
||||
|
||||
#### ToolOAuthClientSchemaResponse
|
||||
#### ToolApiEntity
|
||||
|
||||
| Name | Type | Description | Required |
|
||||
| ---- | ---- | ----------- | -------- |
|
||||
| ToolOAuthClientSchemaResponse | array | | |
|
||||
| author | string | | Yes |
|
||||
| description | [I18nObject](#i18nobject) | | Yes |
|
||||
| label | [I18nObject](#i18nobject) | | Yes |
|
||||
| labels | [ string ] | | No |
|
||||
| name | string | | Yes |
|
||||
| output_schema | object | | No |
|
||||
| parameters | [ [ToolParameter](#toolparameter) ] | | No |
|
||||
|
||||
#### ToolApiListResponse
|
||||
|
||||
| Name | Type | Description | Required |
|
||||
| ---- | ---- | ----------- | -------- |
|
||||
| ToolApiListResponse | array | | |
|
||||
|
||||
#### ToolEmojiIcon
|
||||
|
||||
| Name | Type | Description | Required |
|
||||
| ---- | ---- | ----------- | -------- |
|
||||
| background | string | | Yes |
|
||||
| content | string | | Yes |
|
||||
|
||||
#### ToolLabel
|
||||
|
||||
Tool label
|
||||
|
||||
| Name | Type | Description | Required |
|
||||
| ---- | ---- | ----------- | -------- |
|
||||
| icon | string | The icon of the tool | Yes |
|
||||
| label | [I18nObject](#i18nobject) | The label of the tool | Yes |
|
||||
| name | string | The name of the tool | Yes |
|
||||
|
||||
#### ToolLabelListResponse
|
||||
|
||||
| Name | Type | Description | Required |
|
||||
| ---- | ---- | ----------- | -------- |
|
||||
| ToolLabelListResponse | array | | |
|
||||
|
||||
#### ToolOAuthCustomClientPayload
|
||||
|
||||
@ -21469,11 +21609,29 @@ Available voices
|
||||
| client_params | object | | No |
|
||||
| enable_oauth_custom_client | boolean | | No |
|
||||
|
||||
#### ToolOAuthCustomClientResponse
|
||||
#### ToolParameter
|
||||
|
||||
Overrides type
|
||||
|
||||
| Name | Type | Description | Required |
|
||||
| ---- | ---- | ----------- | -------- |
|
||||
| ToolOAuthCustomClientResponse | object | | |
|
||||
| auto_generate | [PluginParameterAutoGenerate](#pluginparameterautogenerate) | | No |
|
||||
| default | number<br>integer<br>string<br>boolean<br>[ object ]<br>object | | No |
|
||||
| form | [ToolParameterForm](#toolparameterform) | The form of the parameter, schema/form/llm | Yes |
|
||||
| human_description | [I18nObject](#i18nobject) | The description presented to the user | No |
|
||||
| input_schema | object | | No |
|
||||
| label | [I18nObject](#i18nobject) | The label presented to the user | Yes |
|
||||
| llm_description | string | | No |
|
||||
| max | number<br>integer | | No |
|
||||
| min | number<br>integer | | No |
|
||||
| name | string | The name of the parameter | Yes |
|
||||
| options | [ [PluginParameterOption](#pluginparameteroption) ] | | No |
|
||||
| placeholder | [I18nObject](#i18nobject) | The placeholder presented to the user | No |
|
||||
| precision | integer | | No |
|
||||
| required | boolean | | No |
|
||||
| scope | string | | No |
|
||||
| template | [PluginParameterTemplate](#pluginparametertemplate) | | No |
|
||||
| type | [ToolParameterType](#toolparametertype) | The type of the parameter | Yes |
|
||||
|
||||
#### ToolParameterForm
|
||||
|
||||
@ -21481,17 +21639,84 @@ Available voices
|
||||
| ---- | ---- | ----------- | -------- |
|
||||
| ToolParameterForm | string | | |
|
||||
|
||||
#### ToolParameterType
|
||||
|
||||
removes TOOLS_SELECTOR from PluginParameterType
|
||||
|
||||
| Name | Type | Description | Required |
|
||||
| ---- | ---- | ----------- | -------- |
|
||||
| ToolParameterType | string | removes TOOLS_SELECTOR from PluginParameterType | |
|
||||
|
||||
#### ToolProviderApiEntityResponse
|
||||
|
||||
| Name | Type | Description | Required |
|
||||
| ---- | ---- | ----------- | -------- |
|
||||
| allow_delete | boolean, <br>**Default:** true | | No |
|
||||
| authentication | [MCPAuthentication](#mcpauthentication) | The OAuth config of the MCP tool | No |
|
||||
| author | string | | Yes |
|
||||
| configuration | [MCPConfiguration](#mcpconfiguration) | The timeout and sse_read_timeout of the MCP tool | No |
|
||||
| description | [I18nObject](#i18nobject) | | Yes |
|
||||
| icon | string<br>object | | Yes |
|
||||
| icon_dark | string<br>object | | No |
|
||||
| id | string | | Yes |
|
||||
| identity_mode | string, <br>**Default:** off | Identity-forwarding mechanism: 'off' or 'idp_token' | No |
|
||||
| is_dynamic_registration | boolean, <br>**Default:** true | Whether the MCP tool is dynamically registered | No |
|
||||
| is_team_authorization | boolean | | No |
|
||||
| label | [I18nObject](#i18nobject) | | Yes |
|
||||
| labels | [ string ] | | No |
|
||||
| masked_headers | object | The masked headers of the MCP tool | No |
|
||||
| name | string | | Yes |
|
||||
| original_headers | object | The original headers of the MCP tool | No |
|
||||
| plugin_id | string | The plugin id of the tool | No |
|
||||
| plugin_unique_identifier | string | The unique identifier of the tool | No |
|
||||
| server_identifier | string | The server identifier of the MCP tool | No |
|
||||
| server_url | string | The server url of the tool | No |
|
||||
| team_credentials | object | | No |
|
||||
| tools | [ [ToolApiEntity](#toolapientity) ] | | No |
|
||||
| type | [ToolProviderType](#toolprovidertype) | | Yes |
|
||||
| updated_at | integer | | No |
|
||||
| workflow_app_id | string | The app id of the workflow tool | No |
|
||||
|
||||
#### ToolProviderCredentialApiEntity
|
||||
|
||||
| Name | Type | Description | Required |
|
||||
| ---- | ---- | ----------- | -------- |
|
||||
| created_by | string | User ID of the credential creator | No |
|
||||
| credential_type | [CredentialType](#credentialtype) | The type of the credential | Yes |
|
||||
| credentials | object | The credentials of the provider | No |
|
||||
| from_other_member | boolean | True when this credential is being returned only because a workflow/agent node still references it but it would normally be hidden from this user by the visibility filter (another member's only_me credential). The frontend renders it as 'borrowed' — selectable until the node switches away, but not editable/deletable. | No |
|
||||
| id | string | The unique id of the credential | Yes |
|
||||
| is_default | boolean | Whether the credential is the default credential for the provider in the workspace | No |
|
||||
| name | string | The name of the credential | Yes |
|
||||
| partial_member_list | [ string ] | List of user IDs allowed when visibility is partial_members | No |
|
||||
| provider | string | The provider of the credential | Yes |
|
||||
| visibility | string, <br>**Default:** all_team_members | Credential visibility: only_me, all_team_members, or partial_members | No |
|
||||
|
||||
#### ToolProviderCredentialInfoApiEntity
|
||||
|
||||
| Name | Type | Description | Required |
|
||||
| ---- | ---- | ----------- | -------- |
|
||||
| credentials | [ [ToolProviderCredentialApiEntity](#toolprovidercredentialapientity) ] | The credentials of the provider | Yes |
|
||||
| is_oauth_custom_client_enabled | boolean | Whether the OAuth custom client is enabled for the provider | No |
|
||||
| supported_credential_types | [ [CredentialType](#credentialtype) ] | The supported credential types of the provider | Yes |
|
||||
|
||||
#### ToolProviderCredentialListResponse
|
||||
|
||||
| Name | Type | Description | Required |
|
||||
| ---- | ---- | ----------- | -------- |
|
||||
| ToolProviderCredentialListResponse | array | | |
|
||||
|
||||
#### ToolProviderListQuery
|
||||
|
||||
| Name | Type | Description | Required |
|
||||
| ---- | ---- | ----------- | -------- |
|
||||
| type | string | | No |
|
||||
|
||||
#### ToolProviderOpaqueResponse
|
||||
#### ToolProviderListResponse
|
||||
|
||||
| Name | Type | Description | Required |
|
||||
| ---- | ---- | ----------- | -------- |
|
||||
| ToolProviderOpaqueResponse | | | |
|
||||
| ToolProviderListResponse | array | | |
|
||||
|
||||
#### ToolProviderType
|
||||
|
||||
@ -21772,7 +21997,7 @@ Enum class for tool provider
|
||||
| configured | boolean | | Yes |
|
||||
| custom_configured | boolean | | Yes |
|
||||
| custom_enabled | boolean | | Yes |
|
||||
| oauth_client_schema | [ [TriggerProviderConfigResponse](#triggerproviderconfigresponse) ] | | Yes |
|
||||
| oauth_client_schema | [ [ProviderConfig](#providerconfig) ] | | Yes |
|
||||
| params | object | | Yes |
|
||||
| redirect_uri | string | | Yes |
|
||||
| system_configured | boolean | | Yes |
|
||||
@ -21795,28 +22020,11 @@ Enum class for tool provider
|
||||
| supported_creation_methods | [ [TriggerCreationMethod](#triggercreationmethod) ] | Supported creation methods for the trigger provider. like 'OAUTH', 'APIKEY', 'MANUAL'. | No |
|
||||
| tags | [ string ] | The tags of the trigger provider | No |
|
||||
|
||||
#### TriggerProviderConfigOptionResponse
|
||||
#### TriggerProviderErrorResponse
|
||||
|
||||
| Name | Type | Description | Required |
|
||||
| ---- | ---- | ----------- | -------- |
|
||||
| label | [I18nObject](#i18nobject) | The label of the option | Yes |
|
||||
| value | string | The value of the option | Yes |
|
||||
|
||||
#### TriggerProviderConfigResponse
|
||||
|
||||
| Name | Type | Description | Required |
|
||||
| ---- | ---- | ----------- | -------- |
|
||||
| default | integer<br>string<br>number<br>boolean | | No |
|
||||
| help | [I18nObject](#i18nobject) | | No |
|
||||
| label | [I18nObject](#i18nobject) | | No |
|
||||
| multiple | boolean | | No |
|
||||
| name | string | The name of the credentials | Yes |
|
||||
| options | [ [TriggerProviderConfigOptionResponse](#triggerproviderconfigoptionresponse) ] | | No |
|
||||
| placeholder | [I18nObject](#i18nobject) | | No |
|
||||
| required | boolean | | No |
|
||||
| scope | [AppSelectorScope](#appselectorscope)<br>[ModelSelectorScope](#modelselectorscope)<br>[ToolSelectorScope](#toolselectorscope) | | No |
|
||||
| type | string, <br>**Available values:** "app-selector", "array[tools]", "boolean", "model-selector", "secret-input", "select", "text-input" | The type of the credentials<br>*Enum:* `"app-selector"`, `"array[tools]"`, `"boolean"`, `"model-selector"`, `"secret-input"`, `"select"`, `"text-input"` | Yes |
|
||||
| url | string | | No |
|
||||
| error | string | | Yes |
|
||||
|
||||
#### TriggerProviderListResponse
|
||||
|
||||
@ -21824,12 +22032,6 @@ Enum class for tool provider
|
||||
| ---- | ---- | ----------- | -------- |
|
||||
| TriggerProviderListResponse | array | | |
|
||||
|
||||
#### TriggerProviderOpaqueResponse
|
||||
|
||||
| Name | Type | Description | Required |
|
||||
| ---- | ---- | ----------- | -------- |
|
||||
| TriggerProviderOpaqueResponse | | | |
|
||||
|
||||
#### TriggerProviderSubscriptionApiEntity
|
||||
|
||||
| Name | Type | Description | Required |
|
||||
@ -21844,6 +22046,12 @@ Enum class for tool provider
|
||||
| provider | string | The provider id of the subscription | Yes |
|
||||
| workflows_in_use | integer | The number of workflows using this subscription | Yes |
|
||||
|
||||
#### TriggerProviderSubscriptionListResponse
|
||||
|
||||
| Name | Type | Description | Required |
|
||||
| ---- | ---- | ----------- | -------- |
|
||||
| TriggerProviderSubscriptionListResponse | array | | |
|
||||
|
||||
#### TriggerSubscriptionBuilderCreatePayload
|
||||
|
||||
| Name | Type | Description | Required |
|
||||
@ -21877,18 +22085,12 @@ Enum class for tool provider
|
||||
| ---- | ---- | ----------- | -------- |
|
||||
| credentials | object | | Yes |
|
||||
|
||||
#### TriggerSubscriptionBuilderVerifyResponse
|
||||
#### TriggerVerificationResponse
|
||||
|
||||
| Name | Type | Description | Required |
|
||||
| ---- | ---- | ----------- | -------- |
|
||||
| verified | boolean | | Yes |
|
||||
|
||||
#### TriggerSubscriptionListResponse
|
||||
|
||||
| Name | Type | Description | Required |
|
||||
| ---- | ---- | ----------- | -------- |
|
||||
| TriggerSubscriptionListResponse | array | | |
|
||||
|
||||
#### UnaddedModelConfiguration
|
||||
|
||||
Model class for provider unadded model configuration.
|
||||
@ -22939,7 +23141,7 @@ Query parameters for workflow runs.
|
||||
| Name | Type | Description | Required |
|
||||
| ---- | ---- | ----------- | -------- |
|
||||
| description | string | | Yes |
|
||||
| icon | object | | Yes |
|
||||
| icon | [ToolEmojiIcon](#toolemojiicon) | | Yes |
|
||||
| label | string | | Yes |
|
||||
| labels | [ string ] | | No |
|
||||
| name | string | | Yes |
|
||||
@ -22953,6 +23155,22 @@ Query parameters for workflow runs.
|
||||
| ---- | ---- | ----------- | -------- |
|
||||
| workflow_tool_id | string | | Yes |
|
||||
|
||||
#### WorkflowToolDetailResponse
|
||||
|
||||
| Name | Type | Description | Required |
|
||||
| ---- | ---- | ----------- | -------- |
|
||||
| description | string | | Yes |
|
||||
| icon | [ToolEmojiIcon](#toolemojiicon) | | Yes |
|
||||
| label | string | | Yes |
|
||||
| name | string | | Yes |
|
||||
| output_schema | object | | No |
|
||||
| parameters | [ [WorkflowToolParameterConfiguration](#workflowtoolparameterconfiguration) ] | | Yes |
|
||||
| privacy_policy | string | | No |
|
||||
| synced | boolean | | Yes |
|
||||
| tool | [ToolApiEntity](#toolapientity) | | Yes |
|
||||
| workflow_app_id | string | | Yes |
|
||||
| workflow_tool_id | string | | Yes |
|
||||
|
||||
#### WorkflowToolGetQuery
|
||||
|
||||
| Name | Type | Description | Required |
|
||||
@ -22981,7 +23199,7 @@ Workflow tool configuration
|
||||
| Name | Type | Description | Required |
|
||||
| ---- | ---- | ----------- | -------- |
|
||||
| description | string | | Yes |
|
||||
| icon | object | | Yes |
|
||||
| icon | [ToolEmojiIcon](#toolemojiicon) | | Yes |
|
||||
| label | string | | Yes |
|
||||
| labels | [ string ] | | No |
|
||||
| name | string | | Yes |
|
||||
|
||||
@ -1424,6 +1424,7 @@ class SummaryIndexService:
|
||||
- generating: Number of summaries being generated
|
||||
- error: Number of summaries with errors
|
||||
- not_started: Number of segments without summary records
|
||||
- timeout: Number of summaries that timed out
|
||||
- summaries: List of summary records with status and content preview
|
||||
"""
|
||||
from services.dataset_service import SegmentService
|
||||
|
||||
@ -1,8 +1,9 @@
|
||||
import json
|
||||
import logging
|
||||
from typing import Any, TypedDict, cast
|
||||
from typing import Any, Literal, TypedDict, cast
|
||||
|
||||
from httpx import get
|
||||
from pydantic import TypeAdapter
|
||||
from sqlalchemy import select
|
||||
from sqlalchemy.orm import sessionmaker
|
||||
|
||||
@ -22,7 +23,6 @@ from core.tools.tool_manager import ToolManager
|
||||
from core.tools.utils.encryption import create_tool_provider_encrypter
|
||||
from core.tools.utils.parser import ApiBasedToolSchemaParser
|
||||
from extensions.ext_database import db
|
||||
from graphon.model_runtime.utils.encoders import jsonable_encoder
|
||||
from models.tools import ApiToolProvider
|
||||
from services.tools.tools_transform_service import ToolTransformService
|
||||
|
||||
@ -36,6 +36,27 @@ class ApiSchemaParseResult(TypedDict):
|
||||
warning: dict[str, str]
|
||||
|
||||
|
||||
class ApiToolPreviewResult(TypedDict, total=False):
|
||||
result: str
|
||||
error: str
|
||||
|
||||
|
||||
class RemoteSchemaResult(TypedDict):
|
||||
schema: str
|
||||
|
||||
|
||||
class SimpleSuccessResult(TypedDict):
|
||||
result: Literal["success"]
|
||||
|
||||
|
||||
def _dump_api_tool_bundles(tool_bundles: list[ApiToolBundle]) -> list[dict[str, Any]]:
|
||||
return cast(list[dict[str, Any]], TypeAdapter(list[ApiToolBundle]).dump_python(tool_bundles, mode="json"))
|
||||
|
||||
|
||||
def _dump_provider_configs(configs: list[ProviderConfig]) -> list[dict[str, Any]]:
|
||||
return cast(list[dict[str, Any]], TypeAdapter(list[ProviderConfig]).dump_python(configs, mode="json"))
|
||||
|
||||
|
||||
class ApiToolManageService:
|
||||
@staticmethod
|
||||
def parser_api_schema(schema: str) -> ApiSchemaParseResult:
|
||||
@ -80,14 +101,12 @@ class ApiToolManageService:
|
||||
|
||||
return cast(
|
||||
ApiSchemaParseResult,
|
||||
jsonable_encoder(
|
||||
{
|
||||
"schema_type": schema_type,
|
||||
"parameters_schema": tool_bundles,
|
||||
"credentials_schema": credentials_schema,
|
||||
"warning": warnings,
|
||||
}
|
||||
),
|
||||
{
|
||||
"schema_type": schema_type.value,
|
||||
"parameters_schema": _dump_api_tool_bundles(tool_bundles),
|
||||
"credentials_schema": _dump_provider_configs(credentials_schema),
|
||||
"warning": warnings,
|
||||
},
|
||||
)
|
||||
except Exception as e:
|
||||
raise ValueError(f"invalid schema: {str(e)}")
|
||||
@ -118,7 +137,7 @@ class ApiToolManageService:
|
||||
privacy_policy: str,
|
||||
custom_disclaimer: str,
|
||||
labels: list[str],
|
||||
) -> dict[str, Any]:
|
||||
) -> SimpleSuccessResult:
|
||||
"""
|
||||
Create a new API tool provider.
|
||||
|
||||
@ -169,7 +188,7 @@ class ApiToolManageService:
|
||||
schema=schema,
|
||||
description=extra_info.get("description", ""),
|
||||
schema_type_str=schema_type,
|
||||
tools_str=json.dumps(jsonable_encoder(tool_bundles)),
|
||||
tools_str=json.dumps(_dump_api_tool_bundles(tool_bundles)),
|
||||
credentials_str="{}",
|
||||
privacy_policy=privacy_policy,
|
||||
custom_disclaimer=custom_disclaimer,
|
||||
@ -201,7 +220,7 @@ class ApiToolManageService:
|
||||
return {"result": "success"}
|
||||
|
||||
@staticmethod
|
||||
def get_api_tool_provider_remote_schema(user_id: str, tenant_id: str, url: str):
|
||||
def get_api_tool_provider_remote_schema(user_id: str, tenant_id: str, url: str) -> RemoteSchemaResult:
|
||||
"""
|
||||
get api tool provider remote schema
|
||||
"""
|
||||
@ -276,7 +295,7 @@ class ApiToolManageService:
|
||||
privacy_policy: str | None,
|
||||
custom_disclaimer: str,
|
||||
labels: list[str],
|
||||
) -> dict[str, Any]:
|
||||
) -> SimpleSuccessResult:
|
||||
"""
|
||||
Update an existing API tool provider.
|
||||
|
||||
@ -322,7 +341,7 @@ class ApiToolManageService:
|
||||
provider.schema = schema
|
||||
provider.description = extra_info.get("description", "")
|
||||
provider.schema_type_str = schema_type
|
||||
provider.tools_str = json.dumps(jsonable_encoder(tool_bundles))
|
||||
provider.tools_str = json.dumps(_dump_api_tool_bundles(tool_bundles))
|
||||
provider.privacy_policy = privacy_policy
|
||||
provider.custom_disclaimer = custom_disclaimer
|
||||
|
||||
@ -365,7 +384,7 @@ class ApiToolManageService:
|
||||
return {"result": "success"}
|
||||
|
||||
@staticmethod
|
||||
def delete_api_tool_provider(user_id: str, tenant_id: str, provider_name: str):
|
||||
def delete_api_tool_provider(user_id: str, tenant_id: str, provider_name: str) -> SimpleSuccessResult:
|
||||
"""
|
||||
Delete an API tool provider.
|
||||
|
||||
@ -413,9 +432,9 @@ class ApiToolManageService:
|
||||
tool_name: str,
|
||||
credentials: dict[str, Any],
|
||||
parameters: dict[str, Any],
|
||||
schema_type: ApiProviderSchemaType,
|
||||
schema_type: ApiProviderSchemaType | str,
|
||||
schema: str,
|
||||
) -> dict[str, Any]:
|
||||
) -> ApiToolPreviewResult:
|
||||
"""
|
||||
Test an API tool before adding the API tool provider.
|
||||
|
||||
@ -464,7 +483,7 @@ class ApiToolManageService:
|
||||
schema=schema,
|
||||
description="",
|
||||
schema_type_str=ApiProviderSchemaType.OPENAPI,
|
||||
tools_str=json.dumps(jsonable_encoder(tool_bundles)),
|
||||
tools_str=json.dumps(_dump_api_tool_bundles(tool_bundles)),
|
||||
credentials_str=json.dumps(credentials),
|
||||
)
|
||||
|
||||
|
||||
@ -44,6 +44,7 @@ from controllers.console.workspace.tool_providers import (
|
||||
ToolWorkflowProviderUpdateApi,
|
||||
is_valid_url,
|
||||
)
|
||||
from core.tools.entities.api_entities import ToolProviderApiEntity as CoreToolProviderApiEntity
|
||||
from models.account import Account, TenantAccountRole
|
||||
from services.tools.mcp_tools_manage_service import ReconnectResult
|
||||
from tests.test_containers_integration_tests.controllers.console.helpers import (
|
||||
@ -60,6 +61,148 @@ def empty_list() -> list[object]:
|
||||
return []
|
||||
|
||||
|
||||
def emoji_icon() -> dict[str, str]:
|
||||
return {"content": "tool", "background": "#252525"}
|
||||
|
||||
|
||||
def i18n(text: str) -> dict[str, str]:
|
||||
return {"en_US": text}
|
||||
|
||||
|
||||
def tool_payload(name: str = "ping") -> dict[str, object]:
|
||||
return {
|
||||
"author": "langgenius",
|
||||
"name": name,
|
||||
"label": i18n(name.title()),
|
||||
"description": i18n(f"{name} description"),
|
||||
"parameters": [],
|
||||
"labels": ["utilities"],
|
||||
"output_schema": {},
|
||||
}
|
||||
|
||||
|
||||
def provider_payload(
|
||||
*,
|
||||
provider_id: str = "provider-1",
|
||||
name: str = "provider",
|
||||
provider_type: str = "builtin",
|
||||
tools: list[dict[str, object]] | None = None,
|
||||
) -> dict[str, object]:
|
||||
return {
|
||||
"id": provider_id,
|
||||
"author": "langgenius",
|
||||
"name": name,
|
||||
"description": i18n(f"{name} description"),
|
||||
"icon": emoji_icon(),
|
||||
"icon_dark": emoji_icon(),
|
||||
"label": i18n(name.title()),
|
||||
"type": provider_type,
|
||||
"masked_credentials": {"api_key": "[__HIDDEN__]"},
|
||||
"original_credentials": {"api_key": "sk-secret"},
|
||||
"is_team_authorization": False,
|
||||
"allow_delete": True,
|
||||
"plugin_id": "langgenius/provider",
|
||||
"plugin_unique_identifier": "langgenius/provider:1.0.0",
|
||||
"tools": tools or [tool_payload()],
|
||||
"labels": ["utilities"],
|
||||
"server_url": "",
|
||||
"updated_at": 1710000000,
|
||||
"server_identifier": "",
|
||||
"masked_headers": None,
|
||||
"original_headers": None,
|
||||
"authentication": None,
|
||||
"is_dynamic_registration": True,
|
||||
"configuration": None,
|
||||
"identity_mode": "off",
|
||||
"workflow_app_id": None,
|
||||
}
|
||||
|
||||
|
||||
def provider_entity(
|
||||
*,
|
||||
provider_id: str = "provider-1",
|
||||
name: str = "provider",
|
||||
provider_type: str = "builtin",
|
||||
tools: list[dict[str, object]] | None = None,
|
||||
) -> CoreToolProviderApiEntity:
|
||||
return CoreToolProviderApiEntity.model_validate(
|
||||
provider_payload(provider_id=provider_id, name=name, provider_type=provider_type, tools=tools)
|
||||
)
|
||||
|
||||
|
||||
def credential_payload() -> dict[str, object]:
|
||||
return {
|
||||
"id": "credential-1",
|
||||
"name": "Default credential",
|
||||
"provider": "provider",
|
||||
"credential_type": "api-key",
|
||||
"is_default": True,
|
||||
"credentials": {"api_key": "masked"},
|
||||
"visibility": "all_team_members",
|
||||
"created_by": "user-1",
|
||||
"partial_member_list": [],
|
||||
"from_other_member": False,
|
||||
}
|
||||
|
||||
|
||||
def provider_config_payload() -> dict[str, object]:
|
||||
return {"type": "secret-input", "name": "api_key", "required": True}
|
||||
|
||||
|
||||
def api_tool_bundle_payload() -> dict[str, object]:
|
||||
return {
|
||||
"server_url": "https://api.example.com",
|
||||
"method": "get",
|
||||
"summary": "Ping",
|
||||
"operation_id": "ping",
|
||||
"parameters": [],
|
||||
"author": "langgenius",
|
||||
"icon": None,
|
||||
"openapi": {"operationId": "ping"},
|
||||
"output_schema": {},
|
||||
}
|
||||
|
||||
|
||||
def api_provider_detail_payload() -> dict[str, object]:
|
||||
return {
|
||||
"schema_type": "openapi",
|
||||
"schema": "{}",
|
||||
"tools": [api_tool_bundle_payload()],
|
||||
"icon": emoji_icon(),
|
||||
"description": "API provider",
|
||||
"credentials": {},
|
||||
"privacy_policy": "",
|
||||
"custom_disclaimer": "",
|
||||
"labels": ["utilities"],
|
||||
}
|
||||
|
||||
|
||||
def credential_info_payload() -> dict[str, object]:
|
||||
return {
|
||||
"supported_credential_types": ["api-key", "oauth2"],
|
||||
"is_oauth_custom_client_enabled": False,
|
||||
"credentials": [credential_payload()],
|
||||
}
|
||||
|
||||
|
||||
def oauth_client_schema_payload() -> dict[str, object]:
|
||||
return {
|
||||
"schema": [provider_config_payload()],
|
||||
"is_oauth_custom_client_enabled": False,
|
||||
"is_system_oauth_params_exists": True,
|
||||
"client_params": {"client_id": "masked"},
|
||||
"redirect_uri": "https://console.example.com/oauth/callback",
|
||||
}
|
||||
|
||||
|
||||
def tool_label_payload() -> dict[str, object]:
|
||||
return {
|
||||
"name": "utilities",
|
||||
"label": i18n("Utilities"),
|
||||
"icon": "wrench",
|
||||
}
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def _mock_cache() -> None:
|
||||
return
|
||||
@ -127,7 +270,7 @@ def test_create_mcp_provider_populates_tools(
|
||||
with (
|
||||
patch(
|
||||
"services.tools.tools_transform_service.ToolTransformService.mcp_provider_to_user_provider",
|
||||
return_value={"id": "provider-1", "tools": [{"name": "ping"}]},
|
||||
return_value=provider_entity(provider_id="provider-1", provider_type="mcp", tools=[tool_payload()]),
|
||||
autospec=True,
|
||||
),
|
||||
):
|
||||
@ -138,13 +281,15 @@ def test_create_mcp_provider_populates_tools(
|
||||
content_type="application/json",
|
||||
)
|
||||
|
||||
# Assert
|
||||
assert resp.status_code == 200
|
||||
body = resp.get_json()
|
||||
assert body.get("id") == "provider-1"
|
||||
# 若 transform 后包含 tools 字段,确保非空
|
||||
assert isinstance(body.get("tools"), list)
|
||||
assert body["tools"]
|
||||
# Assert
|
||||
assert resp.status_code == 200
|
||||
body = resp.get_json()
|
||||
assert body.get("id") == "provider-1"
|
||||
assert body["team_credentials"] == {"api_key": "[__HIDDEN__]"}
|
||||
assert "masked_credentials" not in body
|
||||
assert "original_credentials" not in body
|
||||
assert isinstance(body.get("tools"), list)
|
||||
assert body["tools"]
|
||||
|
||||
|
||||
class TestUtils:
|
||||
@ -170,10 +315,16 @@ class TestToolProviderListApi:
|
||||
app.test_request_context("/"),
|
||||
patch(
|
||||
"controllers.console.workspace.tool_providers.ToolCommonService.list_tool_providers",
|
||||
return_value=["p1"],
|
||||
return_value=[provider_entity(provider_id="p1").to_dict()],
|
||||
),
|
||||
):
|
||||
assert method(api, "t1", make_account(id="u1")) == ["p1"]
|
||||
result = method(api, "t1", make_account(id="u1"))
|
||||
|
||||
assert result[0]["id"] == "p1"
|
||||
assert result[0]["team_credentials"] == {"api_key": "[__HIDDEN__]"}
|
||||
assert "masked_credentials" not in result[0]
|
||||
assert "original_credentials" not in result[0]
|
||||
assert result[0]["tools"][0]["name"] == "ping"
|
||||
|
||||
|
||||
class TestBuiltinProviderApis:
|
||||
@ -189,10 +340,10 @@ class TestBuiltinProviderApis:
|
||||
app.test_request_context("/"),
|
||||
patch(
|
||||
"controllers.console.workspace.tool_providers.BuiltinToolManageService.list_builtin_tool_provider_tools",
|
||||
return_value=[{"a": 1}],
|
||||
return_value=[tool_payload()],
|
||||
),
|
||||
):
|
||||
assert method(api, "t1", "provider") == [{"a": 1}]
|
||||
assert method(api, "t1", "provider")[0]["name"] == "ping"
|
||||
|
||||
def test_info(self, app: Flask) -> None:
|
||||
api = ToolBuiltinProviderInfoApi()
|
||||
@ -202,10 +353,15 @@ class TestBuiltinProviderApis:
|
||||
app.test_request_context("/"),
|
||||
patch(
|
||||
"controllers.console.workspace.tool_providers.BuiltinToolManageService.get_builtin_tool_provider_info",
|
||||
return_value={"x": 1},
|
||||
return_value=provider_entity(),
|
||||
),
|
||||
):
|
||||
assert method(api, "t1", "provider") == {"x": 1}
|
||||
result = method(api, "t1", "provider")
|
||||
|
||||
assert result["id"] == "provider-1"
|
||||
assert result["team_credentials"] == {"api_key": "[__HIDDEN__]"}
|
||||
assert "masked_credentials" not in result
|
||||
assert "original_credentials" not in result
|
||||
|
||||
def test_delete(self, app: Flask) -> None:
|
||||
api = ToolBuiltinProviderDeleteApi()
|
||||
@ -240,10 +396,10 @@ class TestBuiltinProviderApis:
|
||||
app.test_request_context("/", json=payload),
|
||||
patch(
|
||||
"controllers.console.workspace.tool_providers.BuiltinToolManageService.add_builtin_tool_provider",
|
||||
return_value={"id": 1},
|
||||
return_value={"result": "success"},
|
||||
),
|
||||
):
|
||||
assert method(api, "t", make_account(), "provider")["id"] == 1
|
||||
assert method(api, "t", make_account(), "provider")["result"] == "success"
|
||||
|
||||
def test_update(self, app: Flask) -> None:
|
||||
api = ToolBuiltinProviderUpdateApi()
|
||||
@ -255,10 +411,10 @@ class TestBuiltinProviderApis:
|
||||
app.test_request_context("/", json=payload),
|
||||
patch(
|
||||
"controllers.console.workspace.tool_providers.BuiltinToolManageService.update_builtin_tool_provider",
|
||||
return_value={"ok": True},
|
||||
return_value={"result": "success"},
|
||||
),
|
||||
):
|
||||
assert method(api, "t", make_account(), "provider")["ok"]
|
||||
assert method(api, "t", make_account(), "provider")["result"] == "success"
|
||||
|
||||
def test_get_credentials(self, app: Flask) -> None:
|
||||
api = ToolBuiltinProviderGetCredentialsApi()
|
||||
@ -268,10 +424,10 @@ class TestBuiltinProviderApis:
|
||||
app.test_request_context("/"),
|
||||
patch(
|
||||
"controllers.console.workspace.tool_providers.BuiltinToolManageService.get_builtin_tool_provider_credentials",
|
||||
return_value={"k": "v"},
|
||||
return_value=[credential_payload()],
|
||||
),
|
||||
):
|
||||
assert method(api, "t", make_account(id="user-1"), "provider") == {"k": "v"}
|
||||
assert method(api, "t", make_account(id="user-1"), "provider")[0]["id"] == "credential-1"
|
||||
|
||||
def test_icon(self, app: Flask) -> None:
|
||||
api = ToolBuiltinProviderIconApi()
|
||||
@ -295,10 +451,10 @@ class TestBuiltinProviderApis:
|
||||
app.test_request_context("/"),
|
||||
patch(
|
||||
"controllers.console.workspace.tool_providers.BuiltinToolManageService.list_builtin_provider_credentials_schema",
|
||||
return_value={"schema": {}},
|
||||
return_value=[provider_config_payload()],
|
||||
),
|
||||
):
|
||||
assert method(api, "t", "provider", "oauth2") == {"schema": {}}
|
||||
assert method(api, "t", "provider", "oauth2")[0]["name"] == "api_key"
|
||||
|
||||
def test_set_default_credential(self, app: Flask) -> None:
|
||||
api = ToolBuiltinProviderSetDefaultApi()
|
||||
@ -308,10 +464,10 @@ class TestBuiltinProviderApis:
|
||||
app.test_request_context("/", json={"id": "c1"}),
|
||||
patch(
|
||||
"controllers.console.workspace.tool_providers.BuiltinToolManageService.set_default_provider",
|
||||
return_value={"ok": True},
|
||||
return_value={"result": "success"},
|
||||
),
|
||||
):
|
||||
assert method(api, "t", "provider")["ok"]
|
||||
assert method(api, "t", "provider")["result"] == "success"
|
||||
|
||||
def test_get_credential_info(self, app: Flask) -> None:
|
||||
api = ToolBuiltinProviderGetCredentialInfoApi()
|
||||
@ -321,10 +477,10 @@ class TestBuiltinProviderApis:
|
||||
app.test_request_context("/"),
|
||||
patch(
|
||||
"controllers.console.workspace.tool_providers.BuiltinToolManageService.get_builtin_tool_provider_credential_info",
|
||||
return_value={"info": "x"},
|
||||
return_value=credential_info_payload(),
|
||||
),
|
||||
):
|
||||
assert method(api, "t", make_account(), "provider") == {"info": "x"}
|
||||
assert method(api, "t", make_account(), "provider")["credentials"][0]["id"] == "credential-1"
|
||||
|
||||
def test_get_oauth_client_schema(self, app: Flask) -> None:
|
||||
api = ToolBuiltinProviderGetOauthClientSchemaApi()
|
||||
@ -334,10 +490,10 @@ class TestBuiltinProviderApis:
|
||||
app.test_request_context("/"),
|
||||
patch(
|
||||
"controllers.console.workspace.tool_providers.BuiltinToolManageService.get_builtin_tool_provider_oauth_client_schema",
|
||||
return_value={"schema": {}},
|
||||
return_value=oauth_client_schema_payload(),
|
||||
),
|
||||
):
|
||||
assert method(api, "t", "provider") == {"schema": {}}
|
||||
assert method(api, "t", "provider")["schema"][0]["name"] == "api_key"
|
||||
|
||||
|
||||
class TestApiProviderApis:
|
||||
@ -354,30 +510,34 @@ class TestApiProviderApis:
|
||||
"schema_type": "openapi",
|
||||
"schema": "{}",
|
||||
"provider": "p",
|
||||
"icon": empty_mapping(),
|
||||
"icon": emoji_icon(),
|
||||
}
|
||||
|
||||
with (
|
||||
app.test_request_context("/", json=payload),
|
||||
patch(
|
||||
"controllers.console.workspace.tool_providers.ApiToolManageService.create_api_tool_provider",
|
||||
return_value={"id": 1},
|
||||
),
|
||||
return_value={"result": "success"},
|
||||
) as create_api_tool_provider,
|
||||
):
|
||||
assert method(api, "t", make_account())["id"] == 1
|
||||
assert method(api, "t", make_account()) == {"result": "success"}
|
||||
|
||||
create_api_tool_provider.assert_called_once()
|
||||
assert create_api_tool_provider.call_args.args[3] == emoji_icon()
|
||||
|
||||
def test_remote_schema(self, app: Flask) -> None:
|
||||
api = ToolApiProviderGetRemoteSchemaApi()
|
||||
method = unwrap(api.get)
|
||||
openapi_schema = '{"openapi":"3.0.0","info":{"title":"Demo API","version":"1.0.0"},"paths":{}}'
|
||||
|
||||
with (
|
||||
app.test_request_context("/?url=http://x.com"),
|
||||
patch(
|
||||
"controllers.console.workspace.tool_providers.ApiToolManageService.get_api_tool_provider_remote_schema",
|
||||
return_value={"schema": "x"},
|
||||
return_value={"schema": openapi_schema},
|
||||
),
|
||||
):
|
||||
assert method(api, "t", make_account())["schema"] == "x"
|
||||
assert method(api, "t", make_account()) == {"schema": openapi_schema}
|
||||
|
||||
def test_list_tools(self, app: Flask) -> None:
|
||||
api = ToolApiProviderListToolsApi()
|
||||
@ -387,10 +547,10 @@ class TestApiProviderApis:
|
||||
app.test_request_context("/?provider=p"),
|
||||
patch(
|
||||
"controllers.console.workspace.tool_providers.ApiToolManageService.list_api_tool_provider_tools",
|
||||
return_value=[{"tool": 1}],
|
||||
return_value=[tool_payload("api_ping")],
|
||||
),
|
||||
):
|
||||
assert method(api, "t", make_account()) == [{"tool": 1}]
|
||||
assert method(api, "t", make_account())[0]["name"] == "api_ping"
|
||||
|
||||
def test_update(self, app: Flask) -> None:
|
||||
api = ToolApiProviderUpdateApi()
|
||||
@ -402,7 +562,7 @@ class TestApiProviderApis:
|
||||
"schema": "{}",
|
||||
"provider": "p",
|
||||
"original_provider": "o",
|
||||
"icon": empty_mapping(),
|
||||
"icon": emoji_icon(),
|
||||
"privacy_policy": "",
|
||||
"custom_disclaimer": "",
|
||||
}
|
||||
@ -411,10 +571,13 @@ class TestApiProviderApis:
|
||||
app.test_request_context("/", json=payload),
|
||||
patch(
|
||||
"controllers.console.workspace.tool_providers.ApiToolManageService.update_api_tool_provider",
|
||||
return_value={"ok": True},
|
||||
),
|
||||
return_value={"result": "success"},
|
||||
) as update_api_tool_provider,
|
||||
):
|
||||
assert method(api, "t", make_account())["ok"]
|
||||
assert method(api, "t", make_account()) == {"result": "success"}
|
||||
|
||||
update_api_tool_provider.assert_called_once()
|
||||
assert update_api_tool_provider.call_args.args[4] == emoji_icon()
|
||||
|
||||
def test_delete(self, app: Flask) -> None:
|
||||
api = ToolApiProviderDeleteApi()
|
||||
@ -437,10 +600,10 @@ class TestApiProviderApis:
|
||||
app.test_request_context("/?provider=p"),
|
||||
patch(
|
||||
"controllers.console.workspace.tool_providers.ApiToolManageService.get_api_tool_provider",
|
||||
return_value={"x": 1},
|
||||
return_value=api_provider_detail_payload(),
|
||||
),
|
||||
):
|
||||
assert method(api, "t", make_account()) == {"x": 1}
|
||||
assert method(api, "t", make_account())["schema"] == "{}"
|
||||
|
||||
|
||||
class TestWorkflowApis:
|
||||
@ -457,7 +620,7 @@ class TestWorkflowApis:
|
||||
"name": "n",
|
||||
"label": "l",
|
||||
"description": "d",
|
||||
"icon": empty_mapping(),
|
||||
"icon": emoji_icon(),
|
||||
"parameters": empty_list(),
|
||||
}
|
||||
|
||||
@ -465,10 +628,13 @@ class TestWorkflowApis:
|
||||
app.test_request_context("/", json=payload),
|
||||
patch(
|
||||
"controllers.console.workspace.tool_providers.WorkflowToolManageService.create_workflow_tool",
|
||||
return_value={"id": 1},
|
||||
),
|
||||
return_value={"result": "success"},
|
||||
) as create_workflow_tool,
|
||||
):
|
||||
assert method(api, "t", make_account())["id"] == 1
|
||||
assert method(api, "t", make_account()) == {"result": "success"}
|
||||
|
||||
create_workflow_tool.assert_called_once()
|
||||
assert create_workflow_tool.call_args.kwargs["icon"] == emoji_icon()
|
||||
|
||||
def test_update_invalid(self, app: Flask) -> None:
|
||||
api = ToolWorkflowProviderUpdateApi()
|
||||
@ -479,18 +645,21 @@ class TestWorkflowApis:
|
||||
"name": "Tool",
|
||||
"label": "Tool Label",
|
||||
"description": "A tool",
|
||||
"icon": empty_mapping(),
|
||||
"icon": emoji_icon(),
|
||||
}
|
||||
|
||||
with (
|
||||
app.test_request_context("/", json=payload),
|
||||
patch(
|
||||
"controllers.console.workspace.tool_providers.WorkflowToolManageService.update_workflow_tool",
|
||||
return_value={"ok": True},
|
||||
),
|
||||
return_value={"result": "success"},
|
||||
) as update_workflow_tool,
|
||||
):
|
||||
result = method(api, "t", make_account())
|
||||
assert result["ok"]
|
||||
assert result == {"result": "success"}
|
||||
|
||||
update_workflow_tool.assert_called_once()
|
||||
assert update_workflow_tool.call_args.args[5] == emoji_icon()
|
||||
|
||||
def test_delete(self, app: Flask) -> None:
|
||||
api = ToolWorkflowProviderDeleteApi()
|
||||
@ -500,10 +669,10 @@ class TestWorkflowApis:
|
||||
app.test_request_context("/", json={"workflow_tool_id": "123e4567-e89b-12d3-a456-426614174000"}),
|
||||
patch(
|
||||
"controllers.console.workspace.tool_providers.WorkflowToolManageService.delete_workflow_tool",
|
||||
return_value={"ok": True},
|
||||
return_value={"result": "success"},
|
||||
),
|
||||
):
|
||||
assert method(api, "t", make_account())["ok"]
|
||||
assert method(api, "t", make_account())["result"] == "success"
|
||||
|
||||
def test_get_error(self, app: Flask) -> None:
|
||||
api = ToolWorkflowProviderGetApi()
|
||||
@ -525,49 +694,40 @@ class TestLists:
|
||||
api = ToolBuiltinListApi()
|
||||
method = unwrap(api.get)
|
||||
|
||||
m = MagicMock()
|
||||
m.to_dict.return_value = {"x": 1}
|
||||
|
||||
with (
|
||||
app.test_request_context("/"),
|
||||
patch(
|
||||
"controllers.console.workspace.tool_providers.BuiltinToolManageService.list_builtin_tools",
|
||||
return_value=[m],
|
||||
return_value=[provider_entity(provider_id="builtin-1")],
|
||||
),
|
||||
):
|
||||
assert method(api, "t", make_account()) == [{"x": 1}]
|
||||
assert method(api, "t", make_account())[0]["id"] == "builtin-1"
|
||||
|
||||
def test_api_list(self, app: Flask) -> None:
|
||||
api = ToolApiListApi()
|
||||
method = unwrap(api.get)
|
||||
|
||||
m = MagicMock()
|
||||
m.to_dict.return_value = {"x": 1}
|
||||
|
||||
with (
|
||||
app.test_request_context("/"),
|
||||
patch(
|
||||
"controllers.console.workspace.tool_providers.ApiToolManageService.list_api_tools",
|
||||
return_value=[m],
|
||||
return_value=[provider_entity(provider_id="api-1", provider_type="api")],
|
||||
),
|
||||
):
|
||||
assert method(api, "t") == [{"x": 1}]
|
||||
assert method(api, "t")[0]["id"] == "api-1"
|
||||
|
||||
def test_workflow_list(self, app: Flask) -> None:
|
||||
api = ToolWorkflowListApi()
|
||||
method = unwrap(api.get)
|
||||
|
||||
m = MagicMock()
|
||||
m.to_dict.return_value = {"x": 1}
|
||||
|
||||
with (
|
||||
app.test_request_context("/"),
|
||||
patch(
|
||||
"controllers.console.workspace.tool_providers.WorkflowToolManageService.list_tenant_workflow_tools",
|
||||
return_value=[m],
|
||||
return_value=[provider_entity(provider_id="workflow-1", provider_type="workflow")],
|
||||
),
|
||||
):
|
||||
assert method(api, "t", make_account()) == [{"x": 1}]
|
||||
assert method(api, "t", make_account())[0]["id"] == "workflow-1"
|
||||
|
||||
|
||||
class TestLabels:
|
||||
@ -583,10 +743,10 @@ class TestLabels:
|
||||
app.test_request_context("/"),
|
||||
patch(
|
||||
"controllers.console.workspace.tool_providers.ToolLabelsService.list_tool_labels",
|
||||
return_value=["l1"],
|
||||
return_value=[tool_label_payload()],
|
||||
),
|
||||
):
|
||||
assert method(api) == ["l1"]
|
||||
assert method(api)[0]["name"] == "utilities"
|
||||
|
||||
|
||||
class TestOAuth:
|
||||
@ -630,10 +790,10 @@ class TestOAuthCustomClient:
|
||||
app.test_request_context("/", json={"client_params": {"a": 1}}),
|
||||
patch(
|
||||
"controllers.console.workspace.tool_providers.BuiltinToolManageService.save_custom_oauth_client_params",
|
||||
return_value={"ok": True},
|
||||
return_value={"result": "success"},
|
||||
),
|
||||
):
|
||||
assert method(api, "t", "provider")["ok"]
|
||||
assert method(api, "t", "provider") == {"result": "success"}
|
||||
|
||||
def test_get_custom_client(self, app: Flask) -> None:
|
||||
api = ToolOAuthCustomClient()
|
||||
@ -656,7 +816,7 @@ class TestOAuthCustomClient:
|
||||
app.test_request_context("/"),
|
||||
patch(
|
||||
"controllers.console.workspace.tool_providers.BuiltinToolManageService.delete_custom_oauth_client_params",
|
||||
return_value={"ok": True},
|
||||
return_value={"result": "success"},
|
||||
),
|
||||
):
|
||||
assert method(api, "t", "provider")["ok"]
|
||||
assert method(api, "t", "provider") == {"result": "success"}
|
||||
|
||||
@ -2,6 +2,7 @@
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from datetime import datetime
|
||||
from inspect import unwrap
|
||||
from unittest.mock import MagicMock, patch
|
||||
|
||||
@ -29,6 +30,8 @@ from controllers.console.workspace.trigger_providers import (
|
||||
TriggerSubscriptionVerifyApi,
|
||||
)
|
||||
from core.plugin.entities.plugin_daemon import CredentialType
|
||||
from core.trigger.entities.api_entities import SubscriptionBuilderApiEntity, TriggerProviderApiEntity
|
||||
from core.trigger.entities.entities import RequestLog
|
||||
from models.account import Account
|
||||
|
||||
|
||||
@ -38,6 +41,47 @@ def mock_user() -> Account:
|
||||
return user
|
||||
|
||||
|
||||
def trigger_provider() -> TriggerProviderApiEntity:
|
||||
return TriggerProviderApiEntity(
|
||||
author="Dify",
|
||||
name="github",
|
||||
label={"en_US": "GitHub"},
|
||||
description={"en_US": "GitHub trigger provider"},
|
||||
icon="icon.svg",
|
||||
icon_dark=None,
|
||||
tags=["code"],
|
||||
plugin_id="plugin",
|
||||
plugin_unique_identifier="plugin:github",
|
||||
supported_creation_methods=[],
|
||||
subscription_constructor=None,
|
||||
subscription_schema=[],
|
||||
events=[],
|
||||
)
|
||||
|
||||
|
||||
def subscription_builder() -> SubscriptionBuilderApiEntity:
|
||||
return SubscriptionBuilderApiEntity(
|
||||
id="b1",
|
||||
name="Builder",
|
||||
provider="github",
|
||||
endpoint="b1",
|
||||
parameters={"repo": "dify"},
|
||||
properties={"branch": "main"},
|
||||
credentials={"token": "secret"},
|
||||
credential_type=CredentialType.UNAUTHORIZED,
|
||||
)
|
||||
|
||||
|
||||
def request_log() -> RequestLog:
|
||||
return RequestLog(
|
||||
id="log1",
|
||||
endpoint="/hooks/b1",
|
||||
request={"headers": {}, "body": {"event": "push"}},
|
||||
response={"status": 200, "body": {"ok": True}},
|
||||
created_at=datetime(2024, 1, 1),
|
||||
)
|
||||
|
||||
|
||||
class TestTriggerProviderApis:
|
||||
@pytest.fixture
|
||||
def app(self, flask_app_with_containers: Flask) -> Flask:
|
||||
@ -77,10 +121,10 @@ class TestTriggerProviderApis:
|
||||
app.test_request_context("/"),
|
||||
patch(
|
||||
"controllers.console.workspace.trigger_providers.TriggerProviderService.get_trigger_provider",
|
||||
return_value={"id": "p1"},
|
||||
return_value=trigger_provider(),
|
||||
),
|
||||
):
|
||||
assert method(api, "t1", "github") == {"id": "p1"}
|
||||
assert method(api, "t1", "github")["name"] == "github"
|
||||
|
||||
|
||||
class TestTriggerSubscriptionListApi:
|
||||
@ -129,11 +173,11 @@ class TestTriggerSubscriptionBuilderApis:
|
||||
app.test_request_context("/", json={"credential_type": "UNAUTHORIZED"}),
|
||||
patch(
|
||||
"controllers.console.workspace.trigger_providers.TriggerSubscriptionBuilderService.create_trigger_subscription_builder",
|
||||
return_value={"id": "b1"},
|
||||
return_value=subscription_builder(),
|
||||
),
|
||||
):
|
||||
result = method(api, "t1", mock_user(), "github")
|
||||
assert "subscription_builder" in result
|
||||
assert result["subscription_builder"]["id"] == "b1"
|
||||
|
||||
def test_get_builder(self, app: Flask) -> None:
|
||||
api = TriggerSubscriptionBuilderGetApi()
|
||||
@ -143,10 +187,10 @@ class TestTriggerSubscriptionBuilderApis:
|
||||
app.test_request_context("/"),
|
||||
patch(
|
||||
"controllers.console.workspace.trigger_providers.TriggerSubscriptionBuilderService.get_subscription_builder_by_id",
|
||||
return_value={"id": "b1"},
|
||||
return_value=subscription_builder(),
|
||||
),
|
||||
):
|
||||
assert method(api, "github", "b1") == {"id": "b1"}
|
||||
assert method(api, "github", "b1")["id"] == "b1"
|
||||
|
||||
def test_verify_builder(self, app: Flask) -> None:
|
||||
api = TriggerSubscriptionBuilderVerifyApi()
|
||||
@ -156,10 +200,10 @@ class TestTriggerSubscriptionBuilderApis:
|
||||
app.test_request_context("/", json={"credentials": {"a": 1}}),
|
||||
patch(
|
||||
"controllers.console.workspace.trigger_providers.TriggerSubscriptionBuilderService.update_and_verify_builder",
|
||||
return_value={"ok": True},
|
||||
return_value={"verified": True},
|
||||
),
|
||||
):
|
||||
assert method(api, "t1", mock_user(), "github", "b1") == {"ok": True}
|
||||
assert method(api, "t1", mock_user(), "github", "b1") == {"verified": True}
|
||||
|
||||
def test_verify_builder_error(self, app: Flask) -> None:
|
||||
api = TriggerSubscriptionBuilderVerifyApi()
|
||||
@ -183,26 +227,24 @@ class TestTriggerSubscriptionBuilderApis:
|
||||
app.test_request_context("/", json={"name": "n"}),
|
||||
patch(
|
||||
"controllers.console.workspace.trigger_providers.TriggerSubscriptionBuilderService.update_trigger_subscription_builder",
|
||||
return_value={"id": "b1"},
|
||||
return_value=subscription_builder(),
|
||||
),
|
||||
):
|
||||
assert method(api, "t1", "github", "b1") == {"id": "b1"}
|
||||
assert method(api, "t1", "github", "b1")["id"] == "b1"
|
||||
|
||||
def test_logs(self, app: Flask) -> None:
|
||||
api = TriggerSubscriptionBuilderLogsApi()
|
||||
method = unwrap(api.get)
|
||||
|
||||
log = MagicMock()
|
||||
log.model_dump.return_value = {"a": 1}
|
||||
|
||||
with (
|
||||
app.test_request_context("/"),
|
||||
patch(
|
||||
"controllers.console.workspace.trigger_providers.TriggerSubscriptionBuilderService.list_logs",
|
||||
return_value=[log],
|
||||
return_value=[request_log()],
|
||||
),
|
||||
):
|
||||
assert "logs" in method(api, "github", "b1")
|
||||
result = method(api, "github", "b1")
|
||||
assert result["logs"][0]["id"] == "log1"
|
||||
|
||||
def test_build(self, app: Flask) -> None:
|
||||
api = TriggerSubscriptionBuilderBuildApi()
|
||||
@ -215,7 +257,7 @@ class TestTriggerSubscriptionBuilderApis:
|
||||
return_value=None,
|
||||
),
|
||||
):
|
||||
assert method(api, "t1", mock_user(), "github", "b1") == 200
|
||||
assert method(api, "t1", mock_user(), "github", "b1") == {"result": "success"}
|
||||
|
||||
|
||||
class TestTriggerSubscriptionCrud:
|
||||
@ -239,7 +281,7 @@ class TestTriggerSubscriptionCrud:
|
||||
),
|
||||
patch("controllers.console.workspace.trigger_providers.TriggerProviderService.update_trigger_subscription"),
|
||||
):
|
||||
assert method(api, "t1", "s1") == 200
|
||||
assert method(api, "t1", "s1") == {"result": "success"}
|
||||
|
||||
def test_update_not_found(self, app: Flask) -> None:
|
||||
api = TriggerSubscriptionUpdateApi()
|
||||
@ -275,7 +317,7 @@ class TestTriggerSubscriptionCrud:
|
||||
"controllers.console.workspace.trigger_providers.TriggerProviderService.rebuild_trigger_subscription"
|
||||
),
|
||||
):
|
||||
assert method(api, "t1", "s1") == 200
|
||||
assert method(api, "t1", "s1") == {"result": "success"}
|
||||
|
||||
def test_delete_subscription(self, app: Flask) -> None:
|
||||
api = TriggerSubscriptionDeleteApi()
|
||||
@ -336,7 +378,7 @@ class TestTriggerOAuthApis:
|
||||
),
|
||||
patch(
|
||||
"controllers.console.workspace.trigger_providers.TriggerSubscriptionBuilderService.create_trigger_subscription_builder",
|
||||
return_value=MagicMock(id="b1"),
|
||||
return_value=subscription_builder(),
|
||||
),
|
||||
patch(
|
||||
"controllers.console.workspace.trigger_providers.OAuthProxyService.create_proxy_context",
|
||||
@ -480,7 +522,7 @@ class TestTriggerOAuthClientManageApi:
|
||||
),
|
||||
patch(
|
||||
"controllers.console.workspace.trigger_providers.TriggerManager.get_trigger_provider",
|
||||
return_value=MagicMock(get_oauth_client_schema=lambda: {}),
|
||||
return_value=MagicMock(get_oauth_client_schema=lambda: []),
|
||||
),
|
||||
):
|
||||
result = method(api, "t1", "github")
|
||||
@ -494,10 +536,10 @@ class TestTriggerOAuthClientManageApi:
|
||||
app.test_request_context("/", json={"enabled": True}),
|
||||
patch(
|
||||
"controllers.console.workspace.trigger_providers.TriggerProviderService.save_custom_oauth_client_params",
|
||||
return_value={"ok": True},
|
||||
return_value={"result": "success"},
|
||||
),
|
||||
):
|
||||
assert method(api, "t1", "github") == {"ok": True}
|
||||
assert method(api, "t1", "github") == {"result": "success"}
|
||||
|
||||
def test_delete_client(self, app: Flask) -> None:
|
||||
api = TriggerOAuthClientManageApi()
|
||||
@ -507,10 +549,10 @@ class TestTriggerOAuthClientManageApi:
|
||||
app.test_request_context("/"),
|
||||
patch(
|
||||
"controllers.console.workspace.trigger_providers.TriggerProviderService.delete_custom_oauth_client_params",
|
||||
return_value={"ok": True},
|
||||
return_value={"result": "success"},
|
||||
),
|
||||
):
|
||||
assert method(api, "t1", "github") == {"ok": True}
|
||||
assert method(api, "t1", "github") == {"result": "success"}
|
||||
|
||||
def test_oauth_client_post_value_error(self, app: Flask) -> None:
|
||||
api = TriggerOAuthClientManageApi()
|
||||
@ -540,10 +582,10 @@ class TestTriggerSubscriptionVerifyApi:
|
||||
app.test_request_context("/", json={"credentials": {}}),
|
||||
patch(
|
||||
"controllers.console.workspace.trigger_providers.TriggerProviderService.verify_subscription_credentials",
|
||||
return_value={"ok": True},
|
||||
return_value={"verified": True},
|
||||
),
|
||||
):
|
||||
assert method(api, "t1", mock_user(), "github", "s1") == {"ok": True}
|
||||
assert method(api, "t1", mock_user(), "github", "s1") == {"verified": True}
|
||||
|
||||
@pytest.mark.parametrize("raised_exception", [ValueError("bad"), Exception("boom")])
|
||||
def test_verify_errors(self, app: Flask, raised_exception: Exception) -> None:
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
import inspect
|
||||
import json
|
||||
from unittest.mock import patch
|
||||
from collections.abc import Iterator
|
||||
from unittest.mock import MagicMock, patch
|
||||
|
||||
import pytest
|
||||
from faker import Faker
|
||||
@ -10,16 +11,18 @@ from sqlalchemy.orm import Session
|
||||
from core.tools.entities.tool_entities import ApiProviderSchemaType
|
||||
from core.tools.errors import ApiToolProviderNotFoundError
|
||||
from core.tools.tool_label_manager import ToolLabelManager
|
||||
from models import Account, Tenant
|
||||
from models import Account, AccountStatus, Tenant, TenantStatus
|
||||
from models.tools import ApiToolProvider
|
||||
from services.tools.api_tools_manage_service import ApiToolManageService
|
||||
|
||||
MockDependencies = dict[str, MagicMock]
|
||||
|
||||
|
||||
class TestApiToolManageService:
|
||||
"""Integration tests for ApiToolManageService using testcontainers."""
|
||||
|
||||
@pytest.fixture
|
||||
def mock_external_service_dependencies(self):
|
||||
def mock_external_service_dependencies(self) -> Iterator[MockDependencies]:
|
||||
"""Mock setup for external service dependencies."""
|
||||
with (
|
||||
patch("services.tools.api_tools_manage_service.ToolLabelManager") as mock_tool_label_manager,
|
||||
@ -39,7 +42,9 @@ class TestApiToolManageService:
|
||||
"provider_controller": mock_provider_controller,
|
||||
}
|
||||
|
||||
def _create_test_account_and_tenant(self, db_session_with_containers: Session, mock_external_service_dependencies):
|
||||
def _create_test_account_and_tenant(
|
||||
self, db_session_with_containers: Session, mock_external_service_dependencies: MockDependencies
|
||||
) -> tuple[Account, Tenant]:
|
||||
"""
|
||||
Helper method to create a test account and tenant for testing.
|
||||
|
||||
@ -57,7 +62,7 @@ class TestApiToolManageService:
|
||||
email=fake.email(),
|
||||
name=fake.name(),
|
||||
interface_language="en-US",
|
||||
status="active",
|
||||
status=AccountStatus.ACTIVE,
|
||||
)
|
||||
|
||||
db_session_with_containers.add(account)
|
||||
@ -66,7 +71,7 @@ class TestApiToolManageService:
|
||||
# Create tenant for the account
|
||||
tenant = Tenant(
|
||||
name=fake.company(),
|
||||
status="normal",
|
||||
status=TenantStatus.NORMAL,
|
||||
)
|
||||
db_session_with_containers.add(tenant)
|
||||
db_session_with_containers.commit()
|
||||
@ -88,7 +93,7 @@ class TestApiToolManageService:
|
||||
|
||||
return account, tenant
|
||||
|
||||
def _create_test_openapi_schema(self):
|
||||
def _create_test_openapi_schema(self) -> str:
|
||||
"""Helper method to create a test OpenAPI schema."""
|
||||
return """
|
||||
{
|
||||
@ -121,8 +126,11 @@ class TestApiToolManageService:
|
||||
"""
|
||||
|
||||
def test_parser_api_schema_success(
|
||||
self, flask_req_ctx_with_containers, db_session_with_containers: Session, mock_external_service_dependencies
|
||||
):
|
||||
self,
|
||||
flask_req_ctx_with_containers: object,
|
||||
db_session_with_containers: Session,
|
||||
mock_external_service_dependencies: MockDependencies,
|
||||
) -> None:
|
||||
"""
|
||||
Test successful parsing of API schema.
|
||||
|
||||
@ -148,6 +156,8 @@ class TestApiToolManageService:
|
||||
# Verify credentials schema structure
|
||||
credentials_schema = result["credentials_schema"]
|
||||
assert len(credentials_schema) == 3
|
||||
assert all(isinstance(field, dict) for field in credentials_schema)
|
||||
assert all(isinstance(tool, dict) for tool in result["parameters_schema"])
|
||||
|
||||
# Check auth_type field
|
||||
auth_type_field = next(field for field in credentials_schema if field["name"] == "auth_type")
|
||||
@ -166,8 +176,11 @@ class TestApiToolManageService:
|
||||
assert api_key_value_field["default"] == ""
|
||||
|
||||
def test_parser_api_schema_invalid_schema(
|
||||
self, flask_req_ctx_with_containers, db_session_with_containers: Session, mock_external_service_dependencies
|
||||
):
|
||||
self,
|
||||
flask_req_ctx_with_containers: object,
|
||||
db_session_with_containers: Session,
|
||||
mock_external_service_dependencies: MockDependencies,
|
||||
) -> None:
|
||||
"""
|
||||
Test parsing of invalid API schema.
|
||||
|
||||
@ -186,8 +199,11 @@ class TestApiToolManageService:
|
||||
assert "invalid schema" in str(exc_info.value)
|
||||
|
||||
def test_parser_api_schema_malformed_json(
|
||||
self, flask_req_ctx_with_containers, db_session_with_containers: Session, mock_external_service_dependencies
|
||||
):
|
||||
self,
|
||||
flask_req_ctx_with_containers: object,
|
||||
db_session_with_containers: Session,
|
||||
mock_external_service_dependencies: MockDependencies,
|
||||
) -> None:
|
||||
"""
|
||||
Test parsing of malformed JSON schema.
|
||||
|
||||
@ -206,8 +222,11 @@ class TestApiToolManageService:
|
||||
assert "invalid schema" in str(exc_info.value)
|
||||
|
||||
def test_convert_schema_to_tool_bundles_success(
|
||||
self, flask_req_ctx_with_containers, db_session_with_containers: Session, mock_external_service_dependencies
|
||||
):
|
||||
self,
|
||||
flask_req_ctx_with_containers: object,
|
||||
db_session_with_containers: Session,
|
||||
mock_external_service_dependencies: MockDependencies,
|
||||
) -> None:
|
||||
"""
|
||||
Test successful conversion of schema to tool bundles.
|
||||
|
||||
@ -236,8 +255,11 @@ class TestApiToolManageService:
|
||||
assert tool_bundle.operation_id == "testOperation"
|
||||
|
||||
def test_convert_schema_to_tool_bundles_with_extra_info(
|
||||
self, flask_req_ctx_with_containers, db_session_with_containers: Session, mock_external_service_dependencies
|
||||
):
|
||||
self,
|
||||
flask_req_ctx_with_containers: object,
|
||||
db_session_with_containers: Session,
|
||||
mock_external_service_dependencies: MockDependencies,
|
||||
) -> None:
|
||||
"""
|
||||
Test successful conversion of schema to tool bundles with extra info.
|
||||
|
||||
@ -262,8 +284,11 @@ class TestApiToolManageService:
|
||||
assert isinstance(schema_type, str)
|
||||
|
||||
def test_convert_schema_to_tool_bundles_invalid_schema(
|
||||
self, flask_req_ctx_with_containers, db_session_with_containers: Session, mock_external_service_dependencies
|
||||
):
|
||||
self,
|
||||
flask_req_ctx_with_containers: object,
|
||||
db_session_with_containers: Session,
|
||||
mock_external_service_dependencies: MockDependencies,
|
||||
) -> None:
|
||||
"""
|
||||
Test conversion of invalid schema to tool bundles.
|
||||
|
||||
@ -282,8 +307,11 @@ class TestApiToolManageService:
|
||||
assert "invalid schema" in str(exc_info.value)
|
||||
|
||||
def test_create_api_tool_provider_success(
|
||||
self, flask_req_ctx_with_containers, db_session_with_containers: Session, mock_external_service_dependencies
|
||||
):
|
||||
self,
|
||||
flask_req_ctx_with_containers: object,
|
||||
db_session_with_containers: Session,
|
||||
mock_external_service_dependencies: MockDependencies,
|
||||
) -> None:
|
||||
"""
|
||||
Test successful creation of API tool provider.
|
||||
|
||||
@ -301,7 +329,7 @@ class TestApiToolManageService:
|
||||
)
|
||||
|
||||
provider_name = fake.company()
|
||||
icon = {"type": "emoji", "value": "🔧"}
|
||||
icon = {"content": "🔧", "background": "#FFF"}
|
||||
credentials = {"auth_type": "none", "api_key_header": "X-API-Key", "api_key_value": ""}
|
||||
schema_type = ApiProviderSchemaType.OPENAPI
|
||||
schema = self._create_test_openapi_schema()
|
||||
@ -341,6 +369,7 @@ class TestApiToolManageService:
|
||||
assert provider.schema_type_str == schema_type
|
||||
assert provider.privacy_policy == privacy_policy
|
||||
assert provider.custom_disclaimer == custom_disclaimer
|
||||
assert json.loads(provider.icon) == icon
|
||||
|
||||
# Verify mock interactions
|
||||
mock_external_service_dependencies["tool_label_manager"].update_tool_labels.assert_called_once()
|
||||
@ -349,8 +378,11 @@ class TestApiToolManageService:
|
||||
mock_external_service_dependencies["provider_controller"].load_bundled_tools.assert_called_once()
|
||||
|
||||
def test_create_api_tool_provider_duplicate_name(
|
||||
self, flask_req_ctx_with_containers, db_session_with_containers: Session, mock_external_service_dependencies
|
||||
):
|
||||
self,
|
||||
flask_req_ctx_with_containers: object,
|
||||
db_session_with_containers: Session,
|
||||
mock_external_service_dependencies: MockDependencies,
|
||||
) -> None:
|
||||
"""
|
||||
Test creation of API tool provider with duplicate name.
|
||||
|
||||
@ -366,7 +398,7 @@ class TestApiToolManageService:
|
||||
)
|
||||
|
||||
provider_name = fake.company()
|
||||
icon = {"type": "emoji", "value": "🔧"}
|
||||
icon = {"content": "🔧", "background": "#FFF"}
|
||||
credentials = {"auth_type": "none"}
|
||||
schema_type = ApiProviderSchemaType.OPENAPI
|
||||
schema = self._create_test_openapi_schema()
|
||||
@ -406,8 +438,11 @@ class TestApiToolManageService:
|
||||
assert f"provider {provider_name} already exists" in str(exc_info.value)
|
||||
|
||||
def test_create_api_tool_provider_invalid_schema_type(
|
||||
self, flask_req_ctx_with_containers, db_session_with_containers: Session, mock_external_service_dependencies
|
||||
):
|
||||
self,
|
||||
flask_req_ctx_with_containers: object,
|
||||
db_session_with_containers: Session,
|
||||
mock_external_service_dependencies: MockDependencies,
|
||||
) -> None:
|
||||
"""
|
||||
Test creation of API tool provider with invalid schema type.
|
||||
|
||||
@ -423,7 +458,7 @@ class TestApiToolManageService:
|
||||
)
|
||||
|
||||
provider_name = fake.company()
|
||||
icon = {"type": "emoji", "value": "🔧"}
|
||||
icon = {"content": "🔧", "background": "#FFF"}
|
||||
credentials = {"auth_type": "none"}
|
||||
schema_type = "invalid_type"
|
||||
schema = self._create_test_openapi_schema()
|
||||
@ -438,8 +473,11 @@ class TestApiToolManageService:
|
||||
assert "validation error" in str(exc_info.value)
|
||||
|
||||
def test_create_api_tool_provider_missing_auth_type(
|
||||
self, flask_req_ctx_with_containers, db_session_with_containers: Session, mock_external_service_dependencies
|
||||
):
|
||||
self,
|
||||
flask_req_ctx_with_containers: object,
|
||||
db_session_with_containers: Session,
|
||||
mock_external_service_dependencies: MockDependencies,
|
||||
) -> None:
|
||||
"""
|
||||
Test creation of API tool provider with missing auth type.
|
||||
|
||||
@ -455,7 +493,7 @@ class TestApiToolManageService:
|
||||
)
|
||||
|
||||
provider_name = fake.company()
|
||||
icon = {"type": "emoji", "value": "🔧"}
|
||||
icon = {"content": "🔧", "background": "#FFF"}
|
||||
credentials = {} # Missing auth_type
|
||||
schema_type = ApiProviderSchemaType.OPENAPI
|
||||
schema = self._create_test_openapi_schema()
|
||||
@ -481,8 +519,11 @@ class TestApiToolManageService:
|
||||
assert "auth_type is required" in str(exc_info.value)
|
||||
|
||||
def test_create_api_tool_provider_with_api_key_auth(
|
||||
self, flask_req_ctx_with_containers, db_session_with_containers: Session, mock_external_service_dependencies
|
||||
):
|
||||
self,
|
||||
flask_req_ctx_with_containers: object,
|
||||
db_session_with_containers: Session,
|
||||
mock_external_service_dependencies: MockDependencies,
|
||||
) -> None:
|
||||
"""
|
||||
Test successful creation of API tool provider with API key authentication.
|
||||
|
||||
@ -498,7 +539,7 @@ class TestApiToolManageService:
|
||||
)
|
||||
|
||||
provider_name = fake.company()
|
||||
icon = {"type": "emoji", "value": "🔑"}
|
||||
icon = {"content": "🔑", "background": "#FFF"}
|
||||
credentials = {"auth_type": "api_key", "api_key_header": "X-API-Key", "api_key_value": fake.uuid4()}
|
||||
schema_type = ApiProviderSchemaType.OPENAPI
|
||||
schema = self._create_test_openapi_schema()
|
||||
@ -542,8 +583,11 @@ class TestApiToolManageService:
|
||||
mock_external_service_dependencies["provider_controller"].from_db.assert_called_once()
|
||||
|
||||
def test_delete_api_tool_provider_success(
|
||||
self, flask_req_ctx_with_containers, db_session_with_containers: Session, mock_external_service_dependencies
|
||||
):
|
||||
self,
|
||||
flask_req_ctx_with_containers: object,
|
||||
db_session_with_containers: Session,
|
||||
mock_external_service_dependencies: MockDependencies,
|
||||
) -> None:
|
||||
"""Test successful deletion of an API tool provider."""
|
||||
fake = Faker()
|
||||
account, tenant = self._create_test_account_and_tenant(
|
||||
@ -583,8 +627,8 @@ class TestApiToolManageService:
|
||||
assert deleted is None
|
||||
|
||||
def test_delete_api_tool_provider_not_found(
|
||||
self, db_session_with_containers: Session, mock_external_service_dependencies
|
||||
):
|
||||
self, db_session_with_containers: Session, mock_external_service_dependencies: MockDependencies
|
||||
) -> None:
|
||||
"""Test deletion raises ValueError when provider not found."""
|
||||
fake = Faker()
|
||||
account, tenant = self._create_test_account_and_tenant(
|
||||
@ -595,14 +639,15 @@ class TestApiToolManageService:
|
||||
ApiToolManageService.delete_api_tool_provider(account.id, tenant.id, "nonexistent")
|
||||
|
||||
def test_update_api_tool_provider_success(
|
||||
self, flask_req_ctx_with_containers, db_session_with_containers: Session, mock_external_service_dependencies
|
||||
):
|
||||
self,
|
||||
flask_req_ctx_with_containers: object,
|
||||
db_session_with_containers: Session,
|
||||
mock_external_service_dependencies: MockDependencies,
|
||||
) -> None:
|
||||
fake = Faker()
|
||||
|
||||
# Firmware fix for cache.delete() in update flow
|
||||
mock_encrypter = mock_external_service_dependencies["encrypter"]
|
||||
from unittest.mock import MagicMock
|
||||
|
||||
mock_cache = MagicMock()
|
||||
mock_cache.delete.return_value = None
|
||||
mock_encrypter.return_value = (mock_encrypter, mock_cache)
|
||||
@ -620,7 +665,7 @@ class TestApiToolManageService:
|
||||
user_id=account.id,
|
||||
tenant_id=tenant.id,
|
||||
provider_name=original_name,
|
||||
icon={"type": "emoji", "value": "🔧"},
|
||||
icon={"content": "🔧", "background": "#FFF"},
|
||||
credentials={"auth_type": "none"},
|
||||
schema_type=ApiProviderSchemaType.OPENAPI,
|
||||
schema=self._create_test_openapi_schema(),
|
||||
@ -646,7 +691,7 @@ class TestApiToolManageService:
|
||||
provider_name=new_name,
|
||||
original_provider=original_name,
|
||||
# new icon - changed 2
|
||||
icon={"type": "emoji", "value": "🚀"},
|
||||
icon={"content": "🚀", "background": "#FFF"},
|
||||
credentials={"auth_type": "none"},
|
||||
_schema_type=ApiProviderSchemaType.OPENAPI,
|
||||
schema=self._create_test_openapi_schema(),
|
||||
@ -677,9 +722,7 @@ class TestApiToolManageService:
|
||||
# - changed 1
|
||||
assert updated_provider.name == new_name
|
||||
# - changed 2
|
||||
icon_data = json.loads(updated_provider.icon)
|
||||
assert icon_data["type"] == "emoji"
|
||||
assert icon_data["value"] == "🚀"
|
||||
assert json.loads(updated_provider.icon) == {"content": "🚀", "background": "#FFF"}
|
||||
# - changed 3
|
||||
assert updated_provider.privacy_policy == "https://new-policy.com"
|
||||
# - changed 4
|
||||
@ -712,8 +755,11 @@ class TestApiToolManageService:
|
||||
)
|
||||
|
||||
def test_update_api_tool_provider_not_found(
|
||||
self, flask_req_ctx_with_containers, db_session_with_containers: Session, mock_external_service_dependencies
|
||||
):
|
||||
self,
|
||||
flask_req_ctx_with_containers: object,
|
||||
db_session_with_containers: Session,
|
||||
mock_external_service_dependencies: MockDependencies,
|
||||
) -> None:
|
||||
"""
|
||||
Test update raises ValueError when original provider not found.
|
||||
|
||||
@ -733,7 +779,7 @@ class TestApiToolManageService:
|
||||
user_id=account.id,
|
||||
tenant_id=tenant.id,
|
||||
provider_name=existing_provider_name,
|
||||
icon={"type": "emoji", "value": "🔧"},
|
||||
icon={"content": "🔧", "background": "#FFF"},
|
||||
credentials={"auth_type": "none"},
|
||||
schema_type=ApiProviderSchemaType.OPENAPI,
|
||||
schema=self._create_test_openapi_schema(),
|
||||
@ -756,7 +802,7 @@ class TestApiToolManageService:
|
||||
tenant_id=tenant.id,
|
||||
provider_name=target_new_name,
|
||||
original_provider=missing_original_name,
|
||||
icon={"type": "emoji", "value": "🚀"},
|
||||
icon={"content": "🚀", "background": "#FFF"},
|
||||
credentials={"auth_type": "none"},
|
||||
_schema_type=ApiProviderSchemaType.OPENAPI,
|
||||
schema=self._create_test_openapi_schema(),
|
||||
@ -793,8 +839,11 @@ class TestApiToolManageService:
|
||||
mock_external_service_dependencies["provider_controller"].from_db.assert_not_called()
|
||||
|
||||
def test_update_api_tool_provider_missing_auth_type(
|
||||
self, flask_req_ctx_with_containers, db_session_with_containers: Session, mock_external_service_dependencies
|
||||
):
|
||||
self,
|
||||
flask_req_ctx_with_containers: object,
|
||||
db_session_with_containers: Session,
|
||||
mock_external_service_dependencies: MockDependencies,
|
||||
) -> None:
|
||||
"""Test update raises ValueError when auth_type is missing from credentials."""
|
||||
fake = Faker()
|
||||
account, tenant = self._create_test_account_and_tenant(
|
||||
@ -822,7 +871,7 @@ class TestApiToolManageService:
|
||||
tenant_id=tenant.id,
|
||||
provider_name=provider_name,
|
||||
original_provider=provider_name,
|
||||
icon={},
|
||||
icon={"content": "🔧", "background": "#FFF"},
|
||||
credentials={},
|
||||
_schema_type=ApiProviderSchemaType.OPENAPI,
|
||||
schema=schema,
|
||||
@ -832,8 +881,8 @@ class TestApiToolManageService:
|
||||
)
|
||||
|
||||
def test_list_api_tool_provider_tools_not_found(
|
||||
self, db_session_with_containers: Session, mock_external_service_dependencies
|
||||
):
|
||||
self, db_session_with_containers: Session, mock_external_service_dependencies: MockDependencies
|
||||
) -> None:
|
||||
"""Test listing tools raises ValueError when provider not found."""
|
||||
fake = Faker()
|
||||
account, tenant = self._create_test_account_and_tenant(
|
||||
@ -844,8 +893,8 @@ class TestApiToolManageService:
|
||||
ApiToolManageService.list_api_tool_provider_tools(account.id, tenant.id, "nonexistent")
|
||||
|
||||
def test_test_api_tool_preview_invalid_schema_type(
|
||||
self, db_session_with_containers: Session, mock_external_service_dependencies
|
||||
):
|
||||
self, db_session_with_containers: Session, mock_external_service_dependencies: MockDependencies
|
||||
) -> None:
|
||||
"""Test preview raises ValueError for invalid schema type."""
|
||||
fake = Faker()
|
||||
account, tenant = self._create_test_account_and_tenant(
|
||||
|
||||
@ -11,7 +11,17 @@ class TestSpecSchemaDefinitionsApi:
|
||||
api = spec_module.SpecSchemaDefinitionsApi()
|
||||
method = unwrap(api.get)
|
||||
|
||||
schema_definitions = [{"type": "string"}]
|
||||
schema_definitions = [
|
||||
{
|
||||
"name": "conversation-variable",
|
||||
"label": "Conversation variable",
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"properties": {"name": {"type": "string"}},
|
||||
"required": ["name"],
|
||||
},
|
||||
}
|
||||
]
|
||||
|
||||
with patch.object(
|
||||
spec_module,
|
||||
@ -23,6 +33,12 @@ class TestSpecSchemaDefinitionsApi:
|
||||
|
||||
assert status == 200
|
||||
assert resp == schema_definitions
|
||||
assert spec_module.SchemaDefinitionsResponse.model_validate(resp).model_dump(mode="json") == schema_definitions
|
||||
|
||||
def test_get_documents_tight_response_model(self):
|
||||
response = spec_module.SpecSchemaDefinitionsApi.get.__apidoc__["responses"]["200"]
|
||||
|
||||
assert response[1].name == spec_module.SchemaDefinitionsResponse.__name__
|
||||
|
||||
def test_get_exception_returns_empty_list(self, caplog: pytest.LogCaptureFixture):
|
||||
api = spec_module.SpecSchemaDefinitionsApi()
|
||||
|
||||
@ -13,6 +13,9 @@ import pytest
|
||||
from flask import Flask
|
||||
from flask.views import MethodView
|
||||
|
||||
from core.tools.entities.api_entities import ToolProviderApiEntity as CoreToolProviderApiEntity
|
||||
from core.tools.entities.common_entities import I18nObject
|
||||
from core.tools.entities.tool_entities import ToolParameter
|
||||
from models import Account
|
||||
from models.account import TenantAccountRole
|
||||
|
||||
@ -21,6 +24,7 @@ if not hasattr(builtins, "MethodView"):
|
||||
|
||||
|
||||
_CONTROLLER_MODULE: ModuleType | None = None
|
||||
_WRAPS_MODULE: ModuleType | None = None
|
||||
|
||||
|
||||
@contextmanager
|
||||
@ -69,10 +73,11 @@ def controller_module(monkeypatch: pytest.MonkeyPatch):
|
||||
_CONTROLLER_MODULE = importlib.import_module(module_name)
|
||||
|
||||
module = _CONTROLLER_MODULE
|
||||
monkeypatch.setattr(module, "jsonable_encoder", lambda payload: payload)
|
||||
|
||||
# Ensure decorators that consult deployment edition do not reach the database.
|
||||
global _WRAPS_MODULE
|
||||
wraps_module = importlib.import_module("controllers.console.wraps")
|
||||
_WRAPS_MODULE = wraps_module
|
||||
monkeypatch.setattr(module.dify_config, "EDITION", "CLOUD")
|
||||
monkeypatch.setattr(wraps_module.dify_config, "EDITION", "CLOUD")
|
||||
|
||||
@ -88,19 +93,194 @@ def _mock_account(user_id: str = "user-123") -> Account:
|
||||
return user
|
||||
|
||||
|
||||
def _set_current_account(
|
||||
monkeypatch: pytest.MonkeyPatch,
|
||||
controller_module: ModuleType,
|
||||
user: Account,
|
||||
tenant_id: str,
|
||||
) -> None:
|
||||
def _getter():
|
||||
return user, tenant_id
|
||||
|
||||
monkeypatch.setattr(controller_module, "current_account_with_tenant", _getter, raising=False)
|
||||
if _WRAPS_MODULE is not None:
|
||||
monkeypatch.setattr(_WRAPS_MODULE, "current_account_with_tenant", _getter)
|
||||
|
||||
login_module = importlib.import_module("libs.login")
|
||||
monkeypatch.setattr(login_module, "_get_user", lambda: user)
|
||||
|
||||
|
||||
def _i18n(text: str) -> dict[str, str]:
|
||||
return {"en_US": text, "zh_Hans": text, "pt_BR": text, "ja_JP": text}
|
||||
|
||||
|
||||
def _tool_response(controller_module: ModuleType, name: str = "tool-a") -> tuple[dict, dict]:
|
||||
expected = {
|
||||
"author": "Dify",
|
||||
"name": name,
|
||||
"label": _i18n(name),
|
||||
"description": _i18n(f"{name} description"),
|
||||
"parameters": [],
|
||||
"labels": [],
|
||||
"output_schema": {},
|
||||
}
|
||||
tool = controller_module.ToolApiEntity.model_validate(expected)
|
||||
return tool.model_dump(mode="json"), expected
|
||||
|
||||
|
||||
def _provider_entity_response(
|
||||
controller_module: ModuleType, name: str = "provider", provider_type: str = "builtin"
|
||||
) -> tuple[CoreToolProviderApiEntity, dict]:
|
||||
service_payload = {
|
||||
"id": f"{name}-id",
|
||||
"author": "Dify",
|
||||
"name": name,
|
||||
"description": _i18n(f"{name} description"),
|
||||
"icon": "tool.svg",
|
||||
"icon_dark": "",
|
||||
"label": _i18n(name),
|
||||
"type": provider_type,
|
||||
"masked_credentials": {"api_key": "[__HIDDEN__]"},
|
||||
"original_credentials": {"api_key": "sk-secret"},
|
||||
"is_team_authorization": False,
|
||||
"allow_delete": True,
|
||||
"plugin_id": "",
|
||||
"plugin_unique_identifier": "",
|
||||
"tools": [],
|
||||
"labels": [],
|
||||
"server_url": "",
|
||||
"updated_at": 1,
|
||||
"server_identifier": "",
|
||||
"masked_headers": None,
|
||||
"original_headers": None,
|
||||
"authentication": None,
|
||||
"is_dynamic_registration": True,
|
||||
"configuration": None,
|
||||
"identity_mode": "off",
|
||||
"workflow_app_id": None,
|
||||
}
|
||||
provider = CoreToolProviderApiEntity.model_validate(service_payload)
|
||||
return provider, provider.to_dict()
|
||||
|
||||
|
||||
def _provider_list_item(
|
||||
controller_module: ModuleType, name: str = "provider", provider_type: str = "builtin"
|
||||
) -> tuple[dict, dict]:
|
||||
service_payload = {
|
||||
"id": f"{name}-id",
|
||||
"author": "Dify",
|
||||
"name": name,
|
||||
"description": _i18n(f"{name} description"),
|
||||
"icon": "tool.svg",
|
||||
"icon_dark": "",
|
||||
"label": _i18n(name),
|
||||
"type": provider_type,
|
||||
"team_credentials": {"api_key": "[__HIDDEN__]"},
|
||||
"is_team_authorization": False,
|
||||
"allow_delete": True,
|
||||
"plugin_id": "",
|
||||
"plugin_unique_identifier": "",
|
||||
"tools": [],
|
||||
"labels": [],
|
||||
}
|
||||
expected = {
|
||||
**service_payload,
|
||||
}
|
||||
provider = controller_module.ToolProviderApiEntityResponse.model_validate(expected)
|
||||
return service_payload, provider.model_dump(mode="json", exclude_unset=True)
|
||||
|
||||
|
||||
def _credential_response(controller_module: ModuleType, credential_id: str = "cred-1") -> tuple[dict, dict]:
|
||||
expected = {
|
||||
"id": credential_id,
|
||||
"name": "Credential",
|
||||
"provider": "demo",
|
||||
"credential_type": controller_module.CredentialType.API_KEY,
|
||||
"is_default": False,
|
||||
"credentials": {},
|
||||
"visibility": "all_team_members",
|
||||
"created_by": "",
|
||||
"partial_member_list": [],
|
||||
"from_other_member": False,
|
||||
}
|
||||
credential = controller_module.ToolProviderCredentialApiEntity.model_validate(expected)
|
||||
return credential.model_dump(mode="json"), credential.model_dump(mode="json")
|
||||
|
||||
|
||||
def _provider_config_response(controller_module: ModuleType) -> tuple[dict, dict]:
|
||||
expected = {
|
||||
"type": "secret-input",
|
||||
"name": "api_key",
|
||||
"scope": None,
|
||||
"required": False,
|
||||
"default": None,
|
||||
"options": None,
|
||||
"multiple": False,
|
||||
"label": None,
|
||||
"help": None,
|
||||
"url": None,
|
||||
"placeholder": None,
|
||||
}
|
||||
config = controller_module.ProviderConfig.model_validate(expected)
|
||||
return config.model_dump(mode="json"), expected
|
||||
|
||||
|
||||
def _api_provider_detail_response(controller_module: ModuleType) -> tuple[dict, dict]:
|
||||
expected = {
|
||||
"schema_type": "openapi",
|
||||
"schema": "{}",
|
||||
"tools": [],
|
||||
"icon": {"background": "#252525", "content": "tool"},
|
||||
"description": "provider description",
|
||||
"credentials": {"auth_type": "none"},
|
||||
"privacy_policy": "",
|
||||
"custom_disclaimer": "",
|
||||
"labels": [],
|
||||
}
|
||||
detail = controller_module.ApiProviderDetailResponse.model_validate(expected)
|
||||
return detail.model_dump(mode="json", by_alias=True), expected
|
||||
|
||||
|
||||
def _workflow_detail_response(controller_module: ModuleType) -> tuple[dict, dict]:
|
||||
tool_payload, tool_expected = _tool_response(controller_module, "workflow-tool")
|
||||
expected = {
|
||||
"name": "workflow-tool",
|
||||
"label": "Workflow Tool",
|
||||
"workflow_tool_id": "00000000-0000-0000-0000-000000000001",
|
||||
"workflow_app_id": "00000000-0000-0000-0000-000000000002",
|
||||
"icon": {"background": "#252525", "content": "tool"},
|
||||
"description": "description",
|
||||
"parameters": [],
|
||||
"output_schema": {},
|
||||
"tool": tool_expected,
|
||||
"synced": True,
|
||||
"privacy_policy": "",
|
||||
}
|
||||
service_payload = {**expected, "tool": tool_payload}
|
||||
detail = controller_module.WorkflowToolDetailResponse.model_validate(service_payload)
|
||||
return detail.model_dump(mode="json"), expected
|
||||
|
||||
|
||||
def _tool_label_response(controller_module: ModuleType, name: str = "search") -> tuple[dict, dict]:
|
||||
expected = {"name": name, "label": _i18n(name), "icon": "search"}
|
||||
label = controller_module.ToolLabel.model_validate(expected)
|
||||
return label.model_dump(mode="json"), expected
|
||||
|
||||
|
||||
def test_tool_provider_list_calls_service_with_query(
|
||||
app: Flask, controller_module: ModuleType, monkeypatch: pytest.MonkeyPatch
|
||||
):
|
||||
user = _mock_account()
|
||||
_set_current_account(monkeypatch, controller_module, user, "tenant-456")
|
||||
|
||||
service_mock = MagicMock(return_value=[{"provider": "builtin"}])
|
||||
service_payload, expected_response = _provider_list_item(controller_module, "builtin", "builtin")
|
||||
service_mock = MagicMock(return_value=[service_payload])
|
||||
monkeypatch.setattr(controller_module.ToolCommonService, "list_tool_providers", service_mock)
|
||||
|
||||
with app.test_request_context("/workspaces/current/tool-providers?type=builtin"):
|
||||
api = controller_module.ToolProviderListApi()
|
||||
response = unwrap(api.get)(api, "tenant-456", user)
|
||||
response = controller_module.ToolProviderListApi().get()
|
||||
|
||||
assert response == [{"provider": "builtin"}]
|
||||
assert response == [expected_response]
|
||||
service_mock.assert_called_once_with(user.id, "tenant-456", "builtin")
|
||||
|
||||
|
||||
@ -108,8 +288,9 @@ def test_builtin_provider_add_passes_payload(
|
||||
app: Flask, controller_module: ModuleType, monkeypatch: pytest.MonkeyPatch
|
||||
):
|
||||
user = _mock_account()
|
||||
_set_current_account(monkeypatch, controller_module, user, "tenant-456")
|
||||
|
||||
service_mock = MagicMock(return_value={"status": "ok"})
|
||||
service_mock = MagicMock(return_value={"result": "success"})
|
||||
monkeypatch.setattr(controller_module.BuiltinToolManageService, "add_builtin_tool_provider", service_mock)
|
||||
|
||||
payload = {
|
||||
@ -123,10 +304,9 @@ def test_builtin_provider_add_passes_payload(
|
||||
method="POST",
|
||||
json=payload,
|
||||
):
|
||||
api = controller_module.ToolBuiltinProviderAddApi()
|
||||
response = unwrap(api.post)(api, "tenant-456", user, provider="openai")
|
||||
response = controller_module.ToolBuiltinProviderAddApi().post(provider="openai")
|
||||
|
||||
assert response == {"status": "ok"}
|
||||
assert response == {"result": "success"}
|
||||
service_mock.assert_called_once_with(
|
||||
user_id="user-123",
|
||||
tenant_id="tenant-456",
|
||||
@ -140,38 +320,88 @@ def test_builtin_provider_add_passes_payload(
|
||||
|
||||
def test_builtin_provider_tools_get(app: Flask, controller_module, monkeypatch: pytest.MonkeyPatch):
|
||||
user = _mock_account("user-tenant-789")
|
||||
_set_current_account(monkeypatch, controller_module, user, "tenant-789")
|
||||
|
||||
service_mock = MagicMock(return_value=[{"name": "tool-a"}])
|
||||
service_payload, expected_response = _tool_response(controller_module, "tool-a")
|
||||
service_mock = MagicMock(return_value=[service_payload])
|
||||
monkeypatch.setattr(controller_module.BuiltinToolManageService, "list_builtin_tool_provider_tools", service_mock)
|
||||
monkeypatch.setattr(controller_module, "jsonable_encoder", lambda payload: payload)
|
||||
|
||||
with app.test_request_context(
|
||||
"/workspaces/current/tool-provider/builtin/my-provider/tools",
|
||||
method="GET",
|
||||
):
|
||||
api = controller_module.ToolBuiltinProviderListToolsApi()
|
||||
response = unwrap(api.get)(api, "tenant-789", provider="my-provider")
|
||||
response = controller_module.ToolBuiltinProviderListToolsApi().get(provider="my-provider")
|
||||
|
||||
assert response == [{"name": "tool-a"}]
|
||||
assert response == [expected_response]
|
||||
service_mock.assert_called_once_with("tenant-789", "my-provider")
|
||||
|
||||
|
||||
def test_builtin_provider_info_get(app: Flask, controller_module, monkeypatch: pytest.MonkeyPatch):
|
||||
user = _mock_account("user-tenant-9")
|
||||
service_mock = MagicMock(return_value={"info": True})
|
||||
_set_current_account(monkeypatch, controller_module, user, "tenant-9")
|
||||
service_payload, expected_response = _provider_entity_response(controller_module, "demo", "builtin")
|
||||
service_mock = MagicMock(return_value=service_payload)
|
||||
monkeypatch.setattr(controller_module.BuiltinToolManageService, "get_builtin_tool_provider_info", service_mock)
|
||||
|
||||
with app.test_request_context("/info", method="GET"):
|
||||
api = controller_module.ToolBuiltinProviderInfoApi()
|
||||
resp = unwrap(api.get)(api, "tenant-9", provider="demo")
|
||||
resp = controller_module.ToolBuiltinProviderInfoApi().get(provider="demo")
|
||||
|
||||
assert resp == {"info": True}
|
||||
assert resp == expected_response
|
||||
service_mock.assert_called_once_with("tenant-9", "demo")
|
||||
|
||||
|
||||
def test_builtin_provider_info_uses_core_to_dict_tool_projection(
|
||||
app: Flask, controller_module: ModuleType, monkeypatch: pytest.MonkeyPatch
|
||||
):
|
||||
user = _mock_account("user-tenant-9")
|
||||
_set_current_account(monkeypatch, controller_module, user, "tenant-9")
|
||||
tool_parameter = ToolParameter(
|
||||
name="system_files",
|
||||
label=I18nObject(en_US="System Files", zh_Hans="System Files"),
|
||||
type=ToolParameter.ToolParameterType.SYSTEM_FILES,
|
||||
form=ToolParameter.ToolParameterForm.LLM,
|
||||
input_schema=None,
|
||||
)
|
||||
tool = controller_module.ToolApiEntity(
|
||||
author="Dify",
|
||||
name="demo-tool",
|
||||
label=I18nObject(en_US="Demo Tool", zh_Hans="Demo Tool"),
|
||||
description=I18nObject(en_US="Demo Tool description", zh_Hans="Demo Tool description"),
|
||||
parameters=[tool_parameter],
|
||||
labels=[],
|
||||
output_schema={},
|
||||
)
|
||||
provider = CoreToolProviderApiEntity(
|
||||
id="demo-id",
|
||||
author="Dify",
|
||||
name="demo",
|
||||
description=I18nObject(en_US="demo description", zh_Hans="demo description"),
|
||||
icon="tool.svg",
|
||||
label=I18nObject(en_US="demo", zh_Hans="demo"),
|
||||
type=controller_module.ToolProviderType.BUILT_IN,
|
||||
masked_credentials={"api_key": "[__HIDDEN__]"},
|
||||
original_credentials={"api_key": "sk-secret"},
|
||||
tools=[tool],
|
||||
)
|
||||
service_mock = MagicMock(return_value=provider)
|
||||
monkeypatch.setattr(controller_module.BuiltinToolManageService, "get_builtin_tool_provider_info", service_mock)
|
||||
|
||||
with app.test_request_context("/info", method="GET"):
|
||||
resp = controller_module.ToolBuiltinProviderInfoApi().get(provider="demo")
|
||||
|
||||
parameter = resp["tools"][0]["parameters"][0]
|
||||
assert parameter["type"] == "files"
|
||||
assert parameter["input_schema"] is None
|
||||
assert resp["team_credentials"] == {"api_key": "[__HIDDEN__]"}
|
||||
assert "masked_credentials" not in resp
|
||||
assert "original_credentials" not in resp
|
||||
|
||||
|
||||
def test_builtin_provider_credentials_get(app: Flask, controller_module, monkeypatch: pytest.MonkeyPatch):
|
||||
user = _mock_account("user-tenant-cred")
|
||||
service_mock = MagicMock(return_value=[{"cred": 1}])
|
||||
_set_current_account(monkeypatch, controller_module, user, "tenant-cred")
|
||||
service_payload, expected_response = _credential_response(controller_module)
|
||||
service_mock = MagicMock(return_value=[service_payload])
|
||||
monkeypatch.setattr(
|
||||
controller_module.BuiltinToolManageService,
|
||||
"get_builtin_tool_provider_credentials",
|
||||
@ -179,10 +409,9 @@ def test_builtin_provider_credentials_get(app: Flask, controller_module, monkeyp
|
||||
)
|
||||
|
||||
with app.test_request_context("/creds", method="GET"):
|
||||
api = controller_module.ToolBuiltinProviderGetCredentialsApi()
|
||||
resp = unwrap(api.get)(api, "tenant-cred", user, provider="demo")
|
||||
resp = controller_module.ToolBuiltinProviderGetCredentialsApi().get(provider="demo")
|
||||
|
||||
assert resp == [{"cred": 1}]
|
||||
assert resp == [expected_response]
|
||||
service_mock.assert_called_once_with(
|
||||
tenant_id="tenant-cred",
|
||||
provider_name="demo",
|
||||
@ -196,7 +425,8 @@ def test_builtin_provider_credentials_get_reads_repeated_include_ids(
|
||||
app: Flask, controller_module, monkeypatch: pytest.MonkeyPatch
|
||||
):
|
||||
user = _mock_account("user-tenant-cred")
|
||||
service_mock = MagicMock(return_value=[{"cred": 1}])
|
||||
credential_payload, expected = _credential_response(controller_module)
|
||||
service_mock = MagicMock(return_value=[credential_payload])
|
||||
monkeypatch.setattr(
|
||||
controller_module.BuiltinToolManageService,
|
||||
"get_builtin_tool_provider_credentials",
|
||||
@ -207,7 +437,7 @@ def test_builtin_provider_credentials_get_reads_repeated_include_ids(
|
||||
api = controller_module.ToolBuiltinProviderGetCredentialsApi()
|
||||
resp = unwrap(api.get)(api, "tenant-cred", user, provider="demo")
|
||||
|
||||
assert resp == [{"cred": 1}]
|
||||
assert resp == [expected]
|
||||
service_mock.assert_called_once_with(
|
||||
tenant_id="tenant-cred",
|
||||
provider_name="demo",
|
||||
@ -219,46 +449,51 @@ def test_builtin_provider_credentials_get_reads_repeated_include_ids(
|
||||
|
||||
def test_api_provider_remote_schema_get(app: Flask, controller_module, monkeypatch: pytest.MonkeyPatch):
|
||||
user = _mock_account()
|
||||
service_mock = MagicMock(return_value={"schema": "ok"})
|
||||
_set_current_account(monkeypatch, controller_module, user, "tenant-10")
|
||||
openapi_schema = '{"openapi":"3.0.0","info":{"title":"Demo API","version":"1.0.0"},"paths":{}}'
|
||||
service_mock = MagicMock(return_value={"schema": openapi_schema})
|
||||
monkeypatch.setattr(controller_module.ApiToolManageService, "get_api_tool_provider_remote_schema", service_mock)
|
||||
|
||||
with app.test_request_context("/remote?url=https://example.com/"):
|
||||
api = controller_module.ToolApiProviderGetRemoteSchemaApi()
|
||||
resp = unwrap(api.get)(api, "tenant-10", user)
|
||||
resp = controller_module.ToolApiProviderGetRemoteSchemaApi().get()
|
||||
|
||||
assert resp == {"schema": "ok"}
|
||||
assert resp == {"schema": openapi_schema}
|
||||
service_mock.assert_called_once_with(user.id, "tenant-10", "https://example.com/")
|
||||
|
||||
|
||||
def test_api_provider_list_tools_get(app: Flask, controller_module, monkeypatch: pytest.MonkeyPatch):
|
||||
user = _mock_account()
|
||||
service_mock = MagicMock(return_value=[{"tool": "t"}])
|
||||
_set_current_account(monkeypatch, controller_module, user, "tenant-11")
|
||||
service_payload, expected_response = _tool_response(controller_module, "t")
|
||||
service_mock = MagicMock(return_value=[service_payload])
|
||||
monkeypatch.setattr(controller_module.ApiToolManageService, "list_api_tool_provider_tools", service_mock)
|
||||
|
||||
with app.test_request_context("/tools?provider=foo"):
|
||||
api = controller_module.ToolApiProviderListToolsApi()
|
||||
resp = unwrap(api.get)(api, "tenant-11", user)
|
||||
resp = controller_module.ToolApiProviderListToolsApi().get()
|
||||
|
||||
assert resp == [{"tool": "t"}]
|
||||
assert resp == [expected_response]
|
||||
service_mock.assert_called_once_with(user.id, "tenant-11", "foo")
|
||||
|
||||
|
||||
def test_api_provider_get(app: Flask, controller_module, monkeypatch: pytest.MonkeyPatch):
|
||||
user = _mock_account()
|
||||
service_mock = MagicMock(return_value={"provider": "foo"})
|
||||
_set_current_account(monkeypatch, controller_module, user, "tenant-12")
|
||||
service_payload, expected_response = _api_provider_detail_response(controller_module)
|
||||
service_mock = MagicMock(return_value=service_payload)
|
||||
monkeypatch.setattr(controller_module.ApiToolManageService, "get_api_tool_provider", service_mock)
|
||||
|
||||
with app.test_request_context("/get?provider=foo"):
|
||||
api = controller_module.ToolApiProviderGetApi()
|
||||
resp = unwrap(api.get)(api, "tenant-12", user)
|
||||
resp = controller_module.ToolApiProviderGetApi().get()
|
||||
|
||||
assert resp == {"provider": "foo"}
|
||||
assert resp == expected_response
|
||||
service_mock.assert_called_once_with(user.id, "tenant-12", "foo")
|
||||
|
||||
|
||||
def test_builtin_provider_credentials_schema_get(app: Flask, controller_module, monkeypatch: pytest.MonkeyPatch):
|
||||
user = _mock_account("user-tenant-13")
|
||||
service_mock = MagicMock(return_value={"schema": True})
|
||||
_set_current_account(monkeypatch, controller_module, user, "tenant-13")
|
||||
service_payload, expected_response = _provider_config_response(controller_module)
|
||||
service_mock = MagicMock(return_value=[service_payload])
|
||||
monkeypatch.setattr(
|
||||
controller_module.BuiltinToolManageService,
|
||||
"list_builtin_provider_credentials_schema",
|
||||
@ -266,16 +501,19 @@ def test_builtin_provider_credentials_schema_get(app: Flask, controller_module,
|
||||
)
|
||||
|
||||
with app.test_request_context("/schema", method="GET"):
|
||||
api = controller_module.ToolBuiltinProviderCredentialsSchemaApi()
|
||||
resp = unwrap(api.get)(api, "tenant-13", provider="demo", credential_type="api-key")
|
||||
resp = controller_module.ToolBuiltinProviderCredentialsSchemaApi().get(
|
||||
provider="demo", credential_type="api-key"
|
||||
)
|
||||
|
||||
assert resp == {"schema": True}
|
||||
assert resp == [expected_response]
|
||||
service_mock.assert_called_once()
|
||||
|
||||
|
||||
def test_workflow_provider_get_by_tool(app: Flask, controller_module, monkeypatch: pytest.MonkeyPatch):
|
||||
user = _mock_account()
|
||||
tool_service = MagicMock(return_value={"wf": 1})
|
||||
_set_current_account(monkeypatch, controller_module, user, "tenant-wf")
|
||||
service_payload, expected_response = _workflow_detail_response(controller_module)
|
||||
tool_service = MagicMock(return_value=service_payload)
|
||||
monkeypatch.setattr(
|
||||
controller_module.WorkflowToolManageService,
|
||||
"get_workflow_tool_by_tool_id",
|
||||
@ -284,16 +522,17 @@ def test_workflow_provider_get_by_tool(app: Flask, controller_module, monkeypatc
|
||||
|
||||
tool_id = "00000000-0000-0000-0000-000000000001"
|
||||
with app.test_request_context(f"/workflow?workflow_tool_id={tool_id}"):
|
||||
api = controller_module.ToolWorkflowProviderGetApi()
|
||||
resp = unwrap(api.get)(api, "tenant-wf", user)
|
||||
resp = controller_module.ToolWorkflowProviderGetApi().get()
|
||||
|
||||
assert resp == {"wf": 1}
|
||||
assert resp == expected_response
|
||||
tool_service.assert_called_once_with(user.id, "tenant-wf", tool_id)
|
||||
|
||||
|
||||
def test_workflow_provider_get_by_app(app: Flask, controller_module, monkeypatch: pytest.MonkeyPatch):
|
||||
user = _mock_account()
|
||||
service_mock = MagicMock(return_value={"app": 1})
|
||||
_set_current_account(monkeypatch, controller_module, user, "tenant-wf2")
|
||||
service_payload, expected_response = _workflow_detail_response(controller_module)
|
||||
service_mock = MagicMock(return_value=service_payload)
|
||||
monkeypatch.setattr(
|
||||
controller_module.WorkflowToolManageService,
|
||||
"get_workflow_tool_by_app_id",
|
||||
@ -302,31 +541,32 @@ def test_workflow_provider_get_by_app(app: Flask, controller_module, monkeypatch
|
||||
|
||||
app_id = "00000000-0000-0000-0000-000000000002"
|
||||
with app.test_request_context(f"/workflow?workflow_app_id={app_id}"):
|
||||
api = controller_module.ToolWorkflowProviderGetApi()
|
||||
resp = unwrap(api.get)(api, "tenant-wf2", user)
|
||||
resp = controller_module.ToolWorkflowProviderGetApi().get()
|
||||
|
||||
assert resp == {"app": 1}
|
||||
assert resp == expected_response
|
||||
service_mock.assert_called_once_with(user.id, "tenant-wf2", app_id)
|
||||
|
||||
|
||||
def test_workflow_provider_list_tools(app: Flask, controller_module, monkeypatch: pytest.MonkeyPatch):
|
||||
user = _mock_account()
|
||||
service_mock = MagicMock(return_value=[{"id": 1}])
|
||||
_set_current_account(monkeypatch, controller_module, user, "tenant-wf3")
|
||||
service_payload, expected_response = _tool_response(controller_module, "workflow-tool")
|
||||
service_mock = MagicMock(return_value=[service_payload])
|
||||
monkeypatch.setattr(controller_module.WorkflowToolManageService, "list_single_workflow_tools", service_mock)
|
||||
|
||||
tool_id = "00000000-0000-0000-0000-000000000003"
|
||||
with app.test_request_context(f"/workflow/tools?workflow_tool_id={tool_id}"):
|
||||
api = controller_module.ToolWorkflowProviderListToolApi()
|
||||
resp = unwrap(api.get)(api, "tenant-wf3", user)
|
||||
resp = controller_module.ToolWorkflowProviderListToolApi().get()
|
||||
|
||||
assert resp == [{"id": 1}]
|
||||
assert resp == [expected_response]
|
||||
service_mock.assert_called_once_with(user.id, "tenant-wf3", tool_id)
|
||||
|
||||
|
||||
def test_builtin_tools_list(app: Flask, controller_module, monkeypatch: pytest.MonkeyPatch):
|
||||
user = _mock_account()
|
||||
_set_current_account(monkeypatch, controller_module, user, "tenant-bt")
|
||||
|
||||
provider = SimpleNamespace(to_dict=lambda: {"name": "builtin"})
|
||||
provider, expected_response = _provider_entity_response(controller_module, "builtin", "builtin")
|
||||
monkeypatch.setattr(
|
||||
controller_module.BuiltinToolManageService,
|
||||
"list_builtin_tools",
|
||||
@ -334,16 +574,16 @@ def test_builtin_tools_list(app: Flask, controller_module, monkeypatch: pytest.M
|
||||
)
|
||||
|
||||
with app.test_request_context("/tools/builtin"):
|
||||
api = controller_module.ToolBuiltinListApi()
|
||||
resp = unwrap(api.get)(api, "tenant-bt", user)
|
||||
resp = controller_module.ToolBuiltinListApi().get()
|
||||
|
||||
assert resp == [{"name": "builtin"}]
|
||||
assert resp == [expected_response]
|
||||
|
||||
|
||||
def test_api_tools_list(app: Flask, controller_module, monkeypatch: pytest.MonkeyPatch):
|
||||
user = _mock_account("user-tenant-api")
|
||||
_set_current_account(monkeypatch, controller_module, user, "tenant-api")
|
||||
|
||||
provider = SimpleNamespace(to_dict=lambda: {"name": "api"})
|
||||
provider, expected_response = _provider_entity_response(controller_module, "api", "api")
|
||||
monkeypatch.setattr(
|
||||
controller_module.ApiToolManageService,
|
||||
"list_api_tools",
|
||||
@ -351,16 +591,16 @@ def test_api_tools_list(app: Flask, controller_module, monkeypatch: pytest.Monke
|
||||
)
|
||||
|
||||
with app.test_request_context("/tools/api"):
|
||||
api = controller_module.ToolApiListApi()
|
||||
resp = unwrap(api.get)(api, "tenant-api")
|
||||
resp = controller_module.ToolApiListApi().get()
|
||||
|
||||
assert resp == [{"name": "api"}]
|
||||
assert resp == [expected_response]
|
||||
|
||||
|
||||
def test_workflow_tools_list(app: Flask, controller_module, monkeypatch: pytest.MonkeyPatch):
|
||||
user = _mock_account()
|
||||
_set_current_account(monkeypatch, controller_module, user, "tenant-wf4")
|
||||
|
||||
provider = SimpleNamespace(to_dict=lambda: {"name": "wf"})
|
||||
provider, expected_response = _provider_entity_response(controller_module, "wf", "workflow")
|
||||
monkeypatch.setattr(
|
||||
controller_module.WorkflowToolManageService,
|
||||
"list_tenant_workflow_tools",
|
||||
@ -368,20 +608,21 @@ def test_workflow_tools_list(app: Flask, controller_module, monkeypatch: pytest.
|
||||
)
|
||||
|
||||
with app.test_request_context("/tools/workflow"):
|
||||
api = controller_module.ToolWorkflowListApi()
|
||||
resp = unwrap(api.get)(api, "tenant-wf4", user)
|
||||
resp = controller_module.ToolWorkflowListApi().get()
|
||||
|
||||
assert resp == [{"name": "wf"}]
|
||||
assert resp == [expected_response]
|
||||
|
||||
|
||||
def test_tool_labels_list(app: Flask, controller_module, monkeypatch: pytest.MonkeyPatch):
|
||||
monkeypatch.setattr(controller_module.ToolLabelsService, "list_tool_labels", lambda: ["a", "b"])
|
||||
user = _mock_account("user-label")
|
||||
_set_current_account(monkeypatch, controller_module, user, "tenant-labels")
|
||||
service_payload, expected_response = _tool_label_response(controller_module, "a")
|
||||
monkeypatch.setattr(controller_module.ToolLabelsService, "list_tool_labels", lambda: [service_payload])
|
||||
|
||||
with app.test_request_context("/tool-labels"):
|
||||
api = controller_module.ToolLabelsApi()
|
||||
resp = unwrap(api.get)(api)
|
||||
resp = controller_module.ToolLabelsApi().get()
|
||||
|
||||
assert resp == ["a", "b"]
|
||||
assert resp == [expected_response]
|
||||
|
||||
|
||||
# --- _resolve_identity_mode: gating + None-resolution (PR #36839 review) ---
|
||||
|
||||
@ -1009,8 +1009,7 @@ class TestExternalDatasetApi:
|
||||
# 4. Provide default values when parameters are missing
|
||||
# 5. Raise BadRequest exceptions when validation fails
|
||||
#
|
||||
# Response formatting is handled by Flask-RESTX's marshal_with decorator
|
||||
# or marshal function, which:
|
||||
# Response formatting is handled by controller response schemas, which:
|
||||
#
|
||||
# 1. Formats response data according to defined models
|
||||
# 2. Handles nested objects and lists
|
||||
|
||||
@ -145,7 +145,7 @@ export const zGetOauthPluginByProviderToolAuthorizationUrlPath = z.object({
|
||||
})
|
||||
|
||||
/**
|
||||
* Authorization URL retrieved successfully
|
||||
* Tool OAuth authorization URL generated successfully
|
||||
*/
|
||||
export const zGetOauthPluginByProviderToolAuthorizationUrlResponse
|
||||
= zPluginOAuthAuthorizationUrlResponse
|
||||
|
||||
@ -4,7 +4,15 @@ export type ClientOptions = {
|
||||
baseUrl: `${string}://${string}/console/api` | (string & {})
|
||||
}
|
||||
|
||||
export type SchemaDefinitionsResponse = unknown
|
||||
export type SchemaDefinitionsResponse = Array<SchemaDefinitionItemResponse>
|
||||
|
||||
export type SchemaDefinitionItemResponse = {
|
||||
label: string
|
||||
name: string
|
||||
schema: {
|
||||
[key: string]: unknown
|
||||
}
|
||||
}
|
||||
|
||||
export type GetSpecSchemaDefinitionsData = {
|
||||
body?: never
|
||||
|
||||
@ -2,10 +2,19 @@
|
||||
|
||||
import * as z from 'zod'
|
||||
|
||||
/**
|
||||
* SchemaDefinitionItemResponse
|
||||
*/
|
||||
export const zSchemaDefinitionItemResponse = z.object({
|
||||
label: z.string(),
|
||||
name: z.string(),
|
||||
schema: z.record(z.string(), z.unknown()),
|
||||
})
|
||||
|
||||
/**
|
||||
* SchemaDefinitionsResponse
|
||||
*/
|
||||
export const zSchemaDefinitionsResponse = z.unknown()
|
||||
export const zSchemaDefinitionsResponse = z.array(zSchemaDefinitionItemResponse)
|
||||
|
||||
/**
|
||||
* Success
|
||||
|
||||
@ -609,16 +609,14 @@ export type WorkspaceAccessMatrix = {
|
||||
pagination?: Pagination | null
|
||||
}
|
||||
|
||||
export type ToolProviderOpaqueResponse = unknown
|
||||
export type ToolLabelListResponse = Array<ToolLabel>
|
||||
|
||||
export type ApiToolProviderAddPayload = {
|
||||
credentials: {
|
||||
[key: string]: unknown
|
||||
}
|
||||
custom_disclaimer?: string
|
||||
icon: {
|
||||
[key: string]: unknown
|
||||
}
|
||||
icon: ToolEmojiIcon
|
||||
labels?: Array<string> | null
|
||||
privacy_policy?: string | null
|
||||
provider: string
|
||||
@ -630,10 +628,37 @@ export type ApiToolProviderDeletePayload = {
|
||||
provider: string
|
||||
}
|
||||
|
||||
export type ApiProviderDetailResponse = {
|
||||
credentials?: {
|
||||
[key: string]: unknown
|
||||
}
|
||||
custom_disclaimer?: string | null
|
||||
description?: string | null
|
||||
icon: ToolEmojiIcon
|
||||
labels?: Array<string>
|
||||
privacy_policy?: string | null
|
||||
schema: string
|
||||
schema_type: ApiProviderSchemaType
|
||||
tools: Array<ApiToolBundle>
|
||||
}
|
||||
|
||||
export type ApiProviderRemoteSchemaResponse = {
|
||||
schema: string
|
||||
}
|
||||
|
||||
export type ApiToolSchemaPayload = {
|
||||
schema: string
|
||||
}
|
||||
|
||||
export type ApiSchemaParseResponse = {
|
||||
credentials_schema: Array<ProviderConfig>
|
||||
parameters_schema: Array<ApiToolBundle>
|
||||
schema_type: ApiProviderSchemaType
|
||||
warning: {
|
||||
[key: string]: string
|
||||
}
|
||||
}
|
||||
|
||||
export type ApiToolTestPayload = {
|
||||
credentials: {
|
||||
[key: string]: unknown
|
||||
@ -647,14 +672,16 @@ export type ApiToolTestPayload = {
|
||||
tool_name: string
|
||||
}
|
||||
|
||||
export type ApiToolPreviewResponse = ApiToolPreviewResult
|
||||
|
||||
export type ToolApiListResponse = Array<ToolApiEntity>
|
||||
|
||||
export type ApiToolProviderUpdatePayload = {
|
||||
credentials: {
|
||||
[key: string]: unknown
|
||||
}
|
||||
custom_disclaimer?: string
|
||||
icon: {
|
||||
[key: string]: unknown
|
||||
}
|
||||
icon: ToolEmojiIcon
|
||||
labels?: Array<string> | null
|
||||
original_provider: string
|
||||
privacy_policy?: string | null
|
||||
@ -672,6 +699,16 @@ export type BuiltinToolAddPayload = {
|
||||
visibility?: string | null
|
||||
}
|
||||
|
||||
export type ToolProviderCredentialInfoApiEntity = {
|
||||
credentials: Array<ToolProviderCredentialApiEntity>
|
||||
is_oauth_custom_client_enabled?: boolean
|
||||
supported_credential_types: Array<CredentialType>
|
||||
}
|
||||
|
||||
export type ProviderConfigListResponse = Array<ProviderConfig>
|
||||
|
||||
export type ToolProviderCredentialListResponse = Array<ToolProviderCredentialApiEntity>
|
||||
|
||||
export type BuiltinProviderDefaultCredentialPayload = {
|
||||
id: string
|
||||
}
|
||||
@ -680,12 +717,56 @@ export type BuiltinToolCredentialDeletePayload = {
|
||||
credential_id: string
|
||||
}
|
||||
|
||||
export type ToolOAuthClientSchemaResponse = Array<{
|
||||
[key: string]: unknown
|
||||
}>
|
||||
export type ToolProviderApiEntityResponse = {
|
||||
allow_delete?: boolean
|
||||
authentication?: McpAuthentication | null
|
||||
author: string
|
||||
configuration?: McpConfiguration | null
|
||||
description: I18nObject
|
||||
icon:
|
||||
| string
|
||||
| {
|
||||
[key: string]: string
|
||||
}
|
||||
icon_dark?:
|
||||
| string
|
||||
| {
|
||||
[key: string]: string
|
||||
}
|
||||
id: string
|
||||
identity_mode?: string
|
||||
is_dynamic_registration?: boolean
|
||||
is_team_authorization?: boolean
|
||||
label: I18nObject
|
||||
labels?: Array<string>
|
||||
masked_headers?: {
|
||||
[key: string]: string
|
||||
} | null
|
||||
name: string
|
||||
original_headers?: {
|
||||
[key: string]: string
|
||||
} | null
|
||||
plugin_id?: string | null
|
||||
plugin_unique_identifier?: string | null
|
||||
server_identifier?: string | null
|
||||
server_url?: string | null
|
||||
team_credentials?: {
|
||||
[key: string]: unknown
|
||||
}
|
||||
tools?: Array<ToolApiEntity>
|
||||
type: ToolProviderType
|
||||
updated_at?: number
|
||||
workflow_app_id?: string | null
|
||||
}
|
||||
|
||||
export type ToolOAuthCustomClientResponse = {
|
||||
[key: string]: unknown
|
||||
export type BuiltinProviderOAuthClientSchemaResponse = {
|
||||
client_params?: {
|
||||
[key: string]: unknown
|
||||
} | null
|
||||
is_oauth_custom_client_enabled: boolean
|
||||
is_system_oauth_params_exists: boolean
|
||||
redirect_uri: string
|
||||
schema: Array<ProviderConfig>
|
||||
}
|
||||
|
||||
export type ToolOAuthCustomClientPayload = {
|
||||
@ -708,14 +789,10 @@ export type McpProviderDeletePayload = {
|
||||
}
|
||||
|
||||
export type McpProviderCreatePayload = {
|
||||
authentication?: {
|
||||
[key: string]: unknown
|
||||
} | null
|
||||
configuration?: {
|
||||
[key: string]: unknown
|
||||
} | null
|
||||
authentication?: McpAuthentication | null
|
||||
configuration?: McpConfiguration | null
|
||||
headers?: {
|
||||
[key: string]: unknown
|
||||
[key: string]: string
|
||||
} | null
|
||||
icon: string
|
||||
icon_background?: string
|
||||
@ -727,14 +804,10 @@ export type McpProviderCreatePayload = {
|
||||
}
|
||||
|
||||
export type McpProviderUpdatePayload = {
|
||||
authentication?: {
|
||||
[key: string]: unknown
|
||||
} | null
|
||||
configuration?: {
|
||||
[key: string]: unknown
|
||||
} | null
|
||||
authentication?: McpAuthentication | null
|
||||
configuration?: McpConfiguration | null
|
||||
headers?: {
|
||||
[key: string]: unknown
|
||||
[key: string]: string
|
||||
} | null
|
||||
icon: string
|
||||
icon_background?: string
|
||||
@ -751,11 +824,14 @@ export type McpAuthPayload = {
|
||||
provider_id: string
|
||||
}
|
||||
|
||||
export type McpAuthResponse = {
|
||||
authorization_url?: string | null
|
||||
result?: 'success' | null
|
||||
}
|
||||
|
||||
export type WorkflowToolCreatePayload = {
|
||||
description: string
|
||||
icon: {
|
||||
[key: string]: unknown
|
||||
}
|
||||
icon: ToolEmojiIcon
|
||||
label: string
|
||||
labels?: Array<string> | null
|
||||
name: string
|
||||
@ -768,11 +844,25 @@ export type WorkflowToolDeletePayload = {
|
||||
workflow_tool_id: string
|
||||
}
|
||||
|
||||
export type WorkflowToolUpdatePayload = {
|
||||
export type WorkflowToolDetailResponse = {
|
||||
description: string
|
||||
icon: {
|
||||
icon: ToolEmojiIcon
|
||||
label: string
|
||||
name: string
|
||||
output_schema?: {
|
||||
[key: string]: unknown
|
||||
}
|
||||
parameters: Array<WorkflowToolParameterConfiguration>
|
||||
privacy_policy?: string | null
|
||||
synced: boolean
|
||||
tool: ToolApiEntity
|
||||
workflow_app_id: string
|
||||
workflow_tool_id: string
|
||||
}
|
||||
|
||||
export type WorkflowToolUpdatePayload = {
|
||||
description: string
|
||||
icon: ToolEmojiIcon
|
||||
label: string
|
||||
labels?: Array<string> | null
|
||||
name: string
|
||||
@ -781,6 +871,8 @@ export type WorkflowToolUpdatePayload = {
|
||||
workflow_tool_id: string
|
||||
}
|
||||
|
||||
export type ToolProviderListResponse = Array<ToolProviderApiEntityResponse>
|
||||
|
||||
export type TriggerProviderApiEntity = {
|
||||
author: string
|
||||
description: I18nObject
|
||||
@ -801,7 +893,7 @@ export type TriggerOAuthClientResponse = {
|
||||
configured: boolean
|
||||
custom_configured: boolean
|
||||
custom_enabled: boolean
|
||||
oauth_client_schema: Array<TriggerProviderConfigResponse>
|
||||
oauth_client_schema: Array<ProviderConfig>
|
||||
params: {
|
||||
[key: string]: unknown
|
||||
}
|
||||
@ -829,8 +921,6 @@ export type TriggerSubscriptionBuilderUpdatePayload = {
|
||||
} | null
|
||||
}
|
||||
|
||||
export type TriggerProviderOpaqueResponse = unknown
|
||||
|
||||
export type TriggerSubscriptionBuilderCreatePayload = {
|
||||
credential_type?: string
|
||||
}
|
||||
@ -866,11 +956,15 @@ export type TriggerSubscriptionBuilderVerifyPayload = {
|
||||
}
|
||||
}
|
||||
|
||||
export type TriggerSubscriptionBuilderVerifyResponse = {
|
||||
export type TriggerVerificationResponse = {
|
||||
verified: boolean
|
||||
}
|
||||
|
||||
export type TriggerSubscriptionListResponse = Array<TriggerProviderSubscriptionApiEntity>
|
||||
export type TriggerProviderSubscriptionListResponse = Array<TriggerProviderSubscriptionApiEntity>
|
||||
|
||||
export type TriggerProviderErrorResponse = {
|
||||
error: string
|
||||
}
|
||||
|
||||
export type TriggerOAuthAuthorizeResponse = {
|
||||
authorization_url: string
|
||||
@ -1294,16 +1388,91 @@ export type AccessPolicyRole = {
|
||||
role_tag?: string
|
||||
}
|
||||
|
||||
export type ToolLabel = {
|
||||
icon: string
|
||||
label: I18nObject
|
||||
name: string
|
||||
}
|
||||
|
||||
export type ToolEmojiIcon = {
|
||||
background: string
|
||||
content: string
|
||||
}
|
||||
|
||||
export type ApiProviderSchemaType = 'openai_actions' | 'openai_plugin' | 'openapi' | 'swagger'
|
||||
|
||||
export type ApiToolBundle = {
|
||||
author: string
|
||||
icon?: string | null
|
||||
method: string
|
||||
openapi: {
|
||||
[key: string]: unknown
|
||||
}
|
||||
operation_id?: string | null
|
||||
output_schema?: {
|
||||
[key: string]: unknown
|
||||
}
|
||||
parameters?: Array<ToolParameter> | null
|
||||
server_url: string
|
||||
summary?: string | null
|
||||
}
|
||||
|
||||
export type ProviderConfig = {
|
||||
default?: number | string | number | boolean | null
|
||||
help?: I18nObject | null
|
||||
label?: I18nObject | null
|
||||
multiple?: boolean
|
||||
name: string
|
||||
options?: Array<Option> | null
|
||||
placeholder?: I18nObject | null
|
||||
required?: boolean
|
||||
scope?: AppSelectorScope | ModelSelectorScope | ToolSelectorScope | null
|
||||
type: ProviderConfigType
|
||||
url?: string | null
|
||||
}
|
||||
|
||||
export type ApiToolPreviewResult = {
|
||||
error?: string
|
||||
result?: string
|
||||
}
|
||||
|
||||
export type ToolApiEntity = {
|
||||
author: string
|
||||
description: I18nObject
|
||||
label: I18nObject
|
||||
labels?: Array<string>
|
||||
name: string
|
||||
output_schema?: {
|
||||
[key: string]: unknown
|
||||
}
|
||||
parameters?: Array<ToolParameter> | null
|
||||
}
|
||||
|
||||
export type CredentialType = 'api-key' | 'oauth2' | 'unauthorized'
|
||||
|
||||
export type IdentityMode = 'idp_token' | 'off'
|
||||
|
||||
export type WorkflowToolParameterConfiguration = {
|
||||
description: string
|
||||
form: ToolParameterForm
|
||||
export type ToolProviderCredentialApiEntity = {
|
||||
created_by?: string
|
||||
credential_type: CredentialType
|
||||
credentials?: {
|
||||
[key: string]: unknown
|
||||
}
|
||||
from_other_member?: boolean
|
||||
id: string
|
||||
is_default?: boolean
|
||||
name: string
|
||||
partial_member_list?: Array<string>
|
||||
provider: string
|
||||
visibility?: string
|
||||
}
|
||||
|
||||
export type McpAuthentication = {
|
||||
client_id: string
|
||||
client_secret?: string | null
|
||||
}
|
||||
|
||||
export type McpConfiguration = {
|
||||
sse_read_timeout?: number
|
||||
timeout?: number
|
||||
}
|
||||
|
||||
export type I18nObject = {
|
||||
@ -1313,6 +1482,23 @@ export type I18nObject = {
|
||||
zh_Hans?: string | null
|
||||
}
|
||||
|
||||
export type ToolProviderType
|
||||
= | 'api'
|
||||
| 'app'
|
||||
| 'builtin'
|
||||
| 'dataset-retrieval'
|
||||
| 'mcp'
|
||||
| 'plugin'
|
||||
| 'workflow'
|
||||
|
||||
export type IdentityMode = 'idp_token' | 'off'
|
||||
|
||||
export type WorkflowToolParameterConfiguration = {
|
||||
description: string
|
||||
form: ToolParameterForm
|
||||
name: string
|
||||
}
|
||||
|
||||
export type EventApiEntity = {
|
||||
description: I18nObject
|
||||
identity: EventIdentity
|
||||
@ -1329,43 +1515,8 @@ export type SubscriptionConstructor = {
|
||||
parameters?: Array<EventParameter>
|
||||
}
|
||||
|
||||
export type ProviderConfig = {
|
||||
default?: number | string | number | boolean | null
|
||||
help?: I18nObject | null
|
||||
label?: I18nObject | null
|
||||
multiple?: boolean
|
||||
name: string
|
||||
options?: Array<Option> | null
|
||||
placeholder?: I18nObject | null
|
||||
required?: boolean
|
||||
scope?: AppSelectorScope | ModelSelectorScope | ToolSelectorScope | null
|
||||
type: ProviderConfigType
|
||||
url?: string | null
|
||||
}
|
||||
|
||||
export type TriggerCreationMethod = 'APIKEY' | 'MANUAL' | 'OAUTH'
|
||||
|
||||
export type TriggerProviderConfigResponse = {
|
||||
default?: number | string | number | boolean | null
|
||||
help?: I18nObject | null
|
||||
label?: I18nObject | null
|
||||
multiple?: boolean
|
||||
name: string
|
||||
options?: Array<TriggerProviderConfigOptionResponse> | null
|
||||
placeholder?: I18nObject | null
|
||||
required?: boolean
|
||||
scope?: AppSelectorScope | ModelSelectorScope | ToolSelectorScope | null
|
||||
type:
|
||||
| 'app-selector'
|
||||
| 'array[tools]'
|
||||
| 'boolean'
|
||||
| 'model-selector'
|
||||
| 'secret-input'
|
||||
| 'select'
|
||||
| 'text-input'
|
||||
url?: string | null
|
||||
}
|
||||
|
||||
export type RequestLog = {
|
||||
created_at: string
|
||||
endpoint: string
|
||||
@ -1591,15 +1742,6 @@ export type PluginCategoryBuiltinToolResponse = {
|
||||
[key: string]: unknown
|
||||
}
|
||||
|
||||
export type ToolProviderType
|
||||
= | 'api'
|
||||
| 'app'
|
||||
| 'builtin'
|
||||
| 'dataset-retrieval'
|
||||
| 'mcp'
|
||||
| 'plugin'
|
||||
| 'workflow'
|
||||
|
||||
export type RbacRoleAccount = {
|
||||
account_id: string
|
||||
account_name?: string
|
||||
@ -1618,6 +1760,64 @@ export type PermissionCatalogItem = {
|
||||
name: string
|
||||
}
|
||||
|
||||
export type ToolParameter = {
|
||||
auto_generate?: PluginParameterAutoGenerate | null
|
||||
default?:
|
||||
| number
|
||||
| number
|
||||
| string
|
||||
| boolean
|
||||
| Array<unknown>
|
||||
| {
|
||||
[key: string]: unknown
|
||||
}
|
||||
| null
|
||||
form: ToolParameterForm
|
||||
human_description?: I18nObject | null
|
||||
input_schema?: {
|
||||
[key: string]: unknown
|
||||
} | null
|
||||
label: I18nObject
|
||||
llm_description?: string | null
|
||||
max?: number | number | null
|
||||
min?: number | number | null
|
||||
name: string
|
||||
options?: Array<PluginParameterOption>
|
||||
placeholder?: I18nObject | null
|
||||
precision?: number | null
|
||||
required?: boolean
|
||||
scope?: string | null
|
||||
template?: PluginParameterTemplate | null
|
||||
type: ToolParameterType
|
||||
}
|
||||
|
||||
export type Option = {
|
||||
label: I18nObject
|
||||
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 ProviderConfigType
|
||||
= | 'app-selector'
|
||||
| 'array[tools]'
|
||||
| 'boolean'
|
||||
| 'model-selector'
|
||||
| 'secret-input'
|
||||
| 'select'
|
||||
| 'text-input'
|
||||
|
||||
export type ToolParameterForm = 'form' | 'llm' | 'schema'
|
||||
|
||||
export type EventIdentity = {
|
||||
@ -1649,38 +1849,6 @@ export type OAuthSchema = {
|
||||
credentials_schema?: Array<ProviderConfig>
|
||||
}
|
||||
|
||||
export type Option = {
|
||||
label: I18nObject
|
||||
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 ProviderConfigType
|
||||
= | 'app-selector'
|
||||
| 'array[tools]'
|
||||
| 'boolean'
|
||||
| 'model-selector'
|
||||
| 'secret-input'
|
||||
| 'select'
|
||||
| 'text-input'
|
||||
|
||||
export type TriggerProviderConfigOptionResponse = {
|
||||
label: I18nObject
|
||||
value: string
|
||||
}
|
||||
|
||||
export type AiModelEntityResponse = {
|
||||
deprecated?: boolean
|
||||
features?: Array<ModelFeature> | null
|
||||
@ -1801,6 +1969,23 @@ export type PluginParameterTemplate = {
|
||||
enabled?: boolean
|
||||
}
|
||||
|
||||
export type ToolParameterType
|
||||
= | 'any'
|
||||
| 'app-selector'
|
||||
| 'array'
|
||||
| 'boolean'
|
||||
| 'checkbox'
|
||||
| 'dynamic-select'
|
||||
| 'file'
|
||||
| 'files'
|
||||
| 'model-selector'
|
||||
| 'number'
|
||||
| 'object'
|
||||
| 'secret-input'
|
||||
| 'select'
|
||||
| 'string'
|
||||
| 'system-files'
|
||||
|
||||
export type EventParameterType
|
||||
= | 'app-selector'
|
||||
| 'array'
|
||||
@ -4099,7 +4284,7 @@ export type GetWorkspacesCurrentToolLabelsData = {
|
||||
}
|
||||
|
||||
export type GetWorkspacesCurrentToolLabelsResponses = {
|
||||
200: ToolProviderOpaqueResponse
|
||||
200: ToolLabelListResponse
|
||||
}
|
||||
|
||||
export type GetWorkspacesCurrentToolLabelsResponse
|
||||
@ -4113,7 +4298,7 @@ export type PostWorkspacesCurrentToolProviderApiAddData = {
|
||||
}
|
||||
|
||||
export type PostWorkspacesCurrentToolProviderApiAddResponses = {
|
||||
200: ToolProviderOpaqueResponse
|
||||
200: SimpleResultResponse
|
||||
}
|
||||
|
||||
export type PostWorkspacesCurrentToolProviderApiAddResponse
|
||||
@ -4127,7 +4312,7 @@ export type PostWorkspacesCurrentToolProviderApiDeleteData = {
|
||||
}
|
||||
|
||||
export type PostWorkspacesCurrentToolProviderApiDeleteResponses = {
|
||||
200: ToolProviderOpaqueResponse
|
||||
200: SimpleResultResponse
|
||||
}
|
||||
|
||||
export type PostWorkspacesCurrentToolProviderApiDeleteResponse
|
||||
@ -4143,7 +4328,7 @@ export type GetWorkspacesCurrentToolProviderApiGetData = {
|
||||
}
|
||||
|
||||
export type GetWorkspacesCurrentToolProviderApiGetResponses = {
|
||||
200: ToolProviderOpaqueResponse
|
||||
200: ApiProviderDetailResponse
|
||||
}
|
||||
|
||||
export type GetWorkspacesCurrentToolProviderApiGetResponse
|
||||
@ -4159,7 +4344,7 @@ export type GetWorkspacesCurrentToolProviderApiRemoteData = {
|
||||
}
|
||||
|
||||
export type GetWorkspacesCurrentToolProviderApiRemoteResponses = {
|
||||
200: ToolProviderOpaqueResponse
|
||||
200: ApiProviderRemoteSchemaResponse
|
||||
}
|
||||
|
||||
export type GetWorkspacesCurrentToolProviderApiRemoteResponse
|
||||
@ -4173,7 +4358,7 @@ export type PostWorkspacesCurrentToolProviderApiSchemaData = {
|
||||
}
|
||||
|
||||
export type PostWorkspacesCurrentToolProviderApiSchemaResponses = {
|
||||
200: ToolProviderOpaqueResponse
|
||||
200: ApiSchemaParseResponse
|
||||
}
|
||||
|
||||
export type PostWorkspacesCurrentToolProviderApiSchemaResponse
|
||||
@ -4187,7 +4372,7 @@ export type PostWorkspacesCurrentToolProviderApiTestPreData = {
|
||||
}
|
||||
|
||||
export type PostWorkspacesCurrentToolProviderApiTestPreResponses = {
|
||||
200: ToolProviderOpaqueResponse
|
||||
200: ApiToolPreviewResponse
|
||||
}
|
||||
|
||||
export type PostWorkspacesCurrentToolProviderApiTestPreResponse
|
||||
@ -4203,7 +4388,7 @@ export type GetWorkspacesCurrentToolProviderApiToolsData = {
|
||||
}
|
||||
|
||||
export type GetWorkspacesCurrentToolProviderApiToolsResponses = {
|
||||
200: ToolProviderOpaqueResponse
|
||||
200: ToolApiListResponse
|
||||
}
|
||||
|
||||
export type GetWorkspacesCurrentToolProviderApiToolsResponse
|
||||
@ -4217,7 +4402,7 @@ export type PostWorkspacesCurrentToolProviderApiUpdateData = {
|
||||
}
|
||||
|
||||
export type PostWorkspacesCurrentToolProviderApiUpdateResponses = {
|
||||
200: ToolProviderOpaqueResponse
|
||||
200: SimpleResultResponse
|
||||
}
|
||||
|
||||
export type PostWorkspacesCurrentToolProviderApiUpdateResponse
|
||||
@ -4233,7 +4418,7 @@ export type PostWorkspacesCurrentToolProviderBuiltinByProviderAddData = {
|
||||
}
|
||||
|
||||
export type PostWorkspacesCurrentToolProviderBuiltinByProviderAddResponses = {
|
||||
200: ToolProviderOpaqueResponse
|
||||
200: SimpleResultResponse
|
||||
}
|
||||
|
||||
export type PostWorkspacesCurrentToolProviderBuiltinByProviderAddResponse
|
||||
@ -4251,7 +4436,7 @@ export type GetWorkspacesCurrentToolProviderBuiltinByProviderCredentialInfoData
|
||||
}
|
||||
|
||||
export type GetWorkspacesCurrentToolProviderBuiltinByProviderCredentialInfoResponses = {
|
||||
200: ToolProviderOpaqueResponse
|
||||
200: ToolProviderCredentialInfoApiEntity
|
||||
}
|
||||
|
||||
export type GetWorkspacesCurrentToolProviderBuiltinByProviderCredentialInfoResponse
|
||||
@ -4270,7 +4455,7 @@ export type GetWorkspacesCurrentToolProviderBuiltinByProviderCredentialSchemaByC
|
||||
|
||||
export type GetWorkspacesCurrentToolProviderBuiltinByProviderCredentialSchemaByCredentialTypeResponses
|
||||
= {
|
||||
200: ToolProviderOpaqueResponse
|
||||
200: ProviderConfigListResponse
|
||||
}
|
||||
|
||||
export type GetWorkspacesCurrentToolProviderBuiltinByProviderCredentialSchemaByCredentialTypeResponse
|
||||
@ -4288,7 +4473,7 @@ export type GetWorkspacesCurrentToolProviderBuiltinByProviderCredentialsData = {
|
||||
}
|
||||
|
||||
export type GetWorkspacesCurrentToolProviderBuiltinByProviderCredentialsResponses = {
|
||||
200: ToolProviderOpaqueResponse
|
||||
200: ToolProviderCredentialListResponse
|
||||
}
|
||||
|
||||
export type GetWorkspacesCurrentToolProviderBuiltinByProviderCredentialsResponse
|
||||
@ -4304,7 +4489,7 @@ export type PostWorkspacesCurrentToolProviderBuiltinByProviderDefaultCredentialD
|
||||
}
|
||||
|
||||
export type PostWorkspacesCurrentToolProviderBuiltinByProviderDefaultCredentialResponses = {
|
||||
200: ToolProviderOpaqueResponse
|
||||
200: SimpleResultResponse
|
||||
}
|
||||
|
||||
export type PostWorkspacesCurrentToolProviderBuiltinByProviderDefaultCredentialResponse
|
||||
@ -4320,7 +4505,7 @@ export type PostWorkspacesCurrentToolProviderBuiltinByProviderDeleteData = {
|
||||
}
|
||||
|
||||
export type PostWorkspacesCurrentToolProviderBuiltinByProviderDeleteResponses = {
|
||||
200: ToolProviderOpaqueResponse
|
||||
200: SimpleResultResponse
|
||||
}
|
||||
|
||||
export type PostWorkspacesCurrentToolProviderBuiltinByProviderDeleteResponse
|
||||
@ -4336,7 +4521,9 @@ export type GetWorkspacesCurrentToolProviderBuiltinByProviderIconData = {
|
||||
}
|
||||
|
||||
export type GetWorkspacesCurrentToolProviderBuiltinByProviderIconResponses = {
|
||||
200: BinaryFileResponse
|
||||
200: {
|
||||
[key: string]: unknown
|
||||
}
|
||||
}
|
||||
|
||||
export type GetWorkspacesCurrentToolProviderBuiltinByProviderIconResponse
|
||||
@ -4352,7 +4539,7 @@ export type GetWorkspacesCurrentToolProviderBuiltinByProviderInfoData = {
|
||||
}
|
||||
|
||||
export type GetWorkspacesCurrentToolProviderBuiltinByProviderInfoResponses = {
|
||||
200: ToolProviderOpaqueResponse
|
||||
200: ToolProviderApiEntityResponse
|
||||
}
|
||||
|
||||
export type GetWorkspacesCurrentToolProviderBuiltinByProviderInfoResponse
|
||||
@ -4368,7 +4555,7 @@ export type GetWorkspacesCurrentToolProviderBuiltinByProviderOauthClientSchemaDa
|
||||
}
|
||||
|
||||
export type GetWorkspacesCurrentToolProviderBuiltinByProviderOauthClientSchemaResponses = {
|
||||
200: ToolOAuthClientSchemaResponse
|
||||
200: BuiltinProviderOAuthClientSchemaResponse
|
||||
}
|
||||
|
||||
export type GetWorkspacesCurrentToolProviderBuiltinByProviderOauthClientSchemaResponse
|
||||
@ -4400,7 +4587,9 @@ export type GetWorkspacesCurrentToolProviderBuiltinByProviderOauthCustomClientDa
|
||||
}
|
||||
|
||||
export type GetWorkspacesCurrentToolProviderBuiltinByProviderOauthCustomClientResponses = {
|
||||
200: ToolOAuthCustomClientResponse
|
||||
200: {
|
||||
[key: string]: unknown
|
||||
}
|
||||
}
|
||||
|
||||
export type GetWorkspacesCurrentToolProviderBuiltinByProviderOauthCustomClientResponse
|
||||
@ -4432,7 +4621,7 @@ export type GetWorkspacesCurrentToolProviderBuiltinByProviderToolsData = {
|
||||
}
|
||||
|
||||
export type GetWorkspacesCurrentToolProviderBuiltinByProviderToolsResponses = {
|
||||
200: ToolProviderOpaqueResponse
|
||||
200: ToolApiListResponse
|
||||
}
|
||||
|
||||
export type GetWorkspacesCurrentToolProviderBuiltinByProviderToolsResponse
|
||||
@ -4448,7 +4637,7 @@ export type PostWorkspacesCurrentToolProviderBuiltinByProviderUpdateData = {
|
||||
}
|
||||
|
||||
export type PostWorkspacesCurrentToolProviderBuiltinByProviderUpdateResponses = {
|
||||
200: ToolProviderOpaqueResponse
|
||||
200: SimpleResultResponse
|
||||
}
|
||||
|
||||
export type PostWorkspacesCurrentToolProviderBuiltinByProviderUpdateResponse
|
||||
@ -4476,7 +4665,7 @@ export type PostWorkspacesCurrentToolProviderMcpData = {
|
||||
}
|
||||
|
||||
export type PostWorkspacesCurrentToolProviderMcpResponses = {
|
||||
200: ToolProviderOpaqueResponse
|
||||
200: ToolProviderApiEntityResponse
|
||||
}
|
||||
|
||||
export type PostWorkspacesCurrentToolProviderMcpResponse
|
||||
@ -4504,7 +4693,7 @@ export type PostWorkspacesCurrentToolProviderMcpAuthData = {
|
||||
}
|
||||
|
||||
export type PostWorkspacesCurrentToolProviderMcpAuthResponses = {
|
||||
200: ToolProviderOpaqueResponse
|
||||
200: McpAuthResponse
|
||||
}
|
||||
|
||||
export type PostWorkspacesCurrentToolProviderMcpAuthResponse
|
||||
@ -4520,7 +4709,7 @@ export type GetWorkspacesCurrentToolProviderMcpToolsByProviderIdData = {
|
||||
}
|
||||
|
||||
export type GetWorkspacesCurrentToolProviderMcpToolsByProviderIdResponses = {
|
||||
200: ToolProviderOpaqueResponse
|
||||
200: ToolProviderApiEntityResponse
|
||||
}
|
||||
|
||||
export type GetWorkspacesCurrentToolProviderMcpToolsByProviderIdResponse
|
||||
@ -4536,7 +4725,7 @@ export type GetWorkspacesCurrentToolProviderMcpUpdateByProviderIdData = {
|
||||
}
|
||||
|
||||
export type GetWorkspacesCurrentToolProviderMcpUpdateByProviderIdResponses = {
|
||||
200: ToolProviderOpaqueResponse
|
||||
200: ToolProviderApiEntityResponse
|
||||
}
|
||||
|
||||
export type GetWorkspacesCurrentToolProviderMcpUpdateByProviderIdResponse
|
||||
@ -4550,7 +4739,7 @@ export type PostWorkspacesCurrentToolProviderWorkflowCreateData = {
|
||||
}
|
||||
|
||||
export type PostWorkspacesCurrentToolProviderWorkflowCreateResponses = {
|
||||
200: ToolProviderOpaqueResponse
|
||||
200: SimpleResultResponse
|
||||
}
|
||||
|
||||
export type PostWorkspacesCurrentToolProviderWorkflowCreateResponse
|
||||
@ -4564,7 +4753,7 @@ export type PostWorkspacesCurrentToolProviderWorkflowDeleteData = {
|
||||
}
|
||||
|
||||
export type PostWorkspacesCurrentToolProviderWorkflowDeleteResponses = {
|
||||
200: ToolProviderOpaqueResponse
|
||||
200: SimpleResultResponse
|
||||
}
|
||||
|
||||
export type PostWorkspacesCurrentToolProviderWorkflowDeleteResponse
|
||||
@ -4581,7 +4770,7 @@ export type GetWorkspacesCurrentToolProviderWorkflowGetData = {
|
||||
}
|
||||
|
||||
export type GetWorkspacesCurrentToolProviderWorkflowGetResponses = {
|
||||
200: ToolProviderOpaqueResponse
|
||||
200: WorkflowToolDetailResponse
|
||||
}
|
||||
|
||||
export type GetWorkspacesCurrentToolProviderWorkflowGetResponse
|
||||
@ -4597,7 +4786,7 @@ export type GetWorkspacesCurrentToolProviderWorkflowToolsData = {
|
||||
}
|
||||
|
||||
export type GetWorkspacesCurrentToolProviderWorkflowToolsResponses = {
|
||||
200: ToolProviderOpaqueResponse
|
||||
200: ToolApiListResponse
|
||||
}
|
||||
|
||||
export type GetWorkspacesCurrentToolProviderWorkflowToolsResponse
|
||||
@ -4611,7 +4800,7 @@ export type PostWorkspacesCurrentToolProviderWorkflowUpdateData = {
|
||||
}
|
||||
|
||||
export type PostWorkspacesCurrentToolProviderWorkflowUpdateResponses = {
|
||||
200: ToolProviderOpaqueResponse
|
||||
200: SimpleResultResponse
|
||||
}
|
||||
|
||||
export type PostWorkspacesCurrentToolProviderWorkflowUpdateResponse
|
||||
@ -4627,7 +4816,7 @@ export type GetWorkspacesCurrentToolProvidersData = {
|
||||
}
|
||||
|
||||
export type GetWorkspacesCurrentToolProvidersResponses = {
|
||||
200: ToolProviderOpaqueResponse
|
||||
200: ToolProviderListResponse
|
||||
}
|
||||
|
||||
export type GetWorkspacesCurrentToolProvidersResponse
|
||||
@ -4641,7 +4830,7 @@ export type GetWorkspacesCurrentToolsApiData = {
|
||||
}
|
||||
|
||||
export type GetWorkspacesCurrentToolsApiResponses = {
|
||||
200: ToolProviderOpaqueResponse
|
||||
200: ToolProviderListResponse
|
||||
}
|
||||
|
||||
export type GetWorkspacesCurrentToolsApiResponse
|
||||
@ -4655,7 +4844,7 @@ export type GetWorkspacesCurrentToolsBuiltinData = {
|
||||
}
|
||||
|
||||
export type GetWorkspacesCurrentToolsBuiltinResponses = {
|
||||
200: ToolProviderOpaqueResponse
|
||||
200: ToolProviderListResponse
|
||||
}
|
||||
|
||||
export type GetWorkspacesCurrentToolsBuiltinResponse
|
||||
@ -4669,7 +4858,7 @@ export type GetWorkspacesCurrentToolsMcpData = {
|
||||
}
|
||||
|
||||
export type GetWorkspacesCurrentToolsMcpResponses = {
|
||||
200: ToolProviderOpaqueResponse
|
||||
200: ToolProviderListResponse
|
||||
}
|
||||
|
||||
export type GetWorkspacesCurrentToolsMcpResponse
|
||||
@ -4683,7 +4872,7 @@ export type GetWorkspacesCurrentToolsWorkflowData = {
|
||||
}
|
||||
|
||||
export type GetWorkspacesCurrentToolsWorkflowResponses = {
|
||||
200: ToolProviderOpaqueResponse
|
||||
200: ToolProviderListResponse
|
||||
}
|
||||
|
||||
export type GetWorkspacesCurrentToolsWorkflowResponse
|
||||
@ -4699,7 +4888,9 @@ export type GetWorkspacesCurrentTriggerProviderByProviderIconData = {
|
||||
}
|
||||
|
||||
export type GetWorkspacesCurrentTriggerProviderByProviderIconResponses = {
|
||||
200: BinaryFileResponse
|
||||
200: {
|
||||
[key: string]: unknown
|
||||
}
|
||||
}
|
||||
|
||||
export type GetWorkspacesCurrentTriggerProviderByProviderIconResponse
|
||||
@ -4782,7 +4973,7 @@ export type PostWorkspacesCurrentTriggerProviderByProviderSubscriptionsBuilderBu
|
||||
|
||||
export type PostWorkspacesCurrentTriggerProviderByProviderSubscriptionsBuilderBuildBySubscriptionBuilderIdResponses
|
||||
= {
|
||||
200: TriggerProviderOpaqueResponse
|
||||
200: SimpleResultResponse
|
||||
}
|
||||
|
||||
export type PostWorkspacesCurrentTriggerProviderByProviderSubscriptionsBuilderBuildBySubscriptionBuilderIdResponse
|
||||
@ -4855,7 +5046,7 @@ export type PostWorkspacesCurrentTriggerProviderByProviderSubscriptionsBuilderVe
|
||||
|
||||
export type PostWorkspacesCurrentTriggerProviderByProviderSubscriptionsBuilderVerifyAndUpdateBySubscriptionBuilderIdResponses
|
||||
= {
|
||||
200: TriggerSubscriptionBuilderVerifyResponse
|
||||
200: TriggerVerificationResponse
|
||||
}
|
||||
|
||||
export type PostWorkspacesCurrentTriggerProviderByProviderSubscriptionsBuilderVerifyAndUpdateBySubscriptionBuilderIdResponse
|
||||
@ -4889,8 +5080,15 @@ export type GetWorkspacesCurrentTriggerProviderByProviderSubscriptionsListData =
|
||||
url: '/workspaces/current/trigger-provider/{provider}/subscriptions/list'
|
||||
}
|
||||
|
||||
export type GetWorkspacesCurrentTriggerProviderByProviderSubscriptionsListErrors = {
|
||||
404: TriggerProviderErrorResponse
|
||||
}
|
||||
|
||||
export type GetWorkspacesCurrentTriggerProviderByProviderSubscriptionsListError
|
||||
= GetWorkspacesCurrentTriggerProviderByProviderSubscriptionsListErrors[keyof GetWorkspacesCurrentTriggerProviderByProviderSubscriptionsListErrors]
|
||||
|
||||
export type GetWorkspacesCurrentTriggerProviderByProviderSubscriptionsListResponses = {
|
||||
200: TriggerSubscriptionListResponse
|
||||
200: TriggerProviderSubscriptionListResponse
|
||||
}
|
||||
|
||||
export type GetWorkspacesCurrentTriggerProviderByProviderSubscriptionsListResponse
|
||||
@ -4925,7 +5123,7 @@ export type PostWorkspacesCurrentTriggerProviderByProviderSubscriptionsVerifyByS
|
||||
|
||||
export type PostWorkspacesCurrentTriggerProviderByProviderSubscriptionsVerifyBySubscriptionIdResponses
|
||||
= {
|
||||
200: TriggerSubscriptionBuilderVerifyResponse
|
||||
200: TriggerVerificationResponse
|
||||
}
|
||||
|
||||
export type PostWorkspacesCurrentTriggerProviderByProviderSubscriptionsVerifyBySubscriptionIdResponse
|
||||
@ -4957,7 +5155,7 @@ export type PostWorkspacesCurrentTriggerProviderBySubscriptionIdSubscriptionsUpd
|
||||
}
|
||||
|
||||
export type PostWorkspacesCurrentTriggerProviderBySubscriptionIdSubscriptionsUpdateResponses = {
|
||||
200: TriggerProviderOpaqueResponse
|
||||
200: SimpleResultResponse
|
||||
}
|
||||
|
||||
export type PostWorkspacesCurrentTriggerProviderBySubscriptionIdSubscriptionsUpdateResponse
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user