mirror of
https://github.com/langgenius/dify.git
synced 2026-10-16 15:35:32 +08:00
refactor(api): align app model config write contract (#42979)
This commit is contained in:
@@ -1,9 +1,6 @@
|
||||
import json
|
||||
from typing import Any, cast
|
||||
|
||||
from flask import request
|
||||
from flask_restx import Resource
|
||||
from pydantic import BaseModel, Field
|
||||
from sqlalchemy.orm import Session
|
||||
|
||||
from controllers.common.fields import SimpleResultResponse
|
||||
@@ -11,6 +8,7 @@ from controllers.common.rbac import PlainApp, RBACCheck
|
||||
from controllers.common.schema import register_response_schema_models, register_schema_models
|
||||
from controllers.common.session import with_session
|
||||
from controllers.console import console_ns
|
||||
from controllers.console.app.model_config_payload import AppModelConfigPayload
|
||||
from controllers.console.app.wraps import get_app_model
|
||||
from controllers.console.wraps import (
|
||||
RBACPermission,
|
||||
@@ -30,47 +28,7 @@ from libs.login import login_required
|
||||
from models.model import App, AppMode, AppModelConfig
|
||||
from services.app_model_config_service import AppModelConfigService
|
||||
|
||||
|
||||
class ModelConfigRequest(BaseModel):
|
||||
provider: str | None = Field(default=None, description="Model provider")
|
||||
model: str | None = Field(default=None, description="Model name")
|
||||
configs: dict[str, Any] | None = Field(
|
||||
default=None,
|
||||
description="Model configuration parameters",
|
||||
)
|
||||
opening_statement: str | None = Field(default=None, description="Opening statement")
|
||||
suggested_questions: list[str] | None = Field(default=None, description="Suggested questions")
|
||||
more_like_this: dict[str, Any] | None = Field(
|
||||
default=None,
|
||||
description="More like this configuration",
|
||||
)
|
||||
speech_to_text: dict[str, Any] | None = Field(
|
||||
default=None,
|
||||
description="Speech to text configuration",
|
||||
)
|
||||
text_to_speech: dict[str, Any] | None = Field(
|
||||
default=None,
|
||||
description="Text to speech configuration",
|
||||
)
|
||||
retrieval_model: dict[str, Any] | None = Field(
|
||||
default=None,
|
||||
description="Retrieval model configuration",
|
||||
)
|
||||
tools: list[dict[str, Any]] | None = Field(
|
||||
default=None,
|
||||
description="Available tools",
|
||||
)
|
||||
dataset_configs: dict[str, Any] | None = Field(
|
||||
default=None,
|
||||
description="Dataset configurations",
|
||||
)
|
||||
agent_mode: dict[str, Any] | None = Field(
|
||||
default=None,
|
||||
description="Agent mode configuration",
|
||||
)
|
||||
|
||||
|
||||
register_schema_models(console_ns, ModelConfigRequest)
|
||||
register_schema_models(console_ns, AppModelConfigPayload)
|
||||
register_response_schema_models(console_ns, SimpleResultResponse)
|
||||
|
||||
|
||||
@@ -79,7 +37,7 @@ class ModelConfigResource(Resource):
|
||||
@console_ns.doc("update_app_model_config")
|
||||
@console_ns.doc(description="Update application model configuration")
|
||||
@console_ns.doc(params={"app_id": "Application ID"})
|
||||
@console_ns.expect(console_ns.models[ModelConfigRequest.__name__])
|
||||
@console_ns.expect(console_ns.models[AppModelConfigPayload.__name__])
|
||||
@console_ns.response(
|
||||
200,
|
||||
"Model configuration updated successfully",
|
||||
@@ -98,10 +56,11 @@ class ModelConfigResource(Resource):
|
||||
@get_app_model(mode=[AppMode.AGENT_CHAT, AppMode.CHAT, AppMode.COMPLETION])
|
||||
def post(self, session: Session, current_tenant_id: str, current_user_id: str, app_model: App):
|
||||
"""Modify the app model config and dataset joins in one request transaction."""
|
||||
# validate config
|
||||
payload = AppModelConfigPayload.model_validate(console_ns.payload or {})
|
||||
model_configuration = AppModelConfigService.validate_configuration(
|
||||
tenant_id=current_tenant_id,
|
||||
config=cast(dict, request.json),
|
||||
# Preserve omission so feature validators retain their existing defaults.
|
||||
config=payload.model_dump(exclude_unset=True),
|
||||
app_mode=AppMode.value_of(app_model.mode),
|
||||
session=session,
|
||||
)
|
||||
|
||||
@@ -0,0 +1,384 @@
|
||||
from typing import Literal, NotRequired
|
||||
|
||||
from pydantic import BaseModel, ConfigDict, Field, with_config
|
||||
from typing_extensions import TypedDict
|
||||
|
||||
from core.entities.agent_entities import PlanningStrategy
|
||||
from core.rag.entities.metadata_entities import SupportedComparisonOperator
|
||||
from core.rag.rerank.rerank_type import RerankMode
|
||||
from core.tools.entities.tool_entities import ToolProviderType
|
||||
from graphon.file.enums import FileTransferMethod, FileType
|
||||
from graphon.model_runtime.entities.llm_entities import LLMMode
|
||||
|
||||
# The recursive schema also keeps generated clients from turning JSON values into `any`.
|
||||
type AppConfigJsonValue = str | int | float | bool | None | list[AppConfigJsonValue] | dict[str, AppConfigJsonValue]
|
||||
|
||||
|
||||
# Mypy does not yet support PEP 728 extra_items; pyrefly and Pydantic check these declarations.
|
||||
# https://github.com/python/mypy/issues/18176
|
||||
class AppModelSelectionPayload(TypedDict, extra_items=AppConfigJsonValue): # type: ignore[call-arg]
|
||||
provider: str
|
||||
name: str
|
||||
completion_params: dict[str, AppConfigJsonValue]
|
||||
mode: NotRequired[str | None]
|
||||
|
||||
|
||||
# These config managers persist nested extensions alongside their known fields.
|
||||
# Keep those JSON values when an existing configuration is published again.
|
||||
class AppPromptMessagePayload(TypedDict, extra_items=AppConfigJsonValue): # type: ignore[call-arg]
|
||||
text: str
|
||||
role: str
|
||||
|
||||
|
||||
class AppChatPromptPayload(TypedDict, extra_items=AppConfigJsonValue): # type: ignore[call-arg]
|
||||
prompt: NotRequired[list[AppPromptMessagePayload]]
|
||||
|
||||
|
||||
class AppConversationRolesPayload(TypedDict, extra_items=AppConfigJsonValue): # type: ignore[call-arg]
|
||||
user_prefix: str
|
||||
assistant_prefix: str
|
||||
|
||||
|
||||
class AppCompletionPromptTextPayload(TypedDict, extra_items=AppConfigJsonValue): # type: ignore[call-arg]
|
||||
text: str
|
||||
|
||||
|
||||
class AppCompletionPromptPayload(TypedDict, extra_items=AppConfigJsonValue): # type: ignore[call-arg]
|
||||
prompt: NotRequired[AppCompletionPromptTextPayload]
|
||||
conversation_histories_role: NotRequired[AppConversationRolesPayload]
|
||||
|
||||
|
||||
@with_config(ConfigDict(extra="allow"))
|
||||
class AppInputFieldBasePayload(TypedDict):
|
||||
label: str
|
||||
variable: str
|
||||
description: NotRequired[str]
|
||||
required: NotRequired[bool | None]
|
||||
default: NotRequired[AppConfigJsonValue]
|
||||
max_length: NotRequired[int | None]
|
||||
hide: NotRequired[bool]
|
||||
type: NotRequired[str]
|
||||
enabled: NotRequired[bool]
|
||||
config: NotRequired[dict[str, AppConfigJsonValue]]
|
||||
icon: NotRequired[str | None]
|
||||
icon_background: NotRequired[str | None]
|
||||
json_schema: NotRequired[str | dict[str, AppConfigJsonValue] | None]
|
||||
|
||||
|
||||
class AppInputFieldPayload(AppInputFieldBasePayload, extra_items=AppConfigJsonValue): # type: ignore[call-arg]
|
||||
options: NotRequired[list[str]]
|
||||
|
||||
|
||||
class AppSelectFieldPayload(AppInputFieldBasePayload, extra_items=AppConfigJsonValue): # type: ignore[call-arg]
|
||||
options: NotRequired[list[str] | None]
|
||||
|
||||
|
||||
class AppTextInputPayload(BaseModel):
|
||||
model_config = ConfigDict(extra="forbid", serialize_by_alias=True)
|
||||
|
||||
text_input: AppInputFieldPayload = Field(alias="text-input")
|
||||
|
||||
|
||||
class AppSelectInputPayload(BaseModel):
|
||||
model_config = ConfigDict(extra="forbid")
|
||||
|
||||
select: AppSelectFieldPayload
|
||||
|
||||
|
||||
class AppParagraphInputPayload(BaseModel):
|
||||
model_config = ConfigDict(extra="forbid")
|
||||
|
||||
paragraph: AppInputFieldPayload
|
||||
|
||||
|
||||
class AppNumberInputPayload(BaseModel):
|
||||
model_config = ConfigDict(extra="forbid")
|
||||
|
||||
number: AppInputFieldPayload
|
||||
|
||||
|
||||
class AppCheckboxInputPayload(BaseModel):
|
||||
model_config = ConfigDict(extra="forbid")
|
||||
|
||||
checkbox: AppInputFieldPayload
|
||||
|
||||
|
||||
class AppExternalDataInputPayload(BaseModel):
|
||||
model_config = ConfigDict(extra="forbid")
|
||||
|
||||
external_data_tool: AppInputFieldPayload
|
||||
|
||||
|
||||
type AppUserInputFormPayload = (
|
||||
AppTextInputPayload
|
||||
| AppSelectInputPayload
|
||||
| AppParagraphInputPayload
|
||||
| AppNumberInputPayload
|
||||
| AppCheckboxInputPayload
|
||||
| AppExternalDataInputPayload
|
||||
)
|
||||
|
||||
|
||||
class AppFeaturePayload(TypedDict, extra_items=AppConfigJsonValue): # type: ignore[call-arg]
|
||||
enabled: NotRequired[bool | None]
|
||||
|
||||
|
||||
class AppSuggestedQuestionsModelPayload(TypedDict, extra_items=AppConfigJsonValue): # type: ignore[call-arg]
|
||||
provider: str
|
||||
name: str
|
||||
mode: NotRequired[LLMMode | Literal[""]]
|
||||
completion_params: NotRequired[dict[str, AppConfigJsonValue]]
|
||||
|
||||
|
||||
class AppSuggestedQuestionsPayload(TypedDict, extra_items=AppConfigJsonValue): # type: ignore[call-arg]
|
||||
enabled: NotRequired[bool | None]
|
||||
prompt: NotRequired[str]
|
||||
model: NotRequired[AppSuggestedQuestionsModelPayload]
|
||||
|
||||
|
||||
class AppTextToSpeechPayload(TypedDict, extra_items=AppConfigJsonValue): # type: ignore[call-arg]
|
||||
enabled: NotRequired[bool | None]
|
||||
voice: NotRequired[str]
|
||||
language: NotRequired[str]
|
||||
autoPlay: NotRequired[Literal["enabled", "disabled"]]
|
||||
|
||||
|
||||
class AppModerationContentPayload(TypedDict, extra_items=AppConfigJsonValue): # type: ignore[call-arg]
|
||||
enabled: NotRequired[bool | None]
|
||||
preset_response: NotRequired[str | None]
|
||||
|
||||
|
||||
class AppModerationConfigPayload(TypedDict, extra_items=AppConfigJsonValue): # type: ignore[call-arg]
|
||||
inputs_config: NotRequired[AppModerationContentPayload | None]
|
||||
outputs_config: NotRequired[AppModerationContentPayload | None]
|
||||
keywords: NotRequired[str | None]
|
||||
api_based_extension_id: NotRequired[str | None]
|
||||
|
||||
|
||||
class AppModerationPayload(BaseModel):
|
||||
enabled: bool | None = None
|
||||
type: str | None = None
|
||||
config: AppModerationConfigPayload | None = None
|
||||
|
||||
|
||||
class AppExternalDataToolPayload(TypedDict, extra_items=AppConfigJsonValue): # type: ignore[call-arg]
|
||||
enabled: NotRequired[bool | None]
|
||||
type: NotRequired[str]
|
||||
label: NotRequired[str]
|
||||
variable: NotRequired[str]
|
||||
config: NotRequired[dict[str, AppConfigJsonValue]]
|
||||
icon: NotRequired[str]
|
||||
icon_background: NotRequired[str]
|
||||
|
||||
|
||||
class AppDatasetSelectionPayload(TypedDict, extra_items=AppConfigJsonValue): # type: ignore[call-arg]
|
||||
id: NotRequired[str]
|
||||
enabled: NotRequired[bool]
|
||||
|
||||
|
||||
class AppLegacyDatasetSelectionPayload(TypedDict, extra_items=AppConfigJsonValue): # type: ignore[call-arg]
|
||||
id: NotRequired[str]
|
||||
enabled: NotRequired[bool | None]
|
||||
|
||||
|
||||
class AppDatasetToolPayload(TypedDict, extra_items=AppConfigJsonValue): # type: ignore[call-arg]
|
||||
dataset: AppDatasetSelectionPayload
|
||||
|
||||
|
||||
class AppEmptyDatasetCollectionPayload(TypedDict, closed=True):
|
||||
pass
|
||||
|
||||
|
||||
class AppDatasetCollectionPayload(TypedDict, extra_items=AppConfigJsonValue): # type: ignore[call-arg]
|
||||
strategy: NotRequired[str]
|
||||
datasets: list[AppDatasetToolPayload]
|
||||
|
||||
|
||||
class AppRerankingModelPayload(TypedDict, extra_items=AppConfigJsonValue): # type: ignore[call-arg]
|
||||
reranking_provider_name: NotRequired[str]
|
||||
reranking_model_name: NotRequired[str]
|
||||
|
||||
|
||||
class AppVectorWeightPayload(TypedDict, extra_items=AppConfigJsonValue): # type: ignore[call-arg]
|
||||
vector_weight: float
|
||||
embedding_provider_name: str
|
||||
embedding_model_name: str
|
||||
|
||||
|
||||
class AppKeywordWeightPayload(TypedDict, extra_items=AppConfigJsonValue): # type: ignore[call-arg]
|
||||
keyword_weight: float
|
||||
|
||||
|
||||
class AppRetrievalWeightsPayload(TypedDict, extra_items=AppConfigJsonValue): # type: ignore[call-arg]
|
||||
weight_type: NotRequired[Literal["semantic_first", "keyword_first", "customized"]]
|
||||
vector_setting: AppVectorWeightPayload
|
||||
keyword_setting: AppKeywordWeightPayload
|
||||
|
||||
|
||||
class AppMetadataModelPayload(TypedDict, extra_items=AppConfigJsonValue): # type: ignore[call-arg]
|
||||
provider: NotRequired[str]
|
||||
name: NotRequired[str]
|
||||
mode: NotRequired[LLMMode | Literal[""]]
|
||||
completion_params: NotRequired[dict[str, AppConfigJsonValue]]
|
||||
|
||||
|
||||
class AppMetadataConditionPayload(TypedDict, extra_items=AppConfigJsonValue): # type: ignore[call-arg]
|
||||
id: NotRequired[str]
|
||||
name: str
|
||||
metadata_id: NotRequired[str]
|
||||
comparison_operator: SupportedComparisonOperator
|
||||
value: NotRequired[str | int | float | list[str] | None]
|
||||
|
||||
|
||||
class AppMetadataFilteringPayload(TypedDict, extra_items=AppConfigJsonValue): # type: ignore[call-arg]
|
||||
logical_operator: NotRequired[Literal["and", "or"] | None]
|
||||
conditions: NotRequired[list[AppMetadataConditionPayload] | None]
|
||||
|
||||
|
||||
class AppDatasetConfigPayload(TypedDict, extra_items=AppConfigJsonValue): # type: ignore[call-arg]
|
||||
retrieval_model: NotRequired[Literal["single", "multiple"]]
|
||||
datasets: NotRequired[AppDatasetCollectionPayload | AppEmptyDatasetCollectionPayload | None]
|
||||
top_k: NotRequired[int]
|
||||
score_threshold: NotRequired[float | None]
|
||||
score_threshold_enabled: NotRequired[bool]
|
||||
reranking_model: NotRequired[AppRerankingModelPayload | None]
|
||||
weights: NotRequired[AppRetrievalWeightsPayload | None]
|
||||
reranking_enabled: NotRequired[bool]
|
||||
reranking_enable: NotRequired[bool]
|
||||
reranking_mode: NotRequired[RerankMode]
|
||||
metadata_filtering_mode: NotRequired[Literal["disabled", "automatic", "manual"]]
|
||||
metadata_model_config: NotRequired[AppMetadataModelPayload | None]
|
||||
metadata_filtering_conditions: NotRequired[AppMetadataFilteringPayload | None]
|
||||
|
||||
|
||||
class AppAgentPromptPayload(TypedDict, extra_items=AppConfigJsonValue): # type: ignore[call-arg]
|
||||
first_prompt: NotRequired[str]
|
||||
next_iteration: NotRequired[str]
|
||||
|
||||
|
||||
class AppProviderAgentToolPayload(TypedDict, extra_items=AppConfigJsonValue): # type: ignore[call-arg]
|
||||
enabled: NotRequired[bool | None]
|
||||
provider_type: ToolProviderType
|
||||
provider_id: str
|
||||
provider_name: NotRequired[str]
|
||||
tool_name: str
|
||||
tool_label: NotRequired[str]
|
||||
tool_parameters: dict[str, AppConfigJsonValue]
|
||||
plugin_unique_identifier: NotRequired[str | None]
|
||||
credential_id: NotRequired[str | None]
|
||||
isDeleted: NotRequired[bool]
|
||||
notAuthor: NotRequired[bool]
|
||||
|
||||
|
||||
class AppLegacyDatasetToolPayload(TypedDict, extra_items=AppConfigJsonValue): # type: ignore[call-arg]
|
||||
dataset: AppLegacyDatasetSelectionPayload
|
||||
|
||||
|
||||
class AppLegacyGoogleSearchToolPayload(TypedDict, extra_items=AppConfigJsonValue): # type: ignore[call-arg]
|
||||
google_search: AppFeaturePayload
|
||||
|
||||
|
||||
class AppLegacyWebReaderToolPayload(TypedDict, extra_items=AppConfigJsonValue): # type: ignore[call-arg]
|
||||
web_reader: AppFeaturePayload
|
||||
|
||||
|
||||
class AppLegacyWikipediaToolPayload(TypedDict, extra_items=AppConfigJsonValue): # type: ignore[call-arg]
|
||||
wikipedia: AppFeaturePayload
|
||||
|
||||
|
||||
class AppLegacyCurrentDatetimeToolPayload(TypedDict, extra_items=AppConfigJsonValue): # type: ignore[call-arg]
|
||||
current_datetime: AppFeaturePayload
|
||||
|
||||
|
||||
class AppLegacySensitiveWordConfigPayload(TypedDict, extra_items=AppConfigJsonValue): # type: ignore[call-arg]
|
||||
enabled: bool
|
||||
words: list[str]
|
||||
canned_response: str
|
||||
|
||||
|
||||
AppLegacySensitiveWordToolPayload = TypedDict( # type: ignore[misc]
|
||||
"AppLegacySensitiveWordToolPayload",
|
||||
{"sensitive-word-avoidance": AppLegacySensitiveWordConfigPayload},
|
||||
extra_items=AppConfigJsonValue,
|
||||
)
|
||||
|
||||
type AppAgentToolPayload = (
|
||||
AppProviderAgentToolPayload
|
||||
| AppLegacyDatasetToolPayload
|
||||
| AppLegacyGoogleSearchToolPayload
|
||||
| AppLegacyWebReaderToolPayload
|
||||
| AppLegacyWikipediaToolPayload
|
||||
| AppLegacyCurrentDatetimeToolPayload
|
||||
| AppLegacySensitiveWordToolPayload
|
||||
)
|
||||
|
||||
|
||||
class AppAgentModePayload(TypedDict, extra_items=AppConfigJsonValue): # type: ignore[call-arg]
|
||||
enabled: NotRequired[bool | None]
|
||||
strategy: NotRequired[PlanningStrategy | Literal["cot", "function-calling", ""] | None]
|
||||
max_iteration: NotRequired[int]
|
||||
tools: NotRequired[list[AppAgentToolPayload] | None]
|
||||
prompt: NotRequired[AppAgentPromptPayload | str | None]
|
||||
|
||||
|
||||
class AppImageUploadPayload(TypedDict, extra_items=AppConfigJsonValue): # type: ignore[call-arg]
|
||||
enabled: NotRequired[bool]
|
||||
number_limits: NotRequired[int]
|
||||
detail: NotRequired[Literal["low", "high"] | None]
|
||||
transfer_methods: NotRequired[list[FileTransferMethod]]
|
||||
|
||||
|
||||
class AppImageConfigPayload(TypedDict, extra_items=AppConfigJsonValue): # type: ignore[call-arg]
|
||||
number_limits: NotRequired[int]
|
||||
detail: NotRequired[Literal["low", "high"] | None]
|
||||
transfer_methods: NotRequired[list[FileTransferMethod]]
|
||||
|
||||
|
||||
class AppFileTypeUploadPayload(TypedDict, extra_items=AppConfigJsonValue): # type: ignore[call-arg]
|
||||
enabled: NotRequired[bool | None]
|
||||
number_limits: NotRequired[int | None]
|
||||
transfer_methods: NotRequired[list[FileTransferMethod] | None]
|
||||
|
||||
|
||||
class AppFilePreviewPayload(TypedDict, extra_items=AppConfigJsonValue): # type: ignore[call-arg]
|
||||
mode: NotRequired[str | None]
|
||||
file_type_list: NotRequired[list[str] | None]
|
||||
|
||||
|
||||
class AppFileUploadPayload(TypedDict, extra_items=AppConfigJsonValue): # type: ignore[call-arg]
|
||||
enabled: NotRequired[bool]
|
||||
image: NotRequired[AppImageUploadPayload]
|
||||
image_config: NotRequired[AppImageConfigPayload | None]
|
||||
document: NotRequired[AppFileTypeUploadPayload | None]
|
||||
audio: NotRequired[AppFileTypeUploadPayload | None]
|
||||
video: NotRequired[AppFileTypeUploadPayload | None]
|
||||
custom: NotRequired[AppFileTypeUploadPayload | None]
|
||||
preview_config: NotRequired[AppFilePreviewPayload | None]
|
||||
allowed_file_types: NotRequired[list[FileType]]
|
||||
allowed_file_extensions: NotRequired[list[str]]
|
||||
allowed_file_upload_methods: NotRequired[list[FileTransferMethod]]
|
||||
number_limits: NotRequired[int]
|
||||
|
||||
|
||||
class AppModelConfigPayload(BaseModel):
|
||||
"""Write transport; app-mode validators own defaults and feature-specific rules."""
|
||||
|
||||
model: AppModelSelectionPayload
|
||||
prompt_type: Literal["simple", "advanced", ""] | None = None
|
||||
pre_prompt: str | None = None
|
||||
chat_prompt_config: AppChatPromptPayload | None = None
|
||||
completion_prompt_config: AppCompletionPromptPayload | None = None
|
||||
user_input_form: list[AppUserInputFormPayload] | None = None
|
||||
dataset_query_variable: str | None = None
|
||||
dataset_configs: AppDatasetConfigPayload | None = None
|
||||
agent_mode: AppAgentModePayload | None = None
|
||||
external_data_tools: list[AppExternalDataToolPayload] | None = None
|
||||
file_upload: AppFileUploadPayload | None = None
|
||||
opening_statement: str | None = None
|
||||
suggested_questions: list[str] | None = None
|
||||
suggested_questions_after_answer: AppSuggestedQuestionsPayload | None = None
|
||||
more_like_this: AppFeaturePayload | None = None
|
||||
speech_to_text: AppFeaturePayload | None = None
|
||||
text_to_speech: AppTextToSpeechPayload | None = None
|
||||
retriever_resource: AppFeaturePayload | None = None
|
||||
sensitive_word_avoidance: AppModerationPayload | None = None
|
||||
@@ -207,6 +207,36 @@ class DatasetConfigManager:
|
||||
if not isinstance(config["agent_mode"]["tools"], list):
|
||||
raise ValueError("tools in agent_mode must be a list of objects")
|
||||
|
||||
# All app modes persist these tools, including modes that skip the agent validator.
|
||||
for tool in config["agent_mode"]["tools"]:
|
||||
if not isinstance(tool, dict):
|
||||
continue
|
||||
if all(field in tool for field in ("provider_type", "provider_id", "tool_name", "tool_parameters")):
|
||||
tool_config = tool
|
||||
else:
|
||||
tool_name = next(
|
||||
(
|
||||
name
|
||||
for name in (
|
||||
"dataset",
|
||||
"google_search",
|
||||
"web_reader",
|
||||
"wikipedia",
|
||||
"current_datetime",
|
||||
"sensitive-word-avoidance",
|
||||
)
|
||||
if name in tool
|
||||
),
|
||||
None,
|
||||
)
|
||||
if tool_name is None:
|
||||
continue
|
||||
tool_config = tool[tool_name]
|
||||
if not isinstance(tool_config, dict):
|
||||
continue
|
||||
if "enabled" not in tool_config or tool_config["enabled"] is None:
|
||||
tool_config["enabled"] = False
|
||||
|
||||
# strategy
|
||||
if "strategy" not in config["agent_mode"] or not config["agent_mode"].get("strategy"):
|
||||
config["agent_mode"]["strategy"] = PlanningStrategy.ROUTER
|
||||
|
||||
@@ -2811,7 +2811,7 @@ Update application model configuration
|
||||
|
||||
| Required | Schema |
|
||||
| -------- | ------ |
|
||||
| Yes | **application/json**: [ModelConfigRequest](#modelconfigrequest)<br> |
|
||||
| Yes | **application/json**: [AppModelConfigPayload](#appmodelconfigpayload)<br> |
|
||||
|
||||
#### Responses
|
||||
|
||||
@@ -15742,6 +15742,16 @@ This class is used to store the schema information of an api based tool.
|
||||
| app_id | string | | No |
|
||||
| items | [ [AccessMatrixItem](#accessmatrixitem) ] | | No |
|
||||
|
||||
#### AppAgentModePayload
|
||||
|
||||
| Name | Type | Description | Required |
|
||||
| ---- | ---- | ----------- | -------- |
|
||||
| enabled | boolean | | No |
|
||||
| max_iteration | integer | | No |
|
||||
| prompt | [AppAgentPromptPayload](#appagentpromptpayload)<br>string | | No |
|
||||
| strategy | [PlanningStrategy](#planningstrategy)<br>string, <br>**Available values:** "", "cot", "function-calling" | | No |
|
||||
| tools | [ [AppAgentToolPayload](#appagenttoolpayload) ] | | No |
|
||||
|
||||
#### AppAgentModeResponse
|
||||
|
||||
| Name | Type | Description | Required |
|
||||
@@ -15752,6 +15762,13 @@ This class is used to store the schema information of an api based tool.
|
||||
| strategy | [PlanningStrategy](#planningstrategy)<br>string, <br>**Available values:** "cot", "function-calling" | | No |
|
||||
| tools | [ [AppProviderAgentToolResponse](#appprovideragenttoolresponse)<br>[AppLegacyDatasetToolResponse](#applegacydatasettoolresponse)<br>[AppLegacyGoogleSearchToolResponse](#applegacygooglesearchtoolresponse)<br>[AppLegacyWebReaderToolResponse](#applegacywebreadertoolresponse)<br>[AppLegacyWikipediaToolResponse](#applegacywikipediatoolresponse)<br>[AppLegacyCurrentDatetimeToolResponse](#applegacycurrentdatetimetoolresponse)<br>[AppLegacySensitiveWordToolResponseItem](#applegacysensitivewordtoolresponseitem) ] | | No |
|
||||
|
||||
#### AppAgentPromptPayload
|
||||
|
||||
| Name | Type | Description | Required |
|
||||
| ---- | ---- | ----------- | -------- |
|
||||
| first_prompt | string | | No |
|
||||
| next_iteration | string | | No |
|
||||
|
||||
#### AppAgentPromptResponse
|
||||
|
||||
| Name | Type | Description | Required |
|
||||
@@ -15759,6 +15776,12 @@ This class is used to store the schema information of an api based tool.
|
||||
| first_prompt | string | | No |
|
||||
| next_iteration | string | | No |
|
||||
|
||||
#### AppAgentToolPayload
|
||||
|
||||
| Name | Type | Description | Required |
|
||||
| ---- | ---- | ----------- | -------- |
|
||||
| AppAgentToolPayload | [AppProviderAgentToolPayload](#appprovideragenttoolpayload)<br>[AppLegacyDatasetToolPayload](#applegacydatasettoolpayload)<br>[AppLegacyGoogleSearchToolPayload](#applegacygooglesearchtoolpayload)<br>[AppLegacyWebReaderToolPayload](#applegacywebreadertoolpayload)<br>[AppLegacyWikipediaToolPayload](#applegacywikipediatoolpayload)<br>[AppLegacyCurrentDatetimeToolPayload](#applegacycurrentdatetimetoolpayload)<br>[AppLegacySensitiveWordToolPayload](#applegacysensitivewordtoolpayload) | | |
|
||||
|
||||
#### AppAnnotationReplyDisabledResponse
|
||||
|
||||
| Name | Type | Description | Required |
|
||||
@@ -15793,12 +15816,24 @@ This class is used to store the schema information of an api based tool.
|
||||
| role | string | | Yes |
|
||||
| text | string | | Yes |
|
||||
|
||||
#### AppChatPromptPayload
|
||||
|
||||
| Name | Type | Description | Required |
|
||||
| ---- | ---- | ----------- | -------- |
|
||||
| prompt | [ [AppPromptMessagePayload](#apppromptmessagepayload) ] | | No |
|
||||
|
||||
#### AppCheckboxFormResponse
|
||||
|
||||
| Name | Type | Description | Required |
|
||||
| ---- | ---- | ----------- | -------- |
|
||||
| checkbox | [AppUserInputFormConfigResponse](#appuserinputformconfigresponse) | | Yes |
|
||||
|
||||
#### AppCheckboxInputPayload
|
||||
|
||||
| Name | Type | Description | Required |
|
||||
| ---- | ---- | ----------- | -------- |
|
||||
| checkbox | [AppInputFieldPayload](#appinputfieldpayload) | | Yes |
|
||||
|
||||
#### AppCompletionPromptConfigResponse
|
||||
|
||||
| Name | Type | Description | Required |
|
||||
@@ -15806,12 +15841,31 @@ This class is used to store the schema information of an api based tool.
|
||||
| conversation_histories_role | [AppConversationHistoriesRoleResponse](#appconversationhistoriesroleresponse) | | No |
|
||||
| prompt | [AppCompletionPromptTextResponse](#appcompletionprompttextresponse) | | No |
|
||||
|
||||
#### AppCompletionPromptPayload
|
||||
|
||||
| Name | Type | Description | Required |
|
||||
| ---- | ---- | ----------- | -------- |
|
||||
| conversation_histories_role | [AppConversationRolesPayload](#appconversationrolespayload) | | No |
|
||||
| prompt | [AppCompletionPromptTextPayload](#appcompletionprompttextpayload) | | No |
|
||||
|
||||
#### AppCompletionPromptTextPayload
|
||||
|
||||
| Name | Type | Description | Required |
|
||||
| ---- | ---- | ----------- | -------- |
|
||||
| text | string | | Yes |
|
||||
|
||||
#### AppCompletionPromptTextResponse
|
||||
|
||||
| Name | Type | Description | Required |
|
||||
| ---- | ---- | ----------- | -------- |
|
||||
| text | string | | Yes |
|
||||
|
||||
#### AppConfigJsonValue
|
||||
|
||||
| Name | Type | Description | Required |
|
||||
| ---- | ---- | ----------- | -------- |
|
||||
| AppConfigJsonValue | string<br>integer<br>number<br>boolean<br>[ [AppConfigJsonValue](#appconfigjsonvalue) ]<br>object | | |
|
||||
|
||||
#### AppConversationHistoriesRoleResponse
|
||||
|
||||
| Name | Type | Description | Required |
|
||||
@@ -15819,6 +15873,38 @@ This class is used to store the schema information of an api based tool.
|
||||
| assistant_prefix | string | | Yes |
|
||||
| user_prefix | string | | Yes |
|
||||
|
||||
#### AppConversationRolesPayload
|
||||
|
||||
| Name | Type | Description | Required |
|
||||
| ---- | ---- | ----------- | -------- |
|
||||
| assistant_prefix | string | | Yes |
|
||||
| user_prefix | string | | Yes |
|
||||
|
||||
#### AppDatasetCollectionPayload
|
||||
|
||||
| Name | Type | Description | Required |
|
||||
| ---- | ---- | ----------- | -------- |
|
||||
| datasets | [ [AppDatasetToolPayload](#appdatasettoolpayload) ] | | Yes |
|
||||
| strategy | string | | No |
|
||||
|
||||
#### AppDatasetConfigPayload
|
||||
|
||||
| Name | Type | Description | Required |
|
||||
| ---- | ---- | ----------- | -------- |
|
||||
| datasets | [AppDatasetCollectionPayload](#appdatasetcollectionpayload)<br>[AppEmptyDatasetCollectionPayload](#appemptydatasetcollectionpayload) | | No |
|
||||
| metadata_filtering_conditions | [AppMetadataFilteringPayload](#appmetadatafilteringpayload) | | No |
|
||||
| metadata_filtering_mode | string, <br>**Available values:** "automatic", "disabled", "manual" | *Enum:* `"automatic"`, `"disabled"`, `"manual"` | No |
|
||||
| metadata_model_config | [AppMetadataModelPayload](#appmetadatamodelpayload) | | No |
|
||||
| reranking_enable | boolean | | No |
|
||||
| reranking_enabled | boolean | | No |
|
||||
| reranking_mode | [RerankMode](#rerankmode) | | No |
|
||||
| reranking_model | [AppRerankingModelPayload](#apprerankingmodelpayload) | | No |
|
||||
| retrieval_model | string, <br>**Available values:** "multiple", "single" | *Enum:* `"multiple"`, `"single"` | No |
|
||||
| score_threshold | number | | No |
|
||||
| score_threshold_enabled | boolean | | No |
|
||||
| top_k | integer | | No |
|
||||
| weights | [AppRetrievalWeightsPayload](#appretrievalweightspayload) | | No |
|
||||
|
||||
#### AppDatasetConfigsResponse
|
||||
|
||||
| Name | Type | Description | Required |
|
||||
@@ -15857,6 +15943,19 @@ This class is used to store the schema information of an api based tool.
|
||||
| enabled | boolean | | No |
|
||||
| id | string | | No |
|
||||
|
||||
#### AppDatasetSelectionPayload
|
||||
|
||||
| Name | Type | Description | Required |
|
||||
| ---- | ---- | ----------- | -------- |
|
||||
| enabled | boolean | | No |
|
||||
| id | string | | No |
|
||||
|
||||
#### AppDatasetToolPayload
|
||||
|
||||
| Name | Type | Description | Required |
|
||||
| ---- | ---- | ----------- | -------- |
|
||||
| dataset | [AppDatasetSelectionPayload](#appdatasetselectionpayload) | | Yes |
|
||||
|
||||
#### AppDetail
|
||||
|
||||
| Name | Type | Description | Required |
|
||||
@@ -15970,6 +16069,11 @@ This class is used to store the schema information of an api based tool.
|
||||
| embedding_model_name | string | | Yes |
|
||||
| embedding_provider_name | string | | Yes |
|
||||
|
||||
#### AppEmptyDatasetCollectionPayload
|
||||
|
||||
| Name | Type | Description | Required |
|
||||
| ---- | ---- | ----------- | -------- |
|
||||
|
||||
#### AppEnabledConfigResponse
|
||||
|
||||
| Name | Type | Description | Required |
|
||||
@@ -16003,12 +16107,36 @@ This class is used to store the schema information of an api based tool.
|
||||
| ---- | ---- | ----------- | -------- |
|
||||
| data | string | | Yes |
|
||||
|
||||
#### AppExternalDataInputPayload
|
||||
|
||||
| Name | Type | Description | Required |
|
||||
| ---- | ---- | ----------- | -------- |
|
||||
| external_data_tool | [AppInputFieldPayload](#appinputfieldpayload) | | Yes |
|
||||
|
||||
#### AppExternalDataToolFormResponse
|
||||
|
||||
| Name | Type | Description | Required |
|
||||
| ---- | ---- | ----------- | -------- |
|
||||
| external_data_tool | [AppUserInputFormConfigResponse](#appuserinputformconfigresponse) | | Yes |
|
||||
|
||||
#### AppExternalDataToolPayload
|
||||
|
||||
| Name | Type | Description | Required |
|
||||
| ---- | ---- | ----------- | -------- |
|
||||
| config | object | | No |
|
||||
| enabled | boolean | | No |
|
||||
| icon | string | | No |
|
||||
| icon_background | string | | No |
|
||||
| label | string | | No |
|
||||
| type | string | | No |
|
||||
| variable | string | | No |
|
||||
|
||||
#### AppFeaturePayload
|
||||
|
||||
| Name | Type | Description | Required |
|
||||
| ---- | ---- | ----------- | -------- |
|
||||
| enabled | boolean | | No |
|
||||
|
||||
#### AppFileFormResponse
|
||||
|
||||
| Name | Type | Description | Required |
|
||||
@@ -16021,6 +16149,38 @@ This class is used to store the schema information of an api based tool.
|
||||
| ---- | ---- | ----------- | -------- |
|
||||
| file-list | [AppUserInputFormConfigResponse](#appuserinputformconfigresponse) | | Yes |
|
||||
|
||||
#### AppFilePreviewPayload
|
||||
|
||||
| Name | Type | Description | Required |
|
||||
| ---- | ---- | ----------- | -------- |
|
||||
| file_type_list | [ string ] | | No |
|
||||
| mode | string | | No |
|
||||
|
||||
#### AppFileTypeUploadPayload
|
||||
|
||||
| Name | Type | Description | Required |
|
||||
| ---- | ---- | ----------- | -------- |
|
||||
| enabled | boolean | | No |
|
||||
| number_limits | integer | | No |
|
||||
| transfer_methods | [ [FileTransferMethod](#filetransfermethod) ] | | No |
|
||||
|
||||
#### AppFileUploadPayload
|
||||
|
||||
| Name | Type | Description | Required |
|
||||
| ---- | ---- | ----------- | -------- |
|
||||
| allowed_file_extensions | [ string ] | | No |
|
||||
| allowed_file_types | [ [FileType](#filetype) ] | | No |
|
||||
| allowed_file_upload_methods | [ [FileTransferMethod](#filetransfermethod) ] | | No |
|
||||
| audio | [AppFileTypeUploadPayload](#appfiletypeuploadpayload) | | No |
|
||||
| custom | [AppFileTypeUploadPayload](#appfiletypeuploadpayload) | | No |
|
||||
| document | [AppFileTypeUploadPayload](#appfiletypeuploadpayload) | | No |
|
||||
| enabled | boolean | | No |
|
||||
| image | [AppImageUploadPayload](#appimageuploadpayload) | | No |
|
||||
| image_config | [AppImageConfigPayload](#appimageconfigpayload) | | No |
|
||||
| number_limits | integer | | No |
|
||||
| preview_config | [AppFilePreviewPayload](#appfilepreviewpayload) | | No |
|
||||
| video | [AppFileTypeUploadPayload](#appfiletypeuploadpayload) | | No |
|
||||
|
||||
#### AppFileUploadResponse
|
||||
|
||||
| Name | Type | Description | Required |
|
||||
@@ -16040,6 +16200,23 @@ This class is used to store the schema information of an api based tool.
|
||||
| icon_background | string | Icon background color | No |
|
||||
| icon_type | [IconType](#icontype) | Icon type | No |
|
||||
|
||||
#### AppImageConfigPayload
|
||||
|
||||
| Name | Type | Description | Required |
|
||||
| ---- | ---- | ----------- | -------- |
|
||||
| detail | string, <br>**Available values:** "high", "low" | | No |
|
||||
| number_limits | integer | | No |
|
||||
| transfer_methods | [ [FileTransferMethod](#filetransfermethod) ] | | No |
|
||||
|
||||
#### AppImageUploadPayload
|
||||
|
||||
| Name | Type | Description | Required |
|
||||
| ---- | ---- | ----------- | -------- |
|
||||
| detail | string, <br>**Available values:** "high", "low" | | No |
|
||||
| enabled | boolean | | No |
|
||||
| number_limits | integer | | No |
|
||||
| transfer_methods | [ [FileTransferMethod](#filetransfermethod) ] | | No |
|
||||
|
||||
#### AppImageUploadResponse
|
||||
|
||||
| Name | Type | Description | Required |
|
||||
@@ -16076,6 +16253,25 @@ This class is used to store the schema information of an api based tool.
|
||||
| status | [ImportStatus](#importstatus) | | Yes |
|
||||
| warnings | [ [DslImportWarning](#dslimportwarning) ] | | No |
|
||||
|
||||
#### AppInputFieldPayload
|
||||
|
||||
| Name | Type | Description | Required |
|
||||
| ---- | ---- | ----------- | -------- |
|
||||
| config | object | | No |
|
||||
| default | [AppConfigJsonValue](#appconfigjsonvalue) | | No |
|
||||
| description | string | | No |
|
||||
| enabled | boolean | | No |
|
||||
| hide | boolean | | No |
|
||||
| icon | string | | No |
|
||||
| icon_background | string | | No |
|
||||
| json_schema | string<br>object | | No |
|
||||
| label | string | | Yes |
|
||||
| max_length | integer | | No |
|
||||
| options | [ string ] | | No |
|
||||
| required | boolean | | No |
|
||||
| type | string | | No |
|
||||
| variable | string | | Yes |
|
||||
|
||||
#### AppJsonObjectFormResponse
|
||||
|
||||
| Name | Type | Description | Required |
|
||||
@@ -16088,24 +16284,69 @@ This class is used to store the schema information of an api based tool.
|
||||
| ---- | ---- | ----------- | -------- |
|
||||
| keyword_weight | number | | Yes |
|
||||
|
||||
#### AppKeywordWeightPayload
|
||||
|
||||
| Name | Type | Description | Required |
|
||||
| ---- | ---- | ----------- | -------- |
|
||||
| keyword_weight | number | | Yes |
|
||||
|
||||
#### AppLegacyCurrentDatetimeToolPayload
|
||||
|
||||
| Name | Type | Description | Required |
|
||||
| ---- | ---- | ----------- | -------- |
|
||||
| current_datetime | [AppFeaturePayload](#appfeaturepayload) | | Yes |
|
||||
|
||||
#### AppLegacyCurrentDatetimeToolResponse
|
||||
|
||||
| Name | Type | Description | Required |
|
||||
| ---- | ---- | ----------- | -------- |
|
||||
| current_datetime | object | | Yes |
|
||||
|
||||
#### AppLegacyDatasetSelectionPayload
|
||||
|
||||
| Name | Type | Description | Required |
|
||||
| ---- | ---- | ----------- | -------- |
|
||||
| enabled | boolean | | No |
|
||||
| id | string | | No |
|
||||
|
||||
#### AppLegacyDatasetToolPayload
|
||||
|
||||
| Name | Type | Description | Required |
|
||||
| ---- | ---- | ----------- | -------- |
|
||||
| dataset | [AppLegacyDatasetSelectionPayload](#applegacydatasetselectionpayload) | | Yes |
|
||||
|
||||
#### AppLegacyDatasetToolResponse
|
||||
|
||||
| Name | Type | Description | Required |
|
||||
| ---- | ---- | ----------- | -------- |
|
||||
| dataset | [AppDatasetReferenceResponse](#appdatasetreferenceresponse) | | Yes |
|
||||
|
||||
#### AppLegacyGoogleSearchToolPayload
|
||||
|
||||
| Name | Type | Description | Required |
|
||||
| ---- | ---- | ----------- | -------- |
|
||||
| google_search | [AppFeaturePayload](#appfeaturepayload) | | Yes |
|
||||
|
||||
#### AppLegacyGoogleSearchToolResponse
|
||||
|
||||
| Name | Type | Description | Required |
|
||||
| ---- | ---- | ----------- | -------- |
|
||||
| google_search | object | | Yes |
|
||||
|
||||
#### AppLegacySensitiveWordConfigPayload
|
||||
|
||||
| Name | Type | Description | Required |
|
||||
| ---- | ---- | ----------- | -------- |
|
||||
| canned_response | string | | Yes |
|
||||
| enabled | boolean | | Yes |
|
||||
| words | [ string ] | | Yes |
|
||||
|
||||
#### AppLegacySensitiveWordToolPayload
|
||||
|
||||
| Name | Type | Description | Required |
|
||||
| ---- | ---- | ----------- | -------- |
|
||||
| sensitive-word-avoidance | [AppLegacySensitiveWordConfigPayload](#applegacysensitivewordconfigpayload) | | Yes |
|
||||
|
||||
#### AppLegacySensitiveWordToolResponse
|
||||
|
||||
| Name | Type | Description | Required |
|
||||
@@ -16120,12 +16361,24 @@ This class is used to store the schema information of an api based tool.
|
||||
| ---- | ---- | ----------- | -------- |
|
||||
| sensitive-word-avoidance | [AppLegacySensitiveWordToolResponse](#applegacysensitivewordtoolresponse) | | Yes |
|
||||
|
||||
#### AppLegacyWebReaderToolPayload
|
||||
|
||||
| Name | Type | Description | Required |
|
||||
| ---- | ---- | ----------- | -------- |
|
||||
| web_reader | [AppFeaturePayload](#appfeaturepayload) | | Yes |
|
||||
|
||||
#### AppLegacyWebReaderToolResponse
|
||||
|
||||
| Name | Type | Description | Required |
|
||||
| ---- | ---- | ----------- | -------- |
|
||||
| web_reader | object | | Yes |
|
||||
|
||||
#### AppLegacyWikipediaToolPayload
|
||||
|
||||
| Name | Type | Description | Required |
|
||||
| ---- | ---- | ----------- | -------- |
|
||||
| wikipedia | [AppFeaturePayload](#appfeaturepayload) | | Yes |
|
||||
|
||||
#### AppLegacyWikipediaToolResponse
|
||||
|
||||
| Name | Type | Description | Required |
|
||||
@@ -16166,6 +16419,16 @@ AppMCPServer Status Enum
|
||||
| ---- | ---- | ----------- | -------- |
|
||||
| AppMCPServerStatus | string | AppMCPServer Status Enum | |
|
||||
|
||||
#### AppMetadataConditionPayload
|
||||
|
||||
| Name | Type | Description | Required |
|
||||
| ---- | ---- | ----------- | -------- |
|
||||
| comparison_operator | string, <br>**Available values:** "<", "=", ">", "after", "before", "contains", "empty", "end with", "in", "is", "is not", "not contains", "not empty", "not in", "start with", "≠", "≤", "≥" | *Enum:* `"<"`, `"="`, `">"`, `"after"`, `"before"`, `"contains"`, `"empty"`, `"end with"`, `"in"`, `"is"`, `"is not"`, `"not contains"`, `"not empty"`, `"not in"`, `"start with"`, `"≠"`, `"≤"`, `"≥"` | Yes |
|
||||
| id | string | | No |
|
||||
| metadata_id | string | | No |
|
||||
| name | string | | Yes |
|
||||
| value | string<br>[ string ]<br>integer<br>number | | No |
|
||||
|
||||
#### AppMetadataConditionResponse
|
||||
|
||||
| Name | Type | Description | Required |
|
||||
@@ -16183,12 +16446,54 @@ AppMCPServer Status Enum
|
||||
| conditions | [ [AppMetadataConditionResponse](#appmetadataconditionresponse) ] | | No |
|
||||
| logical_operator | string, <br>**Available values:** "and", "or" | | No |
|
||||
|
||||
#### AppMetadataFilteringPayload
|
||||
|
||||
| Name | Type | Description | Required |
|
||||
| ---- | ---- | ----------- | -------- |
|
||||
| conditions | [ [AppMetadataConditionPayload](#appmetadataconditionpayload) ] | | No |
|
||||
| logical_operator | string, <br>**Available values:** "and", "or" | | No |
|
||||
|
||||
#### AppMetadataModelPayload
|
||||
|
||||
| Name | Type | Description | Required |
|
||||
| ---- | ---- | ----------- | -------- |
|
||||
| completion_params | object | | No |
|
||||
| mode | [LLMMode](#llmmode)<br>string | | No |
|
||||
| name | string | | No |
|
||||
| provider | string | | No |
|
||||
|
||||
#### AppMode
|
||||
|
||||
| Name | Type | Description | Required |
|
||||
| ---- | ---- | ----------- | -------- |
|
||||
| AppMode | string | | |
|
||||
|
||||
#### AppModelConfigPayload
|
||||
|
||||
Write transport; app-mode validators own defaults and feature-specific rules.
|
||||
|
||||
| Name | Type | Description | Required |
|
||||
| ---- | ---- | ----------- | -------- |
|
||||
| agent_mode | [AppAgentModePayload](#appagentmodepayload) | | No |
|
||||
| chat_prompt_config | [AppChatPromptPayload](#appchatpromptpayload) | | No |
|
||||
| completion_prompt_config | [AppCompletionPromptPayload](#appcompletionpromptpayload) | | No |
|
||||
| dataset_configs | [AppDatasetConfigPayload](#appdatasetconfigpayload) | | No |
|
||||
| dataset_query_variable | string | | No |
|
||||
| external_data_tools | [ [AppExternalDataToolPayload](#appexternaldatatoolpayload) ] | | No |
|
||||
| file_upload | [AppFileUploadPayload](#appfileuploadpayload) | | No |
|
||||
| model | [AppModelSelectionPayload](#appmodelselectionpayload) | | Yes |
|
||||
| more_like_this | [AppFeaturePayload](#appfeaturepayload) | | No |
|
||||
| opening_statement | string | | No |
|
||||
| pre_prompt | string | | No |
|
||||
| prompt_type | string, <br>**Available values:** "", "advanced", "simple" | | No |
|
||||
| retriever_resource | [AppFeaturePayload](#appfeaturepayload) | | No |
|
||||
| sensitive_word_avoidance | [AppModerationPayload](#appmoderationpayload) | | No |
|
||||
| speech_to_text | [AppFeaturePayload](#appfeaturepayload) | | No |
|
||||
| suggested_questions | [ string ] | | No |
|
||||
| suggested_questions_after_answer | [AppSuggestedQuestionsPayload](#appsuggestedquestionspayload) | | No |
|
||||
| text_to_speech | [AppTextToSpeechPayload](#apptexttospeechpayload) | | No |
|
||||
| user_input_form | [ [AppUserInputFormPayload](#appuserinputformpayload) ] | | No |
|
||||
|
||||
#### AppModelConfigResponse
|
||||
|
||||
| Name | Type | Description | Required |
|
||||
@@ -16218,6 +16523,15 @@ AppMCPServer Status Enum
|
||||
| updated_by | string | | Yes |
|
||||
| user_input_form | [ [AppTextInputFormResponse](#apptextinputformresponse)<br>[AppSelectFormResponse](#appselectformresponse)<br>[AppParagraphFormResponse](#appparagraphformresponse)<br>[AppNumberFormResponse](#appnumberformresponse)<br>[AppCheckboxFormResponse](#appcheckboxformresponse)<br>[AppFileFormResponse](#appfileformresponse)<br>[AppFileListFormResponse](#appfilelistformresponse)<br>[AppExternalDataToolFormResponse](#appexternaldatatoolformresponse)<br>[AppJsonObjectFormResponse](#appjsonobjectformresponse) ] | | Yes |
|
||||
|
||||
#### AppModelSelectionPayload
|
||||
|
||||
| Name | Type | Description | Required |
|
||||
| ---- | ---- | ----------- | -------- |
|
||||
| completion_params | object | | Yes |
|
||||
| mode | string | | No |
|
||||
| name | string | | Yes |
|
||||
| provider | string | | Yes |
|
||||
|
||||
#### AppModelSelectionResponse
|
||||
|
||||
| Name | Type | Description | Required |
|
||||
@@ -16227,6 +16541,30 @@ AppMCPServer Status Enum
|
||||
| name | string | | No |
|
||||
| provider | string | | No |
|
||||
|
||||
#### AppModerationConfigPayload
|
||||
|
||||
| Name | Type | Description | Required |
|
||||
| ---- | ---- | ----------- | -------- |
|
||||
| api_based_extension_id | string | | No |
|
||||
| inputs_config | [AppModerationContentPayload](#appmoderationcontentpayload) | | No |
|
||||
| keywords | string | | No |
|
||||
| outputs_config | [AppModerationContentPayload](#appmoderationcontentpayload) | | No |
|
||||
|
||||
#### AppModerationContentPayload
|
||||
|
||||
| Name | Type | Description | Required |
|
||||
| ---- | ---- | ----------- | -------- |
|
||||
| enabled | boolean | | No |
|
||||
| preset_response | string | | No |
|
||||
|
||||
#### AppModerationPayload
|
||||
|
||||
| Name | Type | Description | Required |
|
||||
| ---- | ---- | ----------- | -------- |
|
||||
| config | [AppModerationConfigPayload](#appmoderationconfigpayload) | | No |
|
||||
| enabled | boolean | | No |
|
||||
| type | string | | No |
|
||||
|
||||
#### AppNamePayload
|
||||
|
||||
| Name | Type | Description | Required |
|
||||
@@ -16239,6 +16577,12 @@ AppMCPServer Status Enum
|
||||
| ---- | ---- | ----------- | -------- |
|
||||
| number | [AppUserInputFormConfigResponse](#appuserinputformconfigresponse) | | Yes |
|
||||
|
||||
#### AppNumberInputPayload
|
||||
|
||||
| Name | Type | Description | Required |
|
||||
| ---- | ---- | ----------- | -------- |
|
||||
| number | [AppInputFieldPayload](#appinputfieldpayload) | | Yes |
|
||||
|
||||
#### AppPagination
|
||||
|
||||
| Name | Type | Description | Required |
|
||||
@@ -16255,6 +16599,12 @@ AppMCPServer Status Enum
|
||||
| ---- | ---- | ----------- | -------- |
|
||||
| paragraph | [AppUserInputFormConfigResponse](#appuserinputformconfigresponse) | | Yes |
|
||||
|
||||
#### AppParagraphInputPayload
|
||||
|
||||
| Name | Type | Description | Required |
|
||||
| ---- | ---- | ----------- | -------- |
|
||||
| paragraph | [AppInputFieldPayload](#appinputfieldpayload) | | Yes |
|
||||
|
||||
#### AppPartial
|
||||
|
||||
| Name | Type | Description | Required |
|
||||
@@ -16286,6 +16636,29 @@ AppMCPServer Status Enum
|
||||
| use_icon_as_answer_icon | boolean | | No |
|
||||
| workflow | [WorkflowPartial](#workflowpartial) | | No |
|
||||
|
||||
#### AppPromptMessagePayload
|
||||
|
||||
| Name | Type | Description | Required |
|
||||
| ---- | ---- | ----------- | -------- |
|
||||
| role | string | | Yes |
|
||||
| text | string | | Yes |
|
||||
|
||||
#### AppProviderAgentToolPayload
|
||||
|
||||
| Name | Type | Description | Required |
|
||||
| ---- | ---- | ----------- | -------- |
|
||||
| credential_id | string | | No |
|
||||
| enabled | boolean | | No |
|
||||
| isDeleted | boolean | | No |
|
||||
| notAuthor | boolean | | No |
|
||||
| plugin_unique_identifier | string | | No |
|
||||
| provider_id | string | | Yes |
|
||||
| provider_name | string | | No |
|
||||
| provider_type | [ToolProviderType](#toolprovidertype) | | Yes |
|
||||
| tool_label | string | | No |
|
||||
| tool_name | string | | Yes |
|
||||
| tool_parameters | object | | Yes |
|
||||
|
||||
#### AppProviderAgentToolResponse
|
||||
|
||||
| Name | Type | Description | Required |
|
||||
@@ -16302,6 +16675,13 @@ AppMCPServer Status Enum
|
||||
| tool_name | string | | Yes |
|
||||
| tool_parameters | object | | Yes |
|
||||
|
||||
#### AppRerankingModelPayload
|
||||
|
||||
| Name | Type | Description | Required |
|
||||
| ---- | ---- | ----------- | -------- |
|
||||
| reranking_model_name | string | | No |
|
||||
| reranking_provider_name | string | | No |
|
||||
|
||||
#### AppRerankingModelResponse
|
||||
|
||||
| Name | Type | Description | Required |
|
||||
@@ -16309,12 +16689,45 @@ AppMCPServer Status Enum
|
||||
| reranking_model_name | string | | No |
|
||||
| reranking_provider_name | string | | No |
|
||||
|
||||
#### AppRetrievalWeightsPayload
|
||||
|
||||
| Name | Type | Description | Required |
|
||||
| ---- | ---- | ----------- | -------- |
|
||||
| keyword_setting | [AppKeywordWeightPayload](#appkeywordweightpayload) | | Yes |
|
||||
| vector_setting | [AppVectorWeightPayload](#appvectorweightpayload) | | Yes |
|
||||
| weight_type | string, <br>**Available values:** "customized", "keyword_first", "semantic_first" | *Enum:* `"customized"`, `"keyword_first"`, `"semantic_first"` | No |
|
||||
|
||||
#### AppSelectFieldPayload
|
||||
|
||||
| Name | Type | Description | Required |
|
||||
| ---- | ---- | ----------- | -------- |
|
||||
| config | object | | No |
|
||||
| default | [AppConfigJsonValue](#appconfigjsonvalue) | | No |
|
||||
| description | string | | No |
|
||||
| enabled | boolean | | No |
|
||||
| hide | boolean | | No |
|
||||
| icon | string | | No |
|
||||
| icon_background | string | | No |
|
||||
| json_schema | string<br>object | | No |
|
||||
| label | string | | Yes |
|
||||
| max_length | integer | | No |
|
||||
| options | [ string ] | | No |
|
||||
| required | boolean | | No |
|
||||
| type | string | | No |
|
||||
| variable | string | | Yes |
|
||||
|
||||
#### AppSelectFormResponse
|
||||
|
||||
| Name | Type | Description | Required |
|
||||
| ---- | ---- | ----------- | -------- |
|
||||
| select | [AppUserInputFormConfigResponse](#appuserinputformconfigresponse) | | Yes |
|
||||
|
||||
#### AppSelectInputPayload
|
||||
|
||||
| Name | Type | Description | Required |
|
||||
| ---- | ---- | ----------- | -------- |
|
||||
| select | [AppSelectFieldPayload](#appselectfieldpayload) | | Yes |
|
||||
|
||||
#### AppSelectorScope
|
||||
|
||||
| Name | Type | Description | Required |
|
||||
@@ -16387,12 +16800,44 @@ AppMCPServer Status Enum
|
||||
| model | [AppModelSelectionResponse](#appmodelselectionresponse) | | No |
|
||||
| prompt | string | | No |
|
||||
|
||||
#### AppSuggestedQuestionsModelPayload
|
||||
|
||||
| Name | Type | Description | Required |
|
||||
| ---- | ---- | ----------- | -------- |
|
||||
| completion_params | object | | No |
|
||||
| mode | [LLMMode](#llmmode)<br>string | | No |
|
||||
| name | string | | Yes |
|
||||
| provider | string | | Yes |
|
||||
|
||||
#### AppSuggestedQuestionsPayload
|
||||
|
||||
| Name | Type | Description | Required |
|
||||
| ---- | ---- | ----------- | -------- |
|
||||
| enabled | boolean | | No |
|
||||
| model | [AppSuggestedQuestionsModelPayload](#appsuggestedquestionsmodelpayload) | | No |
|
||||
| prompt | string | | No |
|
||||
|
||||
#### AppTextInputFormResponse
|
||||
|
||||
| Name | Type | Description | Required |
|
||||
| ---- | ---- | ----------- | -------- |
|
||||
| text-input | [AppUserInputFormConfigResponse](#appuserinputformconfigresponse) | | Yes |
|
||||
|
||||
#### AppTextInputPayload
|
||||
|
||||
| Name | Type | Description | Required |
|
||||
| ---- | ---- | ----------- | -------- |
|
||||
| text-input | [AppInputFieldPayload](#appinputfieldpayload) | | Yes |
|
||||
|
||||
#### AppTextToSpeechPayload
|
||||
|
||||
| Name | Type | Description | Required |
|
||||
| ---- | ---- | ----------- | -------- |
|
||||
| autoPlay | string, <br>**Available values:** "disabled", "enabled" | *Enum:* `"disabled"`, `"enabled"` | No |
|
||||
| enabled | boolean | | No |
|
||||
| language | string | | No |
|
||||
| voice | string | | No |
|
||||
|
||||
#### AppTextToSpeechResponse
|
||||
|
||||
| Name | Type | Description | Required |
|
||||
@@ -16438,6 +16883,12 @@ AppMCPServer Status Enum
|
||||
| type | string | | No |
|
||||
| variable | string | | Yes |
|
||||
|
||||
#### AppUserInputFormPayload
|
||||
|
||||
| Name | Type | Description | Required |
|
||||
| ---- | ---- | ----------- | -------- |
|
||||
| AppUserInputFormPayload | [AppTextInputPayload](#apptextinputpayload)<br>[AppSelectInputPayload](#appselectinputpayload)<br>[AppParagraphInputPayload](#appparagraphinputpayload)<br>[AppNumberInputPayload](#appnumberinputpayload)<br>[AppCheckboxInputPayload](#appcheckboxinputpayload)<br>[AppExternalDataInputPayload](#appexternaldatainputpayload) | | |
|
||||
|
||||
#### AppVariableConfig
|
||||
|
||||
| Name | Type | Description | Required |
|
||||
@@ -16455,6 +16906,14 @@ AppMCPServer Status Enum
|
||||
| embedding_provider_name | string | | Yes |
|
||||
| vector_weight | number | | Yes |
|
||||
|
||||
#### AppVectorWeightPayload
|
||||
|
||||
| Name | Type | Description | Required |
|
||||
| ---- | ---- | ----------- | -------- |
|
||||
| embedding_model_name | string | | Yes |
|
||||
| embedding_provider_name | string | | Yes |
|
||||
| vector_weight | number | | Yes |
|
||||
|
||||
#### AppWeightsResponse
|
||||
|
||||
| Name | Type | Description | Required |
|
||||
@@ -20097,23 +20556,6 @@ Metadata operation data
|
||||
| updated_at | integer | | No |
|
||||
| updated_by | string | | No |
|
||||
|
||||
#### ModelConfigRequest
|
||||
|
||||
| Name | Type | Description | Required |
|
||||
| ---- | ---- | ----------- | -------- |
|
||||
| agent_mode | object | Agent mode configuration | No |
|
||||
| configs | object | Model configuration parameters | No |
|
||||
| dataset_configs | object | Dataset configurations | No |
|
||||
| model | string | Model name | No |
|
||||
| more_like_this | object | More like this configuration | No |
|
||||
| opening_statement | string | Opening statement | No |
|
||||
| provider | string | Model provider | No |
|
||||
| retrieval_model | object | Retrieval model configuration | No |
|
||||
| speech_to_text | object | Speech to text configuration | No |
|
||||
| suggested_questions | [ string ] | Suggested questions | No |
|
||||
| text_to_speech | object | Text to speech configuration | No |
|
||||
| tools | [ object ] | Available tools | No |
|
||||
|
||||
#### ModelCredentialResponse
|
||||
|
||||
| Name | Type | Description | Required |
|
||||
|
||||
@@ -3,23 +3,656 @@ from __future__ import annotations
|
||||
import importlib
|
||||
import json
|
||||
import os
|
||||
from copy import deepcopy
|
||||
from dataclasses import dataclass
|
||||
from inspect import unwrap
|
||||
from unittest.mock import MagicMock
|
||||
from pathlib import Path
|
||||
from types import SimpleNamespace
|
||||
from unittest.mock import DEFAULT, MagicMock
|
||||
from uuid import uuid4
|
||||
|
||||
import pytest
|
||||
import yaml
|
||||
from flask import Flask
|
||||
from flask.testing import FlaskClient
|
||||
from flask_restx import Resource
|
||||
from sqlalchemy import func, select
|
||||
from sqlalchemy.engine import Engine
|
||||
from sqlalchemy.orm import Session, object_session, sessionmaker
|
||||
|
||||
from controllers.common import session as controller_session
|
||||
from controllers.console.app import model_config as model_config_module
|
||||
from core.app.app_config.easy_ui_based_app.dataset.manager import DatasetConfigManager
|
||||
from core.app.app_config.easy_ui_based_app.model_config import manager as model_config_manager_module
|
||||
from core.app.apps.agent_chat.app_config_manager import AgentChatAppConfigManager
|
||||
from core.app.apps.chat.app_config_manager import ChatAppConfigManager
|
||||
from core.app.apps.completion.app_config_manager import CompletionAppConfigManager
|
||||
from fields.app_model_config_response import AppModelConfigResponse
|
||||
from libs.external_api import ExternalApi
|
||||
from models.model import App, AppMode, AppModelConfig
|
||||
from models.provider_ids import ModelProviderID
|
||||
|
||||
app_wraps_module = importlib.import_module("controllers.console.app.wraps")
|
||||
|
||||
|
||||
def _model_config_payload(**fields: object) -> dict[str, object]:
|
||||
return {
|
||||
"model": {
|
||||
"provider": "langgenius/openai/openai",
|
||||
"name": "gpt-4o-mini",
|
||||
"completion_params": {},
|
||||
},
|
||||
**fields,
|
||||
}
|
||||
|
||||
|
||||
def _existing_publish_configs() -> list[tuple[str, AppMode, dict[str, object]]]:
|
||||
recommended_apps_path = Path(__file__).resolve().parents[5] / "constants" / "recommended_apps.json"
|
||||
recommended_apps = json.loads(recommended_apps_path.read_text())["app_details"]
|
||||
cases = []
|
||||
for app_detail in recommended_apps.values():
|
||||
payload = yaml.safe_load(app_detail["export_data"]).get("model_config")
|
||||
if payload is not None:
|
||||
cases.append((app_detail["name"], AppMode.value_of(app_detail["mode"]), payload))
|
||||
|
||||
# Mirrors the publish body's advanced-prompt, dataset-selection, and feature fields.
|
||||
cases.append(
|
||||
(
|
||||
"configuration-editor-publish",
|
||||
AppMode.CHAT,
|
||||
_model_config_payload(
|
||||
model={
|
||||
"provider": "langgenius/openai/openai",
|
||||
"name": "gpt-4o",
|
||||
"mode": "chat",
|
||||
"completion_params": {"temperature": 0.7},
|
||||
},
|
||||
pre_prompt="",
|
||||
prompt_type="advanced",
|
||||
chat_prompt_config={"prompt": [{"role": "system", "text": "hi"}]},
|
||||
completion_prompt_config={
|
||||
"prompt": {"text": "completion"},
|
||||
"conversation_histories_role": {"assistant_prefix": "assistant", "user_prefix": "user"},
|
||||
},
|
||||
user_input_form=[{"text-input": {"label": "Name", "variable": "name", "required": True}}],
|
||||
dataset_query_variable="context",
|
||||
dataset_configs={
|
||||
"retrieval_model": "multiple",
|
||||
"datasets": {"datasets": [{"dataset": {"enabled": True, "id": "dataset-1"}}]},
|
||||
},
|
||||
agent_mode={"enabled": True, "max_iteration": 3, "strategy": "function_call", "tools": []},
|
||||
external_data_tools=[],
|
||||
more_like_this={"enabled": True},
|
||||
opening_statement="hello",
|
||||
suggested_questions=["how are you?"],
|
||||
suggested_questions_after_answer={"enabled": False},
|
||||
speech_to_text={"enabled": False},
|
||||
text_to_speech={"enabled": False, "voice": "", "language": ""},
|
||||
retriever_resource={"enabled": True},
|
||||
sensitive_word_avoidance={"enabled": False},
|
||||
file_upload={
|
||||
"enabled": True,
|
||||
"image": {
|
||||
"enabled": True,
|
||||
"detail": "high",
|
||||
"number_limits": 2,
|
||||
"transfer_methods": ["local_file"],
|
||||
},
|
||||
},
|
||||
system_parameters={
|
||||
"audio_file_size_limit": 1,
|
||||
"file_size_limit": 1,
|
||||
"image_file_size_limit": 1,
|
||||
"video_file_size_limit": 1,
|
||||
"workflow_file_upload_limit": 1,
|
||||
},
|
||||
),
|
||||
)
|
||||
)
|
||||
return cases
|
||||
|
||||
|
||||
@dataclass
|
||||
class _ModelConfigHttp:
|
||||
client: FlaskClient
|
||||
app_model: App
|
||||
session: Session
|
||||
validate_configuration: MagicMock
|
||||
signal: MagicMock
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def model_config_http(sqlite_session: Session, monkeypatch: pytest.MonkeyPatch) -> _ModelConfigHttp:
|
||||
app_model = App(
|
||||
id="app-1",
|
||||
mode=AppMode.CHAT,
|
||||
app_model_config_id="config-0",
|
||||
updated_by=None,
|
||||
updated_at=None,
|
||||
)
|
||||
original_config = AppModelConfig(app_id=app_model.id, created_by="u1", updated_by="u1")
|
||||
original_config.id = "config-0"
|
||||
sqlite_session.add(original_config)
|
||||
sqlite_session.commit()
|
||||
validate_configuration = MagicMock(
|
||||
wraps=model_config_module.AppModelConfigService.validate_configuration,
|
||||
return_value={"pre_prompt": "Validated prompt"},
|
||||
)
|
||||
monkeypatch.setattr(model_config_module.AppModelConfigService, "validate_configuration", validate_configuration)
|
||||
signal = MagicMock()
|
||||
monkeypatch.setattr(model_config_module.app_model_config_was_updated, "send", signal)
|
||||
|
||||
class ModelConfigHttpResource(Resource):
|
||||
def post(self):
|
||||
# Admission is supplied by this harness; parsing and HTTP errors use the real controller and API.
|
||||
return unwrap(model_config_module.ModelConfigResource.post)(
|
||||
model_config_module.ModelConfigResource(), sqlite_session, "t1", "u1", app_model=app_model
|
||||
)
|
||||
|
||||
http_app = Flask(__name__)
|
||||
http_app.config.update(TESTING=True)
|
||||
ExternalApi(http_app).add_resource(ModelConfigHttpResource, "/apps/app-1/model-config")
|
||||
return _ModelConfigHttp(http_app.test_client(), app_model, sqlite_session, validate_configuration, signal)
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def real_model_config_validation(model_config_http: _ModelConfigHttp, monkeypatch: pytest.MonkeyPatch) -> None:
|
||||
assembly = MagicMock()
|
||||
assembly.model_provider_factory.get_providers.return_value = [SimpleNamespace(provider="langgenius/openai/openai")]
|
||||
assembly.provider_manager.get_configurations.return_value.get_models.return_value = [
|
||||
SimpleNamespace(model="gpt-4o-mini", model_properties={"mode": "chat"})
|
||||
]
|
||||
monkeypatch.setattr(model_config_manager_module, "create_plugin_model_assembly", lambda **_kwargs: assembly)
|
||||
monkeypatch.setattr(DatasetConfigManager, "is_dataset_exists", lambda *_args: True)
|
||||
monkeypatch.setattr(
|
||||
model_config_module.ToolManager,
|
||||
"get_agent_tool_runtime",
|
||||
MagicMock(side_effect=ValueError("Tool provider is unavailable in this test")),
|
||||
)
|
||||
model_config_http.validate_configuration.return_value = DEFAULT
|
||||
|
||||
|
||||
def test_post_preserves_configuration_wire_for_business_validation(model_config_http: _ModelConfigHttp) -> None:
|
||||
payload = _model_config_payload(
|
||||
model={
|
||||
"provider": "langgenius/openai/openai",
|
||||
"name": "gpt-4o-mini",
|
||||
"mode": "chat",
|
||||
"completion_params": {
|
||||
"temperature": 0,
|
||||
"stop": [],
|
||||
"provider_options": {"cache": False, "routing": {"fallback": None}},
|
||||
},
|
||||
},
|
||||
pre_prompt="Answer {{topic}}",
|
||||
prompt_type="advanced",
|
||||
chat_prompt_config={"prompt": [{"role": "system", "text": "Answer {{topic}}"}]},
|
||||
completion_prompt_config={
|
||||
"prompt": {"text": "{{topic}}"},
|
||||
"conversation_histories_role": {"user_prefix": "Human", "assistant_prefix": "Assistant"},
|
||||
},
|
||||
user_input_form=[
|
||||
{"text-input": {"label": "Topic", "variable": "topic", "required": False, "default": ""}},
|
||||
{"select": {"label": "Style", "variable": "style", "options": ["brief", "detailed"], "required": True}},
|
||||
],
|
||||
dataset_query_variable="topic",
|
||||
dataset_configs={
|
||||
"retrieval_model": "multiple",
|
||||
"top_k": 3,
|
||||
"score_threshold": 0,
|
||||
"score_threshold_enabled": False,
|
||||
"datasets": {"datasets": [{"dataset": {"id": "dataset-1", "enabled": True}}]},
|
||||
"weights": {
|
||||
"vector_setting": {
|
||||
"vector_weight": 0.7,
|
||||
"embedding_provider_name": "provider",
|
||||
"embedding_model_name": "model",
|
||||
},
|
||||
"keyword_setting": {"keyword_weight": 0.3},
|
||||
},
|
||||
},
|
||||
agent_mode={
|
||||
"enabled": True,
|
||||
"strategy": "function_call",
|
||||
"max_iteration": 5,
|
||||
"tools": [
|
||||
{
|
||||
"provider_id": "provider",
|
||||
"provider_type": "builtin",
|
||||
"tool_name": "search",
|
||||
"tool_parameters": {
|
||||
"query": "{{topic}}",
|
||||
"limit": 0,
|
||||
"filters": {"archived": False, "tags": ["docs", None, {"score": 0.5}]},
|
||||
},
|
||||
}
|
||||
],
|
||||
},
|
||||
file_upload={
|
||||
"enabled": True,
|
||||
"number_limits": 3,
|
||||
"allowed_file_types": ["image", "document"],
|
||||
"allowed_file_extensions": [".pdf"],
|
||||
"allowed_file_upload_methods": ["local_file", "remote_url"],
|
||||
"image": {"enabled": True, "number_limits": 3, "transfer_methods": ["remote_url"]},
|
||||
},
|
||||
external_data_tools=[
|
||||
{
|
||||
"enabled": True,
|
||||
"type": "api",
|
||||
"label": "Context",
|
||||
"variable": "context",
|
||||
"config": {"api_based_extension_id": "extension-1", "options": {"limit": 0, "enabled": False}},
|
||||
}
|
||||
],
|
||||
opening_statement="Hello",
|
||||
suggested_questions=["What can you do?"],
|
||||
suggested_questions_after_answer={"enabled": True},
|
||||
more_like_this={"enabled": False},
|
||||
speech_to_text={"enabled": True},
|
||||
text_to_speech={"enabled": True, "voice": "alloy", "language": "en-US"},
|
||||
retriever_resource={"enabled": True},
|
||||
sensitive_word_avoidance={
|
||||
"enabled": True,
|
||||
"type": "keywords",
|
||||
"config": {"keywords": "blocked", "inputs_config": {"enabled": True, "preset_response": ""}},
|
||||
},
|
||||
)
|
||||
|
||||
response = model_config_http.client.post("/apps/app-1/model-config", json=payload)
|
||||
|
||||
assert response.status_code == 200, response.get_json()
|
||||
assert response.get_json() == {"result": "success"}
|
||||
model_config_http.validate_configuration.assert_called_once_with(
|
||||
tenant_id="t1", config=payload, app_mode=AppMode.CHAT, session=model_config_http.session
|
||||
)
|
||||
stored_config = model_config_http.session.get(AppModelConfig, model_config_http.app_model.app_model_config_id)
|
||||
assert stored_config is not None
|
||||
assert stored_config.pre_prompt == "Validated prompt"
|
||||
assert model_config_http.signal.call_args.kwargs["session"] is model_config_http.session
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"optional_fields",
|
||||
[
|
||||
{},
|
||||
{
|
||||
"pre_prompt": "",
|
||||
"opening_statement": "",
|
||||
"suggested_questions": [],
|
||||
"chat_prompt_config": None,
|
||||
"completion_prompt_config": None,
|
||||
"file_upload": None,
|
||||
"dataset_configs": {"score_threshold": 0, "score_threshold_enabled": False},
|
||||
"agent_mode": {"enabled": False, "tools": []},
|
||||
"speech_to_text": {"enabled": False},
|
||||
"text_to_speech": {"enabled": False, "voice": ""},
|
||||
"external_data_tools": [],
|
||||
},
|
||||
],
|
||||
ids=["omitted", "explicit-empty-disabled-and-null"],
|
||||
)
|
||||
def test_post_keeps_optional_values_for_domain_defaults(
|
||||
model_config_http: _ModelConfigHttp, optional_fields: dict[str, object]
|
||||
) -> None:
|
||||
payload = _model_config_payload(**optional_fields)
|
||||
|
||||
response = model_config_http.client.post("/apps/app-1/model-config", json=payload)
|
||||
|
||||
assert response.status_code == 200, response.get_json()
|
||||
assert model_config_http.validate_configuration.call_args.kwargs["config"] == payload
|
||||
|
||||
|
||||
@pytest.mark.parametrize(("case_name", "app_mode", "payload"), _existing_publish_configs())
|
||||
def test_post_preserves_existing_publish_results(
|
||||
model_config_http: _ModelConfigHttp,
|
||||
monkeypatch: pytest.MonkeyPatch,
|
||||
case_name: str,
|
||||
app_mode: AppMode,
|
||||
payload: dict[str, object],
|
||||
) -> None:
|
||||
selected_model = payload["model"]
|
||||
assert isinstance(selected_model, dict)
|
||||
assembly = MagicMock()
|
||||
assembly.model_provider_factory.get_providers.return_value = [
|
||||
SimpleNamespace(provider=str(ModelProviderID(selected_model["provider"])))
|
||||
]
|
||||
assembly.provider_manager.get_configurations.return_value.get_models.return_value = [
|
||||
SimpleNamespace(model=selected_model["name"], model_properties={"mode": selected_model.get("mode", "chat")})
|
||||
]
|
||||
monkeypatch.setattr(model_config_manager_module, "create_plugin_model_assembly", lambda **_kwargs: assembly)
|
||||
monkeypatch.setattr(
|
||||
model_config_module.ToolManager,
|
||||
"get_agent_tool_runtime",
|
||||
MagicMock(side_effect=ValueError("Tool provider is unavailable in this test")),
|
||||
)
|
||||
config_manager = {
|
||||
AppMode.CHAT: ChatAppConfigManager,
|
||||
AppMode.COMPLETION: CompletionAppConfigManager,
|
||||
AppMode.AGENT_CHAT: AgentChatAppConfigManager,
|
||||
}[app_mode]
|
||||
expected_config = config_manager.config_validate("t1", deepcopy(payload), model_config_http.session)
|
||||
expected_record = AppModelConfig(app_id="app-1", created_by="u1", updated_by="u1").from_model_config_dict(
|
||||
expected_config
|
||||
)
|
||||
assert "system_parameters" not in expected_config
|
||||
assert "annotation_reply" not in expected_config
|
||||
model_config_http.app_model.mode = app_mode
|
||||
model_config_http.validate_configuration.return_value = DEFAULT
|
||||
|
||||
response = model_config_http.client.post("/apps/app-1/model-config", json=payload)
|
||||
|
||||
assert response.status_code == 200, (case_name, response.get_json())
|
||||
assert response.get_json() == {"result": "success"}
|
||||
stored_config = model_config_http.session.get(AppModelConfig, model_config_http.app_model.app_model_config_id)
|
||||
assert stored_config is not None
|
||||
assert stored_config.to_dict(annotation_reply={"enabled": False}) == expected_record.to_dict(
|
||||
annotation_reply={"enabled": False}
|
||||
), case_name
|
||||
assert model_config_http.signal.call_args.kwargs["session"] is model_config_http.session
|
||||
|
||||
|
||||
@pytest.mark.parametrize("app_mode", [AppMode.CHAT, AppMode.COMPLETION, AppMode.AGENT_CHAT])
|
||||
@pytest.mark.usefixtures("real_model_config_validation")
|
||||
@pytest.mark.parametrize(
|
||||
("fields", "stored_path", "expected_value"),
|
||||
[
|
||||
(
|
||||
{
|
||||
"chat_prompt_config": {"prompt": [{"text": "Chat", "role": "system"}]},
|
||||
"completion_prompt_config": {"prompt": {"text": "Completion"}},
|
||||
},
|
||||
("completion_prompt_config", "prompt"),
|
||||
{"text": "Completion"},
|
||||
),
|
||||
(
|
||||
{"text_to_speech": {}, "suggested_questions_after_answer": {}},
|
||||
("text_to_speech",),
|
||||
{"enabled": False, "voice": "", "language": ""},
|
||||
),
|
||||
(
|
||||
{
|
||||
"user_input_form": [
|
||||
{
|
||||
"text-input": {
|
||||
"label": "Topic",
|
||||
"variable": "topic",
|
||||
"max_length": None,
|
||||
"json_schema": None,
|
||||
"icon": None,
|
||||
"extension": {"values": [None, False, 0]},
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
("user_input_form",),
|
||||
[
|
||||
{
|
||||
"text-input": {
|
||||
"label": "Topic",
|
||||
"variable": "topic",
|
||||
"max_length": None,
|
||||
"json_schema": None,
|
||||
"icon": None,
|
||||
"required": False,
|
||||
"extension": {"values": [None, False, 0]},
|
||||
}
|
||||
}
|
||||
],
|
||||
),
|
||||
(
|
||||
{"user_input_form": [{"select": {"label": "Topic", "variable": "topic", "options": None}}]},
|
||||
("user_input_form",),
|
||||
[{"select": {"label": "Topic", "variable": "topic", "options": [], "required": False}}],
|
||||
),
|
||||
(
|
||||
{"dataset_configs": {"datasets": {}}},
|
||||
("dataset_configs", "datasets"),
|
||||
{"strategy": "router", "datasets": []},
|
||||
),
|
||||
(
|
||||
{"file_upload": {"image_config": {"enabled": None}}},
|
||||
("file_upload",),
|
||||
{"image_config": {"enabled": None}},
|
||||
),
|
||||
(
|
||||
{
|
||||
"agent_mode": {
|
||||
"strategy": "react",
|
||||
"tools": [
|
||||
{
|
||||
"enabled": None,
|
||||
"provider_type": "builtin",
|
||||
"provider_id": "time",
|
||||
"tool_name": "time",
|
||||
"tool_parameters": {},
|
||||
"credential_id": None,
|
||||
"plugin_unique_identifier": None,
|
||||
}
|
||||
],
|
||||
"prompt": None,
|
||||
}
|
||||
},
|
||||
("agent_mode", "tools"),
|
||||
[
|
||||
{
|
||||
"provider_type": "builtin",
|
||||
"provider_id": "time",
|
||||
"tool_name": "time",
|
||||
"tool_parameters": {},
|
||||
"credential_id": None,
|
||||
"plugin_unique_identifier": None,
|
||||
"enabled": False,
|
||||
}
|
||||
],
|
||||
),
|
||||
],
|
||||
ids=[
|
||||
"completion-prompt-without-role",
|
||||
"omitted-feature-options",
|
||||
"nullable-input-values-and-json-extensions",
|
||||
"select-null-options",
|
||||
"empty-dataset-collection",
|
||||
"image-config-null-extension",
|
||||
"nullable-agent-credentials-and-prompt",
|
||||
],
|
||||
)
|
||||
def test_post_persists_readable_configuration_variants(
|
||||
model_config_http: _ModelConfigHttp,
|
||||
app_mode: AppMode,
|
||||
fields: dict[str, object],
|
||||
stored_path: tuple[str, ...],
|
||||
expected_value: object,
|
||||
) -> None:
|
||||
model_config_http.app_model.mode = app_mode
|
||||
|
||||
response = model_config_http.client.post("/apps/app-1/model-config", json=_model_config_payload(**deepcopy(fields)))
|
||||
|
||||
assert response.status_code == 200, response.get_json()
|
||||
stored_config = model_config_http.session.get(AppModelConfig, model_config_http.app_model.app_model_config_id)
|
||||
assert stored_config is not None
|
||||
wire = stored_config.to_dict(annotation_reply={"enabled": False})
|
||||
AppModelConfigResponse.model_validate(
|
||||
{
|
||||
**wire,
|
||||
"created_by": stored_config.created_by,
|
||||
"created_at": stored_config.created_at,
|
||||
"updated_by": stored_config.updated_by,
|
||||
"updated_at": stored_config.updated_at,
|
||||
}
|
||||
)
|
||||
actual: object = wire
|
||||
for key in stored_path:
|
||||
assert isinstance(actual, dict)
|
||||
actual = actual[key]
|
||||
assert actual == expected_value
|
||||
|
||||
|
||||
@pytest.mark.parametrize("app_mode", [AppMode.CHAT, AppMode.COMPLETION])
|
||||
@pytest.mark.parametrize("strategy", ["router", "react"])
|
||||
@pytest.mark.usefixtures("real_model_config_validation")
|
||||
def test_post_keeps_legacy_tools_readable_across_planning_strategies(
|
||||
model_config_http: _ModelConfigHttp, app_mode: AppMode, strategy: str
|
||||
) -> None:
|
||||
model_config_http.app_model.mode = app_mode
|
||||
tools = [
|
||||
{
|
||||
"extension": {"values": [None, False]},
|
||||
"dataset": {"id": "00000000-0000-0000-0000-000000000001", "enabled": None},
|
||||
},
|
||||
{"google_search": {"enabled": None}},
|
||||
{"web_reader": {}},
|
||||
{"wikipedia": {"enabled": False}},
|
||||
{"current_datetime": {"enabled": True}},
|
||||
{"sensitive-word-avoidance": {"enabled": False, "words": [], "canned_response": ""}},
|
||||
]
|
||||
|
||||
response = model_config_http.client.post(
|
||||
"/apps/app-1/model-config", json=_model_config_payload(agent_mode={"strategy": strategy, "tools": tools})
|
||||
)
|
||||
|
||||
assert response.status_code == 200, response.get_json()
|
||||
stored_config = model_config_http.session.get(AppModelConfig, model_config_http.app_model.app_model_config_id)
|
||||
assert stored_config is not None
|
||||
AppModelConfigResponse.model_validate(
|
||||
{
|
||||
**stored_config.to_dict(annotation_reply={"enabled": False}),
|
||||
"created_by": stored_config.created_by,
|
||||
"created_at": stored_config.created_at,
|
||||
"updated_by": stored_config.updated_by,
|
||||
"updated_at": stored_config.updated_at,
|
||||
}
|
||||
)
|
||||
assert stored_config.agent_mode_dict["tools"] == [
|
||||
{
|
||||
"dataset": {"id": "00000000-0000-0000-0000-000000000001", "enabled": False},
|
||||
"extension": {"values": [None, False]},
|
||||
},
|
||||
{"google_search": {"enabled": False}},
|
||||
{"web_reader": {"enabled": False}},
|
||||
{"wikipedia": {"enabled": False}},
|
||||
{"current_datetime": {"enabled": True}},
|
||||
{"sensitive-word-avoidance": {"enabled": False, "words": [], "canned_response": ""}},
|
||||
]
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"invalid_fields",
|
||||
[
|
||||
{"model": "gpt-4o-mini"},
|
||||
{"model": {"provider": "langgenius/openai/openai", "name": "gpt-4o-mini", "completion_params": []}},
|
||||
{"user_input_form": {"text-input": {"variable": "topic"}}},
|
||||
{"file_upload": []},
|
||||
{"chat_prompt_config": {"prompt": [{"role": "system", "text": {"invalid": "prompt"}}]}},
|
||||
{"completion_prompt_config": {"conversation_histories_role": {"user_prefix": []}}},
|
||||
{"user_input_form": [{"select": {"label": "Style", "variable": "style", "options": {"brief": True}}}]},
|
||||
{"dataset_configs": {"weights": {"vector_setting": {"vector_weight": {"invalid": 0.7}}}}},
|
||||
{
|
||||
"agent_mode": {
|
||||
"tools": [
|
||||
{
|
||||
"provider_id": "provider",
|
||||
"provider_type": "builtin",
|
||||
"tool_name": "search",
|
||||
"tool_parameters": [],
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{"file_upload": {"image": {"transfer_methods": "remote_url"}}},
|
||||
{"speech_to_text": {"enabled": {"invalid": True}}},
|
||||
{"external_data_tools": [{"enabled": True, "type": "api", "config": []}]},
|
||||
{"chat_prompt_config": {"prompt": [{"text": "Missing role"}]}},
|
||||
{"chat_prompt_config": {"prompt": None}},
|
||||
{"completion_prompt_config": {"conversation_histories_role": {"user_prefix": "Human"}}},
|
||||
{"text_to_speech": {"voice": None}},
|
||||
{"suggested_questions_after_answer": {"model": None}},
|
||||
{
|
||||
"suggested_questions_after_answer": {
|
||||
"model": {"provider": "provider", "name": "model", "completion_params": None}
|
||||
}
|
||||
},
|
||||
{"file_upload": {"allowed_file_types": None}},
|
||||
{"user_input_form": [{"text-input": {"label": "Topic", "variable": "topic", "options": None}}]},
|
||||
{"dataset_configs": {"datasets": {"datasets": [{"dataset": {"enabled": None}}]}}},
|
||||
{"file_upload": {"image": {"enabled": None}}},
|
||||
{"dataset_configs": {"datasets": {"strategy": "router"}}},
|
||||
{"dataset_configs": {"weights": {"vector_setting": {"vector_weight": 0.7}}}},
|
||||
{"dataset_configs": {"metadata_filtering_conditions": {"conditions": [{"comparison_operator": "is"}]}}},
|
||||
{"dataset_configs": {"retrieval_model": "unsupported"}},
|
||||
{
|
||||
"dataset_configs": {
|
||||
"metadata_filtering_conditions": {
|
||||
"conditions": [{"name": "topic", "comparison_operator": "unsupported"}]
|
||||
}
|
||||
}
|
||||
},
|
||||
{"suggested_questions_after_answer": {"model": {"provider": "p", "name": "m", "mode": "unsupported"}}},
|
||||
{"agent_mode": {"tools": [{}]}},
|
||||
{"agent_mode": {"tools": [{"enabled": False}]}},
|
||||
{"agent_mode": {"tools": [{"provider_type": "builtin", "provider_id": "time", "tool_name": "time"}]}},
|
||||
{"agent_mode": {"tools": [{"dataset": None}]}},
|
||||
],
|
||||
ids=[
|
||||
"model-string",
|
||||
"completion-params-list",
|
||||
"form-object",
|
||||
"file-upload-list",
|
||||
"chat-prompt-text-object",
|
||||
"completion-prefix-list",
|
||||
"form-options-object",
|
||||
"dataset-weight-object",
|
||||
"agent-tool-parameters-list",
|
||||
"image-transfer-methods-string",
|
||||
"feature-enabled-object",
|
||||
"external-tool-config-list",
|
||||
"chat-prompt-role-missing",
|
||||
"chat-prompt-null",
|
||||
"completion-assistant-prefix-missing",
|
||||
"text-to-speech-voice-null",
|
||||
"suggested-model-null",
|
||||
"suggested-completion-params-null",
|
||||
"allowed-file-types-null",
|
||||
"text-input-options-null",
|
||||
"modern-dataset-enabled-null",
|
||||
"legacy-image-enabled-null",
|
||||
"dataset-list-missing",
|
||||
"retrieval-weights-incomplete",
|
||||
"metadata-condition-name-missing",
|
||||
"retrieval-mode-unsupported",
|
||||
"metadata-comparison-unsupported",
|
||||
"suggested-model-mode-unsupported",
|
||||
"empty-agent-tool",
|
||||
"agent-tool-only-enabled",
|
||||
"provider-tool-parameters-missing",
|
||||
"legacy-dataset-null",
|
||||
],
|
||||
)
|
||||
def test_post_rejects_invalid_wire_before_business_validation(
|
||||
model_config_http: _ModelConfigHttp, invalid_fields: dict[str, object]
|
||||
) -> None:
|
||||
response = model_config_http.client.post("/apps/app-1/model-config", json=_model_config_payload(**invalid_fields))
|
||||
|
||||
assert response.status_code == 400, response.get_json()
|
||||
assert response.get_json()["code"] == "invalid_param"
|
||||
model_config_http.validate_configuration.assert_not_called()
|
||||
model_config_http.signal.assert_not_called()
|
||||
assert model_config_http.app_model.app_model_config_id == "config-0"
|
||||
assert model_config_http.session.scalar(select(func.count()).select_from(AppModelConfig)) == 1
|
||||
|
||||
|
||||
def test_post_keeps_business_validation_as_the_configuration_policy_owner(model_config_http: _ModelConfigHttp) -> None:
|
||||
model_config_http.validate_configuration.side_effect = ValueError("model.name must be in the specified model list")
|
||||
|
||||
response = model_config_http.client.post("/apps/app-1/model-config", json=_model_config_payload())
|
||||
|
||||
assert response.status_code == 400, response.get_json()
|
||||
assert response.get_json()["message"] == "model.name must be in the specified model list"
|
||||
model_config_http.signal.assert_not_called()
|
||||
assert model_config_http.app_model.app_model_config_id == "config-0"
|
||||
assert model_config_http.session.scalar(select(func.count()).select_from(AppModelConfig)) == 1
|
||||
|
||||
|
||||
def _assert_no_implicit_app_config_properties() -> None:
|
||||
# `App.is_agent` and `App.app_model_config` used to be poisoned here with a
|
||||
# raising property. Neither exists as an implicit accessor any more, so their
|
||||
@@ -69,7 +702,9 @@ def test_post_updates_non_agent_model_config_without_implicit_properties(
|
||||
send_mock = MagicMock()
|
||||
monkeypatch.setattr(model_config_module.app_model_config_was_updated, "send", send_mock)
|
||||
|
||||
with app.test_request_context("/console/api/apps/app-1/model-config", method="POST", json={"pre_prompt": "hi"}):
|
||||
with app.test_request_context(
|
||||
"/console/api/apps/app-1/model-config", method="POST", json=_model_config_payload(pre_prompt="hi")
|
||||
):
|
||||
response = method(api, sqlite_session, "t1", "u1", app_model=app_model)
|
||||
|
||||
assert send_mock.call_args.kwargs["session"] is sqlite_session
|
||||
@@ -150,7 +785,9 @@ def test_post_uses_one_session_and_rolls_back_when_signal_fails(
|
||||
|
||||
api = model_config_module.ModelConfigResource()
|
||||
with (
|
||||
app.test_request_context(f"/console/api/apps/{app_id}/model-config", method="POST", json={}),
|
||||
app.test_request_context(
|
||||
f"/console/api/apps/{app_id}/model-config", method="POST", json=_model_config_payload()
|
||||
),
|
||||
pytest.raises(RuntimeError, match="signal failed"),
|
||||
):
|
||||
method(
|
||||
@@ -248,7 +885,9 @@ def test_post_encrypts_agent_tool_parameters(
|
||||
send_mock = MagicMock()
|
||||
monkeypatch.setattr(model_config_module.app_model_config_was_updated, "send", send_mock)
|
||||
|
||||
with app.test_request_context("/console/api/apps/app-1/model-config", method="POST", json={"pre_prompt": "hi"}):
|
||||
with app.test_request_context(
|
||||
"/console/api/apps/app-1/model-config", method="POST", json=_model_config_payload(pre_prompt="hi")
|
||||
):
|
||||
response = method(api, sqlite_session, "t1", "u1", app_model=app_model)
|
||||
|
||||
stored_config = sqlite_session.get(AppModelConfig, app_model.app_model_config_id)
|
||||
|
||||
@@ -0,0 +1,170 @@
|
||||
import type { InferContractRouterInputs } from '@orpc/contract'
|
||||
import type { z } from 'zod'
|
||||
import type { apps } from './generated/api/console/apps/orpc.gen.ts'
|
||||
import type { AppModelConfigPayload } from './generated/api/console/apps/types.gen.ts'
|
||||
import { describe, expect, it } from 'vite-plus/test'
|
||||
import {
|
||||
zAppConfigJsonValueWritable,
|
||||
zAppModelConfigPayload,
|
||||
} from './generated/api/console/apps/zod.gen.ts'
|
||||
|
||||
const model = {
|
||||
provider: 'langgenius/openai/openai',
|
||||
name: 'gpt-4o-mini',
|
||||
completion_params: {
|
||||
temperature: 0,
|
||||
stop: [],
|
||||
provider_options: { cache: false, fallback: null },
|
||||
},
|
||||
} satisfies AppModelConfigPayload['model']
|
||||
|
||||
describe('generated app model-config write contract', () => {
|
||||
it('keeps recursive JSON strict in the generated writable schema', () => {
|
||||
const value = { nested: [null, false, { count: 2 }] }
|
||||
expect(zAppConfigJsonValueWritable.parse(value)).toEqual(value)
|
||||
|
||||
// @ts-expect-error The derived writable schema must reject non-JSON values at any depth.
|
||||
const invalid: z.infer<typeof zAppConfigJsonValueWritable> = {
|
||||
nested: { callback: () => true },
|
||||
}
|
||||
expect(zAppConfigJsonValueWritable.safeParse(invalid).success).toBe(false)
|
||||
})
|
||||
|
||||
it('preserves dynamic JSON parameters without synthesizing omitted configuration', () => {
|
||||
const body = {
|
||||
model: { ...model, provider_metadata: { cached: false } },
|
||||
speech_to_text: { enabled: false, extension: { locale: 'en' } },
|
||||
} satisfies AppModelConfigPayload
|
||||
|
||||
expect(zAppModelConfigPayload.parse(body)).toEqual(body)
|
||||
})
|
||||
|
||||
it('requires one supported form field per input item', () => {
|
||||
const field = { label: 'Topic', variable: 'topic' }
|
||||
for (const item of [{}, { 'text-input': field, select: field }]) {
|
||||
expect(zAppModelConfigPayload.safeParse({ model, user_input_form: [item] }).success).toBe(
|
||||
false,
|
||||
)
|
||||
}
|
||||
})
|
||||
|
||||
it('preserves omitted and nullable values according to their configuration variant', () => {
|
||||
const body = {
|
||||
model,
|
||||
completion_prompt_config: { prompt: { text: 'Completion without a role' } },
|
||||
text_to_speech: {},
|
||||
dataset_configs: { datasets: {} },
|
||||
agent_mode: { tools: [{ dataset: { enabled: null } }] },
|
||||
file_upload: { image_config: { enabled: null } },
|
||||
user_input_form: [
|
||||
{
|
||||
'text-input': {
|
||||
label: 'Topic',
|
||||
variable: 'topic',
|
||||
max_length: null,
|
||||
json_schema: null,
|
||||
extension: { values: [false, null, 0] },
|
||||
},
|
||||
},
|
||||
{ select: { label: 'Choice', variable: 'choice', options: null } },
|
||||
],
|
||||
} satisfies AppModelConfigPayload
|
||||
|
||||
expect(zAppModelConfigPayload.parse(body)).toEqual(body)
|
||||
})
|
||||
|
||||
it('rejects structures that cannot be persisted as readable configuration', () => {
|
||||
const invalidVoice: AppModelConfigPayload = {
|
||||
model,
|
||||
// @ts-expect-error Omission preserves the domain default; an explicit null is invalid.
|
||||
text_to_speech: { voice: null },
|
||||
}
|
||||
const missingRole: AppModelConfigPayload = {
|
||||
model,
|
||||
// @ts-expect-error A chat message requires its role, unlike a completion prompt.
|
||||
chat_prompt_config: { prompt: [{ text: 'Missing role' }] },
|
||||
}
|
||||
const invalidClientVoice: InferContractRouterInputs<
|
||||
typeof apps
|
||||
>['byAppId']['modelConfig']['post'] = {
|
||||
params: { app_id: 'app-1' },
|
||||
body: {
|
||||
model,
|
||||
// @ts-expect-error The Zod-derived client input also distinguishes omitted from null.
|
||||
text_to_speech: { voice: null },
|
||||
},
|
||||
}
|
||||
for (const invalidBody of [
|
||||
invalidVoice,
|
||||
missingRole,
|
||||
invalidClientVoice.body,
|
||||
{ model, dataset_configs: { datasets: { strategy: 'router' } } },
|
||||
{ model, dataset_configs: { datasets: { datasets: [{ dataset: { enabled: null } }] } } },
|
||||
{ model, dataset_configs: { retrieval_model: 'unsupported' } },
|
||||
{ model, file_upload: { image: { enabled: null } } },
|
||||
{
|
||||
model,
|
||||
user_input_form: [{ 'text-input': { label: 'Topic', variable: 'topic', options: null } }],
|
||||
},
|
||||
]) {
|
||||
expect(zAppModelConfigPayload.safeParse(invalidBody).success).toBe(false)
|
||||
}
|
||||
})
|
||||
|
||||
it('types and validates the fixed configuration fields', () => {
|
||||
const body = {
|
||||
model,
|
||||
file_upload: { enabled: false, number_limits: 3 },
|
||||
dataset_configs: { retrieval_model: 'multiple', top_k: 4 },
|
||||
chat_prompt_config: { prompt: [{ role: 'system', text: 'Answer {{topic}}' }] },
|
||||
user_input_form: [{ 'text-input': { label: 'Topic', variable: 'topic', required: false } }],
|
||||
} satisfies AppModelConfigPayload
|
||||
|
||||
expect(zAppModelConfigPayload.parse(body)).toEqual(body)
|
||||
|
||||
const invalidUpload: AppModelConfigPayload = {
|
||||
model,
|
||||
// @ts-expect-error Upload enablement is a boolean in the generated write contract.
|
||||
file_upload: { enabled: 'false' },
|
||||
}
|
||||
const invalidDataset: AppModelConfigPayload = {
|
||||
model,
|
||||
// @ts-expect-error The retrieval limit is numeric in the generated write contract.
|
||||
dataset_configs: { top_k: '4' },
|
||||
}
|
||||
const invalidPrompt: AppModelConfigPayload = {
|
||||
model,
|
||||
// @ts-expect-error Prompt text is a string in the generated write contract.
|
||||
chat_prompt_config: { prompt: [{ role: 'system', text: 1 }] },
|
||||
}
|
||||
const invalidParameters: AppModelConfigPayload = {
|
||||
model: {
|
||||
...model,
|
||||
// @ts-expect-error Provider parameters remain JSON values, not arbitrary JavaScript values.
|
||||
completion_params: { callback: () => 'not JSON' },
|
||||
},
|
||||
}
|
||||
const invalidClientParameters: InferContractRouterInputs<
|
||||
typeof apps
|
||||
>['byAppId']['modelConfig']['post'] = {
|
||||
params: { app_id: 'app-1' },
|
||||
body: {
|
||||
model: {
|
||||
...model,
|
||||
// @ts-expect-error Recursive JSON stays typed in the Zod-backed client input too.
|
||||
completion_params: { nested: { callback: () => 'not JSON' } },
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for (const invalidBody of [
|
||||
invalidUpload,
|
||||
invalidDataset,
|
||||
invalidPrompt,
|
||||
invalidParameters,
|
||||
invalidClientParameters.body,
|
||||
]) {
|
||||
expect(zAppModelConfigPayload.safeParse(invalidBody).success).toBe(false)
|
||||
}
|
||||
})
|
||||
})
|
||||
@@ -537,35 +537,26 @@ export type MessageDetailResponse = {
|
||||
workflow_run_id?: string | null
|
||||
}
|
||||
|
||||
export type ModelConfigRequest = {
|
||||
agent_mode?: {
|
||||
[key: string]: unknown
|
||||
} | null
|
||||
configs?: {
|
||||
[key: string]: unknown
|
||||
} | null
|
||||
dataset_configs?: {
|
||||
[key: string]: unknown
|
||||
} | null
|
||||
model?: string | null
|
||||
more_like_this?: {
|
||||
[key: string]: unknown
|
||||
} | null
|
||||
export type AppModelConfigPayload = {
|
||||
agent_mode?: AppAgentModePayload | null
|
||||
chat_prompt_config?: AppChatPromptPayload | null
|
||||
completion_prompt_config?: AppCompletionPromptPayload | null
|
||||
dataset_configs?: AppDatasetConfigPayload | null
|
||||
dataset_query_variable?: string | null
|
||||
external_data_tools?: Array<AppExternalDataToolPayload> | null
|
||||
file_upload?: AppFileUploadPayload | null
|
||||
model: AppModelSelectionPayload
|
||||
more_like_this?: AppFeaturePayload | null
|
||||
opening_statement?: string | null
|
||||
provider?: string | null
|
||||
retrieval_model?: {
|
||||
[key: string]: unknown
|
||||
} | null
|
||||
speech_to_text?: {
|
||||
[key: string]: unknown
|
||||
} | null
|
||||
pre_prompt?: string | null
|
||||
prompt_type?: '' | 'advanced' | 'simple' | null
|
||||
retriever_resource?: AppFeaturePayload | null
|
||||
sensitive_word_avoidance?: AppModerationPayload | null
|
||||
speech_to_text?: AppFeaturePayload | null
|
||||
suggested_questions?: Array<string> | null
|
||||
text_to_speech?: {
|
||||
[key: string]: unknown
|
||||
} | null
|
||||
tools?: Array<{
|
||||
[key: string]: unknown
|
||||
}> | null
|
||||
suggested_questions_after_answer?: AppSuggestedQuestionsPayload | null
|
||||
text_to_speech?: AppTextToSpeechPayload | null
|
||||
user_input_form?: Array<AppUserInputFormPayload> | null
|
||||
}
|
||||
|
||||
export type AppNamePayload = {
|
||||
@@ -1620,6 +1611,200 @@ export type MessageFile = {
|
||||
url?: string | null
|
||||
}
|
||||
|
||||
export type AppAgentModePayload = {
|
||||
enabled?: boolean | null
|
||||
max_iteration?: number
|
||||
prompt?: AppAgentPromptPayload | string | null
|
||||
strategy?: PlanningStrategy | '' | 'cot' | 'function-calling' | null
|
||||
tools?: Array<AppAgentToolPayload> | null
|
||||
[key: string]:
|
||||
| AppConfigJsonValue
|
||||
| boolean
|
||||
| null
|
||||
| number
|
||||
| AppAgentPromptPayload
|
||||
| string
|
||||
| null
|
||||
| PlanningStrategy
|
||||
| ''
|
||||
| 'cot'
|
||||
| 'function-calling'
|
||||
| null
|
||||
| Array<AppAgentToolPayload>
|
||||
| null
|
||||
| undefined
|
||||
}
|
||||
|
||||
export type AppChatPromptPayload = {
|
||||
prompt?: Array<AppPromptMessagePayload>
|
||||
[key: string]: AppConfigJsonValue | Array<AppPromptMessagePayload> | undefined
|
||||
}
|
||||
|
||||
export type AppCompletionPromptPayload = {
|
||||
conversation_histories_role?: AppConversationRolesPayload
|
||||
prompt?: AppCompletionPromptTextPayload
|
||||
[key: string]:
|
||||
| AppConfigJsonValue
|
||||
| AppConversationRolesPayload
|
||||
| AppCompletionPromptTextPayload
|
||||
| undefined
|
||||
}
|
||||
|
||||
export type AppDatasetConfigPayload = {
|
||||
datasets?: AppDatasetCollectionPayload | AppEmptyDatasetCollectionPayload | null
|
||||
metadata_filtering_conditions?: AppMetadataFilteringPayload | null
|
||||
metadata_filtering_mode?: 'automatic' | 'disabled' | 'manual'
|
||||
metadata_model_config?: AppMetadataModelPayload | null
|
||||
reranking_enable?: boolean
|
||||
reranking_enabled?: boolean
|
||||
reranking_mode?: RerankMode
|
||||
reranking_model?: AppRerankingModelPayload | null
|
||||
retrieval_model?: 'multiple' | 'single'
|
||||
score_threshold?: number | null
|
||||
score_threshold_enabled?: boolean
|
||||
top_k?: number
|
||||
weights?: AppRetrievalWeightsPayload | null
|
||||
[key: string]:
|
||||
| AppConfigJsonValue
|
||||
| AppDatasetCollectionPayload
|
||||
| AppEmptyDatasetCollectionPayload
|
||||
| null
|
||||
| AppMetadataFilteringPayload
|
||||
| null
|
||||
| 'automatic'
|
||||
| 'disabled'
|
||||
| 'manual'
|
||||
| AppMetadataModelPayload
|
||||
| null
|
||||
| boolean
|
||||
| RerankMode
|
||||
| AppRerankingModelPayload
|
||||
| null
|
||||
| 'multiple'
|
||||
| 'single'
|
||||
| number
|
||||
| null
|
||||
| number
|
||||
| AppRetrievalWeightsPayload
|
||||
| null
|
||||
| undefined
|
||||
}
|
||||
|
||||
export type AppExternalDataToolPayload = {
|
||||
config?: {
|
||||
[key: string]: AppConfigJsonValue
|
||||
}
|
||||
enabled?: boolean | null
|
||||
icon?: string
|
||||
icon_background?: string
|
||||
label?: string
|
||||
type?: string
|
||||
variable?: string
|
||||
[key: string]:
|
||||
| AppConfigJsonValue
|
||||
| {
|
||||
[key: string]: AppConfigJsonValue
|
||||
}
|
||||
| boolean
|
||||
| null
|
||||
| string
|
||||
| undefined
|
||||
}
|
||||
|
||||
export type AppFileUploadPayload = {
|
||||
allowed_file_extensions?: Array<string>
|
||||
allowed_file_types?: Array<FileType>
|
||||
allowed_file_upload_methods?: Array<FileTransferMethod>
|
||||
audio?: AppFileTypeUploadPayload | null
|
||||
custom?: AppFileTypeUploadPayload | null
|
||||
document?: AppFileTypeUploadPayload | null
|
||||
enabled?: boolean
|
||||
image?: AppImageUploadPayload
|
||||
image_config?: AppImageConfigPayload | null
|
||||
number_limits?: number
|
||||
preview_config?: AppFilePreviewPayload | null
|
||||
video?: AppFileTypeUploadPayload | null
|
||||
[key: string]:
|
||||
| AppConfigJsonValue
|
||||
| Array<string>
|
||||
| Array<FileType>
|
||||
| Array<FileTransferMethod>
|
||||
| AppFileTypeUploadPayload
|
||||
| null
|
||||
| AppFileTypeUploadPayload
|
||||
| null
|
||||
| AppFileTypeUploadPayload
|
||||
| null
|
||||
| boolean
|
||||
| AppImageUploadPayload
|
||||
| AppImageConfigPayload
|
||||
| null
|
||||
| number
|
||||
| AppFilePreviewPayload
|
||||
| null
|
||||
| AppFileTypeUploadPayload
|
||||
| null
|
||||
| undefined
|
||||
}
|
||||
|
||||
export type AppModelSelectionPayload = {
|
||||
completion_params: {
|
||||
[key: string]: AppConfigJsonValue
|
||||
}
|
||||
mode?: string | null
|
||||
name: string
|
||||
provider: string
|
||||
[key: string]:
|
||||
| AppConfigJsonValue
|
||||
| {
|
||||
[key: string]: AppConfigJsonValue
|
||||
}
|
||||
| string
|
||||
| null
|
||||
| string
|
||||
| undefined
|
||||
}
|
||||
|
||||
export type AppFeaturePayload = {
|
||||
enabled?: boolean | null
|
||||
[key: string]: AppConfigJsonValue | boolean | null | undefined
|
||||
}
|
||||
|
||||
export type AppModerationPayload = {
|
||||
config?: AppModerationConfigPayload | null
|
||||
enabled?: boolean | null
|
||||
type?: string | null
|
||||
}
|
||||
|
||||
export type AppSuggestedQuestionsPayload = {
|
||||
enabled?: boolean | null
|
||||
model?: AppSuggestedQuestionsModelPayload
|
||||
prompt?: string
|
||||
[key: string]:
|
||||
| AppConfigJsonValue
|
||||
| boolean
|
||||
| null
|
||||
| AppSuggestedQuestionsModelPayload
|
||||
| string
|
||||
| undefined
|
||||
}
|
||||
|
||||
export type AppTextToSpeechPayload = {
|
||||
autoPlay?: 'disabled' | 'enabled'
|
||||
enabled?: boolean | null
|
||||
language?: string
|
||||
voice?: string
|
||||
[key: string]: AppConfigJsonValue | 'disabled' | 'enabled' | boolean | null | string | undefined
|
||||
}
|
||||
|
||||
export type AppUserInputFormPayload =
|
||||
| AppTextInputPayload
|
||||
| AppSelectInputPayload
|
||||
| AppParagraphInputPayload
|
||||
| AppNumberInputPayload
|
||||
| AppCheckboxInputPayload
|
||||
| AppExternalDataInputPayload
|
||||
|
||||
export type AppMcpServerStatus = 'active' | 'inactive' | 'normal'
|
||||
|
||||
export type AverageResponseTimeStatisticItem = {
|
||||
@@ -2378,6 +2563,229 @@ export type HumanInputFormSubmissionData = {
|
||||
|
||||
export type ExecutionContentType = 'human_input'
|
||||
|
||||
export type AppConfigJsonValue =
|
||||
| string
|
||||
| number
|
||||
| number
|
||||
| boolean
|
||||
| Array<AppConfigJsonValue>
|
||||
| {
|
||||
[key: string]: AppConfigJsonValue
|
||||
}
|
||||
| null
|
||||
|
||||
export type AppAgentPromptPayload = {
|
||||
first_prompt?: string
|
||||
next_iteration?: string
|
||||
[key: string]: AppConfigJsonValue | string | undefined
|
||||
}
|
||||
|
||||
export type PlanningStrategy = 'function_call' | 'react' | 'react_router' | 'router'
|
||||
|
||||
export type AppAgentToolPayload =
|
||||
| AppProviderAgentToolPayload
|
||||
| AppLegacyDatasetToolPayload
|
||||
| AppLegacyGoogleSearchToolPayload
|
||||
| AppLegacyWebReaderToolPayload
|
||||
| AppLegacyWikipediaToolPayload
|
||||
| AppLegacyCurrentDatetimeToolPayload
|
||||
| AppLegacySensitiveWordToolPayload
|
||||
|
||||
export type AppPromptMessagePayload = {
|
||||
role: string
|
||||
text: string
|
||||
[key: string]: AppConfigJsonValue | string
|
||||
}
|
||||
|
||||
export type AppConversationRolesPayload = {
|
||||
assistant_prefix: string
|
||||
user_prefix: string
|
||||
[key: string]: AppConfigJsonValue | string
|
||||
}
|
||||
|
||||
export type AppCompletionPromptTextPayload = {
|
||||
text: string
|
||||
[key: string]: AppConfigJsonValue | string
|
||||
}
|
||||
|
||||
export type AppDatasetCollectionPayload = {
|
||||
datasets: Array<AppDatasetToolPayload>
|
||||
strategy?: string
|
||||
[key: string]: AppConfigJsonValue | Array<AppDatasetToolPayload> | string | undefined
|
||||
}
|
||||
|
||||
export type AppEmptyDatasetCollectionPayload = {
|
||||
[key: string]: never
|
||||
}
|
||||
|
||||
export type AppMetadataFilteringPayload = {
|
||||
conditions?: Array<AppMetadataConditionPayload> | null
|
||||
logical_operator?: 'and' | 'or' | null
|
||||
[key: string]:
|
||||
| AppConfigJsonValue
|
||||
| Array<AppMetadataConditionPayload>
|
||||
| null
|
||||
| 'and'
|
||||
| 'or'
|
||||
| null
|
||||
| undefined
|
||||
}
|
||||
|
||||
export type AppMetadataModelPayload = {
|
||||
completion_params?: {
|
||||
[key: string]: AppConfigJsonValue
|
||||
}
|
||||
mode?: LlmMode | ''
|
||||
name?: string
|
||||
provider?: string
|
||||
[key: string]:
|
||||
| AppConfigJsonValue
|
||||
| {
|
||||
[key: string]: AppConfigJsonValue
|
||||
}
|
||||
| LlmMode
|
||||
| ''
|
||||
| string
|
||||
| undefined
|
||||
}
|
||||
|
||||
export type RerankMode = 'reranking_model' | 'weighted_score'
|
||||
|
||||
export type AppRerankingModelPayload = {
|
||||
reranking_model_name?: string
|
||||
reranking_provider_name?: string
|
||||
[key: string]: AppConfigJsonValue | string | undefined
|
||||
}
|
||||
|
||||
export type AppRetrievalWeightsPayload = {
|
||||
keyword_setting: AppKeywordWeightPayload
|
||||
vector_setting: AppVectorWeightPayload
|
||||
weight_type?: 'customized' | 'keyword_first' | 'semantic_first'
|
||||
[key: string]:
|
||||
| AppConfigJsonValue
|
||||
| AppKeywordWeightPayload
|
||||
| AppVectorWeightPayload
|
||||
| 'customized'
|
||||
| 'keyword_first'
|
||||
| 'semantic_first'
|
||||
| undefined
|
||||
}
|
||||
|
||||
export type FileType = 'audio' | 'custom' | 'document' | 'image' | 'video'
|
||||
|
||||
export type FileTransferMethod = 'datasource_file' | 'local_file' | 'remote_url' | 'tool_file'
|
||||
|
||||
export type AppFileTypeUploadPayload = {
|
||||
enabled?: boolean | null
|
||||
number_limits?: number | null
|
||||
transfer_methods?: Array<FileTransferMethod> | null
|
||||
[key: string]:
|
||||
| AppConfigJsonValue
|
||||
| boolean
|
||||
| null
|
||||
| number
|
||||
| null
|
||||
| Array<FileTransferMethod>
|
||||
| null
|
||||
| undefined
|
||||
}
|
||||
|
||||
export type AppImageUploadPayload = {
|
||||
detail?: 'high' | 'low' | null
|
||||
enabled?: boolean
|
||||
number_limits?: number
|
||||
transfer_methods?: Array<FileTransferMethod>
|
||||
[key: string]:
|
||||
| AppConfigJsonValue
|
||||
| 'high'
|
||||
| 'low'
|
||||
| null
|
||||
| boolean
|
||||
| number
|
||||
| Array<FileTransferMethod>
|
||||
| undefined
|
||||
}
|
||||
|
||||
export type AppImageConfigPayload = {
|
||||
detail?: 'high' | 'low' | null
|
||||
number_limits?: number
|
||||
transfer_methods?: Array<FileTransferMethod>
|
||||
[key: string]:
|
||||
| AppConfigJsonValue
|
||||
| 'high'
|
||||
| 'low'
|
||||
| null
|
||||
| number
|
||||
| Array<FileTransferMethod>
|
||||
| undefined
|
||||
}
|
||||
|
||||
export type AppFilePreviewPayload = {
|
||||
file_type_list?: Array<string> | null
|
||||
mode?: string | null
|
||||
[key: string]: AppConfigJsonValue | Array<string> | null | string | null | undefined
|
||||
}
|
||||
|
||||
export type AppModerationConfigPayload = {
|
||||
api_based_extension_id?: string | null
|
||||
inputs_config?: AppModerationContentPayload | null
|
||||
keywords?: string | null
|
||||
outputs_config?: AppModerationContentPayload | null
|
||||
[key: string]:
|
||||
| AppConfigJsonValue
|
||||
| string
|
||||
| null
|
||||
| AppModerationContentPayload
|
||||
| null
|
||||
| string
|
||||
| null
|
||||
| AppModerationContentPayload
|
||||
| null
|
||||
| undefined
|
||||
}
|
||||
|
||||
export type AppSuggestedQuestionsModelPayload = {
|
||||
completion_params?: {
|
||||
[key: string]: AppConfigJsonValue
|
||||
}
|
||||
mode?: LlmMode | ''
|
||||
name: string
|
||||
provider: string
|
||||
[key: string]:
|
||||
| AppConfigJsonValue
|
||||
| {
|
||||
[key: string]: AppConfigJsonValue
|
||||
}
|
||||
| LlmMode
|
||||
| ''
|
||||
| string
|
||||
| undefined
|
||||
}
|
||||
|
||||
export type AppTextInputPayload = {
|
||||
'text-input': AppInputFieldPayload
|
||||
}
|
||||
|
||||
export type AppSelectInputPayload = {
|
||||
select: AppSelectFieldPayload
|
||||
}
|
||||
|
||||
export type AppParagraphInputPayload = {
|
||||
paragraph: AppInputFieldPayload
|
||||
}
|
||||
|
||||
export type AppNumberInputPayload = {
|
||||
number: AppInputFieldPayload
|
||||
}
|
||||
|
||||
export type AppCheckboxInputPayload = {
|
||||
checkbox: AppInputFieldPayload
|
||||
}
|
||||
|
||||
export type AppExternalDataInputPayload = {
|
||||
external_data_tool: AppInputFieldPayload
|
||||
}
|
||||
|
||||
export type WorkflowRunForLogResponse = {
|
||||
created_at?: number | null
|
||||
elapsed_time?: number | null
|
||||
@@ -2674,8 +3082,6 @@ export type AppAgentPromptResponse = {
|
||||
[key: string]: unknown
|
||||
}
|
||||
|
||||
export type PlanningStrategy = 'function_call' | 'react' | 'react_router' | 'router'
|
||||
|
||||
export type AppProviderAgentToolResponse = {
|
||||
credential_id?: string | null
|
||||
enabled?: boolean
|
||||
@@ -2762,8 +3168,6 @@ export type AppMetadataFilteringConditionsResponse = {
|
||||
[key: string]: unknown
|
||||
}
|
||||
|
||||
export type RerankMode = 'reranking_model' | 'weighted_score'
|
||||
|
||||
export type AppRerankingModelResponse = {
|
||||
reranking_model_name?: string
|
||||
reranking_provider_name?: string
|
||||
@@ -2779,10 +3183,6 @@ export type AppWeightsResponse = {
|
||||
|
||||
export type JsonValue2 = unknown
|
||||
|
||||
export type FileType = 'audio' | 'custom' | 'document' | 'image' | 'video'
|
||||
|
||||
export type FileTransferMethod = 'datasource_file' | 'local_file' | 'remote_url' | 'tool_file'
|
||||
|
||||
export type AppImageUploadResponse = {
|
||||
detail?: 'high' | 'low' | null
|
||||
enabled?: boolean
|
||||
@@ -2838,6 +3238,236 @@ export type FormInputConfig =
|
||||
type: 'file-list'
|
||||
} & FileListInputConfig)
|
||||
|
||||
export type AppProviderAgentToolPayload = {
|
||||
credential_id?: string | null
|
||||
enabled?: boolean | null
|
||||
isDeleted?: boolean
|
||||
notAuthor?: boolean
|
||||
plugin_unique_identifier?: string | null
|
||||
provider_id: string
|
||||
provider_name?: string
|
||||
provider_type: ToolProviderType
|
||||
tool_label?: string
|
||||
tool_name: string
|
||||
tool_parameters: {
|
||||
[key: string]: AppConfigJsonValue
|
||||
}
|
||||
[key: string]:
|
||||
| AppConfigJsonValue
|
||||
| string
|
||||
| null
|
||||
| boolean
|
||||
| null
|
||||
| boolean
|
||||
| string
|
||||
| null
|
||||
| string
|
||||
| ToolProviderType
|
||||
| {
|
||||
[key: string]: AppConfigJsonValue
|
||||
}
|
||||
| undefined
|
||||
}
|
||||
|
||||
export type AppLegacyDatasetToolPayload = {
|
||||
dataset: AppLegacyDatasetSelectionPayload
|
||||
[key: string]: AppConfigJsonValue | AppLegacyDatasetSelectionPayload
|
||||
}
|
||||
|
||||
export type AppLegacyGoogleSearchToolPayload = {
|
||||
google_search: AppFeaturePayload
|
||||
[key: string]: AppConfigJsonValue | AppFeaturePayload
|
||||
}
|
||||
|
||||
export type AppLegacyWebReaderToolPayload = {
|
||||
web_reader: AppFeaturePayload
|
||||
[key: string]: AppConfigJsonValue | AppFeaturePayload
|
||||
}
|
||||
|
||||
export type AppLegacyWikipediaToolPayload = {
|
||||
wikipedia: AppFeaturePayload
|
||||
[key: string]: AppConfigJsonValue | AppFeaturePayload
|
||||
}
|
||||
|
||||
export type AppLegacyCurrentDatetimeToolPayload = {
|
||||
current_datetime: AppFeaturePayload
|
||||
[key: string]: AppConfigJsonValue | AppFeaturePayload
|
||||
}
|
||||
|
||||
export type AppLegacySensitiveWordToolPayload = {
|
||||
'sensitive-word-avoidance': AppLegacySensitiveWordConfigPayload
|
||||
[key: string]: AppConfigJsonValue | AppLegacySensitiveWordConfigPayload
|
||||
}
|
||||
|
||||
export type AppDatasetToolPayload = {
|
||||
dataset: AppDatasetSelectionPayload
|
||||
[key: string]: AppConfigJsonValue | AppDatasetSelectionPayload
|
||||
}
|
||||
|
||||
export type AppMetadataConditionPayload = {
|
||||
comparison_operator:
|
||||
| '<'
|
||||
| '='
|
||||
| '>'
|
||||
| 'after'
|
||||
| 'before'
|
||||
| 'contains'
|
||||
| 'empty'
|
||||
| 'end with'
|
||||
| 'in'
|
||||
| 'is'
|
||||
| 'is not'
|
||||
| 'not contains'
|
||||
| 'not empty'
|
||||
| 'not in'
|
||||
| 'start with'
|
||||
| '≠'
|
||||
| '≤'
|
||||
| '≥'
|
||||
id?: string
|
||||
metadata_id?: string
|
||||
name: string
|
||||
value?: string | Array<string> | number | number | null
|
||||
[key: string]:
|
||||
| AppConfigJsonValue
|
||||
| '<'
|
||||
| '='
|
||||
| '>'
|
||||
| 'after'
|
||||
| 'before'
|
||||
| 'contains'
|
||||
| 'empty'
|
||||
| 'end with'
|
||||
| 'in'
|
||||
| 'is'
|
||||
| 'is not'
|
||||
| 'not contains'
|
||||
| 'not empty'
|
||||
| 'not in'
|
||||
| 'start with'
|
||||
| '≠'
|
||||
| '≤'
|
||||
| '≥'
|
||||
| string
|
||||
| string
|
||||
| Array<string>
|
||||
| number
|
||||
| number
|
||||
| null
|
||||
| undefined
|
||||
}
|
||||
|
||||
export type AppKeywordWeightPayload = {
|
||||
keyword_weight: number
|
||||
[key: string]: AppConfigJsonValue | number
|
||||
}
|
||||
|
||||
export type AppVectorWeightPayload = {
|
||||
embedding_model_name: string
|
||||
embedding_provider_name: string
|
||||
vector_weight: number
|
||||
[key: string]: AppConfigJsonValue | string | number
|
||||
}
|
||||
|
||||
export type AppModerationContentPayload = {
|
||||
enabled?: boolean | null
|
||||
preset_response?: string | null
|
||||
[key: string]: AppConfigJsonValue | boolean | null | string | null | undefined
|
||||
}
|
||||
|
||||
export type AppInputFieldPayload = {
|
||||
config?: {
|
||||
[key: string]: AppConfigJsonValue
|
||||
}
|
||||
default?: AppConfigJsonValue
|
||||
description?: string
|
||||
enabled?: boolean
|
||||
hide?: boolean
|
||||
icon?: string | null
|
||||
icon_background?: string | null
|
||||
json_schema?:
|
||||
| string
|
||||
| {
|
||||
[key: string]: AppConfigJsonValue
|
||||
}
|
||||
| null
|
||||
label: string
|
||||
max_length?: number | null
|
||||
options?: Array<string>
|
||||
required?: boolean | null
|
||||
type?: string
|
||||
variable: string
|
||||
[key: string]:
|
||||
| AppConfigJsonValue
|
||||
| {
|
||||
[key: string]: AppConfigJsonValue
|
||||
}
|
||||
| string
|
||||
| boolean
|
||||
| string
|
||||
| null
|
||||
| string
|
||||
| null
|
||||
| string
|
||||
| {
|
||||
[key: string]: AppConfigJsonValue
|
||||
}
|
||||
| null
|
||||
| number
|
||||
| null
|
||||
| Array<string>
|
||||
| boolean
|
||||
| null
|
||||
| undefined
|
||||
}
|
||||
|
||||
export type AppSelectFieldPayload = {
|
||||
config?: {
|
||||
[key: string]: AppConfigJsonValue
|
||||
}
|
||||
default?: AppConfigJsonValue
|
||||
description?: string
|
||||
enabled?: boolean
|
||||
hide?: boolean
|
||||
icon?: string | null
|
||||
icon_background?: string | null
|
||||
json_schema?:
|
||||
| string
|
||||
| {
|
||||
[key: string]: AppConfigJsonValue
|
||||
}
|
||||
| null
|
||||
label: string
|
||||
max_length?: number | null
|
||||
options?: Array<string> | null
|
||||
required?: boolean | null
|
||||
type?: string
|
||||
variable: string
|
||||
[key: string]:
|
||||
| AppConfigJsonValue
|
||||
| {
|
||||
[key: string]: AppConfigJsonValue
|
||||
}
|
||||
| string
|
||||
| boolean
|
||||
| string
|
||||
| null
|
||||
| string
|
||||
| null
|
||||
| string
|
||||
| {
|
||||
[key: string]: AppConfigJsonValue
|
||||
}
|
||||
| null
|
||||
| number
|
||||
| null
|
||||
| Array<string>
|
||||
| null
|
||||
| boolean
|
||||
| null
|
||||
| undefined
|
||||
}
|
||||
|
||||
export type WorkflowFileUploadTransferPayload = {
|
||||
enabled?: boolean | null
|
||||
number_limits?: number | null
|
||||
@@ -3172,6 +3802,25 @@ export type FileListInputConfig = {
|
||||
type?: 'file-list'
|
||||
}
|
||||
|
||||
export type AppLegacyDatasetSelectionPayload = {
|
||||
enabled?: boolean | null
|
||||
id?: string
|
||||
[key: string]: AppConfigJsonValue | boolean | null | string | undefined
|
||||
}
|
||||
|
||||
export type AppLegacySensitiveWordConfigPayload = {
|
||||
canned_response: string
|
||||
enabled: boolean
|
||||
words: Array<string>
|
||||
[key: string]: AppConfigJsonValue | string | boolean | Array<string>
|
||||
}
|
||||
|
||||
export type AppDatasetSelectionPayload = {
|
||||
enabled?: boolean
|
||||
id?: string
|
||||
[key: string]: AppConfigJsonValue | boolean | string | undefined
|
||||
}
|
||||
|
||||
export type AgentFileUploadImageFeatureConfig = {
|
||||
enabled?: boolean
|
||||
[key: string]: unknown
|
||||
@@ -3502,6 +4151,21 @@ export type WorkflowCommentReplyWritable = {
|
||||
id: string
|
||||
}
|
||||
|
||||
export type AppConfigJsonValueWritable =
|
||||
| string
|
||||
| number
|
||||
| number
|
||||
| boolean
|
||||
| Array<AppConfigJsonValueWritable>
|
||||
| {
|
||||
[key: string]: AppConfigJsonValueWritable
|
||||
}
|
||||
| null
|
||||
|
||||
export type AppEmptyDatasetCollectionPayloadWritable = {
|
||||
[key: string]: never
|
||||
}
|
||||
|
||||
export type GetAppsData = {
|
||||
body?: never
|
||||
path?: never
|
||||
@@ -4944,7 +5608,7 @@ export type GetAppsByAppIdMessagesByMessageIdResponse =
|
||||
GetAppsByAppIdMessagesByMessageIdResponses[keyof GetAppsByAppIdMessagesByMessageIdResponses]
|
||||
|
||||
export type PostAppsByAppIdModelConfigData = {
|
||||
body: ModelConfigRequest
|
||||
body: AppModelConfigPayload
|
||||
path: {
|
||||
app_id: string
|
||||
}
|
||||
|
||||
@@ -321,24 +321,6 @@ export const zMessageFeedbackPayload = z.object({
|
||||
*/
|
||||
export const zTextFileResponse = z.string()
|
||||
|
||||
/**
|
||||
* ModelConfigRequest
|
||||
*/
|
||||
export const zModelConfigRequest = z.object({
|
||||
agent_mode: z.record(z.string(), z.unknown()).nullish(),
|
||||
configs: z.record(z.string(), z.unknown()).nullish(),
|
||||
dataset_configs: z.record(z.string(), z.unknown()).nullish(),
|
||||
model: z.string().nullish(),
|
||||
more_like_this: z.record(z.string(), z.unknown()).nullish(),
|
||||
opening_statement: z.string().nullish(),
|
||||
provider: z.string().nullish(),
|
||||
retrieval_model: z.record(z.string(), z.unknown()).nullish(),
|
||||
speech_to_text: z.record(z.string(), z.unknown()).nullish(),
|
||||
suggested_questions: z.array(z.string()).nullish(),
|
||||
text_to_speech: z.record(z.string(), z.unknown()).nullish(),
|
||||
tools: z.array(z.record(z.string(), z.unknown())).nullish(),
|
||||
})
|
||||
|
||||
/**
|
||||
* AppNamePayload
|
||||
*/
|
||||
@@ -2457,6 +2439,253 @@ export const zConversationMessageDetail = z.object({
|
||||
*/
|
||||
export const zExecutionContentType = z.enum(['human_input'])
|
||||
|
||||
export const zAppConfigJsonValue = z.json().nullable()
|
||||
|
||||
/**
|
||||
* AppExternalDataToolPayload
|
||||
*/
|
||||
export const zAppExternalDataToolPayload = z
|
||||
.object({
|
||||
config: z.record(z.string(), zAppConfigJsonValue).optional(),
|
||||
enabled: z.boolean().nullish(),
|
||||
icon: z.string().optional(),
|
||||
icon_background: z.string().optional(),
|
||||
label: z.string().optional(),
|
||||
type: z.string().optional(),
|
||||
variable: z.string().optional(),
|
||||
})
|
||||
.catchall(z.json())
|
||||
|
||||
/**
|
||||
* AppModelSelectionPayload
|
||||
*/
|
||||
export const zAppModelSelectionPayload = z
|
||||
.object({
|
||||
completion_params: z.record(z.string(), zAppConfigJsonValue),
|
||||
mode: z.string().nullish(),
|
||||
name: z.string(),
|
||||
provider: z.string(),
|
||||
})
|
||||
.catchall(z.json())
|
||||
|
||||
/**
|
||||
* AppFeaturePayload
|
||||
*/
|
||||
export const zAppFeaturePayload = z
|
||||
.object({
|
||||
enabled: z.boolean().nullish(),
|
||||
})
|
||||
.catchall(z.json())
|
||||
|
||||
/**
|
||||
* AppTextToSpeechPayload
|
||||
*/
|
||||
export const zAppTextToSpeechPayload = z
|
||||
.object({
|
||||
autoPlay: z.enum(['disabled', 'enabled']).optional(),
|
||||
enabled: z.boolean().nullish(),
|
||||
language: z.string().optional(),
|
||||
voice: z.string().optional(),
|
||||
})
|
||||
.catchall(z.json())
|
||||
|
||||
/**
|
||||
* AppAgentPromptPayload
|
||||
*/
|
||||
export const zAppAgentPromptPayload = z
|
||||
.object({
|
||||
first_prompt: z.string().optional(),
|
||||
next_iteration: z.string().optional(),
|
||||
})
|
||||
.catchall(z.json())
|
||||
|
||||
/**
|
||||
* PlanningStrategy
|
||||
*/
|
||||
export const zPlanningStrategy = z.enum(['function_call', 'react', 'react_router', 'router'])
|
||||
|
||||
/**
|
||||
* AppPromptMessagePayload
|
||||
*/
|
||||
export const zAppPromptMessagePayload = z
|
||||
.object({
|
||||
role: z.string(),
|
||||
text: z.string(),
|
||||
})
|
||||
.catchall(z.json())
|
||||
|
||||
/**
|
||||
* AppChatPromptPayload
|
||||
*/
|
||||
export const zAppChatPromptPayload = z
|
||||
.object({
|
||||
prompt: z.array(zAppPromptMessagePayload).optional(),
|
||||
})
|
||||
.catchall(z.json())
|
||||
|
||||
/**
|
||||
* AppConversationRolesPayload
|
||||
*/
|
||||
export const zAppConversationRolesPayload = z
|
||||
.object({
|
||||
assistant_prefix: z.string(),
|
||||
user_prefix: z.string(),
|
||||
})
|
||||
.catchall(z.json())
|
||||
|
||||
/**
|
||||
* AppCompletionPromptTextPayload
|
||||
*/
|
||||
export const zAppCompletionPromptTextPayload = z
|
||||
.object({
|
||||
text: z.string(),
|
||||
})
|
||||
.catchall(z.json())
|
||||
|
||||
/**
|
||||
* AppCompletionPromptPayload
|
||||
*/
|
||||
export const zAppCompletionPromptPayload = z
|
||||
.object({
|
||||
conversation_histories_role: zAppConversationRolesPayload.optional(),
|
||||
prompt: zAppCompletionPromptTextPayload.optional(),
|
||||
})
|
||||
.catchall(z.json())
|
||||
|
||||
/**
|
||||
* AppEmptyDatasetCollectionPayload
|
||||
*/
|
||||
export const zAppEmptyDatasetCollectionPayload = z.record(z.string(), z.never())
|
||||
|
||||
/**
|
||||
* AppMetadataModelPayload
|
||||
*/
|
||||
export const zAppMetadataModelPayload = z
|
||||
.object({
|
||||
completion_params: z.record(z.string(), zAppConfigJsonValue).optional(),
|
||||
mode: z.union([zLlmMode, z.literal('')]).optional(),
|
||||
name: z.string().optional(),
|
||||
provider: z.string().optional(),
|
||||
})
|
||||
.catchall(z.json())
|
||||
|
||||
/**
|
||||
* RerankMode
|
||||
*/
|
||||
export const zRerankMode = z.enum(['reranking_model', 'weighted_score'])
|
||||
|
||||
/**
|
||||
* AppRerankingModelPayload
|
||||
*/
|
||||
export const zAppRerankingModelPayload = z
|
||||
.object({
|
||||
reranking_model_name: z.string().optional(),
|
||||
reranking_provider_name: z.string().optional(),
|
||||
})
|
||||
.catchall(z.json())
|
||||
|
||||
/**
|
||||
* FileType
|
||||
*/
|
||||
export const zFileType = z.enum(['audio', 'custom', 'document', 'image', 'video'])
|
||||
|
||||
/**
|
||||
* FileTransferMethod
|
||||
*/
|
||||
export const zFileTransferMethod = z.enum([
|
||||
'datasource_file',
|
||||
'local_file',
|
||||
'remote_url',
|
||||
'tool_file',
|
||||
])
|
||||
|
||||
/**
|
||||
* AppFileTypeUploadPayload
|
||||
*/
|
||||
export const zAppFileTypeUploadPayload = z
|
||||
.object({
|
||||
enabled: z.boolean().nullish(),
|
||||
number_limits: z.int().nullish(),
|
||||
transfer_methods: z.array(zFileTransferMethod).nullish(),
|
||||
})
|
||||
.catchall(z.json())
|
||||
|
||||
/**
|
||||
* AppImageUploadPayload
|
||||
*/
|
||||
export const zAppImageUploadPayload = z
|
||||
.object({
|
||||
detail: z.enum(['high', 'low']).nullish(),
|
||||
enabled: z.boolean().optional(),
|
||||
number_limits: z.int().optional(),
|
||||
transfer_methods: z.array(zFileTransferMethod).optional(),
|
||||
})
|
||||
.catchall(z.json())
|
||||
|
||||
/**
|
||||
* AppImageConfigPayload
|
||||
*/
|
||||
export const zAppImageConfigPayload = z
|
||||
.object({
|
||||
detail: z.enum(['high', 'low']).nullish(),
|
||||
number_limits: z.int().optional(),
|
||||
transfer_methods: z.array(zFileTransferMethod).optional(),
|
||||
})
|
||||
.catchall(z.json())
|
||||
|
||||
/**
|
||||
* AppFilePreviewPayload
|
||||
*/
|
||||
export const zAppFilePreviewPayload = z
|
||||
.object({
|
||||
file_type_list: z.array(z.string()).nullish(),
|
||||
mode: z.string().nullish(),
|
||||
})
|
||||
.catchall(z.json())
|
||||
|
||||
/**
|
||||
* AppFileUploadPayload
|
||||
*/
|
||||
export const zAppFileUploadPayload = z
|
||||
.object({
|
||||
allowed_file_extensions: z.array(z.string()).optional(),
|
||||
allowed_file_types: z.array(zFileType).optional(),
|
||||
allowed_file_upload_methods: z.array(zFileTransferMethod).optional(),
|
||||
audio: zAppFileTypeUploadPayload.nullish(),
|
||||
custom: zAppFileTypeUploadPayload.nullish(),
|
||||
document: zAppFileTypeUploadPayload.nullish(),
|
||||
enabled: z.boolean().optional(),
|
||||
image: zAppImageUploadPayload.optional(),
|
||||
image_config: zAppImageConfigPayload.nullish(),
|
||||
number_limits: z.int().optional(),
|
||||
preview_config: zAppFilePreviewPayload.nullish(),
|
||||
video: zAppFileTypeUploadPayload.nullish(),
|
||||
})
|
||||
.catchall(z.json())
|
||||
|
||||
/**
|
||||
* AppSuggestedQuestionsModelPayload
|
||||
*/
|
||||
export const zAppSuggestedQuestionsModelPayload = z
|
||||
.object({
|
||||
completion_params: z.record(z.string(), zAppConfigJsonValue).optional(),
|
||||
mode: z.union([zLlmMode, z.literal('')]).optional(),
|
||||
name: z.string(),
|
||||
provider: z.string(),
|
||||
})
|
||||
.catchall(z.json())
|
||||
|
||||
/**
|
||||
* AppSuggestedQuestionsPayload
|
||||
*/
|
||||
export const zAppSuggestedQuestionsPayload = z
|
||||
.object({
|
||||
enabled: z.boolean().nullish(),
|
||||
model: zAppSuggestedQuestionsModelPayload.optional(),
|
||||
prompt: z.string().optional(),
|
||||
})
|
||||
.catchall(z.json())
|
||||
|
||||
/**
|
||||
* WorkflowRunForLogResponse
|
||||
*/
|
||||
@@ -2799,11 +3028,6 @@ export const zAppAgentPromptResponse = z.object({
|
||||
next_iteration: z.string().optional(),
|
||||
})
|
||||
|
||||
/**
|
||||
* PlanningStrategy
|
||||
*/
|
||||
export const zPlanningStrategy = z.enum(['function_call', 'react', 'react_router', 'router'])
|
||||
|
||||
/**
|
||||
* AppEmbeddingModelResponse
|
||||
*/
|
||||
@@ -2860,11 +3084,6 @@ export const zAppCompletionPromptConfigResponse = z.object({
|
||||
prompt: zAppCompletionPromptTextResponse.optional(),
|
||||
})
|
||||
|
||||
/**
|
||||
* RerankMode
|
||||
*/
|
||||
export const zRerankMode = z.enum(['reranking_model', 'weighted_score'])
|
||||
|
||||
/**
|
||||
* AppRerankingModelResponse
|
||||
*/
|
||||
@@ -3025,21 +3244,6 @@ export const zAppLegacyCurrentDatetimeToolResponse = z.object({
|
||||
current_datetime: z.record(z.string(), zJsonValue2),
|
||||
})
|
||||
|
||||
/**
|
||||
* FileType
|
||||
*/
|
||||
export const zFileType = z.enum(['audio', 'custom', 'document', 'image', 'video'])
|
||||
|
||||
/**
|
||||
* FileTransferMethod
|
||||
*/
|
||||
export const zFileTransferMethod = z.enum([
|
||||
'datasource_file',
|
||||
'local_file',
|
||||
'remote_url',
|
||||
'tool_file',
|
||||
])
|
||||
|
||||
/**
|
||||
* AppImageUploadResponse
|
||||
*/
|
||||
@@ -3148,6 +3352,253 @@ export const zAppJsonObjectFormResponse = z.object({
|
||||
json_object: zAppUserInputFormConfigResponse,
|
||||
})
|
||||
|
||||
/**
|
||||
* AppLegacyGoogleSearchToolPayload
|
||||
*/
|
||||
export const zAppLegacyGoogleSearchToolPayload = z
|
||||
.object({
|
||||
google_search: zAppFeaturePayload,
|
||||
})
|
||||
.catchall(z.json())
|
||||
|
||||
/**
|
||||
* AppLegacyWebReaderToolPayload
|
||||
*/
|
||||
export const zAppLegacyWebReaderToolPayload = z
|
||||
.object({
|
||||
web_reader: zAppFeaturePayload,
|
||||
})
|
||||
.catchall(z.json())
|
||||
|
||||
/**
|
||||
* AppLegacyWikipediaToolPayload
|
||||
*/
|
||||
export const zAppLegacyWikipediaToolPayload = z
|
||||
.object({
|
||||
wikipedia: zAppFeaturePayload,
|
||||
})
|
||||
.catchall(z.json())
|
||||
|
||||
/**
|
||||
* AppLegacyCurrentDatetimeToolPayload
|
||||
*/
|
||||
export const zAppLegacyCurrentDatetimeToolPayload = z
|
||||
.object({
|
||||
current_datetime: zAppFeaturePayload,
|
||||
})
|
||||
.catchall(z.json())
|
||||
|
||||
/**
|
||||
* AppMetadataConditionPayload
|
||||
*/
|
||||
export const zAppMetadataConditionPayload = z
|
||||
.object({
|
||||
comparison_operator: z.enum([
|
||||
'<',
|
||||
'=',
|
||||
'>',
|
||||
'after',
|
||||
'before',
|
||||
'contains',
|
||||
'empty',
|
||||
'end with',
|
||||
'in',
|
||||
'is',
|
||||
'is not',
|
||||
'not contains',
|
||||
'not empty',
|
||||
'not in',
|
||||
'start with',
|
||||
'≠',
|
||||
'≤',
|
||||
'≥',
|
||||
]),
|
||||
id: z.string().optional(),
|
||||
metadata_id: z.string().optional(),
|
||||
name: z.string(),
|
||||
value: z.union([z.string(), z.array(z.string()), z.int(), z.number()]).nullish(),
|
||||
})
|
||||
.catchall(z.json())
|
||||
|
||||
/**
|
||||
* AppMetadataFilteringPayload
|
||||
*/
|
||||
export const zAppMetadataFilteringPayload = z
|
||||
.object({
|
||||
conditions: z.array(zAppMetadataConditionPayload).nullish(),
|
||||
logical_operator: z.enum(['and', 'or']).nullish(),
|
||||
})
|
||||
.catchall(z.json())
|
||||
|
||||
/**
|
||||
* AppKeywordWeightPayload
|
||||
*/
|
||||
export const zAppKeywordWeightPayload = z
|
||||
.object({
|
||||
keyword_weight: z.number(),
|
||||
})
|
||||
.catchall(z.json())
|
||||
|
||||
/**
|
||||
* AppVectorWeightPayload
|
||||
*/
|
||||
export const zAppVectorWeightPayload = z
|
||||
.object({
|
||||
embedding_model_name: z.string(),
|
||||
embedding_provider_name: z.string(),
|
||||
vector_weight: z.number(),
|
||||
})
|
||||
.catchall(z.json())
|
||||
|
||||
/**
|
||||
* AppRetrievalWeightsPayload
|
||||
*/
|
||||
export const zAppRetrievalWeightsPayload = z
|
||||
.object({
|
||||
keyword_setting: zAppKeywordWeightPayload,
|
||||
vector_setting: zAppVectorWeightPayload,
|
||||
weight_type: z.enum(['customized', 'keyword_first', 'semantic_first']).optional(),
|
||||
})
|
||||
.catchall(z.json())
|
||||
|
||||
/**
|
||||
* AppModerationContentPayload
|
||||
*/
|
||||
export const zAppModerationContentPayload = z
|
||||
.object({
|
||||
enabled: z.boolean().nullish(),
|
||||
preset_response: z.string().nullish(),
|
||||
})
|
||||
.catchall(z.json())
|
||||
|
||||
/**
|
||||
* AppModerationConfigPayload
|
||||
*/
|
||||
export const zAppModerationConfigPayload = z
|
||||
.object({
|
||||
api_based_extension_id: z.string().nullish(),
|
||||
inputs_config: zAppModerationContentPayload.nullish(),
|
||||
keywords: z.string().nullish(),
|
||||
outputs_config: zAppModerationContentPayload.nullish(),
|
||||
})
|
||||
.catchall(z.json())
|
||||
|
||||
/**
|
||||
* AppModerationPayload
|
||||
*/
|
||||
export const zAppModerationPayload = z.object({
|
||||
config: zAppModerationConfigPayload.nullish(),
|
||||
enabled: z.boolean().nullish(),
|
||||
type: z.string().nullish(),
|
||||
})
|
||||
|
||||
/**
|
||||
* AppInputFieldPayload
|
||||
*/
|
||||
export const zAppInputFieldPayload = z
|
||||
.object({
|
||||
config: z.record(z.string(), zAppConfigJsonValue).optional(),
|
||||
default: zAppConfigJsonValue.optional(),
|
||||
description: z.string().optional(),
|
||||
enabled: z.boolean().optional(),
|
||||
hide: z.boolean().optional(),
|
||||
icon: z.string().nullish(),
|
||||
icon_background: z.string().nullish(),
|
||||
json_schema: z.union([z.string(), z.record(z.string(), zAppConfigJsonValue)]).nullish(),
|
||||
label: z.string(),
|
||||
max_length: z.int().nullish(),
|
||||
options: z.array(z.string()).optional(),
|
||||
required: z.boolean().nullish(),
|
||||
type: z.string().optional(),
|
||||
variable: z.string(),
|
||||
})
|
||||
.catchall(z.json())
|
||||
|
||||
/**
|
||||
* AppTextInputPayload
|
||||
*/
|
||||
export const zAppTextInputPayload = z
|
||||
.object({
|
||||
'text-input': zAppInputFieldPayload,
|
||||
})
|
||||
.strict()
|
||||
|
||||
/**
|
||||
* AppParagraphInputPayload
|
||||
*/
|
||||
export const zAppParagraphInputPayload = z
|
||||
.object({
|
||||
paragraph: zAppInputFieldPayload,
|
||||
})
|
||||
.strict()
|
||||
|
||||
/**
|
||||
* AppNumberInputPayload
|
||||
*/
|
||||
export const zAppNumberInputPayload = z
|
||||
.object({
|
||||
number: zAppInputFieldPayload,
|
||||
})
|
||||
.strict()
|
||||
|
||||
/**
|
||||
* AppCheckboxInputPayload
|
||||
*/
|
||||
export const zAppCheckboxInputPayload = z
|
||||
.object({
|
||||
checkbox: zAppInputFieldPayload,
|
||||
})
|
||||
.strict()
|
||||
|
||||
/**
|
||||
* AppExternalDataInputPayload
|
||||
*/
|
||||
export const zAppExternalDataInputPayload = z
|
||||
.object({
|
||||
external_data_tool: zAppInputFieldPayload,
|
||||
})
|
||||
.strict()
|
||||
|
||||
/**
|
||||
* AppSelectFieldPayload
|
||||
*/
|
||||
export const zAppSelectFieldPayload = z
|
||||
.object({
|
||||
config: z.record(z.string(), zAppConfigJsonValue).optional(),
|
||||
default: zAppConfigJsonValue.optional(),
|
||||
description: z.string().optional(),
|
||||
enabled: z.boolean().optional(),
|
||||
hide: z.boolean().optional(),
|
||||
icon: z.string().nullish(),
|
||||
icon_background: z.string().nullish(),
|
||||
json_schema: z.union([z.string(), z.record(z.string(), zAppConfigJsonValue)]).nullish(),
|
||||
label: z.string(),
|
||||
max_length: z.int().nullish(),
|
||||
options: z.array(z.string()).nullish(),
|
||||
required: z.boolean().nullish(),
|
||||
type: z.string().optional(),
|
||||
variable: z.string(),
|
||||
})
|
||||
.catchall(z.json())
|
||||
|
||||
/**
|
||||
* AppSelectInputPayload
|
||||
*/
|
||||
export const zAppSelectInputPayload = z
|
||||
.object({
|
||||
select: zAppSelectFieldPayload,
|
||||
})
|
||||
.strict()
|
||||
|
||||
export const zAppUserInputFormPayload = z.union([
|
||||
zAppTextInputPayload,
|
||||
zAppSelectInputPayload,
|
||||
zAppParagraphInputPayload,
|
||||
zAppNumberInputPayload,
|
||||
zAppCheckboxInputPayload,
|
||||
zAppExternalDataInputPayload,
|
||||
])
|
||||
|
||||
/**
|
||||
* WorkflowFileUploadTransferPayload
|
||||
*/
|
||||
@@ -3589,6 +4040,25 @@ export const zAppProviderAgentToolResponse = z.object({
|
||||
tool_parameters: z.record(z.string(), zJsonValue2),
|
||||
})
|
||||
|
||||
/**
|
||||
* AppProviderAgentToolPayload
|
||||
*/
|
||||
export const zAppProviderAgentToolPayload = z
|
||||
.object({
|
||||
credential_id: z.string().nullish(),
|
||||
enabled: z.boolean().nullish(),
|
||||
isDeleted: z.boolean().optional(),
|
||||
notAuthor: z.boolean().optional(),
|
||||
plugin_unique_identifier: z.string().nullish(),
|
||||
provider_id: z.string(),
|
||||
provider_name: z.string().optional(),
|
||||
provider_type: zToolProviderType,
|
||||
tool_label: z.string().optional(),
|
||||
tool_name: z.string(),
|
||||
tool_parameters: z.record(z.string(), zAppConfigJsonValue),
|
||||
})
|
||||
.catchall(z.json())
|
||||
|
||||
/**
|
||||
* AppDatasetReferenceResponse
|
||||
*/
|
||||
@@ -3891,6 +4361,145 @@ export const zFileListInputConfig = z.object({
|
||||
type: z.literal('file-list').optional().default('file-list'),
|
||||
})
|
||||
|
||||
/**
|
||||
* AppLegacyDatasetSelectionPayload
|
||||
*/
|
||||
export const zAppLegacyDatasetSelectionPayload = z
|
||||
.object({
|
||||
enabled: z.boolean().nullish(),
|
||||
id: z.string().optional(),
|
||||
})
|
||||
.catchall(z.json())
|
||||
|
||||
/**
|
||||
* AppLegacyDatasetToolPayload
|
||||
*/
|
||||
export const zAppLegacyDatasetToolPayload = z
|
||||
.object({
|
||||
dataset: zAppLegacyDatasetSelectionPayload,
|
||||
})
|
||||
.catchall(z.json())
|
||||
|
||||
/**
|
||||
* AppLegacySensitiveWordConfigPayload
|
||||
*/
|
||||
export const zAppLegacySensitiveWordConfigPayload = z
|
||||
.object({
|
||||
canned_response: z.string(),
|
||||
enabled: z.boolean(),
|
||||
words: z.array(z.string()),
|
||||
})
|
||||
.catchall(z.json())
|
||||
|
||||
/**
|
||||
* AppLegacySensitiveWordToolPayload
|
||||
*/
|
||||
export const zAppLegacySensitiveWordToolPayload = z
|
||||
.object({
|
||||
'sensitive-word-avoidance': zAppLegacySensitiveWordConfigPayload,
|
||||
})
|
||||
.catchall(z.json())
|
||||
|
||||
export const zAppAgentToolPayload = z.union([
|
||||
zAppProviderAgentToolPayload,
|
||||
zAppLegacyDatasetToolPayload,
|
||||
zAppLegacyGoogleSearchToolPayload,
|
||||
zAppLegacyWebReaderToolPayload,
|
||||
zAppLegacyWikipediaToolPayload,
|
||||
zAppLegacyCurrentDatetimeToolPayload,
|
||||
zAppLegacySensitiveWordToolPayload,
|
||||
])
|
||||
|
||||
/**
|
||||
* AppAgentModePayload
|
||||
*/
|
||||
export const zAppAgentModePayload = z
|
||||
.object({
|
||||
enabled: z.boolean().nullish(),
|
||||
max_iteration: z.int().optional(),
|
||||
prompt: z.union([zAppAgentPromptPayload, z.string()]).nullish(),
|
||||
strategy: z.union([zPlanningStrategy, z.enum(['', 'cot', 'function-calling'])]).nullish(),
|
||||
tools: z.array(zAppAgentToolPayload).nullish(),
|
||||
})
|
||||
.catchall(z.json())
|
||||
|
||||
/**
|
||||
* AppDatasetSelectionPayload
|
||||
*/
|
||||
export const zAppDatasetSelectionPayload = z
|
||||
.object({
|
||||
enabled: z.boolean().optional(),
|
||||
id: z.string().optional(),
|
||||
})
|
||||
.catchall(z.json())
|
||||
|
||||
/**
|
||||
* AppDatasetToolPayload
|
||||
*/
|
||||
export const zAppDatasetToolPayload = z
|
||||
.object({
|
||||
dataset: zAppDatasetSelectionPayload,
|
||||
})
|
||||
.catchall(z.json())
|
||||
|
||||
/**
|
||||
* AppDatasetCollectionPayload
|
||||
*/
|
||||
export const zAppDatasetCollectionPayload = z
|
||||
.object({
|
||||
datasets: z.array(zAppDatasetToolPayload),
|
||||
strategy: z.string().optional(),
|
||||
})
|
||||
.catchall(z.json())
|
||||
|
||||
/**
|
||||
* AppDatasetConfigPayload
|
||||
*/
|
||||
export const zAppDatasetConfigPayload = z
|
||||
.object({
|
||||
datasets: z.union([zAppDatasetCollectionPayload, zAppEmptyDatasetCollectionPayload]).nullish(),
|
||||
metadata_filtering_conditions: zAppMetadataFilteringPayload.nullish(),
|
||||
metadata_filtering_mode: z.enum(['automatic', 'disabled', 'manual']).optional(),
|
||||
metadata_model_config: zAppMetadataModelPayload.nullish(),
|
||||
reranking_enable: z.boolean().optional(),
|
||||
reranking_enabled: z.boolean().optional(),
|
||||
reranking_mode: zRerankMode.optional(),
|
||||
reranking_model: zAppRerankingModelPayload.nullish(),
|
||||
retrieval_model: z.enum(['multiple', 'single']).optional(),
|
||||
score_threshold: z.number().nullish(),
|
||||
score_threshold_enabled: z.boolean().optional(),
|
||||
top_k: z.int().optional(),
|
||||
weights: zAppRetrievalWeightsPayload.nullish(),
|
||||
})
|
||||
.catchall(z.json())
|
||||
|
||||
/**
|
||||
* AppModelConfigPayload
|
||||
*
|
||||
* Write transport; app-mode validators own defaults and feature-specific rules.
|
||||
*/
|
||||
export const zAppModelConfigPayload = z.object({
|
||||
agent_mode: zAppAgentModePayload.nullish(),
|
||||
chat_prompt_config: zAppChatPromptPayload.nullish(),
|
||||
completion_prompt_config: zAppCompletionPromptPayload.nullish(),
|
||||
dataset_configs: zAppDatasetConfigPayload.nullish(),
|
||||
dataset_query_variable: z.string().nullish(),
|
||||
external_data_tools: z.array(zAppExternalDataToolPayload).nullish(),
|
||||
file_upload: zAppFileUploadPayload.nullish(),
|
||||
model: zAppModelSelectionPayload,
|
||||
more_like_this: zAppFeaturePayload.nullish(),
|
||||
opening_statement: z.string().nullish(),
|
||||
pre_prompt: z.string().nullish(),
|
||||
prompt_type: z.enum(['', 'advanced', 'simple']).nullish(),
|
||||
retriever_resource: zAppFeaturePayload.nullish(),
|
||||
sensitive_word_avoidance: zAppModerationPayload.nullish(),
|
||||
speech_to_text: zAppFeaturePayload.nullish(),
|
||||
suggested_questions: z.array(z.string()).nullish(),
|
||||
suggested_questions_after_answer: zAppSuggestedQuestionsPayload.nullish(),
|
||||
text_to_speech: zAppTextToSpeechPayload.nullish(),
|
||||
user_input_form: z.array(zAppUserInputFormPayload).nullish(),
|
||||
})
|
||||
|
||||
/**
|
||||
* AgentFileUploadImageFeatureConfig
|
||||
*/
|
||||
@@ -4744,6 +5353,13 @@ export const zWorkflowCommentDetailWritable = z.object({
|
||||
updated_at: z.int().nullish(),
|
||||
})
|
||||
|
||||
export const zAppConfigJsonValueWritable = z.json().nullable()
|
||||
|
||||
/**
|
||||
* AppEmptyDatasetCollectionPayload
|
||||
*/
|
||||
export const zAppEmptyDatasetCollectionPayloadWritable = z.record(z.string(), z.never())
|
||||
|
||||
export const zGetAppsQuery = z.object({
|
||||
creator_ids: z.array(z.string()).optional(),
|
||||
is_created_by_me: z.boolean().optional(),
|
||||
@@ -5654,7 +6270,7 @@ export const zGetAppsByAppIdMessagesByMessageIdPath = z.object({
|
||||
*/
|
||||
export const zGetAppsByAppIdMessagesByMessageIdResponse = zMessageDetailResponse
|
||||
|
||||
export const zPostAppsByAppIdModelConfigBody = zModelConfigRequest
|
||||
export const zPostAppsByAppIdModelConfigBody = zAppModelConfigPayload
|
||||
|
||||
export const zPostAppsByAppIdModelConfigPath = z.object({
|
||||
app_id: z.uuid(),
|
||||
|
||||
@@ -60,7 +60,16 @@ const currentDir = path.dirname(fileURLToPath(import.meta.url))
|
||||
const apiOpenApiDir = path.resolve(currentDir, 'openapi')
|
||||
|
||||
const operationMethods = new Set(['delete', 'get', 'patch', 'post', 'put'])
|
||||
const strictZodSchemaNames = new Set(['AccountProfilePatchPayload', 'Parameters'])
|
||||
const strictZodSchemaNames = new Set([
|
||||
'AccountProfilePatchPayload',
|
||||
'Parameters',
|
||||
'AppTextInputPayload',
|
||||
'AppSelectInputPayload',
|
||||
'AppParagraphInputPayload',
|
||||
'AppNumberInputPayload',
|
||||
'AppCheckboxInputPayload',
|
||||
'AppExternalDataInputPayload',
|
||||
])
|
||||
const pydanticDecimalStringPattern = '^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$'
|
||||
const codegenSafeDecimalStringPattern = '^(?![-+.]*$)[+-]?0*\\d*\\.?\\d*$'
|
||||
const fastOpenApiConsoleSpecFilename = 'fastopenapi-console-openapi.json'
|
||||
@@ -628,9 +637,31 @@ const createApiConfig = (job: ApiJob): UserConfig => ({
|
||||
{
|
||||
name: 'zod',
|
||||
'~resolvers': {
|
||||
union: (ctx) => {
|
||||
// The generator's recursive lazy schemas infer `any`. Keep this JSON
|
||||
// leaf typed through Zod so oRPC clients retain the request contract.
|
||||
if (
|
||||
ctx.path['~ref'].some(
|
||||
(segment) =>
|
||||
segment === 'AppConfigJsonValue' || segment === 'AppConfigJsonValueWritable',
|
||||
)
|
||||
)
|
||||
return $(ctx.symbols.z).attr('json').call()
|
||||
|
||||
return ctx.nodes.base(ctx)
|
||||
},
|
||||
object: (ctx) => {
|
||||
const objectSchema = ctx.nodes.base(ctx)
|
||||
const additionalProperties = ctx.schema.additionalProperties
|
||||
// Shaped objects otherwise discard the backend's typed JSON extensions.
|
||||
if (
|
||||
additionalProperties &&
|
||||
typeof additionalProperties !== 'boolean' &&
|
||||
additionalProperties.$ref === '#/components/schemas/AppConfigJsonValue' &&
|
||||
ctx.schema.properties
|
||||
)
|
||||
return objectSchema.attr('catchall').call($(ctx.symbols.z).attr('json').call())
|
||||
|
||||
// openapi-ts normalizes `additionalProperties: false` to `never`, but
|
||||
// does not make shaped Zod objects strict.
|
||||
const isStrictSchema = ctx.path['~ref'].some(
|
||||
|
||||
Reference in New Issue
Block a user