This commit is contained in:
chariri 2026-06-25 18:39:44 +00:00 committed by GitHub
commit 8f15e681e5
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
53 changed files with 3247 additions and 3201 deletions

View File

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

View File

@ -1,28 +1,24 @@
import logging
from typing import Any, Literal, cast
from typing import Literal
from flask import request
from flask_restx import Resource, fields, marshal, marshal_with
from flask_restx import Resource
from pydantic import BaseModel, Field
from sqlalchemy import select
from werkzeug.exceptions import Forbidden, InternalServerError, NotFound
import services
from controllers.common.fields import (
AudioBinaryResponse,
AudioTranscriptResponse,
GeneratedAppResponse,
SimpleResultResponse,
)
from controllers.common.fields import AudioBinaryResponse, AudioTranscriptResponse, SimpleResultResponse
from controllers.common.fields import Parameters as ParametersResponse
from controllers.common.fields import Site as SiteResponse
from controllers.common.schema import (
get_or_create_model,
query_params_from_model,
query_params_from_request,
register_response_schema_models,
register_schema_models,
)
from controllers.console import console_ns
from controllers.console.app.app import AppDetailWithSite
from controllers.console.app.error import (
AppUnavailableError,
AudioTooLargeError,
@ -36,6 +32,7 @@ from controllers.console.app.error import (
ProviderQuotaExceededError,
UnsupportedAudioTypeError,
)
from controllers.console.app.workflow import WorkflowResponse
from controllers.console.app.wraps import get_app_model_with_trial
from controllers.console.explore.error import (
AppSuggestedQuestionsAfterAnswerDisabledError,
@ -56,26 +53,13 @@ from core.errors.error import (
)
from extensions.ext_database import db
from extensions.ext_redis import redis_client
from fields.app_fields import (
app_detail_fields_with_site,
deleted_tool_fields,
model_config_fields,
site_fields,
tag_fields,
)
from fields.dataset_fields import dataset_fields
from fields.member_fields import simple_account_fields
from fields.base import ResponseModel
from fields.dataset_fields import DatasetDetailResponse
from fields.message_fields import SuggestedQuestionsResponse
from fields.workflow_fields import (
conversation_variable_fields,
pipeline_variable_fields,
workflow_fields,
workflow_partial_fields,
)
from graphon.graph_engine.manager import GraphEngineManager
from graphon.model_runtime.errors.invoke import InvokeError
from libs import helper
from libs.helper import uuid_value
from libs.helper import dump_response, uuid_value
from models import Account
from models.account import TenantStatus
from models.model import AppMode, Site
@ -102,57 +86,42 @@ from services.recommended_app_service import RecommendedAppService
logger = logging.getLogger(__name__)
model_config_model = get_or_create_model("TrialAppModelConfig", model_config_fields)
workflow_partial_model = get_or_create_model("TrialWorkflowPartial", workflow_partial_fields)
deleted_tool_model = get_or_create_model("TrialDeletedTool", deleted_tool_fields)
tag_model = get_or_create_model("TrialTag", tag_fields)
site_model = get_or_create_model("TrialSite", site_fields)
class TrialDatasetListItemResponse(DatasetDetailResponse):
pass
app_detail_fields_with_site_copy = app_detail_fields_with_site.copy()
app_detail_fields_with_site_copy["model_config"] = fields.Nested(
model_config_model, attribute="app_model_config", allow_null=True
)
app_detail_fields_with_site_copy["workflow"] = fields.Nested(workflow_partial_model, allow_null=True)
app_detail_fields_with_site_copy["deleted_tools"] = fields.List(fields.Nested(deleted_tool_model))
app_detail_fields_with_site_copy["tags"] = fields.List(fields.Nested(tag_model))
app_detail_fields_with_site_copy["site"] = fields.Nested(site_model)
app_detail_with_site_model = get_or_create_model("TrialAppDetailWithSite", app_detail_fields_with_site_copy)
simple_account_model = get_or_create_model("TrialSimpleAccount", simple_account_fields)
conversation_variable_model = get_or_create_model("TrialConversationVariable", conversation_variable_fields)
pipeline_variable_model = get_or_create_model("TrialPipelineVariable", pipeline_variable_fields)
class TrialDatasetListResponse(ResponseModel):
data: list[TrialDatasetListItemResponse]
has_more: bool
limit: int
total: int
page: int
workflow_fields_copy = workflow_fields.copy()
workflow_fields_copy["created_by"] = fields.Nested(simple_account_model, attribute="created_by_account")
workflow_fields_copy["updated_by"] = fields.Nested(
simple_account_model, attribute="updated_by_account", allow_null=True
)
workflow_fields_copy["conversation_variables"] = fields.List(fields.Nested(conversation_variable_model))
workflow_fields_copy["rag_pipeline_variables"] = fields.List(fields.Nested(pipeline_variable_model))
workflow_model = get_or_create_model("TrialWorkflow", workflow_fields_copy)
dataset_model = get_or_create_model("TrialDataset", dataset_fields)
dataset_list_model = get_or_create_model(
"TrialDatasetList",
{
"data": fields.List(fields.Nested(dataset_model)),
"has_more": fields.Boolean,
"limit": fields.Integer,
"total": fields.Integer,
"page": fields.Integer,
},
register_response_schema_models(
console_ns,
ParametersResponse,
AppDetailWithSite,
AudioBinaryResponse,
AudioTranscriptResponse,
SimpleResultResponse,
SiteResponse,
SuggestedQuestionsResponse,
TrialDatasetListItemResponse,
TrialDatasetListResponse,
WorkflowResponse,
)
class WorkflowRunRequest(BaseModel):
inputs: dict
files: list | None = Field(default=None)
files: list | None = None
class ChatRequest(BaseModel):
inputs: dict
query: str
files: list | None = Field(default=None)
files: list | None = None
conversation_id: str | None = None
parent_message_id: str | None = None
retriever_from: str = "explore_app"
@ -168,7 +137,7 @@ class TextToSpeechRequest(BaseModel):
class CompletionRequest(BaseModel):
inputs: dict
query: str = ""
files: list | None = Field(default=None)
files: list | None = None
response_mode: Literal["blocking", "streaming"] | None = None
retriever_from: str = "explore_app"
@ -187,23 +156,13 @@ register_schema_models(
CompletionRequest,
TrialDatasetListQuery,
)
register_response_schema_models(
console_ns,
ParametersResponse,
AudioBinaryResponse,
AudioTranscriptResponse,
GeneratedAppResponse,
SimpleResultResponse,
SiteResponse,
SuggestedQuestionsResponse,
)
class TrialAppWorkflowRunApi(TrialAppResource):
@trial_feature_enable
@console_ns.expect(console_ns.models[WorkflowRunRequest.__name__])
@console_ns.response(200, "Success", console_ns.models[GeneratedAppResponse.__name__])
@with_current_user
@console_ns.expect(console_ns.models[WorkflowRunRequest.__name__])
@console_ns.response(200, "Success")
def post(self, current_user: Account, trial_app):
"""
Run workflow
@ -224,6 +183,7 @@ class TrialAppWorkflowRunApi(TrialAppResource):
app_model=app_model, user=current_user, args=args, invoke_from=InvokeFrom.EXPLORE, streaming=True
)
RecommendedAppService.add_trial_app_record(db.session, app_id, user_id)
# response-contract:ignore compact_generate_response
return helper.compact_generate_response(response)
except ProviderTokenNotInitError as ex:
raise ProviderNotInitializeError(ex.description)
@ -263,12 +223,12 @@ class TrialAppWorkflowTaskStopApi(TrialAppResource):
# New graph engine command channel mechanism
GraphEngineManager(redis_client).send_stop_command(task_id)
return {"result": "success"}
return SimpleResultResponse(result="success").model_dump(mode="json")
class TrialChatApi(TrialAppResource):
@console_ns.expect(console_ns.models[ChatRequest.__name__])
@console_ns.response(200, "Success", console_ns.models[GeneratedAppResponse.__name__])
@console_ns.response(200, "Success")
@trial_feature_enable
@with_current_user
def post(self, current_user: Account, trial_app):
@ -297,6 +257,7 @@ class TrialChatApi(TrialAppResource):
app_model=app_model, user=current_user, args=args, invoke_from=InvokeFrom.EXPLORE, streaming=True
)
RecommendedAppService.add_trial_app_record(db.session, app_id, user_id)
# response-contract:ignore compact_generate_response
return helper.compact_generate_response(response)
except services.errors.conversation.ConversationNotExistsError:
raise NotFound("Conversation Not Exists.")
@ -355,7 +316,7 @@ class TrialMessageSuggestedQuestionApi(TrialAppResource):
logger.exception("internal server error.")
raise InternalServerError()
return {"data": questions}
return dump_response(SuggestedQuestionsResponse, {"data": questions})
class TrialChatAudioApi(TrialAppResource):
@ -374,7 +335,7 @@ class TrialChatAudioApi(TrialAppResource):
response = AudioService.transcript_asr(app_model=app_model, file=file, end_user=None)
RecommendedAppService.add_trial_app_record(db.session, app_id, user_id)
return response
return dump_response(AudioTranscriptResponse, response)
except services.errors.app_model_config.AppModelConfigBrokenError:
logger.exception("App model config broken.")
raise AppUnavailableError()
@ -427,6 +388,7 @@ class TrialChatTextApi(TrialAppResource):
message_id=message_id,
)
RecommendedAppService.add_trial_app_record(db.session, app_id, user_id)
# response-contract:ignore binary response
return response
except services.errors.app_model_config.AppModelConfigBrokenError:
logger.exception("App model config broken.")
@ -456,7 +418,7 @@ class TrialChatTextApi(TrialAppResource):
class TrialCompletionApi(TrialAppResource):
@console_ns.expect(console_ns.models[CompletionRequest.__name__])
@console_ns.response(200, "Success", console_ns.models[GeneratedAppResponse.__name__])
@console_ns.response(200, "Success")
@trial_feature_enable
@with_current_user
def post(self, current_user: Account, trial_app):
@ -480,6 +442,7 @@ class TrialCompletionApi(TrialAppResource):
)
RecommendedAppService.add_trial_app_record(db.session, app_id, user_id)
# response-contract:ignore compact_generate_response
return helper.compact_generate_response(response)
except services.errors.conversation.ConversationNotExistsError:
raise NotFound("Conversation Not Exists.")
@ -557,50 +520,49 @@ class TrialAppParameterApi(Resource):
class AppApi(Resource):
@console_ns.response(200, "Success", app_detail_with_site_model)
@get_app_model_with_trial(None)
@marshal_with(app_detail_with_site_model)
@console_ns.response(200, "App detail retrieved successfully", console_ns.models[AppDetailWithSite.__name__])
def get(self, app_model):
"""Get app detail"""
app_service = AppService()
app_model = app_service.get_app(app_model)
return app_model
return dump_response(AppDetailWithSite, app_model)
class AppWorkflowApi(Resource):
@console_ns.response(200, "Success", workflow_model)
@get_app_model_with_trial(None)
@marshal_with(workflow_model)
@console_ns.response(200, "Workflow detail retrieved successfully", console_ns.models[WorkflowResponse.__name__])
def get(self, app_model):
"""Get workflow detail"""
if not app_model.workflow_id:
raise AppUnavailableError()
workflow = db.session.get(Workflow, app_model.workflow_id)
return workflow
return dump_response(WorkflowResponse, workflow)
class DatasetListApi(Resource):
@console_ns.doc(params=query_params_from_model(TrialDatasetListQuery))
@console_ns.response(200, "Success", dataset_list_model)
@console_ns.response(200, "Success", console_ns.models[TrialDatasetListResponse.__name__])
@get_app_model_with_trial(None)
def get(self, app_model):
page = request.args.get("page", default=1, type=int)
limit = request.args.get("limit", default=20, type=int)
ids = request.args.getlist("ids")
query = query_params_from_request(
TrialDatasetListQuery,
list_fields=("ids",),
use_defaults_for_malformed_ints=True,
)
tenant_id = app_model.tenant_id
if ids:
datasets, total = DatasetService.get_datasets_by_ids(ids, tenant_id)
if query.ids:
datasets, total = DatasetService.get_datasets_by_ids(query.ids, tenant_id)
else:
raise NeedAddIdsError()
data = cast(list[dict[str, Any]], marshal(datasets, dataset_fields))
response = {"data": data, "has_more": len(datasets) == limit, "limit": limit, "total": total, "page": page}
return response
return TrialDatasetListResponse(
data=datasets, has_more=len(datasets) == query.limit, limit=query.limit, total=total or 0, page=query.page
).model_dump(mode="json")
console_ns.add_resource(TrialChatApi, "/trial-apps/<uuid:app_id>/chat-messages", endpoint="trial_app_chat_completion")

View File

@ -1,12 +1,12 @@
from __future__ import annotations
from datetime import datetime
from typing import Any, Literal
from typing import Literal
import pytz
from flask import request
from flask_restx import Resource
from pydantic import BaseModel, Field, RootModel, field_validator, model_validator
from pydantic import BaseModel, Field, field_validator, model_validator
from sqlalchemy import select
from werkzeug.exceptions import NotFound
@ -47,7 +47,7 @@ from controllers.console.wraps import (
)
from extensions.ext_database import db
from fields.base import ResponseModel
from fields.member_fields import Account as AccountResponse
from fields.member_fields import AccountResponse
from graphon.file import helpers as file_helpers
from libs.datetime_utils import naive_utc_now
from libs.helper import EmailStr, dump_response, extract_remote_ip, timezone, to_timestamp
@ -194,10 +194,6 @@ register_schema_models(
)
def _serialize_account(account) -> dict[str, Any]:
return AccountResponse.model_validate(account, from_attributes=True).model_dump(mode="json")
class AccountIntegrateResponse(ResponseModel):
provider: str
created_at: int | None = None
@ -236,23 +232,15 @@ class EducationAutocompleteResponse(ResponseModel):
has_next: bool | None = None
class EducationActivateResponse(RootModel[dict[str, Any]]):
root: dict[str, Any]
register_schema_models(
console_ns,
AccountIntegrateResponse,
AccountIntegrateListResponse,
EducationVerifyResponse,
EducationStatusResponse,
EducationAutocompleteResponse,
)
register_response_schema_models(
console_ns,
AccountResponse,
AccountIntegrateResponse,
AccountIntegrateListResponse,
AvatarUrlResponse,
EducationActivateResponse,
EducationVerifyResponse,
EducationStatusResponse,
EducationAutocompleteResponse,
SimpleResultDataResponse,
SimpleResultResponse,
VerificationTokenResponse,
@ -302,7 +290,7 @@ class AccountInitApi(Resource):
account.initialized_at = naive_utc_now()
db.session.commit()
return {"result": "success"}
return SimpleResultResponse(result="success").model_dump(mode="json")
@console_ns.route("/account/profile")
@ -314,7 +302,7 @@ class AccountProfileApi(Resource):
@enterprise_license_required
@with_current_user
def get(self, current_user: Account):
return _serialize_account(current_user)
return dump_response(AccountResponse, current_user)
@console_ns.route("/account/name")
@ -330,7 +318,7 @@ class AccountNameApi(Resource):
args = AccountNamePayload.model_validate(payload)
updated_account = AccountService.update_account(current_user, session=db.session, name=args.name)
return _serialize_account(updated_account)
return dump_response(AccountResponse, updated_account)
@console_ns.route("/account/avatar")
@ -349,7 +337,7 @@ class AccountAvatarApi(Resource):
avatar = args.avatar
if avatar.startswith(("http://", "https://")):
return dump_response(AvatarUrlResponse, {"avatar_url": avatar})
return AvatarUrlResponse(avatar_url=avatar).model_dump(mode="json")
upload_file = db.session.scalar(select(UploadFile).where(UploadFile.id == avatar).limit(1))
if upload_file is None:
@ -362,7 +350,7 @@ class AccountAvatarApi(Resource):
raise NotFound("Avatar file not found")
avatar_url = file_helpers.get_signed_file_url(upload_file_id=upload_file.id)
return dump_response(AvatarUrlResponse, {"avatar_url": avatar_url})
return AvatarUrlResponse(avatar_url=avatar_url).model_dump(mode="json")
@console_ns.expect(console_ns.models[AccountAvatarPayload.__name__])
@setup_required
@ -376,7 +364,7 @@ class AccountAvatarApi(Resource):
updated_account = AccountService.update_account(current_user, session=db.session, avatar=args.avatar)
return _serialize_account(updated_account)
return dump_response(AccountResponse, updated_account)
@console_ns.route("/account/interface-language")
@ -395,7 +383,7 @@ class AccountInterfaceLanguageApi(Resource):
current_user, session=db.session, interface_language=args.interface_language
)
return _serialize_account(updated_account)
return dump_response(AccountResponse, updated_account)
@console_ns.route("/account/interface-theme")
@ -414,7 +402,7 @@ class AccountInterfaceThemeApi(Resource):
current_user, session=db.session, interface_theme=args.interface_theme
)
return _serialize_account(updated_account)
return dump_response(AccountResponse, updated_account)
@console_ns.route("/account/timezone")
@ -431,7 +419,7 @@ class AccountTimezoneApi(Resource):
updated_account = AccountService.update_account(current_user, session=db.session, timezone=args.timezone)
return _serialize_account(updated_account)
return dump_response(AccountResponse, updated_account)
@console_ns.route("/account/password")
@ -452,7 +440,7 @@ class AccountPasswordApi(Resource):
except ServiceCurrentPasswordIncorrectError:
raise CurrentPasswordIncorrectError()
return _serialize_account(current_user)
return dump_response(AccountResponse, current_user)
@console_ns.route("/account/integrates")
@ -471,33 +459,29 @@ class AccountIntegrateApi(Resource):
oauth_base_path = "/console/api/oauth/login"
providers = ["github", "google"]
integrate_data = []
integrate_data: list[AccountIntegrateResponse] = []
for provider in providers:
existing_integrate = next((ai for ai in account_integrates if ai.provider == provider), None)
if existing_integrate:
integrate_data.append(
{
"id": existing_integrate.id,
"provider": provider,
"created_at": existing_integrate.created_at,
"is_bound": True,
"link": None,
}
AccountIntegrateResponse(
provider=provider,
created_at=to_timestamp(existing_integrate.created_at),
is_bound=True,
link=None,
)
)
else:
integrate_data.append(
{
"id": None,
"provider": provider,
"created_at": None,
"is_bound": False,
"link": f"{base_url}{oauth_base_path}/{provider}",
}
AccountIntegrateResponse(
provider=provider,
created_at=None,
is_bound=False,
link=f"{base_url}{oauth_base_path}/{provider}",
)
)
return AccountIntegrateListResponse(
data=[AccountIntegrateResponse.model_validate(item) for item in integrate_data]
).model_dump(mode="json")
return AccountIntegrateListResponse(data=integrate_data).model_dump(mode="json")
@console_ns.route("/account/delete/verify")
@ -511,7 +495,7 @@ class AccountDeleteVerifyApi(Resource):
token, code = AccountService.generate_account_deletion_verification_code(account)
AccountService.send_account_deletion_verification_email(account, code)
return {"result": "success", "data": token}
return SimpleResultDataResponse(result="success", data=token).model_dump(mode="json")
@console_ns.route("/account/delete")
@ -531,7 +515,7 @@ class AccountDeleteApi(Resource):
AccountService.delete_account(account)
return {"result": "success"}
return SimpleResultResponse(result="success").model_dump(mode="json")
@console_ns.route("/account/delete/feedback")
@ -545,7 +529,7 @@ class AccountDeleteUpdateFeedbackApi(Resource):
BillingService.update_account_deletion_feedback(args.email, args.feedback)
return {"result": "success"}
return SimpleResultResponse(result="success").model_dump(mode="json")
@console_ns.route("/account/education/verify")
@ -558,15 +542,16 @@ class EducationVerifyApi(Resource):
@console_ns.response(200, "Success", console_ns.models[EducationVerifyResponse.__name__])
@with_current_user
def get(self, account: Account):
return EducationVerifyResponse.model_validate(
BillingService.EducationIdentity.verify(account.id, account.email) or {}
).model_dump(mode="json")
return dump_response(
EducationVerifyResponse, BillingService.EducationIdentity.verify(account.id, account.email) or {}
)
@console_ns.route("/account/education")
class EducationApi(Resource):
@console_ns.expect(console_ns.models[EducationActivatePayload.__name__])
@console_ns.response(200, "Success", console_ns.models[EducationActivateResponse.__name__])
# response-contract:ignore billing-service activation payload; TODO: model education activation result.
@console_ns.response(200, "Success")
@setup_required
@login_required
@account_initialization_required
@ -577,7 +562,8 @@ class EducationApi(Resource):
payload = console_ns.payload or {}
args = EducationActivatePayload.model_validate(payload)
return BillingService.EducationIdentity.activate(account, args.token, args.institution, args.role)
result = BillingService.EducationIdentity.activate(account, args.token, args.institution, args.role)
return result
@setup_required
@login_required
@ -591,7 +577,7 @@ class EducationApi(Resource):
# convert expire_at to UTC timestamp from isoformat
if res and "expire_at" in res:
res["expire_at"] = datetime.fromisoformat(res["expire_at"]).astimezone(pytz.utc)
return EducationStatusResponse.model_validate(res).model_dump(mode="json")
return dump_response(EducationStatusResponse, res)
@console_ns.route("/account/education/autocomplete")
@ -607,9 +593,10 @@ class EducationAutoCompleteApi(Resource):
payload = request.args.to_dict(flat=True)
args = EducationAutocompleteQuery.model_validate(payload)
return EducationAutocompleteResponse.model_validate(
BillingService.EducationIdentity.autocomplete(args.keywords, args.page, args.limit) or {}
).model_dump(mode="json")
return dump_response(
EducationAutocompleteResponse,
BillingService.EducationIdentity.autocomplete(args.keywords, args.page, args.limit) or {},
)
@console_ns.route("/account/change-email")
@ -669,7 +656,7 @@ class ChangeEmailSendEmailApi(Resource):
language=language,
phase=send_phase,
)
return {"result": "success", "data": token}
return SimpleResultDataResponse(result="success", data=token).model_dump(mode="json")
@console_ns.route("/account/change-email/validity")
@ -716,7 +703,9 @@ class ChangeEmailCheckApi(Resource):
new_token = AccountService.generate_change_email_token(refreshed_token_data, current_user)
AccountService.reset_change_email_error_rate_limit(user_email)
return {"is_valid": True, "email": normalized_token_email, "token": new_token}
return VerificationTokenResponse(is_valid=True, email=normalized_token_email, token=new_token).model_dump(
mode="json"
)
@console_ns.route("/account/change-email/reset")
@ -768,7 +757,7 @@ class ChangeEmailResetApi(Resource):
email=normalized_new_email,
)
return _serialize_account(updated_account)
return dump_response(AccountResponse, updated_account)
@console_ns.route("/account/change-email/check-email-unique")
@ -784,4 +773,4 @@ class CheckEmailUnique(Resource):
raise AccountInFreezeError()
if not AccountService.check_email_unique(normalized_email, session=db.session):
raise EmailAlreadyInUseError()
return {"result": "success"}
return SimpleResultResponse(result="success").model_dump(mode="json")

View File

@ -12,7 +12,8 @@ from flask import request
from flask_restx import Resource
from pydantic import BaseModel, Field
from controllers.common.schema import query_params_from_model, register_schema_models
from controllers.common.fields import SuccessResponse
from controllers.common.schema import query_params_from_model, register_response_schema_models, register_schema_models
from controllers.console import console_ns
from controllers.console.wraps import (
RBACPermission,
@ -24,8 +25,9 @@ from controllers.console.wraps import (
with_current_tenant_id,
with_current_user_id,
)
from core.plugin.entities.endpoint import EndpointEntityWithInstance
from core.plugin.impl.exc import PluginPermissionDeniedError
from graphon.model_runtime.utils.encoders import jsonable_encoder
from fields.base import ResponseModel
from libs.login import login_required
from services.plugin.endpoint_service import EndpointService
@ -40,14 +42,17 @@ class EndpointIdPayload(BaseModel):
endpoint_id: str
class EndpointUpdatePayload(BaseModel):
class EndpointSettingsPayload(BaseModel):
settings: dict[str, Any]
name: str = Field(min_length=1)
class LegacyEndpointUpdatePayload(EndpointIdPayload):
settings: dict[str, Any]
name: str = Field(min_length=1)
class EndpointUpdatePayload(EndpointSettingsPayload):
pass
class LegacyEndpointUpdatePayload(EndpointIdPayload, EndpointSettingsPayload):
pass
class EndpointListQuery(BaseModel):
@ -59,98 +64,85 @@ class EndpointListForPluginQuery(EndpointListQuery):
plugin_id: str
class EndpointCreateResponse(BaseModel):
success: bool = Field(description="Operation success")
class EndpointListResponse(BaseModel):
endpoints: list[dict[str, Any]] = Field(
description="Endpoint information",
)
class PluginEndpointListResponse(BaseModel):
endpoints: list[dict[str, Any]] = Field(
description="Endpoint information",
)
class EndpointDeleteResponse(BaseModel):
success: bool = Field(description="Operation success")
class EndpointUpdateResponse(BaseModel):
success: bool = Field(description="Operation success")
class EndpointEnableResponse(BaseModel):
success: bool = Field(description="Operation success")
class EndpointDisableResponse(BaseModel):
success: bool = Field(description="Operation success")
class EndpointListResponse(ResponseModel):
endpoints: list[EndpointEntityWithInstance] = Field(description="Endpoint information")
register_schema_models(
console_ns,
EndpointCreatePayload,
EndpointIdPayload,
EndpointSettingsPayload,
EndpointUpdatePayload,
LegacyEndpointUpdatePayload,
EndpointListQuery,
EndpointListForPluginQuery,
EndpointCreateResponse,
)
register_response_schema_models(
console_ns,
SuccessResponse,
EndpointListResponse,
PluginEndpointListResponse,
EndpointDeleteResponse,
EndpointUpdateResponse,
EndpointEnableResponse,
EndpointDisableResponse,
)
def _create_endpoint(tenant_id: str, user_id: str) -> dict[str, bool]:
def _create_endpoint(tenant_id: str, user_id: str) -> bool:
"""Create a plugin endpoint for the injected workspace and user."""
args = EndpointCreatePayload.model_validate(console_ns.payload)
try:
return {
"success": EndpointService.create_endpoint(
tenant_id=tenant_id,
user_id=user_id,
plugin_unique_identifier=args.plugin_unique_identifier,
name=args.name,
settings=args.settings,
)
}
return EndpointService.create_endpoint(
tenant_id=tenant_id,
user_id=user_id,
plugin_unique_identifier=args.plugin_unique_identifier,
name=args.name,
settings=args.settings,
)
except PluginPermissionDeniedError as e:
raise ValueError(e.description) from e
def _update_endpoint(tenant_id: str, user_id: str, endpoint_id: str) -> dict[str, bool]:
def _update_endpoint(tenant_id: str, user_id: str, endpoint_id: str) -> bool:
"""Update a plugin endpoint identified by the canonical path parameter."""
args = EndpointUpdatePayload.model_validate(console_ns.payload)
return {
"success": EndpointService.update_endpoint(
tenant_id=tenant_id,
user_id=user_id,
endpoint_id=endpoint_id,
name=args.name,
settings=args.settings,
)
}
return EndpointService.update_endpoint(
tenant_id=tenant_id,
user_id=user_id,
endpoint_id=endpoint_id,
name=args.name,
settings=args.settings,
)
def _delete_endpoint(tenant_id: str, user_id: str, endpoint_id: str) -> dict[str, bool]:
def _legacy_update_endpoint(tenant_id: str, user_id: str) -> bool:
args = LegacyEndpointUpdatePayload.model_validate(console_ns.payload)
return EndpointService.update_endpoint(
tenant_id=tenant_id,
user_id=user_id,
endpoint_id=args.endpoint_id,
name=args.name,
settings=args.settings,
)
def _delete_endpoint(tenant_id: str, user_id: str, endpoint_id: str) -> bool:
"""Delete a plugin endpoint identified by the canonical path parameter."""
return {
"success": EndpointService.delete_endpoint(
tenant_id=tenant_id,
user_id=user_id,
endpoint_id=endpoint_id,
)
}
return EndpointService.delete_endpoint(
tenant_id=tenant_id,
user_id=user_id,
endpoint_id=endpoint_id,
)
def _delete_endpoint_from_payload(tenant_id: str, user_id: str) -> bool:
args = EndpointIdPayload.model_validate(console_ns.payload)
return _delete_endpoint(tenant_id=tenant_id, user_id=user_id, endpoint_id=args.endpoint_id)
def _set_endpoint_enabled(tenant_id: str, user_id: str, *, enabled: bool) -> bool:
args = EndpointIdPayload.model_validate(console_ns.payload)
action = EndpointService.enable_endpoint if enabled else EndpointService.disable_endpoint
return action(tenant_id=tenant_id, user_id=user_id, endpoint_id=args.endpoint_id)
@console_ns.route("/workspaces/current/endpoints")
@ -163,7 +155,7 @@ class EndpointCollectionApi(Resource):
@console_ns.response(
200,
"Endpoint created successfully",
console_ns.models[EndpointCreateResponse.__name__],
console_ns.models[SuccessResponse.__name__],
)
@console_ns.response(403, "Admin privileges required")
@setup_required
@ -174,7 +166,7 @@ class EndpointCollectionApi(Resource):
@with_current_user_id
@with_current_tenant_id
def post(self, tenant_id: str, user_id: str):
return _create_endpoint(tenant_id=tenant_id, user_id=user_id)
return SuccessResponse(success=_create_endpoint(tenant_id=tenant_id, user_id=user_id)).model_dump(mode="json")
@console_ns.route("/workspaces/current/endpoints/create")
@ -192,7 +184,7 @@ class DeprecatedEndpointCreateApi(Resource):
@console_ns.response(
200,
"Endpoint created successfully",
console_ns.models[EndpointCreateResponse.__name__],
console_ns.models[SuccessResponse.__name__],
)
@console_ns.response(403, "Admin privileges required")
@setup_required
@ -203,7 +195,7 @@ class DeprecatedEndpointCreateApi(Resource):
@with_current_user_id
@with_current_tenant_id
def post(self, tenant_id: str, user_id: str):
return _create_endpoint(tenant_id=tenant_id, user_id=user_id)
return SuccessResponse(success=_create_endpoint(tenant_id=tenant_id, user_id=user_id)).model_dump(mode="json")
@console_ns.route("/workspaces/current/endpoints/list")
@ -224,19 +216,14 @@ class EndpointListApi(Resource):
def get(self, tenant_id: str, user_id: str):
args = EndpointListQuery.model_validate(request.args.to_dict(flat=True))
page = args.page
page_size = args.page_size
return jsonable_encoder(
{
"endpoints": EndpointService.list_endpoints(
tenant_id=tenant_id,
user_id=user_id,
page=page,
page_size=page_size,
)
}
)
return EndpointListResponse(
endpoints=EndpointService.list_endpoints(
tenant_id=tenant_id,
user_id=user_id,
page=args.page,
page_size=args.page_size,
)
).model_dump(mode="json")
@console_ns.route("/workspaces/current/endpoints/list/plugin")
@ -247,7 +234,7 @@ class EndpointListForSinglePluginApi(Resource):
@console_ns.response(
200,
"Success",
console_ns.models[PluginEndpointListResponse.__name__],
console_ns.models[EndpointListResponse.__name__],
)
@setup_required
@login_required
@ -257,21 +244,15 @@ class EndpointListForSinglePluginApi(Resource):
def get(self, tenant_id: str, user_id: str):
args = EndpointListForPluginQuery.model_validate(request.args.to_dict(flat=True))
page = args.page
page_size = args.page_size
plugin_id = args.plugin_id
return jsonable_encoder(
{
"endpoints": EndpointService.list_endpoints_for_single_plugin(
tenant_id=tenant_id,
user_id=user_id,
plugin_id=plugin_id,
page=page,
page_size=page_size,
)
}
)
return EndpointListResponse(
endpoints=EndpointService.list_endpoints_for_single_plugin(
tenant_id=tenant_id,
user_id=user_id,
plugin_id=args.plugin_id,
page=args.page,
page_size=args.page_size,
)
).model_dump(mode="json")
@console_ns.route("/workspaces/current/endpoints/<string:id>")
@ -284,7 +265,7 @@ class EndpointItemApi(Resource):
@console_ns.response(
200,
"Endpoint deleted successfully",
console_ns.models[EndpointDeleteResponse.__name__],
console_ns.models[SuccessResponse.__name__],
)
@console_ns.response(403, "Admin privileges required")
@setup_required
@ -295,7 +276,9 @@ class EndpointItemApi(Resource):
@with_current_user_id
@with_current_tenant_id
def delete(self, tenant_id: str, user_id: str, id: str):
return _delete_endpoint(tenant_id=tenant_id, user_id=user_id, endpoint_id=id)
return SuccessResponse(
success=_delete_endpoint(tenant_id=tenant_id, user_id=user_id, endpoint_id=id)
).model_dump(mode="json")
@console_ns.doc("update_endpoint")
@console_ns.doc(description="Update a plugin endpoint")
@ -304,7 +287,7 @@ class EndpointItemApi(Resource):
@console_ns.response(
200,
"Endpoint updated successfully",
console_ns.models[EndpointUpdateResponse.__name__],
console_ns.models[SuccessResponse.__name__],
)
@console_ns.response(403, "Admin privileges required")
@setup_required
@ -315,7 +298,9 @@ class EndpointItemApi(Resource):
@with_current_user_id
@with_current_tenant_id
def patch(self, tenant_id: str, user_id: str, id: str):
return _update_endpoint(tenant_id=tenant_id, user_id=user_id, endpoint_id=id)
return SuccessResponse(
success=_update_endpoint(tenant_id=tenant_id, user_id=user_id, endpoint_id=id)
).model_dump(mode="json")
@console_ns.route("/workspaces/current/endpoints/delete")
@ -334,7 +319,7 @@ class DeprecatedEndpointDeleteApi(Resource):
@console_ns.response(
200,
"Endpoint deleted successfully",
console_ns.models[EndpointDeleteResponse.__name__],
console_ns.models[SuccessResponse.__name__],
)
@console_ns.response(403, "Admin privileges required")
@setup_required
@ -345,8 +330,9 @@ class DeprecatedEndpointDeleteApi(Resource):
@with_current_user_id
@with_current_tenant_id
def post(self, tenant_id: str, user_id: str):
args = EndpointIdPayload.model_validate(console_ns.payload)
return _delete_endpoint(tenant_id=tenant_id, user_id=user_id, endpoint_id=args.endpoint_id)
return SuccessResponse( #
success=_delete_endpoint_from_payload(tenant_id=tenant_id, user_id=user_id)
).model_dump(mode="json")
@console_ns.route("/workspaces/current/endpoints/update")
@ -365,7 +351,7 @@ class DeprecatedEndpointUpdateApi(Resource):
@console_ns.response(
200,
"Endpoint updated successfully",
console_ns.models[EndpointUpdateResponse.__name__],
console_ns.models[SuccessResponse.__name__],
)
@console_ns.response(403, "Admin privileges required")
@setup_required
@ -376,8 +362,9 @@ class DeprecatedEndpointUpdateApi(Resource):
@with_current_user_id
@with_current_tenant_id
def post(self, tenant_id: str, user_id: str):
args = LegacyEndpointUpdatePayload.model_validate(console_ns.payload)
return _update_endpoint(tenant_id=tenant_id, user_id=user_id, endpoint_id=args.endpoint_id)
return SuccessResponse( #
success=_legacy_update_endpoint(tenant_id=tenant_id, user_id=user_id)
).model_dump(mode="json")
@console_ns.route("/workspaces/current/endpoints/enable")
@ -388,7 +375,7 @@ class EndpointEnableApi(Resource):
@console_ns.response(
200,
"Endpoint enabled successfully",
console_ns.models[EndpointEnableResponse.__name__],
console_ns.models[SuccessResponse.__name__],
)
@console_ns.response(403, "Admin privileges required")
@setup_required
@ -399,13 +386,9 @@ class EndpointEnableApi(Resource):
@with_current_user_id
@with_current_tenant_id
def post(self, tenant_id: str, user_id: str):
args = EndpointIdPayload.model_validate(console_ns.payload)
return {
"success": EndpointService.enable_endpoint(
tenant_id=tenant_id, user_id=user_id, endpoint_id=args.endpoint_id
)
}
return SuccessResponse(
success=_set_endpoint_enabled(tenant_id=tenant_id, user_id=user_id, enabled=True)
).model_dump(mode="json")
@console_ns.route("/workspaces/current/endpoints/disable")
@ -416,7 +399,7 @@ class EndpointDisableApi(Resource):
@console_ns.response(
200,
"Endpoint disabled successfully",
console_ns.models[EndpointDisableResponse.__name__],
console_ns.models[SuccessResponse.__name__],
)
@console_ns.response(403, "Admin privileges required")
@setup_required
@ -427,10 +410,6 @@ class EndpointDisableApi(Resource):
@with_current_user_id
@with_current_tenant_id
def post(self, tenant_id: str, user_id: str):
args = EndpointIdPayload.model_validate(console_ns.payload)
return {
"success": EndpointService.disable_endpoint(
tenant_id=tenant_id, user_id=user_id, endpoint_id=args.endpoint_id
)
}
return SuccessResponse(
success=_set_endpoint_enabled(tenant_id=tenant_id, user_id=user_id, enabled=False)
).model_dump(mode="json")

View File

@ -3,7 +3,7 @@ from uuid import UUID
from flask import abort, request
from flask_restx import Resource
from pydantic import BaseModel, Field, TypeAdapter
from pydantic import BaseModel, Field
from sqlalchemy import func, select
import services
@ -30,8 +30,8 @@ from controllers.console.wraps import (
from extensions.ext_database import db
from extensions.ext_redis import redis_client
from fields.base import ResponseModel
from fields.member_fields import AccountWithRole, AccountWithRoleList
from libs.helper import extract_remote_ip
from fields.member_fields import AccountWithRoleListResponse, AccountWithRoleResponse
from libs.helper import dump_response, extract_remote_ip
from libs.login import current_account_with_tenant, login_required
from models.account import Account, TenantAccountJoin, TenantAccountRole
from services.account_service import AccountService, RegisterService, TenantService
@ -70,22 +70,20 @@ class MemberInviteResultResponse(ResponseModel):
message: str | None = None
class MemberActionResponse(ResponseModel):
result: str
tenant_id: str = ""
class MemberInviteResponse(ResponseModel):
result: str
invitation_results: list[MemberInviteResultResponse]
tenant_id: str
class MemberActionTenantResponse(ResponseModel):
result: str
tenant_id: str
register_enum_models(console_ns, TenantAccountRole)
register_schema_models(
console_ns,
AccountWithRole,
AccountWithRoleList,
MemberInvitePayload,
MemberRoleUpdatePayload,
OwnerTransferEmailPayload,
@ -94,11 +92,14 @@ register_schema_models(
)
register_response_schema_models(
console_ns,
AccountWithRoleResponse,
AccountWithRoleListResponse,
MemberActionResponse,
MemberInviteResponse,
MemberInviteResultResponse,
SimpleResultDataResponse,
SimpleResultResponse,
VerificationTokenResponse,
MemberInviteResponse,
MemberActionTenantResponse,
)
@ -179,7 +180,7 @@ class MemberListApi(Resource):
@setup_required
@login_required
@account_initialization_required
@console_ns.response(200, "Success", console_ns.models[AccountWithRoleList.__name__])
@console_ns.response(200, "Success", console_ns.models[AccountWithRoleListResponse.__name__])
@with_current_user
def get(self, current_user: Account | None = None):
if current_user is None:
@ -216,9 +217,7 @@ class MemberListApi(Resource):
}
)
member_models = TypeAdapter(list[AccountWithRole]).validate_python(serialized_members)
response = AccountWithRoleList(accounts=member_models)
return response.model_dump(mode="json"), 200
return dump_response(AccountWithRoleListResponse, {"accounts": serialized_members}), 200
@console_ns.route("/workspaces/current/members/invite-email")
@ -254,7 +253,7 @@ class MemberInviteEmailApi(Resource):
check_workspace_member_invite_permission(inviter.current_tenant.id)
invitation_results = []
invitation_results: list[MemberInviteResultResponse] = []
console_web_url = dify_config.CONSOLE_WEB_URL
tenant_id = inviter.current_tenant.id
@ -277,38 +276,40 @@ class MemberInviteEmailApi(Resource):
)
encoded_invitee_email = parse.quote(invitee_email)
invitation_results.append(
{
"status": "success",
"email": invitee_email,
"url": f"{console_web_url}/activate?email={encoded_invitee_email}&token={token}",
}
MemberInviteResultResponse(
status="success",
email=invitee_email,
url=f"{console_web_url}/activate?email={encoded_invitee_email}&token={token}",
)
)
except AccountAlreadyInTenantError:
invitation_results.append(
{
"status": "already_member",
"email": invitee_email,
"message": "Account already in workspace.",
}
MemberInviteResultResponse(
status="already_member",
email=invitee_email,
message="Account already in workspace.",
)
)
except Exception as e:
invitation_results.append({"status": "failed", "email": invitee_email, "message": str(e)})
invitation_results.append(
MemberInviteResultResponse(status="failed", email=invitee_email, message=str(e))
)
return {
"result": "success",
"invitation_results": invitation_results,
"tenant_id": str(inviter.current_tenant.id) if inviter.current_tenant else "",
}, 201
return MemberInviteResponse(
result="success",
invitation_results=invitation_results,
tenant_id=inviter.current_tenant.id if inviter.current_tenant else "",
).model_dump(mode="json"), 201
@console_ns.route("/workspaces/current/members/<uuid:member_id>")
class MemberCancelInviteApi(Resource):
"""Cancel an invitation by member id."""
@console_ns.response(200, "Success", console_ns.models[MemberActionTenantResponse.__name__])
@setup_required
@login_required
@account_initialization_required
@console_ns.response(200, "Success", console_ns.models[MemberActionResponse.__name__])
@with_current_user
def delete(self, current_user: Account, member_id: UUID):
if not current_user.current_tenant:
@ -330,10 +331,10 @@ class MemberCancelInviteApi(Resource):
except Exception as e:
raise ValueError(str(e))
return {
"result": "success",
"tenant_id": str(current_user.current_tenant.id) if current_user.current_tenant else "",
}, 200
return MemberActionResponse(
result="success",
tenant_id=current_user.current_tenant.id if current_user.current_tenant else "",
).model_dump(mode="json"), 200
@console_ns.route("/workspaces/current/members/<uuid:member_id>/update-role")
@ -377,7 +378,7 @@ class MemberUpdateRoleApi(Resource):
except Exception as e:
raise ValueError(str(e))
return {"result": "success"}
return SimpleResultResponse(result="success").model_dump(mode="json")
@console_ns.route("/workspaces/current/dataset-operators")
@ -387,15 +388,13 @@ class DatasetOperatorMemberListApi(Resource):
@setup_required
@login_required
@account_initialization_required
@console_ns.response(200, "Success", console_ns.models[AccountWithRoleList.__name__])
@console_ns.response(200, "Success", console_ns.models[AccountWithRoleListResponse.__name__])
@with_current_user
def get(self, current_user: Account):
if not current_user.current_tenant:
raise ValueError("No current tenant")
members = TenantService.get_dataset_operator_members(current_user.current_tenant, session=db.session)
member_models = TypeAdapter(list[AccountWithRole]).validate_python(members, from_attributes=True)
response = AccountWithRoleList(accounts=member_models)
return response.model_dump(mode="json"), 200
return dump_response(AccountWithRoleListResponse, {"accounts": members}), 200
@console_ns.route("/workspaces/current/members/send-owner-transfer-confirm-email")
@ -435,7 +434,7 @@ class SendOwnerTransferEmailApi(Resource):
workspace_name=current_user.current_tenant.name if current_user.current_tenant else "",
)
return {"result": "success", "data": token}
return SimpleResultDataResponse(result="success", data=token).model_dump(mode="json")
@console_ns.route("/workspaces/current/members/owner-transfer-check")
@ -480,7 +479,7 @@ class OwnerTransferCheckApi(Resource):
_, new_token = AccountService.generate_owner_transfer_token(user_email, code=args.code, additional_data={})
AccountService.reset_owner_transfer_error_rate_limit(user_email)
return {"is_valid": True, "email": token_data.get("email"), "token": new_token}
return VerificationTokenResponse(is_valid=True, email=user_email, token=new_token).model_dump(mode="json")
@console_ns.route("/workspaces/current/members/<uuid:member_id>/owner-transfer")
@ -546,4 +545,4 @@ class OwnerTransfer(Resource):
except Exception as e:
raise ValueError(str(e))
return {"result": "success"}
return SimpleResultResponse(result="success").model_dump(mode="json")

View File

@ -1,16 +1,13 @@
import logging
import re
from typing import Any
from urllib.parse import quote
from flask import Response, request
from flask_restx import Resource, marshal
from pydantic import RootModel
from flask_restx import Resource
from sqlalchemy.orm import Session, sessionmaker
from werkzeug.datastructures import MultiDict
from werkzeug.exceptions import NotFound
from controllers.common.fields import TextFileResponse
from controllers.common.schema import query_params_from_model, register_response_schema_models, register_schema_models
from controllers.console import console_ns
from controllers.console.snippets.payloads import (
@ -32,12 +29,13 @@ from controllers.console.wraps import (
)
from extensions.ext_database import db
from fields.base import ResponseModel
from fields.snippet_fields import snippet_fields, snippet_list_fields, snippet_pagination_fields
from fields.snippet_fields import SnippetPaginationResponse, SnippetResponse
from libs.helper import dump_response
from libs.login import login_required
from models import Account
from models.snippet import SnippetType
from services.app_dsl_service import ImportStatus
from services.snippet_dsl_service import SnippetDslService
from services.snippet_dsl_service import CheckDependenciesResult, SnippetDslService, SnippetImportInfo
from services.snippet_service import SnippetService
logger = logging.getLogger(__name__)
@ -45,15 +43,7 @@ _TAG_IDS_BRACKET_PATTERN = re.compile(r"^tag_ids\[(\d+)\]$")
_CREATOR_IDS_BRACKET_PATTERN = re.compile(r"^creator_ids\[(\d+)\]$")
class SnippetImportResponse(RootModel[dict[str, Any]]):
root: dict[str, Any]
class SnippetDependencyCheckResponse(RootModel[dict[str, Any]]):
root: dict[str, Any]
class SnippetUseCountResponse(ResponseModel):
class SnippetUseCountIncrementResponse(ResponseModel):
result: str
use_count: int
@ -100,30 +90,22 @@ register_schema_models(
IncludeSecretQuery,
)
register_response_schema_models(
console_ns,
TextFileResponse,
SnippetImportResponse,
SnippetDependencyCheckResponse,
SnippetUseCountResponse,
console_ns, SnippetResponse, SnippetPaginationResponse, SnippetUseCountIncrementResponse, SnippetImportInfo
)
# Create namespace models for marshaling
snippet_model = console_ns.model("Snippet", snippet_fields)
snippet_list_model = console_ns.model("SnippetList", snippet_list_fields)
snippet_pagination_model = console_ns.model("SnippetPagination", snippet_pagination_fields)
@console_ns.route("/workspaces/current/customized-snippets")
class CustomizedSnippetsApi(Resource):
@console_ns.doc("list_customized_snippets")
@console_ns.doc(params=query_params_from_model(SnippetListQuery))
@console_ns.response(200, "Snippets retrieved successfully", snippet_pagination_model)
@console_ns.response(200, "Snippets retrieved successfully", console_ns.models[SnippetPaginationResponse.__name__])
@setup_required
@login_required
@account_initialization_required
@with_current_tenant_id
def get(self, current_tenant_id: str):
"""List customized snippets with pagination and search."""
query = SnippetListQuery.model_validate(_normalize_snippet_list_query_args(request.args))
snippet_service = _snippet_service()
@ -138,17 +120,20 @@ class CustomizedSnippetsApi(Resource):
tag_ids=query.tag_ids,
)
return {
"data": marshal(snippets, snippet_list_fields),
"page": query.page,
"limit": query.limit,
"total": total,
"has_more": has_more,
}, 200
return dump_response(
SnippetPaginationResponse,
{
"data": snippets,
"page": query.page,
"limit": query.limit,
"total": total,
"has_more": has_more,
},
), 200
@console_ns.doc("create_customized_snippet")
@console_ns.expect(console_ns.models.get(CreateSnippetPayload.__name__))
@console_ns.response(201, "Snippet created successfully", snippet_model)
@console_ns.response(201, "Snippet created successfully", console_ns.models[SnippetResponse.__name__])
@console_ns.response(400, "Invalid request")
@setup_required
@login_required
@ -161,6 +146,7 @@ class CustomizedSnippetsApi(Resource):
@with_current_tenant_id
def post(self, current_tenant_id: str, current_user: Account):
"""Create a new customized snippet."""
payload = CreateSnippetPayload.model_validate(console_ns.payload or {})
try:
@ -185,13 +171,13 @@ class CustomizedSnippetsApi(Resource):
except ValueError as e:
return {"message": str(e)}, 400
return marshal(snippet, snippet_fields), 201
return dump_response(SnippetResponse, snippet), 201
@console_ns.route("/workspaces/current/customized-snippets/<uuid:snippet_id>")
class CustomizedSnippetDetailApi(Resource):
@console_ns.doc("get_customized_snippet")
@console_ns.response(200, "Snippet retrieved successfully", snippet_model)
@console_ns.response(200, "Snippet retrieved successfully", console_ns.models[SnippetResponse.__name__])
@console_ns.response(404, "Snippet not found")
@setup_required
@login_required
@ -199,20 +185,21 @@ class CustomizedSnippetDetailApi(Resource):
@with_current_tenant_id
def get(self, current_tenant_id: str, snippet_id: str):
"""Get customized snippet details."""
snippet_service = _snippet_service()
snippet = snippet_service.get_snippet_by_id(
snippet_id=str(snippet_id),
snippet_id=snippet_id,
tenant_id=current_tenant_id,
)
if not snippet:
raise NotFound("Snippet not found")
return marshal(snippet, snippet_fields), 200
return dump_response(SnippetResponse, snippet), 200
@console_ns.doc("update_customized_snippet")
@console_ns.expect(console_ns.models.get(UpdateSnippetPayload.__name__))
@console_ns.response(200, "Snippet updated successfully", snippet_model)
@console_ns.response(200, "Snippet updated successfully", console_ns.models[SnippetResponse.__name__])
@console_ns.response(400, "Invalid request")
@console_ns.response(404, "Snippet not found")
@setup_required
@ -226,9 +213,10 @@ class CustomizedSnippetDetailApi(Resource):
@with_current_tenant_id
def patch(self, current_tenant_id: str, current_user: Account, snippet_id: str):
"""Update customized snippet."""
snippet_service = _snippet_service()
snippet = snippet_service.get_snippet_by_id(
snippet_id=str(snippet_id),
snippet_id=snippet_id,
tenant_id=current_tenant_id,
)
@ -257,7 +245,7 @@ class CustomizedSnippetDetailApi(Resource):
except ValueError as e:
return {"message": str(e)}, 400
return marshal(snippet, snippet_fields), 200
return dump_response(SnippetResponse, snippet), 200
@console_ns.doc("delete_customized_snippet")
@console_ns.response(204, "Snippet deleted successfully")
@ -270,9 +258,10 @@ class CustomizedSnippetDetailApi(Resource):
@with_current_tenant_id
def delete(self, current_tenant_id: str, snippet_id: str):
"""Delete customized snippet."""
snippet_service = _snippet_service()
snippet = snippet_service.get_snippet_by_id(
snippet_id=str(snippet_id),
snippet_id=snippet_id,
tenant_id=current_tenant_id,
)
@ -296,7 +285,7 @@ class CustomizedSnippetExportApi(Resource):
@console_ns.doc(description="Export snippet configuration as DSL")
@console_ns.doc(params={"snippet_id": "Snippet ID to export"})
@console_ns.doc(params=query_params_from_model(IncludeSecretQuery))
@console_ns.response(200, "Snippet exported successfully", console_ns.models[TextFileResponse.__name__])
@console_ns.response(200, "Snippet exported successfully")
@console_ns.response(404, "Snippet not found")
@setup_required
@login_required
@ -308,9 +297,10 @@ class CustomizedSnippetExportApi(Resource):
@with_current_tenant_id
def get(self, current_tenant_id: str, snippet_id: str):
"""Export snippet as DSL."""
snippet_service = _snippet_service()
snippet = snippet_service.get_snippet_by_id(
snippet_id=str(snippet_id),
snippet_id=snippet_id,
tenant_id=current_tenant_id,
)
@ -343,8 +333,8 @@ class CustomizedSnippetImportApi(Resource):
@console_ns.doc("import_customized_snippet")
@console_ns.doc(description="Import snippet from DSL")
@console_ns.expect(console_ns.models.get(SnippetImportPayload.__name__))
@console_ns.response(200, "Snippet imported successfully", console_ns.models[SnippetImportResponse.__name__])
@console_ns.response(202, "Import pending confirmation", console_ns.models[SnippetImportResponse.__name__])
@console_ns.response(200, "Snippet imported successfully", console_ns.models[SnippetImportInfo.__name__])
@console_ns.response(202, "Import pending confirmation", console_ns.models[SnippetImportInfo.__name__])
@console_ns.response(400, "Import failed")
@setup_required
@login_required
@ -385,7 +375,7 @@ class CustomizedSnippetImportConfirmApi(Resource):
@console_ns.doc("confirm_snippet_import")
@console_ns.doc(description="Confirm a pending snippet import")
@console_ns.doc(params={"import_id": "Import ID to confirm"})
@console_ns.response(200, "Import confirmed successfully", console_ns.models[SnippetImportResponse.__name__])
@console_ns.response(200, "Import confirmed successfully", console_ns.models[SnippetImportInfo.__name__])
@console_ns.response(400, "Import failed")
@setup_required
@login_required
@ -412,11 +402,7 @@ class CustomizedSnippetCheckDependenciesApi(Resource):
@console_ns.doc("check_snippet_dependencies")
@console_ns.doc(description="Check dependencies for a snippet")
@console_ns.doc(params={"snippet_id": "Snippet ID"})
@console_ns.response(
200,
"Dependencies checked successfully",
console_ns.models[SnippetDependencyCheckResponse.__name__],
)
@console_ns.response(200, "Dependencies checked successfully", console_ns.models[CheckDependenciesResult.__name__])
@console_ns.response(404, "Snippet not found")
@setup_required
@login_required
@ -430,7 +416,7 @@ class CustomizedSnippetCheckDependenciesApi(Resource):
"""Check dependencies for a snippet."""
snippet_service = _snippet_service()
snippet = snippet_service.get_snippet_by_id(
snippet_id=str(snippet_id),
snippet_id=snippet_id,
tenant_id=current_tenant_id,
)
@ -449,7 +435,11 @@ class CustomizedSnippetUseCountIncrementApi(Resource):
@console_ns.doc("increment_snippet_use_count")
@console_ns.doc(description="Increment snippet use count by 1")
@console_ns.doc(params={"snippet_id": "Snippet ID"})
@console_ns.response(200, "Use count incremented successfully", console_ns.models[SnippetUseCountResponse.__name__])
@console_ns.response(
200,
"Use count incremented successfully",
console_ns.models[SnippetUseCountIncrementResponse.__name__],
)
@console_ns.response(404, "Snippet not found")
@setup_required
@login_required
@ -461,9 +451,10 @@ class CustomizedSnippetUseCountIncrementApi(Resource):
@with_current_tenant_id
def post(self, current_tenant_id: str, snippet_id: str):
"""Increment snippet use count when it is inserted into a workflow."""
snippet_service = _snippet_service()
snippet = snippet_service.get_snippet_by_id(
snippet_id=str(snippet_id),
snippet_id=snippet_id,
tenant_id=current_tenant_id,
)
@ -476,4 +467,6 @@ class CustomizedSnippetUseCountIncrementApi(Resource):
session.commit()
session.refresh(snippet)
return {"result": "success", "use_count": snippet.use_count}, 200
return SnippetUseCountIncrementResponse(result="success", use_count=snippet.use_count).model_dump(
mode="json"
), 200

View File

@ -2,7 +2,7 @@ import logging
from datetime import datetime
from flask import request
from flask_restx import Resource, fields, marshal
from flask_restx import Resource
from pydantic import BaseModel, Field, field_validator
from sqlalchemy import select
from werkzeug.exceptions import Unauthorized
@ -16,7 +16,12 @@ from controllers.common.errors import (
TooManyFilesError,
UnsupportedFileTypeError,
)
from controllers.common.schema import query_params_from_model, register_response_schema_models, register_schema_models
from controllers.common.schema import (
query_params_from_model,
query_params_from_request,
register_response_schema_models,
register_schema_models,
)
from controllers.console import console_ns
from controllers.console.admin import admin_required
from controllers.console.error import AccountNotLinkTenantError
@ -31,7 +36,7 @@ from controllers.console.wraps import (
from enums.cloud_plan import CloudPlan
from extensions.ext_database import db
from fields.base import ResponseModel
from libs.helper import OptionalTimestampField, TimestampField, dump_response, to_timestamp
from libs.helper import dump_response, to_timestamp
from libs.login import login_required
from models.account import Account, Tenant, TenantAccountJoin, TenantCustomConfigDict, TenantStatus
from services.account_service import TenantService
@ -102,6 +107,7 @@ class TenantListItemResponse(ResponseModel):
plan: str | None = None
status: str | None = None
created_at: int | None = None
last_opened_at: int | None = None
current: bool
@field_validator("plan", "status", mode="before")
@ -113,9 +119,9 @@ class TenantListItemResponse(ResponseModel):
return value
return str(getattr(value, "value", value))
@field_validator("created_at", mode="before")
@field_validator("created_at", "last_opened_at", mode="before")
@classmethod
def _normalize_created_at(cls, value: datetime | int | None):
def _normalize_timestamp(cls, value: datetime | int | None):
return to_timestamp(value)
@ -131,7 +137,7 @@ class WorkspaceListItemResponse(ResponseModel):
@field_validator("status", mode="before")
@classmethod
def _normalize_status(cls, value):
def _normalize_enum_like(cls, value):
if value is None:
return None
if isinstance(value, str):
@ -144,7 +150,7 @@ class WorkspaceListItemResponse(ResponseModel):
return to_timestamp(value)
class WorkspaceListResponse(ResponseModel):
class WorkspacePaginationResponse(ResponseModel):
data: list[WorkspaceListItemResponse]
has_more: bool
limit: int
@ -157,7 +163,7 @@ class SwitchWorkspaceResponse(ResponseModel):
new_tenant: TenantInfoResponse
class WorkspaceMutationResponse(ResponseModel):
class WorkspaceTenantResultResponse(ResponseModel):
result: str
tenant: TenantInfoResponse
@ -172,6 +178,16 @@ class WorkspacePermissionResponse(ResponseModel):
allow_owner_transfer: bool
WORKSPACE_LOGO_UPLOAD_PARAMS = {
"file": {
"in": "formData",
"type": "file",
"required": True,
"description": "Workspace web app logo file. Only SVG and PNG files are supported.",
}
}
register_schema_models(
console_ns,
WorkspaceListQuery,
@ -182,49 +198,17 @@ register_schema_models(
register_response_schema_models(
console_ns,
TenantInfoResponse,
TenantListItemResponse,
TenantListResponse,
WorkspaceListResponse,
SwitchWorkspaceResponse,
WorkspaceMutationResponse,
WorkspaceLogoUploadResponse,
WorkspaceCustomConfigResponse,
WorkspaceListItemResponse,
WorkspacePaginationResponse,
SwitchWorkspaceResponse,
WorkspaceTenantResultResponse,
WorkspaceLogoUploadResponse,
WorkspacePermissionResponse,
)
provider_fields = {
"provider_name": fields.String,
"provider_type": fields.String,
"is_valid": fields.Boolean,
"token_is_set": fields.Boolean,
}
tenant_fields = {
"id": fields.String,
"name": fields.String,
"plan": fields.String,
"status": fields.String,
"created_at": TimestampField,
"role": fields.String,
"in_trial": fields.Boolean,
"trial_end_reason": fields.String,
"custom_config": fields.Raw(attribute="custom_config"),
"trial_credits": fields.Integer,
"trial_credits_used": fields.Integer,
"next_credit_reset_date": fields.Integer,
}
tenants_fields = {
"id": fields.String,
"name": fields.String,
"plan": fields.String,
"status": fields.String,
"created_at": TimestampField,
"last_opened_at": OptionalTimestampField,
"current": fields.Boolean,
}
workspace_fields = {"id": fields.String, "name": fields.String, "status": fields.String, "created_at": TimestampField}
@console_ns.route("/workspaces")
class TenantListApi(Resource):
@ -279,18 +263,17 @@ class TenantListApi(Resource):
tenant_dicts.append(tenant_dict)
return {"workspaces": marshal(tenant_dicts, tenants_fields)}, 200
return dump_response(TenantListResponse, {"workspaces": tenant_dicts}), 200
@console_ns.route("/all-workspaces")
class WorkspaceListApi(Resource):
@console_ns.doc(params=query_params_from_model(WorkspaceListQuery))
@console_ns.response(200, "Success", console_ns.models[WorkspaceListResponse.__name__])
@console_ns.response(200, "Success", console_ns.models[WorkspacePaginationResponse.__name__])
@setup_required
@admin_required
def get(self):
payload = request.args.to_dict(flat=True)
args = WorkspaceListQuery.model_validate(payload)
args = query_params_from_request(WorkspaceListQuery)
stmt = select(Tenant).order_by(Tenant.created_at.desc())
tenants = db.paginate(select=stmt, page=args.page, per_page=args.limit, error_out=False)
@ -299,13 +282,9 @@ class WorkspaceListApi(Resource):
if tenants.has_next:
has_more = True
return {
"data": marshal(tenants.items, workspace_fields),
"has_more": has_more,
"limit": args.limit,
"page": args.page,
"total": tenants.total,
}, 200
return WorkspacePaginationResponse(
data=tenants.items, has_more=has_more, limit=args.limit, page=args.page, total=tenants.total or 0
).model_dump(mode="json"), 200
@console_ns.route("/workspaces/current", endpoint="workspaces_current")
@ -359,13 +338,15 @@ class SwitchWorkspaceApi(Resource):
if new_tenant is None:
raise ValueError("Tenant not found")
return {"result": "success", "new_tenant": marshal(WorkspaceService.get_tenant_info(new_tenant), tenant_fields)}
return SwitchWorkspaceResponse(
result="success", new_tenant=WorkspaceService.get_tenant_info(new_tenant)
).model_dump(mode="json")
@console_ns.route("/workspaces/custom-config")
class CustomConfigWorkspaceApi(Resource):
@console_ns.expect(console_ns.models[WorkspaceCustomConfigPayload.__name__])
@console_ns.response(200, "Success", console_ns.models[WorkspaceMutationResponse.__name__])
@console_ns.response(200, "Success", console_ns.models[WorkspaceTenantResultResponse.__name__])
@setup_required
@login_required
@account_initialization_required
@ -388,11 +369,14 @@ class CustomConfigWorkspaceApi(Resource):
tenant.custom_config_dict = custom_config_dict
db.session.commit()
return {"result": "success", "tenant": marshal(WorkspaceService.get_tenant_info(tenant), tenant_fields)}
return WorkspaceTenantResultResponse(
result="success", tenant=WorkspaceService.get_tenant_info(tenant)
).model_dump(mode="json")
@console_ns.route("/workspaces/custom-config/webapp-logo/upload")
class WebappLogoWorkspaceApi(Resource):
@console_ns.doc(consumes=["multipart/form-data"], params=WORKSPACE_LOGO_UPLOAD_PARAMS)
@console_ns.response(201, "Logo uploaded", console_ns.models[WorkspaceLogoUploadResponse.__name__])
@setup_required
@login_required
@ -429,13 +413,13 @@ class WebappLogoWorkspaceApi(Resource):
except services.errors.file.UnsupportedFileTypeError:
raise UnsupportedFileTypeError()
return {"id": upload_file.id}, 201
return WorkspaceLogoUploadResponse(id=upload_file.id).model_dump(mode="json"), 201
@console_ns.route("/workspaces/info")
class WorkspaceInfoApi(Resource):
@console_ns.expect(console_ns.models[WorkspaceInfoPayload.__name__])
@console_ns.response(200, "Success", console_ns.models[WorkspaceMutationResponse.__name__])
@console_ns.response(200, "Success", console_ns.models[WorkspaceTenantResultResponse.__name__])
@setup_required
@login_required
@account_initialization_required
@ -451,7 +435,9 @@ class WorkspaceInfoApi(Resource):
tenant.name = args.name
db.session.commit()
return {"result": "success", "tenant": marshal(WorkspaceService.get_tenant_info(tenant), tenant_fields)}
return WorkspaceTenantResultResponse(
result="success", tenant=WorkspaceService.get_tenant_info(tenant)
).model_dump(mode="json")
@console_ns.route("/workspaces/current/permission")
@ -475,8 +461,8 @@ class WorkspacePermissionApi(Resource):
# Get workspace permissions from enterprise service
permission = EnterpriseService.WorkspacePermissionService.get_permission(current_tenant_id)
return {
"workspace_id": permission.workspace_id,
"allow_member_invite": permission.allow_member_invite,
"allow_owner_transfer": permission.allow_owner_transfer,
}, 200
return WorkspacePermissionResponse(
workspace_id=permission.workspace_id,
allow_member_invite=permission.allow_member_invite,
allow_owner_transfer=permission.allow_owner_transfer,
).model_dump(mode="json"), 200

View File

@ -1,271 +0,0 @@
import json
from typing import override
from flask_restx import fields
from fields.workflow_fields import workflow_partial_fields
from libs.helper import AppIconUrlField, TimestampField
class JsonStringField(fields.Raw):
@override
def format(self, value):
if isinstance(value, str):
try:
return json.loads(value)
except (json.JSONDecodeError, TypeError):
return value
return value
class OpaqueRawField(fields.Raw):
@override
def schema(self) -> dict[str, object]:
return {"type": "object"}
class StringListRawField(fields.Raw):
@override
def schema(self) -> dict[str, object]:
return {"type": "array", "items": {"type": "string"}}
class ObjectListRawField(fields.Raw):
@override
def schema(self) -> dict[str, object]:
return {"type": "array", "items": {"type": "object"}}
app_detail_kernel_fields = {
"id": fields.String,
"name": fields.String,
"description": fields.String,
"mode": fields.String(attribute="mode_compatible_with_agent"),
"icon_type": fields.String,
"icon": fields.String,
"icon_background": fields.String,
"icon_url": AppIconUrlField,
}
related_app_list = {
"data": fields.List(fields.Nested(app_detail_kernel_fields)),
"total": fields.Integer,
}
model_config_fields = {
"opening_statement": fields.String,
"suggested_questions": StringListRawField(attribute="suggested_questions_list"),
"suggested_questions_after_answer": OpaqueRawField(attribute="suggested_questions_after_answer_dict"),
"speech_to_text": OpaqueRawField(attribute="speech_to_text_dict"),
"text_to_speech": OpaqueRawField(attribute="text_to_speech_dict"),
"retriever_resource": OpaqueRawField(attribute="retriever_resource_dict"),
"annotation_reply": OpaqueRawField(attribute="annotation_reply_dict"),
"more_like_this": OpaqueRawField(attribute="more_like_this_dict"),
"sensitive_word_avoidance": OpaqueRawField(attribute="sensitive_word_avoidance_dict"),
"external_data_tools": ObjectListRawField(attribute="external_data_tools_list"),
"model": OpaqueRawField(attribute="model_dict"),
"user_input_form": ObjectListRawField(attribute="user_input_form_list"),
"dataset_query_variable": fields.String,
"pre_prompt": fields.String,
"agent_mode": OpaqueRawField(attribute="agent_mode_dict"),
"prompt_type": fields.String,
"chat_prompt_config": OpaqueRawField(attribute="chat_prompt_config_dict"),
"completion_prompt_config": OpaqueRawField(attribute="completion_prompt_config_dict"),
"dataset_configs": OpaqueRawField(attribute="dataset_configs_dict"),
"file_upload": OpaqueRawField(attribute="file_upload_dict"),
"created_by": fields.String,
"created_at": TimestampField,
"updated_by": fields.String,
"updated_at": TimestampField,
}
tag_fields = {"id": fields.String, "name": fields.String, "type": fields.String}
app_detail_fields = {
"id": fields.String,
"name": fields.String,
"description": fields.String,
"mode": fields.String(attribute="mode_compatible_with_agent"),
"icon": fields.String,
"icon_background": fields.String,
"enable_site": fields.Boolean,
"enable_api": fields.Boolean,
"model_config": fields.Nested(model_config_fields, attribute="app_model_config", allow_null=True),
"workflow": fields.Nested(workflow_partial_fields, allow_null=True),
"tracing": OpaqueRawField,
"use_icon_as_answer_icon": fields.Boolean,
"created_by": fields.String,
"created_at": TimestampField,
"updated_by": fields.String,
"updated_at": TimestampField,
"access_mode": fields.String,
"tags": fields.List(fields.Nested(tag_fields)),
"permission_keys": fields.List(fields.String()),
}
prompt_config_fields = {
"prompt_template": fields.String,
}
model_config_partial_fields = {
"model": OpaqueRawField(attribute="model_dict"),
"pre_prompt": fields.String,
"created_by": fields.String,
"created_at": TimestampField,
"updated_by": fields.String,
"updated_at": TimestampField,
}
app_partial_fields = {
"id": fields.String,
"name": fields.String,
"max_active_requests": OpaqueRawField(),
"description": fields.String(attribute="desc_or_prompt"),
"mode": fields.String(attribute="mode_compatible_with_agent"),
"icon_type": fields.String,
"icon": fields.String,
"icon_background": fields.String,
"icon_url": AppIconUrlField,
"model_config": fields.Nested(model_config_partial_fields, attribute="app_model_config", allow_null=True),
"workflow": fields.Nested(workflow_partial_fields, allow_null=True),
"use_icon_as_answer_icon": fields.Boolean,
"created_by": fields.String,
"created_at": TimestampField,
"updated_by": fields.String,
"updated_at": TimestampField,
"tags": fields.List(fields.Nested(tag_fields)),
"access_mode": fields.String,
"create_user_name": fields.String,
"author_name": fields.String,
"has_draft_trigger": fields.Boolean,
"permission_keys": fields.List(fields.String()),
}
app_pagination_fields = {
"page": fields.Integer,
"limit": fields.Integer(attribute="per_page"),
"total": fields.Integer,
"has_more": fields.Boolean(attribute="has_next"),
"data": fields.List(fields.Nested(app_partial_fields), attribute="items"),
}
template_fields = {
"name": fields.String,
"icon": fields.String,
"icon_background": fields.String,
"description": fields.String,
"mode": fields.String,
"model_config": fields.Nested(model_config_fields),
}
template_list_fields = {
"data": fields.List(fields.Nested(template_fields)),
}
site_fields = {
"access_token": fields.String(attribute="code"),
"code": fields.String,
"title": fields.String,
"icon_type": fields.String,
"icon": fields.String,
"icon_background": fields.String,
"icon_url": AppIconUrlField,
"description": fields.String,
"default_language": fields.String,
"chat_color_theme": fields.String,
"chat_color_theme_inverted": fields.Boolean,
"customize_domain": fields.String,
"copyright": fields.String,
"privacy_policy": fields.String,
"custom_disclaimer": fields.String,
"customize_token_strategy": fields.String,
"prompt_public": fields.Boolean,
"app_base_url": fields.String,
"show_workflow_steps": fields.Boolean,
"use_icon_as_answer_icon": fields.Boolean,
"created_by": fields.String,
"created_at": TimestampField,
"updated_by": fields.String,
"updated_at": TimestampField,
}
deleted_tool_fields = {
"type": fields.String,
"tool_name": fields.String,
"provider_id": fields.String,
}
app_detail_fields_with_site = {
"id": fields.String,
"name": fields.String,
"description": fields.String,
"mode": fields.String(attribute="mode_compatible_with_agent"),
"icon_type": fields.String,
"icon": fields.String,
"icon_background": fields.String,
"icon_url": AppIconUrlField,
"enable_site": fields.Boolean,
"enable_api": fields.Boolean,
"model_config": fields.Nested(model_config_fields, attribute="app_model_config", allow_null=True),
"workflow": fields.Nested(workflow_partial_fields, allow_null=True),
"api_base_url": fields.String,
"use_icon_as_answer_icon": fields.Boolean,
"max_active_requests": fields.Integer,
"created_by": fields.String,
"created_at": TimestampField,
"updated_by": fields.String,
"updated_at": TimestampField,
"deleted_tools": fields.List(fields.Nested(deleted_tool_fields)),
"access_mode": fields.String,
"tags": fields.List(fields.Nested(tag_fields)),
"permission_keys": fields.List(fields.String()),
"site": fields.Nested(site_fields),
}
app_site_fields = {
"app_id": fields.String,
"access_token": fields.String(attribute="code"),
"code": fields.String,
"title": fields.String,
"icon": fields.String,
"icon_background": fields.String,
"description": fields.String,
"default_language": fields.String,
"customize_domain": fields.String,
"copyright": fields.String,
"privacy_policy": fields.String,
"custom_disclaimer": fields.String,
"customize_token_strategy": fields.String,
"prompt_public": fields.Boolean,
"show_workflow_steps": fields.Boolean,
"use_icon_as_answer_icon": fields.Boolean,
}
leaked_dependency_fields = {"type": fields.String, "value": OpaqueRawField, "current_identifier": fields.String}
app_import_fields = {
"id": fields.String,
"status": fields.String,
"app_id": fields.String,
"app_mode": fields.String,
"current_dsl_version": fields.String,
"imported_dsl_version": fields.String,
"error": fields.String,
}
app_import_check_dependencies_fields = {
"leaked_dependencies": fields.List(fields.Nested(leaked_dependency_fields)),
}
app_server_fields = {
"id": fields.String,
"name": fields.String,
"server_code": fields.String,
"description": fields.String,
"status": fields.String,
"parameters": JsonStringField,
"created_at": TimestampField,
"updated_at": TimestampField,
}

View File

@ -2,26 +2,19 @@ from __future__ import annotations
from datetime import datetime
from flask_restx import fields
from pydantic import Field, computed_field, field_validator
from fields.base import ResponseModel
from libs.helper import build_avatar_url, to_timestamp
simple_account_fields = {
"id": fields.String,
"name": fields.String,
"email": fields.String,
}
class SimpleAccount(ResponseModel):
class SimpleAccountResponse(ResponseModel):
id: str
name: str
email: str
class _AccountAvatar(ResponseModel):
class _AccountAvatarResponseMixin(ResponseModel):
avatar: str | None = None
@computed_field(return_type=str | None) # type: ignore[prop-decorator]
@ -30,7 +23,7 @@ class _AccountAvatar(ResponseModel):
return build_avatar_url(self.avatar)
class Account(_AccountAvatar):
class AccountResponse(_AccountAvatarResponseMixin):
id: str
name: str
email: str
@ -48,7 +41,7 @@ class Account(_AccountAvatar):
return to_timestamp(value)
class AccountWithRole(_AccountAvatar):
class AccountWithRoleResponse(_AccountAvatarResponseMixin):
id: str
name: str
email: str
@ -65,5 +58,11 @@ class AccountWithRole(_AccountAvatar):
return to_timestamp(value)
class AccountWithRoleList(ResponseModel):
accounts: list[AccountWithRole]
class AccountWithRoleListResponse(ResponseModel):
accounts: list[AccountWithRoleResponse]
SimpleAccount = SimpleAccountResponse
Account = AccountResponse
AccountWithRole = AccountWithRoleResponse
AccountWithRoleList = AccountWithRoleListResponse

View File

@ -1,61 +1,67 @@
from typing import override
from datetime import datetime
from typing import Any
from flask_restx import fields
from pydantic import Field, field_validator
from fields.member_fields import simple_account_fields
from libs.helper import TimestampField
from fields.base import ResponseModel
from fields.member_fields import SimpleAccountResponse
from libs.helper import to_timestamp
class OpaqueRawField(fields.Raw):
@override
def schema(self) -> dict[str, object]:
return {"type": "object"}
class SnippetTagResponse(ResponseModel):
id: str
name: str
type: str
tag_fields = {"id": fields.String, "name": fields.String, "type": fields.String}
class SnippetListItemResponse(ResponseModel):
id: str
name: str
description: str | None = None
type: str
version: int
use_count: int
is_published: bool
icon_info: dict[str, Any] | None = None
tags: list[SnippetTagResponse] = Field(default_factory=list)
created_by: str | None = None
author_name: str | None = None
created_at: int | None = None
updated_by: str | None = None
updated_at: int | None = None
# Snippet list item fields (lightweight for list display)
snippet_list_fields = {
"id": fields.String,
"name": fields.String,
"description": fields.String,
"type": fields.String,
"version": fields.Integer,
"use_count": fields.Integer,
"is_published": fields.Boolean,
"icon_info": OpaqueRawField,
"tags": fields.List(fields.Nested(tag_fields)),
"created_by": fields.String,
"author_name": fields.String,
"created_at": TimestampField,
"updated_by": fields.String,
"updated_at": TimestampField,
}
@field_validator("created_at", "updated_at", mode="before")
@classmethod
def _normalize_timestamp(cls, value: datetime | int | None) -> int | None:
return to_timestamp(value)
# Full snippet fields (includes creator info and graph data)
snippet_fields = {
"id": fields.String,
"name": fields.String,
"description": fields.String,
"type": fields.String,
"version": fields.Integer,
"use_count": fields.Integer,
"is_published": fields.Boolean,
"icon_info": OpaqueRawField,
"graph": OpaqueRawField(attribute="graph_dict"),
"input_fields": OpaqueRawField(attribute="input_fields_list"),
"tags": fields.List(fields.Nested(tag_fields)),
"created_by": fields.Nested(simple_account_fields, attribute="created_by_account", allow_null=True),
"created_at": TimestampField,
"updated_by": fields.Nested(simple_account_fields, attribute="updated_by_account", allow_null=True),
"updated_at": TimestampField,
}
# Pagination response fields
snippet_pagination_fields = {
"data": fields.List(fields.Nested(snippet_list_fields)),
"page": fields.Integer,
"limit": fields.Integer,
"total": fields.Integer,
"has_more": fields.Boolean,
}
class SnippetResponse(ResponseModel):
id: str
name: str
description: str | None = None
type: str
version: int
use_count: int
is_published: bool
icon_info: dict[str, Any] | None = None
graph: dict[str, Any] | None = Field(default=None, validation_alias="graph_dict")
input_fields: list[dict[str, Any]] | None = Field(default=None, validation_alias="input_fields_list")
tags: list[SnippetTagResponse] = Field(default_factory=list)
created_by: SimpleAccountResponse | None = Field(default=None, validation_alias="created_by_account")
created_at: int | None = None
updated_by: SimpleAccountResponse | None = Field(default=None, validation_alias="updated_by_account")
updated_at: int | None = None
@field_validator("created_at", "updated_at", mode="before")
@classmethod
def _normalize_timestamp(cls, value: datetime | int | None) -> int | None:
return to_timestamp(value)
class SnippetPaginationResponse(ResponseModel):
data: list[SnippetListItemResponse]
page: int
limit: int
total: int
has_more: bool

View File

@ -1,129 +0,0 @@
from typing import override
from flask_restx import fields
from core.helper import encrypter
from fields.member_fields import simple_account_fields
from graphon.variables import SecretVariable, SegmentType, VariableBase
from libs.helper import TimestampField
from ._value_type_serializer import serialize_value_type
ENVIRONMENT_VARIABLE_SUPPORTED_TYPES = (SegmentType.STRING, SegmentType.NUMBER, SegmentType.SECRET)
class OpaqueRawField(fields.Raw):
@override
def schema(self) -> dict[str, object]:
return {"type": "object"}
class JsonValueRawField(fields.Raw):
@override
def schema(self) -> dict[str, object]:
return {
"anyOf": [
{"type": "string"},
{"type": "integer"},
{"type": "number"},
{"type": "boolean"},
{"type": "object", "additionalProperties": True},
{"type": "array", "items": {}},
{"type": "null"},
]
}
class EnvironmentVariableField(fields.Raw):
@override
def schema(self) -> dict[str, object]:
return {"type": "object"}
@override
def format(self, value):
# Mask secret variables values in environment_variables
if isinstance(value, SecretVariable):
return {
"id": value.id,
"name": value.name,
"value": encrypter.full_mask_token(),
"value_type": value.value_type.value,
"description": value.description,
}
if isinstance(value, VariableBase):
return {
"id": value.id,
"name": value.name,
"value": value.value,
"value_type": str(value.value_type.exposed_type()),
"description": value.description,
}
if isinstance(value, dict):
value_type_str = value.get("value_type")
if not isinstance(value_type_str, str):
raise TypeError(
f"unexpected type for value_type field, value={value_type_str}, type={type(value_type_str)}"
)
value_type = SegmentType(value_type_str).exposed_type()
if value_type not in ENVIRONMENT_VARIABLE_SUPPORTED_TYPES:
raise ValueError(f"Unsupported environment variable value type: {value_type}")
return value
conversation_variable_fields = {
"id": fields.String,
"name": fields.String,
"value_type": fields.String(attribute=serialize_value_type),
"value": JsonValueRawField,
"description": fields.String,
}
pipeline_variable_fields = {
"label": fields.String,
"variable": fields.String,
"type": fields.String,
"belong_to_node_id": fields.String,
"max_length": fields.Integer,
"required": fields.Boolean,
"unit": fields.String,
"default_value": JsonValueRawField,
"options": fields.List(fields.String),
"placeholder": fields.String,
"tooltips": fields.String,
"allowed_file_types": fields.List(fields.String),
"allow_file_extension": fields.List(fields.String),
"allow_file_upload_methods": fields.List(fields.String),
}
workflow_fields = {
"id": fields.String,
"graph": OpaqueRawField(attribute="graph_dict"),
"features": OpaqueRawField(attribute="features_dict"),
"hash": fields.String(attribute="unique_hash"),
"version": fields.String,
"marked_name": fields.String,
"marked_comment": fields.String,
"created_by": fields.Nested(simple_account_fields, attribute="created_by_account"),
"created_at": TimestampField,
"updated_by": fields.Nested(simple_account_fields, attribute="updated_by_account", allow_null=True),
"updated_at": TimestampField,
"tool_published": fields.Boolean,
"environment_variables": fields.List(EnvironmentVariableField()),
"conversation_variables": fields.List(fields.Nested(conversation_variable_fields)),
"rag_pipeline_variables": fields.List(fields.Nested(pipeline_variable_fields)),
}
workflow_partial_fields = {
"id": fields.String,
"created_by": fields.String,
"created_at": TimestampField,
"updated_by": fields.String,
"updated_at": TimestampField,
}
workflow_pagination_fields = {
"items": fields.List(fields.Nested(workflow_fields), attribute="items"),
"page": fields.Integer,
"limit": fields.Integer(attribute="limit"),
"has_more": fields.Boolean(attribute="has_more"),
}

File diff suppressed because it is too large Load Diff

View File

@ -3937,7 +3937,7 @@ Model class for provider with models response.
| output_variable_name | string | | Yes |
| type | string | | No |
#### SimpleAccount
#### SimpleAccountResponse
| Name | Type | Description | Required |
| ---- | ---- | ----------- | -------- |
@ -4147,7 +4147,7 @@ in form definiton, or a variable while the workflow is running.
| Name | Type | Description | Required |
| ---- | ---- | ----------- | -------- |
| created_at | integer | | No |
| created_by_account | [SimpleAccount](#simpleaccount) | | No |
| created_by_account | [SimpleAccountResponse](#simpleaccountresponse) | | No |
| created_by_end_user | [SimpleEndUser](#simpleenduser) | | No |
| created_by_role | string | | No |
| created_from | string | | No |

View File

@ -1,4 +1,4 @@
from inspect import unwrap as inspect_unwrap
from inspect import unwrap
from io import BytesIO
from typing import Any
from unittest.mock import MagicMock, patch
@ -35,24 +35,16 @@ from models.model import AppMode
from services.errors.conversation import ConversationNotExistsError
from services.errors.llm import InvokeRateLimitError
unwrap: Any = inspect_unwrap
@pytest.fixture
def account() -> Account:
acc = Account(name="User", email="user@example.com")
def account():
acc = MagicMock(spec=Account)
acc.id = "u1"
return acc
def _file_data() -> Any:
file_data: Any = BytesIO(b"fake audio data")
file_data.filename = "test.wav"
return file_data
@pytest.fixture
def trial_app_chat() -> MagicMock:
def trial_app_chat():
app = MagicMock()
app.id = "a-chat"
app.mode = AppMode.CHAT
@ -60,7 +52,7 @@ def trial_app_chat() -> MagicMock:
@pytest.fixture
def trial_app_completion() -> MagicMock:
def trial_app_completion():
app = MagicMock()
app.id = "a-comp"
app.mode = AppMode.COMPLETION
@ -68,7 +60,7 @@ def trial_app_completion() -> MagicMock:
@pytest.fixture
def trial_app_workflow() -> MagicMock:
def trial_app_workflow():
app = MagicMock()
app.id = "a-workflow"
app.mode = AppMode.WORKFLOW
@ -76,7 +68,7 @@ def trial_app_workflow() -> MagicMock:
@pytest.fixture
def valid_parameters() -> dict[str, object]:
def valid_parameters():
return {
"user_input_form": [],
"system_parameters": {},
@ -92,13 +84,54 @@ def valid_parameters() -> dict[str, object]:
}
def test_trial_workflow_uses_trial_scoped_simple_account_model() -> None:
assert module.simple_account_model.name == "TrialSimpleAccount"
assert hasattr(module.simple_account_model, "items")
def test_trial_workflow_registers_normalized_simple_account_response_model():
assert "SimpleAccountResponse" in module.console_ns.models
def _response_model_name(entry: object) -> str:
assert isinstance(entry, tuple)
assert len(entry) >= 2
model = entry[1]
name = getattr(model, "name", None)
assert isinstance(name, str)
return name
def test_trial_endpoints_keep_response_and_query_docs():
untyped_generated_response_views = [
module.TrialAppWorkflowRunApi.post,
module.TrialChatApi.post,
module.TrialCompletionApi.post,
]
for view in untyped_generated_response_views:
apidoc = getattr(view, "__apidoc__", {})
assert apidoc.get("responses", {})["200"] == ("Success", None, {})
cases = [
(module.TrialMessageSuggestedQuestionApi.get, module.SuggestedQuestionsResponse.__name__),
(module.TrialChatAudioApi.post, module.AudioTranscriptResponse.__name__),
(module.TrialChatTextApi.post, module.AudioBinaryResponse.__name__),
(module.TrialSitApi.get, module.SiteResponse.__name__),
(module.TrialAppParameterApi.get, module.ParametersResponse.__name__),
(module.AppApi.get, module.AppDetailWithSite.__name__),
(module.AppWorkflowApi.get, module.WorkflowResponse.__name__),
(module.DatasetListApi.get, module.TrialDatasetListResponse.__name__),
]
for view, model_name in cases:
apidoc = getattr(view, "__apidoc__", {})
responses = apidoc.get("responses", {})
assert _response_model_name(responses["200"]) == model_name
dataset_params = module.DatasetListApi.get.__apidoc__["params"]
assert dataset_params["ids"]["in"] == "query"
assert dataset_params["ids"]["type"] == "array"
assert dataset_params["page"]["default"] == 1
assert dataset_params["limit"]["default"] == 20
class TestTrialAppWorkflowRunApi:
def test_not_workflow_app(self, app: Flask, account: Account) -> None:
def test_not_workflow_app(self, app: Flask, account):
api = module.TrialAppWorkflowRunApi()
method = unwrap(api.post)
@ -106,7 +139,7 @@ class TestTrialAppWorkflowRunApi:
with pytest.raises(NotWorkflowAppError):
method(api, account, MagicMock(mode=AppMode.CHAT))
def test_success(self, app: Flask, trial_app_workflow: MagicMock, account: Account) -> None:
def test_success(self, app: Flask, trial_app_workflow, account):
api = module.TrialAppWorkflowRunApi()
method = unwrap(api.post)
@ -119,7 +152,7 @@ class TestTrialAppWorkflowRunApi:
assert result is not None
def test_workflow_provider_not_init(self, app: Flask, trial_app_workflow: MagicMock, account: Account) -> None:
def test_workflow_provider_not_init(self, app: Flask, trial_app_workflow, account):
api = module.TrialAppWorkflowRunApi()
method = unwrap(api.post)
@ -134,7 +167,7 @@ class TestTrialAppWorkflowRunApi:
with pytest.raises(ProviderNotInitializeError):
method(api, account, trial_app_workflow)
def test_workflow_quota_exceeded(self, app: Flask, trial_app_workflow: MagicMock, account: Account) -> None:
def test_workflow_quota_exceeded(self, app: Flask, trial_app_workflow, account):
api = module.TrialAppWorkflowRunApi()
method = unwrap(api.post)
@ -149,7 +182,7 @@ class TestTrialAppWorkflowRunApi:
with pytest.raises(ProviderQuotaExceededError):
method(api, account, trial_app_workflow)
def test_workflow_model_not_support(self, app: Flask, trial_app_workflow: MagicMock, account: Account) -> None:
def test_workflow_model_not_support(self, app: Flask, trial_app_workflow, account):
api = module.TrialAppWorkflowRunApi()
method = unwrap(api.post)
@ -164,7 +197,7 @@ class TestTrialAppWorkflowRunApi:
with pytest.raises(ProviderModelCurrentlyNotSupportError):
method(api, account, trial_app_workflow)
def test_workflow_invoke_error(self, app: Flask, trial_app_workflow: MagicMock, account: Account) -> None:
def test_workflow_invoke_error(self, app: Flask, trial_app_workflow, account):
api = module.TrialAppWorkflowRunApi()
method = unwrap(api.post)
@ -179,7 +212,7 @@ class TestTrialAppWorkflowRunApi:
with pytest.raises(CompletionRequestError):
method(api, account, trial_app_workflow)
def test_workflow_rate_limit_error(self, app: Flask, trial_app_workflow: MagicMock, account: Account) -> None:
def test_workflow_rate_limit_error(self, app: Flask, trial_app_workflow, account):
api = module.TrialAppWorkflowRunApi()
method = unwrap(api.post)
@ -194,7 +227,7 @@ class TestTrialAppWorkflowRunApi:
with pytest.raises(InvokeRateLimitHttpError):
method(api, account, trial_app_workflow)
def test_workflow_value_error(self, app: Flask, trial_app_workflow: MagicMock, account: Account) -> None:
def test_workflow_value_error(self, app: Flask, trial_app_workflow, account):
api = module.TrialAppWorkflowRunApi()
method = unwrap(api.post)
@ -209,7 +242,7 @@ class TestTrialAppWorkflowRunApi:
with pytest.raises(ValueError):
method(api, account, trial_app_workflow)
def test_workflow_generic_exception(self, app: Flask, trial_app_workflow: MagicMock, account: Account) -> None:
def test_workflow_generic_exception(self, app: Flask, trial_app_workflow, account):
api = module.TrialAppWorkflowRunApi()
method = unwrap(api.post)
@ -226,7 +259,7 @@ class TestTrialAppWorkflowRunApi:
class TestTrialChatApi:
def test_not_chat_app(self, app: Flask, account: Account) -> None:
def test_not_chat_app(self, app: Flask, account):
api = module.TrialChatApi()
method = unwrap(api.post)
@ -234,7 +267,7 @@ class TestTrialChatApi:
with pytest.raises(NotChatAppError):
method(api, account, MagicMock(mode="completion"))
def test_success(self, app: Flask, trial_app_chat: MagicMock, account: Account) -> None:
def test_success(self, app: Flask, trial_app_chat, account):
api = module.TrialChatApi()
method = unwrap(api.post)
@ -247,7 +280,7 @@ class TestTrialChatApi:
assert result is not None
def test_chat_conversation_not_exists(self, app: Flask, trial_app_chat: MagicMock, account: Account) -> None:
def test_chat_conversation_not_exists(self, app: Flask, trial_app_chat, account):
api = module.TrialChatApi()
method = unwrap(api.post)
@ -262,7 +295,7 @@ class TestTrialChatApi:
with pytest.raises(NotFound):
method(api, account, trial_app_chat)
def test_chat_conversation_completed(self, app: Flask, trial_app_chat: MagicMock, account: Account) -> None:
def test_chat_conversation_completed(self, app: Flask, trial_app_chat, account):
api = module.TrialChatApi()
method = unwrap(api.post)
@ -277,7 +310,7 @@ class TestTrialChatApi:
with pytest.raises(ConversationCompletedError):
method(api, account, trial_app_chat)
def test_chat_app_config_broken(self, app: Flask, trial_app_chat: MagicMock, account: Account) -> None:
def test_chat_app_config_broken(self, app: Flask, trial_app_chat, account):
api = module.TrialChatApi()
method = unwrap(api.post)
@ -292,7 +325,7 @@ class TestTrialChatApi:
with pytest.raises(AppUnavailableError):
method(api, account, trial_app_chat)
def test_chat_provider_not_init(self, app: Flask, trial_app_chat: MagicMock, account: Account) -> None:
def test_chat_provider_not_init(self, app: Flask, trial_app_chat, account):
api = module.TrialChatApi()
method = unwrap(api.post)
@ -307,7 +340,7 @@ class TestTrialChatApi:
with pytest.raises(ProviderNotInitializeError):
method(api, account, trial_app_chat)
def test_chat_quota_exceeded(self, app: Flask, trial_app_chat: MagicMock, account: Account) -> None:
def test_chat_quota_exceeded(self, app: Flask, trial_app_chat, account):
api = module.TrialChatApi()
method = unwrap(api.post)
@ -322,7 +355,7 @@ class TestTrialChatApi:
with pytest.raises(ProviderQuotaExceededError):
method(api, account, trial_app_chat)
def test_chat_model_not_support(self, app: Flask, trial_app_chat: MagicMock, account: Account) -> None:
def test_chat_model_not_support(self, app: Flask, trial_app_chat, account):
api = module.TrialChatApi()
method = unwrap(api.post)
@ -337,7 +370,7 @@ class TestTrialChatApi:
with pytest.raises(ProviderModelCurrentlyNotSupportError):
method(api, account, trial_app_chat)
def test_chat_invoke_error(self, app: Flask, trial_app_chat: MagicMock, account: Account) -> None:
def test_chat_invoke_error(self, app: Flask, trial_app_chat, account):
api = module.TrialChatApi()
method = unwrap(api.post)
@ -352,7 +385,7 @@ class TestTrialChatApi:
with pytest.raises(CompletionRequestError):
method(api, account, trial_app_chat)
def test_chat_rate_limit_error(self, app: Flask, trial_app_chat: MagicMock, account: Account) -> None:
def test_chat_rate_limit_error(self, app: Flask, trial_app_chat, account):
api = module.TrialChatApi()
method = unwrap(api.post)
@ -367,7 +400,7 @@ class TestTrialChatApi:
with pytest.raises(InvokeRateLimitHttpError):
method(api, account, trial_app_chat)
def test_chat_value_error(self, app: Flask, trial_app_chat: MagicMock, account: Account) -> None:
def test_chat_value_error(self, app: Flask, trial_app_chat, account):
api = module.TrialChatApi()
method = unwrap(api.post)
@ -382,7 +415,7 @@ class TestTrialChatApi:
with pytest.raises(ValueError):
method(api, account, trial_app_chat)
def test_chat_generic_exception(self, app: Flask, trial_app_chat: MagicMock, account: Account) -> None:
def test_chat_generic_exception(self, app: Flask, trial_app_chat, account):
api = module.TrialChatApi()
method = unwrap(api.post)
@ -399,7 +432,7 @@ class TestTrialChatApi:
class TestTrialCompletionApi:
def test_not_completion_app(self, app: Flask, account: Account) -> None:
def test_not_completion_app(self, app: Flask, account):
api = module.TrialCompletionApi()
method = unwrap(api.post)
@ -407,7 +440,7 @@ class TestTrialCompletionApi:
with pytest.raises(NotCompletionAppError):
method(api, account, MagicMock(mode=AppMode.CHAT))
def test_success(self, app: Flask, trial_app_completion: MagicMock, account: Account) -> None:
def test_success(self, app: Flask, trial_app_completion, account):
api = module.TrialCompletionApi()
method = unwrap(api.post)
@ -420,7 +453,7 @@ class TestTrialCompletionApi:
assert result is not None
def test_completion_app_config_broken(self, app: Flask, trial_app_completion: MagicMock, account: Account) -> None:
def test_completion_app_config_broken(self, app: Flask, trial_app_completion, account):
api = module.TrialCompletionApi()
method = unwrap(api.post)
@ -435,7 +468,7 @@ class TestTrialCompletionApi:
with pytest.raises(AppUnavailableError):
method(api, account, trial_app_completion)
def test_completion_provider_not_init(self, app: Flask, trial_app_completion: MagicMock, account: Account) -> None:
def test_completion_provider_not_init(self, app: Flask, trial_app_completion, account):
api = module.TrialCompletionApi()
method = unwrap(api.post)
@ -450,7 +483,7 @@ class TestTrialCompletionApi:
with pytest.raises(ProviderNotInitializeError):
method(api, account, trial_app_completion)
def test_completion_quota_exceeded(self, app: Flask, trial_app_completion: MagicMock, account: Account) -> None:
def test_completion_quota_exceeded(self, app: Flask, trial_app_completion, account):
api = module.TrialCompletionApi()
method = unwrap(api.post)
@ -465,7 +498,7 @@ class TestTrialCompletionApi:
with pytest.raises(ProviderQuotaExceededError):
method(api, account, trial_app_completion)
def test_completion_model_not_support(self, app: Flask, trial_app_completion: MagicMock, account: Account) -> None:
def test_completion_model_not_support(self, app: Flask, trial_app_completion, account):
api = module.TrialCompletionApi()
method = unwrap(api.post)
@ -480,7 +513,7 @@ class TestTrialCompletionApi:
with pytest.raises(ProviderModelCurrentlyNotSupportError):
method(api, account, trial_app_completion)
def test_completion_invoke_error(self, app: Flask, trial_app_completion: MagicMock, account: Account) -> None:
def test_completion_invoke_error(self, app: Flask, trial_app_completion, account):
api = module.TrialCompletionApi()
method = unwrap(api.post)
@ -495,7 +528,7 @@ class TestTrialCompletionApi:
with pytest.raises(CompletionRequestError):
method(api, account, trial_app_completion)
def test_completion_rate_limit_error(self, app: Flask, trial_app_completion: MagicMock, account: Account) -> None:
def test_completion_rate_limit_error(self, app: Flask, trial_app_completion, account):
api = module.TrialCompletionApi()
method = unwrap(api.post)
@ -510,7 +543,7 @@ class TestTrialCompletionApi:
with pytest.raises(InternalServerError):
method(api, account, trial_app_completion)
def test_completion_value_error(self, app: Flask, trial_app_completion: MagicMock, account: Account) -> None:
def test_completion_value_error(self, app: Flask, trial_app_completion, account):
api = module.TrialCompletionApi()
method = unwrap(api.post)
@ -525,7 +558,7 @@ class TestTrialCompletionApi:
with pytest.raises(ValueError):
method(api, account, trial_app_completion)
def test_completion_generic_exception(self, app: Flask, trial_app_completion: MagicMock, account: Account) -> None:
def test_completion_generic_exception(self, app: Flask, trial_app_completion, account):
api = module.TrialCompletionApi()
method = unwrap(api.post)
@ -542,7 +575,7 @@ class TestTrialCompletionApi:
class TestTrialMessageSuggestedQuestionApi:
def test_not_chat_app(self, app: Flask, account: Account) -> None:
def test_not_chat_app(self, app: Flask, account):
api = module.TrialMessageSuggestedQuestionApi()
method = unwrap(api.get)
@ -550,7 +583,7 @@ class TestTrialMessageSuggestedQuestionApi:
with pytest.raises(NotChatAppError):
method(api, account, MagicMock(mode="completion"), str(uuid4()))
def test_success(self, app: Flask, trial_app_chat: MagicMock, account: Account) -> None:
def test_success(self, app: Flask, trial_app_chat, account):
api = module.TrialMessageSuggestedQuestionApi()
method = unwrap(api.get)
@ -566,7 +599,7 @@ class TestTrialMessageSuggestedQuestionApi:
assert result == {"data": ["q1", "q2"]}
def test_conversation_not_exists(self, app: Flask, trial_app_chat: MagicMock, account: Account) -> None:
def test_conversation_not_exists(self, app: Flask, trial_app_chat, account):
api = module.TrialMessageSuggestedQuestionApi()
method = unwrap(api.get)
@ -583,14 +616,14 @@ class TestTrialMessageSuggestedQuestionApi:
class TestTrialAppParameterApi:
def test_app_unavailable(self) -> None:
def test_app_unavailable(self):
api = module.TrialAppParameterApi()
method = unwrap(api.get)
with pytest.raises(AppUnavailableError):
method(api, None)
def test_success_non_workflow(self, valid_parameters: dict[str, object]) -> None:
def test_success_non_workflow(self, valid_parameters):
api = module.TrialAppParameterApi()
method = unwrap(api.get)
@ -617,11 +650,12 @@ class TestTrialAppParameterApi:
class TestTrialChatAudioApi:
def test_success(self, app: Flask, trial_app_chat: MagicMock, account: Account) -> None:
def test_success(self, app: Flask, trial_app_chat, account):
api = module.TrialChatAudioApi()
method = unwrap(api.post)
file_data = _file_data()
file_data: Any = BytesIO(b"fake audio data")
file_data.filename = "test.wav"
with (
app.test_request_context(
@ -634,11 +668,12 @@ class TestTrialChatAudioApi:
assert result == {"text": "hello"}
def test_app_config_broken(self, app: Flask, trial_app_chat: MagicMock, account: Account) -> None:
def test_app_config_broken(self, app: Flask, trial_app_chat, account):
api = module.TrialChatAudioApi()
method = unwrap(api.post)
file_data = _file_data()
file_data: Any = BytesIO(b"fake audio data")
file_data.filename = "test.wav"
with (
app.test_request_context(
@ -653,11 +688,12 @@ class TestTrialChatAudioApi:
with pytest.raises(module.AppUnavailableError):
method(api, account, trial_app_chat)
def test_no_audio_uploaded(self, app: Flask, trial_app_chat: MagicMock, account: Account) -> None:
def test_no_audio_uploaded(self, app: Flask, trial_app_chat, account):
api = module.TrialChatAudioApi()
method = unwrap(api.post)
file_data = _file_data()
file_data: Any = BytesIO(b"fake audio data")
file_data.filename = "test.wav"
with (
app.test_request_context(
@ -672,11 +708,12 @@ class TestTrialChatAudioApi:
with pytest.raises(module.NoAudioUploadedError):
method(api, account, trial_app_chat)
def test_audio_too_large(self, app: Flask, trial_app_chat: MagicMock, account: Account) -> None:
def test_audio_too_large(self, app: Flask, trial_app_chat, account):
api = module.TrialChatAudioApi()
method = unwrap(api.post)
file_data = _file_data()
file_data: Any = BytesIO(b"fake audio data")
file_data.filename = "test.wav"
with (
app.test_request_context(
@ -691,11 +728,12 @@ class TestTrialChatAudioApi:
with pytest.raises(module.AudioTooLargeError):
method(api, account, trial_app_chat)
def test_unsupported_audio_type(self, app: Flask, trial_app_chat: MagicMock, account: Account) -> None:
def test_unsupported_audio_type(self, app: Flask, trial_app_chat, account):
api = module.TrialChatAudioApi()
method = unwrap(api.post)
file_data = _file_data()
file_data: Any = BytesIO(b"fake audio data")
file_data.filename = "test.wav"
with (
app.test_request_context(
@ -710,11 +748,12 @@ class TestTrialChatAudioApi:
with pytest.raises(module.UnsupportedAudioTypeError):
method(api, account, trial_app_chat)
def test_provider_not_support_tts(self, app: Flask, trial_app_chat: MagicMock, account: Account) -> None:
def test_provider_not_support_tts(self, app: Flask, trial_app_chat, account):
api = module.TrialChatAudioApi()
method = unwrap(api.post)
file_data = _file_data()
file_data: Any = BytesIO(b"fake audio data")
file_data.filename = "test.wav"
with (
app.test_request_context(
@ -729,11 +768,12 @@ class TestTrialChatAudioApi:
with pytest.raises(module.ProviderNotSupportSpeechToTextError):
method(api, account, trial_app_chat)
def test_provider_not_init(self, app: Flask, trial_app_chat: MagicMock, account: Account) -> None:
def test_provider_not_init(self, app: Flask, trial_app_chat, account):
api = module.TrialChatAudioApi()
method = unwrap(api.post)
file_data = _file_data()
file_data: Any = BytesIO(b"fake audio data")
file_data.filename = "test.wav"
with (
app.test_request_context(
@ -744,11 +784,12 @@ class TestTrialChatAudioApi:
with pytest.raises(ProviderNotInitializeError):
method(api, account, trial_app_chat)
def test_quota_exceeded(self, app: Flask, trial_app_chat: MagicMock, account: Account) -> None:
def test_quota_exceeded(self, app: Flask, trial_app_chat, account):
api = module.TrialChatAudioApi()
method = unwrap(api.post)
file_data = _file_data()
file_data: Any = BytesIO(b"fake audio data")
file_data.filename = "test.wav"
with (
app.test_request_context(
@ -761,7 +802,7 @@ class TestTrialChatAudioApi:
class TestTrialChatTextApi:
def test_success(self, app: Flask, trial_app_chat: MagicMock, account: Account) -> None:
def test_success(self, app: Flask, trial_app_chat, account):
api = module.TrialChatTextApi()
method = unwrap(api.post)
@ -774,7 +815,7 @@ class TestTrialChatTextApi:
assert result == {"audio": "base64_data"}
def test_app_config_broken(self, app: Flask, trial_app_chat: MagicMock, account: Account) -> None:
def test_app_config_broken(self, app: Flask, trial_app_chat, account):
api = module.TrialChatTextApi()
method = unwrap(api.post)
@ -789,7 +830,7 @@ class TestTrialChatTextApi:
with pytest.raises(module.AppUnavailableError):
method(api, account, trial_app_chat)
def test_provider_not_support(self, app: Flask, trial_app_chat: MagicMock, account: Account) -> None:
def test_provider_not_support(self, app: Flask, trial_app_chat, account):
api = module.TrialChatTextApi()
method = unwrap(api.post)
@ -804,7 +845,7 @@ class TestTrialChatTextApi:
with pytest.raises(module.ProviderNotSupportSpeechToTextError):
method(api, account, trial_app_chat)
def test_audio_too_large(self, app: Flask, trial_app_chat: MagicMock, account: Account) -> None:
def test_audio_too_large(self, app: Flask, trial_app_chat, account):
api = module.TrialChatTextApi()
method = unwrap(api.post)
@ -819,7 +860,7 @@ class TestTrialChatTextApi:
with pytest.raises(module.AudioTooLargeError):
method(api, account, trial_app_chat)
def test_no_audio_uploaded(self, app: Flask, trial_app_chat: MagicMock, account: Account) -> None:
def test_no_audio_uploaded(self, app: Flask, trial_app_chat, account):
api = module.TrialChatTextApi()
method = unwrap(api.post)
@ -834,7 +875,7 @@ class TestTrialChatTextApi:
with pytest.raises(module.NoAudioUploadedError):
method(api, account, trial_app_chat)
def test_provider_not_init(self, app: Flask, trial_app_chat: MagicMock, account: Account) -> None:
def test_provider_not_init(self, app: Flask, trial_app_chat, account):
api = module.TrialChatTextApi()
method = unwrap(api.post)
@ -845,7 +886,7 @@ class TestTrialChatTextApi:
with pytest.raises(ProviderNotInitializeError):
method(api, account, trial_app_chat)
def test_quota_exceeded(self, app: Flask, trial_app_chat: MagicMock, account: Account) -> None:
def test_quota_exceeded(self, app: Flask, trial_app_chat, account):
api = module.TrialChatTextApi()
method = unwrap(api.post)
@ -856,7 +897,7 @@ class TestTrialChatTextApi:
with pytest.raises(ProviderQuotaExceededError):
method(api, account, trial_app_chat)
def test_model_not_support(self, app: Flask, trial_app_chat: MagicMock, account: Account) -> None:
def test_model_not_support(self, app: Flask, trial_app_chat, account):
api = module.TrialChatTextApi()
method = unwrap(api.post)
@ -867,7 +908,7 @@ class TestTrialChatTextApi:
with pytest.raises(ProviderModelCurrentlyNotSupportError):
method(api, account, trial_app_chat)
def test_invoke_error(self, app: Flask, trial_app_chat: MagicMock, account: Account) -> None:
def test_invoke_error(self, app: Flask, trial_app_chat, account):
api = module.TrialChatTextApi()
method = unwrap(api.post)
@ -880,7 +921,7 @@ class TestTrialChatTextApi:
class TestTrialAppWorkflowTaskStopApi:
def test_not_workflow_app(self, app: Flask, trial_app_chat: MagicMock) -> None:
def test_not_workflow_app(self, app: Flask, trial_app_chat):
api = module.TrialAppWorkflowTaskStopApi()
method = unwrap(api.post)
@ -888,7 +929,7 @@ class TestTrialAppWorkflowTaskStopApi:
with pytest.raises(NotWorkflowAppError):
method(api, trial_app_chat, str(uuid4()))
def test_success(self, app: Flask, trial_app_workflow: MagicMock) -> None:
def test_success(self, app: Flask, trial_app_workflow, account):
api = module.TrialAppWorkflowTaskStopApi()
method = unwrap(api.post)
@ -906,7 +947,7 @@ class TestTrialAppWorkflowTaskStopApi:
class TestTrialSitApi:
def test_no_site(self, app: Flask) -> None:
def test_no_site(self, app: Flask):
api = module.TrialSitApi()
method = unwrap(api.get)
app_model = MagicMock()
@ -917,7 +958,7 @@ class TestTrialSitApi:
with pytest.raises(Forbidden):
method(api, app_model)
def test_archived_tenant(self, app: Flask) -> None:
def test_archived_tenant(self, app: Flask):
api = module.TrialSitApi()
method = unwrap(api.get)
@ -932,7 +973,7 @@ class TestTrialSitApi:
with pytest.raises(Forbidden):
method(api, app_model)
def test_success(self, app: Flask) -> None:
def test_success(self, app: Flask):
api = module.TrialSitApi()
method = unwrap(api.get)
@ -957,11 +998,12 @@ class TestTrialSitApi:
class TestTrialChatAudioApiExceptionHandlers:
def test_provider_not_init(self, app: Flask, trial_app_chat: MagicMock, account: Account) -> None:
def test_provider_not_init(self, app: Flask, trial_app_chat, account):
api = module.TrialChatAudioApi()
method = unwrap(api.post)
file_data = _file_data()
file_data: Any = BytesIO(b"fake audio data")
file_data.filename = "test.wav"
with (
app.test_request_context(
@ -976,11 +1018,12 @@ class TestTrialChatAudioApiExceptionHandlers:
with pytest.raises(ProviderNotInitializeError):
method(api, account, trial_app_chat)
def test_quota_exceeded(self, app: Flask, trial_app_chat: MagicMock, account: Account) -> None:
def test_quota_exceeded(self, app: Flask, trial_app_chat, account):
api = module.TrialChatAudioApi()
method = unwrap(api.post)
file_data = _file_data()
file_data: Any = BytesIO(b"fake audio data")
file_data.filename = "test.wav"
with (
app.test_request_context(
@ -995,11 +1038,12 @@ class TestTrialChatAudioApiExceptionHandlers:
with pytest.raises(ProviderQuotaExceededError):
method(api, account, trial_app_chat)
def test_invoke_error(self, app: Flask, trial_app_chat: MagicMock, account: Account) -> None:
def test_invoke_error(self, app: Flask, trial_app_chat, account):
api = module.TrialChatAudioApi()
method = unwrap(api.post)
file_data = _file_data()
file_data: Any = BytesIO(b"fake audio data")
file_data.filename = "test.wav"
with (
app.test_request_context(
@ -1016,7 +1060,7 @@ class TestTrialChatAudioApiExceptionHandlers:
class TestTrialChatTextApiExceptionHandlers:
def test_app_config_broken(self, app: Flask, trial_app_chat: MagicMock, account: Account) -> None:
def test_app_config_broken(self, app: Flask, trial_app_chat, account):
api = module.TrialChatTextApi()
method = unwrap(api.post)
@ -1031,7 +1075,7 @@ class TestTrialChatTextApiExceptionHandlers:
with pytest.raises(module.AppUnavailableError):
method(api, account, trial_app_chat)
def test_unsupported_audio_type(self, app: Flask, trial_app_chat: MagicMock, account: Account) -> None:
def test_unsupported_audio_type(self, app: Flask, trial_app_chat, account):
api = module.TrialChatTextApi()
method = unwrap(api.post)

View File

@ -1,4 +1,5 @@
import inspect
from datetime import UTC, datetime
from unittest.mock import patch
import pytest
@ -16,9 +17,32 @@ from controllers.console.workspace.endpoint import (
EndpointListApi,
EndpointListForSinglePluginApi,
)
from core.plugin.entities.endpoint import EndpointEntityWithInstance
from core.plugin.impl.exc import PluginPermissionDeniedError
def _endpoint_entity() -> EndpointEntityWithInstance:
now = datetime(2026, 1, 1, tzinfo=UTC)
return EndpointEntityWithInstance(
id="e1",
created_at=now,
updated_at=now,
tenant_id="t1",
plugin_id="p1",
settings={
"secret": "value",
"enabled": True,
"ids": ["a", "b"],
"nested": {"limit": 3},
},
expired_at=now,
name="endpoint",
enabled=True,
url="https://example.test/hook-1",
hook_id="hook-1",
)
class TestEndpointCollectionApi:
def test_create_success(self, app: Flask):
api = EndpointCollectionApi()
@ -102,12 +126,34 @@ class TestEndpointListApi:
with (
app.test_request_context("/?page=1&page_size=10"),
patch("controllers.console.workspace.endpoint.EndpointService.list_endpoints", return_value=[{"id": "e1"}]),
patch(
"controllers.console.workspace.endpoint.EndpointService.list_endpoints",
return_value=[_endpoint_entity()],
),
):
result = method(api, "t1", "u1")
assert "endpoints" in result
assert len(result["endpoints"]) == 1
assert result["endpoints"] == [
{
"id": "e1",
"created_at": "2026-01-01T00:00:00Z",
"updated_at": "2026-01-01T00:00:00Z",
"settings": {
"secret": "value",
"enabled": True,
"ids": ["a", "b"],
"nested": {"limit": 3},
},
"tenant_id": "t1",
"plugin_id": "p1",
"expired_at": "2026-01-01T00:00:00Z",
"declaration": {"settings": [], "endpoints": []},
"name": "endpoint",
"enabled": True,
"url": "https://example.test/hook-1",
"hook_id": "hook-1",
}
]
def test_list_invalid_query(self, app: Flask):
api = EndpointListApi()
@ -129,12 +175,13 @@ class TestEndpointListForSinglePluginApi:
app.test_request_context("/?page=1&page_size=10&plugin_id=p1"),
patch(
"controllers.console.workspace.endpoint.EndpointService.list_endpoints_for_single_plugin",
return_value=[{"id": "e1"}],
return_value=[_endpoint_entity()],
),
):
result = method(api, "t1", "u1")
assert "endpoints" in result
assert result["endpoints"][0]["id"] == "e1"
assert result["endpoints"][0]["settings"]["nested"] == {"limit": 3}
def test_list_for_plugin_missing_param(self, app: Flask):
api = EndpointListForSinglePluginApi()

View File

@ -1,3 +1,4 @@
from datetime import datetime
from inspect import unwrap
from types import SimpleNamespace
from unittest.mock import ANY, Mock
@ -46,12 +47,73 @@ def _snippet(**overrides) -> CustomizedSnippet:
"name": "Snippet",
"description": "Description",
"type": snippets_module.SnippetType.NODE,
"version": 3,
"use_count": 7,
"is_published": True,
"icon_info": {"icon": "star", "icon_background": "#101828", "icon_type": "emoji"},
"input_fields": '[{"label": "Question", "variable": "query", "type": "text-input"}]',
"created_by": "account-1",
"created_at": datetime(2024, 1, 2, 3, 4, 5),
"updated_by": None,
"updated_at": datetime(2024, 1, 3, 4, 5, 6),
}
data.update(overrides)
return CustomizedSnippet(**data)
def _patch_snippet_response_properties(monkeypatch: pytest.MonkeyPatch) -> None:
monkeypatch.setattr(
CustomizedSnippet,
"tags",
property(lambda _snippet: [{"id": "tag-1", "name": "Search", "type": "snippet"}]),
)
monkeypatch.setattr(CustomizedSnippet, "created_by_account", property(lambda _snippet: _account("account-1")))
monkeypatch.setattr(CustomizedSnippet, "updated_by_account", property(lambda _snippet: None))
def _expected_snippet_list_item(snippet: CustomizedSnippet) -> dict:
return {
"id": snippet.id,
"name": snippet.name,
"description": snippet.description,
"type": snippet.type,
"version": snippet.version,
"use_count": snippet.use_count,
"is_published": snippet.is_published,
"icon_info": snippet.icon_info,
"tags": [{"id": "tag-1", "name": "Search", "type": "snippet"}],
"created_by": snippet.created_by,
"author_name": "Test User",
"created_at": int(snippet.created_at.timestamp()),
"updated_by": snippet.updated_by,
"updated_at": int(snippet.updated_at.timestamp()),
}
def _expected_snippet_response(snippet: CustomizedSnippet) -> dict:
return {
"id": snippet.id,
"name": snippet.name,
"description": snippet.description,
"type": snippet.type,
"version": snippet.version,
"use_count": snippet.use_count,
"is_published": snippet.is_published,
"icon_info": snippet.icon_info,
"graph": {},
"input_fields": [{"label": "Question", "variable": "query", "type": "text-input"}],
"tags": [{"id": "tag-1", "name": "Search", "type": "snippet"}],
"created_by": {
"id": "account-1",
"name": "Test User",
"email": "account-1@example.com",
},
"created_at": int(snippet.created_at.timestamp()),
"updated_by": None,
"updated_at": int(snippet.updated_at.timestamp()),
}
def test_normalize_snippet_list_query_args_sorts_indexed_values():
query_args = snippets_module.MultiDict(
[
@ -75,7 +137,7 @@ def test_list_snippets_returns_pagination(app: Flask, monkeypatch: pytest.Monkey
tag_id = "11111111-1111-1111-1111-111111111111"
get_snippets = Mock(return_value=(snippets, 1, False))
monkeypatch.setattr(snippets_module.SnippetService, "get_snippets", get_snippets)
monkeypatch.setattr(snippets_module, "marshal", Mock(return_value=[{"id": "snippet-1"}]))
_patch_snippet_response_properties(monkeypatch)
api = snippets_module.CustomizedSnippetsApi()
handler = unwrap(api.get)
@ -87,7 +149,7 @@ def test_list_snippets_returns_pagination(app: Flask, monkeypatch: pytest.Monkey
assert status_code == 200
assert response == {
"data": [{"id": "snippet-1"}],
"data": [_expected_snippet_list_item(snippets[0])],
"page": 2,
"limit": 10,
"total": 1,
@ -110,6 +172,7 @@ def test_create_snippet_defaults_unknown_type_and_returns_created(app: Flask, mo
snippet = _snippet()
create_snippet = Mock(return_value=snippet)
monkeypatch.setattr(snippets_module.SnippetService, "create_snippet", create_snippet)
_patch_snippet_response_properties(monkeypatch)
monkeypatch.setattr(
snippets_module.CreateSnippetPayload,
"model_validate",
@ -124,7 +187,6 @@ def test_create_snippet_defaults_unknown_type_and_returns_created(app: Flask, mo
)
),
)
monkeypatch.setattr(snippets_module, "marshal", Mock(return_value={"id": "snippet-1"}))
api = snippets_module.CustomizedSnippetsApi()
handler = unwrap(api.post)
@ -137,7 +199,7 @@ def test_create_snippet_defaults_unknown_type_and_returns_created(app: Flask, mo
response, status_code = handler(api, "tenant-1", user)
assert status_code == 201
assert response == {"id": "snippet-1"}
assert response == _expected_snippet_response(snippet)
assert create_snippet.call_args.kwargs["snippet_type"] == snippets_module.SnippetType.NODE
@ -184,7 +246,7 @@ def test_get_snippet_detail_raises_when_missing(app: Flask, monkeypatch: pytest.
def test_get_snippet_detail_returns_snippet(app: Flask, monkeypatch: pytest.MonkeyPatch):
snippet = _snippet()
monkeypatch.setattr(snippets_module.SnippetService, "get_snippet_by_id", Mock(return_value=snippet))
monkeypatch.setattr(snippets_module, "marshal", Mock(return_value={"id": "snippet-1"}))
_patch_snippet_response_properties(monkeypatch)
api = snippets_module.CustomizedSnippetDetailApi()
handler = unwrap(api.get)
@ -193,7 +255,7 @@ def test_get_snippet_detail_returns_snippet(app: Flask, monkeypatch: pytest.Monk
response, status_code = handler(api, "tenant-1", snippet_id="snippet-1")
assert status_code == 200
assert response == {"id": "snippet-1"}
assert response == _expected_snippet_response(snippet)
def test_patch_snippet_returns_400_for_empty_payload(app: Flask, monkeypatch: pytest.MonkeyPatch):
@ -230,7 +292,7 @@ def test_patch_snippet_updates_and_commits(app: Flask, monkeypatch: pytest.Monke
monkeypatch.setattr(snippets_module.SnippetService, "update_snippet", update_snippet)
monkeypatch.setattr(snippets_module, "Session", SessionContext)
monkeypatch.setattr(snippets_module, "db", SimpleNamespace(engine=object()))
monkeypatch.setattr(snippets_module, "marshal", Mock(return_value={"id": "snippet-1", "name": "New"}))
_patch_snippet_response_properties(monkeypatch)
api = snippets_module.CustomizedSnippetDetailApi()
handler = unwrap(api.patch)
@ -243,7 +305,7 @@ def test_patch_snippet_updates_and_commits(app: Flask, monkeypatch: pytest.Monke
response, status_code = handler(api, "tenant-1", user, snippet_id="snippet-1")
assert status_code == 200
assert response == {"id": "snippet-1", "name": "New"}
assert response == _expected_snippet_response(updated_snippet)
update_snippet.assert_called_once()
assert update_snippet.call_args.kwargs["data"] == {
"name": "New",

View File

@ -26,7 +26,9 @@ from controllers.console.workspace.workspace import (
WebappLogoWorkspaceApi,
WorkspaceInfoApi,
WorkspaceListApi,
WorkspaceLogoUploadResponse,
WorkspacePermissionApi,
WorkspacePermissionResponse,
)
from enums.cloud_plan import CloudPlan
from libs.datetime_utils import naive_utc_now
@ -587,7 +589,8 @@ class TestWebappLogoWorkspaceApi:
result, status = method(api, user)
assert status == 201
assert result["id"] == "file1"
assert result == {"id": "file1"}
assert WorkspaceLogoUploadResponse.model_validate(result).model_dump(mode="json") == {"id": "file1"}
def test_filename_missing(self, app: Flask):
api = WebappLogoWorkspaceApi()
@ -676,7 +679,7 @@ class TestWorkspaceInfoApi:
patch("controllers.console.workspace.workspace.db.session.commit"),
patch(
"controllers.console.workspace.workspace.WorkspaceService.get_tenant_info",
return_value={"name": "New Name"},
return_value={"id": "t1", "name": "New Name"},
),
):
result = method(api, "t1")
@ -717,7 +720,13 @@ class TestWorkspacePermissionApi:
result, status = method(api, "t1")
assert status == 200
assert result["workspace_id"] == "t1"
expected = {
"workspace_id": "t1",
"allow_member_invite": True,
"allow_owner_transfer": False,
}
assert result == expected
assert WorkspacePermissionResponse.model_validate(result).model_dump(mode="json") == expected
def test_no_current_tenant(self, app: Flask):
api = WorkspacePermissionApi()

View File

@ -1,8 +1,7 @@
from types import SimpleNamespace
from flask_restx import marshal
from fields.snippet_fields import snippet_list_fields
from fields.snippet_fields import SnippetListItemResponse
from libs.helper import dump_response
def test_snippet_list_fields_include_author_name() -> None:
@ -23,6 +22,6 @@ def test_snippet_list_fields_include_author_name() -> None:
updated_at=None,
)
result = marshal(snippet, snippet_list_fields)
result = dump_response(SnippetListItemResponse, snippet)
assert result["author_name"] == "Alice"

View File

@ -27,8 +27,6 @@ import {
zPostAccountDeleteFeedbackBody,
zPostAccountDeleteFeedbackResponse,
zPostAccountDeleteResponse,
zPostAccountEducationBody,
zPostAccountEducationResponse,
zPostAccountInitBody,
zPostAccountInitResponse,
zPostAccountInterfaceLanguageBody,
@ -222,25 +220,13 @@ export const get5 = oc
})
.output(zGetAccountEducationResponse)
export const post8 = oc
.route({
inputStructure: 'detailed',
method: 'POST',
operationId: 'postAccountEducation',
path: '/account/education',
tags: ['console'],
})
.input(z.object({ body: zPostAccountEducationBody }))
.output(zPostAccountEducationResponse)
export const education = {
get: get5,
post: post8,
autocomplete,
verify: verify2,
}
export const post9 = oc
export const post8 = oc
.route({
inputStructure: 'detailed',
method: 'POST',
@ -252,7 +238,7 @@ export const post9 = oc
.output(zPostAccountInitResponse)
export const init = {
post: post9,
post: post8,
}
export const get6 = oc
@ -269,7 +255,7 @@ export const integrates = {
get: get6,
}
export const post10 = oc
export const post9 = oc
.route({
inputStructure: 'detailed',
method: 'POST',
@ -281,10 +267,10 @@ export const post10 = oc
.output(zPostAccountInterfaceLanguageResponse)
export const interfaceLanguage = {
post: post10,
post: post9,
}
export const post11 = oc
export const post10 = oc
.route({
inputStructure: 'detailed',
method: 'POST',
@ -296,10 +282,10 @@ export const post11 = oc
.output(zPostAccountInterfaceThemeResponse)
export const interfaceTheme = {
post: post11,
post: post10,
}
export const post12 = oc
export const post11 = oc
.route({
inputStructure: 'detailed',
method: 'POST',
@ -311,10 +297,10 @@ export const post12 = oc
.output(zPostAccountNameResponse)
export const name = {
post: post12,
post: post11,
}
export const post13 = oc
export const post12 = oc
.route({
inputStructure: 'detailed',
method: 'POST',
@ -326,7 +312,7 @@ export const post13 = oc
.output(zPostAccountPasswordResponse)
export const password = {
post: post13,
post: post12,
}
export const get7 = oc
@ -343,7 +329,7 @@ export const profile = {
get: get7,
}
export const post14 = oc
export const post13 = oc
.route({
inputStructure: 'detailed',
method: 'POST',
@ -355,7 +341,7 @@ export const post14 = oc
.output(zPostAccountTimezoneResponse)
export const timezone = {
post: post14,
post: post13,
}
export const account = {

View File

@ -12,7 +12,7 @@ export type AccountAvatarPayload = {
avatar: string
}
export type Account = {
export type AccountResponse = {
avatar?: string | null
readonly avatar_url: string | null
created_at?: number | null
@ -81,16 +81,6 @@ export type EducationStatusResponse = {
result?: boolean | null
}
export type EducationActivatePayload = {
institution: string
role: string
token: string
}
export type EducationActivateResponse = {
[key: string]: unknown
}
export type EducationAutocompleteResponse = {
curr_page?: number | null
data?: Array<string>
@ -140,7 +130,7 @@ export type AccountIntegrateResponse = {
provider: string
}
export type AccountWritable = {
export type AccountResponseWritable = {
avatar?: string | null
created_at?: number | null
email: string
@ -177,7 +167,7 @@ export type PostAccountAvatarData = {
}
export type PostAccountAvatarResponses = {
200: Account
200: AccountResponse
}
export type PostAccountAvatarResponse = PostAccountAvatarResponses[keyof PostAccountAvatarResponses]
@ -218,7 +208,7 @@ export type PostAccountChangeEmailResetData = {
}
export type PostAccountChangeEmailResetResponses = {
200: Account
200: AccountResponse
}
export type PostAccountChangeEmailResetResponse
@ -293,20 +283,6 @@ export type GetAccountEducationResponses = {
export type GetAccountEducationResponse
= GetAccountEducationResponses[keyof GetAccountEducationResponses]
export type PostAccountEducationData = {
body: EducationActivatePayload
path?: never
query?: never
url: '/account/education'
}
export type PostAccountEducationResponses = {
200: EducationActivateResponse
}
export type PostAccountEducationResponse
= PostAccountEducationResponses[keyof PostAccountEducationResponses]
export type GetAccountEducationAutocompleteData = {
body?: never
path?: never
@ -374,7 +350,7 @@ export type PostAccountInterfaceLanguageData = {
}
export type PostAccountInterfaceLanguageResponses = {
200: Account
200: AccountResponse
}
export type PostAccountInterfaceLanguageResponse
@ -388,7 +364,7 @@ export type PostAccountInterfaceThemeData = {
}
export type PostAccountInterfaceThemeResponses = {
200: Account
200: AccountResponse
}
export type PostAccountInterfaceThemeResponse
@ -402,7 +378,7 @@ export type PostAccountNameData = {
}
export type PostAccountNameResponses = {
200: Account
200: AccountResponse
}
export type PostAccountNameResponse = PostAccountNameResponses[keyof PostAccountNameResponses]
@ -415,7 +391,7 @@ export type PostAccountPasswordData = {
}
export type PostAccountPasswordResponses = {
200: Account
200: AccountResponse
}
export type PostAccountPasswordResponse
@ -429,7 +405,7 @@ export type GetAccountProfileData = {
}
export type GetAccountProfileResponses = {
200: Account
200: AccountResponse
}
export type GetAccountProfileResponse = GetAccountProfileResponses[keyof GetAccountProfileResponses]
@ -442,7 +418,7 @@ export type PostAccountTimezoneData = {
}
export type PostAccountTimezoneResponses = {
200: Account
200: AccountResponse
}
export type PostAccountTimezoneResponse

View File

@ -17,9 +17,9 @@ export const zAccountAvatarPayload = z.object({
})
/**
* Account
* AccountResponse
*/
export const zAccount = z.object({
export const zAccountResponse = z.object({
avatar: z.string().nullish(),
avatar_url: z.string().nullable(),
created_at: z.int().nullish(),
@ -118,20 +118,6 @@ export const zEducationStatusResponse = z.object({
result: z.boolean().nullish(),
})
/**
* EducationActivatePayload
*/
export const zEducationActivatePayload = z.object({
institution: z.string(),
role: z.string(),
token: z.string(),
})
/**
* EducationActivateResponse
*/
export const zEducationActivateResponse = z.record(z.string(), z.unknown())
/**
* EducationAutocompleteResponse
*/
@ -212,9 +198,9 @@ export const zAccountIntegrateListResponse = z.object({
})
/**
* Account
* AccountResponse
*/
export const zAccountWritable = z.object({
export const zAccountResponseWritable = z.object({
avatar: z.string().nullish(),
created_at: z.int().nullish(),
email: z.string(),
@ -242,7 +228,7 @@ export const zPostAccountAvatarBody = zAccountAvatarPayload
/**
* Success
*/
export const zPostAccountAvatarResponse = zAccount
export const zPostAccountAvatarResponse = zAccountResponse
export const zPostAccountChangeEmailBody = zChangeEmailSendPayload
@ -263,7 +249,7 @@ export const zPostAccountChangeEmailResetBody = zChangeEmailResetPayload
/**
* Success
*/
export const zPostAccountChangeEmailResetResponse = zAccount
export const zPostAccountChangeEmailResetResponse = zAccountResponse
export const zPostAccountChangeEmailValidityBody = zChangeEmailValidityPayload
@ -296,13 +282,6 @@ export const zGetAccountDeleteVerifyResponse = zSimpleResultDataResponse
*/
export const zGetAccountEducationResponse = zEducationStatusResponse
export const zPostAccountEducationBody = zEducationActivatePayload
/**
* Success
*/
export const zPostAccountEducationResponse = zEducationActivateResponse
export const zGetAccountEducationAutocompleteQuery = z.object({
keywords: z.string(),
limit: z.int().optional().default(20),
@ -336,37 +315,37 @@ export const zPostAccountInterfaceLanguageBody = zAccountInterfaceLanguagePayloa
/**
* Success
*/
export const zPostAccountInterfaceLanguageResponse = zAccount
export const zPostAccountInterfaceLanguageResponse = zAccountResponse
export const zPostAccountInterfaceThemeBody = zAccountInterfaceThemePayload
/**
* Success
*/
export const zPostAccountInterfaceThemeResponse = zAccount
export const zPostAccountInterfaceThemeResponse = zAccountResponse
export const zPostAccountNameBody = zAccountNamePayload
/**
* Success
*/
export const zPostAccountNameResponse = zAccount
export const zPostAccountNameResponse = zAccountResponse
export const zPostAccountPasswordBody = zAccountPasswordPayload
/**
* Success
*/
export const zPostAccountPasswordResponse = zAccount
export const zPostAccountPasswordResponse = zAccountResponse
/**
* Success
*/
export const zGetAccountProfileResponse = zAccount
export const zGetAccountProfileResponse = zAccountResponse
export const zPostAccountTimezoneBody = zAccountTimezonePayload
/**
* Success
*/
export const zPostAccountTimezoneResponse = zAccount
export const zPostAccountTimezoneResponse = zAccountResponse

View File

@ -269,6 +269,7 @@ export type MessageDetailResponse = {
agent_thoughts?: Array<AgentThought>
annotation?: ConversationAnnotation | null
annotation_hit_history?: ConversationAnnotationHitHistory | null
answer: string
answer_tokens?: number | null
conversation_id: string
created_at?: number | null
@ -284,12 +285,11 @@ export type MessageDetailResponse = {
}
message?: JsonValue | null
message_files?: Array<MessageFile>
message_metadata_dict?: JsonValue | null
message_tokens?: number | null
metadata?: JsonValue | null
parent_message_id?: string | null
provider_response_latency?: number | null
query: string
re_sign_file_url_answer: string
status: string
workflow_run_id?: string | null
}
@ -405,12 +405,30 @@ export type DeletedTool = {
}
export type ModelConfig = {
completion_params?: {
[key: string]: unknown
}
mode: LlmMode
name: string
provider: string
agent_mode?: JsonValue | null
annotation_reply?: JsonValue | null
chat_prompt_config?: JsonValue | null
completion_prompt_config?: JsonValue | null
created_at?: number | null
created_by?: string | null
dataset_configs?: JsonValue | null
dataset_query_variable?: string | null
external_data_tools?: JsonValue | null
file_upload?: JsonValue | null
model?: JsonValue | null
more_like_this?: JsonValue | null
opening_statement?: string | null
pre_prompt?: string | null
prompt_type?: string | null
retriever_resource?: JsonValue | null
sensitive_word_avoidance?: JsonValue | null
speech_to_text?: JsonValue | null
suggested_questions?: JsonValue | null
suggested_questions_after_answer?: JsonValue | null
text_to_speech?: JsonValue | null
updated_at?: number | null
updated_by?: string | null
user_input_form?: JsonValue | null
}
export type Site = {
@ -723,7 +741,6 @@ export type AgentThought = {
created_at?: number | null
files: Array<string>
id: string
message_chain_id?: string | null
message_id: string
observation?: string | null
position: number
@ -743,8 +760,8 @@ export type ConversationAnnotation = {
export type ConversationAnnotationHitHistory = {
annotation_create_account?: SimpleAccount | null
annotation_id: string
created_at?: number | null
id: string
}
export type HumanInputContent = {
@ -879,8 +896,6 @@ export type AgentAppPublishedReferenceResponse = {
app_name: string
}
export type LlmMode = 'chat' | 'completion'
export type AgentKind = 'dify_agent'
export type AgentPublishedReferenceResponse = {

View File

@ -229,6 +229,36 @@ export const zJsonValue = z
])
.nullable()
/**
* ModelConfig
*/
export const zModelConfig = z.object({
agent_mode: zJsonValue.nullish(),
annotation_reply: zJsonValue.nullish(),
chat_prompt_config: zJsonValue.nullish(),
completion_prompt_config: zJsonValue.nullish(),
created_at: z.int().nullish(),
created_by: z.string().nullish(),
dataset_configs: zJsonValue.nullish(),
dataset_query_variable: z.string().nullish(),
external_data_tools: zJsonValue.nullish(),
file_upload: zJsonValue.nullish(),
model: zJsonValue.nullish(),
more_like_this: zJsonValue.nullish(),
opening_statement: z.string().nullish(),
pre_prompt: z.string().nullish(),
prompt_type: z.string().nullish(),
retriever_resource: zJsonValue.nullish(),
sensitive_word_avoidance: zJsonValue.nullish(),
speech_to_text: zJsonValue.nullish(),
suggested_questions: zJsonValue.nullish(),
suggested_questions_after_answer: zJsonValue.nullish(),
text_to_speech: zJsonValue.nullish(),
updated_at: z.int().nullish(),
updated_by: z.string().nullish(),
user_input_form: zJsonValue.nullish(),
})
/**
* WorkflowPartial
*/
@ -240,6 +270,43 @@ export const zWorkflowPartial = z.object({
updated_by: z.string().nullish(),
})
/**
* AgentAppDetailWithSite
*/
export const zAgentAppDetailWithSite = z.object({
access_mode: z.string().nullish(),
active_config_is_published: z.boolean().optional().default(false),
api_base_url: z.string().nullish(),
app_id: z.string().nullish(),
bound_agent_id: z.string().nullish(),
created_at: z.int().nullish(),
created_by: z.string().nullish(),
debug_conversation_id: z.string().nullish(),
deleted_tools: z.array(zDeletedTool).optional(),
description: z.string().nullish(),
enable_api: z.boolean(),
enable_site: z.boolean(),
icon: z.string().nullish(),
icon_background: z.string().nullish(),
icon_type: z.string().nullish(),
icon_url: z.string().nullable(),
id: z.string(),
maintainer: z.string().nullish(),
max_active_requests: z.int().nullish(),
mode: z.string(),
model_config: zModelConfig.nullish(),
name: z.string(),
permission_keys: z.array(z.string()).optional(),
role: z.string().nullish(),
site: zSite.nullish(),
tags: z.array(zTag).optional(),
tracing: zJsonValue.nullish(),
updated_at: z.int().nullish(),
updated_by: z.string().nullish(),
use_icon_as_answer_icon: z.boolean().nullish(),
workflow: zWorkflowPartial.nullish(),
})
/**
* AgentConfigSnapshotSummaryResponse
*/
@ -570,7 +637,6 @@ export const zAgentThought = z.object({
created_at: z.int().nullish(),
files: z.array(z.string()),
id: z.string(),
message_chain_id: z.string().nullish(),
message_id: z.string(),
observation: z.string().nullish(),
position: z.int(),
@ -773,60 +839,6 @@ export const zAgentAppPagination = z.object({
total: z.int(),
})
/**
* LLMMode
*
* Enum class for large language model mode.
*/
export const zLlmMode = z.enum(['chat', 'completion'])
/**
* ModelConfig
*/
export const zModelConfig = z.object({
completion_params: z.record(z.string(), z.unknown()).optional(),
mode: zLlmMode,
name: z.string(),
provider: z.string(),
})
/**
* AgentAppDetailWithSite
*/
export const zAgentAppDetailWithSite = z.object({
access_mode: z.string().nullish(),
active_config_is_published: z.boolean().optional().default(false),
api_base_url: z.string().nullish(),
app_id: z.string().nullish(),
bound_agent_id: z.string().nullish(),
created_at: z.int().nullish(),
created_by: z.string().nullish(),
debug_conversation_id: z.string().nullish(),
deleted_tools: z.array(zDeletedTool).optional(),
description: z.string().nullish(),
enable_api: z.boolean(),
enable_site: z.boolean(),
icon: z.string().nullish(),
icon_background: z.string().nullish(),
icon_type: z.string().nullish(),
icon_url: z.string().nullable(),
id: z.string(),
maintainer: z.string().nullish(),
max_active_requests: z.int().nullish(),
mode: z.string(),
model_config: zModelConfig.nullish(),
name: z.string(),
permission_keys: z.array(z.string()).optional(),
role: z.string().nullish(),
site: zSite.nullish(),
tags: z.array(zTag).optional(),
tracing: zJsonValue.nullish(),
updated_at: z.int().nullish(),
updated_by: z.string().nullish(),
use_icon_as_answer_icon: z.boolean().nullish(),
workflow: zWorkflowPartial.nullish(),
})
/**
* AgentKind
*
@ -1056,8 +1068,8 @@ export const zConversationAnnotation = z.object({
*/
export const zConversationAnnotationHitHistory = z.object({
annotation_create_account: zSimpleAccount.nullish(),
annotation_id: z.string(),
created_at: z.int().nullish(),
id: z.string(),
})
/**
@ -2035,6 +2047,7 @@ export const zMessageDetailResponse = z.object({
agent_thoughts: z.array(zAgentThought).optional(),
annotation: zConversationAnnotation.nullish(),
annotation_hit_history: zConversationAnnotationHitHistory.nullish(),
answer: z.string(),
answer_tokens: z.int().nullish(),
conversation_id: z.string(),
created_at: z.int().nullish(),
@ -2048,12 +2061,11 @@ export const zMessageDetailResponse = z.object({
inputs: z.record(z.string(), zJsonValue),
message: zJsonValue.nullish(),
message_files: z.array(zMessageFile).optional(),
message_metadata_dict: zJsonValue.nullish(),
message_tokens: z.int().nullish(),
metadata: zJsonValue.nullish(),
parent_message_id: z.string().nullish(),
provider_response_latency: z.number().nullish(),
query: z.string(),
re_sign_file_url_answer: z.string(),
status: z.string(),
workflow_run_id: z.string().nullish(),
})

View File

@ -4,7 +4,7 @@ export type ClientOptions = {
baseUrl: `${string}://${string}/console/api` | (string & {})
}
export type WorkspaceListResponse = {
export type WorkspacePaginationResponse = {
data: Array<WorkspaceListItemResponse>
has_more: boolean
limit: number
@ -30,7 +30,7 @@ export type GetAllWorkspacesData = {
}
export type GetAllWorkspacesResponses = {
200: WorkspaceListResponse
200: WorkspacePaginationResponse
}
export type GetAllWorkspacesResponse = GetAllWorkspacesResponses[keyof GetAllWorkspacesResponses]

View File

@ -13,9 +13,9 @@ export const zWorkspaceListItemResponse = z.object({
})
/**
* WorkspaceListResponse
* WorkspacePaginationResponse
*/
export const zWorkspaceListResponse = z.object({
export const zWorkspacePaginationResponse = z.object({
data: z.array(zWorkspaceListItemResponse),
has_more: z.boolean(),
limit: z.int(),
@ -31,4 +31,4 @@ export const zGetAllWorkspacesQuery = z.object({
/**
* Success
*/
export const zGetAllWorkspacesResponse = zWorkspaceListResponse
export const zGetAllWorkspacesResponse = zWorkspacePaginationResponse

View File

@ -472,6 +472,7 @@ export type MessageDetailResponse = {
agent_thoughts?: Array<AgentThought>
annotation?: ConversationAnnotation | null
annotation_hit_history?: ConversationAnnotationHitHistory | null
answer: string
answer_tokens?: number | null
conversation_id: string
created_at?: number | null
@ -487,12 +488,11 @@ export type MessageDetailResponse = {
}
message?: JsonValue | null
message_files?: Array<MessageFile>
message_metadata_dict?: JsonValue | null
message_tokens?: number | null
metadata?: JsonValue | null
parent_message_id?: string | null
provider_response_latency?: number | null
query: string
re_sign_file_url_answer: string
status: string
workflow_run_id?: string | null
}
@ -731,7 +731,7 @@ export type WorkflowRunPaginationResponse = {
export type WorkflowRunDetailResponse = {
created_at?: number | null
created_by_account?: SimpleAccount | null
created_by_account?: SimpleAccountResponse | null
created_by_end_user?: SimpleEndUser | null
created_by_role?: string | null
elapsed_time?: number | null
@ -799,7 +799,7 @@ export type WorkflowCommentCreate = {
}
export type WorkflowCommentMentionUsersPayload = {
users: Array<AccountWithRole>
users: Array<AccountWithRoleResponse>
}
export type WorkflowCommentDetail = {
@ -887,7 +887,7 @@ export type DefaultBlockConfigResponse = {
export type WorkflowResponse = {
conversation_variables: Array<WorkflowConversationVariableResponse>
created_at: number
created_by?: SimpleAccount | null
created_by?: SimpleAccountResponse | null
environment_variables: Array<WorkflowEnvironmentVariableResponse>
features: {
[key: string]: unknown
@ -902,7 +902,7 @@ export type WorkflowResponse = {
rag_pipeline_variables: Array<PipelineVariableResponse>
tool_published: boolean
updated_at: number
updated_by?: SimpleAccount | null
updated_by?: SimpleAccountResponse | null
version: string
}
@ -1029,7 +1029,7 @@ export type AgentComposerValidateResponse = {
export type WorkflowRunNodeExecutionResponse = {
created_at?: number | null
created_by_account?: SimpleAccount | null
created_by_account?: SimpleAccountResponse | null
created_by_end_user?: SimpleEndUser | null
created_by_role?: string | null
elapsed_time?: number | null
@ -1223,12 +1223,30 @@ export type DeletedTool = {
}
export type ModelConfig = {
completion_params?: {
[key: string]: unknown
}
mode: LlmMode
name: string
provider: string
agent_mode?: JsonValue | null
annotation_reply?: JsonValue | null
chat_prompt_config?: JsonValue | null
completion_prompt_config?: JsonValue | null
created_at?: number | null
created_by?: string | null
dataset_configs?: JsonValue | null
dataset_query_variable?: string | null
external_data_tools?: JsonValue | null
file_upload?: JsonValue | null
model?: JsonValue | null
more_like_this?: JsonValue | null
opening_statement?: string | null
pre_prompt?: string | null
prompt_type?: string | null
retriever_resource?: JsonValue | null
sensitive_word_avoidance?: JsonValue | null
speech_to_text?: JsonValue | null
suggested_questions?: JsonValue | null
suggested_questions_after_answer?: JsonValue | null
text_to_speech?: JsonValue | null
updated_at?: number | null
updated_by?: string | null
user_input_form?: JsonValue | null
}
export type Site = {
@ -1289,7 +1307,7 @@ export type WorkflowOnlineUsersByApp = {
export type AdvancedChatWorkflowRunForListResponse = {
conversation_id?: string | null
created_at?: number | null
created_by_account?: SimpleAccount | null
created_by_account?: SimpleAccountResponse | null
elapsed_time?: number | null
exceptions_count?: number | null
finished_at?: number | null
@ -1498,7 +1516,6 @@ export type AgentThought = {
created_at?: number | null
files: Array<string>
id: string
message_chain_id?: string | null
message_id: string
observation?: string | null
position: number
@ -1518,8 +1535,8 @@ export type ConversationAnnotation = {
export type ConversationAnnotationHitHistory = {
annotation_create_account?: SimpleAccount | null
annotation_id: string
created_at?: number | null
id: string
}
export type HumanInputContent = {
@ -1596,7 +1613,7 @@ export type UserSatisfactionRateStatisticItem = {
export type WorkflowAppLogPartialResponse = {
created_at?: number | null
created_by_account?: SimpleAccount | null
created_by_account?: SimpleAccountResponse | null
created_by_end_user?: SimpleEndUser | null
created_by_role?: string | null
created_from?: string | null
@ -1607,7 +1624,7 @@ export type WorkflowAppLogPartialResponse = {
export type WorkflowArchivedLogPartialResponse = {
created_at?: number | null
created_by_account?: SimpleAccount | null
created_by_account?: SimpleAccountResponse | null
created_by_end_user?: SimpleEndUser | null
id: string
trigger_metadata?: unknown
@ -1616,7 +1633,7 @@ export type WorkflowArchivedLogPartialResponse = {
export type WorkflowRunForListResponse = {
created_at?: number | null
created_by_account?: SimpleAccount | null
created_by_account?: SimpleAccountResponse | null
elapsed_time?: number | null
exceptions_count?: number | null
finished_at?: number | null
@ -1628,7 +1645,7 @@ export type WorkflowRunForListResponse = {
version?: string | null
}
export type SimpleAccount = {
export type SimpleAccountResponse = {
email: string
id: string
name: string
@ -1671,8 +1688,9 @@ export type WorkflowCommentBasic = {
updated_at?: number | null
}
export type AccountWithRole = {
export type AccountWithRoleResponse = {
avatar?: string | null
readonly avatar_url: string | null
created_at?: number | null
email: string
id: string
@ -1982,9 +2000,14 @@ export type ModelConfigPartial = {
updated_by?: string | null
}
export type LlmMode = 'chat' | 'completion'
export type Type = 'github' | 'marketplace' | 'package'
export type Type
= | 'app-selector'
| 'array[tools]'
| 'boolean'
| 'model-selector'
| 'secret-input'
| 'select'
| 'text-input'
export type Github = {
github_plugin_unique_identifier: string
@ -2054,6 +2077,12 @@ export type SimpleMessageDetail = {
query: string
}
export type SimpleAccount = {
email: string
id: string
name: string
}
export type HumanInputFormDefinition = {
actions?: Array<UserActionConfig>
display_in_ui?: boolean
@ -2637,6 +2666,10 @@ export type WorkflowCommentBasicListWritable = {
data: Array<WorkflowCommentBasicWritable>
}
export type WorkflowCommentMentionUsersPayloadWritable = {
users: Array<AccountWithRoleResponseWritable>
}
export type WorkflowCommentDetailWritable = {
content: string
created_at?: number | null
@ -2716,6 +2749,21 @@ export type WorkflowCommentBasicWritable = {
updated_at?: number | null
}
export type AccountWithRoleResponseWritable = {
avatar?: string | null
created_at?: number | null
email: string
id: string
last_active_at?: number | null
last_login_at?: number | null
name: string
role: string
roles?: Array<{
[key: string]: string
}>
status: string
}
export type WorkflowCommentAccountWritable = {
email: string
id: string

View File

@ -889,6 +889,36 @@ export const zJsonValue = z
*/
export const zGeneratedAppResponse = zJsonValue
/**
* ModelConfig
*/
export const zModelConfig = z.object({
agent_mode: zJsonValue.nullish(),
annotation_reply: zJsonValue.nullish(),
chat_prompt_config: zJsonValue.nullish(),
completion_prompt_config: zJsonValue.nullish(),
created_at: z.int().nullish(),
created_by: z.string().nullish(),
dataset_configs: zJsonValue.nullish(),
dataset_query_variable: z.string().nullish(),
external_data_tools: zJsonValue.nullish(),
file_upload: zJsonValue.nullish(),
model: zJsonValue.nullish(),
more_like_this: zJsonValue.nullish(),
opening_statement: z.string().nullish(),
pre_prompt: z.string().nullish(),
prompt_type: z.string().nullish(),
retriever_resource: zJsonValue.nullish(),
sensitive_word_avoidance: zJsonValue.nullish(),
speech_to_text: zJsonValue.nullish(),
suggested_questions: zJsonValue.nullish(),
suggested_questions_after_answer: zJsonValue.nullish(),
text_to_speech: zJsonValue.nullish(),
updated_at: z.int().nullish(),
updated_by: z.string().nullish(),
user_input_form: zJsonValue.nullish(),
})
/**
* WorkflowPartial
*/
@ -900,6 +930,66 @@ export const zWorkflowPartial = z.object({
updated_by: z.string().nullish(),
})
/**
* AppDetailWithSite
*/
export const zAppDetailWithSite = z.object({
access_mode: z.string().nullish(),
api_base_url: z.string().nullish(),
app_id: z.string().nullish(),
bound_agent_id: z.string().nullish(),
created_at: z.int().nullish(),
created_by: z.string().nullish(),
deleted_tools: z.array(zDeletedTool).optional(),
description: z.string().nullish(),
enable_api: z.boolean(),
enable_site: z.boolean(),
icon: z.string().nullish(),
icon_background: z.string().nullish(),
icon_type: z.string().nullish(),
icon_url: z.string().nullable(),
id: z.string(),
maintainer: z.string().nullish(),
max_active_requests: z.int().nullish(),
mode: z.string(),
model_config: zModelConfig.nullish(),
name: z.string(),
permission_keys: z.array(z.string()).optional(),
site: zSite.nullish(),
tags: z.array(zTag).optional(),
tracing: zJsonValue.nullish(),
updated_at: z.int().nullish(),
updated_by: z.string().nullish(),
use_icon_as_answer_icon: z.boolean().nullish(),
workflow: zWorkflowPartial.nullish(),
})
/**
* AppDetail
*/
export const zAppDetail = z.object({
access_mode: z.string().nullish(),
app_model_config: zModelConfig.nullish(),
created_at: z.int().nullish(),
created_by: z.string().nullish(),
description: z.string().nullish(),
enable_api: z.boolean(),
enable_site: z.boolean(),
icon: z.string().nullish(),
icon_background: z.string().nullish(),
id: z.string(),
maintainer: z.string().nullish(),
mode_compatible_with_agent: z.string(),
name: z.string(),
permission_keys: z.array(z.string()).optional(),
tags: z.array(zTag).optional(),
tracing: zJsonValue.nullish(),
updated_at: z.int().nullish(),
updated_by: z.string().nullish(),
use_icon_as_answer_icon: z.boolean().nullish(),
workflow: zWorkflowPartial.nullish(),
})
/**
* ImportStatus
*/
@ -1118,6 +1208,25 @@ export const zFeedbackStat = z.object({
like: z.int(),
})
/**
* ConversationDetail
*/
export const zConversationDetail = z.object({
admin_feedback_stats: zFeedbackStat.nullish(),
annotated: z.boolean(),
created_at: z.int().nullish(),
from_account_id: z.string().nullish(),
from_end_user_id: z.string().nullish(),
from_source: z.string(),
id: z.string(),
introduction: z.string().nullish(),
message_count: z.int(),
model_config: zModelConfig.nullish(),
status: z.string(),
updated_at: z.int().nullish(),
user_feedback_stats: zFeedbackStat.nullish(),
})
/**
* ConversationVariableResponse
*/
@ -1150,7 +1259,6 @@ export const zAgentThought = z.object({
created_at: z.int().nullish(),
files: z.array(z.string()),
id: z.string(),
message_chain_id: z.string().nullish(),
message_id: z.string(),
observation: z.string().nullish(),
position: z.int(),
@ -1319,9 +1427,9 @@ export const zUserSatisfactionRateStatisticResponse = z.object({
})
/**
* SimpleAccount
* SimpleAccountResponse
*/
export const zSimpleAccount = z.object({
export const zSimpleAccountResponse = z.object({
email: z.string(),
id: z.string(),
name: z.string(),
@ -1333,7 +1441,7 @@ export const zSimpleAccount = z.object({
export const zAdvancedChatWorkflowRunForListResponse = z.object({
conversation_id: z.string().nullish(),
created_at: z.int().nullish(),
created_by_account: zSimpleAccount.nullish(),
created_by_account: zSimpleAccountResponse.nullish(),
elapsed_time: z.number().nullish(),
exceptions_count: z.int().nullish(),
finished_at: z.int().nullish(),
@ -1355,72 +1463,12 @@ export const zAdvancedChatWorkflowRunPaginationResponse = z.object({
limit: z.int(),
})
/**
* ConversationAnnotation
*/
export const zConversationAnnotation = z.object({
account: zSimpleAccount.nullish(),
content: z.string(),
created_at: z.int().nullish(),
id: z.string(),
question: z.string().nullish(),
})
/**
* ConversationAnnotationHitHistory
*/
export const zConversationAnnotationHitHistory = z.object({
annotation_create_account: zSimpleAccount.nullish(),
created_at: z.int().nullish(),
id: z.string(),
})
/**
* Feedback
*/
export const zFeedback = z.object({
content: z.string().nullish(),
from_account: zSimpleAccount.nullish(),
from_end_user_id: z.string().nullish(),
from_source: z.string(),
rating: z.string(),
})
/**
* MessageDetail
*/
export const zMessageDetail = z.object({
agent_thoughts: z.array(zAgentThought),
annotation: zConversationAnnotation.nullish(),
annotation_hit_history: zConversationAnnotationHitHistory.nullish(),
answer_tokens: z.int(),
conversation_id: z.string(),
created_at: z.int().nullish(),
error: z.string().nullish(),
feedbacks: z.array(zFeedback),
from_account_id: z.string().nullish(),
from_end_user_id: z.string().nullish(),
from_source: z.string(),
id: z.string(),
inputs: z.record(z.string(), zJsonValue),
message: zJsonValue,
message_files: z.array(zMessageFile),
message_metadata_dict: zJsonValue,
message_tokens: z.int(),
parent_message_id: z.string().nullish(),
provider_response_latency: z.number(),
query: z.string(),
re_sign_file_url_answer: z.string(),
status: z.string(),
workflow_run_id: z.string().nullish(),
})
/**
* WorkflowRunForListResponse
*/
export const zWorkflowRunForListResponse = z.object({
created_at: z.int().nullish(),
created_by_account: zSimpleAccount.nullish(),
created_by_account: zSimpleAccountResponse.nullish(),
elapsed_time: z.number().nullish(),
exceptions_count: z.int().nullish(),
finished_at: z.int().nullish(),
@ -1456,7 +1504,7 @@ export const zSimpleEndUser = z.object({
*/
export const zWorkflowRunDetailResponse = z.object({
created_at: z.int().nullish(),
created_by_account: zSimpleAccount.nullish(),
created_by_account: zSimpleAccountResponse.nullish(),
created_by_end_user: zSimpleEndUser.nullish(),
created_by_role: z.string().nullish(),
elapsed_time: z.number().nullish(),
@ -1478,7 +1526,7 @@ export const zWorkflowRunDetailResponse = z.object({
*/
export const zWorkflowRunNodeExecutionResponse = z.object({
created_at: z.int().nullish(),
created_by_account: zSimpleAccount.nullish(),
created_by_account: zSimpleAccountResponse.nullish(),
created_by_end_user: zSimpleEndUser.nullish(),
created_by_role: z.string().nullish(),
elapsed_time: z.number().nullish(),
@ -1544,10 +1592,11 @@ export const zSandboxUploadResponse = z.object({
})
/**
* AccountWithRole
* AccountWithRoleResponse
*/
export const zAccountWithRole = z.object({
export const zAccountWithRoleResponse = z.object({
avatar: z.string().nullish(),
avatar_url: z.string().nullable(),
created_at: z.int().nullish(),
email: z.string(),
id: z.string(),
@ -1563,7 +1612,7 @@ export const zAccountWithRole = z.object({
* WorkflowCommentMentionUsersPayload
*/
export const zWorkflowCommentMentionUsersPayload = z.object({
users: z.array(zAccountWithRole),
users: z.array(zAccountWithRoleResponse),
})
/**
@ -1752,7 +1801,7 @@ export const zPipelineVariableResponse = z.object({
export const zWorkflowResponse = z.object({
conversation_variables: z.array(zWorkflowConversationVariableResponse),
created_at: z.int(),
created_by: zSimpleAccount.nullish(),
created_by: zSimpleAccountResponse.nullish(),
environment_variables: z.array(zWorkflowEnvironmentVariableResponse),
features: z.record(z.string(), z.unknown()),
graph: z.record(z.string(), z.unknown()),
@ -1763,7 +1812,7 @@ export const zWorkflowResponse = z.object({
rag_pipeline_variables: z.array(zPipelineVariableResponse),
tool_published: z.boolean(),
updated_at: z.int(),
updated_by: zSimpleAccount.nullish(),
updated_by: zSimpleAccountResponse.nullish(),
version: z.string(),
})
@ -2056,120 +2105,18 @@ export const zAppPagination = z.object({
total: z.int(),
})
/**
* LLMMode
*
* Enum class for large language model mode.
*/
export const zLlmMode = z.enum(['chat', 'completion'])
/**
* ModelConfig
*/
export const zModelConfig = z.object({
completion_params: z.record(z.string(), z.unknown()).optional(),
mode: zLlmMode,
name: z.string(),
provider: z.string(),
})
/**
* AppDetailWithSite
*/
export const zAppDetailWithSite = z.object({
access_mode: z.string().nullish(),
api_base_url: z.string().nullish(),
app_id: z.string().nullish(),
bound_agent_id: z.string().nullish(),
created_at: z.int().nullish(),
created_by: z.string().nullish(),
deleted_tools: z.array(zDeletedTool).optional(),
description: z.string().nullish(),
enable_api: z.boolean(),
enable_site: z.boolean(),
icon: z.string().nullish(),
icon_background: z.string().nullish(),
icon_type: z.string().nullish(),
icon_url: z.string().nullable(),
id: z.string(),
maintainer: z.string().nullish(),
max_active_requests: z.int().nullish(),
mode: z.string(),
model_config: zModelConfig.nullish(),
name: z.string(),
permission_keys: z.array(z.string()).optional(),
site: zSite.nullish(),
tags: z.array(zTag).optional(),
tracing: zJsonValue.nullish(),
updated_at: z.int().nullish(),
updated_by: z.string().nullish(),
use_icon_as_answer_icon: z.boolean().nullish(),
workflow: zWorkflowPartial.nullish(),
})
/**
* AppDetail
*/
export const zAppDetail = z.object({
access_mode: z.string().nullish(),
app_model_config: zModelConfig.nullish(),
created_at: z.int().nullish(),
created_by: z.string().nullish(),
description: z.string().nullish(),
enable_api: z.boolean(),
enable_site: z.boolean(),
icon: z.string().nullish(),
icon_background: z.string().nullish(),
id: z.string(),
maintainer: z.string().nullish(),
mode_compatible_with_agent: z.string(),
name: z.string(),
permission_keys: z.array(z.string()).optional(),
tags: z.array(zTag).optional(),
tracing: zJsonValue.nullish(),
updated_at: z.int().nullish(),
updated_by: z.string().nullish(),
use_icon_as_answer_icon: z.boolean().nullish(),
workflow: zWorkflowPartial.nullish(),
})
/**
* ConversationDetail
*/
export const zConversationDetail = z.object({
admin_feedback_stats: zFeedbackStat.nullish(),
annotated: z.boolean(),
created_at: z.int().nullish(),
from_account_id: z.string().nullish(),
from_end_user_id: z.string().nullish(),
from_source: z.string(),
id: z.string(),
introduction: z.string().nullish(),
message_count: z.int(),
model_config: zModelConfig.nullish(),
status: z.string(),
updated_at: z.int().nullish(),
user_feedback_stats: zFeedbackStat.nullish(),
})
/**
* ConversationMessageDetail
*/
export const zConversationMessageDetail = z.object({
created_at: z.int().nullish(),
first_message: zMessageDetail.nullish(),
from_account_id: z.string().nullish(),
from_end_user_id: z.string().nullish(),
from_source: z.string(),
id: z.string(),
model_config: zModelConfig.nullish(),
status: z.string(),
})
/**
* Type
*/
export const zType = z.enum(['github', 'marketplace', 'package'])
export const zType = z.enum([
'app-selector',
'array[tools]',
'boolean',
'model-selector',
'secret-input',
'select',
'text-input',
])
/**
* Github
@ -2366,6 +2313,26 @@ export const zSimpleMessageDetail = z.object({
query: z.string(),
})
/**
* SimpleAccount
*/
export const zSimpleAccount = z.object({
email: z.string(),
id: z.string(),
name: z.string(),
})
/**
* ConversationAnnotation
*/
export const zConversationAnnotation = z.object({
account: zSimpleAccount.nullish(),
content: z.string(),
created_at: z.int().nullish(),
id: z.string(),
question: z.string().nullish(),
})
/**
* Conversation
*/
@ -2398,6 +2365,69 @@ export const zConversationPagination = z.object({
total: z.int(),
})
/**
* ConversationAnnotationHitHistory
*/
export const zConversationAnnotationHitHistory = z.object({
annotation_create_account: zSimpleAccount.nullish(),
annotation_id: z.string(),
created_at: z.int().nullish(),
})
/**
* Feedback
*/
export const zFeedback = z.object({
content: z.string().nullish(),
from_account: zSimpleAccount.nullish(),
from_end_user_id: z.string().nullish(),
from_source: z.string(),
rating: z.string(),
})
/**
* MessageDetail
*/
export const zMessageDetail = z.object({
agent_thoughts: z.array(zAgentThought),
annotation: zConversationAnnotation.nullish(),
annotation_hit_history: zConversationAnnotationHitHistory.nullish(),
answer_tokens: z.int(),
conversation_id: z.string(),
created_at: z.int().nullish(),
error: z.string().nullish(),
feedbacks: z.array(zFeedback),
from_account_id: z.string().nullish(),
from_end_user_id: z.string().nullish(),
from_source: z.string(),
id: z.string(),
inputs: z.record(z.string(), zJsonValue),
message: zJsonValue,
message_files: z.array(zMessageFile),
message_metadata_dict: zJsonValue,
message_tokens: z.int(),
parent_message_id: z.string().nullish(),
provider_response_latency: z.number(),
query: z.string(),
re_sign_file_url_answer: z.string(),
status: z.string(),
workflow_run_id: z.string().nullish(),
})
/**
* ConversationMessageDetail
*/
export const zConversationMessageDetail = z.object({
created_at: z.int().nullish(),
first_message: zMessageDetail.nullish(),
from_account_id: z.string().nullish(),
from_end_user_id: z.string().nullish(),
from_source: z.string(),
id: z.string(),
model_config: zModelConfig.nullish(),
status: z.string(),
})
/**
* ExecutionContentType
*/
@ -2425,7 +2455,7 @@ export const zWorkflowRunForLogResponse = z.object({
*/
export const zWorkflowAppLogPartialResponse = z.object({
created_at: z.int().nullish(),
created_by_account: zSimpleAccount.nullish(),
created_by_account: zSimpleAccountResponse.nullish(),
created_by_end_user: zSimpleEndUser.nullish(),
created_by_role: z.string().nullish(),
created_from: z.string().nullish(),
@ -2461,7 +2491,7 @@ export const zWorkflowRunForArchivedLogResponse = z.object({
*/
export const zWorkflowArchivedLogPartialResponse = z.object({
created_at: z.int().nullish(),
created_by_account: zSimpleAccount.nullish(),
created_by_account: zSimpleAccountResponse.nullish(),
created_by_end_user: zSimpleEndUser.nullish(),
id: z.string(),
trigger_metadata: z.unknown().optional(),
@ -3455,6 +3485,7 @@ export const zMessageDetailResponse = z.object({
agent_thoughts: z.array(zAgentThought).optional(),
annotation: zConversationAnnotation.nullish(),
annotation_hit_history: zConversationAnnotationHitHistory.nullish(),
answer: z.string(),
answer_tokens: z.int().nullish(),
conversation_id: z.string(),
created_at: z.int().nullish(),
@ -3468,12 +3499,11 @@ export const zMessageDetailResponse = z.object({
inputs: z.record(z.string(), zJsonValue),
message: zJsonValue.nullish(),
message_files: z.array(zMessageFile).optional(),
message_metadata_dict: zJsonValue.nullish(),
message_tokens: z.int().nullish(),
metadata: zJsonValue.nullish(),
parent_message_id: z.string().nullish(),
provider_response_latency: z.number().nullish(),
query: z.string(),
re_sign_file_url_answer: z.string(),
status: z.string(),
workflow_run_id: z.string().nullish(),
})
@ -3586,6 +3616,29 @@ export const zAppDetailWithSiteWritable = z.object({
workflow: zWorkflowPartial.nullish(),
})
/**
* AccountWithRoleResponse
*/
export const zAccountWithRoleResponseWritable = z.object({
avatar: z.string().nullish(),
created_at: z.int().nullish(),
email: z.string(),
id: z.string(),
last_active_at: z.int().nullish(),
last_login_at: z.int().nullish(),
name: z.string(),
role: z.string(),
roles: z.array(z.record(z.string(), z.string())).optional(),
status: z.string(),
})
/**
* WorkflowCommentMentionUsersPayload
*/
export const zWorkflowCommentMentionUsersPayloadWritable = z.object({
users: z.array(zAccountWithRoleResponseWritable),
})
/**
* WorkflowCommentAccount
*/

View File

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

View File

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

View File

@ -25,15 +25,42 @@ export type SimpleDataResponse = {
}
export type ModelConfig = {
completion_params?: {
[key: string]: unknown
}
mode: LlmMode
name: string
provider: string
agent_mode?: JsonValue | null
annotation_reply?: JsonValue | null
chat_prompt_config?: JsonValue | null
completion_prompt_config?: JsonValue | null
created_at?: number | null
created_by?: string | null
dataset_configs?: JsonValue | null
dataset_query_variable?: string | null
external_data_tools?: JsonValue | null
file_upload?: JsonValue | null
model?: JsonValue | null
more_like_this?: JsonValue | null
opening_statement?: string | null
pre_prompt?: string | null
prompt_type?: string | null
retriever_resource?: JsonValue | null
sensitive_word_avoidance?: JsonValue | null
speech_to_text?: JsonValue | null
suggested_questions?: JsonValue | null
suggested_questions_after_answer?: JsonValue | null
text_to_speech?: JsonValue | null
updated_at?: number | null
updated_by?: string | null
user_input_form?: JsonValue | null
}
export type LlmMode = 'chat' | 'completion'
export type JsonValue
= | string
| number
| number
| boolean
| {
[key: string]: unknown
}
| Array<unknown>
| null
export type PostInstructionGenerateData = {
body: InstructionGeneratePayload

View File

@ -21,21 +21,45 @@ export const zSimpleDataResponse = z.object({
data: z.string(),
})
/**
* LLMMode
*
* Enum class for large language model mode.
*/
export const zLlmMode = z.enum(['chat', 'completion'])
export const zJsonValue = z
.union([
z.string(),
z.int(),
z.number(),
z.boolean(),
z.record(z.string(), z.unknown()),
z.array(z.unknown()),
])
.nullable()
/**
* ModelConfig
*/
export const zModelConfig = z.object({
completion_params: z.record(z.string(), z.unknown()).optional(),
mode: zLlmMode,
name: z.string(),
provider: z.string(),
agent_mode: zJsonValue.nullish(),
annotation_reply: zJsonValue.nullish(),
chat_prompt_config: zJsonValue.nullish(),
completion_prompt_config: zJsonValue.nullish(),
created_at: z.int().nullish(),
created_by: z.string().nullish(),
dataset_configs: zJsonValue.nullish(),
dataset_query_variable: z.string().nullish(),
external_data_tools: zJsonValue.nullish(),
file_upload: zJsonValue.nullish(),
model: zJsonValue.nullish(),
more_like_this: zJsonValue.nullish(),
opening_statement: z.string().nullish(),
pre_prompt: z.string().nullish(),
prompt_type: z.string().nullish(),
retriever_resource: zJsonValue.nullish(),
sensitive_word_avoidance: zJsonValue.nullish(),
speech_to_text: zJsonValue.nullish(),
suggested_questions: zJsonValue.nullish(),
suggested_questions_after_answer: zJsonValue.nullish(),
text_to_speech: zJsonValue.nullish(),
updated_at: z.int().nullish(),
updated_by: z.string().nullish(),
user_input_form: zJsonValue.nullish(),
})
/**

View File

@ -119,7 +119,7 @@ export type SimpleResultResponse = {
export type WorkflowRunDetailResponse = {
created_at?: number | null
created_by_account?: SimpleAccount | null
created_by_account?: SimpleAccountResponse | null
created_by_end_user?: SimpleEndUser | null
created_by_role?: string | null
elapsed_time?: number | null
@ -158,7 +158,7 @@ export type DefaultBlockConfigResponse = {
export type WorkflowResponse = {
conversation_variables: Array<WorkflowConversationVariableResponse>
created_at: number
created_by?: SimpleAccount | null
created_by?: SimpleAccountResponse | null
environment_variables: Array<WorkflowEnvironmentVariableResponse>
features: {
[key: string]: unknown
@ -173,7 +173,7 @@ export type WorkflowResponse = {
rag_pipeline_variables: Array<PipelineVariableResponse>
tool_published: boolean
updated_at: number
updated_by?: SimpleAccount | null
updated_by?: SimpleAccountResponse | null
version: string
}
@ -221,7 +221,7 @@ export type DatasourceVariablesPayload = {
export type WorkflowRunNodeExecutionResponse = {
created_at?: number | null
created_by_account?: SimpleAccount | null
created_by_account?: SimpleAccountResponse | null
created_by_end_user?: SimpleEndUser | null
created_by_role?: string | null
elapsed_time?: number | null
@ -421,7 +421,7 @@ export type PluginDependency = {
export type WorkflowRunForListResponse = {
created_at?: number | null
created_by_account?: SimpleAccount | null
created_by_account?: SimpleAccountResponse | null
elapsed_time?: number | null
exceptions_count?: number | null
finished_at?: number | null
@ -433,7 +433,7 @@ export type WorkflowRunForListResponse = {
version?: string | null
}
export type SimpleAccount = {
export type SimpleAccountResponse = {
email: string
id: string
name: string
@ -515,7 +515,14 @@ export type DatasetWeightedScoreResponse = {
weight_type?: string | null
}
export type Type = 'github' | 'marketplace' | 'package'
export type Type
= | 'app-selector'
| 'array[tools]'
| 'boolean'
| 'model-selector'
| 'secret-input'
| 'select'
| 'text-input'
export type Github = {
github_plugin_unique_identifier: string

View File

@ -322,9 +322,9 @@ export const zPipelineTemplateListResponse = z.object({
})
/**
* SimpleAccount
* SimpleAccountResponse
*/
export const zSimpleAccount = z.object({
export const zSimpleAccountResponse = z.object({
email: z.string(),
id: z.string(),
name: z.string(),
@ -335,7 +335,7 @@ export const zSimpleAccount = z.object({
*/
export const zWorkflowRunForListResponse = z.object({
created_at: z.int().nullish(),
created_by_account: zSimpleAccount.nullish(),
created_by_account: zSimpleAccountResponse.nullish(),
elapsed_time: z.number().nullish(),
exceptions_count: z.int().nullish(),
finished_at: z.int().nullish(),
@ -371,7 +371,7 @@ export const zSimpleEndUser = z.object({
*/
export const zWorkflowRunDetailResponse = z.object({
created_at: z.int().nullish(),
created_by_account: zSimpleAccount.nullish(),
created_by_account: zSimpleAccountResponse.nullish(),
created_by_end_user: zSimpleEndUser.nullish(),
created_by_role: z.string().nullish(),
elapsed_time: z.number().nullish(),
@ -393,7 +393,7 @@ export const zWorkflowRunDetailResponse = z.object({
*/
export const zWorkflowRunNodeExecutionResponse = z.object({
created_at: z.int().nullish(),
created_by_account: zSimpleAccount.nullish(),
created_by_account: zSimpleAccountResponse.nullish(),
created_by_end_user: zSimpleEndUser.nullish(),
created_by_role: z.string().nullish(),
elapsed_time: z.number().nullish(),
@ -471,7 +471,7 @@ export const zPipelineVariableResponse = z.object({
export const zWorkflowResponse = z.object({
conversation_variables: z.array(zWorkflowConversationVariableResponse),
created_at: z.int(),
created_by: zSimpleAccount.nullish(),
created_by: zSimpleAccountResponse.nullish(),
environment_variables: z.array(zWorkflowEnvironmentVariableResponse),
features: z.record(z.string(), z.unknown()),
graph: z.record(z.string(), z.unknown()),
@ -482,7 +482,7 @@ export const zWorkflowResponse = z.object({
rag_pipeline_variables: z.array(zPipelineVariableResponse),
tool_published: z.boolean(),
updated_at: z.int(),
updated_by: zSimpleAccount.nullish(),
updated_by: zSimpleAccountResponse.nullish(),
version: z.string(),
})
@ -547,7 +547,15 @@ export const zDatasetRerankingModelResponse = z.object({
/**
* Type
*/
export const zType = z.enum(['github', 'marketplace', 'package'])
export const zType = z.enum([
'app-selector',
'array[tools]',
'boolean',
'model-selector',
'secret-input',
'select',
'text-input',
])
/**
* Github

View File

@ -14,15 +14,42 @@ export type RuleCodeGeneratePayload = {
export type GeneratorResponse = unknown
export type ModelConfig = {
completion_params?: {
[key: string]: unknown
}
mode: LlmMode
name: string
provider: string
agent_mode?: JsonValue | null
annotation_reply?: JsonValue | null
chat_prompt_config?: JsonValue | null
completion_prompt_config?: JsonValue | null
created_at?: number | null
created_by?: string | null
dataset_configs?: JsonValue | null
dataset_query_variable?: string | null
external_data_tools?: JsonValue | null
file_upload?: JsonValue | null
model?: JsonValue | null
more_like_this?: JsonValue | null
opening_statement?: string | null
pre_prompt?: string | null
prompt_type?: string | null
retriever_resource?: JsonValue | null
sensitive_word_avoidance?: JsonValue | null
speech_to_text?: JsonValue | null
suggested_questions?: JsonValue | null
suggested_questions_after_answer?: JsonValue | null
text_to_speech?: JsonValue | null
updated_at?: number | null
updated_by?: string | null
user_input_form?: JsonValue | null
}
export type LlmMode = 'chat' | 'completion'
export type JsonValue
= | string
| number
| number
| boolean
| {
[key: string]: unknown
}
| Array<unknown>
| null
export type PostRuleCodeGenerateData = {
body: RuleCodeGeneratePayload

View File

@ -7,21 +7,45 @@ import * as z from 'zod'
*/
export const zGeneratorResponse = z.unknown()
/**
* LLMMode
*
* Enum class for large language model mode.
*/
export const zLlmMode = z.enum(['chat', 'completion'])
export const zJsonValue = z
.union([
z.string(),
z.int(),
z.number(),
z.boolean(),
z.record(z.string(), z.unknown()),
z.array(z.unknown()),
])
.nullable()
/**
* ModelConfig
*/
export const zModelConfig = z.object({
completion_params: z.record(z.string(), z.unknown()).optional(),
mode: zLlmMode,
name: z.string(),
provider: z.string(),
agent_mode: zJsonValue.nullish(),
annotation_reply: zJsonValue.nullish(),
chat_prompt_config: zJsonValue.nullish(),
completion_prompt_config: zJsonValue.nullish(),
created_at: z.int().nullish(),
created_by: z.string().nullish(),
dataset_configs: zJsonValue.nullish(),
dataset_query_variable: z.string().nullish(),
external_data_tools: zJsonValue.nullish(),
file_upload: zJsonValue.nullish(),
model: zJsonValue.nullish(),
more_like_this: zJsonValue.nullish(),
opening_statement: z.string().nullish(),
pre_prompt: z.string().nullish(),
prompt_type: z.string().nullish(),
retriever_resource: zJsonValue.nullish(),
sensitive_word_avoidance: zJsonValue.nullish(),
speech_to_text: zJsonValue.nullish(),
suggested_questions: zJsonValue.nullish(),
suggested_questions_after_answer: zJsonValue.nullish(),
text_to_speech: zJsonValue.nullish(),
updated_at: z.int().nullish(),
updated_by: z.string().nullish(),
user_input_form: zJsonValue.nullish(),
})
/**

View File

@ -13,15 +13,42 @@ export type RuleGeneratePayload = {
export type GeneratorResponse = unknown
export type ModelConfig = {
completion_params?: {
[key: string]: unknown
}
mode: LlmMode
name: string
provider: string
agent_mode?: JsonValue | null
annotation_reply?: JsonValue | null
chat_prompt_config?: JsonValue | null
completion_prompt_config?: JsonValue | null
created_at?: number | null
created_by?: string | null
dataset_configs?: JsonValue | null
dataset_query_variable?: string | null
external_data_tools?: JsonValue | null
file_upload?: JsonValue | null
model?: JsonValue | null
more_like_this?: JsonValue | null
opening_statement?: string | null
pre_prompt?: string | null
prompt_type?: string | null
retriever_resource?: JsonValue | null
sensitive_word_avoidance?: JsonValue | null
speech_to_text?: JsonValue | null
suggested_questions?: JsonValue | null
suggested_questions_after_answer?: JsonValue | null
text_to_speech?: JsonValue | null
updated_at?: number | null
updated_by?: string | null
user_input_form?: JsonValue | null
}
export type LlmMode = 'chat' | 'completion'
export type JsonValue
= | string
| number
| number
| boolean
| {
[key: string]: unknown
}
| Array<unknown>
| null
export type PostRuleGenerateData = {
body: RuleGeneratePayload

View File

@ -7,21 +7,45 @@ import * as z from 'zod'
*/
export const zGeneratorResponse = z.unknown()
/**
* LLMMode
*
* Enum class for large language model mode.
*/
export const zLlmMode = z.enum(['chat', 'completion'])
export const zJsonValue = z
.union([
z.string(),
z.int(),
z.number(),
z.boolean(),
z.record(z.string(), z.unknown()),
z.array(z.unknown()),
])
.nullable()
/**
* ModelConfig
*/
export const zModelConfig = z.object({
completion_params: z.record(z.string(), z.unknown()).optional(),
mode: zLlmMode,
name: z.string(),
provider: z.string(),
agent_mode: zJsonValue.nullish(),
annotation_reply: zJsonValue.nullish(),
chat_prompt_config: zJsonValue.nullish(),
completion_prompt_config: zJsonValue.nullish(),
created_at: z.int().nullish(),
created_by: z.string().nullish(),
dataset_configs: zJsonValue.nullish(),
dataset_query_variable: z.string().nullish(),
external_data_tools: zJsonValue.nullish(),
file_upload: zJsonValue.nullish(),
model: zJsonValue.nullish(),
more_like_this: zJsonValue.nullish(),
opening_statement: z.string().nullish(),
pre_prompt: z.string().nullish(),
prompt_type: z.string().nullish(),
retriever_resource: zJsonValue.nullish(),
sensitive_word_avoidance: zJsonValue.nullish(),
speech_to_text: zJsonValue.nullish(),
suggested_questions: zJsonValue.nullish(),
suggested_questions_after_answer: zJsonValue.nullish(),
text_to_speech: zJsonValue.nullish(),
updated_at: z.int().nullish(),
updated_by: z.string().nullish(),
user_input_form: zJsonValue.nullish(),
})
/**

View File

@ -12,15 +12,42 @@ export type RuleStructuredOutputPayload = {
export type GeneratorResponse = unknown
export type ModelConfig = {
completion_params?: {
[key: string]: unknown
}
mode: LlmMode
name: string
provider: string
agent_mode?: JsonValue | null
annotation_reply?: JsonValue | null
chat_prompt_config?: JsonValue | null
completion_prompt_config?: JsonValue | null
created_at?: number | null
created_by?: string | null
dataset_configs?: JsonValue | null
dataset_query_variable?: string | null
external_data_tools?: JsonValue | null
file_upload?: JsonValue | null
model?: JsonValue | null
more_like_this?: JsonValue | null
opening_statement?: string | null
pre_prompt?: string | null
prompt_type?: string | null
retriever_resource?: JsonValue | null
sensitive_word_avoidance?: JsonValue | null
speech_to_text?: JsonValue | null
suggested_questions?: JsonValue | null
suggested_questions_after_answer?: JsonValue | null
text_to_speech?: JsonValue | null
updated_at?: number | null
updated_by?: string | null
user_input_form?: JsonValue | null
}
export type LlmMode = 'chat' | 'completion'
export type JsonValue
= | string
| number
| number
| boolean
| {
[key: string]: unknown
}
| Array<unknown>
| null
export type PostRuleStructuredOutputGenerateData = {
body: RuleStructuredOutputPayload

View File

@ -7,21 +7,45 @@ import * as z from 'zod'
*/
export const zGeneratorResponse = z.unknown()
/**
* LLMMode
*
* Enum class for large language model mode.
*/
export const zLlmMode = z.enum(['chat', 'completion'])
export const zJsonValue = z
.union([
z.string(),
z.int(),
z.number(),
z.boolean(),
z.record(z.string(), z.unknown()),
z.array(z.unknown()),
])
.nullable()
/**
* ModelConfig
*/
export const zModelConfig = z.object({
completion_params: z.record(z.string(), z.unknown()).optional(),
mode: zLlmMode,
name: z.string(),
provider: z.string(),
agent_mode: zJsonValue.nullish(),
annotation_reply: zJsonValue.nullish(),
chat_prompt_config: zJsonValue.nullish(),
completion_prompt_config: zJsonValue.nullish(),
created_at: z.int().nullish(),
created_by: z.string().nullish(),
dataset_configs: zJsonValue.nullish(),
dataset_query_variable: z.string().nullish(),
external_data_tools: zJsonValue.nullish(),
file_upload: zJsonValue.nullish(),
model: zJsonValue.nullish(),
more_like_this: zJsonValue.nullish(),
opening_statement: z.string().nullish(),
pre_prompt: z.string().nullish(),
prompt_type: z.string().nullish(),
retriever_resource: zJsonValue.nullish(),
sensitive_word_avoidance: zJsonValue.nullish(),
speech_to_text: zJsonValue.nullish(),
suggested_questions: zJsonValue.nullish(),
suggested_questions_after_answer: zJsonValue.nullish(),
text_to_speech: zJsonValue.nullish(),
updated_at: z.int().nullish(),
updated_by: z.string().nullish(),
user_input_form: zJsonValue.nullish(),
})
/**

View File

@ -16,7 +16,7 @@ export type SimpleResultResponse = {
export type WorkflowRunDetailResponse = {
created_at?: number | null
created_by_account?: SimpleAccount | null
created_by_account?: SimpleAccountResponse | null
created_by_end_user?: SimpleEndUser | null
created_by_role?: string | null
elapsed_time?: number | null
@ -51,7 +51,7 @@ export type DefaultBlockConfigsResponse = Array<{
export type SnippetWorkflowResponse = {
conversation_variables: Array<WorkflowConversationVariableResponse>
created_at: number
created_by?: SimpleAccount | null
created_by?: SimpleAccountResponse | null
environment_variables: Array<WorkflowEnvironmentVariableResponse>
features: {
[key: string]: unknown
@ -69,7 +69,7 @@ export type SnippetWorkflowResponse = {
rag_pipeline_variables: Array<PipelineVariableResponse>
tool_published: boolean
updated_at: number
updated_by?: SimpleAccount | null
updated_by?: SimpleAccountResponse | null
version: string
}
@ -120,7 +120,7 @@ export type SnippetLoopNodeRunPayload = {
export type WorkflowRunNodeExecutionResponse = {
created_at?: number | null
created_by_account?: SimpleAccount | null
created_by_account?: SimpleAccountResponse | null
created_by_end_user?: SimpleEndUser | null
created_by_role?: string | null
elapsed_time?: number | null
@ -210,7 +210,7 @@ export type WorkflowPublishResponse = {
export type WorkflowRunForListResponse = {
created_at?: number | null
created_by_account?: SimpleAccount | null
created_by_account?: SimpleAccountResponse | null
elapsed_time?: number | null
exceptions_count?: number | null
finished_at?: number | null
@ -222,7 +222,7 @@ export type WorkflowRunForListResponse = {
version?: string | null
}
export type SimpleAccount = {
export type SimpleAccountResponse = {
email: string
id: string
name: string

View File

@ -134,9 +134,9 @@ export const zWorkflowPublishResponse = z.object({
})
/**
* SimpleAccount
* SimpleAccountResponse
*/
export const zSimpleAccount = z.object({
export const zSimpleAccountResponse = z.object({
email: z.string(),
id: z.string(),
name: z.string(),
@ -147,7 +147,7 @@ export const zSimpleAccount = z.object({
*/
export const zWorkflowRunForListResponse = z.object({
created_at: z.int().nullish(),
created_by_account: zSimpleAccount.nullish(),
created_by_account: zSimpleAccountResponse.nullish(),
elapsed_time: z.number().nullish(),
exceptions_count: z.int().nullish(),
finished_at: z.int().nullish(),
@ -183,7 +183,7 @@ export const zSimpleEndUser = z.object({
*/
export const zWorkflowRunDetailResponse = z.object({
created_at: z.int().nullish(),
created_by_account: zSimpleAccount.nullish(),
created_by_account: zSimpleAccountResponse.nullish(),
created_by_end_user: zSimpleEndUser.nullish(),
created_by_role: z.string().nullish(),
elapsed_time: z.number().nullish(),
@ -205,7 +205,7 @@ export const zWorkflowRunDetailResponse = z.object({
*/
export const zWorkflowRunNodeExecutionResponse = z.object({
created_at: z.int().nullish(),
created_by_account: zSimpleAccount.nullish(),
created_by_account: zSimpleAccountResponse.nullish(),
created_by_end_user: zSimpleEndUser.nullish(),
created_by_role: z.string().nullish(),
elapsed_time: z.number().nullish(),
@ -283,7 +283,7 @@ export const zPipelineVariableResponse = z.object({
export const zSnippetWorkflowResponse = z.object({
conversation_variables: z.array(zWorkflowConversationVariableResponse),
created_at: z.int(),
created_by: zSimpleAccount.nullish(),
created_by: zSimpleAccountResponse.nullish(),
environment_variables: z.array(zWorkflowEnvironmentVariableResponse),
features: z.record(z.string(), z.unknown()),
graph: z.record(z.string(), z.unknown()),
@ -295,7 +295,7 @@ export const zSnippetWorkflowResponse = z.object({
rag_pipeline_variables: z.array(zPipelineVariableResponse),
tool_published: z.boolean(),
updated_at: z.int(),
updated_by: zSimpleAccount.nullish(),
updated_by: zSimpleAccountResponse.nullish(),
version: z.string(),
})

View File

@ -19,18 +19,9 @@ import {
zGetTrialAppsByAppIdWorkflowsResponse,
zPostTrialAppsByAppIdAudioToTextPath,
zPostTrialAppsByAppIdAudioToTextResponse,
zPostTrialAppsByAppIdChatMessagesBody,
zPostTrialAppsByAppIdChatMessagesPath,
zPostTrialAppsByAppIdChatMessagesResponse,
zPostTrialAppsByAppIdCompletionMessagesBody,
zPostTrialAppsByAppIdCompletionMessagesPath,
zPostTrialAppsByAppIdCompletionMessagesResponse,
zPostTrialAppsByAppIdTextToAudioBody,
zPostTrialAppsByAppIdTextToAudioPath,
zPostTrialAppsByAppIdTextToAudioResponse,
zPostTrialAppsByAppIdWorkflowsRunBody,
zPostTrialAppsByAppIdWorkflowsRunPath,
zPostTrialAppsByAppIdWorkflowsRunResponse,
zPostTrialAppsByAppIdWorkflowsTasksByTaskIdStopPath,
zPostTrialAppsByAppIdWorkflowsTasksByTaskIdStopResponse,
} from './zod.gen'
@ -50,46 +41,6 @@ export const audioToText = {
post,
}
export const post2 = oc
.route({
inputStructure: 'detailed',
method: 'POST',
operationId: 'postTrialAppsByAppIdChatMessages',
path: '/trial-apps/{app_id}/chat-messages',
tags: ['console'],
})
.input(
z.object({
body: zPostTrialAppsByAppIdChatMessagesBody,
params: zPostTrialAppsByAppIdChatMessagesPath,
}),
)
.output(zPostTrialAppsByAppIdChatMessagesResponse)
export const chatMessages = {
post: post2,
}
export const post3 = oc
.route({
inputStructure: 'detailed',
method: 'POST',
operationId: 'postTrialAppsByAppIdCompletionMessages',
path: '/trial-apps/{app_id}/completion-messages',
tags: ['console'],
})
.input(
z.object({
body: zPostTrialAppsByAppIdCompletionMessagesBody,
params: zPostTrialAppsByAppIdCompletionMessagesPath,
}),
)
.output(zPostTrialAppsByAppIdCompletionMessagesResponse)
export const completionMessages = {
post: post3,
}
export const get = oc
.route({
inputStructure: 'detailed',
@ -175,7 +126,7 @@ export const site = {
get: get4,
}
export const post4 = oc
export const post2 = oc
.route({
inputStructure: 'detailed',
method: 'POST',
@ -192,37 +143,13 @@ export const post4 = oc
.output(zPostTrialAppsByAppIdTextToAudioResponse)
export const textToAudio = {
post: post4,
}
/**
* Run workflow
*/
export const post5 = oc
.route({
inputStructure: 'detailed',
method: 'POST',
operationId: 'postTrialAppsByAppIdWorkflowsRun',
path: '/trial-apps/{app_id}/workflows/run',
summary: 'Run workflow',
tags: ['console'],
})
.input(
z.object({
body: zPostTrialAppsByAppIdWorkflowsRunBody,
params: zPostTrialAppsByAppIdWorkflowsRunPath,
}),
)
.output(zPostTrialAppsByAppIdWorkflowsRunResponse)
export const run = {
post: post5,
post: post2,
}
/**
* Stop workflow task
*/
export const post6 = oc
export const post3 = oc
.route({
inputStructure: 'detailed',
method: 'POST',
@ -235,7 +162,7 @@ export const post6 = oc
.output(zPostTrialAppsByAppIdWorkflowsTasksByTaskIdStopResponse)
export const stop = {
post: post6,
post: post3,
}
export const byTaskId = {
@ -263,7 +190,6 @@ export const get5 = oc
export const workflows = {
get: get5,
run,
tasks,
}
@ -285,8 +211,6 @@ export const get6 = oc
export const byAppId = {
get: get6,
audioToText,
chatMessages,
completionMessages,
datasets,
messages,
parameters,

View File

@ -4,66 +4,47 @@ export type ClientOptions = {
baseUrl: `${string}://${string}/console/api` | (string & {})
}
export type TrialAppDetailWithSite = {
access_mode?: string
api_base_url?: string
created_at?: number
created_by?: string
deleted_tools?: Array<TrialDeletedTool>
description?: string
enable_api?: boolean
enable_site?: boolean
icon?: string
icon_background?: string
icon_type?: string
icon_url?: string
id?: string
max_active_requests?: number
mode?: string
model_config?: TrialAppModelConfig
name?: string
export type AppDetailWithSite = {
access_mode?: string | null
api_base_url?: string | null
app_id?: string | null
bound_agent_id?: string | null
created_at?: number | null
created_by?: string | null
deleted_tools?: Array<DeletedTool>
description?: string | null
enable_api: boolean
enable_site: boolean
icon?: string | null
icon_background?: string | null
icon_type?: string | null
readonly icon_url: string | null
id: string
maintainer?: string | null
max_active_requests?: number | null
mode: string
model_config?: ModelConfig | null
name: string
permission_keys?: Array<string>
site?: TrialSite
tags?: Array<TrialTag>
updated_at?: number
updated_by?: string
use_icon_as_answer_icon?: boolean
workflow?: TrialWorkflowPartial
site?: Site | null
tags?: Array<Tag>
tracing?: JsonValue | null
updated_at?: number | null
updated_by?: string | null
use_icon_as_answer_icon?: boolean | null
workflow?: WorkflowPartial | null
}
export type AudioTranscriptResponse = {
text: string
}
export type ChatRequest = {
conversation_id?: string | null
files?: Array<unknown> | null
inputs: {
[key: string]: unknown
}
parent_message_id?: string | null
query: string
retriever_from?: string
}
export type GeneratedAppResponse = JsonValue
export type CompletionRequest = {
files?: Array<unknown> | null
inputs: {
[key: string]: unknown
}
query?: string
response_mode?: 'blocking' | 'streaming' | null
retriever_from?: string
}
export type TrialDatasetList = {
data?: Array<TrialDataset>
has_more?: boolean
limit?: number
page?: number
total?: number
export type TrialDatasetListResponse = {
data: Array<TrialDatasetListItemResponse>
has_more: boolean
limit: number
page: number
total: number
}
export type SuggestedQuestionsResponse = {
@ -111,143 +92,69 @@ export type TextToSpeechRequest = {
export type AudioBinaryResponse = Blob | File
export type TrialWorkflow = {
conversation_variables?: Array<TrialConversationVariable>
created_at?: number
created_by?: TrialSimpleAccount
environment_variables?: Array<{
[key: string]: unknown
}>
features?: {
export type WorkflowResponse = {
conversation_variables: Array<WorkflowConversationVariableResponse>
created_at: number
created_by?: SimpleAccountResponse | null
environment_variables: Array<WorkflowEnvironmentVariableResponse>
features: {
[key: string]: unknown
}
graph?: {
[key: string]: unknown
}
hash?: string
id?: string
marked_comment?: string
marked_name?: string
rag_pipeline_variables?: Array<TrialPipelineVariable>
tool_published?: boolean
updated_at?: number
updated_by?: TrialSimpleAccount
version?: string
}
export type WorkflowRunRequest = {
files?: Array<unknown> | null
inputs: {
graph: {
[key: string]: unknown
}
hash: string
id: string
marked_comment: string
marked_name: string
rag_pipeline_variables: Array<PipelineVariableResponse>
tool_published: boolean
updated_at: number
updated_by?: SimpleAccountResponse | null
version: string
}
export type SimpleResultResponse = {
result: string
}
export type TrialDeletedTool = {
provider_id?: string
tool_name?: string
type?: string
export type DeletedTool = {
provider_id: string
tool_name: string
type: string
}
export type TrialAppModelConfig = {
agent_mode?: {
[key: string]: unknown
}
annotation_reply?: {
[key: string]: unknown
}
chat_prompt_config?: {
[key: string]: unknown
}
completion_prompt_config?: {
[key: string]: unknown
}
created_at?: number
created_by?: string
dataset_configs?: {
[key: string]: unknown
}
dataset_query_variable?: string
external_data_tools?: Array<{
[key: string]: unknown
}>
file_upload?: {
[key: string]: unknown
}
model?: {
[key: string]: unknown
}
more_like_this?: {
[key: string]: unknown
}
opening_statement?: string
pre_prompt?: string
prompt_type?: string
retriever_resource?: {
[key: string]: unknown
}
sensitive_word_avoidance?: {
[key: string]: unknown
}
speech_to_text?: {
[key: string]: unknown
}
suggested_questions?: Array<string>
suggested_questions_after_answer?: {
[key: string]: unknown
}
text_to_speech?: {
[key: string]: unknown
}
updated_at?: number
updated_by?: string
user_input_form?: Array<{
[key: string]: unknown
}>
export type ModelConfig = {
agent_mode?: JsonValue | null
annotation_reply?: JsonValue | null
chat_prompt_config?: JsonValue | null
completion_prompt_config?: JsonValue | null
created_at?: number | null
created_by?: string | null
dataset_configs?: JsonValue | null
dataset_query_variable?: string | null
external_data_tools?: JsonValue | null
file_upload?: JsonValue | null
model?: JsonValue | null
more_like_this?: JsonValue | null
opening_statement?: string | null
pre_prompt?: string | null
prompt_type?: string | null
retriever_resource?: JsonValue | null
sensitive_word_avoidance?: JsonValue | null
speech_to_text?: JsonValue | null
suggested_questions?: JsonValue | null
suggested_questions_after_answer?: JsonValue | null
text_to_speech?: JsonValue | null
updated_at?: number | null
updated_by?: string | null
user_input_form?: JsonValue | null
}
export type TrialSite = {
access_token?: string
app_base_url?: string
chat_color_theme?: string
chat_color_theme_inverted?: boolean
code?: string
copyright?: string
created_at?: number
created_by?: string
custom_disclaimer?: string
customize_domain?: string
customize_token_strategy?: string
default_language?: string
description?: string
icon?: string
icon_background?: string
icon_type?: string
icon_url?: string
privacy_policy?: string
prompt_public?: boolean
show_workflow_steps?: boolean
title?: string
updated_at?: number
updated_by?: string
use_icon_as_answer_icon?: boolean
}
export type TrialTag = {
id?: string
name?: string
type?: string
}
export type TrialWorkflowPartial = {
created_at?: number
created_by?: string
id?: string
updated_at?: number
updated_by?: string
export type Tag = {
id: string
name: string
type: string
}
export type JsonValue
@ -261,16 +168,52 @@ export type JsonValue
| Array<unknown>
| null
export type TrialDataset = {
created_at?: number
created_by?: string
data_source_type?: string
description?: string
id?: string
indexing_technique?: string
name?: string
permission?: string
export type WorkflowPartial = {
created_at?: number | null
created_by?: string | null
id: string
updated_at?: number | null
updated_by?: string | null
}
export type TrialDatasetListItemResponse = {
app_count: number
author_name: string | null
built_in_field_enabled: boolean
chunk_structure: string | null
created_at: number
created_by: string
data_source_type: string | null
description: string | null
doc_form: string | null
doc_metadata: Array<DatasetDocMetadataResponse>
document_count: number
embedding_available?: boolean | null
embedding_model: string | null
embedding_model_provider: string | null
enable_api: boolean
external_knowledge_info?: DatasetExternalKnowledgeInfoResponse
external_retrieval_model: DatasetExternalRetrievalModelResponse | null
icon_info?: DatasetIconInfoResponse
id: string
indexing_technique: string | null
is_multimodal: boolean
is_published: boolean
maintainer?: string | null
name: string
permission: string
permission_keys?: Array<string>
pipeline_id: string | null
provider: string
retrieval_model_dict: DatasetRetrievalModelResponse
runtime_mode: string | null
summary_index_setting?: DatasetSummaryIndexSettingResponse
tags: Array<DatasetTagResponse>
total_available_documents: number
total_documents: number
updated_at: number
updated_by: string | null
word_count: number
}
export type JsonObject = {
@ -285,56 +228,145 @@ export type SystemParameters = {
workflow_file_upload_limit: number
}
export type TrialConversationVariable = {
description?: string
id?: string
name?: string
value?:
| string
| number
| number
| boolean
| {
[key: string]: unknown
}
| Array<unknown>
| null
value_type?: string
export type WorkflowConversationVariableResponse = {
description: string
id: string
name: string
value: unknown
value_type: string
}
export type TrialSimpleAccount = {
email?: string
id?: string
name?: string
export type SimpleAccountResponse = {
email: string
id: string
name: string
}
export type TrialPipelineVariable = {
allow_file_extension?: Array<string>
allow_file_upload_methods?: Array<string>
allowed_file_types?: Array<string>
belong_to_node_id?: string
default_value?:
| string
| number
| number
| boolean
| {
[key: string]: unknown
}
| Array<unknown>
| null
label?: string
max_length?: number
options?: Array<string>
placeholder?: string
required?: boolean
tooltips?: string
type?: string
unit?: string
variable?: string
export type WorkflowEnvironmentVariableResponse = {
description: string
id: string
name: string
value: unknown
value_type: string
}
export type GeneratedAppResponseWritable = JsonValue
export type PipelineVariableResponse = {
allowed_file_extensions?: Array<string> | null
allowed_file_types?: Array<string> | null
allowed_file_upload_methods?: Array<string> | null
belong_to_node_id: string
default_value?: unknown
label: string
max_length?: number | null
options?: Array<string> | null
placeholder?: string | null
required: boolean
tooltips?: string | null
type: string
unit?: string | null
variable: string
}
export type DatasetDocMetadataResponse = {
id: string
name: string
type: string
}
export type DatasetExternalKnowledgeInfoResponse = {
external_knowledge_api_endpoint?: string | null
external_knowledge_api_id?: string | null
external_knowledge_api_name?: string | null
external_knowledge_id?: string | null
}
export type DatasetExternalRetrievalModelResponse = {
score_threshold?: number | null
score_threshold_enabled?: boolean | null
top_k: number
}
export type DatasetIconInfoResponse = {
icon?: string | null
icon_background?: string | null
icon_type?: string | null
icon_url?: string | null
}
export type DatasetRetrievalModelResponse = {
reranking_enable: boolean
reranking_mode?: string | null
reranking_model?: DatasetRerankingModelResponse
score_threshold?: number | null
score_threshold_enabled: boolean
search_method: string
top_k: number
weights?: DatasetWeightedScoreResponse | null
}
export type DatasetSummaryIndexSettingResponse = {
enable?: boolean | null
model_name?: string | null
model_provider_name?: string | null
summary_prompt?: string | null
}
export type DatasetTagResponse = {
id: string
name: string
type: string
}
export type DatasetRerankingModelResponse = {
reranking_model_name?: string | null
reranking_provider_name?: string | null
}
export type DatasetWeightedScoreResponse = {
keyword_setting?: DatasetKeywordSettingResponse
vector_setting?: DatasetVectorSettingResponse
weight_type?: string | null
}
export type DatasetKeywordSettingResponse = {
keyword_weight?: number | null
}
export type DatasetVectorSettingResponse = {
embedding_model_name?: string | null
embedding_provider_name?: string | null
vector_weight?: number | null
}
export type AppDetailWithSiteWritable = {
access_mode?: string | null
api_base_url?: string | null
app_id?: string | null
bound_agent_id?: string | null
created_at?: number | null
created_by?: string | null
deleted_tools?: Array<DeletedTool>
description?: string | null
enable_api: boolean
enable_site: boolean
icon?: string | null
icon_background?: string | null
icon_type?: string | null
id: string
maintainer?: string | null
max_active_requests?: number | null
mode: string
model_config?: ModelConfig | null
name: string
permission_keys?: Array<string>
site?: SiteWritable | null
tags?: Array<Tag>
tracing?: JsonValue | null
updated_at?: number | null
updated_by?: string | null
use_icon_as_answer_icon?: boolean | null
workflow?: WorkflowPartial | null
}
export type SiteWritable = {
chat_color_theme?: string | null
@ -362,7 +394,7 @@ export type GetTrialAppsByAppIdData = {
}
export type GetTrialAppsByAppIdResponses = {
200: TrialAppDetailWithSite
200: AppDetailWithSite
}
export type GetTrialAppsByAppIdResponse
@ -384,38 +416,6 @@ export type PostTrialAppsByAppIdAudioToTextResponses = {
export type PostTrialAppsByAppIdAudioToTextResponse
= PostTrialAppsByAppIdAudioToTextResponses[keyof PostTrialAppsByAppIdAudioToTextResponses]
export type PostTrialAppsByAppIdChatMessagesData = {
body: ChatRequest
path: {
app_id: string
}
query?: never
url: '/trial-apps/{app_id}/chat-messages'
}
export type PostTrialAppsByAppIdChatMessagesResponses = {
200: GeneratedAppResponse
}
export type PostTrialAppsByAppIdChatMessagesResponse
= PostTrialAppsByAppIdChatMessagesResponses[keyof PostTrialAppsByAppIdChatMessagesResponses]
export type PostTrialAppsByAppIdCompletionMessagesData = {
body: CompletionRequest
path: {
app_id: string
}
query?: never
url: '/trial-apps/{app_id}/completion-messages'
}
export type PostTrialAppsByAppIdCompletionMessagesResponses = {
200: GeneratedAppResponse
}
export type PostTrialAppsByAppIdCompletionMessagesResponse
= PostTrialAppsByAppIdCompletionMessagesResponses[keyof PostTrialAppsByAppIdCompletionMessagesResponses]
export type GetTrialAppsByAppIdDatasetsData = {
body?: never
path: {
@ -430,7 +430,7 @@ export type GetTrialAppsByAppIdDatasetsData = {
}
export type GetTrialAppsByAppIdDatasetsResponses = {
200: TrialDatasetList
200: TrialDatasetListResponse
}
export type GetTrialAppsByAppIdDatasetsResponse
@ -511,28 +511,12 @@ export type GetTrialAppsByAppIdWorkflowsData = {
}
export type GetTrialAppsByAppIdWorkflowsResponses = {
200: TrialWorkflow
200: WorkflowResponse
}
export type GetTrialAppsByAppIdWorkflowsResponse
= GetTrialAppsByAppIdWorkflowsResponses[keyof GetTrialAppsByAppIdWorkflowsResponses]
export type PostTrialAppsByAppIdWorkflowsRunData = {
body: WorkflowRunRequest
path: {
app_id: string
}
query?: never
url: '/trial-apps/{app_id}/workflows/run'
}
export type PostTrialAppsByAppIdWorkflowsRunResponses = {
200: GeneratedAppResponse
}
export type PostTrialAppsByAppIdWorkflowsRunResponse
= PostTrialAppsByAppIdWorkflowsRunResponses[keyof PostTrialAppsByAppIdWorkflowsRunResponses]
export type PostTrialAppsByAppIdWorkflowsTasksByTaskIdStopData = {
body?: never
path: {

View File

@ -9,29 +9,6 @@ export const zAudioTranscriptResponse = z.object({
text: z.string(),
})
/**
* ChatRequest
*/
export const zChatRequest = z.object({
conversation_id: z.string().nullish(),
files: z.array(z.unknown()).nullish(),
inputs: z.record(z.string(), z.unknown()),
parent_message_id: z.string().nullish(),
query: z.string(),
retriever_from: z.string().optional().default('explore_app'),
})
/**
* CompletionRequest
*/
export const zCompletionRequest = z.object({
files: z.array(z.unknown()).nullish(),
inputs: z.record(z.string(), z.unknown()),
query: z.string().optional().default(''),
response_mode: z.enum(['blocking', 'streaming']).nullish(),
retriever_from: z.string().optional().default('explore_app'),
})
/**
* SuggestedQuestionsResponse
*/
@ -74,14 +51,6 @@ export const zTextToSpeechRequest = z.object({
*/
export const zAudioBinaryResponse = z.custom<Blob | File>()
/**
* WorkflowRunRequest
*/
export const zWorkflowRunRequest = z.object({
files: z.array(z.unknown()).nullish(),
inputs: z.record(z.string(), z.unknown()),
})
/**
* SimpleResultResponse
*/
@ -89,169 +58,22 @@ export const zSimpleResultResponse = z.object({
result: z.string(),
})
export const zTrialDeletedTool = z.object({
provider_id: z.string().optional(),
tool_name: z.string().optional(),
type: z.string().optional(),
/**
* DeletedTool
*/
export const zDeletedTool = z.object({
provider_id: z.string(),
tool_name: z.string(),
type: z.string(),
})
export const zTrialAppModelConfig = z.object({
agent_mode: z.record(z.string(), z.unknown()).optional(),
annotation_reply: z.record(z.string(), z.unknown()).optional(),
chat_prompt_config: z.record(z.string(), z.unknown()).optional(),
completion_prompt_config: z.record(z.string(), z.unknown()).optional(),
created_at: z.coerce
.bigint()
.min(BigInt('-9223372036854775808'), {
error: 'Invalid value: Expected int64 to be >= -9223372036854775808',
})
.max(BigInt('9223372036854775807'), {
error: 'Invalid value: Expected int64 to be <= 9223372036854775807',
})
.optional(),
created_by: z.string().optional(),
dataset_configs: z.record(z.string(), z.unknown()).optional(),
dataset_query_variable: z.string().optional(),
external_data_tools: z.array(z.record(z.string(), z.unknown())).optional(),
file_upload: z.record(z.string(), z.unknown()).optional(),
model: z.record(z.string(), z.unknown()).optional(),
more_like_this: z.record(z.string(), z.unknown()).optional(),
opening_statement: z.string().optional(),
pre_prompt: z.string().optional(),
prompt_type: z.string().optional(),
retriever_resource: z.record(z.string(), z.unknown()).optional(),
sensitive_word_avoidance: z.record(z.string(), z.unknown()).optional(),
speech_to_text: z.record(z.string(), z.unknown()).optional(),
suggested_questions: z.array(z.string()).optional(),
suggested_questions_after_answer: z.record(z.string(), z.unknown()).optional(),
text_to_speech: z.record(z.string(), z.unknown()).optional(),
updated_at: z.coerce
.bigint()
.min(BigInt('-9223372036854775808'), {
error: 'Invalid value: Expected int64 to be >= -9223372036854775808',
})
.max(BigInt('9223372036854775807'), {
error: 'Invalid value: Expected int64 to be <= 9223372036854775807',
})
.optional(),
updated_by: z.string().optional(),
user_input_form: z.array(z.record(z.string(), z.unknown())).optional(),
})
export const zTrialSite = z.object({
access_token: z.string().optional(),
app_base_url: z.string().optional(),
chat_color_theme: z.string().optional(),
chat_color_theme_inverted: z.boolean().optional(),
code: z.string().optional(),
copyright: z.string().optional(),
created_at: z.coerce
.bigint()
.min(BigInt('-9223372036854775808'), {
error: 'Invalid value: Expected int64 to be >= -9223372036854775808',
})
.max(BigInt('9223372036854775807'), {
error: 'Invalid value: Expected int64 to be <= 9223372036854775807',
})
.optional(),
created_by: z.string().optional(),
custom_disclaimer: z.string().optional(),
customize_domain: z.string().optional(),
customize_token_strategy: z.string().optional(),
default_language: z.string().optional(),
description: z.string().optional(),
icon: z.string().optional(),
icon_background: z.string().optional(),
icon_type: z.string().optional(),
icon_url: z.string().optional(),
privacy_policy: z.string().optional(),
prompt_public: z.boolean().optional(),
show_workflow_steps: z.boolean().optional(),
title: z.string().optional(),
updated_at: z.coerce
.bigint()
.min(BigInt('-9223372036854775808'), {
error: 'Invalid value: Expected int64 to be >= -9223372036854775808',
})
.max(BigInt('9223372036854775807'), {
error: 'Invalid value: Expected int64 to be <= 9223372036854775807',
})
.optional(),
updated_by: z.string().optional(),
use_icon_as_answer_icon: z.boolean().optional(),
})
export const zTrialTag = z.object({
id: z.string().optional(),
name: z.string().optional(),
type: z.string().optional(),
})
export const zTrialWorkflowPartial = z.object({
created_at: z.coerce
.bigint()
.min(BigInt('-9223372036854775808'), {
error: 'Invalid value: Expected int64 to be >= -9223372036854775808',
})
.max(BigInt('9223372036854775807'), {
error: 'Invalid value: Expected int64 to be <= 9223372036854775807',
})
.optional(),
created_by: z.string().optional(),
id: z.string().optional(),
updated_at: z.coerce
.bigint()
.min(BigInt('-9223372036854775808'), {
error: 'Invalid value: Expected int64 to be >= -9223372036854775808',
})
.max(BigInt('9223372036854775807'), {
error: 'Invalid value: Expected int64 to be <= 9223372036854775807',
})
.optional(),
updated_by: z.string().optional(),
})
export const zTrialAppDetailWithSite = z.object({
access_mode: z.string().optional(),
api_base_url: z.string().optional(),
created_at: z.coerce
.bigint()
.min(BigInt('-9223372036854775808'), {
error: 'Invalid value: Expected int64 to be >= -9223372036854775808',
})
.max(BigInt('9223372036854775807'), {
error: 'Invalid value: Expected int64 to be <= 9223372036854775807',
})
.optional(),
created_by: z.string().optional(),
deleted_tools: z.array(zTrialDeletedTool).optional(),
description: z.string().optional(),
enable_api: z.boolean().optional(),
enable_site: z.boolean().optional(),
icon: z.string().optional(),
icon_background: z.string().optional(),
icon_type: z.string().optional(),
icon_url: z.string().optional(),
id: z.string().optional(),
max_active_requests: z.int().optional(),
mode: z.string().optional(),
model_config: zTrialAppModelConfig.optional(),
name: z.string().optional(),
permission_keys: z.array(z.string()).optional(),
site: zTrialSite.optional(),
tags: z.array(zTrialTag).optional(),
updated_at: z.coerce
.bigint()
.min(BigInt('-9223372036854775808'), {
error: 'Invalid value: Expected int64 to be >= -9223372036854775808',
})
.max(BigInt('9223372036854775807'), {
error: 'Invalid value: Expected int64 to be <= 9223372036854775807',
})
.optional(),
updated_by: z.string().optional(),
use_icon_as_answer_icon: z.boolean().optional(),
workflow: zTrialWorkflowPartial.optional(),
/**
* Tag
*/
export const zTag = z.object({
id: z.string(),
name: z.string(),
type: z.string(),
})
export const zJsonValue = z
@ -266,36 +88,78 @@ export const zJsonValue = z
.nullable()
/**
* GeneratedAppResponse
* ModelConfig
*/
export const zGeneratedAppResponse = zJsonValue
export const zTrialDataset = z.object({
created_at: z.coerce
.bigint()
.min(BigInt('-9223372036854775808'), {
error: 'Invalid value: Expected int64 to be >= -9223372036854775808',
})
.max(BigInt('9223372036854775807'), {
error: 'Invalid value: Expected int64 to be <= 9223372036854775807',
})
.optional(),
created_by: z.string().optional(),
data_source_type: z.string().optional(),
description: z.string().optional(),
id: z.string().optional(),
indexing_technique: z.string().optional(),
name: z.string().optional(),
permission: z.string().optional(),
permission_keys: z.array(z.string()).optional(),
export const zModelConfig = z.object({
agent_mode: zJsonValue.nullish(),
annotation_reply: zJsonValue.nullish(),
chat_prompt_config: zJsonValue.nullish(),
completion_prompt_config: zJsonValue.nullish(),
created_at: z.int().nullish(),
created_by: z.string().nullish(),
dataset_configs: zJsonValue.nullish(),
dataset_query_variable: z.string().nullish(),
external_data_tools: zJsonValue.nullish(),
file_upload: zJsonValue.nullish(),
model: zJsonValue.nullish(),
more_like_this: zJsonValue.nullish(),
opening_statement: z.string().nullish(),
pre_prompt: z.string().nullish(),
prompt_type: z.string().nullish(),
retriever_resource: zJsonValue.nullish(),
sensitive_word_avoidance: zJsonValue.nullish(),
speech_to_text: zJsonValue.nullish(),
suggested_questions: zJsonValue.nullish(),
suggested_questions_after_answer: zJsonValue.nullish(),
text_to_speech: zJsonValue.nullish(),
updated_at: z.int().nullish(),
updated_by: z.string().nullish(),
user_input_form: zJsonValue.nullish(),
})
export const zTrialDatasetList = z.object({
data: z.array(zTrialDataset).optional(),
has_more: z.boolean().optional(),
limit: z.int().optional(),
page: z.int().optional(),
total: z.int().optional(),
/**
* WorkflowPartial
*/
export const zWorkflowPartial = z.object({
created_at: z.int().nullish(),
created_by: z.string().nullish(),
id: z.string(),
updated_at: z.int().nullish(),
updated_by: z.string().nullish(),
})
/**
* AppDetailWithSite
*/
export const zAppDetailWithSite = z.object({
access_mode: z.string().nullish(),
api_base_url: z.string().nullish(),
app_id: z.string().nullish(),
bound_agent_id: z.string().nullish(),
created_at: z.int().nullish(),
created_by: z.string().nullish(),
deleted_tools: z.array(zDeletedTool).optional(),
description: z.string().nullish(),
enable_api: z.boolean(),
enable_site: z.boolean(),
icon: z.string().nullish(),
icon_background: z.string().nullish(),
icon_type: z.string().nullish(),
icon_url: z.string().nullable(),
id: z.string(),
maintainer: z.string().nullish(),
max_active_requests: z.int().nullish(),
mode: z.string(),
model_config: zModelConfig.nullish(),
name: z.string(),
permission_keys: z.array(z.string()).optional(),
site: zSite.nullish(),
tags: z.array(zTag).optional(),
tracing: zJsonValue.nullish(),
updated_at: z.int().nullish(),
updated_by: z.string().nullish(),
use_icon_as_answer_icon: z.boolean().nullish(),
workflow: zWorkflowPartial.nullish(),
})
export const zJsonObject = z.record(z.string(), z.unknown())
@ -329,93 +193,235 @@ export const zParameters = z.object({
user_input_form: z.array(zJsonObject),
})
export const zTrialConversationVariable = z.object({
description: z.string().optional(),
id: z.string().optional(),
name: z.string().optional(),
value: z
.union([
z.string(),
z.int(),
z.number(),
z.boolean(),
z.record(z.string(), z.unknown()),
z.array(z.unknown()),
])
.nullish(),
value_type: z.string().optional(),
})
export const zTrialSimpleAccount = z.object({
email: z.string().optional(),
id: z.string().optional(),
name: z.string().optional(),
})
export const zTrialPipelineVariable = z.object({
allow_file_extension: z.array(z.string()).optional(),
allow_file_upload_methods: z.array(z.string()).optional(),
allowed_file_types: z.array(z.string()).optional(),
belong_to_node_id: z.string().optional(),
default_value: z
.union([
z.string(),
z.int(),
z.number(),
z.boolean(),
z.record(z.string(), z.unknown()),
z.array(z.unknown()),
])
.nullish(),
label: z.string().optional(),
max_length: z.int().optional(),
options: z.array(z.string()).optional(),
placeholder: z.string().optional(),
required: z.boolean().optional(),
tooltips: z.string().optional(),
type: z.string().optional(),
unit: z.string().optional(),
variable: z.string().optional(),
})
export const zTrialWorkflow = z.object({
conversation_variables: z.array(zTrialConversationVariable).optional(),
created_at: z.coerce
.bigint()
.min(BigInt('-9223372036854775808'), {
error: 'Invalid value: Expected int64 to be >= -9223372036854775808',
})
.max(BigInt('9223372036854775807'), {
error: 'Invalid value: Expected int64 to be <= 9223372036854775807',
})
.optional(),
created_by: zTrialSimpleAccount.optional(),
environment_variables: z.array(z.record(z.string(), z.unknown())).optional(),
features: z.record(z.string(), z.unknown()).optional(),
graph: z.record(z.string(), z.unknown()).optional(),
hash: z.string().optional(),
id: z.string().optional(),
marked_comment: z.string().optional(),
marked_name: z.string().optional(),
rag_pipeline_variables: z.array(zTrialPipelineVariable).optional(),
tool_published: z.boolean().optional(),
updated_at: z.coerce
.bigint()
.min(BigInt('-9223372036854775808'), {
error: 'Invalid value: Expected int64 to be >= -9223372036854775808',
})
.max(BigInt('9223372036854775807'), {
error: 'Invalid value: Expected int64 to be <= 9223372036854775807',
})
.optional(),
updated_by: zTrialSimpleAccount.optional(),
version: z.string().optional(),
/**
* WorkflowConversationVariableResponse
*/
export const zWorkflowConversationVariableResponse = z.object({
description: z.string(),
id: z.string(),
name: z.string(),
value: z.unknown(),
value_type: z.string(),
})
/**
* GeneratedAppResponse
* SimpleAccountResponse
*/
export const zGeneratedAppResponseWritable = zJsonValue
export const zSimpleAccountResponse = z.object({
email: z.string(),
id: z.string(),
name: z.string(),
})
/**
* WorkflowEnvironmentVariableResponse
*/
export const zWorkflowEnvironmentVariableResponse = z.object({
description: z.string(),
id: z.string(),
name: z.string(),
value: z.unknown(),
value_type: z.string(),
})
/**
* PipelineVariableResponse
*/
export const zPipelineVariableResponse = z.object({
allowed_file_extensions: z.array(z.string()).nullish(),
allowed_file_types: z.array(z.string()).nullish(),
allowed_file_upload_methods: z.array(z.string()).nullish(),
belong_to_node_id: z.string(),
default_value: z.unknown().optional(),
label: z.string(),
max_length: z.int().nullish(),
options: z.array(z.string()).nullish(),
placeholder: z.string().nullish(),
required: z.boolean(),
tooltips: z.string().nullish(),
type: z.string(),
unit: z.string().nullish(),
variable: z.string(),
})
/**
* WorkflowResponse
*/
export const zWorkflowResponse = z.object({
conversation_variables: z.array(zWorkflowConversationVariableResponse),
created_at: z.int(),
created_by: zSimpleAccountResponse.nullish(),
environment_variables: z.array(zWorkflowEnvironmentVariableResponse),
features: z.record(z.string(), z.unknown()),
graph: z.record(z.string(), z.unknown()),
hash: z.string(),
id: z.string(),
marked_comment: z.string(),
marked_name: z.string(),
rag_pipeline_variables: z.array(zPipelineVariableResponse),
tool_published: z.boolean(),
updated_at: z.int(),
updated_by: zSimpleAccountResponse.nullish(),
version: z.string(),
})
/**
* DatasetDocMetadataResponse
*/
export const zDatasetDocMetadataResponse = z.object({
id: z.string(),
name: z.string(),
type: z.string(),
})
/**
* DatasetExternalKnowledgeInfoResponse
*/
export const zDatasetExternalKnowledgeInfoResponse = z.object({
external_knowledge_api_endpoint: z.string().nullish(),
external_knowledge_api_id: z.string().nullish(),
external_knowledge_api_name: z.string().nullish(),
external_knowledge_id: z.string().nullish(),
})
/**
* DatasetExternalRetrievalModelResponse
*/
export const zDatasetExternalRetrievalModelResponse = z.object({
score_threshold: z.number().nullish(),
score_threshold_enabled: z.boolean().nullish(),
top_k: z.int(),
})
/**
* DatasetIconInfoResponse
*/
export const zDatasetIconInfoResponse = z.object({
icon: z.string().nullish(),
icon_background: z.string().nullish(),
icon_type: z.string().nullish(),
icon_url: z.string().nullish(),
})
/**
* DatasetSummaryIndexSettingResponse
*/
export const zDatasetSummaryIndexSettingResponse = z.object({
enable: z.boolean().nullish(),
model_name: z.string().nullish(),
model_provider_name: z.string().nullish(),
summary_prompt: z.string().nullish(),
})
/**
* DatasetTagResponse
*/
export const zDatasetTagResponse = z.object({
id: z.string(),
name: z.string(),
type: z.string(),
})
/**
* DatasetRerankingModelResponse
*/
export const zDatasetRerankingModelResponse = z.object({
reranking_model_name: z.string().nullish(),
reranking_provider_name: z.string().nullish(),
})
/**
* DatasetKeywordSettingResponse
*/
export const zDatasetKeywordSettingResponse = z.object({
keyword_weight: z.number().nullish(),
})
/**
* DatasetVectorSettingResponse
*/
export const zDatasetVectorSettingResponse = z.object({
embedding_model_name: z.string().nullish(),
embedding_provider_name: z.string().nullish(),
vector_weight: z.number().nullish(),
})
/**
* DatasetWeightedScoreResponse
*/
export const zDatasetWeightedScoreResponse = z.object({
keyword_setting: zDatasetKeywordSettingResponse.optional(),
vector_setting: zDatasetVectorSettingResponse.optional(),
weight_type: z.string().nullish(),
})
/**
* DatasetRetrievalModelResponse
*/
export const zDatasetRetrievalModelResponse = z.object({
reranking_enable: z.boolean(),
reranking_mode: z.string().nullish(),
reranking_model: zDatasetRerankingModelResponse.optional(),
score_threshold: z.number().nullish(),
score_threshold_enabled: z.boolean(),
search_method: z.string(),
top_k: z.int(),
weights: zDatasetWeightedScoreResponse.nullish(),
})
/**
* TrialDatasetListItemResponse
*/
export const zTrialDatasetListItemResponse = z.object({
app_count: z.int(),
author_name: z.string().nullable(),
built_in_field_enabled: z.boolean(),
chunk_structure: z.string().nullable(),
created_at: z.int(),
created_by: z.string(),
data_source_type: z.string().nullable(),
description: z.string().nullable(),
doc_form: z.string().nullable(),
doc_metadata: z.array(zDatasetDocMetadataResponse),
document_count: z.int(),
embedding_available: z.boolean().nullish(),
embedding_model: z.string().nullable(),
embedding_model_provider: z.string().nullable(),
enable_api: z.boolean(),
external_knowledge_info: zDatasetExternalKnowledgeInfoResponse.optional(),
external_retrieval_model: zDatasetExternalRetrievalModelResponse.nullable(),
icon_info: zDatasetIconInfoResponse.optional(),
id: z.string(),
indexing_technique: z.string().nullable(),
is_multimodal: z.boolean(),
is_published: z.boolean(),
maintainer: z.string().nullish(),
name: z.string(),
permission: z.string(),
permission_keys: z.array(z.string()).optional(),
pipeline_id: z.string().nullable(),
provider: z.string(),
retrieval_model_dict: zDatasetRetrievalModelResponse,
runtime_mode: z.string().nullable(),
summary_index_setting: zDatasetSummaryIndexSettingResponse.optional(),
tags: z.array(zDatasetTagResponse),
total_available_documents: z.int(),
total_documents: z.int(),
updated_at: z.int(),
updated_by: z.string().nullable(),
word_count: z.int(),
})
/**
* TrialDatasetListResponse
*/
export const zTrialDatasetListResponse = z.object({
data: z.array(zTrialDatasetListItemResponse),
has_more: z.boolean(),
limit: z.int(),
page: z.int(),
total: z.int(),
})
/**
* Site
@ -436,14 +442,47 @@ export const zSiteWritable = z.object({
use_icon_as_answer_icon: z.boolean(),
})
/**
* AppDetailWithSite
*/
export const zAppDetailWithSiteWritable = z.object({
access_mode: z.string().nullish(),
api_base_url: z.string().nullish(),
app_id: z.string().nullish(),
bound_agent_id: z.string().nullish(),
created_at: z.int().nullish(),
created_by: z.string().nullish(),
deleted_tools: z.array(zDeletedTool).optional(),
description: z.string().nullish(),
enable_api: z.boolean(),
enable_site: z.boolean(),
icon: z.string().nullish(),
icon_background: z.string().nullish(),
icon_type: z.string().nullish(),
id: z.string(),
maintainer: z.string().nullish(),
max_active_requests: z.int().nullish(),
mode: z.string(),
model_config: zModelConfig.nullish(),
name: z.string(),
permission_keys: z.array(z.string()).optional(),
site: zSiteWritable.nullish(),
tags: z.array(zTag).optional(),
tracing: zJsonValue.nullish(),
updated_at: z.int().nullish(),
updated_by: z.string().nullish(),
use_icon_as_answer_icon: z.boolean().nullish(),
workflow: zWorkflowPartial.nullish(),
})
export const zGetTrialAppsByAppIdPath = z.object({
app_id: z.uuid(),
})
/**
* Success
* App detail retrieved successfully
*/
export const zGetTrialAppsByAppIdResponse = zTrialAppDetailWithSite
export const zGetTrialAppsByAppIdResponse = zAppDetailWithSite
export const zPostTrialAppsByAppIdAudioToTextPath = z.object({
app_id: z.uuid(),
@ -454,28 +493,6 @@ export const zPostTrialAppsByAppIdAudioToTextPath = z.object({
*/
export const zPostTrialAppsByAppIdAudioToTextResponse = zAudioTranscriptResponse
export const zPostTrialAppsByAppIdChatMessagesBody = zChatRequest
export const zPostTrialAppsByAppIdChatMessagesPath = z.object({
app_id: z.uuid(),
})
/**
* Success
*/
export const zPostTrialAppsByAppIdChatMessagesResponse = zGeneratedAppResponse
export const zPostTrialAppsByAppIdCompletionMessagesBody = zCompletionRequest
export const zPostTrialAppsByAppIdCompletionMessagesPath = z.object({
app_id: z.uuid(),
})
/**
* Success
*/
export const zPostTrialAppsByAppIdCompletionMessagesResponse = zGeneratedAppResponse
export const zGetTrialAppsByAppIdDatasetsPath = z.object({
app_id: z.uuid(),
})
@ -489,7 +506,7 @@ export const zGetTrialAppsByAppIdDatasetsQuery = z.object({
/**
* Success
*/
export const zGetTrialAppsByAppIdDatasetsResponse = zTrialDatasetList
export const zGetTrialAppsByAppIdDatasetsResponse = zTrialDatasetListResponse
export const zGetTrialAppsByAppIdMessagesByMessageIdSuggestedQuestionsPath = z.object({
app_id: z.uuid(),
@ -536,20 +553,9 @@ export const zGetTrialAppsByAppIdWorkflowsPath = z.object({
})
/**
* Success
* Workflow detail retrieved successfully
*/
export const zGetTrialAppsByAppIdWorkflowsResponse = zTrialWorkflow
export const zPostTrialAppsByAppIdWorkflowsRunBody = zWorkflowRunRequest
export const zPostTrialAppsByAppIdWorkflowsRunPath = z.object({
app_id: z.uuid(),
})
/**
* Success
*/
export const zPostTrialAppsByAppIdWorkflowsRunResponse = zGeneratedAppResponse
export const zGetTrialAppsByAppIdWorkflowsResponse = zWorkflowResponse
export const zPostTrialAppsByAppIdWorkflowsTasksByTaskIdStopPath = z.object({
app_id: z.uuid(),

View File

@ -17,15 +17,42 @@ export type WorkflowGeneratePayload = {
export type GeneratorResponse = unknown
export type ModelConfig = {
completion_params?: {
[key: string]: unknown
}
mode: LlmMode
name: string
provider: string
agent_mode?: JsonValue | null
annotation_reply?: JsonValue | null
chat_prompt_config?: JsonValue | null
completion_prompt_config?: JsonValue | null
created_at?: number | null
created_by?: string | null
dataset_configs?: JsonValue | null
dataset_query_variable?: string | null
external_data_tools?: JsonValue | null
file_upload?: JsonValue | null
model?: JsonValue | null
more_like_this?: JsonValue | null
opening_statement?: string | null
pre_prompt?: string | null
prompt_type?: string | null
retriever_resource?: JsonValue | null
sensitive_word_avoidance?: JsonValue | null
speech_to_text?: JsonValue | null
suggested_questions?: JsonValue | null
suggested_questions_after_answer?: JsonValue | null
text_to_speech?: JsonValue | null
updated_at?: number | null
updated_by?: string | null
user_input_form?: JsonValue | null
}
export type LlmMode = 'chat' | 'completion'
export type JsonValue
= | string
| number
| number
| boolean
| {
[key: string]: unknown
}
| Array<unknown>
| null
export type PostWorkflowGenerateData = {
body: WorkflowGeneratePayload

View File

@ -7,21 +7,45 @@ import * as z from 'zod'
*/
export const zGeneratorResponse = z.unknown()
/**
* LLMMode
*
* Enum class for large language model mode.
*/
export const zLlmMode = z.enum(['chat', 'completion'])
export const zJsonValue = z
.union([
z.string(),
z.int(),
z.number(),
z.boolean(),
z.record(z.string(), z.unknown()),
z.array(z.unknown()),
])
.nullable()
/**
* ModelConfig
*/
export const zModelConfig = z.object({
completion_params: z.record(z.string(), z.unknown()).optional(),
mode: zLlmMode,
name: z.string(),
provider: z.string(),
agent_mode: zJsonValue.nullish(),
annotation_reply: zJsonValue.nullish(),
chat_prompt_config: zJsonValue.nullish(),
completion_prompt_config: zJsonValue.nullish(),
created_at: z.int().nullish(),
created_by: z.string().nullish(),
dataset_configs: zJsonValue.nullish(),
dataset_query_variable: z.string().nullish(),
external_data_tools: zJsonValue.nullish(),
file_upload: zJsonValue.nullish(),
model: zJsonValue.nullish(),
more_like_this: zJsonValue.nullish(),
opening_statement: z.string().nullish(),
pre_prompt: z.string().nullish(),
prompt_type: z.string().nullish(),
retriever_resource: zJsonValue.nullish(),
sensitive_word_avoidance: zJsonValue.nullish(),
speech_to_text: zJsonValue.nullish(),
suggested_questions: zJsonValue.nullish(),
suggested_questions_after_answer: zJsonValue.nullish(),
text_to_speech: zJsonValue.nullish(),
updated_at: z.int().nullish(),
updated_by: z.string().nullish(),
user_input_form: zJsonValue.nullish(),
})
/**

View File

@ -31,12 +31,12 @@ export type AgentProviderListResponse = Array<{
[key: string]: unknown
}>
export type SnippetPagination = {
data?: Array<AnonymousInlineModel744Ff9Cc03E6>
has_more?: boolean
limit?: number
page?: number
total?: number
export type SnippetPaginationResponse = {
data: Array<SnippetListItemResponse>
has_more: boolean
limit: number
page: number
total: number
}
export type CreateSnippetPayload = {
@ -50,28 +50,28 @@ export type CreateSnippetPayload = {
type?: 'group' | 'node'
}
export type Snippet = {
created_at?: number
created_by?: AnonymousInlineModelB0Fd3F86D9D5
description?: string
export type SnippetResponse = {
created_at?: number | null
created_by?: SimpleAccountResponse | null
description?: string | null
graph?: {
[key: string]: unknown
}
} | null
icon_info?: {
[key: string]: unknown
}
id?: string
input_fields?: {
} | null
id: string
input_fields?: Array<{
[key: string]: unknown
}
is_published?: boolean
name?: string
tags?: Array<AnonymousInlineModel7B8B49Ca164e>
type?: string
updated_at?: number
updated_by?: AnonymousInlineModelB0Fd3F86D9D5
use_count?: number
version?: number
}> | null
is_published: boolean
name: string
tags?: Array<SnippetTagResponse>
type: string
updated_at?: number | null
updated_by?: SimpleAccountResponse | null
use_count: number
version: number
}
export type SnippetImportPayload = {
@ -83,8 +83,13 @@ export type SnippetImportPayload = {
yaml_url?: string | null
}
export type SnippetImportResponse = {
[key: string]: unknown
export type SnippetImportInfo = {
current_dsl_version?: string
error?: string
id: string
imported_dsl_version?: string
snippet_id?: string | null
status: ImportStatus
}
export type UpdateSnippetPayload = {
@ -93,19 +98,17 @@ export type UpdateSnippetPayload = {
name?: string | null
}
export type SnippetDependencyCheckResponse = {
[key: string]: unknown
export type CheckDependenciesResult = {
leaked_dependencies?: Array<PluginDependency>
}
export type TextFileResponse = string
export type SnippetUseCountResponse = {
export type SnippetUseCountIncrementResponse = {
result: string
use_count: number
}
export type AccountWithRoleList = {
accounts: Array<AccountWithRole>
export type AccountWithRoleListResponse = {
accounts: Array<AccountWithRoleResponse>
}
export type DefaultModelDataResponse = {
@ -128,7 +131,7 @@ export type EndpointCreatePayload = {
}
}
export type EndpointCreateResponse = {
export type SuccessResponse = {
success: boolean
}
@ -136,28 +139,8 @@ export type EndpointIdPayload = {
endpoint_id: string
}
export type EndpointDeleteResponse = {
success: boolean
}
export type EndpointDisableResponse = {
success: boolean
}
export type EndpointEnableResponse = {
success: boolean
}
export type EndpointListResponse = {
endpoints: Array<{
[key: string]: unknown
}>
}
export type PluginEndpointListResponse = {
endpoints: Array<{
[key: string]: unknown
}>
endpoints: Array<EndpointEntityWithInstance>
}
export type LegacyEndpointUpdatePayload = {
@ -168,10 +151,6 @@ export type LegacyEndpointUpdatePayload = {
}
}
export type EndpointUpdateResponse = {
success: boolean
}
export type EndpointUpdatePayload = {
name: string
settings: {
@ -211,9 +190,9 @@ export type SimpleResultDataResponse = {
result: string
}
export type MemberActionTenantResponse = {
export type MemberActionResponse = {
result: string
tenant_id: string
tenant_id?: string
}
export type OwnerTransferPayload = {
@ -391,10 +370,6 @@ export type ParserExcludePlugin = {
plugin_id: string
}
export type SuccessResponse = {
success: boolean
}
export type PluginAutoUpgradeFetchResponse = {
auto_upgrade: PluginAutoUpgradeSettingsResponseModel
category: PluginCategory
@ -836,7 +811,7 @@ export type WorkspaceCustomConfigPayload = {
replace_webapp_logo?: string | null
}
export type WorkspaceMutationResponse = {
export type WorkspaceTenantResultResponse = {
result: string
tenant: TenantInfoResponse
}
@ -862,6 +837,7 @@ export type TenantListItemResponse = {
created_at?: number | null
current: boolean
id: string
last_opened_at?: number | null
name?: string | null
plan?: string | null
status?: string | null
@ -872,23 +848,23 @@ export type WorkspaceCustomConfigResponse = {
replace_webapp_logo?: string | null
}
export type AnonymousInlineModel744Ff9Cc03E6 = {
author_name?: string
created_at?: number
created_by?: string
description?: string
export type SnippetListItemResponse = {
author_name?: string | null
created_at?: number | null
created_by?: string | null
description?: string | null
icon_info?: {
[key: string]: unknown
}
id?: string
is_published?: boolean
name?: string
tags?: Array<AnonymousInlineModel7B8B49Ca164e>
type?: string
updated_at?: number
updated_by?: string
use_count?: number
version?: number
} | null
id: string
is_published: boolean
name: string
tags?: Array<SnippetTagResponse>
type: string
updated_at?: number | null
updated_by?: string | null
use_count: number
version: number
}
export type IconInfo = {
@ -909,20 +885,29 @@ export type InputFieldDefinition = {
type?: string | null
}
export type AnonymousInlineModelB0Fd3F86D9D5 = {
email?: string
id?: string
name?: string
export type SimpleAccountResponse = {
email: string
id: string
name: string
}
export type AnonymousInlineModel7B8B49Ca164e = {
id?: string
name?: string
type?: string
export type SnippetTagResponse = {
id: string
name: string
type: string
}
export type AccountWithRole = {
export type ImportStatus = 'completed' | 'completed-with-warnings' | 'failed' | 'pending'
export type PluginDependency = {
current_identifier?: string | null
type: Type
value: Github | Marketplace | Package
}
export type AccountWithRoleResponse = {
avatar?: string | null
readonly avatar_url: string | null
created_at?: number | null
email: string
id: string
@ -948,6 +933,23 @@ export type Inner = {
provider?: string | null
}
export type EndpointEntityWithInstance = {
created_at: string
declaration?: EndpointProviderDeclaration
enabled: boolean
expired_at: string
hook_id: string
id: string
name: string
plugin_id: string
settings: {
[key: string]: unknown
}
tenant_id: string
updated_at: string
url: string
}
export type MemberInviteResultResponse = {
email: string
message?: string | null
@ -1198,6 +1200,32 @@ export type WorkflowToolParameterConfiguration = {
name: string
}
export type Type
= | 'app-selector'
| 'array[tools]'
| 'boolean'
| 'model-selector'
| 'secret-input'
| 'select'
| 'text-input'
export type Github = {
github_plugin_unique_identifier: string
package: string
repo: string
version: string
}
export type Marketplace = {
marketplace_plugin_unique_identifier: string
version?: string | null
}
export type Package = {
plugin_unique_identifier: string
version?: string | null
}
export type SimpleProviderEntityResponse = {
icon_small?: I18nObject | null
icon_small_dark?: I18nObject | null
@ -1209,6 +1237,11 @@ export type SimpleProviderEntityResponse = {
tenant_id: string
}
export type EndpointProviderDeclaration = {
endpoints?: Array<EndpointDeclaration> | null
settings?: Array<ProviderConfig>
}
export type ConfigurateMethod = 'customizable-model' | 'predefined-model'
export type CustomConfigurationResponse = {
@ -1419,6 +1452,26 @@ export type AiModelEntityResponse = {
pricing?: PriceConfigResponse | null
}
export type EndpointDeclaration = {
hidden?: boolean
method: string
path: string
}
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: Type
url?: string | null
}
export type UnaddedModelConfiguration = {
model: string
model_type: ModelType
@ -1490,6 +1543,24 @@ export type PriceConfigResponse = {
unit: string
}
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 FormOption = {
label: GraphonModelRuntimeEntitiesCommonEntitiesI18nObject
show_on?: Array<FormShowOnObject>
@ -1511,6 +1582,25 @@ export type RestrictModel = {
model_type: ModelType
}
export type AccountWithRoleListResponseWritable = {
accounts: Array<AccountWithRoleResponseWritable>
}
export type AccountWithRoleResponseWritable = {
avatar?: string | null
created_at?: number | null
email: string
id: string
last_active_at?: number | null
last_login_at?: number | null
name: string
role: string
roles?: Array<{
[key: string]: string
}>
status: string
}
export type GetWorkspacesData = {
body?: never
path?: never
@ -1583,7 +1673,7 @@ export type GetWorkspacesCurrentCustomizedSnippetsData = {
}
export type GetWorkspacesCurrentCustomizedSnippetsResponses = {
200: SnippetPagination
200: SnippetPaginationResponse
}
export type GetWorkspacesCurrentCustomizedSnippetsResponse
@ -1601,7 +1691,7 @@ export type PostWorkspacesCurrentCustomizedSnippetsErrors = {
}
export type PostWorkspacesCurrentCustomizedSnippetsResponses = {
201: Snippet
201: SnippetResponse
}
export type PostWorkspacesCurrentCustomizedSnippetsResponse
@ -1619,8 +1709,8 @@ export type PostWorkspacesCurrentCustomizedSnippetsImportsErrors = {
}
export type PostWorkspacesCurrentCustomizedSnippetsImportsResponses = {
200: SnippetImportResponse
202: SnippetImportResponse
200: SnippetImportInfo
202: SnippetImportInfo
}
export type PostWorkspacesCurrentCustomizedSnippetsImportsResponse
@ -1640,7 +1730,7 @@ export type PostWorkspacesCurrentCustomizedSnippetsImportsByImportIdConfirmError
}
export type PostWorkspacesCurrentCustomizedSnippetsImportsByImportIdConfirmResponses = {
200: SnippetImportResponse
200: SnippetImportInfo
}
export type PostWorkspacesCurrentCustomizedSnippetsImportsByImportIdConfirmResponse
@ -1680,7 +1770,7 @@ export type GetWorkspacesCurrentCustomizedSnippetsBySnippetIdErrors = {
}
export type GetWorkspacesCurrentCustomizedSnippetsBySnippetIdResponses = {
200: Snippet
200: SnippetResponse
}
export type GetWorkspacesCurrentCustomizedSnippetsBySnippetIdResponse
@ -1701,7 +1791,7 @@ export type PatchWorkspacesCurrentCustomizedSnippetsBySnippetIdErrors = {
}
export type PatchWorkspacesCurrentCustomizedSnippetsBySnippetIdResponses = {
200: Snippet
200: SnippetResponse
}
export type PatchWorkspacesCurrentCustomizedSnippetsBySnippetIdResponse
@ -1721,34 +1811,12 @@ export type GetWorkspacesCurrentCustomizedSnippetsBySnippetIdCheckDependenciesEr
}
export type GetWorkspacesCurrentCustomizedSnippetsBySnippetIdCheckDependenciesResponses = {
200: SnippetDependencyCheckResponse
200: CheckDependenciesResult
}
export type GetWorkspacesCurrentCustomizedSnippetsBySnippetIdCheckDependenciesResponse
= GetWorkspacesCurrentCustomizedSnippetsBySnippetIdCheckDependenciesResponses[keyof GetWorkspacesCurrentCustomizedSnippetsBySnippetIdCheckDependenciesResponses]
export type GetWorkspacesCurrentCustomizedSnippetsBySnippetIdExportData = {
body?: never
path: {
snippet_id: string
}
query?: {
include_secret?: string
}
url: '/workspaces/current/customized-snippets/{snippet_id}/export'
}
export type GetWorkspacesCurrentCustomizedSnippetsBySnippetIdExportErrors = {
404: unknown
}
export type GetWorkspacesCurrentCustomizedSnippetsBySnippetIdExportResponses = {
200: TextFileResponse
}
export type GetWorkspacesCurrentCustomizedSnippetsBySnippetIdExportResponse
= GetWorkspacesCurrentCustomizedSnippetsBySnippetIdExportResponses[keyof GetWorkspacesCurrentCustomizedSnippetsBySnippetIdExportResponses]
export type PostWorkspacesCurrentCustomizedSnippetsBySnippetIdUseCountIncrementData = {
body?: never
path: {
@ -1763,7 +1831,7 @@ export type PostWorkspacesCurrentCustomizedSnippetsBySnippetIdUseCountIncrementE
}
export type PostWorkspacesCurrentCustomizedSnippetsBySnippetIdUseCountIncrementResponses = {
200: SnippetUseCountResponse
200: SnippetUseCountIncrementResponse
}
export type PostWorkspacesCurrentCustomizedSnippetsBySnippetIdUseCountIncrementResponse
@ -1777,7 +1845,7 @@ export type GetWorkspacesCurrentDatasetOperatorsData = {
}
export type GetWorkspacesCurrentDatasetOperatorsResponses = {
200: AccountWithRoleList
200: AccountWithRoleListResponse
}
export type GetWorkspacesCurrentDatasetOperatorsResponse
@ -1825,7 +1893,7 @@ export type PostWorkspacesCurrentEndpointsErrors = {
}
export type PostWorkspacesCurrentEndpointsResponses = {
200: EndpointCreateResponse
200: SuccessResponse
}
export type PostWorkspacesCurrentEndpointsResponse
@ -1843,7 +1911,7 @@ export type PostWorkspacesCurrentEndpointsCreateErrors = {
}
export type PostWorkspacesCurrentEndpointsCreateResponses = {
200: EndpointCreateResponse
200: SuccessResponse
}
export type PostWorkspacesCurrentEndpointsCreateResponse
@ -1861,7 +1929,7 @@ export type PostWorkspacesCurrentEndpointsDeleteErrors = {
}
export type PostWorkspacesCurrentEndpointsDeleteResponses = {
200: EndpointDeleteResponse
200: SuccessResponse
}
export type PostWorkspacesCurrentEndpointsDeleteResponse
@ -1879,7 +1947,7 @@ export type PostWorkspacesCurrentEndpointsDisableErrors = {
}
export type PostWorkspacesCurrentEndpointsDisableResponses = {
200: EndpointDisableResponse
200: SuccessResponse
}
export type PostWorkspacesCurrentEndpointsDisableResponse
@ -1897,7 +1965,7 @@ export type PostWorkspacesCurrentEndpointsEnableErrors = {
}
export type PostWorkspacesCurrentEndpointsEnableResponses = {
200: EndpointEnableResponse
200: SuccessResponse
}
export type PostWorkspacesCurrentEndpointsEnableResponse
@ -1932,7 +2000,7 @@ export type GetWorkspacesCurrentEndpointsListPluginData = {
}
export type GetWorkspacesCurrentEndpointsListPluginResponses = {
200: PluginEndpointListResponse
200: EndpointListResponse
}
export type GetWorkspacesCurrentEndpointsListPluginResponse
@ -1950,7 +2018,7 @@ export type PostWorkspacesCurrentEndpointsUpdateErrors = {
}
export type PostWorkspacesCurrentEndpointsUpdateResponses = {
200: EndpointUpdateResponse
200: SuccessResponse
}
export type PostWorkspacesCurrentEndpointsUpdateResponse
@ -1970,7 +2038,7 @@ export type DeleteWorkspacesCurrentEndpointsByIdErrors = {
}
export type DeleteWorkspacesCurrentEndpointsByIdResponses = {
200: EndpointDeleteResponse
200: SuccessResponse
}
export type DeleteWorkspacesCurrentEndpointsByIdResponse
@ -1990,7 +2058,7 @@ export type PatchWorkspacesCurrentEndpointsByIdErrors = {
}
export type PatchWorkspacesCurrentEndpointsByIdResponses = {
200: EndpointUpdateResponse
200: SuccessResponse
}
export type PatchWorkspacesCurrentEndpointsByIdResponse
@ -2004,7 +2072,7 @@ export type GetWorkspacesCurrentMembersData = {
}
export type GetWorkspacesCurrentMembersResponses = {
200: AccountWithRoleList
200: AccountWithRoleListResponse
}
export type GetWorkspacesCurrentMembersResponse
@ -2062,7 +2130,7 @@ export type DeleteWorkspacesCurrentMembersByMemberIdData = {
}
export type DeleteWorkspacesCurrentMembersByMemberIdResponses = {
200: MemberActionTenantResponse
200: MemberActionResponse
}
export type DeleteWorkspacesCurrentMembersByMemberIdResponse
@ -4597,14 +4665,16 @@ export type PostWorkspacesCustomConfigData = {
}
export type PostWorkspacesCustomConfigResponses = {
200: WorkspaceMutationResponse
200: WorkspaceTenantResultResponse
}
export type PostWorkspacesCustomConfigResponse
= PostWorkspacesCustomConfigResponses[keyof PostWorkspacesCustomConfigResponses]
export type PostWorkspacesCustomConfigWebappLogoUploadData = {
body?: never
body: {
file: Blob | File
}
path?: never
query?: never
url: '/workspaces/custom-config/webapp-logo/upload'
@ -4625,7 +4695,7 @@ export type PostWorkspacesInfoData = {
}
export type PostWorkspacesInfoResponses = {
200: WorkspaceMutationResponse
200: WorkspaceTenantResultResponse
}
export type PostWorkspacesInfoResponse

View File

@ -27,24 +27,9 @@ export const zSnippetImportPayload = z.object({
})
/**
* SnippetImportResponse
* SnippetUseCountIncrementResponse
*/
export const zSnippetImportResponse = z.record(z.string(), z.unknown())
/**
* SnippetDependencyCheckResponse
*/
export const zSnippetDependencyCheckResponse = z.record(z.string(), z.unknown())
/**
* TextFileResponse
*/
export const zTextFileResponse = z.string()
/**
* SnippetUseCountResponse
*/
export const zSnippetUseCountResponse = z.object({
export const zSnippetUseCountIncrementResponse = z.object({
result: z.string(),
use_count: z.int(),
})
@ -66,9 +51,9 @@ export const zEndpointCreatePayload = z.object({
})
/**
* EndpointCreateResponse
* SuccessResponse
*/
export const zEndpointCreateResponse = z.object({
export const zSuccessResponse = z.object({
success: z.boolean(),
})
@ -79,41 +64,6 @@ export const zEndpointIdPayload = z.object({
endpoint_id: z.string(),
})
/**
* EndpointDeleteResponse
*/
export const zEndpointDeleteResponse = z.object({
success: z.boolean(),
})
/**
* EndpointDisableResponse
*/
export const zEndpointDisableResponse = z.object({
success: z.boolean(),
})
/**
* EndpointEnableResponse
*/
export const zEndpointEnableResponse = z.object({
success: z.boolean(),
})
/**
* EndpointListResponse
*/
export const zEndpointListResponse = z.object({
endpoints: z.array(z.record(z.string(), z.unknown())),
})
/**
* PluginEndpointListResponse
*/
export const zPluginEndpointListResponse = z.object({
endpoints: z.array(z.record(z.string(), z.unknown())),
})
/**
* LegacyEndpointUpdatePayload
*/
@ -123,13 +73,6 @@ export const zLegacyEndpointUpdatePayload = z.object({
settings: z.record(z.string(), z.unknown()),
})
/**
* EndpointUpdateResponse
*/
export const zEndpointUpdateResponse = z.object({
success: z.boolean(),
})
/**
* EndpointUpdatePayload
*/
@ -180,11 +123,11 @@ export const zSimpleResultDataResponse = z.object({
})
/**
* MemberActionTenantResponse
* MemberActionResponse
*/
export const zMemberActionTenantResponse = z.object({
export const zMemberActionResponse = z.object({
result: z.string(),
tenant_id: z.string(),
tenant_id: z.string().optional().default(''),
})
/**
@ -306,13 +249,6 @@ export const zPluginAutoUpgradeChangeResponse = z.object({
success: z.boolean(),
})
/**
* SuccessResponse
*/
export const zSuccessResponse = z.object({
success: z.boolean(),
})
/**
* PluginDebuggingKeyResponse
*/
@ -694,6 +630,7 @@ export const zTenantListItemResponse = z.object({
created_at: z.int().nullish(),
current: z.boolean(),
id: z.string(),
last_opened_at: z.int().nullish(),
name: z.string().nullish(),
plan: z.string().nullish(),
status: z.string().nullish(),
@ -733,9 +670,9 @@ export const zTenantInfoResponse = z.object({
})
/**
* WorkspaceMutationResponse
* WorkspaceTenantResultResponse
*/
export const zWorkspaceMutationResponse = z.object({
export const zWorkspaceTenantResultResponse = z.object({
result: z.string(),
tenant: zTenantInfoResponse,
})
@ -801,98 +738,99 @@ export const zCreateSnippetPayload = z.object({
type: z.enum(['group', 'node']).optional().default('node'),
})
export const zAnonymousInlineModelB0Fd3F86D9D5 = z.object({
email: z.string().optional(),
id: z.string().optional(),
name: z.string().optional(),
})
export const zAnonymousInlineModel7B8B49Ca164e = z.object({
id: z.string().optional(),
name: z.string().optional(),
type: z.string().optional(),
})
export const zSnippet = z.object({
created_at: z.coerce
.bigint()
.min(BigInt('-9223372036854775808'), {
error: 'Invalid value: Expected int64 to be >= -9223372036854775808',
})
.max(BigInt('9223372036854775807'), {
error: 'Invalid value: Expected int64 to be <= 9223372036854775807',
})
.optional(),
created_by: zAnonymousInlineModelB0Fd3F86D9D5.optional(),
description: z.string().optional(),
graph: z.record(z.string(), z.unknown()).optional(),
icon_info: z.record(z.string(), z.unknown()).optional(),
id: z.string().optional(),
input_fields: z.record(z.string(), z.unknown()).optional(),
is_published: z.boolean().optional(),
name: z.string().optional(),
tags: z.array(zAnonymousInlineModel7B8B49Ca164e).optional(),
type: z.string().optional(),
updated_at: z.coerce
.bigint()
.min(BigInt('-9223372036854775808'), {
error: 'Invalid value: Expected int64 to be >= -9223372036854775808',
})
.max(BigInt('9223372036854775807'), {
error: 'Invalid value: Expected int64 to be <= 9223372036854775807',
})
.optional(),
updated_by: zAnonymousInlineModelB0Fd3F86D9D5.optional(),
use_count: z.int().optional(),
version: z.int().optional(),
})
export const zAnonymousInlineModel744Ff9Cc03E6 = z.object({
author_name: z.string().optional(),
created_at: z.coerce
.bigint()
.min(BigInt('-9223372036854775808'), {
error: 'Invalid value: Expected int64 to be >= -9223372036854775808',
})
.max(BigInt('9223372036854775807'), {
error: 'Invalid value: Expected int64 to be <= 9223372036854775807',
})
.optional(),
created_by: z.string().optional(),
description: z.string().optional(),
icon_info: z.record(z.string(), z.unknown()).optional(),
id: z.string().optional(),
is_published: z.boolean().optional(),
name: z.string().optional(),
tags: z.array(zAnonymousInlineModel7B8B49Ca164e).optional(),
type: z.string().optional(),
updated_at: z.coerce
.bigint()
.min(BigInt('-9223372036854775808'), {
error: 'Invalid value: Expected int64 to be >= -9223372036854775808',
})
.max(BigInt('9223372036854775807'), {
error: 'Invalid value: Expected int64 to be <= 9223372036854775807',
})
.optional(),
updated_by: z.string().optional(),
use_count: z.int().optional(),
version: z.int().optional(),
})
export const zSnippetPagination = z.object({
data: z.array(zAnonymousInlineModel744Ff9Cc03E6).optional(),
has_more: z.boolean().optional(),
limit: z.int().optional(),
page: z.int().optional(),
total: z.int().optional(),
/**
* SimpleAccountResponse
*/
export const zSimpleAccountResponse = z.object({
email: z.string(),
id: z.string(),
name: z.string(),
})
/**
* AccountWithRole
* SnippetTagResponse
*/
export const zAccountWithRole = z.object({
export const zSnippetTagResponse = z.object({
id: z.string(),
name: z.string(),
type: z.string(),
})
/**
* SnippetResponse
*/
export const zSnippetResponse = z.object({
created_at: z.int().nullish(),
created_by: zSimpleAccountResponse.nullish(),
description: z.string().nullish(),
graph: z.record(z.string(), z.unknown()).nullish(),
icon_info: z.record(z.string(), z.unknown()).nullish(),
id: z.string(),
input_fields: z.array(z.record(z.string(), z.unknown())).nullish(),
is_published: z.boolean(),
name: z.string(),
tags: z.array(zSnippetTagResponse).optional(),
type: z.string(),
updated_at: z.int().nullish(),
updated_by: zSimpleAccountResponse.nullish(),
use_count: z.int(),
version: z.int(),
})
/**
* SnippetListItemResponse
*/
export const zSnippetListItemResponse = z.object({
author_name: z.string().nullish(),
created_at: z.int().nullish(),
created_by: z.string().nullish(),
description: z.string().nullish(),
icon_info: z.record(z.string(), z.unknown()).nullish(),
id: z.string(),
is_published: z.boolean(),
name: z.string(),
tags: z.array(zSnippetTagResponse).optional(),
type: z.string(),
updated_at: z.int().nullish(),
updated_by: z.string().nullish(),
use_count: z.int(),
version: z.int(),
})
/**
* SnippetPaginationResponse
*/
export const zSnippetPaginationResponse = z.object({
data: z.array(zSnippetListItemResponse),
has_more: z.boolean(),
limit: z.int(),
page: z.int(),
total: z.int(),
})
/**
* ImportStatus
*/
export const zImportStatus = z.enum(['completed', 'completed-with-warnings', 'failed', 'pending'])
/**
* SnippetImportInfo
*/
export const zSnippetImportInfo = z.object({
current_dsl_version: z.string().optional().default('0.1.0'),
error: z.string().optional().default(''),
id: z.string(),
imported_dsl_version: z.string().optional().default(''),
snippet_id: z.string().nullish(),
status: zImportStatus,
})
/**
* AccountWithRoleResponse
*/
export const zAccountWithRoleResponse = z.object({
avatar: z.string().nullish(),
avatar_url: z.string().nullable(),
created_at: z.int().nullish(),
email: z.string(),
id: z.string(),
@ -905,10 +843,10 @@ export const zAccountWithRole = z.object({
})
/**
* AccountWithRoleList
* AccountWithRoleListResponse
*/
export const zAccountWithRoleList = z.object({
accounts: z.array(zAccountWithRole),
export const zAccountWithRoleListResponse = z.object({
accounts: z.array(zAccountWithRoleResponse),
})
/**
@ -1374,6 +1312,61 @@ export const zMcpProviderUpdatePayload = z.object({
server_url: z.string(),
})
/**
* Type
*/
export const zType = z.enum([
'app-selector',
'array[tools]',
'boolean',
'model-selector',
'secret-input',
'select',
'text-input',
])
/**
* Github
*/
export const zGithub = z.object({
github_plugin_unique_identifier: z.string(),
package: z.string(),
repo: z.string(),
version: z.string(),
})
/**
* Marketplace
*/
export const zMarketplace = z.object({
marketplace_plugin_unique_identifier: z.string(),
version: z.string().nullish(),
})
/**
* Package
*/
export const zPackage = z.object({
plugin_unique_identifier: z.string(),
version: z.string().nullish(),
})
/**
* PluginDependency
*/
export const zPluginDependency = z.object({
current_identifier: z.string().nullish(),
type: zType,
value: z.union([zGithub, zMarketplace, zPackage]),
})
/**
* CheckDependenciesResult
*/
export const zCheckDependenciesResult = z.object({
leaked_dependencies: z.array(zPluginDependency).optional(),
})
/**
* ConfigurateMethod
*
@ -1792,6 +1785,17 @@ export const zWorkflowToolUpdatePayload = z.object({
workflow_tool_id: z.string(),
})
/**
* EndpointDeclaration
*
* declaration of an endpoint
*/
export const zEndpointDeclaration = z.object({
hidden: z.boolean().optional().default(false),
method: z.string(),
path: z.string(),
})
/**
* UnaddedModelConfiguration
*
@ -1934,6 +1938,91 @@ export const zModelWithProviderListResponse = z.object({
data: z.array(zModelWithProviderEntityResponse),
})
/**
* Option
*/
export const zOption = z.object({
label: zI18nObject,
value: z.string(),
})
/**
* AppSelectorScope
*/
export const zAppSelectorScope = z.enum(['all', 'chat', 'completion', 'workflow'])
/**
* ModelSelectorScope
*/
export const zModelSelectorScope = z.enum([
'llm',
'moderation',
'rerank',
'speech2text',
'text-embedding',
'tts',
'vision',
])
/**
* ToolSelectorScope
*/
export const zToolSelectorScope = z.enum(['all', 'builtin', 'custom', 'workflow'])
/**
* ProviderConfig
*
* Model class for common provider settings like credentials
*/
export const zProviderConfig = z.object({
default: z.union([z.int(), z.string(), z.number(), z.boolean()]).nullish(),
help: zI18nObject.nullish(),
label: zI18nObject.nullish(),
multiple: z.boolean().optional().default(false),
name: z.string(),
options: z.array(zOption).nullish(),
placeholder: zI18nObject.nullish(),
required: z.boolean().optional().default(false),
scope: z.union([zAppSelectorScope, zModelSelectorScope, zToolSelectorScope]).nullish(),
type: zType,
url: z.string().nullish(),
})
/**
* EndpointProviderDeclaration
*
* declaration of an endpoint group
*/
export const zEndpointProviderDeclaration = z.object({
endpoints: z.array(zEndpointDeclaration).nullish(),
settings: z.array(zProviderConfig).optional(),
})
/**
* EndpointEntityWithInstance
*/
export const zEndpointEntityWithInstance = z.object({
created_at: z.iso.datetime(),
declaration: zEndpointProviderDeclaration.optional(),
enabled: z.boolean(),
expired_at: z.iso.datetime(),
hook_id: z.string(),
id: z.string(),
name: z.string(),
plugin_id: z.string(),
settings: z.record(z.string(), z.unknown()),
tenant_id: z.string(),
updated_at: z.iso.datetime(),
url: z.string(),
})
/**
* EndpointListResponse
*/
export const zEndpointListResponse = z.object({
endpoints: z.array(zEndpointEntityWithInstance),
})
/**
* FormShowOnObject
*
@ -2147,6 +2236,29 @@ export const zModelProviderListResponse = z.object({
data: z.array(zProviderResponse),
})
/**
* AccountWithRoleResponse
*/
export const zAccountWithRoleResponseWritable = z.object({
avatar: z.string().nullish(),
created_at: z.int().nullish(),
email: z.string(),
id: z.string(),
last_active_at: z.int().nullish(),
last_login_at: z.int().nullish(),
name: z.string(),
role: z.string(),
roles: z.array(z.record(z.string(), z.string())).optional(),
status: z.string(),
})
/**
* AccountWithRoleListResponse
*/
export const zAccountWithRoleListResponseWritable = z.object({
accounts: z.array(zAccountWithRoleResponseWritable),
})
/**
* Success
*/
@ -2183,21 +2295,21 @@ export const zGetWorkspacesCurrentCustomizedSnippetsQuery = z.object({
/**
* Snippets retrieved successfully
*/
export const zGetWorkspacesCurrentCustomizedSnippetsResponse = zSnippetPagination
export const zGetWorkspacesCurrentCustomizedSnippetsResponse = zSnippetPaginationResponse
export const zPostWorkspacesCurrentCustomizedSnippetsBody = zCreateSnippetPayload
/**
* Snippet created successfully
*/
export const zPostWorkspacesCurrentCustomizedSnippetsResponse = zSnippet
export const zPostWorkspacesCurrentCustomizedSnippetsResponse = zSnippetResponse
export const zPostWorkspacesCurrentCustomizedSnippetsImportsBody = zSnippetImportPayload
/**
* Snippet imported successfully
*/
export const zPostWorkspacesCurrentCustomizedSnippetsImportsResponse = zSnippetImportResponse
export const zPostWorkspacesCurrentCustomizedSnippetsImportsResponse = zSnippetImportInfo
export const zPostWorkspacesCurrentCustomizedSnippetsImportsByImportIdConfirmPath = z.object({
import_id: z.string(),
@ -2207,7 +2319,7 @@ export const zPostWorkspacesCurrentCustomizedSnippetsImportsByImportIdConfirmPat
* Import confirmed successfully
*/
export const zPostWorkspacesCurrentCustomizedSnippetsImportsByImportIdConfirmResponse
= zSnippetImportResponse
= zSnippetImportInfo
export const zDeleteWorkspacesCurrentCustomizedSnippetsBySnippetIdPath = z.object({
snippet_id: z.uuid(),
@ -2225,7 +2337,7 @@ export const zGetWorkspacesCurrentCustomizedSnippetsBySnippetIdPath = z.object({
/**
* Snippet retrieved successfully
*/
export const zGetWorkspacesCurrentCustomizedSnippetsBySnippetIdResponse = zSnippet
export const zGetWorkspacesCurrentCustomizedSnippetsBySnippetIdResponse = zSnippetResponse
export const zPatchWorkspacesCurrentCustomizedSnippetsBySnippetIdBody = zUpdateSnippetPayload
@ -2236,7 +2348,7 @@ export const zPatchWorkspacesCurrentCustomizedSnippetsBySnippetIdPath = z.object
/**
* Snippet updated successfully
*/
export const zPatchWorkspacesCurrentCustomizedSnippetsBySnippetIdResponse = zSnippet
export const zPatchWorkspacesCurrentCustomizedSnippetsBySnippetIdResponse = zSnippetResponse
export const zGetWorkspacesCurrentCustomizedSnippetsBySnippetIdCheckDependenciesPath = z.object({
snippet_id: z.uuid(),
@ -2246,20 +2358,7 @@ export const zGetWorkspacesCurrentCustomizedSnippetsBySnippetIdCheckDependencies
* Dependencies checked successfully
*/
export const zGetWorkspacesCurrentCustomizedSnippetsBySnippetIdCheckDependenciesResponse
= zSnippetDependencyCheckResponse
export const zGetWorkspacesCurrentCustomizedSnippetsBySnippetIdExportPath = z.object({
snippet_id: z.uuid(),
})
export const zGetWorkspacesCurrentCustomizedSnippetsBySnippetIdExportQuery = z.object({
include_secret: z.string().optional().default('false'),
})
/**
* Snippet exported successfully
*/
export const zGetWorkspacesCurrentCustomizedSnippetsBySnippetIdExportResponse = zTextFileResponse
= zCheckDependenciesResult
export const zPostWorkspacesCurrentCustomizedSnippetsBySnippetIdUseCountIncrementPath = z.object({
snippet_id: z.uuid(),
@ -2269,12 +2368,12 @@ export const zPostWorkspacesCurrentCustomizedSnippetsBySnippetIdUseCountIncremen
* Use count incremented successfully
*/
export const zPostWorkspacesCurrentCustomizedSnippetsBySnippetIdUseCountIncrementResponse
= zSnippetUseCountResponse
= zSnippetUseCountIncrementResponse
/**
* Success
*/
export const zGetWorkspacesCurrentDatasetOperatorsResponse = zAccountWithRoleList
export const zGetWorkspacesCurrentDatasetOperatorsResponse = zAccountWithRoleListResponse
export const zGetWorkspacesCurrentDefaultModelQuery = z.object({
model_type: z.enum(['llm', 'moderation', 'rerank', 'speech2text', 'text-embedding', 'tts']),
@ -2297,35 +2396,35 @@ export const zPostWorkspacesCurrentEndpointsBody = zEndpointCreatePayload
/**
* Endpoint created successfully
*/
export const zPostWorkspacesCurrentEndpointsResponse = zEndpointCreateResponse
export const zPostWorkspacesCurrentEndpointsResponse = zSuccessResponse
export const zPostWorkspacesCurrentEndpointsCreateBody = zEndpointCreatePayload
/**
* Endpoint created successfully
*/
export const zPostWorkspacesCurrentEndpointsCreateResponse = zEndpointCreateResponse
export const zPostWorkspacesCurrentEndpointsCreateResponse = zSuccessResponse
export const zPostWorkspacesCurrentEndpointsDeleteBody = zEndpointIdPayload
/**
* Endpoint deleted successfully
*/
export const zPostWorkspacesCurrentEndpointsDeleteResponse = zEndpointDeleteResponse
export const zPostWorkspacesCurrentEndpointsDeleteResponse = zSuccessResponse
export const zPostWorkspacesCurrentEndpointsDisableBody = zEndpointIdPayload
/**
* Endpoint disabled successfully
*/
export const zPostWorkspacesCurrentEndpointsDisableResponse = zEndpointDisableResponse
export const zPostWorkspacesCurrentEndpointsDisableResponse = zSuccessResponse
export const zPostWorkspacesCurrentEndpointsEnableBody = zEndpointIdPayload
/**
* Endpoint enabled successfully
*/
export const zPostWorkspacesCurrentEndpointsEnableResponse = zEndpointEnableResponse
export const zPostWorkspacesCurrentEndpointsEnableResponse = zSuccessResponse
export const zGetWorkspacesCurrentEndpointsListQuery = z.object({
page: z.int().gte(1),
@ -2346,14 +2445,14 @@ export const zGetWorkspacesCurrentEndpointsListPluginQuery = z.object({
/**
* Success
*/
export const zGetWorkspacesCurrentEndpointsListPluginResponse = zPluginEndpointListResponse
export const zGetWorkspacesCurrentEndpointsListPluginResponse = zEndpointListResponse
export const zPostWorkspacesCurrentEndpointsUpdateBody = zLegacyEndpointUpdatePayload
/**
* Endpoint updated successfully
*/
export const zPostWorkspacesCurrentEndpointsUpdateResponse = zEndpointUpdateResponse
export const zPostWorkspacesCurrentEndpointsUpdateResponse = zSuccessResponse
export const zDeleteWorkspacesCurrentEndpointsByIdPath = z.object({
id: z.string(),
@ -2362,7 +2461,7 @@ export const zDeleteWorkspacesCurrentEndpointsByIdPath = z.object({
/**
* Endpoint deleted successfully
*/
export const zDeleteWorkspacesCurrentEndpointsByIdResponse = zEndpointDeleteResponse
export const zDeleteWorkspacesCurrentEndpointsByIdResponse = zSuccessResponse
export const zPatchWorkspacesCurrentEndpointsByIdBody = zEndpointUpdatePayload
@ -2373,12 +2472,12 @@ export const zPatchWorkspacesCurrentEndpointsByIdPath = z.object({
/**
* Endpoint updated successfully
*/
export const zPatchWorkspacesCurrentEndpointsByIdResponse = zEndpointUpdateResponse
export const zPatchWorkspacesCurrentEndpointsByIdResponse = zSuccessResponse
/**
* Success
*/
export const zGetWorkspacesCurrentMembersResponse = zAccountWithRoleList
export const zGetWorkspacesCurrentMembersResponse = zAccountWithRoleListResponse
export const zPostWorkspacesCurrentMembersInviteEmailBody = zMemberInvitePayload
@ -2410,7 +2509,7 @@ export const zDeleteWorkspacesCurrentMembersByMemberIdPath = z.object({
/**
* Success
*/
export const zDeleteWorkspacesCurrentMembersByMemberIdResponse = zMemberActionTenantResponse
export const zDeleteWorkspacesCurrentMembersByMemberIdResponse = zMemberActionResponse
export const zPostWorkspacesCurrentMembersByMemberIdOwnerTransferBody = zOwnerTransferPayload
@ -3952,7 +4051,11 @@ export const zPostWorkspacesCustomConfigBody = zWorkspaceCustomConfigPayload
/**
* Success
*/
export const zPostWorkspacesCustomConfigResponse = zWorkspaceMutationResponse
export const zPostWorkspacesCustomConfigResponse = zWorkspaceTenantResultResponse
export const zPostWorkspacesCustomConfigWebappLogoUploadBody = z.object({
file: z.custom<Blob | File>(),
})
/**
* Logo uploaded
@ -3964,7 +4067,7 @@ export const zPostWorkspacesInfoBody = zWorkspaceInfoPayload
/**
* Success
*/
export const zPostWorkspacesInfoResponse = zWorkspaceMutationResponse
export const zPostWorkspacesInfoResponse = zWorkspaceTenantResultResponse
export const zPostWorkspacesSwitchBody = zSwitchWorkspacePayload

View File

@ -1414,7 +1414,7 @@ export type SelectInputConfig = {
type?: 'select'
}
export type SimpleAccount = {
export type SimpleAccountResponse = {
email: string
id: string
name: string
@ -1572,7 +1572,7 @@ export type WorkflowAppLogPaginationResponse = {
export type WorkflowAppLogPartialResponse = {
created_at?: number | null
created_by_account?: SimpleAccount | null
created_by_account?: SimpleAccountResponse | null
created_by_end_user?: SimpleEndUser | null
created_by_role?: string | null
created_from?: string | null

View File

@ -1676,9 +1676,9 @@ export const zProcessRule = z.object({
})
/**
* SimpleAccount
* SimpleAccountResponse
*/
export const zSimpleAccount = z.object({
export const zSimpleAccountResponse = z.object({
email: z.string(),
id: z.string(),
name: z.string(),
@ -2196,7 +2196,7 @@ export const zWorkflowRunForLogResponse = z.object({
*/
export const zWorkflowAppLogPartialResponse = z.object({
created_at: z.int().nullish(),
created_by_account: zSimpleAccount.nullish(),
created_by_account: zSimpleAccountResponse.nullish(),
created_by_end_user: zSimpleEndUser.nullish(),
created_by_role: z.string().nullish(),
created_from: z.string().nullish(),

View File

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

View File

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