mirror of
https://github.com/langgenius/dify.git
synced 2026-10-04 13:47:55 +08:00
refactor(api): tighten app detail response schema (#42876)
This commit is contained in:
52 files changed
+4295
-1373
No files matched your search
@@ -274,6 +274,7 @@ class AgentAppPartial(GenericAppPartial):
|
||||
|
||||
class AgentAppDetailWithSite(GenericAppDetailWithSite):
|
||||
permission_keys: list[str]
|
||||
bound_agent_id: str | None = None
|
||||
app_id: str | None = None
|
||||
backing_app_id: str | None = None
|
||||
hidden_app_backed: bool = False
|
||||
@@ -404,14 +405,14 @@ def _serialize_agent_app_detail(
|
||||
roster persona fields without widening the shared /apps detail schema.
|
||||
"""
|
||||
|
||||
app_model = AppService().get_app(app_model, session=session)
|
||||
access_mode = None
|
||||
if SystemFeatureService.is_webapp_auth_enabled():
|
||||
app_setting = EnterpriseService.WebAppAuth.get_app_access_mode_by_id(app_id=str(app_model.id))
|
||||
app_model.access_mode = app_setting.access_mode # type: ignore[attr-defined]
|
||||
access_mode = app_setting.access_mode
|
||||
|
||||
roster_service = _agent_roster_service(session)
|
||||
payload = GenericAppDetailWithSite.model_validate(
|
||||
AppResponseView(app_model, session=session),
|
||||
AppResponseView(app_model, session=session, account=current_user, access_mode=access_mode),
|
||||
from_attributes=True,
|
||||
).model_dump(mode="json")
|
||||
agent = (
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import uuid
|
||||
from dataclasses import asdict
|
||||
from http import HTTPStatus
|
||||
from typing import Literal, Self, override
|
||||
|
||||
@@ -303,11 +304,12 @@ _ADMIN_ROLES = frozenset({TenantAccountRole.OWNER, TenantAccountRole.ADMIN})
|
||||
|
||||
def _app_detail_response(app: AppRecord) -> AppDetailWithSite:
|
||||
"""Resolve transport URLs here so repositories work without a Flask request."""
|
||||
response = AppDetailWithSite.model_validate(app, from_attributes=True)
|
||||
response.api_base_url = normalize_api_base_url(dify_config.SERVICE_API_URL or request.host_url.rstrip("/"))
|
||||
if response.site is not None:
|
||||
response.site.app_base_url = dify_config.APP_WEB_URL or request.url_root.rstrip("/")
|
||||
return response
|
||||
data = asdict(app)
|
||||
data["api_base_url"] = normalize_api_base_url(dify_config.SERVICE_API_URL or request.host_url.rstrip("/"))
|
||||
data["app_id"] = None
|
||||
if data["site"] is not None:
|
||||
data["site"]["app_base_url"] = dify_config.APP_WEB_URL or request.url_root.rstrip("/")
|
||||
return AppDetailWithSite.model_validate(data)
|
||||
|
||||
|
||||
class AppResource(Resource):
|
||||
|
||||
@@ -2,7 +2,7 @@ import json
|
||||
import logging
|
||||
from collections.abc import Sequence
|
||||
from datetime import datetime
|
||||
from typing import Any, NotRequired, Self, TypedDict
|
||||
from typing import Any, Literal, NotRequired, Self, TypedDict
|
||||
|
||||
from flask import abort, request
|
||||
from flask_restx import Resource
|
||||
@@ -216,7 +216,7 @@ class WorkflowSuggestedQuestionsAfterAnswerPayload(WorkflowFeatureTogglePayload)
|
||||
class WorkflowTextToSpeechPayload(WorkflowFeatureTogglePayload):
|
||||
language: str | None = None
|
||||
voice: str | None = None
|
||||
autoPlay: str | None = None
|
||||
autoPlay: Literal["enabled", "disabled"] | None = None
|
||||
|
||||
|
||||
class WorkflowSensitiveWordAvoidancePayload(WorkflowFeatureTogglePayload):
|
||||
|
||||
@@ -4,6 +4,23 @@ CUSTOM_FOLLOW_UP_PROMPT_MAX_LENGTH = 1000
|
||||
|
||||
|
||||
class SuggestedQuestionsAfterAnswerConfigManager:
|
||||
@staticmethod
|
||||
def validate_optional_fields(config: dict[str, Any]) -> None:
|
||||
feature = config.get("suggested_questions_after_answer")
|
||||
if feature is None:
|
||||
return
|
||||
if not isinstance(feature, dict):
|
||||
raise ValueError("suggested_questions_after_answer must be of dict type")
|
||||
if "prompt" in feature:
|
||||
prompt = feature["prompt"]
|
||||
if not isinstance(prompt, str):
|
||||
raise ValueError("prompt in suggested_questions_after_answer must be of string type")
|
||||
if len(prompt) > CUSTOM_FOLLOW_UP_PROMPT_MAX_LENGTH:
|
||||
raise ValueError(
|
||||
f"prompt in suggested_questions_after_answer must be less than or equal to "
|
||||
f"{CUSTOM_FOLLOW_UP_PROMPT_MAX_LENGTH} characters"
|
||||
)
|
||||
|
||||
@classmethod
|
||||
def convert(cls, config: dict[str, Any]) -> bool:
|
||||
"""
|
||||
@@ -45,14 +62,7 @@ class SuggestedQuestionsAfterAnswerConfigManager:
|
||||
if not isinstance(config["suggested_questions_after_answer"]["enabled"], bool):
|
||||
raise ValueError("enabled in suggested_questions_after_answer must be of boolean type")
|
||||
|
||||
prompt = config["suggested_questions_after_answer"].get("prompt")
|
||||
if prompt is not None and not isinstance(prompt, str):
|
||||
raise ValueError("prompt in suggested_questions_after_answer must be of string type")
|
||||
if isinstance(prompt, str) and len(prompt) > CUSTOM_FOLLOW_UP_PROMPT_MAX_LENGTH:
|
||||
raise ValueError(
|
||||
f"prompt in suggested_questions_after_answer must be less than or equal to "
|
||||
f"{CUSTOM_FOLLOW_UP_PROMPT_MAX_LENGTH} characters"
|
||||
)
|
||||
cls.validate_optional_fields(config)
|
||||
|
||||
if "model" in config["suggested_questions_after_answer"]:
|
||||
model_config = config["suggested_questions_after_answer"]["model"]
|
||||
|
||||
@@ -4,6 +4,19 @@ from core.app.app_config.entities import TextToSpeechEntity
|
||||
|
||||
|
||||
class TextToSpeechConfigManager:
|
||||
@staticmethod
|
||||
def validate_optional_fields(config: dict[str, Any]) -> None:
|
||||
feature = config.get("text_to_speech")
|
||||
if feature is None:
|
||||
return
|
||||
if not isinstance(feature, dict):
|
||||
raise ValueError("text_to_speech must be of dict type")
|
||||
for key in ("voice", "language"):
|
||||
if key in feature and not isinstance(feature[key], str):
|
||||
raise ValueError(f"{key} in text_to_speech must be of string type")
|
||||
if "autoPlay" in feature and feature["autoPlay"] not in ("enabled", "disabled"):
|
||||
raise ValueError("autoPlay in text_to_speech must be enabled or disabled")
|
||||
|
||||
@classmethod
|
||||
def convert(cls, config: dict[str, Any]):
|
||||
"""
|
||||
@@ -36,6 +49,8 @@ class TextToSpeechConfigManager:
|
||||
if not isinstance(config["text_to_speech"], dict):
|
||||
raise ValueError("text_to_speech must be of dict type")
|
||||
|
||||
cls.validate_optional_fields(config)
|
||||
|
||||
if "enabled" not in config["text_to_speech"] or not config["text_to_speech"]["enabled"]:
|
||||
config["text_to_speech"]["enabled"] = False
|
||||
config["text_to_speech"]["voice"] = ""
|
||||
|
||||
+55
-113
@@ -1,13 +1,15 @@
|
||||
"""Shared Console app response schemas for materialized application results."""
|
||||
|
||||
from datetime import datetime
|
||||
from typing import Any
|
||||
|
||||
from pydantic import AliasChoices, Field, computed_field, field_validator
|
||||
|
||||
from enums import WebAppAccessMode
|
||||
from fields.app_model_config_response import AppModelConfigResponse, AppModelSelectionResponse
|
||||
from fields.base import ResponseModel
|
||||
from libs.helper import build_icon_url, to_timestamp
|
||||
from models.model import IconType
|
||||
from models.enums import CustomizeTokenStrategy
|
||||
from models.model import AppMode, IconType
|
||||
from services.entities.app_entities import RecentAppMode
|
||||
from services.entities.dsl_entities import DslImportWarning, ImportStatus
|
||||
|
||||
@@ -37,7 +39,7 @@ class WorkflowPartial(ResponseModel):
|
||||
|
||||
|
||||
class ModelConfigPartial(ResponseModel):
|
||||
model: Any | None = Field(default=None, validation_alias=AliasChoices("model_dict", "model"))
|
||||
model: AppModelSelectionResponse | None = Field(default=None, validation_alias=AliasChoices("model_dict", "model"))
|
||||
pre_prompt: str | None = None
|
||||
created_by: str | None = None
|
||||
created_at: int | None = None
|
||||
@@ -50,90 +52,31 @@ class ModelConfigPartial(ResponseModel):
|
||||
return to_timestamp(value)
|
||||
|
||||
|
||||
class AppModelConfigResponse(ResponseModel):
|
||||
opening_statement: str | None = None
|
||||
suggested_questions: Any | None = Field(
|
||||
default=None, validation_alias=AliasChoices("suggested_questions_list", "suggested_questions")
|
||||
)
|
||||
suggested_questions_after_answer: Any | None = Field(
|
||||
default=None,
|
||||
validation_alias=AliasChoices("suggested_questions_after_answer_dict", "suggested_questions_after_answer"),
|
||||
)
|
||||
speech_to_text: Any | None = Field(
|
||||
default=None, validation_alias=AliasChoices("speech_to_text_dict", "speech_to_text")
|
||||
)
|
||||
text_to_speech: Any | None = Field(
|
||||
default=None, validation_alias=AliasChoices("text_to_speech_dict", "text_to_speech")
|
||||
)
|
||||
retriever_resource: Any | None = Field(
|
||||
default=None, validation_alias=AliasChoices("retriever_resource_dict", "retriever_resource")
|
||||
)
|
||||
annotation_reply: Any | None = Field(
|
||||
default=None, validation_alias=AliasChoices("annotation_reply_dict", "annotation_reply")
|
||||
)
|
||||
more_like_this: Any | None = Field(
|
||||
default=None, validation_alias=AliasChoices("more_like_this_dict", "more_like_this")
|
||||
)
|
||||
sensitive_word_avoidance: Any | None = Field(
|
||||
default=None, validation_alias=AliasChoices("sensitive_word_avoidance_dict", "sensitive_word_avoidance")
|
||||
)
|
||||
external_data_tools: Any | None = Field(
|
||||
default=None, validation_alias=AliasChoices("external_data_tools_list", "external_data_tools")
|
||||
)
|
||||
model: Any | None = Field(default=None, validation_alias=AliasChoices("model_dict", "model"))
|
||||
user_input_form: Any | None = Field(
|
||||
default=None, validation_alias=AliasChoices("user_input_form_list", "user_input_form")
|
||||
)
|
||||
dataset_query_variable: str | None = None
|
||||
pre_prompt: str | None = None
|
||||
agent_mode: Any | None = Field(default=None, validation_alias=AliasChoices("agent_mode_dict", "agent_mode"))
|
||||
prompt_type: str | None = None
|
||||
chat_prompt_config: Any | None = Field(
|
||||
default=None, validation_alias=AliasChoices("chat_prompt_config_dict", "chat_prompt_config")
|
||||
)
|
||||
completion_prompt_config: Any | None = Field(
|
||||
default=None, validation_alias=AliasChoices("completion_prompt_config_dict", "completion_prompt_config")
|
||||
)
|
||||
dataset_configs: Any | None = Field(
|
||||
default=None, validation_alias=AliasChoices("dataset_configs_dict", "dataset_configs")
|
||||
)
|
||||
file_upload: Any | None = Field(default=None, validation_alias=AliasChoices("file_upload_dict", "file_upload"))
|
||||
created_by: str | None = None
|
||||
created_at: int | None = None
|
||||
updated_by: str | None = None
|
||||
updated_at: int | None = None
|
||||
|
||||
@field_validator("created_at", "updated_at", mode="before")
|
||||
@classmethod
|
||||
def _normalize_timestamp(cls, value: datetime | int | None) -> int | None:
|
||||
return to_timestamp(value)
|
||||
|
||||
|
||||
class AppDetailSiteResponse(ResponseModel):
|
||||
access_token: str | None = Field(default=None, validation_alias="code")
|
||||
code: str | None = None
|
||||
title: str | None = None
|
||||
icon_type: str | IconType | None = None
|
||||
icon: str | None = None
|
||||
icon_background: str | None = None
|
||||
description: str | None = None
|
||||
default_language: str | None = None
|
||||
chat_color_theme: str | None = None
|
||||
chat_color_theme_inverted: bool | None = None
|
||||
customize_domain: str | None = None
|
||||
copyright: str | None = None
|
||||
privacy_policy: str | None = None
|
||||
input_placeholder: str | None = None
|
||||
custom_disclaimer: str | None = None
|
||||
customize_token_strategy: str | None = None
|
||||
prompt_public: bool | None = None
|
||||
app_base_url: str | None = None
|
||||
show_workflow_steps: bool | None = None
|
||||
use_icon_as_answer_icon: bool | None = None
|
||||
created_by: str | None = None
|
||||
created_at: int | None = None
|
||||
updated_by: str | None = None
|
||||
updated_at: int | None = None
|
||||
access_token: str | None = Field(validation_alias="code")
|
||||
code: str | None
|
||||
title: str
|
||||
icon_type: IconType | None
|
||||
icon: str | None
|
||||
icon_background: str | None
|
||||
description: str | None
|
||||
default_language: str
|
||||
chat_color_theme: str | None
|
||||
chat_color_theme_inverted: bool
|
||||
customize_domain: str | None
|
||||
copyright: str | None
|
||||
privacy_policy: str | None
|
||||
input_placeholder: str | None
|
||||
custom_disclaimer: str
|
||||
customize_token_strategy: CustomizeTokenStrategy
|
||||
prompt_public: bool
|
||||
app_base_url: str
|
||||
show_workflow_steps: bool
|
||||
use_icon_as_answer_icon: bool
|
||||
created_by: str | None
|
||||
created_at: int
|
||||
updated_by: str | None
|
||||
updated_at: int
|
||||
|
||||
@computed_field(return_type=str | None) # type: ignore
|
||||
@property
|
||||
@@ -164,8 +107,8 @@ class AppPartial(ResponseModel):
|
||||
name: str
|
||||
max_active_requests: int | None = None
|
||||
description: str | None = Field(default=None, validation_alias=AliasChoices("desc_or_prompt", "description"))
|
||||
mode: str = Field(validation_alias="mode_compatible_with_agent")
|
||||
icon_type: str | None = None
|
||||
mode: AppMode = Field(validation_alias="mode_compatible_with_agent")
|
||||
icon_type: IconType | None = None
|
||||
icon: str | None = None
|
||||
icon_background: str | None = None
|
||||
model_config_: ModelConfigPartial | None = Field(
|
||||
@@ -180,7 +123,7 @@ class AppPartial(ResponseModel):
|
||||
updated_by: str | None = None
|
||||
updated_at: int | None = None
|
||||
tags: list[Tag] = Field(default_factory=list)
|
||||
access_mode: str | None = None
|
||||
access_mode: WebAppAccessMode | None = None
|
||||
create_user_name: str | None = None
|
||||
author_name: str | None = None
|
||||
has_draft_trigger: bool | None = None
|
||||
@@ -233,28 +176,27 @@ class RecentAppListResponse(ResponseModel):
|
||||
class AppDetail(ResponseModel):
|
||||
id: str
|
||||
name: str
|
||||
description: str | None = None
|
||||
mode: str = Field(validation_alias="mode_compatible_with_agent")
|
||||
icon: str | None = None
|
||||
icon_background: str | None = None
|
||||
description: str
|
||||
mode: AppMode = Field(validation_alias="mode_compatible_with_agent")
|
||||
icon: str | None
|
||||
icon_background: str | None
|
||||
enable_site: bool
|
||||
enable_api: bool
|
||||
model_config_: AppModelConfigResponse | None = Field(
|
||||
default=None,
|
||||
validation_alias=AliasChoices("app_model_config", "model_config"),
|
||||
alias="model_config",
|
||||
)
|
||||
workflow: WorkflowPartial | None = None
|
||||
tracing: Any | None = None
|
||||
use_icon_as_answer_icon: bool | None = None
|
||||
created_by: str | None = None
|
||||
created_at: int | None = None
|
||||
updated_by: str | None = None
|
||||
updated_at: int | None = None
|
||||
access_mode: str | None = None
|
||||
tags: list[Tag] = Field(default_factory=list)
|
||||
permission_keys: list[str] = Field(default_factory=list)
|
||||
maintainer: str | None = None
|
||||
workflow: WorkflowPartial | None
|
||||
tracing: str | None
|
||||
use_icon_as_answer_icon: bool
|
||||
created_by: str | None
|
||||
created_at: int
|
||||
updated_by: str | None
|
||||
updated_at: int
|
||||
access_mode: WebAppAccessMode | None
|
||||
tags: list[Tag]
|
||||
permission_keys: list[str]
|
||||
maintainer: str | None
|
||||
|
||||
@field_validator("created_at", "updated_at", mode="before")
|
||||
@classmethod
|
||||
@@ -263,15 +205,15 @@ class AppDetail(ResponseModel):
|
||||
|
||||
|
||||
class AppDetailWithSite(AppDetail):
|
||||
icon_type: str | None = None
|
||||
api_base_url: str | None = None
|
||||
max_active_requests: int | None = None
|
||||
deleted_tools: list[DeletedTool] = Field(default_factory=list)
|
||||
site: AppDetailSiteResponse | None = None
|
||||
icon_type: IconType | None
|
||||
api_base_url: str
|
||||
max_active_requests: int | None
|
||||
deleted_tools: list[DeletedTool]
|
||||
site: AppDetailSiteResponse | None
|
||||
# For Agent App type: the roster Agent backing this app (None otherwise).
|
||||
bound_agent_id: str | None = None
|
||||
bound_agent_id: str | None
|
||||
# For Agent App responses exposed through /agent.
|
||||
app_id: str | None = None
|
||||
app_id: str | None
|
||||
|
||||
@computed_field(return_type=str | None) # type: ignore
|
||||
@property
|
||||
@@ -295,7 +237,7 @@ class AppImportResponse(ResponseModel):
|
||||
id: str
|
||||
status: ImportStatus
|
||||
app_id: str | None = None
|
||||
app_mode: str | None = None
|
||||
app_mode: AppMode | None = None
|
||||
current_dsl_version: str
|
||||
imported_dsl_version: str = ""
|
||||
error: str = ""
|
||||
|
||||
@@ -0,0 +1,388 @@
|
||||
from datetime import datetime
|
||||
from typing import Literal, NotRequired, TypedDict
|
||||
|
||||
from pydantic import AliasChoices, ConfigDict, Field, JsonValue, field_validator, with_config
|
||||
|
||||
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 fields.base import ResponseModel
|
||||
from graphon.file import FileTransferMethod, FileType
|
||||
from graphon.model_runtime.entities.llm_entities import LLMMode
|
||||
from libs.helper import to_timestamp
|
||||
from models.enums import PromptType
|
||||
|
||||
|
||||
class AppEnabledConfigResponse(TypedDict):
|
||||
enabled: bool
|
||||
|
||||
|
||||
@with_config(ConfigDict(extra="allow"))
|
||||
class AppModelSelectionResponse(TypedDict, total=False):
|
||||
provider: str
|
||||
name: str
|
||||
mode: LLMMode | Literal[""]
|
||||
completion_params: dict[str, JsonValue]
|
||||
|
||||
|
||||
class AppSuggestedQuestionsAfterAnswerResponse(TypedDict):
|
||||
enabled: bool
|
||||
model: NotRequired[AppModelSelectionResponse]
|
||||
prompt: NotRequired[str]
|
||||
|
||||
|
||||
class AppTextToSpeechResponse(TypedDict):
|
||||
enabled: bool
|
||||
voice: NotRequired[str]
|
||||
language: NotRequired[str]
|
||||
autoPlay: NotRequired[Literal["enabled", "disabled"]]
|
||||
|
||||
|
||||
class AppEmbeddingModelResponse(TypedDict):
|
||||
embedding_provider_name: str
|
||||
embedding_model_name: str
|
||||
|
||||
|
||||
class AppAnnotationReplyDisabledResponse(TypedDict):
|
||||
enabled: Literal[False]
|
||||
|
||||
|
||||
class AppAnnotationReplyEnabledResponse(TypedDict):
|
||||
id: str
|
||||
enabled: Literal[True]
|
||||
score_threshold: float
|
||||
embedding_model: AppEmbeddingModelResponse
|
||||
|
||||
|
||||
@with_config(ConfigDict(extra="allow"))
|
||||
class AppSensitiveWordAvoidanceResponse(TypedDict):
|
||||
enabled: bool
|
||||
type: NotRequired[str]
|
||||
config: NotRequired[dict[str, JsonValue]]
|
||||
configs: NotRequired[list[JsonValue]]
|
||||
|
||||
|
||||
@with_config(ConfigDict(extra="allow"))
|
||||
class AppEnabledExternalDataToolResponse(TypedDict):
|
||||
enabled: Literal[True]
|
||||
variable: str
|
||||
type: str
|
||||
config: dict[str, JsonValue]
|
||||
label: NotRequired[str]
|
||||
icon: NotRequired[str]
|
||||
icon_background: NotRequired[str]
|
||||
|
||||
|
||||
@with_config(ConfigDict(extra="allow"))
|
||||
class AppDisabledExternalDataToolResponse(TypedDict):
|
||||
enabled: Literal[False]
|
||||
variable: NotRequired[str]
|
||||
type: NotRequired[str]
|
||||
config: NotRequired[dict[str, JsonValue]]
|
||||
label: NotRequired[str]
|
||||
icon: NotRequired[str]
|
||||
icon_background: NotRequired[str]
|
||||
|
||||
|
||||
@with_config(ConfigDict(extra="allow"))
|
||||
class AppUserInputFormConfigResponse(TypedDict):
|
||||
variable: str
|
||||
label: str
|
||||
description: NotRequired[str]
|
||||
required: NotRequired[bool]
|
||||
max_length: NotRequired[int | None]
|
||||
options: NotRequired[list[str]]
|
||||
default: NotRequired[JsonValue]
|
||||
type: NotRequired[str]
|
||||
hide: NotRequired[bool]
|
||||
allowed_file_types: NotRequired[list[FileType]]
|
||||
allowed_file_extensions: NotRequired[list[str]]
|
||||
allowed_file_upload_methods: NotRequired[list[FileTransferMethod]]
|
||||
json_schema: NotRequired[str | dict[str, JsonValue] | None]
|
||||
config: NotRequired[dict[str, JsonValue]]
|
||||
enabled: NotRequired[bool]
|
||||
icon: NotRequired[str | None]
|
||||
icon_background: NotRequired[str | None]
|
||||
|
||||
|
||||
AppTextInputFormResponse = TypedDict("AppTextInputFormResponse", {"text-input": AppUserInputFormConfigResponse})
|
||||
|
||||
|
||||
class AppSelectFormResponse(TypedDict):
|
||||
select: AppUserInputFormConfigResponse
|
||||
|
||||
|
||||
class AppParagraphFormResponse(TypedDict):
|
||||
paragraph: AppUserInputFormConfigResponse
|
||||
|
||||
|
||||
class AppNumberFormResponse(TypedDict):
|
||||
number: AppUserInputFormConfigResponse
|
||||
|
||||
|
||||
class AppCheckboxFormResponse(TypedDict):
|
||||
checkbox: AppUserInputFormConfigResponse
|
||||
|
||||
|
||||
class AppFileFormResponse(TypedDict):
|
||||
file: AppUserInputFormConfigResponse
|
||||
|
||||
|
||||
AppFileListFormResponse = TypedDict("AppFileListFormResponse", {"file-list": AppUserInputFormConfigResponse})
|
||||
|
||||
|
||||
class AppExternalDataToolFormResponse(TypedDict):
|
||||
external_data_tool: AppUserInputFormConfigResponse
|
||||
|
||||
|
||||
class AppJsonObjectFormResponse(TypedDict):
|
||||
json_object: AppUserInputFormConfigResponse
|
||||
|
||||
|
||||
AppUserInputFormResponse = (
|
||||
AppTextInputFormResponse
|
||||
| AppSelectFormResponse
|
||||
| AppParagraphFormResponse
|
||||
| AppNumberFormResponse
|
||||
| AppCheckboxFormResponse
|
||||
| AppFileFormResponse
|
||||
| AppFileListFormResponse
|
||||
| AppExternalDataToolFormResponse
|
||||
| AppJsonObjectFormResponse
|
||||
)
|
||||
|
||||
|
||||
class AppDatasetReferenceResponse(TypedDict, total=False):
|
||||
id: str
|
||||
enabled: bool
|
||||
|
||||
|
||||
class AppLegacySensitiveWordToolResponse(TypedDict):
|
||||
enabled: bool
|
||||
words: list[str]
|
||||
canned_response: str
|
||||
|
||||
|
||||
@with_config(ConfigDict(extra="allow"))
|
||||
class AppProviderAgentToolResponse(TypedDict):
|
||||
provider_type: ToolProviderType
|
||||
provider_id: str
|
||||
tool_name: str
|
||||
tool_parameters: dict[str, JsonValue]
|
||||
provider_name: NotRequired[str]
|
||||
tool_label: NotRequired[str]
|
||||
plugin_unique_identifier: NotRequired[str | None]
|
||||
credential_id: NotRequired[str | None]
|
||||
enabled: NotRequired[bool]
|
||||
isDeleted: NotRequired[bool]
|
||||
notAuthor: NotRequired[bool]
|
||||
|
||||
|
||||
class AppLegacyDatasetToolResponse(TypedDict):
|
||||
dataset: AppDatasetReferenceResponse
|
||||
|
||||
|
||||
class AppLegacyGoogleSearchToolResponse(TypedDict):
|
||||
google_search: dict[str, JsonValue]
|
||||
|
||||
|
||||
class AppLegacyWebReaderToolResponse(TypedDict):
|
||||
web_reader: dict[str, JsonValue]
|
||||
|
||||
|
||||
class AppLegacyWikipediaToolResponse(TypedDict):
|
||||
wikipedia: dict[str, JsonValue]
|
||||
|
||||
|
||||
class AppLegacyCurrentDatetimeToolResponse(TypedDict):
|
||||
current_datetime: dict[str, JsonValue]
|
||||
|
||||
|
||||
AppLegacySensitiveWordToolResponseItem = TypedDict(
|
||||
"AppLegacySensitiveWordToolResponseItem",
|
||||
{"sensitive-word-avoidance": AppLegacySensitiveWordToolResponse},
|
||||
)
|
||||
|
||||
|
||||
AppAgentToolResponse = (
|
||||
AppProviderAgentToolResponse
|
||||
| AppLegacyDatasetToolResponse
|
||||
| AppLegacyGoogleSearchToolResponse
|
||||
| AppLegacyWebReaderToolResponse
|
||||
| AppLegacyWikipediaToolResponse
|
||||
| AppLegacyCurrentDatetimeToolResponse
|
||||
| AppLegacySensitiveWordToolResponseItem
|
||||
)
|
||||
|
||||
|
||||
class AppAgentPromptResponse(TypedDict, total=False):
|
||||
first_prompt: str
|
||||
next_iteration: str
|
||||
|
||||
|
||||
@with_config(ConfigDict(extra="allow"))
|
||||
class AppAgentModeResponse(TypedDict):
|
||||
enabled: bool
|
||||
strategy: NotRequired[PlanningStrategy | Literal["cot", "function-calling"] | None]
|
||||
tools: NotRequired[list[AppAgentToolResponse]]
|
||||
prompt: NotRequired[AppAgentPromptResponse | str | None]
|
||||
max_iteration: NotRequired[int]
|
||||
|
||||
|
||||
class AppChatPromptMessageResponse(TypedDict):
|
||||
text: str
|
||||
role: str
|
||||
|
||||
|
||||
class AppChatPromptConfigResponse(TypedDict, total=False):
|
||||
prompt: list[AppChatPromptMessageResponse]
|
||||
|
||||
|
||||
class AppCompletionPromptTextResponse(TypedDict):
|
||||
text: str
|
||||
|
||||
|
||||
class AppConversationHistoriesRoleResponse(TypedDict):
|
||||
user_prefix: str
|
||||
assistant_prefix: str
|
||||
|
||||
|
||||
class AppCompletionPromptConfigResponse(TypedDict, total=False):
|
||||
prompt: AppCompletionPromptTextResponse
|
||||
conversation_histories_role: AppConversationHistoriesRoleResponse
|
||||
|
||||
|
||||
class AppDatasetItemResponse(TypedDict):
|
||||
dataset: AppDatasetReferenceResponse
|
||||
|
||||
|
||||
class AppDatasetListResponse(TypedDict):
|
||||
datasets: list[AppDatasetItemResponse]
|
||||
strategy: NotRequired[str]
|
||||
|
||||
|
||||
class AppRerankingModelResponse(TypedDict, total=False):
|
||||
reranking_provider_name: str
|
||||
reranking_model_name: str
|
||||
|
||||
|
||||
class AppVectorSettingResponse(TypedDict):
|
||||
vector_weight: float
|
||||
embedding_provider_name: str
|
||||
embedding_model_name: str
|
||||
|
||||
|
||||
class AppKeywordSettingResponse(TypedDict):
|
||||
keyword_weight: float
|
||||
|
||||
|
||||
class AppWeightsResponse(TypedDict):
|
||||
vector_setting: AppVectorSettingResponse
|
||||
keyword_setting: AppKeywordSettingResponse
|
||||
weight_type: NotRequired[Literal["semantic_first", "keyword_first", "customized"]]
|
||||
|
||||
|
||||
@with_config(ConfigDict(extra="allow"))
|
||||
class AppMetadataConditionResponse(TypedDict):
|
||||
id: NotRequired[str]
|
||||
metadata_id: NotRequired[str]
|
||||
name: str
|
||||
comparison_operator: SupportedComparisonOperator
|
||||
value: NotRequired[str | list[str] | int | float | None]
|
||||
|
||||
|
||||
class AppMetadataFilteringConditionsResponse(TypedDict, total=False):
|
||||
logical_operator: Literal["and", "or"] | None
|
||||
conditions: list[AppMetadataConditionResponse] | None
|
||||
|
||||
|
||||
@with_config(ConfigDict(extra="allow"))
|
||||
class AppDatasetConfigsResponse(TypedDict):
|
||||
retrieval_model: Literal["single", "multiple"]
|
||||
datasets: NotRequired[AppDatasetListResponse]
|
||||
top_k: NotRequired[int]
|
||||
score_threshold: NotRequired[float | None]
|
||||
score_threshold_enabled: NotRequired[bool]
|
||||
reranking_model: NotRequired[AppRerankingModelResponse | None]
|
||||
weights: NotRequired[AppWeightsResponse | 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[AppModelSelectionResponse | None]
|
||||
metadata_filtering_conditions: NotRequired[AppMetadataFilteringConditionsResponse | None]
|
||||
|
||||
|
||||
class AppImageUploadResponse(TypedDict, total=False):
|
||||
enabled: bool
|
||||
number_limits: int
|
||||
detail: Literal["low", "high"] | None
|
||||
transfer_methods: list[FileTransferMethod]
|
||||
|
||||
|
||||
class AppFileUploadResponse(TypedDict, total=False):
|
||||
image: AppImageUploadResponse
|
||||
enabled: bool
|
||||
allowed_file_types: list[FileType]
|
||||
allowed_file_extensions: list[str]
|
||||
allowed_file_upload_methods: list[FileTransferMethod]
|
||||
number_limits: int
|
||||
|
||||
|
||||
class AppModelConfigResponse(ResponseModel):
|
||||
opening_statement: str | None
|
||||
suggested_questions: list[str] = Field(
|
||||
validation_alias=AliasChoices("suggested_questions_list", "suggested_questions")
|
||||
)
|
||||
suggested_questions_after_answer: AppSuggestedQuestionsAfterAnswerResponse = Field(
|
||||
validation_alias=AliasChoices("suggested_questions_after_answer_dict", "suggested_questions_after_answer"),
|
||||
)
|
||||
speech_to_text: AppEnabledConfigResponse = Field(
|
||||
validation_alias=AliasChoices("speech_to_text_dict", "speech_to_text")
|
||||
)
|
||||
text_to_speech: AppTextToSpeechResponse = Field(
|
||||
validation_alias=AliasChoices("text_to_speech_dict", "text_to_speech")
|
||||
)
|
||||
retriever_resource: AppEnabledConfigResponse = Field(
|
||||
validation_alias=AliasChoices("retriever_resource_dict", "retriever_resource")
|
||||
)
|
||||
annotation_reply: AppAnnotationReplyEnabledResponse | AppAnnotationReplyDisabledResponse = Field(
|
||||
validation_alias=AliasChoices("annotation_reply_dict", "annotation_reply")
|
||||
)
|
||||
more_like_this: AppEnabledConfigResponse = Field(
|
||||
validation_alias=AliasChoices("more_like_this_dict", "more_like_this")
|
||||
)
|
||||
sensitive_word_avoidance: AppSensitiveWordAvoidanceResponse = Field(
|
||||
validation_alias=AliasChoices("sensitive_word_avoidance_dict", "sensitive_word_avoidance")
|
||||
)
|
||||
external_data_tools: list[AppEnabledExternalDataToolResponse | AppDisabledExternalDataToolResponse] = Field(
|
||||
validation_alias=AliasChoices("external_data_tools_list", "external_data_tools")
|
||||
)
|
||||
model: AppModelSelectionResponse = Field(validation_alias=AliasChoices("model_dict", "model"))
|
||||
user_input_form: list[AppUserInputFormResponse] = Field(
|
||||
validation_alias=AliasChoices("user_input_form_list", "user_input_form")
|
||||
)
|
||||
dataset_query_variable: str | None
|
||||
pre_prompt: str | None
|
||||
agent_mode: AppAgentModeResponse = Field(validation_alias=AliasChoices("agent_mode_dict", "agent_mode"))
|
||||
prompt_type: PromptType
|
||||
chat_prompt_config: AppChatPromptConfigResponse = Field(
|
||||
validation_alias=AliasChoices("chat_prompt_config_dict", "chat_prompt_config")
|
||||
)
|
||||
completion_prompt_config: AppCompletionPromptConfigResponse = Field(
|
||||
validation_alias=AliasChoices("completion_prompt_config_dict", "completion_prompt_config")
|
||||
)
|
||||
dataset_configs: AppDatasetConfigsResponse = Field(
|
||||
validation_alias=AliasChoices("dataset_configs_dict", "dataset_configs")
|
||||
)
|
||||
file_upload: AppFileUploadResponse = Field(validation_alias=AliasChoices("file_upload_dict", "file_upload"))
|
||||
created_by: str | None
|
||||
created_at: int
|
||||
updated_by: str | None
|
||||
updated_at: int
|
||||
|
||||
@field_validator("created_at", "updated_at", mode="before")
|
||||
@classmethod
|
||||
def _normalize_timestamp(cls, value: datetime | int | None) -> int | None:
|
||||
return to_timestamp(value)
|
||||
@@ -546,7 +546,7 @@ class AgentFeatureToggleConfig(AgentFlexibleConfig):
|
||||
class AgentTextToSpeechFeatureConfig(AgentFeatureToggleConfig):
|
||||
language: str | None = None
|
||||
voice: str | None = None
|
||||
autoPlay: str | None = None
|
||||
autoPlay: Literal["enabled", "disabled"] | None = None
|
||||
|
||||
|
||||
class AgentSuggestedQuestionsAfterAnswerModelConfig(AgentFlexibleConfig):
|
||||
|
||||
+19
-5
@@ -99,6 +99,13 @@ class EnabledConfig(TypedDict):
|
||||
enabled: bool
|
||||
|
||||
|
||||
class TextToSpeechConfig(TypedDict):
|
||||
enabled: bool
|
||||
voice: NotRequired[str]
|
||||
language: NotRequired[str]
|
||||
autoPlay: NotRequired[Literal["enabled", "disabled"]]
|
||||
|
||||
|
||||
class SuggestedQuestionsAfterAnswerModelConfig(TypedDict):
|
||||
provider: str
|
||||
name: str
|
||||
@@ -148,7 +155,7 @@ class AgentToolConfig(TypedDict):
|
||||
|
||||
class AgentModeConfig(TypedDict):
|
||||
enabled: bool
|
||||
strategy: str | None
|
||||
strategy: NotRequired[str | None]
|
||||
tools: list[AgentToolConfig | dict[str, Any]]
|
||||
prompt: str | None
|
||||
|
||||
@@ -175,6 +182,9 @@ class ExternalDataToolConfig(TypedDict):
|
||||
variable: str
|
||||
type: str
|
||||
config: dict[str, Any]
|
||||
label: NotRequired[str]
|
||||
icon: NotRequired[str]
|
||||
icon_background: NotRequired[str]
|
||||
|
||||
|
||||
class UserInputFormItemConfig(TypedDict):
|
||||
@@ -187,6 +197,9 @@ class UserInputFormItemConfig(TypedDict):
|
||||
default: NotRequired[str]
|
||||
type: NotRequired[str]
|
||||
config: NotRequired[dict[str, Any]]
|
||||
enabled: NotRequired[bool]
|
||||
icon: NotRequired[str]
|
||||
icon_background: NotRequired[str]
|
||||
|
||||
|
||||
# Each item is a single-key dict, e.g. {"text-input": UserInputFormItemConfig}
|
||||
@@ -202,6 +215,7 @@ class DatasetConfigs(TypedDict):
|
||||
reranking_model: NotRequired[dict[str, Any] | None]
|
||||
weights: NotRequired[dict[str, Any] | None]
|
||||
reranking_enabled: NotRequired[bool]
|
||||
reranking_enable: NotRequired[bool]
|
||||
reranking_mode: NotRequired[str]
|
||||
metadata_filtering_mode: NotRequired[str]
|
||||
metadata_model_config: NotRequired[dict[str, Any] | None]
|
||||
@@ -243,7 +257,7 @@ class AppModelConfigDict(TypedDict):
|
||||
suggested_questions: list[str]
|
||||
suggested_questions_after_answer: SuggestedQuestionsAfterAnswerConfig
|
||||
speech_to_text: EnabledConfig
|
||||
text_to_speech: EnabledConfig
|
||||
text_to_speech: TextToSpeechConfig
|
||||
retriever_resource: EnabledConfig
|
||||
annotation_reply: AnnotationReplyConfig
|
||||
more_like_this: EnabledConfig
|
||||
@@ -786,8 +800,8 @@ class AppModelConfig(TypeBase):
|
||||
return self._get_enabled_config(self.speech_to_text)
|
||||
|
||||
@property
|
||||
def text_to_speech_dict(self) -> EnabledConfig:
|
||||
return self._get_enabled_config(self.text_to_speech)
|
||||
def text_to_speech_dict(self) -> TextToSpeechConfig:
|
||||
return cast(TextToSpeechConfig, self._get_enabled_config(self.text_to_speech))
|
||||
|
||||
@property
|
||||
def retriever_resource_dict(self) -> EnabledConfig:
|
||||
@@ -843,7 +857,7 @@ class AppModelConfig(TypeBase):
|
||||
if self.dataset_configs:
|
||||
dataset_configs = json.loads(self.dataset_configs)
|
||||
if "retrieval_model" not in dataset_configs:
|
||||
return {"retrieval_model": "single"}
|
||||
return {**dataset_configs, "retrieval_model": "single"}
|
||||
else:
|
||||
return cast(DatasetConfigs, dataset_configs)
|
||||
return {
|
||||
|
||||
@@ -13670,41 +13670,41 @@ Model class for AI model.
|
||||
|
||||
| Name | Type | Description | Required |
|
||||
| ---- | ---- | ----------- | -------- |
|
||||
| access_mode | string | | No |
|
||||
| access_mode | [WebAppAccessMode](#webappaccessmode) | | Yes |
|
||||
| access_ready | boolean | | No |
|
||||
| api_base_url | string | | No |
|
||||
| api_base_url | string | | Yes |
|
||||
| app_id | string | | No |
|
||||
| backing_app_id | string | | No |
|
||||
| bound_agent_id | string | | No |
|
||||
| created_at | integer | | No |
|
||||
| created_by | string | | No |
|
||||
| created_at | integer | | Yes |
|
||||
| created_by | string | | Yes |
|
||||
| debug_conversation_has_messages | boolean | | No |
|
||||
| debug_conversation_id | string | | No |
|
||||
| debug_conversation_message_count | integer | | No |
|
||||
| deleted_tools | [ [DeletedTool](#deletedtool) ] | | No |
|
||||
| description | string | | No |
|
||||
| deleted_tools | [ [DeletedTool](#deletedtool) ] | | Yes |
|
||||
| description | string | | Yes |
|
||||
| enable_api | boolean | | Yes |
|
||||
| enable_site | boolean | | Yes |
|
||||
| hidden_app_backed | boolean | | No |
|
||||
| icon | string | | No |
|
||||
| icon_background | string | | No |
|
||||
| icon_type | string | | No |
|
||||
| icon | string | | Yes |
|
||||
| icon_background | string | | Yes |
|
||||
| icon_type | [IconType](#icontype) | | Yes |
|
||||
| icon_url | string | | Yes |
|
||||
| id | string | | Yes |
|
||||
| maintainer | string | | No |
|
||||
| max_active_requests | integer | | No |
|
||||
| mode | string | | Yes |
|
||||
| model_config | [AppModelConfigResponse](#appmodelconfigresponse) | | No |
|
||||
| maintainer | string | | Yes |
|
||||
| max_active_requests | integer | | Yes |
|
||||
| mode | [AppMode](#appmode) | | Yes |
|
||||
| model_config | [AppModelConfigResponse](#appmodelconfigresponse) | | Yes |
|
||||
| name | string | | Yes |
|
||||
| permission_keys | [ string ] | | Yes |
|
||||
| role | string | | No |
|
||||
| site | [AppDetailSiteResponse](#appdetailsiteresponse) | | No |
|
||||
| tags | [ [Tag](#tag) ] | | No |
|
||||
| tracing | | | No |
|
||||
| updated_at | integer | | No |
|
||||
| updated_by | string | | No |
|
||||
| use_icon_as_answer_icon | boolean | | No |
|
||||
| workflow | [WorkflowPartial](#workflowpartial) | | No |
|
||||
| site | [AppDetailSiteResponse](#appdetailsiteresponse) | | Yes |
|
||||
| tags | [ [Tag](#tag) ] | | Yes |
|
||||
| tracing | string | | Yes |
|
||||
| updated_at | integer | | Yes |
|
||||
| updated_by | string | | Yes |
|
||||
| use_icon_as_answer_icon | boolean | | Yes |
|
||||
| workflow | [WorkflowPartial](#workflowpartial) | | Yes |
|
||||
|
||||
#### AgentAppFeaturesPayload
|
||||
|
||||
@@ -13752,7 +13752,7 @@ default (the config form sends the full desired feature state on save).
|
||||
|
||||
| Name | Type | Description | Required |
|
||||
| ---- | ---- | ----------- | -------- |
|
||||
| access_mode | string | | No |
|
||||
| access_mode | [WebAppAccessMode](#webappaccessmode) | | No |
|
||||
| active_config_is_published | boolean | | No |
|
||||
| app_id | string | | No |
|
||||
| author_name | string | | No |
|
||||
@@ -13767,13 +13767,13 @@ default (the config form sends the full desired feature state on save).
|
||||
| hidden_app_backed | boolean | | No |
|
||||
| icon | string | | No |
|
||||
| icon_background | string | | No |
|
||||
| icon_type | string | | No |
|
||||
| icon_type | [IconType](#icontype) | | No |
|
||||
| icon_url | string | | Yes |
|
||||
| id | string | | Yes |
|
||||
| is_starred | boolean | | No |
|
||||
| maintainer | string | | No |
|
||||
| max_active_requests | integer | | No |
|
||||
| mode | string | | Yes |
|
||||
| mode | [AppMode](#appmode) | | Yes |
|
||||
| model_config | [ModelConfigPartial](#modelconfigpartial) | | No |
|
||||
| name | string | | Yes |
|
||||
| permission_keys | [ string ] | | Yes |
|
||||
@@ -15357,7 +15357,7 @@ Legacy Chat App model config used only for follow-up question generation.
|
||||
|
||||
| Name | Type | Description | Required |
|
||||
| ---- | ---- | ----------- | -------- |
|
||||
| autoPlay | string | | No |
|
||||
| autoPlay | string, <br>**Available values:** "disabled", "enabled" | | No |
|
||||
| enabled | boolean | | No |
|
||||
| language | string | | No |
|
||||
| voice | string | | No |
|
||||
@@ -15742,99 +15742,220 @@ This class is used to store the schema information of an api based tool.
|
||||
| app_id | string | | No |
|
||||
| items | [ [AccessMatrixItem](#accessmatrixitem) ] | | No |
|
||||
|
||||
#### AppAgentModeResponse
|
||||
|
||||
| Name | Type | Description | Required |
|
||||
| ---- | ---- | ----------- | -------- |
|
||||
| enabled | boolean | | Yes |
|
||||
| max_iteration | integer | | No |
|
||||
| prompt | [AppAgentPromptResponse](#appagentpromptresponse)<br>string | | No |
|
||||
| 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 |
|
||||
|
||||
#### AppAgentPromptResponse
|
||||
|
||||
| Name | Type | Description | Required |
|
||||
| ---- | ---- | ----------- | -------- |
|
||||
| first_prompt | string | | No |
|
||||
| next_iteration | string | | No |
|
||||
|
||||
#### AppAnnotationReplyDisabledResponse
|
||||
|
||||
| Name | Type | Description | Required |
|
||||
| ---- | ---- | ----------- | -------- |
|
||||
| enabled | boolean | | Yes |
|
||||
|
||||
#### AppAnnotationReplyEnabledResponse
|
||||
|
||||
| Name | Type | Description | Required |
|
||||
| ---- | ---- | ----------- | -------- |
|
||||
| embedding_model | [AppEmbeddingModelResponse](#appembeddingmodelresponse) | | Yes |
|
||||
| enabled | boolean | | Yes |
|
||||
| id | string | | Yes |
|
||||
| score_threshold | number | | Yes |
|
||||
|
||||
#### AppApiStatusPayload
|
||||
|
||||
| Name | Type | Description | Required |
|
||||
| ---- | ---- | ----------- | -------- |
|
||||
| enable_api | boolean | Enable or disable API | Yes |
|
||||
|
||||
#### AppChatPromptConfigResponse
|
||||
|
||||
| Name | Type | Description | Required |
|
||||
| ---- | ---- | ----------- | -------- |
|
||||
| prompt | [ [AppChatPromptMessageResponse](#appchatpromptmessageresponse) ] | | No |
|
||||
|
||||
#### AppChatPromptMessageResponse
|
||||
|
||||
| Name | Type | Description | Required |
|
||||
| ---- | ---- | ----------- | -------- |
|
||||
| role | string | | Yes |
|
||||
| text | string | | Yes |
|
||||
|
||||
#### AppCheckboxFormResponse
|
||||
|
||||
| Name | Type | Description | Required |
|
||||
| ---- | ---- | ----------- | -------- |
|
||||
| checkbox | [AppUserInputFormConfigResponse](#appuserinputformconfigresponse) | | Yes |
|
||||
|
||||
#### AppCompletionPromptConfigResponse
|
||||
|
||||
| Name | Type | Description | Required |
|
||||
| ---- | ---- | ----------- | -------- |
|
||||
| conversation_histories_role | [AppConversationHistoriesRoleResponse](#appconversationhistoriesroleresponse) | | No |
|
||||
| prompt | [AppCompletionPromptTextResponse](#appcompletionprompttextresponse) | | No |
|
||||
|
||||
#### AppCompletionPromptTextResponse
|
||||
|
||||
| Name | Type | Description | Required |
|
||||
| ---- | ---- | ----------- | -------- |
|
||||
| text | string | | Yes |
|
||||
|
||||
#### AppConversationHistoriesRoleResponse
|
||||
|
||||
| Name | Type | Description | Required |
|
||||
| ---- | ---- | ----------- | -------- |
|
||||
| assistant_prefix | string | | Yes |
|
||||
| user_prefix | string | | Yes |
|
||||
|
||||
#### AppDatasetConfigsResponse
|
||||
|
||||
| Name | Type | Description | Required |
|
||||
| ---- | ---- | ----------- | -------- |
|
||||
| datasets | [AppDatasetListResponse](#appdatasetlistresponse) | | No |
|
||||
| metadata_filtering_conditions | [AppMetadataFilteringConditionsResponse](#appmetadatafilteringconditionsresponse) | | No |
|
||||
| metadata_filtering_mode | string, <br>**Available values:** "automatic", "disabled", "manual" | *Enum:* `"automatic"`, `"disabled"`, `"manual"` | No |
|
||||
| metadata_model_config | [AppModelSelectionResponse](#appmodelselectionresponse) | | No |
|
||||
| reranking_enable | boolean | | No |
|
||||
| reranking_enabled | boolean | | No |
|
||||
| reranking_mode | [RerankMode](#rerankmode) | | No |
|
||||
| reranking_model | [AppRerankingModelResponse](#apprerankingmodelresponse) | | No |
|
||||
| retrieval_model | string, <br>**Available values:** "multiple", "single" | *Enum:* `"multiple"`, `"single"` | Yes |
|
||||
| score_threshold | number | | No |
|
||||
| score_threshold_enabled | boolean | | No |
|
||||
| top_k | integer | | No |
|
||||
| weights | [AppWeightsResponse](#appweightsresponse) | | No |
|
||||
|
||||
#### AppDatasetItemResponse
|
||||
|
||||
| Name | Type | Description | Required |
|
||||
| ---- | ---- | ----------- | -------- |
|
||||
| dataset | [AppDatasetReferenceResponse](#appdatasetreferenceresponse) | | Yes |
|
||||
|
||||
#### AppDatasetListResponse
|
||||
|
||||
| Name | Type | Description | Required |
|
||||
| ---- | ---- | ----------- | -------- |
|
||||
| datasets | [ [AppDatasetItemResponse](#appdatasetitemresponse) ] | | Yes |
|
||||
| strategy | string | | No |
|
||||
|
||||
#### AppDatasetReferenceResponse
|
||||
|
||||
| Name | Type | Description | Required |
|
||||
| ---- | ---- | ----------- | -------- |
|
||||
| enabled | boolean | | No |
|
||||
| id | string | | No |
|
||||
|
||||
#### AppDetail
|
||||
|
||||
| Name | Type | Description | Required |
|
||||
| ---- | ---- | ----------- | -------- |
|
||||
| access_mode | string | | No |
|
||||
| created_at | integer | | No |
|
||||
| created_by | string | | No |
|
||||
| description | string | | No |
|
||||
| access_mode | [WebAppAccessMode](#webappaccessmode) | | Yes |
|
||||
| created_at | integer | | Yes |
|
||||
| created_by | string | | Yes |
|
||||
| description | string | | Yes |
|
||||
| enable_api | boolean | | Yes |
|
||||
| enable_site | boolean | | Yes |
|
||||
| icon | string | | No |
|
||||
| icon_background | string | | No |
|
||||
| icon | string | | Yes |
|
||||
| icon_background | string | | Yes |
|
||||
| id | string | | Yes |
|
||||
| maintainer | string | | No |
|
||||
| mode | string | | Yes |
|
||||
| model_config | [AppModelConfigResponse](#appmodelconfigresponse) | | No |
|
||||
| maintainer | string | | Yes |
|
||||
| mode | [AppMode](#appmode) | | Yes |
|
||||
| model_config | [AppModelConfigResponse](#appmodelconfigresponse) | | Yes |
|
||||
| name | string | | Yes |
|
||||
| permission_keys | [ string ] | | No |
|
||||
| tags | [ [Tag](#tag) ] | | No |
|
||||
| tracing | | | No |
|
||||
| updated_at | integer | | No |
|
||||
| updated_by | string | | No |
|
||||
| use_icon_as_answer_icon | boolean | | No |
|
||||
| workflow | [WorkflowPartial](#workflowpartial) | | No |
|
||||
| permission_keys | [ string ] | | Yes |
|
||||
| tags | [ [Tag](#tag) ] | | Yes |
|
||||
| tracing | string | | Yes |
|
||||
| updated_at | integer | | Yes |
|
||||
| updated_by | string | | Yes |
|
||||
| use_icon_as_answer_icon | boolean | | Yes |
|
||||
| workflow | [WorkflowPartial](#workflowpartial) | | Yes |
|
||||
|
||||
#### AppDetailSiteResponse
|
||||
|
||||
| Name | Type | Description | Required |
|
||||
| ---- | ---- | ----------- | -------- |
|
||||
| access_token | string | | No |
|
||||
| app_base_url | string | | No |
|
||||
| chat_color_theme | string | | No |
|
||||
| chat_color_theme_inverted | boolean | | No |
|
||||
| code | string | | No |
|
||||
| copyright | string | | No |
|
||||
| created_at | integer | | No |
|
||||
| created_by | string | | No |
|
||||
| custom_disclaimer | string | | No |
|
||||
| customize_domain | string | | No |
|
||||
| customize_token_strategy | string | | No |
|
||||
| default_language | string | | No |
|
||||
| description | string | | No |
|
||||
| icon | string | | No |
|
||||
| icon_background | string | | No |
|
||||
| icon_type | string<br>[IconType](#icontype) | | No |
|
||||
| access_token | string | | Yes |
|
||||
| app_base_url | string | | Yes |
|
||||
| chat_color_theme | string | | Yes |
|
||||
| chat_color_theme_inverted | boolean | | Yes |
|
||||
| code | string | | Yes |
|
||||
| copyright | string | | Yes |
|
||||
| created_at | integer | | Yes |
|
||||
| created_by | string | | Yes |
|
||||
| custom_disclaimer | string | | Yes |
|
||||
| customize_domain | string | | Yes |
|
||||
| customize_token_strategy | [CustomizeTokenStrategy](#customizetokenstrategy) | | Yes |
|
||||
| default_language | string | | Yes |
|
||||
| description | string | | Yes |
|
||||
| icon | string | | Yes |
|
||||
| icon_background | string | | Yes |
|
||||
| icon_type | [IconType](#icontype) | | Yes |
|
||||
| icon_url | string | | Yes |
|
||||
| input_placeholder | string | | No |
|
||||
| privacy_policy | string | | No |
|
||||
| prompt_public | boolean | | No |
|
||||
| show_workflow_steps | boolean | | No |
|
||||
| title | string | | No |
|
||||
| updated_at | integer | | No |
|
||||
| updated_by | string | | No |
|
||||
| use_icon_as_answer_icon | boolean | | No |
|
||||
| input_placeholder | string | | Yes |
|
||||
| privacy_policy | string | | Yes |
|
||||
| prompt_public | boolean | | Yes |
|
||||
| show_workflow_steps | boolean | | Yes |
|
||||
| title | string | | Yes |
|
||||
| updated_at | integer | | Yes |
|
||||
| updated_by | string | | Yes |
|
||||
| use_icon_as_answer_icon | boolean | | Yes |
|
||||
|
||||
#### AppDetailWithSite
|
||||
|
||||
| Name | Type | Description | Required |
|
||||
| ---- | ---- | ----------- | -------- |
|
||||
| access_mode | string | | No |
|
||||
| api_base_url | string | | No |
|
||||
| app_id | string | | No |
|
||||
| bound_agent_id | string | | No |
|
||||
| created_at | integer | | No |
|
||||
| created_by | string | | No |
|
||||
| deleted_tools | [ [DeletedTool](#deletedtool) ] | | No |
|
||||
| description | string | | No |
|
||||
| access_mode | [WebAppAccessMode](#webappaccessmode) | | Yes |
|
||||
| api_base_url | string | | Yes |
|
||||
| app_id | string | | Yes |
|
||||
| bound_agent_id | string | | Yes |
|
||||
| created_at | integer | | Yes |
|
||||
| created_by | string | | Yes |
|
||||
| deleted_tools | [ [DeletedTool](#deletedtool) ] | | Yes |
|
||||
| description | string | | Yes |
|
||||
| enable_api | boolean | | Yes |
|
||||
| enable_site | boolean | | Yes |
|
||||
| icon | string | | No |
|
||||
| icon_background | string | | No |
|
||||
| icon_type | string | | No |
|
||||
| icon | string | | Yes |
|
||||
| icon_background | string | | Yes |
|
||||
| icon_type | [IconType](#icontype) | | Yes |
|
||||
| icon_url | string | | Yes |
|
||||
| id | string | | Yes |
|
||||
| maintainer | string | | No |
|
||||
| max_active_requests | integer | | No |
|
||||
| mode | string | | Yes |
|
||||
| model_config | [AppModelConfigResponse](#appmodelconfigresponse) | | No |
|
||||
| maintainer | string | | Yes |
|
||||
| max_active_requests | integer | | Yes |
|
||||
| mode | [AppMode](#appmode) | | Yes |
|
||||
| model_config | [AppModelConfigResponse](#appmodelconfigresponse) | | Yes |
|
||||
| name | string | | Yes |
|
||||
| permission_keys | [ string ] | | No |
|
||||
| site | [AppDetailSiteResponse](#appdetailsiteresponse) | | No |
|
||||
| tags | [ [Tag](#tag) ] | | No |
|
||||
| tracing | | | No |
|
||||
| updated_at | integer | | No |
|
||||
| updated_by | string | | No |
|
||||
| use_icon_as_answer_icon | boolean | | No |
|
||||
| workflow | [WorkflowPartial](#workflowpartial) | | No |
|
||||
| permission_keys | [ string ] | | Yes |
|
||||
| site | [AppDetailSiteResponse](#appdetailsiteresponse) | | Yes |
|
||||
| tags | [ [Tag](#tag) ] | | Yes |
|
||||
| tracing | string | | Yes |
|
||||
| updated_at | integer | | Yes |
|
||||
| updated_by | string | | Yes |
|
||||
| use_icon_as_answer_icon | boolean | | Yes |
|
||||
| workflow | [WorkflowPartial](#workflowpartial) | | Yes |
|
||||
|
||||
#### AppDisabledExternalDataToolResponse
|
||||
|
||||
| Name | Type | Description | Required |
|
||||
| ---- | ---- | ----------- | -------- |
|
||||
| config | object | | No |
|
||||
| enabled | boolean | | Yes |
|
||||
| icon | string | | No |
|
||||
| icon_background | string | | No |
|
||||
| label | string | | No |
|
||||
| type | string | | No |
|
||||
| variable | string | | No |
|
||||
|
||||
#### AppDslVersionResponse
|
||||
|
||||
@@ -15842,6 +15963,31 @@ This class is used to store the schema information of an api based tool.
|
||||
| ---- | ---- | ----------- | -------- |
|
||||
| app_dsl_version | string | | Yes |
|
||||
|
||||
#### AppEmbeddingModelResponse
|
||||
|
||||
| Name | Type | Description | Required |
|
||||
| ---- | ---- | ----------- | -------- |
|
||||
| embedding_model_name | string | | Yes |
|
||||
| embedding_provider_name | string | | Yes |
|
||||
|
||||
#### AppEnabledConfigResponse
|
||||
|
||||
| Name | Type | Description | Required |
|
||||
| ---- | ---- | ----------- | -------- |
|
||||
| enabled | boolean | | Yes |
|
||||
|
||||
#### AppEnabledExternalDataToolResponse
|
||||
|
||||
| Name | Type | Description | Required |
|
||||
| ---- | ---- | ----------- | -------- |
|
||||
| config | object | | Yes |
|
||||
| enabled | boolean | | Yes |
|
||||
| icon | string | | No |
|
||||
| icon_background | string | | No |
|
||||
| label | string | | No |
|
||||
| type | string | | Yes |
|
||||
| variable | string | | Yes |
|
||||
|
||||
#### AppExportQuery
|
||||
|
||||
| Name | Type | Description | Required |
|
||||
@@ -15857,6 +16003,35 @@ This class is used to store the schema information of an api based tool.
|
||||
| ---- | ---- | ----------- | -------- |
|
||||
| data | string | | Yes |
|
||||
|
||||
#### AppExternalDataToolFormResponse
|
||||
|
||||
| Name | Type | Description | Required |
|
||||
| ---- | ---- | ----------- | -------- |
|
||||
| external_data_tool | [AppUserInputFormConfigResponse](#appuserinputformconfigresponse) | | Yes |
|
||||
|
||||
#### AppFileFormResponse
|
||||
|
||||
| Name | Type | Description | Required |
|
||||
| ---- | ---- | ----------- | -------- |
|
||||
| file | [AppUserInputFormConfigResponse](#appuserinputformconfigresponse) | | Yes |
|
||||
|
||||
#### AppFileListFormResponse
|
||||
|
||||
| Name | Type | Description | Required |
|
||||
| ---- | ---- | ----------- | -------- |
|
||||
| file-list | [AppUserInputFormConfigResponse](#appuserinputformconfigresponse) | | Yes |
|
||||
|
||||
#### AppFileUploadResponse
|
||||
|
||||
| Name | Type | Description | Required |
|
||||
| ---- | ---- | ----------- | -------- |
|
||||
| allowed_file_extensions | [ string ] | | No |
|
||||
| allowed_file_types | [ [FileType](#filetype) ] | | No |
|
||||
| allowed_file_upload_methods | [ [FileTransferMethod](#filetransfermethod) ] | | No |
|
||||
| enabled | boolean | | No |
|
||||
| image | [AppImageUploadResponse](#appimageuploadresponse) | | No |
|
||||
| number_limits | integer | | No |
|
||||
|
||||
#### AppIconPayload
|
||||
|
||||
| Name | Type | Description | Required |
|
||||
@@ -15865,6 +16040,15 @@ 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 |
|
||||
|
||||
#### AppImageUploadResponse
|
||||
|
||||
| Name | Type | Description | Required |
|
||||
| ---- | ---- | ----------- | -------- |
|
||||
| detail | string, <br>**Available values:** "high", "low" | | No |
|
||||
| enabled | boolean | | No |
|
||||
| number_limits | integer | | No |
|
||||
| transfer_methods | [ [FileTransferMethod](#filetransfermethod) ] | | No |
|
||||
|
||||
#### AppImportPayload
|
||||
|
||||
| Name | Type | Description | Required |
|
||||
@@ -15884,7 +16068,7 @@ This class is used to store the schema information of an api based tool.
|
||||
| Name | Type | Description | Required |
|
||||
| ---- | ---- | ----------- | -------- |
|
||||
| app_id | string | | No |
|
||||
| app_mode | string | | No |
|
||||
| app_mode | [AppMode](#appmode) | | No |
|
||||
| current_dsl_version | string | | Yes |
|
||||
| error | string | | No |
|
||||
| id | string | | Yes |
|
||||
@@ -15892,6 +16076,62 @@ This class is used to store the schema information of an api based tool.
|
||||
| status | [ImportStatus](#importstatus) | | Yes |
|
||||
| warnings | [ [DslImportWarning](#dslimportwarning) ] | | No |
|
||||
|
||||
#### AppJsonObjectFormResponse
|
||||
|
||||
| Name | Type | Description | Required |
|
||||
| ---- | ---- | ----------- | -------- |
|
||||
| json_object | [AppUserInputFormConfigResponse](#appuserinputformconfigresponse) | | Yes |
|
||||
|
||||
#### AppKeywordSettingResponse
|
||||
|
||||
| Name | Type | Description | Required |
|
||||
| ---- | ---- | ----------- | -------- |
|
||||
| keyword_weight | number | | Yes |
|
||||
|
||||
#### AppLegacyCurrentDatetimeToolResponse
|
||||
|
||||
| Name | Type | Description | Required |
|
||||
| ---- | ---- | ----------- | -------- |
|
||||
| current_datetime | object | | Yes |
|
||||
|
||||
#### AppLegacyDatasetToolResponse
|
||||
|
||||
| Name | Type | Description | Required |
|
||||
| ---- | ---- | ----------- | -------- |
|
||||
| dataset | [AppDatasetReferenceResponse](#appdatasetreferenceresponse) | | Yes |
|
||||
|
||||
#### AppLegacyGoogleSearchToolResponse
|
||||
|
||||
| Name | Type | Description | Required |
|
||||
| ---- | ---- | ----------- | -------- |
|
||||
| google_search | object | | Yes |
|
||||
|
||||
#### AppLegacySensitiveWordToolResponse
|
||||
|
||||
| Name | Type | Description | Required |
|
||||
| ---- | ---- | ----------- | -------- |
|
||||
| canned_response | string | | Yes |
|
||||
| enabled | boolean | | Yes |
|
||||
| words | [ string ] | | Yes |
|
||||
|
||||
#### AppLegacySensitiveWordToolResponseItem
|
||||
|
||||
| Name | Type | Description | Required |
|
||||
| ---- | ---- | ----------- | -------- |
|
||||
| sensitive-word-avoidance | [AppLegacySensitiveWordToolResponse](#applegacysensitivewordtoolresponse) | | Yes |
|
||||
|
||||
#### AppLegacyWebReaderToolResponse
|
||||
|
||||
| Name | Type | Description | Required |
|
||||
| ---- | ---- | ----------- | -------- |
|
||||
| web_reader | object | | Yes |
|
||||
|
||||
#### AppLegacyWikipediaToolResponse
|
||||
|
||||
| Name | Type | Description | Required |
|
||||
| ---- | ---- | ----------- | -------- |
|
||||
| wikipedia | object | | Yes |
|
||||
|
||||
#### AppListQuery
|
||||
|
||||
| Name | Type | Description | Required |
|
||||
@@ -15926,6 +16166,23 @@ AppMCPServer Status Enum
|
||||
| ---- | ---- | ----------- | -------- |
|
||||
| AppMCPServerStatus | string | AppMCPServer Status Enum | |
|
||||
|
||||
#### AppMetadataConditionResponse
|
||||
|
||||
| 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 |
|
||||
|
||||
#### AppMetadataFilteringConditionsResponse
|
||||
|
||||
| Name | Type | Description | Required |
|
||||
| ---- | ---- | ----------- | -------- |
|
||||
| conditions | [ [AppMetadataConditionResponse](#appmetadataconditionresponse) ] | | No |
|
||||
| logical_operator | string, <br>**Available values:** "and", "or" | | No |
|
||||
|
||||
#### AppMode
|
||||
|
||||
| Name | Type | Description | Required |
|
||||
@@ -15936,30 +16193,39 @@ AppMCPServer Status Enum
|
||||
|
||||
| Name | Type | Description | Required |
|
||||
| ---- | ---- | ----------- | -------- |
|
||||
| agent_mode | | | No |
|
||||
| annotation_reply | | | No |
|
||||
| chat_prompt_config | | | No |
|
||||
| completion_prompt_config | | | No |
|
||||
| created_at | integer | | No |
|
||||
| created_by | string | | No |
|
||||
| dataset_configs | | | No |
|
||||
| dataset_query_variable | string | | No |
|
||||
| external_data_tools | | | No |
|
||||
| file_upload | | | No |
|
||||
| model | | | No |
|
||||
| more_like_this | | | No |
|
||||
| opening_statement | string | | No |
|
||||
| pre_prompt | string | | No |
|
||||
| prompt_type | string | | No |
|
||||
| retriever_resource | | | No |
|
||||
| sensitive_word_avoidance | | | No |
|
||||
| speech_to_text | | | No |
|
||||
| suggested_questions | | | No |
|
||||
| suggested_questions_after_answer | | | No |
|
||||
| text_to_speech | | | No |
|
||||
| updated_at | integer | | No |
|
||||
| updated_by | string | | No |
|
||||
| user_input_form | | | No |
|
||||
| agent_mode | [AppAgentModeResponse](#appagentmoderesponse) | | Yes |
|
||||
| annotation_reply | [AppAnnotationReplyEnabledResponse](#appannotationreplyenabledresponse)<br>[AppAnnotationReplyDisabledResponse](#appannotationreplydisabledresponse) | | Yes |
|
||||
| chat_prompt_config | [AppChatPromptConfigResponse](#appchatpromptconfigresponse) | | Yes |
|
||||
| completion_prompt_config | [AppCompletionPromptConfigResponse](#appcompletionpromptconfigresponse) | | Yes |
|
||||
| created_at | integer | | Yes |
|
||||
| created_by | string | | Yes |
|
||||
| dataset_configs | [AppDatasetConfigsResponse](#appdatasetconfigsresponse) | | Yes |
|
||||
| dataset_query_variable | string | | Yes |
|
||||
| external_data_tools | [ [AppEnabledExternalDataToolResponse](#appenabledexternaldatatoolresponse)<br>[AppDisabledExternalDataToolResponse](#appdisabledexternaldatatoolresponse) ] | | Yes |
|
||||
| file_upload | [AppFileUploadResponse](#appfileuploadresponse) | | Yes |
|
||||
| model | [AppModelSelectionResponse](#appmodelselectionresponse) | | Yes |
|
||||
| more_like_this | [AppEnabledConfigResponse](#appenabledconfigresponse) | | Yes |
|
||||
| opening_statement | string | | Yes |
|
||||
| pre_prompt | string | | Yes |
|
||||
| prompt_type | [PromptType](#prompttype) | | Yes |
|
||||
| retriever_resource | [AppEnabledConfigResponse](#appenabledconfigresponse) | | Yes |
|
||||
| sensitive_word_avoidance | [AppSensitiveWordAvoidanceResponse](#appsensitivewordavoidanceresponse) | | Yes |
|
||||
| speech_to_text | [AppEnabledConfigResponse](#appenabledconfigresponse) | | Yes |
|
||||
| suggested_questions | [ string ] | | Yes |
|
||||
| suggested_questions_after_answer | [AppSuggestedQuestionsAfterAnswerResponse](#appsuggestedquestionsafteranswerresponse) | | Yes |
|
||||
| text_to_speech | [AppTextToSpeechResponse](#apptexttospeechresponse) | | Yes |
|
||||
| updated_at | integer | | Yes |
|
||||
| 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 |
|
||||
|
||||
#### AppModelSelectionResponse
|
||||
|
||||
| Name | Type | Description | Required |
|
||||
| ---- | ---- | ----------- | -------- |
|
||||
| completion_params | object | | No |
|
||||
| mode | [LLMMode](#llmmode)<br>string | | No |
|
||||
| name | string | | No |
|
||||
| provider | string | | No |
|
||||
|
||||
#### AppNamePayload
|
||||
|
||||
@@ -15967,6 +16233,12 @@ AppMCPServer Status Enum
|
||||
| ---- | ---- | ----------- | -------- |
|
||||
| name | string | Name to check | Yes |
|
||||
|
||||
#### AppNumberFormResponse
|
||||
|
||||
| Name | Type | Description | Required |
|
||||
| ---- | ---- | ----------- | -------- |
|
||||
| number | [AppUserInputFormConfigResponse](#appuserinputformconfigresponse) | | Yes |
|
||||
|
||||
#### AppPagination
|
||||
|
||||
| Name | Type | Description | Required |
|
||||
@@ -15977,11 +16249,17 @@ AppMCPServer Status Enum
|
||||
| page | integer | | Yes |
|
||||
| total | integer | | Yes |
|
||||
|
||||
#### AppParagraphFormResponse
|
||||
|
||||
| Name | Type | Description | Required |
|
||||
| ---- | ---- | ----------- | -------- |
|
||||
| paragraph | [AppUserInputFormConfigResponse](#appuserinputformconfigresponse) | | Yes |
|
||||
|
||||
#### AppPartial
|
||||
|
||||
| Name | Type | Description | Required |
|
||||
| ---- | ---- | ----------- | -------- |
|
||||
| access_mode | string | | No |
|
||||
| access_mode | [WebAppAccessMode](#webappaccessmode) | | No |
|
||||
| app_id | string | | No |
|
||||
| author_name | string | | No |
|
||||
| bound_agent_id | string | | No |
|
||||
@@ -15992,13 +16270,13 @@ AppMCPServer Status Enum
|
||||
| has_draft_trigger | boolean | | No |
|
||||
| icon | string | | No |
|
||||
| icon_background | string | | No |
|
||||
| icon_type | string | | No |
|
||||
| icon_type | [IconType](#icontype) | | No |
|
||||
| icon_url | string | | Yes |
|
||||
| id | string | | Yes |
|
||||
| is_starred | boolean | | No |
|
||||
| maintainer | string | | No |
|
||||
| max_active_requests | integer | | No |
|
||||
| mode | string | | Yes |
|
||||
| mode | [AppMode](#appmode) | | Yes |
|
||||
| model_config | [ModelConfigPartial](#modelconfigpartial) | | No |
|
||||
| name | string | | Yes |
|
||||
| permission_keys | [ string ] | | No |
|
||||
@@ -16008,12 +16286,50 @@ AppMCPServer Status Enum
|
||||
| use_icon_as_answer_icon | boolean | | No |
|
||||
| workflow | [WorkflowPartial](#workflowpartial) | | No |
|
||||
|
||||
#### AppProviderAgentToolResponse
|
||||
|
||||
| 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 |
|
||||
|
||||
#### AppRerankingModelResponse
|
||||
|
||||
| Name | Type | Description | Required |
|
||||
| ---- | ---- | ----------- | -------- |
|
||||
| reranking_model_name | string | | No |
|
||||
| reranking_provider_name | string | | No |
|
||||
|
||||
#### AppSelectFormResponse
|
||||
|
||||
| Name | Type | Description | Required |
|
||||
| ---- | ---- | ----------- | -------- |
|
||||
| select | [AppUserInputFormConfigResponse](#appuserinputformconfigresponse) | | Yes |
|
||||
|
||||
#### AppSelectorScope
|
||||
|
||||
| Name | Type | Description | Required |
|
||||
| ---- | ---- | ----------- | -------- |
|
||||
| AppSelectorScope | string | | |
|
||||
|
||||
#### AppSensitiveWordAvoidanceResponse
|
||||
|
||||
| Name | Type | Description | Required |
|
||||
| ---- | ---- | ----------- | -------- |
|
||||
| config | object | | No |
|
||||
| configs | [ [JsonValue](#jsonvalue) ] | | No |
|
||||
| enabled | boolean | | Yes |
|
||||
| type | string | | No |
|
||||
|
||||
#### AppSiteResponse
|
||||
|
||||
| Name | Type | Description | Required |
|
||||
@@ -16063,6 +16379,29 @@ AppMCPServer Status Enum
|
||||
| title | string | | No |
|
||||
| use_icon_as_answer_icon | boolean | | No |
|
||||
|
||||
#### AppSuggestedQuestionsAfterAnswerResponse
|
||||
|
||||
| Name | Type | Description | Required |
|
||||
| ---- | ---- | ----------- | -------- |
|
||||
| enabled | boolean | | Yes |
|
||||
| model | [AppModelSelectionResponse](#appmodelselectionresponse) | | No |
|
||||
| prompt | string | | No |
|
||||
|
||||
#### AppTextInputFormResponse
|
||||
|
||||
| Name | Type | Description | Required |
|
||||
| ---- | ---- | ----------- | -------- |
|
||||
| text-input | [AppUserInputFormConfigResponse](#appuserinputformconfigresponse) | | Yes |
|
||||
|
||||
#### AppTextToSpeechResponse
|
||||
|
||||
| Name | Type | Description | Required |
|
||||
| ---- | ---- | ----------- | -------- |
|
||||
| autoPlay | string, <br>**Available values:** "disabled", "enabled" | *Enum:* `"disabled"`, `"enabled"` | No |
|
||||
| enabled | boolean | | Yes |
|
||||
| language | string | | No |
|
||||
| voice | string | | No |
|
||||
|
||||
#### AppTracePayload
|
||||
|
||||
| Name | Type | Description | Required |
|
||||
@@ -16077,6 +16416,28 @@ AppMCPServer Status Enum
|
||||
| enabled | boolean | | No |
|
||||
| tracing_provider | string | | No |
|
||||
|
||||
#### AppUserInputFormConfigResponse
|
||||
|
||||
| Name | Type | Description | Required |
|
||||
| ---- | ---- | ----------- | -------- |
|
||||
| allowed_file_extensions | [ string ] | | No |
|
||||
| allowed_file_types | [ [FileType](#filetype) ] | | No |
|
||||
| allowed_file_upload_methods | [ [FileTransferMethod](#filetransfermethod) ] | | No |
|
||||
| config | object | | No |
|
||||
| default | [JsonValue](#jsonvalue) | | 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 |
|
||||
|
||||
#### AppVariableConfig
|
||||
|
||||
| Name | Type | Description | Required |
|
||||
@@ -16086,6 +16447,22 @@ AppMCPServer Status Enum
|
||||
| required | boolean | | No |
|
||||
| type | string | | Yes |
|
||||
|
||||
#### AppVectorSettingResponse
|
||||
|
||||
| Name | Type | Description | Required |
|
||||
| ---- | ---- | ----------- | -------- |
|
||||
| embedding_model_name | string | | Yes |
|
||||
| embedding_provider_name | string | | Yes |
|
||||
| vector_weight | number | | Yes |
|
||||
|
||||
#### AppWeightsResponse
|
||||
|
||||
| Name | Type | Description | Required |
|
||||
| ---- | ---- | ----------- | -------- |
|
||||
| keyword_setting | [AppKeywordSettingResponse](#appkeywordsettingresponse) | | Yes |
|
||||
| vector_setting | [AppVectorSettingResponse](#appvectorsettingresponse) | | Yes |
|
||||
| weight_type | string, <br>**Available values:** "customized", "keyword_first", "semantic_first" | *Enum:* `"customized"`, `"keyword_first"`, `"semantic_first"` | No |
|
||||
|
||||
#### AudioBinaryResponse
|
||||
|
||||
| Name | Type | Description | Required |
|
||||
@@ -16977,6 +17354,14 @@ Model class for provider custom model configuration.
|
||||
| model_type | [ModelType](#modeltype) | | Yes |
|
||||
| unadded_to_model_list | boolean | | No |
|
||||
|
||||
#### CustomizeTokenStrategy
|
||||
|
||||
Site token customization strategy
|
||||
|
||||
| Name | Type | Description | Required |
|
||||
| ---- | ---- | ----------- | -------- |
|
||||
| CustomizeTokenStrategy | string | Site token customization strategy | |
|
||||
|
||||
#### CustomizedPipelineTemplatePayload
|
||||
|
||||
| Name | Type | Description | Required |
|
||||
@@ -19050,7 +19435,7 @@ How Dify forwards the end-user's identity to an MCP server.
|
||||
| Name | Type | Description | Required |
|
||||
| ---- | ---- | ----------- | -------- |
|
||||
| app_id | string | | No |
|
||||
| app_mode | string | | No |
|
||||
| app_mode | [AppMode](#appmode) | | No |
|
||||
| current_dsl_version | string, <br>**Default:** 0.7.0 | | No |
|
||||
| error | string | | No |
|
||||
| id | string | | Yes |
|
||||
@@ -19707,7 +20092,7 @@ Metadata operation data
|
||||
| ---- | ---- | ----------- | -------- |
|
||||
| created_at | integer | | No |
|
||||
| created_by | string | | No |
|
||||
| model | | | No |
|
||||
| model | [AppModelSelectionResponse](#appmodelselectionresponse) | | No |
|
||||
| pre_prompt | string | | No |
|
||||
| updated_at | integer | | No |
|
||||
| updated_by | string | | No |
|
||||
@@ -20755,6 +21140,12 @@ Shared permission levels for resources (datasets, credentials, etc.)
|
||||
| unit | string | | No |
|
||||
| variable | string | | Yes |
|
||||
|
||||
#### PlanningStrategy
|
||||
|
||||
| Name | Type | Description | Required |
|
||||
| ---- | ---- | ----------- | -------- |
|
||||
| PlanningStrategy | string | | |
|
||||
|
||||
#### PluginAutoUpgradeChangeResponse
|
||||
|
||||
| Name | Type | Description | Required |
|
||||
@@ -21263,6 +21654,14 @@ Dataset Process Rule Mode
|
||||
| mode | [ProcessRuleMode](#processrulemode) | | Yes |
|
||||
| rules | [Rule](#rule) | | No |
|
||||
|
||||
#### PromptType
|
||||
|
||||
Prompt configuration type
|
||||
|
||||
| Name | Type | Description | Required |
|
||||
| ---- | ---- | ----------- | -------- |
|
||||
| PromptType | string | Prompt configuration type | |
|
||||
|
||||
#### ProviderConfig
|
||||
|
||||
Model class for common provider settings like credentials
|
||||
@@ -21755,6 +22154,12 @@ Resource types understood by access policies.
|
||||
| request | object | The request of the request log | Yes |
|
||||
| response | object | The response of the request log | Yes |
|
||||
|
||||
#### RerankMode
|
||||
|
||||
| Name | Type | Description | Required |
|
||||
| ---- | ---- | ----------- | -------- |
|
||||
| RerankMode | string | | |
|
||||
|
||||
#### RerankingModel
|
||||
|
||||
| Name | Type | Description | Required |
|
||||
@@ -24022,6 +24427,12 @@ in form definition, or a variable while the workflow is running.
|
||||
| is_valid | boolean | | Yes |
|
||||
| token | string | | Yes |
|
||||
|
||||
#### WebAppAccessMode
|
||||
|
||||
| Name | Type | Description | Required |
|
||||
| ---- | ---- | ----------- | -------- |
|
||||
| WebAppAccessMode | string | | |
|
||||
|
||||
#### WebAppAuthModel
|
||||
|
||||
| Name | Type | Description | Required |
|
||||
@@ -25112,7 +25523,7 @@ Query parameters for workflow runs.
|
||||
|
||||
| Name | Type | Description | Required |
|
||||
| ---- | ---- | ----------- | -------- |
|
||||
| autoPlay | string | | No |
|
||||
| autoPlay | string, <br>**Available values:** "disabled", "enabled" | | No |
|
||||
| enabled | boolean | | No |
|
||||
| language | string | | No |
|
||||
| voice | string | | No |
|
||||
|
||||
@@ -694,7 +694,7 @@ Request body for POST /workspaces/<workspace_id>/apps/imports.
|
||||
| Name | Type | Description | Required |
|
||||
| ---- | ---- | ----------- | -------- |
|
||||
| app_id | string | | No |
|
||||
| app_mode | string | | No |
|
||||
| app_mode | [AppMode](#appmode) | | No |
|
||||
| current_dsl_version | string, <br>**Default:** 0.7.0 | | No |
|
||||
| error | string | | No |
|
||||
| hints | [ [Hint](#hint) ] | Next steps the caller can take | No |
|
||||
@@ -971,7 +971,7 @@ A next step the caller can hand straight to `call <op> --input <input>`.
|
||||
| Name | Type | Description | Required |
|
||||
| ---- | ---- | ----------- | -------- |
|
||||
| app_id | string | | No |
|
||||
| app_mode | string | | No |
|
||||
| app_mode | [AppMode](#appmode) | | No |
|
||||
| current_dsl_version | string, <br>**Default:** 0.7.0 | | No |
|
||||
| error | string | | No |
|
||||
| id | string | | Yes |
|
||||
|
||||
@@ -8,6 +8,7 @@ from typing import BinaryIO, Literal, Protocol
|
||||
from uuid import UUID, uuid4
|
||||
|
||||
from machinery.context import RequestContext
|
||||
from models.model import AppMode
|
||||
from services.agent.errors import InvalidRosterAgentPackageError
|
||||
from services.agent.roster_package_entities import RosterAgentPackageExport
|
||||
from services.entities.app_entities import (
|
||||
@@ -228,7 +229,7 @@ class ConsoleAppService:
|
||||
id=str(uuid4()),
|
||||
status=ImportStatus.COMPLETED_WITH_WARNINGS if result.warnings else ImportStatus.COMPLETED,
|
||||
app_id=result.app_id,
|
||||
app_mode="agent",
|
||||
app_mode=AppMode.AGENT,
|
||||
warnings=result.warnings,
|
||||
)
|
||||
|
||||
@@ -300,7 +301,7 @@ class ConsoleAppService:
|
||||
def update(self, context: RequestContext, app_id: str, params: UpdateAppParams) -> AppRecord:
|
||||
app = self._apps.update(context, app_id, params)
|
||||
self._lifecycle.updated(context, app)
|
||||
return self._lifecycle.present(context, app)
|
||||
return self.get(context, app_id)
|
||||
|
||||
def rename(self, context: RequestContext, app_id: str, name: str) -> AppRecord:
|
||||
app = self._apps.rename(context, app_id, name)
|
||||
|
||||
@@ -17,6 +17,10 @@ from sqlalchemy.orm import Session
|
||||
|
||||
from configs import dify_config
|
||||
from constants.dsl_version import CURRENT_APP_DSL_VERSION
|
||||
from core.app.app_config.features.suggested_questions_after_answer.manager import (
|
||||
SuggestedQuestionsAfterAnswerConfigManager,
|
||||
)
|
||||
from core.app.app_config.features.text_to_speech.manager import TextToSpeechConfigManager
|
||||
from core.file import remote_fetcher
|
||||
from core.plugin.entities.plugin import PluginDependency
|
||||
from core.rbac import RBACPermission, RBACResourceScope
|
||||
@@ -694,6 +698,8 @@ class AppDslService:
|
||||
model_config = data.get("model_config")
|
||||
if not model_config or not isinstance(model_config, dict):
|
||||
raise ValueError("Missing model_config for chat/agent-chat/completion app")
|
||||
SuggestedQuestionsAfterAnswerConfigManager.validate_optional_fields(model_config)
|
||||
TextToSpeechConfigManager.validate_optional_fields(model_config)
|
||||
# Initialize or update model config
|
||||
app_model_config = (
|
||||
self._session.get(AppModelConfig, app.app_model_config_id) if app.app_model_config_id else None
|
||||
|
||||
+32
-44
@@ -1,9 +1,10 @@
|
||||
import json
|
||||
import logging
|
||||
from collections.abc import Callable, Mapping, Sequence
|
||||
from copy import deepcopy
|
||||
from dataclasses import dataclass
|
||||
from datetime import datetime
|
||||
from typing import Any, NotRequired, TypedDict, cast, override
|
||||
from typing import Any, NotRequired, TypedDict, cast
|
||||
|
||||
import sqlalchemy as sa
|
||||
from pydantic import JsonValue
|
||||
@@ -120,9 +121,13 @@ class AppModelConfigResponseView:
|
||||
class AppResponseView:
|
||||
"""Expose App response properties through one caller-owned database session."""
|
||||
|
||||
def __init__(self, app: App, *, session: Session) -> None:
|
||||
def __init__(
|
||||
self, app: App, *, session: Session, account: Account | None = None, access_mode: str | None = None
|
||||
) -> None:
|
||||
self._app = app
|
||||
self._session = session
|
||||
self._account = account
|
||||
self._access_mode = access_mode
|
||||
|
||||
def __getattr__(self, name: str) -> Any:
|
||||
return getattr(self._app, name) # guard-ignore: no-new-getattr -- delegates model fields
|
||||
@@ -140,6 +145,19 @@ class AppResponseView:
|
||||
app_model_config = self._app.app_model_config_with_session(session=self._session)
|
||||
if app_model_config is None:
|
||||
return None
|
||||
if self._account is not None and (
|
||||
self._app.mode == AppMode.AGENT_CHAT or self._app.is_agent_with_session(session=self._session)
|
||||
):
|
||||
tenant_id = self._account.current_tenant_id
|
||||
assert tenant_id is not None
|
||||
masked_agent_mode = mask_agent_tool_parameters(
|
||||
agent_mode=cast(Mapping[str, JsonValue], app_model_config.agent_mode_dict),
|
||||
app_id=self._app.id,
|
||||
tenant_id=tenant_id,
|
||||
user_id=self._account.id,
|
||||
)
|
||||
app_model_config = deepcopy(app_model_config)
|
||||
app_model_config.agent_mode = json.dumps(masked_agent_mode)
|
||||
return AppModelConfigResponseView(app_model_config, session=self._session)
|
||||
|
||||
@property
|
||||
@@ -154,6 +172,18 @@ class AppResponseView:
|
||||
def mode_compatible_with_agent(self) -> str:
|
||||
return self._app.mode_compatible_with_agent_with_session(session=self._session)
|
||||
|
||||
@property
|
||||
def access_mode(self) -> str | None:
|
||||
return self._access_mode
|
||||
|
||||
@property
|
||||
def permission_keys(self) -> list[str]:
|
||||
return []
|
||||
|
||||
@property
|
||||
def app_id(self) -> str | None:
|
||||
return None
|
||||
|
||||
@property
|
||||
def deleted_tools(self) -> list[Any]:
|
||||
return self._app.deleted_tools_with_session(session=self._session)
|
||||
@@ -580,48 +610,6 @@ class AppService:
|
||||
if dify_config.DEPLOYMENT_EDITION == DeploymentEdition.CLOUD:
|
||||
BillingService.clean_billing_info_cache(app.tenant_id)
|
||||
|
||||
def get_app(self, app: App, *, session: Session) -> App:
|
||||
"""
|
||||
Get App
|
||||
"""
|
||||
assert isinstance(current_user, Account)
|
||||
assert current_user.current_tenant_id is not None
|
||||
# get original app model config
|
||||
if app.mode == AppMode.AGENT_CHAT or app.is_agent_with_session(session=session):
|
||||
model_config = app.app_model_config_with_session(session=session)
|
||||
if not model_config:
|
||||
return app
|
||||
agent_mode = mask_agent_tool_parameters(
|
||||
agent_mode=cast(Mapping[str, JsonValue], model_config.agent_mode_dict),
|
||||
app_id=app.id,
|
||||
tenant_id=current_user.current_tenant_id,
|
||||
user_id=current_user.id,
|
||||
)
|
||||
|
||||
# override agent mode
|
||||
if model_config:
|
||||
model_config.agent_mode = json.dumps(agent_mode)
|
||||
|
||||
class ModifiedApp(App):
|
||||
"""
|
||||
Modified App class
|
||||
"""
|
||||
|
||||
def __init__(self, app):
|
||||
self.__dict__.update(app.__dict__)
|
||||
|
||||
@override
|
||||
def app_model_config_with_session(self, *, session: Session) -> AppModelConfig | None:
|
||||
# Hand back the in-memory config the masking pass above produced, and
|
||||
# deliberately ignore `session`: re-reading the row here would undo the
|
||||
# masking. Response paths resolve the config through this accessor
|
||||
# (`AppResponseView.app_model_config`), so the override has to sit here.
|
||||
return model_config
|
||||
|
||||
app = ModifiedApp(app)
|
||||
|
||||
return app
|
||||
|
||||
class ArgsDict(TypedDict):
|
||||
name: str
|
||||
description: str
|
||||
|
||||
@@ -10,7 +10,6 @@ import logging
|
||||
import uuid
|
||||
from collections.abc import Iterable
|
||||
from dataclasses import dataclass
|
||||
from typing import cast
|
||||
|
||||
from flask import Response, stream_with_context
|
||||
from sqlalchemy import select
|
||||
@@ -269,7 +268,7 @@ class AudioService:
|
||||
if not text_to_speech_dict.get("enabled"):
|
||||
raise ValueError("TTS is not enabled")
|
||||
|
||||
voice = cast(str | None, text_to_speech_dict.get("voice"))
|
||||
voice = text_to_speech_dict.get("voice")
|
||||
|
||||
return PreparedTextToAudio(text=text, voice=voice)
|
||||
|
||||
|
||||
@@ -82,7 +82,7 @@ class Import(BaseModel):
|
||||
id: str
|
||||
status: ImportStatus
|
||||
app_id: str | None = None
|
||||
app_mode: str | None = None
|
||||
app_mode: AppMode | None = None
|
||||
permission_keys: list[str] = Field(default_factory=list)
|
||||
current_dsl_version: str = CURRENT_APP_DSL_VERSION
|
||||
imported_dsl_version: str = ""
|
||||
|
||||
+86
@@ -0,0 +1,86 @@
|
||||
"""App detail responses must not write masked configuration back to storage."""
|
||||
|
||||
import json
|
||||
|
||||
from flask.testing import FlaskClient
|
||||
from sqlalchemy.orm import Session
|
||||
|
||||
from models.model import AppMode, AppModelConfig
|
||||
from tests.test_containers_integration_tests.controllers.console.helpers import (
|
||||
authenticate_console_client,
|
||||
create_console_account_and_tenant,
|
||||
create_console_app,
|
||||
)
|
||||
|
||||
|
||||
def test_put_app_detail_preserves_agent_tool_secret_after_commit(
|
||||
db_session_with_containers: Session,
|
||||
test_client_with_containers: FlaskClient,
|
||||
) -> None:
|
||||
account, tenant = create_console_account_and_tenant(db_session_with_containers)
|
||||
app = create_console_app(db_session_with_containers, tenant.id, account.id, AppMode.AGENT_CHAT)
|
||||
agent_mode = {
|
||||
"enabled": True,
|
||||
"strategy": "react",
|
||||
"tools": [
|
||||
{
|
||||
"provider_type": "api",
|
||||
"provider_id": "00000000-0000-0000-0000-000000000001",
|
||||
"tool_name": "private_tool",
|
||||
"tool_parameters": {"api_key": "encrypted-secret"},
|
||||
}
|
||||
],
|
||||
}
|
||||
config = AppModelConfig(app_id=app.id, agent_mode=json.dumps(agent_mode))
|
||||
db_session_with_containers.add(config)
|
||||
db_session_with_containers.flush()
|
||||
app.app_model_config_id = config.id
|
||||
db_session_with_containers.commit()
|
||||
|
||||
headers = authenticate_console_client(test_client_with_containers, account)
|
||||
response = test_client_with_containers.put(
|
||||
f"/console/api/apps/{app.id}",
|
||||
headers=headers,
|
||||
json={"name": "Updated App"},
|
||||
)
|
||||
|
||||
assert response.status_code == 200
|
||||
assert response.json is not None
|
||||
assert response.json["model_config"]["agent_mode"]["tools"][0]["tool_parameters"] != {"api_key": "encrypted-secret"}
|
||||
with Session(db_session_with_containers.get_bind()) as reread_session:
|
||||
persisted = reread_session.get(AppModelConfig, config.id)
|
||||
assert persisted is not None
|
||||
assert persisted.agent_mode is not None
|
||||
assert json.loads(persisted.agent_mode) == agent_mode
|
||||
|
||||
|
||||
def test_get_and_put_app_detail_preserve_historical_agent_mode_without_tools(
|
||||
db_session_with_containers: Session,
|
||||
test_client_with_containers: FlaskClient,
|
||||
) -> None:
|
||||
account, tenant = create_console_account_and_tenant(db_session_with_containers)
|
||||
app = create_console_app(db_session_with_containers, tenant.id, account.id, AppMode.AGENT_CHAT)
|
||||
agent_mode = {"enabled": True, "max_iteration": 5, "strategy": "function_call"}
|
||||
config = AppModelConfig(app_id=app.id, agent_mode=json.dumps(agent_mode))
|
||||
db_session_with_containers.add(config)
|
||||
db_session_with_containers.flush()
|
||||
app.app_model_config_id = config.id
|
||||
db_session_with_containers.commit()
|
||||
|
||||
headers = authenticate_console_client(test_client_with_containers, account)
|
||||
get_response = test_client_with_containers.get(f"/console/api/apps/{app.id}", headers=headers)
|
||||
assert get_response.status_code == 200
|
||||
assert get_response.json is not None
|
||||
assert get_response.json["model_config"]["agent_mode"] == agent_mode
|
||||
|
||||
put_response = test_client_with_containers.put(
|
||||
f"/console/api/apps/{app.id}", headers=headers, json={"name": "Updated App"}
|
||||
)
|
||||
assert put_response.status_code == 200
|
||||
assert put_response.json is not None
|
||||
assert put_response.json["model_config"]["agent_mode"] == agent_mode
|
||||
|
||||
with Session(db_session_with_containers.get_bind()) as reread_session:
|
||||
persisted = reread_session.get(AppModelConfig, config.id)
|
||||
assert persisted is not None
|
||||
assert persisted.agent_mode == json.dumps(agent_mode)
|
||||
@@ -151,55 +151,6 @@ class TestAppService:
|
||||
assert app.tenant_id == tenant.id
|
||||
assert app.created_by == account.id
|
||||
|
||||
def test_get_app_success(self, db_session_with_containers: Session, mock_external_service_dependencies):
|
||||
"""
|
||||
Test successful app retrieval.
|
||||
"""
|
||||
fake = Faker()
|
||||
|
||||
# Create account and tenant first
|
||||
account = AccountService.create_account(
|
||||
email=fake.email(),
|
||||
name=fake.name(),
|
||||
interface_language="en-US",
|
||||
password=generate_valid_password(fake),
|
||||
session=db_session_with_containers,
|
||||
)
|
||||
TenantService.create_owner_tenant_if_not_exist(account, name=fake.company(), session=db_session_with_containers)
|
||||
tenant = account.current_tenant
|
||||
|
||||
# Create app first
|
||||
# Import here to avoid circular dependency
|
||||
from services.app_service import AppService, CreateAppParams
|
||||
|
||||
app_params = CreateAppParams(
|
||||
name=fake.company(),
|
||||
description=fake.text(max_nb_chars=100),
|
||||
mode="chat",
|
||||
icon_type="emoji",
|
||||
icon="🎯",
|
||||
icon_background="#45B7D1",
|
||||
)
|
||||
|
||||
app_service = AppService()
|
||||
created_app = app_service.create_app(tenant.id, app_params, account, session=db_session_with_containers)
|
||||
|
||||
# Get app using the service - needs current_user mock
|
||||
mock_current_user = create_autospec(Account, instance=True)
|
||||
mock_current_user.id = account.id
|
||||
mock_current_user.current_tenant_id = account.current_tenant_id
|
||||
|
||||
with patch("services.app_service.current_user", mock_current_user):
|
||||
retrieved_app = app_service.get_app(created_app, session=db_session_with_containers)
|
||||
|
||||
# Verify retrieved app matches created app
|
||||
assert retrieved_app.id == created_app.id
|
||||
assert retrieved_app.name == created_app.name
|
||||
assert retrieved_app.description == created_app.description
|
||||
assert retrieved_app.mode == created_app.mode
|
||||
assert retrieved_app.tenant_id == created_app.tenant_id
|
||||
assert retrieved_app.created_by == created_app.created_by
|
||||
|
||||
def test_get_paginate_apps_success(self, db_session_with_containers: Session, mock_external_service_dependencies):
|
||||
"""
|
||||
Test successful paginated app list retrieval.
|
||||
|
||||
@@ -812,6 +812,14 @@ def test_generate_specs_include_console_contract_shapes_for_schema_migration(tmp
|
||||
)
|
||||
assert {"enabled", "model", "prompt"} <= set(schemas["WorkflowSuggestedQuestionsAfterAnswerPayload"]["properties"])
|
||||
assert {"enabled", "language", "voice", "autoPlay"} <= set(schemas["WorkflowTextToSpeechPayload"]["properties"])
|
||||
assert schemas["WorkflowTextToSpeechPayload"]["properties"]["autoPlay"]["anyOf"][0]["enum"] == [
|
||||
"disabled",
|
||||
"enabled",
|
||||
]
|
||||
assert schemas["AgentTextToSpeechFeatureConfig"]["properties"]["autoPlay"]["anyOf"][0]["enum"] == [
|
||||
"disabled",
|
||||
"enabled",
|
||||
]
|
||||
assert {"enabled", "type", "config"} <= set(schemas["WorkflowSensitiveWordAvoidancePayload"]["properties"])
|
||||
file_upload = schemas["WorkflowFileUploadPayload"]["properties"]
|
||||
assert {"document", "audio", "video", "custom", "preview_config"} <= set(file_upload)
|
||||
|
||||
@@ -216,9 +216,9 @@ def _app_detail_obj(**overrides) -> App:
|
||||
"tracing": None,
|
||||
"use_icon_as_answer_icon": False,
|
||||
"created_by": "account-1",
|
||||
"created_at": None,
|
||||
"created_at": datetime(2025, 1, 1),
|
||||
"updated_by": "account-1",
|
||||
"updated_at": None,
|
||||
"updated_at": datetime(2025, 1, 1),
|
||||
"max_active_requests": 0,
|
||||
}
|
||||
overrides.pop("bound_agent_id", None)
|
||||
@@ -369,9 +369,6 @@ def test_agent_app_list_and_create_use_agent_route(
|
||||
apply_config_overrides(monkeypatch, RBAC_ENABLED=True)
|
||||
|
||||
class FakeAppService:
|
||||
def get_app(self, app_obj: object, *, session: object) -> object:
|
||||
return app_obj
|
||||
|
||||
def get_paginate_apps(self, user_id: str, tenant_id: str, params, session) -> object:
|
||||
captured["list"] = {"user_id": user_id, "tenant_id": tenant_id, "params": params}
|
||||
return SimpleNamespace(
|
||||
@@ -649,10 +646,6 @@ def test_agent_app_detail_update_delete_resolve_app_from_agent_id(
|
||||
)
|
||||
|
||||
class FakeAppService:
|
||||
def get_app(self, app_obj: object, *, session: object) -> object:
|
||||
captured["get_app"] = {"app": app_obj, "session": session}
|
||||
return app_obj
|
||||
|
||||
def update_app(self, app_obj: object, args: dict[str, object], *, session: object) -> object:
|
||||
captured["update"] = {"app": app_obj, "args": args}
|
||||
return _app_detail_obj(id=app_id, tenant_id=tenant_id, name=args["name"], bound_agent_id=agent_id)
|
||||
@@ -674,7 +667,6 @@ def test_agent_app_detail_update_delete_resolve_app_from_agent_id(
|
||||
assert detail["access_ready"] is False
|
||||
assert "active_config_is_published" not in detail
|
||||
assert "bound_agent_id" not in detail
|
||||
assert captured["get_app"] == {"app": app_model, "session": session}
|
||||
with app.test_request_context(
|
||||
"/console/api/agent/00000000-0000-0000-0000-000000000001",
|
||||
json={"name": "Renamed", "description": "", "role": "Reviewer", "icon_type": "emoji", "icon": "R"},
|
||||
@@ -1043,9 +1035,6 @@ def test_agent_app_update_allows_empty_role(
|
||||
)
|
||||
|
||||
class FakeAppService:
|
||||
def get_app(self, app_obj: object, *, session: object) -> object:
|
||||
return app_obj
|
||||
|
||||
def update_app(self, app_obj: object, args: dict[str, object], *, session: object) -> object:
|
||||
captured["update"] = {"app": app_obj, "args": args}
|
||||
return _app_detail_obj(id="app-1", name=args["name"], bound_agent_id=agent_id)
|
||||
|
||||
@@ -3,8 +3,10 @@
|
||||
import json
|
||||
from dataclasses import replace
|
||||
from datetime import datetime
|
||||
from pathlib import Path
|
||||
|
||||
import pytest
|
||||
import yaml
|
||||
from flask import Flask
|
||||
from pydantic import ValidationError
|
||||
from sqlalchemy.orm import Session
|
||||
@@ -12,6 +14,7 @@ from werkzeug.datastructures import MultiDict
|
||||
|
||||
from controllers.console.app import app as controller
|
||||
from fields import app_fields
|
||||
from fields.app_model_config_response import AppModelConfigResponse
|
||||
from libs.pagination import PaginatedResult
|
||||
from models.account import Account
|
||||
from models.enums import CustomizeTokenStrategy, TagType
|
||||
@@ -308,7 +311,6 @@ def test_app_detail_with_site_includes_nested_serialization(
|
||||
monkeypatch: pytest.MonkeyPatch,
|
||||
sqlite_session: Session,
|
||||
):
|
||||
AppDetailWithSite = app_models.AppDetailWithSite
|
||||
app_obj = _persist_response_graph(sqlite_session)
|
||||
app_obj.name = "Detailed App"
|
||||
app_obj.description = "Desc"
|
||||
@@ -323,16 +325,19 @@ def test_app_detail_with_site_includes_nested_serialization(
|
||||
assert model_config is not None
|
||||
model_config.opening_statement = "hi"
|
||||
model_config.retriever_resource = json.dumps({"enabled": True})
|
||||
monkeypatch.setattr("repositories.app.response.load_annotation_reply_config", lambda _session, _app_id: {})
|
||||
monkeypatch.setattr(
|
||||
"repositories.app.response.load_annotation_reply_config", lambda _session, _app_id: {"enabled": False}
|
||||
)
|
||||
|
||||
with app.test_request_context("/"):
|
||||
serialized = AppDetailWithSite.model_validate(
|
||||
response = controller._app_detail_response(
|
||||
replace(
|
||||
app_record(app_obj, session=sqlite_session, projection="detail-with-site"),
|
||||
permission_keys=app_obj.permission_keys,
|
||||
),
|
||||
from_attributes=True,
|
||||
).model_dump(mode="json")
|
||||
)
|
||||
assert isinstance(response, app_models.AppDetailWithSite)
|
||||
serialized = response.model_dump(mode="json")
|
||||
|
||||
assert serialized["icon_url"] == "signed:detail-icon"
|
||||
assert serialized["model_config"]["retriever_resource"] == {"enabled": True}
|
||||
@@ -427,3 +432,166 @@ def test_app_pagination_aliases_per_page_and_has_next(app_models, sqlite_session
|
||||
assert len(serialized["data"]) == 2
|
||||
assert serialized["data"][0]["icon_url"] == "signed:first-icon"
|
||||
assert serialized["data"][1]["icon_url"] is None
|
||||
|
||||
|
||||
@pytest.mark.parametrize("strategy", [None, "cot", "function-calling"])
|
||||
def test_app_detail_preserves_historical_agent_strategy(
|
||||
app: Flask, monkeypatch: pytest.MonkeyPatch, sqlite_session: Session, strategy: str | None
|
||||
):
|
||||
app_obj = _persist_response_graph(sqlite_session)
|
||||
config = sqlite_session.get(AppModelConfig, CONFIG_ID)
|
||||
assert config is not None
|
||||
agent_mode = {"enabled": True, "tools": []}
|
||||
if strategy is not None:
|
||||
agent_mode["strategy"] = strategy
|
||||
config.agent_mode = json.dumps(agent_mode)
|
||||
sqlite_session.commit()
|
||||
monkeypatch.setattr(
|
||||
"repositories.app.response.load_annotation_reply_config", lambda _session, _app_id: {"enabled": False}
|
||||
)
|
||||
|
||||
with app.test_request_context("/"):
|
||||
response = controller._app_detail_response(
|
||||
app_record(app_obj, session=sqlite_session, projection="detail-with-site")
|
||||
).model_dump(mode="json")
|
||||
|
||||
assert response["model_config"]["agent_mode"] == agent_mode
|
||||
|
||||
|
||||
def test_app_detail_preserves_historical_agent_mode_without_tools(
|
||||
app: Flask, monkeypatch: pytest.MonkeyPatch, sqlite_session: Session
|
||||
):
|
||||
app_obj = _persist_response_graph(sqlite_session)
|
||||
app_obj.mode = AppMode.AGENT_CHAT
|
||||
config = sqlite_session.get(AppModelConfig, CONFIG_ID)
|
||||
assert config is not None
|
||||
agent_mode = {"enabled": True, "max_iteration": 5, "strategy": "function_call"}
|
||||
config.agent_mode = json.dumps(agent_mode)
|
||||
sqlite_session.commit()
|
||||
monkeypatch.setattr(
|
||||
"repositories.app.response.load_annotation_reply_config", lambda _session, _app_id: {"enabled": False}
|
||||
)
|
||||
|
||||
with app.test_request_context("/"):
|
||||
response = controller._app_detail_response(
|
||||
app_record(app_obj, session=sqlite_session, projection="detail-with-site")
|
||||
).model_dump(mode="json")
|
||||
|
||||
assert response["model_config"]["agent_mode"] == agent_mode
|
||||
|
||||
|
||||
def test_app_model_config_response_round_trips_persisted_dataset_and_external_tool_fields(
|
||||
app: Flask, monkeypatch: pytest.MonkeyPatch, sqlite_session: Session
|
||||
):
|
||||
app_obj = _persist_response_graph(sqlite_session)
|
||||
config = sqlite_session.get(AppModelConfig, CONFIG_ID)
|
||||
assert config is not None
|
||||
dataset_configs = {
|
||||
"retrieval_model": "multiple",
|
||||
"reranking_enable": True,
|
||||
"reranking_enabled": True,
|
||||
"metadata_filtering_conditions": {
|
||||
"logical_operator": "and",
|
||||
"conditions": [
|
||||
{
|
||||
"id": "condition-1",
|
||||
"metadata_id": "metadata-1",
|
||||
"name": "category",
|
||||
"comparison_operator": "is",
|
||||
"value": "books",
|
||||
}
|
||||
],
|
||||
},
|
||||
"extension_setting": {"value": 1},
|
||||
}
|
||||
external_form = {
|
||||
"external_data_tool": {
|
||||
"variable": "customer",
|
||||
"label": "Customer",
|
||||
"type": "api",
|
||||
"enabled": True,
|
||||
"icon": "icon-key",
|
||||
"icon_background": "#fff",
|
||||
"config": {"provider": "crm"},
|
||||
"extension_setting": {"value": 2},
|
||||
}
|
||||
}
|
||||
config.dataset_configs = json.dumps(dataset_configs)
|
||||
config.user_input_form = json.dumps([external_form])
|
||||
sqlite_session.commit()
|
||||
monkeypatch.setattr(
|
||||
"repositories.app.response.load_annotation_reply_config", lambda _session, _app_id: {"enabled": False}
|
||||
)
|
||||
|
||||
with app.test_request_context("/"):
|
||||
response = controller._app_detail_response(
|
||||
app_record(app_obj, session=sqlite_session, projection="detail-with-site")
|
||||
).model_dump(mode="json")
|
||||
|
||||
model_config = response["model_config"]
|
||||
assert model_config["dataset_configs"] == dataset_configs
|
||||
assert model_config["user_input_form"] == [external_form]
|
||||
|
||||
reimported = AppModelConfig(app_id=APP_ID)
|
||||
reimported.from_model_config_dict(model_config)
|
||||
assert reimported.dataset_configs_dict == dataset_configs
|
||||
assert reimported.user_input_form_list == [external_form]
|
||||
|
||||
|
||||
def test_recommended_app_model_configs_keep_all_published_fields():
|
||||
catalog_path = Path(__file__).resolve().parents[5] / "constants" / "recommended_apps.json"
|
||||
catalog = json.loads(catalog_path.read_text())
|
||||
|
||||
def assert_fields_preserved(source, serialized):
|
||||
if isinstance(source, dict):
|
||||
for key, value in source.items():
|
||||
assert key in serialized
|
||||
assert_fields_preserved(value, serialized[key])
|
||||
elif isinstance(source, list):
|
||||
assert len(source) == len(serialized)
|
||||
for value, serialized_value in zip(source, serialized, strict=True):
|
||||
assert_fields_preserved(value, serialized_value)
|
||||
else:
|
||||
assert serialized == source
|
||||
|
||||
for entry in catalog["app_details"].values():
|
||||
source = yaml.safe_load(entry["export_data"]).get("model_config") or {}
|
||||
if not source:
|
||||
continue
|
||||
payload = {**source, "created_by": None, "created_at": 1, "updated_by": None, "updated_at": 1}
|
||||
response = AppModelConfigResponse.model_validate(payload).model_dump(mode="json")
|
||||
assert_fields_preserved(source, response)
|
||||
|
||||
|
||||
def test_app_detail_rejects_invalid_known_configuration_fields(
|
||||
app: Flask, monkeypatch: pytest.MonkeyPatch, sqlite_session: Session
|
||||
):
|
||||
app_obj = _persist_response_graph(sqlite_session)
|
||||
monkeypatch.setattr(
|
||||
"repositories.app.response.load_annotation_reply_config", lambda _session, _app_id: {"enabled": False}
|
||||
)
|
||||
with app.test_request_context("/"):
|
||||
detail = controller._app_detail_response(
|
||||
app_record(app_obj, session=sqlite_session, projection="detail-with-site")
|
||||
).model_dump(mode="json")
|
||||
|
||||
for field in ("mode", "permission_keys", "site", "model_config"):
|
||||
with pytest.raises(ValidationError):
|
||||
app_fields.AppDetailWithSite.model_validate({key: value for key, value in detail.items() if key != field})
|
||||
|
||||
with pytest.raises(ValidationError):
|
||||
app_fields.AppDetailWithSite.model_validate({**detail, "mode": "unsupported"})
|
||||
|
||||
config = detail["model_config"]
|
||||
for invalid in (
|
||||
{"speech_to_text": {"enabled": "not-a-boolean"}},
|
||||
{"agent_mode": {"enabled": True, "strategy": "unsupported", "tools": []}},
|
||||
{"agent_mode": {"enabled": True, "tools": "not-a-list"}},
|
||||
{"agent_mode": {"enabled": True, "tools": [{"provider_id": "only-id"}]}},
|
||||
{"dataset_configs": {"retrieval_model": "unsupported"}},
|
||||
{"dataset_configs": {"retrieval_model": "multiple", "reranking_mode": "unsupported"}},
|
||||
{"model": {"provider": "openai", "name": "gpt-4o", "mode": "unsupported"}},
|
||||
{"user_input_form": [{"unsupported": {"label": "Name", "variable": "name"}}]},
|
||||
):
|
||||
with pytest.raises(ValidationError):
|
||||
app_fields.AppDetailWithSite.model_validate({**detail, "model_config": {**config, **invalid}})
|
||||
@@ -3,6 +3,7 @@
|
||||
import inspect
|
||||
from collections.abc import Callable
|
||||
from dataclasses import dataclass, field, replace
|
||||
from datetime import datetime
|
||||
from io import BytesIO
|
||||
from typing import cast
|
||||
from uuid import UUID
|
||||
@@ -18,6 +19,7 @@ from controllers.console.app.error import AppNotFoundError
|
||||
from libs.login import AccountWithTenant
|
||||
from machinery.context import RequestContext
|
||||
from models.account import Account, TenantAccountRole
|
||||
from models.enums import CustomizeTokenStrategy
|
||||
from services.agent.roster_package_entities import RosterAgentPackageExport
|
||||
from services.app.console_service import (
|
||||
AppExportPaidPlanRequiredError,
|
||||
@@ -41,7 +43,33 @@ from tests.unit_tests.config_override import apply_config_overrides
|
||||
|
||||
APP_ID = UUID("11111111-1111-1111-1111-111111111111")
|
||||
CONTEXT = RequestContext("request", "trace", "actor", "workspace")
|
||||
RECORD = AppRecord(str(APP_ID), "Example", "chat")
|
||||
RECORD = AppRecord(
|
||||
str(APP_ID), "Example", "chat", description="", created_at=datetime(2024, 1, 1), updated_at=datetime(2024, 1, 1)
|
||||
)
|
||||
SITE = {
|
||||
"code": "site",
|
||||
"title": "Example",
|
||||
"icon_type": None,
|
||||
"icon": None,
|
||||
"icon_background": None,
|
||||
"description": None,
|
||||
"default_language": "en-US",
|
||||
"chat_color_theme": None,
|
||||
"chat_color_theme_inverted": False,
|
||||
"customize_domain": None,
|
||||
"copyright": None,
|
||||
"privacy_policy": None,
|
||||
"input_placeholder": None,
|
||||
"custom_disclaimer": "",
|
||||
"customize_token_strategy": CustomizeTokenStrategy.NOT_ALLOW,
|
||||
"prompt_public": False,
|
||||
"show_workflow_steps": False,
|
||||
"use_icon_as_answer_icon": False,
|
||||
"created_by": None,
|
||||
"created_at": datetime(2024, 1, 1),
|
||||
"updated_by": None,
|
||||
"updated_at": datetime(2024, 1, 1),
|
||||
}
|
||||
|
||||
|
||||
@dataclass
|
||||
@@ -133,7 +161,7 @@ def test_detail_resolves_urls_at_the_http_boundary(
|
||||
SERVICE_API_URL="https://api.example.com" if configured else "",
|
||||
APP_WEB_URL="https://apps.example.com" if configured else "",
|
||||
)
|
||||
boundary.record = replace(RECORD, site={"code": "site", "title": "Example"})
|
||||
boundary.record = replace(RECORD, site=SITE)
|
||||
with app.test_request_context("/", base_url="https://console.example.com/"):
|
||||
response = cast(dict[str, object], invoke(controller.AppApi, controller.AppApi.get, app_id=APP_ID))
|
||||
assert response["api_base_url"] == (
|
||||
|
||||
@@ -48,7 +48,7 @@ from repositories.app_preview_query_repository import AppPreviewQueryRepository
|
||||
from repositories.trial_app_repository import TrialAppRepository
|
||||
from services.app_preview_details_adapters import AppPreviewDetailsRuntime
|
||||
from services.app_preview_query_service import AppPreviewQueryService
|
||||
from services.app_service import AppResponseView, AppService
|
||||
from services.app_service import AppResponseView
|
||||
from services.recommended_app_query_service import (
|
||||
RecommendedAppCatalogPage,
|
||||
RecommendedAppDetailRecord,
|
||||
@@ -204,9 +204,8 @@ class _Harness:
|
||||
with self.app.test_request_context(f"/trial-apps/{self.target.id}"), self.factory() as session:
|
||||
app = session.get(App, self.target.id)
|
||||
assert app is not None
|
||||
app = AppService().get_app(app, session=session)
|
||||
return trial_module.TrialAppDetailResponse.model_validate(
|
||||
AppResponseView(app, session=session), from_attributes=True
|
||||
AppResponseView(app, session=session, account=self.viewer), from_attributes=True
|
||||
).model_dump(mode="json")
|
||||
|
||||
|
||||
|
||||
@@ -81,6 +81,10 @@ class TestAdditionalFeatureManagers:
|
||||
SuggestedQuestionsAfterAnswerConfigManager.validate_and_set_defaults(
|
||||
{"suggested_questions_after_answer": {"enabled": True, "prompt": 123}}
|
||||
)
|
||||
with pytest.raises(ValueError, match="prompt in suggested_questions_after_answer must be of string type"):
|
||||
SuggestedQuestionsAfterAnswerConfigManager.validate_and_set_defaults(
|
||||
{"suggested_questions_after_answer": {"enabled": False, "prompt": None}}
|
||||
)
|
||||
with pytest.raises(ValueError, match="must be less than or equal to 1000 characters"):
|
||||
SuggestedQuestionsAfterAnswerConfigManager.validate_and_set_defaults(
|
||||
{"suggested_questions_after_answer": {"enabled": True, "prompt": "a" * 1001}}
|
||||
@@ -128,6 +132,16 @@ class TestAdditionalFeatureManagers:
|
||||
TextToSpeechConfigManager.validate_and_set_defaults({"text_to_speech": "bad"})
|
||||
with pytest.raises(ValueError):
|
||||
TextToSpeechConfigManager.validate_and_set_defaults({"text_to_speech": {"enabled": "yes"}})
|
||||
for field, value in (("voice", None), ("language", 42), ("autoPlay", "auto"), ("autoPlay", None)):
|
||||
with pytest.raises(ValueError, match=f"{field} in text_to_speech"):
|
||||
TextToSpeechConfigManager.validate_and_set_defaults(
|
||||
{"text_to_speech": {"enabled": False, field: value}}
|
||||
)
|
||||
|
||||
valid, _ = TextToSpeechConfigManager.validate_and_set_defaults(
|
||||
{"text_to_speech": {"enabled": True, "voice": "v", "language": "en", "autoPlay": "enabled"}}
|
||||
)
|
||||
assert valid["text_to_speech"]["autoPlay"] == "enabled"
|
||||
|
||||
result = TextToSpeechConfigManager.convert(
|
||||
{"text_to_speech": {"enabled": True, "voice": "v", "language": "en"}}
|
||||
|
||||
@@ -427,6 +427,18 @@ class TestAppModelValidation:
|
||||
class TestAppModelConfig:
|
||||
"""Test suite for AppModelConfig model."""
|
||||
|
||||
def test_legacy_dataset_configs_default_retrieval_model_without_dropping_settings(self):
|
||||
config = AppModelConfig(
|
||||
app_id=str(uuid4()),
|
||||
dataset_configs=json.dumps({"reranking_enable": True, "top_k": 8}),
|
||||
)
|
||||
|
||||
assert config.dataset_configs_dict == {
|
||||
"retrieval_model": "single",
|
||||
"reranking_enable": True,
|
||||
"top_k": 8,
|
||||
}
|
||||
|
||||
def test_app_model_config_creation(self):
|
||||
"""Test creating an AppModelConfig."""
|
||||
# Arrange
|
||||
|
||||
@@ -9,7 +9,7 @@ from flask import has_request_context
|
||||
from sqlalchemy import Engine, event, func, select, text
|
||||
from sqlalchemy.orm import Session, sessionmaker
|
||||
|
||||
from fields.app_fields import AppDetailWithSite, AppPagination
|
||||
from fields.app_fields import AppPagination
|
||||
from machinery.context import RequestContext
|
||||
from models.agent import Agent, AgentScope, AgentSource, AgentStatus
|
||||
from models.enums import CustomizeTokenStrategy
|
||||
@@ -101,13 +101,11 @@ def test_all_single_app_operations_preserve_visibility(
|
||||
assert sqlite_session.scalar(select(func.count()).select_from(AppStar)) == 0
|
||||
|
||||
|
||||
def test_detail_is_serializable_after_repository_session_closes(
|
||||
def test_detail_is_materialized_after_repository_session_closes(
|
||||
repository: ConsoleAppRepository,
|
||||
sqlite_session: Session,
|
||||
sqlite_engine: Engine,
|
||||
config_overrides: Callable[..., None],
|
||||
) -> None:
|
||||
config_overrides(SERVICE_API_URL="", APP_WEB_URL="")
|
||||
assert not has_request_context()
|
||||
app = persist_app(sqlite_session)
|
||||
config = AppModelConfig(app_id=app.id, model='{"provider":"openai","name":"example"}', pre_prompt="Prompt")
|
||||
@@ -129,14 +127,16 @@ def test_detail_is_serializable_after_repository_session_closes(
|
||||
|
||||
event.listen(sqlite_engine, "before_cursor_execute", reject_queries)
|
||||
try:
|
||||
data = AppDetailWithSite.model_validate(record, from_attributes=True).model_dump(mode="json")
|
||||
model_config = record.app_model_config
|
||||
site_data = record.site
|
||||
description = record.description
|
||||
finally:
|
||||
event.remove(sqlite_engine, "before_cursor_execute", reject_queries)
|
||||
assert data["model_config"]["model"] == {"provider": "openai", "name": "example"}
|
||||
assert data["site"]["access_token"] == "site-code"
|
||||
assert data["description"] == ""
|
||||
assert data["api_base_url"] is None
|
||||
assert data["site"]["app_base_url"] is None
|
||||
assert model_config is not None
|
||||
assert model_config["model"] == {"provider": "openai", "name": "example"}
|
||||
assert site_data is not None
|
||||
assert site_data["code"] == "site-code"
|
||||
assert description == ""
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
|
||||
@@ -17,7 +17,6 @@ from core.plugin.impl.plugin import PluginInstaller
|
||||
from core.tools.entities.tool_entities import ApiProviderSchemaType
|
||||
from core.tools.tool_manager import ToolManager
|
||||
from events.app_event import app_was_updated
|
||||
from fields.app_fields import AppDetailWithSite
|
||||
from graphon.model_runtime.entities.model_entities import ModelType
|
||||
from machinery.context import RequestContext
|
||||
from models.account import Account, Tenant, TenantAccountJoin, TenantAccountRole
|
||||
@@ -839,13 +838,11 @@ def test_detail_tool_enrichment_releases_database_before_plugin_io(
|
||||
assert read.scalar(select(App.id).where(App.name == "Created")) is not None
|
||||
else:
|
||||
result = read_result()
|
||||
data = AppDetailWithSite.model_validate(result, from_attributes=True).model_dump(mode="json")
|
||||
assert data["deleted_tools"] == [
|
||||
assert result.deleted_tools == [
|
||||
{"type": "api", "provider_id": missing_api, "tool_name": "tool"},
|
||||
{"type": "api", "provider_id": providers[1].id, "tool_name": "tool"},
|
||||
{"type": "builtin", "provider_id": "vendor/missing/tool", "tool_name": "tool"},
|
||||
]
|
||||
assert "tool_references" not in data
|
||||
assert remote_calls == [["vendor/missing/tool", "vendor/installed/tool"]]
|
||||
assert not checked_out
|
||||
finally:
|
||||
|
||||
@@ -515,6 +515,52 @@ def test_create_or_update_app_flushes_new_model_config_before_signal(
|
||||
assert sqlite_session.in_transaction()
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
("feature", "field", "value"),
|
||||
[
|
||||
("suggested_questions_after_answer", "prompt", None),
|
||||
("suggested_questions_after_answer", "prompt", 123),
|
||||
("text_to_speech", "voice", None),
|
||||
("text_to_speech", "language", 123),
|
||||
("text_to_speech", "autoPlay", "auto"),
|
||||
],
|
||||
)
|
||||
def test_chat_dsl_import_rejects_invalid_feature_fields(
|
||||
sqlite_session: Session, feature: str, field: str, value: object
|
||||
) -> None:
|
||||
app = _app()
|
||||
|
||||
with pytest.raises(ValueError, match=field):
|
||||
AppDslService(session=sqlite_session)._create_or_update_app(
|
||||
app=app,
|
||||
data={"app": {"mode": AppMode.CHAT}, "model_config": {feature: {"enabled": True, field: value}}},
|
||||
account=_account(),
|
||||
)
|
||||
|
||||
assert app.app_model_config_id is None
|
||||
assert list(sqlite_session.scalars(select(AppModelConfig))) == []
|
||||
|
||||
|
||||
def test_chat_dsl_import_preserves_valid_feature_fields(sqlite_session: Session) -> None:
|
||||
app = _app()
|
||||
model_config = {
|
||||
"suggested_questions_after_answer": {"enabled": True, "prompt": "Follow up"},
|
||||
"text_to_speech": {"enabled": True, "voice": "alloy", "language": "en", "autoPlay": "disabled"},
|
||||
}
|
||||
|
||||
AppDslService(session=sqlite_session)._create_or_update_app(
|
||||
app=app,
|
||||
data={"app": {"mode": AppMode.CHAT}, "model_config": model_config},
|
||||
account=_account(),
|
||||
)
|
||||
|
||||
assert app.app_model_config_id is not None
|
||||
persisted = sqlite_session.get(AppModelConfig, app.app_model_config_id)
|
||||
assert persisted is not None
|
||||
assert persisted.suggested_questions_after_answer_dict == model_config["suggested_questions_after_answer"]
|
||||
assert persisted.text_to_speech_dict == model_config["text_to_speech"]
|
||||
|
||||
|
||||
def test_create_or_update_app_removes_imported_workflow_viewport(monkeypatch: pytest.MonkeyPatch) -> None:
|
||||
session = cast(Session, SimpleNamespace(add=Mock(), flush=Mock(), get=Mock()))
|
||||
service = AppDslService(session=session)
|
||||
|
||||
@@ -9,7 +9,7 @@ from uuid import uuid4
|
||||
|
||||
import pytest
|
||||
from sqlalchemy import event, select
|
||||
from sqlalchemy.orm import Session
|
||||
from sqlalchemy.orm import Session, sessionmaker
|
||||
|
||||
from enums import DeploymentEdition
|
||||
from graphon.model_runtime.entities.model_entities import ModelType
|
||||
@@ -31,7 +31,7 @@ from models.provider import TenantDefaultModel
|
||||
from models.workflow import Workflow, WorkflowType
|
||||
from repositories.app.console_repository import ConsoleAppRepository
|
||||
from services.agent.errors import AgentAccessNotReadyError, AgentNameConflictError
|
||||
from services.app_service import AppListParams, AppService, CreateAppParams
|
||||
from services.app_service import AppListParams, AppResponseView, AppService, CreateAppParams
|
||||
from services.enterprise import rbac_service as enterprise_rbac_service
|
||||
|
||||
|
||||
@@ -586,68 +586,40 @@ def test_get_recent_apps_uses_one_tenant_scoped_projection_query(sqlite_session:
|
||||
assert "app_model_configs" not in select_statements[0].lower()
|
||||
|
||||
|
||||
class TestGetApp:
|
||||
def test_legacy_agent_detection_uses_caller_session(self, unbound_session: Session):
|
||||
app = App(
|
||||
mode=AppMode.CHAT,
|
||||
)
|
||||
class TestAppResponseViewAgentConfig:
|
||||
def test_masking_persistent_agent_config_does_not_change_database(
|
||||
self, sqlite_session: Session, sqlite_session_factory: sessionmaker[Session]
|
||||
):
|
||||
tenant_id = str(uuid4())
|
||||
app = _persist_app(sqlite_session, tenant_id=tenant_id)
|
||||
app.mode = AppMode.AGENT_CHAT
|
||||
original_agent_mode = {"enabled": True, "tools": [{"parameters": {"secret": "encrypted-value"}}]}
|
||||
config = AppModelConfig(app_id=app.id, agent_mode=json.dumps(original_agent_mode))
|
||||
sqlite_session.add(config)
|
||||
sqlite_session.flush()
|
||||
app.app_model_config_id = config.id
|
||||
sqlite_session.commit()
|
||||
|
||||
account = Account(name="Test Account", email="test@example.com")
|
||||
account._current_tenant = Tenant(name="Test Tenant")
|
||||
account._current_tenant.id = "tenant-1"
|
||||
account._current_tenant.id = tenant_id
|
||||
masked_agent_mode = {"enabled": True, "tools": [{"parameters": {"secret": "[masked]"}}]}
|
||||
|
||||
with (
|
||||
patch.object(App, "is_agent_with_session", return_value=False) as is_agent,
|
||||
patch.object(App, "app_model_config_with_session") as get_model_config,
|
||||
patch("services.app_service.current_user", account),
|
||||
patch("services.app_service.mask_agent_tool_parameters", return_value=masked_agent_mode),
|
||||
patch.object(sqlite_session, "refresh", side_effect=AssertionError("App refresh is unnecessary")),
|
||||
):
|
||||
assert AppService().get_app(app, session=unbound_session) is app
|
||||
response_config = AppResponseView(app, session=sqlite_session, account=account).app_model_config
|
||||
assert response_config is not None
|
||||
assert response_config.agent_mode_dict == masked_agent_mode
|
||||
assert config.agent_mode_dict == original_agent_mode
|
||||
assert not sqlite_session.is_modified(config)
|
||||
sqlite_session.commit()
|
||||
|
||||
is_agent.assert_called_once_with(session=unbound_session)
|
||||
get_model_config.assert_not_called()
|
||||
|
||||
def test_agent_model_config_uses_caller_session(self, unbound_session: Session):
|
||||
app = App(
|
||||
mode=AppMode.AGENT_CHAT,
|
||||
)
|
||||
account = Account(name="Test Account", email="test@example.com")
|
||||
account._current_tenant = Tenant(name="Test Tenant")
|
||||
account._current_tenant.id = "tenant-1"
|
||||
|
||||
with (
|
||||
patch.object(App, "is_agent_with_session") as is_agent,
|
||||
patch.object(App, "app_model_config_with_session", return_value=None) as get_model_config,
|
||||
patch("services.app_service.current_user", account),
|
||||
):
|
||||
assert AppService().get_app(app, session=unbound_session) is app
|
||||
|
||||
is_agent.assert_not_called()
|
||||
get_model_config.assert_called_once_with(session=unbound_session)
|
||||
|
||||
def test_masked_agent_config_is_served_through_the_session_accessor(self, unbound_session: Session):
|
||||
"""The masked config must be reachable via `app_model_config_with_session`.
|
||||
|
||||
Every response path resolves an `App`'s model config through that accessor
|
||||
(`AppResponseView.app_model_config`), never through a raw attribute, so the
|
||||
masking `get_app` applies has to be observable there.
|
||||
"""
|
||||
app = App(mode=AppMode.AGENT_CHAT)
|
||||
app.id = str(uuid4())
|
||||
masked_config = AppModelConfig(app_id=app.id, agent_mode=json.dumps({"enabled": True, "tools": []}))
|
||||
# A second, unmasked instance: what a fresh lookup would hand back if the
|
||||
# returned app ever fell through to the base accessor.
|
||||
refetched_config = AppModelConfig(app_id=app.id, agent_mode=json.dumps({"enabled": True, "tools": []}))
|
||||
account = Account(name="Test Account", email="test@example.com")
|
||||
account._current_tenant = Tenant(name="Test Tenant")
|
||||
account._current_tenant.id = "tenant-1"
|
||||
|
||||
with (
|
||||
patch.object(App, "app_model_config_with_session", side_effect=[masked_config, refetched_config]),
|
||||
patch("services.app_service.current_user", account),
|
||||
):
|
||||
result = AppService().get_app(app, session=unbound_session)
|
||||
|
||||
assert result is not app
|
||||
assert result.app_model_config_with_session(session=unbound_session) is masked_config
|
||||
with sqlite_session_factory() as read_session:
|
||||
saved_config = read_session.get(AppModelConfig, config.id)
|
||||
assert saved_config is not None
|
||||
assert saved_config.agent_mode_dict == original_agent_mode
|
||||
|
||||
|
||||
class TestAgentAppType:
|
||||
|
||||
@@ -23,41 +23,41 @@ export type AgentAppCreatePayload = {
|
||||
}
|
||||
|
||||
export type AgentAppDetailWithSite = {
|
||||
access_mode?: string | null
|
||||
access_mode: WebAppAccessMode | null
|
||||
access_ready?: boolean
|
||||
api_base_url?: string | null
|
||||
api_base_url: string
|
||||
app_id?: string | null
|
||||
backing_app_id?: string | null
|
||||
bound_agent_id?: string | null
|
||||
created_at?: number | null
|
||||
created_by?: string | null
|
||||
created_at: number
|
||||
created_by: string | null
|
||||
debug_conversation_has_messages?: boolean
|
||||
debug_conversation_id?: string | null
|
||||
debug_conversation_message_count?: number
|
||||
deleted_tools?: Array<DeletedTool>
|
||||
description?: string | null
|
||||
deleted_tools: Array<DeletedTool>
|
||||
description: string
|
||||
enable_api: boolean
|
||||
enable_site: boolean
|
||||
hidden_app_backed?: boolean
|
||||
icon?: string | null
|
||||
icon_background?: string | null
|
||||
icon_type?: string | null
|
||||
icon: string | null
|
||||
icon_background: string | null
|
||||
icon_type: IconType | null
|
||||
readonly icon_url: string | null
|
||||
id: string
|
||||
maintainer?: string | null
|
||||
max_active_requests?: number | null
|
||||
mode: string
|
||||
model_config?: AppModelConfigResponse | null
|
||||
maintainer: string | null
|
||||
max_active_requests: number | null
|
||||
mode: AppMode
|
||||
model_config: AppModelConfigResponse | null
|
||||
name: string
|
||||
permission_keys: Array<string>
|
||||
role?: string | null
|
||||
site?: AppDetailSiteResponse | null
|
||||
tags?: Array<Tag>
|
||||
tracing?: unknown | null
|
||||
updated_at?: number | null
|
||||
updated_by?: string | null
|
||||
use_icon_as_answer_icon?: boolean | null
|
||||
workflow?: WorkflowPartial | null
|
||||
site: AppDetailSiteResponse | null
|
||||
tags: Array<Tag>
|
||||
tracing: string | null
|
||||
updated_at: number
|
||||
updated_by: string | null
|
||||
use_icon_as_answer_icon: boolean
|
||||
workflow: WorkflowPartial | null
|
||||
}
|
||||
|
||||
export type AgentInviteOptionsResponse = {
|
||||
@@ -443,7 +443,7 @@ export type AgentConfigSnapshotRestoreResponse = {
|
||||
}
|
||||
|
||||
export type AgentAppPartial = {
|
||||
access_mode?: string | null
|
||||
access_mode?: WebAppAccessMode | null
|
||||
active_config_is_published?: boolean
|
||||
app_id?: string | null
|
||||
author_name?: string | null
|
||||
@@ -458,13 +458,13 @@ export type AgentAppPartial = {
|
||||
hidden_app_backed?: boolean
|
||||
icon?: string | null
|
||||
icon_background?: string | null
|
||||
icon_type?: string | null
|
||||
icon_type?: IconType | null
|
||||
readonly icon_url: string | null
|
||||
id: string
|
||||
is_starred?: boolean
|
||||
maintainer?: string | null
|
||||
max_active_requests?: number | null
|
||||
mode: string
|
||||
mode: AppMode
|
||||
model_config?: ModelConfigPartial | null
|
||||
name: string
|
||||
permission_keys: Array<string>
|
||||
@@ -486,65 +486,89 @@ export type AgentPublicationCountsResponse = {
|
||||
|
||||
export type IconType = 'emoji' | 'image' | 'link'
|
||||
|
||||
export type WebAppAccessMode = 'private' | 'private_all' | 'public' | 'sso_verified'
|
||||
|
||||
export type DeletedTool = {
|
||||
provider_id: string
|
||||
tool_name: string
|
||||
type: string
|
||||
}
|
||||
|
||||
export type AppMode =
|
||||
| 'advanced-chat'
|
||||
| 'agent'
|
||||
| 'agent-chat'
|
||||
| 'channel'
|
||||
| 'chat'
|
||||
| 'completion'
|
||||
| 'rag-pipeline'
|
||||
| 'workflow'
|
||||
|
||||
export type AppModelConfigResponse = {
|
||||
agent_mode?: unknown | null
|
||||
annotation_reply?: unknown | null
|
||||
chat_prompt_config?: unknown | null
|
||||
completion_prompt_config?: unknown | null
|
||||
created_at?: number | null
|
||||
created_by?: string | null
|
||||
dataset_configs?: unknown | null
|
||||
dataset_query_variable?: string | null
|
||||
external_data_tools?: unknown | null
|
||||
file_upload?: unknown | null
|
||||
model?: unknown | null
|
||||
more_like_this?: unknown | null
|
||||
opening_statement?: string | null
|
||||
pre_prompt?: string | null
|
||||
prompt_type?: string | null
|
||||
retriever_resource?: unknown | null
|
||||
sensitive_word_avoidance?: unknown | null
|
||||
speech_to_text?: unknown | null
|
||||
suggested_questions?: unknown | null
|
||||
suggested_questions_after_answer?: unknown | null
|
||||
text_to_speech?: unknown | null
|
||||
updated_at?: number | null
|
||||
updated_by?: string | null
|
||||
user_input_form?: unknown | null
|
||||
agent_mode: AppAgentModeResponse
|
||||
annotation_reply: AppAnnotationReplyEnabledResponse | AppAnnotationReplyDisabledResponse
|
||||
chat_prompt_config: AppChatPromptConfigResponse
|
||||
completion_prompt_config: AppCompletionPromptConfigResponse
|
||||
created_at: number
|
||||
created_by: string | null
|
||||
dataset_configs: AppDatasetConfigsResponse
|
||||
dataset_query_variable: string | null
|
||||
external_data_tools: Array<
|
||||
AppEnabledExternalDataToolResponse | AppDisabledExternalDataToolResponse
|
||||
>
|
||||
file_upload: AppFileUploadResponse
|
||||
model: AppModelSelectionResponse
|
||||
more_like_this: AppEnabledConfigResponse
|
||||
opening_statement: string | null
|
||||
pre_prompt: string | null
|
||||
prompt_type: PromptType
|
||||
retriever_resource: AppEnabledConfigResponse
|
||||
sensitive_word_avoidance: AppSensitiveWordAvoidanceResponse
|
||||
speech_to_text: AppEnabledConfigResponse
|
||||
suggested_questions: Array<string>
|
||||
suggested_questions_after_answer: AppSuggestedQuestionsAfterAnswerResponse
|
||||
text_to_speech: AppTextToSpeechResponse
|
||||
updated_at: number
|
||||
updated_by: string | null
|
||||
user_input_form: Array<
|
||||
| AppTextInputFormResponse
|
||||
| AppSelectFormResponse
|
||||
| AppParagraphFormResponse
|
||||
| AppNumberFormResponse
|
||||
| AppCheckboxFormResponse
|
||||
| AppFileFormResponse
|
||||
| AppFileListFormResponse
|
||||
| AppExternalDataToolFormResponse
|
||||
| AppJsonObjectFormResponse
|
||||
>
|
||||
}
|
||||
|
||||
export type AppDetailSiteResponse = {
|
||||
access_token?: string | null
|
||||
app_base_url?: string | null
|
||||
chat_color_theme?: string | null
|
||||
chat_color_theme_inverted?: boolean | null
|
||||
code?: string | null
|
||||
copyright?: string | null
|
||||
created_at?: number | null
|
||||
created_by?: string | null
|
||||
custom_disclaimer?: string | null
|
||||
customize_domain?: string | null
|
||||
customize_token_strategy?: string | null
|
||||
default_language?: string | null
|
||||
description?: string | null
|
||||
icon?: string | null
|
||||
icon_background?: string | null
|
||||
icon_type?: string | IconType | null
|
||||
access_token: string | null
|
||||
app_base_url: string
|
||||
chat_color_theme: string | null
|
||||
chat_color_theme_inverted: boolean
|
||||
code: string | null
|
||||
copyright: string | null
|
||||
created_at: number
|
||||
created_by: string | null
|
||||
custom_disclaimer: string
|
||||
customize_domain: string | null
|
||||
customize_token_strategy: CustomizeTokenStrategy
|
||||
default_language: string
|
||||
description: string | null
|
||||
icon: string | null
|
||||
icon_background: string | null
|
||||
icon_type: IconType | null
|
||||
readonly icon_url: string | null
|
||||
input_placeholder?: string | null
|
||||
privacy_policy?: string | null
|
||||
prompt_public?: boolean | null
|
||||
show_workflow_steps?: boolean | null
|
||||
title?: string | null
|
||||
updated_at?: number | null
|
||||
updated_by?: string | null
|
||||
use_icon_as_answer_icon?: boolean | null
|
||||
input_placeholder: string | null
|
||||
privacy_policy: string | null
|
||||
prompt_public: boolean
|
||||
show_workflow_steps: boolean
|
||||
title: string
|
||||
updated_at: number
|
||||
updated_by: string | null
|
||||
use_icon_as_answer_icon: boolean
|
||||
}
|
||||
|
||||
export type Tag = {
|
||||
@@ -794,7 +818,7 @@ export type AgentSuggestedQuestionsAfterAnswerFeatureConfig = {
|
||||
}
|
||||
|
||||
export type AgentTextToSpeechFeatureConfig = {
|
||||
autoPlay?: string | null
|
||||
autoPlay?: 'disabled' | 'enabled' | null
|
||||
enabled?: boolean
|
||||
language?: string | null
|
||||
voice?: string | null
|
||||
@@ -989,7 +1013,7 @@ export type AgentConfigRevisionResponse = {
|
||||
export type ModelConfigPartial = {
|
||||
created_at?: number | null
|
||||
created_by?: string | null
|
||||
model?: unknown | null
|
||||
model?: AppModelSelectionResponse | null
|
||||
pre_prompt?: string | null
|
||||
updated_at?: number | null
|
||||
updated_by?: string | null
|
||||
@@ -1003,6 +1027,172 @@ export type AgentAppPublishedReferenceResponse = {
|
||||
app_name: string
|
||||
}
|
||||
|
||||
export type AppAgentModeResponse = {
|
||||
enabled: boolean
|
||||
max_iteration?: number
|
||||
prompt?: AppAgentPromptResponse | string | null
|
||||
strategy?: PlanningStrategy | 'cot' | 'function-calling' | null
|
||||
tools?: Array<
|
||||
| AppProviderAgentToolResponse
|
||||
| AppLegacyDatasetToolResponse
|
||||
| AppLegacyGoogleSearchToolResponse
|
||||
| AppLegacyWebReaderToolResponse
|
||||
| AppLegacyWikipediaToolResponse
|
||||
| AppLegacyCurrentDatetimeToolResponse
|
||||
| AppLegacySensitiveWordToolResponseItem
|
||||
>
|
||||
[key: string]: unknown
|
||||
}
|
||||
|
||||
export type AppAnnotationReplyEnabledResponse = {
|
||||
embedding_model: AppEmbeddingModelResponse
|
||||
enabled: true
|
||||
id: string
|
||||
score_threshold: number
|
||||
}
|
||||
|
||||
export type AppAnnotationReplyDisabledResponse = {
|
||||
enabled: false
|
||||
}
|
||||
|
||||
export type AppChatPromptConfigResponse = {
|
||||
prompt?: Array<AppChatPromptMessageResponse>
|
||||
}
|
||||
|
||||
export type AppCompletionPromptConfigResponse = {
|
||||
conversation_histories_role?: AppConversationHistoriesRoleResponse
|
||||
prompt?: AppCompletionPromptTextResponse
|
||||
}
|
||||
|
||||
export type AppDatasetConfigsResponse = {
|
||||
datasets?: AppDatasetListResponse
|
||||
metadata_filtering_conditions?: AppMetadataFilteringConditionsResponse | null
|
||||
metadata_filtering_mode?: 'automatic' | 'disabled' | 'manual'
|
||||
metadata_model_config?: AppModelSelectionResponse | null
|
||||
reranking_enable?: boolean
|
||||
reranking_enabled?: boolean
|
||||
reranking_mode?: RerankMode
|
||||
reranking_model?: AppRerankingModelResponse | null
|
||||
retrieval_model: 'multiple' | 'single'
|
||||
score_threshold?: number | null
|
||||
score_threshold_enabled?: boolean
|
||||
top_k?: number
|
||||
weights?: AppWeightsResponse | null
|
||||
[key: string]: unknown
|
||||
}
|
||||
|
||||
export type AppEnabledExternalDataToolResponse = {
|
||||
config: {
|
||||
[key: string]: JsonValue2
|
||||
}
|
||||
enabled: true
|
||||
icon?: string
|
||||
icon_background?: string
|
||||
label?: string
|
||||
type: string
|
||||
variable: string
|
||||
[key: string]: unknown
|
||||
}
|
||||
|
||||
export type AppDisabledExternalDataToolResponse = {
|
||||
config?: {
|
||||
[key: string]: JsonValue2
|
||||
}
|
||||
enabled: false
|
||||
icon?: string
|
||||
icon_background?: string
|
||||
label?: string
|
||||
type?: string
|
||||
variable?: string
|
||||
[key: string]: unknown
|
||||
}
|
||||
|
||||
export type AppFileUploadResponse = {
|
||||
allowed_file_extensions?: Array<string>
|
||||
allowed_file_types?: Array<FileType>
|
||||
allowed_file_upload_methods?: Array<FileTransferMethod>
|
||||
enabled?: boolean
|
||||
image?: AppImageUploadResponse
|
||||
number_limits?: number
|
||||
}
|
||||
|
||||
export type AppModelSelectionResponse = {
|
||||
completion_params?: {
|
||||
[key: string]: JsonValue2
|
||||
}
|
||||
mode?: LlmMode | ''
|
||||
name?: string
|
||||
provider?: string
|
||||
[key: string]: unknown
|
||||
}
|
||||
|
||||
export type AppEnabledConfigResponse = {
|
||||
enabled: boolean
|
||||
}
|
||||
|
||||
export type PromptType = 'advanced' | 'simple'
|
||||
|
||||
export type AppSensitiveWordAvoidanceResponse = {
|
||||
config?: {
|
||||
[key: string]: JsonValue2
|
||||
}
|
||||
configs?: Array<JsonValue2>
|
||||
enabled: boolean
|
||||
type?: string
|
||||
[key: string]: unknown
|
||||
}
|
||||
|
||||
export type AppSuggestedQuestionsAfterAnswerResponse = {
|
||||
enabled: boolean
|
||||
model?: AppModelSelectionResponse
|
||||
prompt?: string
|
||||
}
|
||||
|
||||
export type AppTextToSpeechResponse = {
|
||||
autoPlay?: 'disabled' | 'enabled'
|
||||
enabled: boolean
|
||||
language?: string
|
||||
voice?: string
|
||||
}
|
||||
|
||||
export type AppTextInputFormResponse = {
|
||||
'text-input': AppUserInputFormConfigResponse
|
||||
}
|
||||
|
||||
export type AppSelectFormResponse = {
|
||||
select: AppUserInputFormConfigResponse
|
||||
}
|
||||
|
||||
export type AppParagraphFormResponse = {
|
||||
paragraph: AppUserInputFormConfigResponse
|
||||
}
|
||||
|
||||
export type AppNumberFormResponse = {
|
||||
number: AppUserInputFormConfigResponse
|
||||
}
|
||||
|
||||
export type AppCheckboxFormResponse = {
|
||||
checkbox: AppUserInputFormConfigResponse
|
||||
}
|
||||
|
||||
export type AppFileFormResponse = {
|
||||
file: AppUserInputFormConfigResponse
|
||||
}
|
||||
|
||||
export type AppFileListFormResponse = {
|
||||
'file-list': AppUserInputFormConfigResponse
|
||||
}
|
||||
|
||||
export type AppExternalDataToolFormResponse = {
|
||||
external_data_tool: AppUserInputFormConfigResponse
|
||||
}
|
||||
|
||||
export type AppJsonObjectFormResponse = {
|
||||
json_object: AppUserInputFormConfigResponse
|
||||
}
|
||||
|
||||
export type CustomizeTokenStrategy = 'allow' | 'must' | 'not_allow' | 'uuid'
|
||||
|
||||
export type AgentKind = 'dify_agent'
|
||||
|
||||
export type AgentPublishedReferenceResponse = {
|
||||
@@ -1341,6 +1531,158 @@ export type AgentConfigRevisionOperation =
|
||||
| 'save_new_version'
|
||||
| 'save_to_roster'
|
||||
|
||||
export type AppAgentPromptResponse = {
|
||||
first_prompt?: string
|
||||
next_iteration?: string
|
||||
[key: string]: unknown
|
||||
}
|
||||
|
||||
export type PlanningStrategy = 'function_call' | 'react' | 'react_router' | 'router'
|
||||
|
||||
export type AppProviderAgentToolResponse = {
|
||||
credential_id?: string | null
|
||||
enabled?: boolean
|
||||
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]: JsonValue2
|
||||
}
|
||||
[key: string]: unknown
|
||||
}
|
||||
|
||||
export type AppLegacyDatasetToolResponse = {
|
||||
dataset: AppDatasetReferenceResponse
|
||||
[key: string]: unknown
|
||||
}
|
||||
|
||||
export type AppLegacyGoogleSearchToolResponse = {
|
||||
google_search: {
|
||||
[key: string]: JsonValue2
|
||||
}
|
||||
[key: string]: unknown
|
||||
}
|
||||
|
||||
export type AppLegacyWebReaderToolResponse = {
|
||||
web_reader: {
|
||||
[key: string]: JsonValue2
|
||||
}
|
||||
[key: string]: unknown
|
||||
}
|
||||
|
||||
export type AppLegacyWikipediaToolResponse = {
|
||||
wikipedia: {
|
||||
[key: string]: JsonValue2
|
||||
}
|
||||
[key: string]: unknown
|
||||
}
|
||||
|
||||
export type AppLegacyCurrentDatetimeToolResponse = {
|
||||
current_datetime: {
|
||||
[key: string]: JsonValue2
|
||||
}
|
||||
[key: string]: unknown
|
||||
}
|
||||
|
||||
export type AppLegacySensitiveWordToolResponseItem = {
|
||||
'sensitive-word-avoidance': AppLegacySensitiveWordToolResponse
|
||||
[key: string]: unknown
|
||||
}
|
||||
|
||||
export type AppEmbeddingModelResponse = {
|
||||
embedding_model_name: string
|
||||
embedding_provider_name: string
|
||||
}
|
||||
|
||||
export type AppChatPromptMessageResponse = {
|
||||
role: string
|
||||
text: string
|
||||
}
|
||||
|
||||
export type AppConversationHistoriesRoleResponse = {
|
||||
assistant_prefix: string
|
||||
user_prefix: string
|
||||
}
|
||||
|
||||
export type AppCompletionPromptTextResponse = {
|
||||
text: string
|
||||
}
|
||||
|
||||
export type AppDatasetListResponse = {
|
||||
datasets: Array<AppDatasetItemResponse>
|
||||
strategy?: string
|
||||
[key: string]: unknown
|
||||
}
|
||||
|
||||
export type AppMetadataFilteringConditionsResponse = {
|
||||
conditions?: Array<AppMetadataConditionResponse> | null
|
||||
logical_operator?: 'and' | 'or' | null
|
||||
[key: string]: unknown
|
||||
}
|
||||
|
||||
export type RerankMode = 'reranking_model' | 'weighted_score'
|
||||
|
||||
export type AppRerankingModelResponse = {
|
||||
reranking_model_name?: string
|
||||
reranking_provider_name?: string
|
||||
[key: string]: unknown
|
||||
}
|
||||
|
||||
export type AppWeightsResponse = {
|
||||
keyword_setting: AppKeywordSettingResponse
|
||||
vector_setting: AppVectorSettingResponse
|
||||
weight_type?: 'customized' | 'keyword_first' | 'semantic_first'
|
||||
[key: string]: unknown
|
||||
}
|
||||
|
||||
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
|
||||
number_limits?: number
|
||||
transfer_methods?: Array<FileTransferMethod>
|
||||
}
|
||||
|
||||
export type LlmMode = 'chat' | 'completion'
|
||||
|
||||
export type AppUserInputFormConfigResponse = {
|
||||
allowed_file_extensions?: Array<string>
|
||||
allowed_file_types?: Array<FileType>
|
||||
allowed_file_upload_methods?: Array<FileTransferMethod>
|
||||
config?: {
|
||||
[key: string]: JsonValue2
|
||||
}
|
||||
default?: JsonValue2
|
||||
description?: string
|
||||
enabled?: boolean
|
||||
hide?: boolean
|
||||
icon?: string | null
|
||||
icon_background?: string | null
|
||||
json_schema?:
|
||||
| string
|
||||
| {
|
||||
[key: string]: JsonValue2
|
||||
}
|
||||
| null
|
||||
label: string
|
||||
max_length?: number | null
|
||||
options?: Array<string>
|
||||
required?: boolean
|
||||
type?: string
|
||||
variable: string
|
||||
[key: string]: unknown
|
||||
}
|
||||
|
||||
export type AgentFileUploadFeatureConfig = {
|
||||
allowed_file_extensions?: Array<string>
|
||||
allowed_file_types?: Array<FileType>
|
||||
@@ -1592,11 +1934,71 @@ export type FormInputConfig =
|
||||
type: 'file-list'
|
||||
} & FileListInputConfig)
|
||||
|
||||
export type JsonValue2 = unknown
|
||||
export type ToolProviderType =
|
||||
| 'api'
|
||||
| 'app'
|
||||
| 'builtin'
|
||||
| 'dataset-retrieval'
|
||||
| 'mcp'
|
||||
| 'plugin'
|
||||
| 'workflow'
|
||||
|
||||
export type FileType = 'audio' | 'custom' | 'document' | 'image' | 'video'
|
||||
export type AppDatasetReferenceResponse = {
|
||||
enabled?: boolean
|
||||
id?: string
|
||||
[key: string]: unknown
|
||||
}
|
||||
|
||||
export type FileTransferMethod = 'datasource_file' | 'local_file' | 'remote_url' | 'tool_file'
|
||||
export type AppLegacySensitiveWordToolResponse = {
|
||||
canned_response: string
|
||||
enabled: boolean
|
||||
words: Array<string>
|
||||
[key: string]: unknown
|
||||
}
|
||||
|
||||
export type AppDatasetItemResponse = {
|
||||
dataset: AppDatasetReferenceResponse
|
||||
[key: string]: unknown
|
||||
}
|
||||
|
||||
export type AppMetadataConditionResponse = {
|
||||
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]: unknown
|
||||
}
|
||||
|
||||
export type AppKeywordSettingResponse = {
|
||||
keyword_weight: number
|
||||
[key: string]: unknown
|
||||
}
|
||||
|
||||
export type AppVectorSettingResponse = {
|
||||
embedding_model_name: string
|
||||
embedding_provider_name: string
|
||||
vector_weight: number
|
||||
[key: string]: unknown
|
||||
}
|
||||
|
||||
export type AgentFileUploadImageFeatureConfig = {
|
||||
enabled?: boolean
|
||||
@@ -1642,15 +2044,6 @@ export type AgentSoulDifyToolCredentialRef = {
|
||||
type?: 'provider' | 'tool'
|
||||
}
|
||||
|
||||
export type ToolProviderType =
|
||||
| 'api'
|
||||
| 'app'
|
||||
| 'builtin'
|
||||
| 'dataset-retrieval'
|
||||
| 'mcp'
|
||||
| 'plugin'
|
||||
| 'workflow'
|
||||
|
||||
export type OutputErrorStrategy = 'default_value' | 'fail_branch' | 'stop'
|
||||
|
||||
export type DeclaredOutputRetryConfig = {
|
||||
@@ -1772,44 +2165,44 @@ export type AgentAppPaginationWritable = {
|
||||
}
|
||||
|
||||
export type AgentAppDetailWithSiteWritable = {
|
||||
access_mode?: string | null
|
||||
access_mode: WebAppAccessMode | null
|
||||
access_ready?: boolean
|
||||
api_base_url?: string | null
|
||||
api_base_url: string
|
||||
app_id?: string | null
|
||||
backing_app_id?: string | null
|
||||
bound_agent_id?: string | null
|
||||
created_at?: number | null
|
||||
created_by?: string | null
|
||||
created_at: number
|
||||
created_by: string | null
|
||||
debug_conversation_has_messages?: boolean
|
||||
debug_conversation_id?: string | null
|
||||
debug_conversation_message_count?: number
|
||||
deleted_tools?: Array<DeletedTool>
|
||||
description?: string | null
|
||||
deleted_tools: Array<DeletedTool>
|
||||
description: string
|
||||
enable_api: boolean
|
||||
enable_site: boolean
|
||||
hidden_app_backed?: boolean
|
||||
icon?: string | null
|
||||
icon_background?: string | null
|
||||
icon_type?: string | null
|
||||
icon: string | null
|
||||
icon_background: string | null
|
||||
icon_type: IconType | null
|
||||
id: string
|
||||
maintainer?: string | null
|
||||
max_active_requests?: number | null
|
||||
mode: string
|
||||
model_config?: AppModelConfigResponse | null
|
||||
maintainer: string | null
|
||||
max_active_requests: number | null
|
||||
mode: AppMode
|
||||
model_config: AppModelConfigResponse | null
|
||||
name: string
|
||||
permission_keys: Array<string>
|
||||
role?: string | null
|
||||
site?: AppDetailSiteResponseWritable | null
|
||||
tags?: Array<Tag>
|
||||
tracing?: unknown | null
|
||||
updated_at?: number | null
|
||||
updated_by?: string | null
|
||||
use_icon_as_answer_icon?: boolean | null
|
||||
workflow?: WorkflowPartial | null
|
||||
site: AppDetailSiteResponseWritable | null
|
||||
tags: Array<Tag>
|
||||
tracing: string | null
|
||||
updated_at: number
|
||||
updated_by: string | null
|
||||
use_icon_as_answer_icon: boolean
|
||||
workflow: WorkflowPartial | null
|
||||
}
|
||||
|
||||
export type AgentAppPartialWritable = {
|
||||
access_mode?: string | null
|
||||
access_mode?: WebAppAccessMode | null
|
||||
active_config_is_published?: boolean
|
||||
app_id?: string | null
|
||||
author_name?: string | null
|
||||
@@ -1824,12 +2217,12 @@ export type AgentAppPartialWritable = {
|
||||
hidden_app_backed?: boolean
|
||||
icon?: string | null
|
||||
icon_background?: string | null
|
||||
icon_type?: string | null
|
||||
icon_type?: IconType | null
|
||||
id: string
|
||||
is_starred?: boolean
|
||||
maintainer?: string | null
|
||||
max_active_requests?: number | null
|
||||
mode: string
|
||||
mode: AppMode
|
||||
model_config?: ModelConfigPartial | null
|
||||
name: string
|
||||
permission_keys: Array<string>
|
||||
@@ -1845,30 +2238,30 @@ export type AgentAppPartialWritable = {
|
||||
}
|
||||
|
||||
export type AppDetailSiteResponseWritable = {
|
||||
access_token?: string | null
|
||||
app_base_url?: string | null
|
||||
chat_color_theme?: string | null
|
||||
chat_color_theme_inverted?: boolean | null
|
||||
code?: string | null
|
||||
copyright?: string | null
|
||||
created_at?: number | null
|
||||
created_by?: string | null
|
||||
custom_disclaimer?: string | null
|
||||
customize_domain?: string | null
|
||||
customize_token_strategy?: string | null
|
||||
default_language?: string | null
|
||||
description?: string | null
|
||||
icon?: string | null
|
||||
icon_background?: string | null
|
||||
icon_type?: string | IconType | null
|
||||
input_placeholder?: string | null
|
||||
privacy_policy?: string | null
|
||||
prompt_public?: boolean | null
|
||||
show_workflow_steps?: boolean | null
|
||||
title?: string | null
|
||||
updated_at?: number | null
|
||||
updated_by?: string | null
|
||||
use_icon_as_answer_icon?: boolean | null
|
||||
access_token: string | null
|
||||
app_base_url: string
|
||||
chat_color_theme: string | null
|
||||
chat_color_theme_inverted: boolean
|
||||
code: string | null
|
||||
copyright: string | null
|
||||
created_at: number
|
||||
created_by: string | null
|
||||
custom_disclaimer: string
|
||||
customize_domain: string | null
|
||||
customize_token_strategy: CustomizeTokenStrategy
|
||||
default_language: string
|
||||
description: string | null
|
||||
icon: string | null
|
||||
icon_background: string | null
|
||||
icon_type: IconType | null
|
||||
input_placeholder: string | null
|
||||
privacy_policy: string | null
|
||||
prompt_public: boolean
|
||||
show_workflow_steps: boolean
|
||||
title: string
|
||||
updated_at: number
|
||||
updated_by: string | null
|
||||
use_icon_as_answer_icon: boolean
|
||||
}
|
||||
|
||||
export type GetAgentData = {
|
||||
|
||||
File diff suppressed because it is too large.
Load diff
@@ -22,34 +22,34 @@ export type CreateAppPayload = {
|
||||
}
|
||||
|
||||
export type AppDetailWithSite = {
|
||||
access_mode?: string | null
|
||||
api_base_url?: string | null
|
||||
app_id?: string | null
|
||||
bound_agent_id?: string | null
|
||||
created_at?: number | null
|
||||
created_by?: string | null
|
||||
deleted_tools?: Array<DeletedTool>
|
||||
description?: string | null
|
||||
access_mode: WebAppAccessMode | null
|
||||
api_base_url: string
|
||||
app_id: string | null
|
||||
bound_agent_id: string | null
|
||||
created_at: number
|
||||
created_by: string | null
|
||||
deleted_tools: Array<DeletedTool>
|
||||
description: string
|
||||
enable_api: boolean
|
||||
enable_site: boolean
|
||||
icon?: string | null
|
||||
icon_background?: string | null
|
||||
icon_type?: string | null
|
||||
icon: string | null
|
||||
icon_background: string | null
|
||||
icon_type: IconType | null
|
||||
readonly icon_url: string | null
|
||||
id: string
|
||||
maintainer?: string | null
|
||||
max_active_requests?: number | null
|
||||
mode: string
|
||||
model_config?: AppModelConfigResponse | null
|
||||
maintainer: string | null
|
||||
max_active_requests: number | null
|
||||
mode: AppMode
|
||||
model_config: AppModelConfigResponse | null
|
||||
name: string
|
||||
permission_keys?: Array<string>
|
||||
site?: AppDetailSiteResponse | null
|
||||
tags?: Array<Tag>
|
||||
tracing?: unknown | null
|
||||
updated_at?: number | null
|
||||
updated_by?: string | null
|
||||
use_icon_as_answer_icon?: boolean | null
|
||||
workflow?: WorkflowPartial | null
|
||||
permission_keys: Array<string>
|
||||
site: AppDetailSiteResponse | null
|
||||
tags: Array<Tag>
|
||||
tracing: string | null
|
||||
updated_at: number
|
||||
updated_by: string | null
|
||||
use_icon_as_answer_icon: boolean
|
||||
workflow: WorkflowPartial | null
|
||||
}
|
||||
|
||||
export type AppImportPayload = {
|
||||
@@ -66,7 +66,7 @@ export type AppImportPayload = {
|
||||
|
||||
export type Import = {
|
||||
app_id?: string | null
|
||||
app_mode?: string | null
|
||||
app_mode?: AppMode | null
|
||||
current_dsl_version?: string
|
||||
error?: string
|
||||
id: string
|
||||
@@ -362,26 +362,26 @@ export type AppApiStatusPayload = {
|
||||
}
|
||||
|
||||
export type AppDetail = {
|
||||
access_mode?: string | null
|
||||
created_at?: number | null
|
||||
created_by?: string | null
|
||||
description?: string | null
|
||||
access_mode: WebAppAccessMode | null
|
||||
created_at: number
|
||||
created_by: string | null
|
||||
description: string
|
||||
enable_api: boolean
|
||||
enable_site: boolean
|
||||
icon?: string | null
|
||||
icon_background?: string | null
|
||||
icon: string | null
|
||||
icon_background: string | null
|
||||
id: string
|
||||
maintainer?: string | null
|
||||
mode: string
|
||||
model_config?: AppModelConfigResponse | null
|
||||
maintainer: string | null
|
||||
mode: AppMode
|
||||
model_config: AppModelConfigResponse | null
|
||||
name: string
|
||||
permission_keys?: Array<string>
|
||||
tags?: Array<Tag>
|
||||
tracing?: unknown | null
|
||||
updated_at?: number | null
|
||||
updated_by?: string | null
|
||||
use_icon_as_answer_icon?: boolean | null
|
||||
workflow?: WorkflowPartial | null
|
||||
permission_keys: Array<string>
|
||||
tags: Array<Tag>
|
||||
tracing: string | null
|
||||
updated_at: number
|
||||
updated_by: string | null
|
||||
use_icon_as_answer_icon: boolean
|
||||
workflow: WorkflowPartial | null
|
||||
}
|
||||
|
||||
export type AudioTranscriptResponse = {
|
||||
@@ -488,7 +488,7 @@ export type CopyAppPayload = {
|
||||
|
||||
export type AppImportResponse = {
|
||||
app_id?: string | null
|
||||
app_mode?: string | null
|
||||
app_mode?: AppMode | null
|
||||
current_dsl_version: string
|
||||
error?: string
|
||||
id: string
|
||||
@@ -1199,7 +1199,7 @@ export type ApiKeyItem = {
|
||||
}
|
||||
|
||||
export type AppPartial = {
|
||||
access_mode?: string | null
|
||||
access_mode?: WebAppAccessMode | null
|
||||
app_id?: string | null
|
||||
author_name?: string | null
|
||||
bound_agent_id?: string | null
|
||||
@@ -1210,13 +1210,13 @@ export type AppPartial = {
|
||||
has_draft_trigger?: boolean | null
|
||||
icon?: string | null
|
||||
icon_background?: string | null
|
||||
icon_type?: string | null
|
||||
icon_type?: IconType | null
|
||||
readonly icon_url: string | null
|
||||
id: string
|
||||
is_starred?: boolean
|
||||
maintainer?: string | null
|
||||
max_active_requests?: number | null
|
||||
mode: string
|
||||
mode: AppMode
|
||||
model_config?: ModelConfigPartial | null
|
||||
name: string
|
||||
permission_keys?: Array<string>
|
||||
@@ -1229,65 +1229,89 @@ export type AppPartial = {
|
||||
|
||||
export type IconType = 'emoji' | 'image' | 'link'
|
||||
|
||||
export type WebAppAccessMode = 'private' | 'private_all' | 'public' | 'sso_verified'
|
||||
|
||||
export type DeletedTool = {
|
||||
provider_id: string
|
||||
tool_name: string
|
||||
type: string
|
||||
}
|
||||
|
||||
export type AppMode =
|
||||
| 'advanced-chat'
|
||||
| 'agent'
|
||||
| 'agent-chat'
|
||||
| 'channel'
|
||||
| 'chat'
|
||||
| 'completion'
|
||||
| 'rag-pipeline'
|
||||
| 'workflow'
|
||||
|
||||
export type AppModelConfigResponse = {
|
||||
agent_mode?: unknown | null
|
||||
annotation_reply?: unknown | null
|
||||
chat_prompt_config?: unknown | null
|
||||
completion_prompt_config?: unknown | null
|
||||
created_at?: number | null
|
||||
created_by?: string | null
|
||||
dataset_configs?: unknown | null
|
||||
dataset_query_variable?: string | null
|
||||
external_data_tools?: unknown | null
|
||||
file_upload?: unknown | null
|
||||
model?: unknown | null
|
||||
more_like_this?: unknown | null
|
||||
opening_statement?: string | null
|
||||
pre_prompt?: string | null
|
||||
prompt_type?: string | null
|
||||
retriever_resource?: unknown | null
|
||||
sensitive_word_avoidance?: unknown | null
|
||||
speech_to_text?: unknown | null
|
||||
suggested_questions?: unknown | null
|
||||
suggested_questions_after_answer?: unknown | null
|
||||
text_to_speech?: unknown | null
|
||||
updated_at?: number | null
|
||||
updated_by?: string | null
|
||||
user_input_form?: unknown | null
|
||||
agent_mode: AppAgentModeResponse
|
||||
annotation_reply: AppAnnotationReplyEnabledResponse | AppAnnotationReplyDisabledResponse
|
||||
chat_prompt_config: AppChatPromptConfigResponse
|
||||
completion_prompt_config: AppCompletionPromptConfigResponse
|
||||
created_at: number
|
||||
created_by: string | null
|
||||
dataset_configs: AppDatasetConfigsResponse
|
||||
dataset_query_variable: string | null
|
||||
external_data_tools: Array<
|
||||
AppEnabledExternalDataToolResponse | AppDisabledExternalDataToolResponse
|
||||
>
|
||||
file_upload: AppFileUploadResponse
|
||||
model: AppModelSelectionResponse
|
||||
more_like_this: AppEnabledConfigResponse
|
||||
opening_statement: string | null
|
||||
pre_prompt: string | null
|
||||
prompt_type: PromptType
|
||||
retriever_resource: AppEnabledConfigResponse
|
||||
sensitive_word_avoidance: AppSensitiveWordAvoidanceResponse
|
||||
speech_to_text: AppEnabledConfigResponse
|
||||
suggested_questions: Array<string>
|
||||
suggested_questions_after_answer: AppSuggestedQuestionsAfterAnswerResponse
|
||||
text_to_speech: AppTextToSpeechResponse
|
||||
updated_at: number
|
||||
updated_by: string | null
|
||||
user_input_form: Array<
|
||||
| AppTextInputFormResponse
|
||||
| AppSelectFormResponse
|
||||
| AppParagraphFormResponse
|
||||
| AppNumberFormResponse
|
||||
| AppCheckboxFormResponse
|
||||
| AppFileFormResponse
|
||||
| AppFileListFormResponse
|
||||
| AppExternalDataToolFormResponse
|
||||
| AppJsonObjectFormResponse
|
||||
>
|
||||
}
|
||||
|
||||
export type AppDetailSiteResponse = {
|
||||
access_token?: string | null
|
||||
app_base_url?: string | null
|
||||
chat_color_theme?: string | null
|
||||
chat_color_theme_inverted?: boolean | null
|
||||
code?: string | null
|
||||
copyright?: string | null
|
||||
created_at?: number | null
|
||||
created_by?: string | null
|
||||
custom_disclaimer?: string | null
|
||||
customize_domain?: string | null
|
||||
customize_token_strategy?: string | null
|
||||
default_language?: string | null
|
||||
description?: string | null
|
||||
icon?: string | null
|
||||
icon_background?: string | null
|
||||
icon_type?: string | IconType | null
|
||||
access_token: string | null
|
||||
app_base_url: string
|
||||
chat_color_theme: string | null
|
||||
chat_color_theme_inverted: boolean
|
||||
code: string | null
|
||||
copyright: string | null
|
||||
created_at: number
|
||||
created_by: string | null
|
||||
custom_disclaimer: string
|
||||
customize_domain: string | null
|
||||
customize_token_strategy: CustomizeTokenStrategy
|
||||
default_language: string
|
||||
description: string | null
|
||||
icon: string | null
|
||||
icon_background: string | null
|
||||
icon_type: IconType | null
|
||||
readonly icon_url: string | null
|
||||
input_placeholder?: string | null
|
||||
privacy_policy?: string | null
|
||||
prompt_public?: boolean | null
|
||||
show_workflow_steps?: boolean | null
|
||||
title?: string | null
|
||||
updated_at?: number | null
|
||||
updated_by?: string | null
|
||||
use_icon_as_answer_icon?: boolean | null
|
||||
input_placeholder: string | null
|
||||
privacy_policy: string | null
|
||||
prompt_public: boolean
|
||||
show_workflow_steps: boolean
|
||||
title: string
|
||||
updated_at: number
|
||||
updated_by: string | null
|
||||
use_icon_as_answer_icon: boolean
|
||||
}
|
||||
|
||||
export type Tag = {
|
||||
@@ -2088,12 +2112,178 @@ export type WorkflowDraftVariableFullContentResponse = {
|
||||
export type ModelConfigPartial = {
|
||||
created_at?: number | null
|
||||
created_by?: string | null
|
||||
model?: unknown | null
|
||||
model?: AppModelSelectionResponse | null
|
||||
pre_prompt?: string | null
|
||||
updated_at?: number | null
|
||||
updated_by?: string | null
|
||||
}
|
||||
|
||||
export type AppAgentModeResponse = {
|
||||
enabled: boolean
|
||||
max_iteration?: number
|
||||
prompt?: AppAgentPromptResponse | string | null
|
||||
strategy?: PlanningStrategy | 'cot' | 'function-calling' | null
|
||||
tools?: Array<
|
||||
| AppProviderAgentToolResponse
|
||||
| AppLegacyDatasetToolResponse
|
||||
| AppLegacyGoogleSearchToolResponse
|
||||
| AppLegacyWebReaderToolResponse
|
||||
| AppLegacyWikipediaToolResponse
|
||||
| AppLegacyCurrentDatetimeToolResponse
|
||||
| AppLegacySensitiveWordToolResponseItem
|
||||
>
|
||||
[key: string]: unknown
|
||||
}
|
||||
|
||||
export type AppAnnotationReplyEnabledResponse = {
|
||||
embedding_model: AppEmbeddingModelResponse
|
||||
enabled: true
|
||||
id: string
|
||||
score_threshold: number
|
||||
}
|
||||
|
||||
export type AppAnnotationReplyDisabledResponse = {
|
||||
enabled: false
|
||||
}
|
||||
|
||||
export type AppChatPromptConfigResponse = {
|
||||
prompt?: Array<AppChatPromptMessageResponse>
|
||||
}
|
||||
|
||||
export type AppCompletionPromptConfigResponse = {
|
||||
conversation_histories_role?: AppConversationHistoriesRoleResponse
|
||||
prompt?: AppCompletionPromptTextResponse
|
||||
}
|
||||
|
||||
export type AppDatasetConfigsResponse = {
|
||||
datasets?: AppDatasetListResponse
|
||||
metadata_filtering_conditions?: AppMetadataFilteringConditionsResponse | null
|
||||
metadata_filtering_mode?: 'automatic' | 'disabled' | 'manual'
|
||||
metadata_model_config?: AppModelSelectionResponse | null
|
||||
reranking_enable?: boolean
|
||||
reranking_enabled?: boolean
|
||||
reranking_mode?: RerankMode
|
||||
reranking_model?: AppRerankingModelResponse | null
|
||||
retrieval_model: 'multiple' | 'single'
|
||||
score_threshold?: number | null
|
||||
score_threshold_enabled?: boolean
|
||||
top_k?: number
|
||||
weights?: AppWeightsResponse | null
|
||||
[key: string]: unknown
|
||||
}
|
||||
|
||||
export type AppEnabledExternalDataToolResponse = {
|
||||
config: {
|
||||
[key: string]: JsonValue2
|
||||
}
|
||||
enabled: true
|
||||
icon?: string
|
||||
icon_background?: string
|
||||
label?: string
|
||||
type: string
|
||||
variable: string
|
||||
[key: string]: unknown
|
||||
}
|
||||
|
||||
export type AppDisabledExternalDataToolResponse = {
|
||||
config?: {
|
||||
[key: string]: JsonValue2
|
||||
}
|
||||
enabled: false
|
||||
icon?: string
|
||||
icon_background?: string
|
||||
label?: string
|
||||
type?: string
|
||||
variable?: string
|
||||
[key: string]: unknown
|
||||
}
|
||||
|
||||
export type AppFileUploadResponse = {
|
||||
allowed_file_extensions?: Array<string>
|
||||
allowed_file_types?: Array<FileType>
|
||||
allowed_file_upload_methods?: Array<FileTransferMethod>
|
||||
enabled?: boolean
|
||||
image?: AppImageUploadResponse
|
||||
number_limits?: number
|
||||
}
|
||||
|
||||
export type AppModelSelectionResponse = {
|
||||
completion_params?: {
|
||||
[key: string]: JsonValue2
|
||||
}
|
||||
mode?: LlmMode | ''
|
||||
name?: string
|
||||
provider?: string
|
||||
[key: string]: unknown
|
||||
}
|
||||
|
||||
export type AppEnabledConfigResponse = {
|
||||
enabled: boolean
|
||||
}
|
||||
|
||||
export type PromptType = 'advanced' | 'simple'
|
||||
|
||||
export type AppSensitiveWordAvoidanceResponse = {
|
||||
config?: {
|
||||
[key: string]: JsonValue2
|
||||
}
|
||||
configs?: Array<JsonValue2>
|
||||
enabled: boolean
|
||||
type?: string
|
||||
[key: string]: unknown
|
||||
}
|
||||
|
||||
export type AppSuggestedQuestionsAfterAnswerResponse = {
|
||||
enabled: boolean
|
||||
model?: AppModelSelectionResponse
|
||||
prompt?: string
|
||||
}
|
||||
|
||||
export type AppTextToSpeechResponse = {
|
||||
autoPlay?: 'disabled' | 'enabled'
|
||||
enabled: boolean
|
||||
language?: string
|
||||
voice?: string
|
||||
}
|
||||
|
||||
export type AppTextInputFormResponse = {
|
||||
'text-input': AppUserInputFormConfigResponse
|
||||
}
|
||||
|
||||
export type AppSelectFormResponse = {
|
||||
select: AppUserInputFormConfigResponse
|
||||
}
|
||||
|
||||
export type AppParagraphFormResponse = {
|
||||
paragraph: AppUserInputFormConfigResponse
|
||||
}
|
||||
|
||||
export type AppNumberFormResponse = {
|
||||
number: AppUserInputFormConfigResponse
|
||||
}
|
||||
|
||||
export type AppCheckboxFormResponse = {
|
||||
checkbox: AppUserInputFormConfigResponse
|
||||
}
|
||||
|
||||
export type AppFileFormResponse = {
|
||||
file: AppUserInputFormConfigResponse
|
||||
}
|
||||
|
||||
export type AppFileListFormResponse = {
|
||||
'file-list': AppUserInputFormConfigResponse
|
||||
}
|
||||
|
||||
export type AppExternalDataToolFormResponse = {
|
||||
external_data_tool: AppUserInputFormConfigResponse
|
||||
}
|
||||
|
||||
export type AppJsonObjectFormResponse = {
|
||||
json_object: AppUserInputFormConfigResponse
|
||||
}
|
||||
|
||||
export type CustomizeTokenStrategy = 'allow' | 'must' | 'not_allow' | 'uuid'
|
||||
|
||||
export type PluginDependencyType = 'github' | 'marketplace' | 'package'
|
||||
|
||||
export type Github = {
|
||||
@@ -2250,7 +2440,7 @@ export type WorkflowSuggestedQuestionsAfterAnswerPayload = {
|
||||
}
|
||||
|
||||
export type WorkflowTextToSpeechPayload = {
|
||||
autoPlay?: string | null
|
||||
autoPlay?: 'disabled' | 'enabled' | null
|
||||
enabled?: boolean | null
|
||||
language?: string | null
|
||||
voice?: string | null
|
||||
@@ -2484,6 +2674,156 @@ export type CheckResultView = {
|
||||
reason?: string | null
|
||||
}
|
||||
|
||||
export type AppAgentPromptResponse = {
|
||||
first_prompt?: string
|
||||
next_iteration?: string
|
||||
[key: string]: unknown
|
||||
}
|
||||
|
||||
export type PlanningStrategy = 'function_call' | 'react' | 'react_router' | 'router'
|
||||
|
||||
export type AppProviderAgentToolResponse = {
|
||||
credential_id?: string | null
|
||||
enabled?: boolean
|
||||
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]: JsonValue2
|
||||
}
|
||||
[key: string]: unknown
|
||||
}
|
||||
|
||||
export type AppLegacyDatasetToolResponse = {
|
||||
dataset: AppDatasetReferenceResponse
|
||||
[key: string]: unknown
|
||||
}
|
||||
|
||||
export type AppLegacyGoogleSearchToolResponse = {
|
||||
google_search: {
|
||||
[key: string]: JsonValue2
|
||||
}
|
||||
[key: string]: unknown
|
||||
}
|
||||
|
||||
export type AppLegacyWebReaderToolResponse = {
|
||||
web_reader: {
|
||||
[key: string]: JsonValue2
|
||||
}
|
||||
[key: string]: unknown
|
||||
}
|
||||
|
||||
export type AppLegacyWikipediaToolResponse = {
|
||||
wikipedia: {
|
||||
[key: string]: JsonValue2
|
||||
}
|
||||
[key: string]: unknown
|
||||
}
|
||||
|
||||
export type AppLegacyCurrentDatetimeToolResponse = {
|
||||
current_datetime: {
|
||||
[key: string]: JsonValue2
|
||||
}
|
||||
[key: string]: unknown
|
||||
}
|
||||
|
||||
export type AppLegacySensitiveWordToolResponseItem = {
|
||||
'sensitive-word-avoidance': AppLegacySensitiveWordToolResponse
|
||||
[key: string]: unknown
|
||||
}
|
||||
|
||||
export type AppEmbeddingModelResponse = {
|
||||
embedding_model_name: string
|
||||
embedding_provider_name: string
|
||||
}
|
||||
|
||||
export type AppChatPromptMessageResponse = {
|
||||
role: string
|
||||
text: string
|
||||
}
|
||||
|
||||
export type AppConversationHistoriesRoleResponse = {
|
||||
assistant_prefix: string
|
||||
user_prefix: string
|
||||
}
|
||||
|
||||
export type AppCompletionPromptTextResponse = {
|
||||
text: string
|
||||
}
|
||||
|
||||
export type AppDatasetListResponse = {
|
||||
datasets: Array<AppDatasetItemResponse>
|
||||
strategy?: string
|
||||
[key: string]: unknown
|
||||
}
|
||||
|
||||
export type AppMetadataFilteringConditionsResponse = {
|
||||
conditions?: Array<AppMetadataConditionResponse> | null
|
||||
logical_operator?: 'and' | 'or' | null
|
||||
[key: string]: unknown
|
||||
}
|
||||
|
||||
export type RerankMode = 'reranking_model' | 'weighted_score'
|
||||
|
||||
export type AppRerankingModelResponse = {
|
||||
reranking_model_name?: string
|
||||
reranking_provider_name?: string
|
||||
[key: string]: unknown
|
||||
}
|
||||
|
||||
export type AppWeightsResponse = {
|
||||
keyword_setting: AppKeywordSettingResponse
|
||||
vector_setting: AppVectorSettingResponse
|
||||
weight_type?: 'customized' | 'keyword_first' | 'semantic_first'
|
||||
[key: string]: unknown
|
||||
}
|
||||
|
||||
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
|
||||
number_limits?: number
|
||||
transfer_methods?: Array<FileTransferMethod>
|
||||
}
|
||||
|
||||
export type AppUserInputFormConfigResponse = {
|
||||
allowed_file_extensions?: Array<string>
|
||||
allowed_file_types?: Array<FileType>
|
||||
allowed_file_upload_methods?: Array<FileTransferMethod>
|
||||
config?: {
|
||||
[key: string]: JsonValue2
|
||||
}
|
||||
default?: JsonValue2
|
||||
description?: string
|
||||
enabled?: boolean
|
||||
hide?: boolean
|
||||
icon?: string | null
|
||||
icon_background?: string | null
|
||||
json_schema?:
|
||||
| string
|
||||
| {
|
||||
[key: string]: JsonValue2
|
||||
}
|
||||
| null
|
||||
label: string
|
||||
max_length?: number | null
|
||||
options?: Array<string>
|
||||
required?: boolean
|
||||
type?: string
|
||||
variable: string
|
||||
[key: string]: unknown
|
||||
}
|
||||
|
||||
export type UserActionConfig = {
|
||||
button_style?: ButtonStyle
|
||||
id: string
|
||||
@@ -2504,8 +2844,6 @@ export type FormInputConfig =
|
||||
type: 'file-list'
|
||||
} & FileListInputConfig)
|
||||
|
||||
export type JsonValue2 = unknown
|
||||
|
||||
export type WorkflowFileUploadTransferPayload = {
|
||||
enabled?: boolean | null
|
||||
number_limits?: number | null
|
||||
@@ -2556,7 +2894,7 @@ export type AgentSuggestedQuestionsAfterAnswerFeatureConfig = {
|
||||
}
|
||||
|
||||
export type AgentTextToSpeechFeatureConfig = {
|
||||
autoPlay?: string | null
|
||||
autoPlay?: 'disabled' | 'enabled' | null
|
||||
enabled?: boolean
|
||||
language?: string | null
|
||||
voice?: string | null
|
||||
@@ -2743,6 +3081,72 @@ export type AgentComposerKnowledgeDatasetCandidateResponse = {
|
||||
name?: string | null
|
||||
}
|
||||
|
||||
export type ToolProviderType =
|
||||
| 'api'
|
||||
| 'app'
|
||||
| 'builtin'
|
||||
| 'dataset-retrieval'
|
||||
| 'mcp'
|
||||
| 'plugin'
|
||||
| 'workflow'
|
||||
|
||||
export type AppDatasetReferenceResponse = {
|
||||
enabled?: boolean
|
||||
id?: string
|
||||
[key: string]: unknown
|
||||
}
|
||||
|
||||
export type AppLegacySensitiveWordToolResponse = {
|
||||
canned_response: string
|
||||
enabled: boolean
|
||||
words: Array<string>
|
||||
[key: string]: unknown
|
||||
}
|
||||
|
||||
export type AppDatasetItemResponse = {
|
||||
dataset: AppDatasetReferenceResponse
|
||||
[key: string]: unknown
|
||||
}
|
||||
|
||||
export type AppMetadataConditionResponse = {
|
||||
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]: unknown
|
||||
}
|
||||
|
||||
export type AppKeywordSettingResponse = {
|
||||
keyword_weight: number
|
||||
[key: string]: unknown
|
||||
}
|
||||
|
||||
export type AppVectorSettingResponse = {
|
||||
embedding_model_name: string
|
||||
embedding_provider_name: string
|
||||
vector_weight: number
|
||||
[key: string]: unknown
|
||||
}
|
||||
|
||||
export type ButtonStyle = 'accent' | 'default' | 'ghost' | 'primary'
|
||||
|
||||
export type ParagraphInputConfig = {
|
||||
@@ -2774,10 +3178,6 @@ export type FileListInputConfig = {
|
||||
type?: 'file-list'
|
||||
}
|
||||
|
||||
export type FileType = 'audio' | 'custom' | 'document' | 'image' | 'video'
|
||||
|
||||
export type FileTransferMethod = 'datasource_file' | 'local_file' | 'remote_url' | 'tool_file'
|
||||
|
||||
export type AgentFileUploadImageFeatureConfig = {
|
||||
enabled?: boolean
|
||||
[key: string]: unknown
|
||||
@@ -2840,15 +3240,6 @@ export type AgentSoulDifyToolCredentialRef = {
|
||||
type?: 'provider' | 'tool'
|
||||
}
|
||||
|
||||
export type ToolProviderType =
|
||||
| 'api'
|
||||
| 'app'
|
||||
| 'builtin'
|
||||
| 'dataset-retrieval'
|
||||
| 'mcp'
|
||||
| 'plugin'
|
||||
| 'workflow'
|
||||
|
||||
export type StringSource = {
|
||||
selector?: Array<string>
|
||||
type: ValueSourceType
|
||||
@@ -2936,33 +3327,33 @@ export type AppPaginationWritable = {
|
||||
}
|
||||
|
||||
export type AppDetailWithSiteWritable = {
|
||||
access_mode?: string | null
|
||||
api_base_url?: string | null
|
||||
app_id?: string | null
|
||||
bound_agent_id?: string | null
|
||||
created_at?: number | null
|
||||
created_by?: string | null
|
||||
deleted_tools?: Array<DeletedTool>
|
||||
description?: string | null
|
||||
access_mode: WebAppAccessMode | null
|
||||
api_base_url: string
|
||||
app_id: string | null
|
||||
bound_agent_id: string | null
|
||||
created_at: number
|
||||
created_by: string | null
|
||||
deleted_tools: Array<DeletedTool>
|
||||
description: string
|
||||
enable_api: boolean
|
||||
enable_site: boolean
|
||||
icon?: string | null
|
||||
icon_background?: string | null
|
||||
icon_type?: string | null
|
||||
icon: string | null
|
||||
icon_background: string | null
|
||||
icon_type: IconType | null
|
||||
id: string
|
||||
maintainer?: string | null
|
||||
max_active_requests?: number | null
|
||||
mode: string
|
||||
model_config?: AppModelConfigResponse | null
|
||||
maintainer: string | null
|
||||
max_active_requests: number | null
|
||||
mode: AppMode
|
||||
model_config: AppModelConfigResponse | null
|
||||
name: string
|
||||
permission_keys?: Array<string>
|
||||
site?: AppDetailSiteResponseWritable | null
|
||||
tags?: Array<Tag>
|
||||
tracing?: unknown | null
|
||||
updated_at?: number | null
|
||||
updated_by?: string | null
|
||||
use_icon_as_answer_icon?: boolean | null
|
||||
workflow?: WorkflowPartial | null
|
||||
permission_keys: Array<string>
|
||||
site: AppDetailSiteResponseWritable | null
|
||||
tags: Array<Tag>
|
||||
tracing: string | null
|
||||
updated_at: number
|
||||
updated_by: string | null
|
||||
use_icon_as_answer_icon: boolean
|
||||
workflow: WorkflowPartial | null
|
||||
}
|
||||
|
||||
export type RecentAppListResponseWritable = {
|
||||
@@ -2997,7 +3388,7 @@ export type WorkflowCommentDetailWritable = {
|
||||
}
|
||||
|
||||
export type AppPartialWritable = {
|
||||
access_mode?: string | null
|
||||
access_mode?: WebAppAccessMode | null
|
||||
app_id?: string | null
|
||||
author_name?: string | null
|
||||
bound_agent_id?: string | null
|
||||
@@ -3008,12 +3399,12 @@ export type AppPartialWritable = {
|
||||
has_draft_trigger?: boolean | null
|
||||
icon?: string | null
|
||||
icon_background?: string | null
|
||||
icon_type?: string | null
|
||||
icon_type?: IconType | null
|
||||
id: string
|
||||
is_starred?: boolean
|
||||
maintainer?: string | null
|
||||
max_active_requests?: number | null
|
||||
mode: string
|
||||
mode: AppMode
|
||||
model_config?: ModelConfigPartial | null
|
||||
name: string
|
||||
permission_keys?: Array<string>
|
||||
@@ -3025,30 +3416,30 @@ export type AppPartialWritable = {
|
||||
}
|
||||
|
||||
export type AppDetailSiteResponseWritable = {
|
||||
access_token?: string | null
|
||||
app_base_url?: string | null
|
||||
chat_color_theme?: string | null
|
||||
chat_color_theme_inverted?: boolean | null
|
||||
code?: string | null
|
||||
copyright?: string | null
|
||||
created_at?: number | null
|
||||
created_by?: string | null
|
||||
custom_disclaimer?: string | null
|
||||
customize_domain?: string | null
|
||||
customize_token_strategy?: string | null
|
||||
default_language?: string | null
|
||||
description?: string | null
|
||||
icon?: string | null
|
||||
icon_background?: string | null
|
||||
icon_type?: string | IconType | null
|
||||
input_placeholder?: string | null
|
||||
privacy_policy?: string | null
|
||||
prompt_public?: boolean | null
|
||||
show_workflow_steps?: boolean | null
|
||||
title?: string | null
|
||||
updated_at?: number | null
|
||||
updated_by?: string | null
|
||||
use_icon_as_answer_icon?: boolean | null
|
||||
access_token: string | null
|
||||
app_base_url: string
|
||||
chat_color_theme: string | null
|
||||
chat_color_theme_inverted: boolean
|
||||
code: string | null
|
||||
copyright: string | null
|
||||
created_at: number
|
||||
created_by: string | null
|
||||
custom_disclaimer: string
|
||||
customize_domain: string | null
|
||||
customize_token_strategy: CustomizeTokenStrategy
|
||||
default_language: string
|
||||
description: string | null
|
||||
icon: string | null
|
||||
icon_background: string | null
|
||||
icon_type: IconType | null
|
||||
input_placeholder: string | null
|
||||
privacy_policy: string | null
|
||||
prompt_public: boolean
|
||||
show_workflow_steps: boolean
|
||||
title: string
|
||||
updated_at: number
|
||||
updated_by: string | null
|
||||
use_icon_as_answer_icon: boolean
|
||||
}
|
||||
|
||||
export type RecentAppResponseWritable = {
|
||||
|
||||
File diff suppressed because it is too large.
Load diff
@@ -799,7 +799,7 @@ export type AgentSuggestedQuestionsAfterAnswerFeatureConfig = {
|
||||
}
|
||||
|
||||
export type AgentTextToSpeechFeatureConfig = {
|
||||
autoPlay?: string | null
|
||||
autoPlay?: 'disabled' | 'enabled' | null
|
||||
enabled?: boolean
|
||||
language?: string | null
|
||||
voice?: string | null
|
||||
|
||||
@@ -760,7 +760,7 @@ export const zAgentFeatureToggleConfig = z.object({
|
||||
* AgentTextToSpeechFeatureConfig
|
||||
*/
|
||||
export const zAgentTextToSpeechFeatureConfig = z.object({
|
||||
autoPlay: z.string().nullish(),
|
||||
autoPlay: z.enum(['disabled', 'enabled']).nullish(),
|
||||
enabled: z.boolean().optional().default(false),
|
||||
language: z.string().nullish(),
|
||||
voice: z.string().nullish(),
|
||||
|
||||
@@ -81,7 +81,7 @@ export type AppDslImportPayload = {
|
||||
|
||||
export type AppDslImportResponse = {
|
||||
app_id?: string | null
|
||||
app_mode?: string | null
|
||||
app_mode?: AppMode | null
|
||||
current_dsl_version?: string
|
||||
error?: string
|
||||
hints?: Array<Hint>
|
||||
@@ -305,7 +305,7 @@ export type HumanInputFormDefinitionResponse = {
|
||||
|
||||
export type Import = {
|
||||
app_id?: string | null
|
||||
app_mode?: string | null
|
||||
app_mode?: AppMode | null
|
||||
current_dsl_version?: string
|
||||
error?: string
|
||||
id: string
|
||||
|
||||
@@ -398,7 +398,7 @@ export const zImportStatus = z.enum(['completed', 'completed-with-warnings', 'fa
|
||||
*/
|
||||
export const zAppDslImportResponse = z.object({
|
||||
app_id: z.string().nullish(),
|
||||
app_mode: z.string().nullish(),
|
||||
app_mode: zAppMode.nullish(),
|
||||
current_dsl_version: z.string().optional().default('0.7.0'),
|
||||
error: z.string().optional().default(''),
|
||||
hints: z.array(zHint).optional(),
|
||||
@@ -414,7 +414,7 @@ export const zAppDslImportResponse = z.object({
|
||||
*/
|
||||
export const zImport = z.object({
|
||||
app_id: z.string().nullish(),
|
||||
app_mode: z.string().nullish(),
|
||||
app_mode: zAppMode.nullish(),
|
||||
current_dsl_version: z.string().optional().default('0.7.0'),
|
||||
error: z.string().optional().default(''),
|
||||
id: z.string(),
|
||||
|
||||
@@ -198,7 +198,7 @@ describe('useAppInfoActions', () => {
|
||||
|
||||
describe('onEdit', () => {
|
||||
it('should update app info and close modal on success', async () => {
|
||||
const updatedApp = { ...mockAppDetail, name: 'Updated' }
|
||||
const updatedApp = { ...mockAppDetail, name: 'Updated', max_active_requests: null }
|
||||
mockUpdateAppInfo.mockResolvedValue(updatedApp)
|
||||
|
||||
const { result } = renderHook(() => useAppInfoActions({}))
|
||||
@@ -222,8 +222,8 @@ describe('useAppInfoActions', () => {
|
||||
expect.any(Function),
|
||||
)
|
||||
const updateCachedApp = mockSetQueryData.mock.calls[0]![1]
|
||||
expect(updateCachedApp({ id: 'app-1', name: 'Old name' })).toEqual(
|
||||
expect.objectContaining({ id: 'app-1', name: 'Updated' }),
|
||||
expect(updateCachedApp({ id: 'app-1', name: 'Old name', max_active_requests: 5 })).toEqual(
|
||||
expect.objectContaining({ id: 'app-1', name: 'Updated', max_active_requests: null }),
|
||||
)
|
||||
expect(mockInvalidateQueries).toHaveBeenCalledWith({
|
||||
queryKey: consoleQuery.apps.get.key(),
|
||||
|
||||
@@ -68,7 +68,10 @@ const updateCachedAppMetadata = (cachedApp: AppDetailWithSite | undefined, app:
|
||||
icon_background: app.icon_background,
|
||||
icon_type: app.icon_type,
|
||||
icon_url: app.icon_url,
|
||||
max_active_requests: app.max_active_requests,
|
||||
max_active_requests:
|
||||
app.max_active_requests === undefined
|
||||
? cachedApp.max_active_requests
|
||||
: app.max_active_requests,
|
||||
name: app.name,
|
||||
updated_at: app.updated_at,
|
||||
use_icon_as_answer_icon: app.use_icon_as_answer_icon,
|
||||
|
||||
+8
-1
@@ -646,8 +646,12 @@ describe('SettingsModal', () => {
|
||||
it('should disable save button while saving', async () => {
|
||||
// Arrange
|
||||
const user = userEvent.setup()
|
||||
let finishSave!: (dataset: DataSet) => void
|
||||
mockUpdateDatasetSetting.mockImplementation(
|
||||
() => new Promise((resolve) => setTimeout(resolve, 100)),
|
||||
() =>
|
||||
new Promise((resolve) => {
|
||||
finishSave = resolve
|
||||
}),
|
||||
)
|
||||
|
||||
// Act
|
||||
@@ -658,6 +662,9 @@ describe('SettingsModal', () => {
|
||||
|
||||
// Assert
|
||||
expect(saveButton).toBeDisabled()
|
||||
|
||||
finishSave(createDataset())
|
||||
await waitFor(() => expect(saveButton).toBeEnabled())
|
||||
})
|
||||
|
||||
it('should show error toast when save fails', async () => {
|
||||
|
||||
@@ -4,6 +4,7 @@ import { consoleQuery } from '@/service/console'
|
||||
import { seedAccountProfileQuery } from '@/test/console/account-profile'
|
||||
import { createQueryClientWrapper } from '@/test/console/query-client'
|
||||
import { renderHook as renderHookWithConsoleState } from '@/test/console/render'
|
||||
import { createAppDetailFixture } from '@/test/fixtures/app'
|
||||
import { createTestQueryClient } from '@/test/query-client'
|
||||
import { AppModeEnum, ModelModeType } from '@/types/app'
|
||||
import { AppACLPermission } from '@/utils/permission'
|
||||
@@ -272,14 +273,17 @@ describe('useConfiguration', () => {
|
||||
const detailQueryKey = consoleQuery.apps.byAppId.get.queryKey({
|
||||
input: { params: { app_id: 'app-1' } },
|
||||
})
|
||||
queryClient.setQueryData(detailQueryKey, {
|
||||
enable_api: false,
|
||||
enable_site: false,
|
||||
icon_url: null,
|
||||
id: 'app-1',
|
||||
mode: 'chat',
|
||||
name: 'Cached app',
|
||||
})
|
||||
queryClient.setQueryData(
|
||||
detailQueryKey,
|
||||
createAppDetailFixture({
|
||||
enable_api: false,
|
||||
enable_site: false,
|
||||
icon_url: null,
|
||||
id: 'app-1',
|
||||
mode: 'chat',
|
||||
name: 'Cached app',
|
||||
}),
|
||||
)
|
||||
|
||||
await waitFor(() => {
|
||||
expect(result.current.showLoading).toBe(false)
|
||||
|
||||
@@ -91,7 +91,7 @@ const createMockApp = (overrides: Partial<AppPartial> = {}): AppPartial => ({
|
||||
created_at: Date.now(),
|
||||
updated_at: Date.now(),
|
||||
tags: [],
|
||||
access_mode: 'public_access',
|
||||
access_mode: 'public',
|
||||
...overrides,
|
||||
})
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
'use client'
|
||||
import type { AppDetailWithSite } from '@dify/contracts/api/console/apps/types.gen'
|
||||
import type { AppPartial } from '@dify/contracts/api/console/apps/types.gen'
|
||||
import { Button } from '@langgenius/dify-ui/button'
|
||||
import { cn } from '@langgenius/dify-ui/cn'
|
||||
import { useRef } from 'react'
|
||||
@@ -13,7 +13,7 @@ type Props = Readonly<{
|
||||
app_id: string
|
||||
inputs: Record<string, unknown>
|
||||
}
|
||||
appDetail: Pick<AppDetailWithSite, 'id' | 'mode'>
|
||||
appDetail: Pick<AppPartial, 'id' | 'mode'>
|
||||
onFormChange: (value: Record<string, unknown>) => void
|
||||
}>
|
||||
|
||||
|
||||
+2
-1
@@ -1,6 +1,7 @@
|
||||
'use client'
|
||||
import type {
|
||||
AppDetailWithSite,
|
||||
AppPartial,
|
||||
WorkflowResponse,
|
||||
} from '@dify/contracts/api/console/apps/types.gen'
|
||||
import type { FileUpload } from '@/app/components/base/features/types'
|
||||
@@ -162,7 +163,7 @@ function buildWorkflowSchema(
|
||||
}
|
||||
|
||||
type UseAppInputsFormSchemaParams = {
|
||||
appDetail: Pick<AppDetailWithSite, 'id' | 'mode'>
|
||||
appDetail: Pick<AppPartial, 'id' | 'mode'>
|
||||
}
|
||||
|
||||
type UseAppInputsFormSchemaResult = {
|
||||
|
||||
@@ -3,6 +3,7 @@ import { QueryClient, QueryClientProvider } from '@tanstack/react-query'
|
||||
import { render, screen, waitFor, within } from '@testing-library/react'
|
||||
import userEvent from '@testing-library/user-event'
|
||||
import { AgentPermission } from '@/features/agent-v2/acl'
|
||||
import { createAgentFixture } from '@/test/fixtures/agent'
|
||||
import { AgentDetailSection, AgentDetailTop } from '../navigation'
|
||||
|
||||
const mocks = vi.hoisted(() => ({
|
||||
@@ -86,22 +87,23 @@ vi.mock('@/service/console', () => ({
|
||||
},
|
||||
}))
|
||||
|
||||
const createAgent = (overrides: Partial<AgentAppDetailWithSite> = {}): AgentAppDetailWithSite => ({
|
||||
permission_keys: Object.values(AgentPermission),
|
||||
app_id: 'app-1',
|
||||
description: 'Find and summarize market materials.',
|
||||
enable_api: true,
|
||||
enable_site: true,
|
||||
icon: '🧪',
|
||||
icon_background: '#E0F2FE',
|
||||
icon_type: 'emoji',
|
||||
id: 'agent-1',
|
||||
icon_url: null,
|
||||
mode: 'agent',
|
||||
name: 'Research Agent',
|
||||
role: 'Research Assistant',
|
||||
...overrides,
|
||||
})
|
||||
const createAgent = (overrides: Partial<AgentAppDetailWithSite> = {}): AgentAppDetailWithSite =>
|
||||
createAgentFixture({
|
||||
permission_keys: Object.values(AgentPermission),
|
||||
app_id: 'app-1',
|
||||
description: 'Find and summarize market materials.',
|
||||
enable_api: true,
|
||||
enable_site: true,
|
||||
icon: '🧪',
|
||||
icon_background: '#E0F2FE',
|
||||
icon_type: 'emoji',
|
||||
id: 'agent-1',
|
||||
icon_url: null,
|
||||
mode: 'agent',
|
||||
name: 'Research Agent',
|
||||
role: 'Research Assistant',
|
||||
...overrides,
|
||||
})
|
||||
|
||||
function renderAgentDetailSection(expand = true) {
|
||||
const queryClient = new QueryClient()
|
||||
|
||||
+54
-44
@@ -15,6 +15,8 @@ import { consoleQuery } from '@/service/console'
|
||||
import { seedAccountProfileQuery } from '@/test/console/account-profile'
|
||||
import { createQueryClientWrapper } from '@/test/console/query-client'
|
||||
import { seedFeatures, seedSystemFeatures } from '@/test/console/query-data'
|
||||
import { createAgentFixture } from '@/test/fixtures/agent'
|
||||
import { createAppDetailFixture, createAppSiteFixture } from '@/test/fixtures/app'
|
||||
import { ServiceApiAccessCard } from '../service-api-access-card'
|
||||
import { WebAppAccessCard } from '../web-app-access-card'
|
||||
|
||||
@@ -230,7 +232,7 @@ vi.mock('@/service/console', () => ({
|
||||
}))
|
||||
|
||||
function createAgent(overrides: Partial<AgentAppDetailWithSite> = {}): AgentAppDetailWithSite {
|
||||
return {
|
||||
return createAgentFixture({
|
||||
permission_keys: Object.values(AgentPermission),
|
||||
access_ready: true,
|
||||
enable_api: true,
|
||||
@@ -243,32 +245,23 @@ function createAgent(overrides: Partial<AgentAppDetailWithSite> = {}): AgentAppD
|
||||
backing_app_id: 'app-1',
|
||||
api_base_url: 'https://api.example.test/v1',
|
||||
access_mode: 'sso_verified',
|
||||
site: {
|
||||
access_token: 'site-token',
|
||||
site: createAppSiteFixture({
|
||||
app_base_url: 'https://chat.example.test',
|
||||
chat_color_theme_inverted: false,
|
||||
default_language: 'en-US',
|
||||
icon_url: null,
|
||||
show_workflow_steps: false,
|
||||
title: 'Support Agent',
|
||||
use_icon_as_answer_icon: false,
|
||||
} as NonNullable<AgentAppDetailWithSite['site']> & {
|
||||
access_token: string
|
||||
app_base_url: string
|
||||
},
|
||||
}),
|
||||
...overrides,
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
function createAppDetailResponse(overrides: Partial<AppDetail> = {}): AppDetail {
|
||||
return {
|
||||
return createAppDetailFixture({
|
||||
enable_api: true,
|
||||
enable_site: true,
|
||||
id: 'app-1',
|
||||
mode: 'agent',
|
||||
name: 'Support Agent',
|
||||
...overrides,
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
function createAgentApiAccessResponse(
|
||||
@@ -624,6 +617,35 @@ describe('Agent access surface cards', () => {
|
||||
expect(toast.error).toHaveBeenCalledWith('common.actionMsg.modifiedUnsuccessfully')
|
||||
})
|
||||
|
||||
it('should replace the Web App URL token without discarding the cached site settings', async () => {
|
||||
const user = userEvent.setup()
|
||||
const agent = createAgent()
|
||||
const queryClient = renderWithQueryClient(
|
||||
<WebAppAccessCard agent={agent} agentId="agent-1" isLoading={false} />,
|
||||
)
|
||||
queryClient.setQueryData(['agent-detail', 'agent-1'], agent)
|
||||
mocks.siteAccessTokenResetMutation.mockResolvedValueOnce(
|
||||
createAppSiteFixture({ code: 'new-site-token' }),
|
||||
)
|
||||
|
||||
await user.click(
|
||||
screen.getByRole('button', { name: 'agentV2.agentDetail.access.webApp.refreshUrl' }),
|
||||
)
|
||||
|
||||
expect(mocks.siteAccessTokenResetMutation.mock.calls[0]?.[0]).toEqual({
|
||||
params: { app_id: 'app-1' },
|
||||
})
|
||||
await waitFor(() => {
|
||||
expect(
|
||||
queryClient.getQueryData<AgentAppDetailWithSite>(['agent-detail', 'agent-1'])?.site,
|
||||
).toMatchObject({
|
||||
code: 'new-site-token',
|
||||
access_token: 'new-site-token',
|
||||
title: 'Support Agent',
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
it('should open the customize dialog with the backing app id and API base URL', async () => {
|
||||
const user = userEvent.setup()
|
||||
|
||||
@@ -707,7 +729,7 @@ describe('Agent access surface cards', () => {
|
||||
})
|
||||
})
|
||||
|
||||
it('should save settings through the backing app id and update the agent detail cache', async () => {
|
||||
it('should save settings through the backing app id and invalidate agent detail', async () => {
|
||||
const user = userEvent.setup()
|
||||
mocks.getUserCanAccess.mockResolvedValue({ result: false })
|
||||
const agent = createAgent({
|
||||
@@ -781,18 +803,9 @@ describe('Agent access surface cards', () => {
|
||||
})
|
||||
})
|
||||
expect(mocks.siteMutation.mock.calls[0]?.[0].body).not.toHaveProperty('enable_sso')
|
||||
expect(
|
||||
queryClient.getQueryData<AgentAppDetailWithSite>(['agent-detail', 'agent-1']),
|
||||
).toMatchObject({
|
||||
site: {
|
||||
access_token: 'new-site-token',
|
||||
chat_color_theme: '#123456',
|
||||
description: 'Updated web description.',
|
||||
icon_url: null,
|
||||
title: 'Support Portal',
|
||||
},
|
||||
await waitFor(() => {
|
||||
expect(invalidateSpy).toHaveBeenCalledWith({ queryKey: ['agent-detail', 'agent-1'] })
|
||||
})
|
||||
expect(invalidateSpy).toHaveBeenCalledWith({ queryKey: ['agent-detail', 'agent-1'] })
|
||||
})
|
||||
|
||||
it('should fall back to the Agent icon tuple when WebApp site icon data is missing', async () => {
|
||||
@@ -918,10 +931,10 @@ describe('Agent access surface cards', () => {
|
||||
).toBeDisabled()
|
||||
})
|
||||
|
||||
it('should keep customize disabled until the generated contract provides the required fields', () => {
|
||||
it('should keep customize disabled when the app base URL is empty', () => {
|
||||
renderWithQueryClient(
|
||||
<WebAppAccessCard
|
||||
agent={createAgent({ api_base_url: null })}
|
||||
agent={createAgent({ api_base_url: '' })}
|
||||
agentId="agent-1"
|
||||
isLoading={false}
|
||||
/>,
|
||||
@@ -1246,22 +1259,19 @@ describe('Agent access surface cards', () => {
|
||||
expect(screen.getByRole('button', { name: organizationAccessLabel })).toBeDisabled()
|
||||
})
|
||||
|
||||
it.each([null, 'future-access-mode'])(
|
||||
'should hide the access mode entry when the access mode is %s',
|
||||
(accessMode) => {
|
||||
renderWithQueryClient(
|
||||
<WebAppAccessCard
|
||||
agent={createAgent({ access_mode: accessMode })}
|
||||
agentId="agent-1"
|
||||
isLoading={false}
|
||||
/>,
|
||||
)
|
||||
it('should hide the access mode entry when the access mode is unavailable', () => {
|
||||
renderWithQueryClient(
|
||||
<WebAppAccessCard
|
||||
agent={createAgent({ access_mode: null })}
|
||||
agentId="agent-1"
|
||||
isLoading={false}
|
||||
/>,
|
||||
)
|
||||
|
||||
expect(
|
||||
screen.queryByRole('button', { name: organizationAccessLabel }),
|
||||
).not.toBeInTheDocument()
|
||||
},
|
||||
)
|
||||
expect(
|
||||
screen.queryByRole('button', { name: organizationAccessLabel }),
|
||||
).not.toBeInTheDocument()
|
||||
})
|
||||
|
||||
it('should open the shared App access control dialog for the backing app', async () => {
|
||||
const user = userEvent.setup()
|
||||
|
||||
@@ -117,8 +117,8 @@ export function WebAppAccessCard({
|
||||
...agentDetail,
|
||||
site: {
|
||||
...agentDetail.site,
|
||||
...site,
|
||||
access_token: site.code,
|
||||
code: site.code ?? agentDetail.site.code,
|
||||
access_token: site.code ?? agentDetail.site.access_token,
|
||||
},
|
||||
}
|
||||
},
|
||||
@@ -191,39 +191,12 @@ export function WebAppAccessCard({
|
||||
const sitePayload = body satisfies AppSiteUpdatePayload
|
||||
|
||||
try {
|
||||
const updatedSite = await updateSiteMutation.mutateAsync({
|
||||
await updateSiteMutation.mutateAsync({
|
||||
params: {
|
||||
app_id: appId,
|
||||
},
|
||||
body: sitePayload,
|
||||
})
|
||||
|
||||
queryClient.setQueryData<AgentAppDetailWithSite | undefined>(
|
||||
agentDetailQueryKey,
|
||||
(agentDetail) =>
|
||||
agentDetail
|
||||
? {
|
||||
...agentDetail,
|
||||
site: {
|
||||
...agentDetail.site,
|
||||
...updatedSite,
|
||||
...sitePayload,
|
||||
access_token:
|
||||
updatedSite.code ??
|
||||
agentDetail.site?.access_token ??
|
||||
agentDetail.site?.code ??
|
||||
null,
|
||||
code:
|
||||
updatedSite.code ??
|
||||
agentDetail.site?.code ??
|
||||
agentDetail.site?.access_token ??
|
||||
null,
|
||||
app_base_url: agentDetail.site?.app_base_url ?? site?.app_base_url ?? null,
|
||||
icon_url: null,
|
||||
},
|
||||
}
|
||||
: agentDetail,
|
||||
)
|
||||
await queryClient.invalidateQueries({ queryKey: agentDetailQueryKey })
|
||||
toast.success(tCommon(($) => $['actionMsg.modifiedSuccessfully']))
|
||||
} catch {
|
||||
|
||||
+3
-3
@@ -9,6 +9,7 @@ import { systemFeaturesQueryOptions } from '@/features/system-features/client'
|
||||
import { consoleQuery } from '@/service/console'
|
||||
import { createSystemFeaturesFixture } from '@/test/console/system-features'
|
||||
import { createAgentFixture } from '@/test/fixtures/agent'
|
||||
import { createAppSiteFixture } from '@/test/fixtures/app'
|
||||
import { createTestQueryClient } from '@/test/query-client'
|
||||
import { AgentConfigurePublishBar } from '../publish-bar'
|
||||
|
||||
@@ -49,11 +50,10 @@ async function setup() {
|
||||
createAgentFixture({
|
||||
access_ready: true,
|
||||
enable_site: true,
|
||||
site: {
|
||||
site: createAppSiteFixture({
|
||||
access_token: 'published-token',
|
||||
app_base_url: 'https://apps.example.test',
|
||||
icon_url: null,
|
||||
},
|
||||
}),
|
||||
}),
|
||||
)
|
||||
queryClient.setQueryData(
|
||||
|
||||
+3
-3
@@ -17,6 +17,7 @@ import {
|
||||
import { agentComposerPromptAtom } from '@/features/agent-v2/agent-composer/store-modules/prompt'
|
||||
import { systemFeaturesQueryOptions } from '@/features/system-features/client'
|
||||
import { consoleQuery } from '@/service/console'
|
||||
import { createAppSiteFixture } from '@/test/fixtures/app'
|
||||
import { createNuqsTestWrapper } from '@/test/nuqs-testing'
|
||||
import { AgentConfigurePublishBar } from '../publish-bar'
|
||||
|
||||
@@ -1140,11 +1141,10 @@ describe('AgentConfigurePublishBar', () => {
|
||||
const readyAgent = {
|
||||
access_ready: true,
|
||||
enable_site: true,
|
||||
site: {
|
||||
site: createAppSiteFixture({
|
||||
access_token: 'published-token',
|
||||
app_base_url: 'https://apps.example.test',
|
||||
icon_url: null,
|
||||
},
|
||||
}),
|
||||
}
|
||||
|
||||
it.each([
|
||||
|
||||
@@ -6,6 +6,8 @@ import type { MutationFunctionContext, QueryFunctionContext } from '@tanstack/re
|
||||
import type { consoleQuery as ConsoleQuery } from '@/service/console'
|
||||
import { MutationObserver, QueryClient, QueryObserver } from '@tanstack/react-query'
|
||||
import { afterEach, beforeEach, describe, expect, it, vi } from 'vite-plus/test'
|
||||
import { createAgentFixture } from '@/test/fixtures/agent'
|
||||
import { createAppDetailFixture } from '@/test/fixtures/app'
|
||||
import { normalizeConsoleOpenAPIURL } from './openapi-url'
|
||||
|
||||
const loadConsoleQuery = async () => {
|
||||
@@ -84,22 +86,8 @@ const getRetryFn = (queryOptions: object): RetryFn => {
|
||||
return retry as RetryFn
|
||||
}
|
||||
|
||||
const createAgent = (overrides: Partial<AgentMutationResponse> = {}): AgentMutationResponse => ({
|
||||
...overrides,
|
||||
access_ready: overrides.access_ready ?? true,
|
||||
debug_conversation_has_messages: overrides.debug_conversation_has_messages ?? false,
|
||||
debug_conversation_message_count: overrides.debug_conversation_message_count ?? 0,
|
||||
enable_api: overrides.enable_api ?? true,
|
||||
enable_site: overrides.enable_site ?? true,
|
||||
description: overrides.description ?? 'Agent description',
|
||||
hidden_app_backed: overrides.hidden_app_backed ?? false,
|
||||
id: overrides.id ?? 'agent-1',
|
||||
icon_url: overrides.icon_url ?? null,
|
||||
mode: overrides.mode ?? 'agent',
|
||||
name: overrides.name ?? 'Agent',
|
||||
permission_keys: overrides.permission_keys ?? [],
|
||||
role: overrides.role ?? 'Assistant',
|
||||
})
|
||||
const createAgent = (overrides: Partial<AgentMutationResponse> = {}): AgentMutationResponse =>
|
||||
createAgentFixture({ role: 'Assistant', ...overrides })
|
||||
|
||||
const createComposerState = (
|
||||
overrides: Partial<AgentComposerMutationResponse> = {},
|
||||
@@ -645,13 +633,7 @@ describe('consoleQuery app mutation defaults', () => {
|
||||
.spyOn(queryClient, 'invalidateQueries')
|
||||
.mockImplementation(() => new Promise(() => {}))
|
||||
const context = createMutationContext(queryClient)
|
||||
const appDetail: AppDetail = {
|
||||
enable_api: true,
|
||||
enable_site: true,
|
||||
id: 'app-1',
|
||||
mode: 'chat',
|
||||
name: 'App',
|
||||
}
|
||||
const appDetail: AppDetail = createAppDetailFixture()
|
||||
const appSite: AppSiteResponse = {
|
||||
app_id: 'app-1',
|
||||
customize_token_strategy: 'fixed',
|
||||
@@ -723,14 +705,11 @@ describe('consoleQuery app mutation defaults', () => {
|
||||
const otherDetailQueryKey = consoleQuery.apps.byAppId.get.queryKey({
|
||||
input: { params: { app_id: 'app-2' } },
|
||||
})
|
||||
const updatedApp = {
|
||||
const updatedApp = createAppDetailFixture({
|
||||
enable_api: false,
|
||||
enable_site: false,
|
||||
icon_url: null,
|
||||
id: 'app-1',
|
||||
mode: 'chat',
|
||||
name: 'Updated app',
|
||||
}
|
||||
})
|
||||
queryClient.setQueryData(detailQueryKey, { ...updatedApp, name: 'Old app' })
|
||||
queryClient.setQueryData(otherDetailQueryKey, { ...updatedApp, id: 'app-2', name: 'Other app' })
|
||||
|
||||
|
||||
Vendored
+2
@@ -1,9 +1,11 @@
|
||||
import type { AgentAppDetailWithSite } from '@dify/contracts/api/console/agent/types.gen'
|
||||
import { zAgentAppDetailWithSite } from '@dify/contracts/api/console/agent/zod.gen'
|
||||
import { AgentPermission } from '@/features/agent-v2/acl'
|
||||
import { createAppDetailFixture } from './app'
|
||||
|
||||
export function createAgentFixture(overrides: Partial<AgentAppDetailWithSite> = {}) {
|
||||
return zAgentAppDetailWithSite.parse({
|
||||
...createAppDetailFixture(),
|
||||
id: 'agent-1',
|
||||
app_id: 'app-1',
|
||||
name: 'Agent',
|
||||
|
||||
Vendored
+73
@@ -0,0 +1,73 @@
|
||||
import type {
|
||||
AppDetailSiteResponse,
|
||||
AppDetailWithSite,
|
||||
} from '@dify/contracts/api/console/apps/types.gen'
|
||||
|
||||
export function createAppSiteFixture(
|
||||
overrides: Partial<AppDetailSiteResponse> = {},
|
||||
): AppDetailSiteResponse {
|
||||
return {
|
||||
access_token: 'site-token',
|
||||
app_base_url: 'https://apps.example.test',
|
||||
chat_color_theme: null,
|
||||
chat_color_theme_inverted: false,
|
||||
code: 'site-token',
|
||||
copyright: null,
|
||||
created_at: 1,
|
||||
created_by: null,
|
||||
custom_disclaimer: '',
|
||||
customize_domain: null,
|
||||
customize_token_strategy: 'not_allow',
|
||||
default_language: 'en-US',
|
||||
description: null,
|
||||
icon: null,
|
||||
icon_background: null,
|
||||
icon_type: null,
|
||||
icon_url: null,
|
||||
input_placeholder: null,
|
||||
privacy_policy: null,
|
||||
prompt_public: false,
|
||||
show_workflow_steps: false,
|
||||
title: 'App',
|
||||
updated_at: 1,
|
||||
updated_by: null,
|
||||
use_icon_as_answer_icon: false,
|
||||
...overrides,
|
||||
}
|
||||
}
|
||||
|
||||
export function createAppDetailFixture(
|
||||
overrides: Partial<AppDetailWithSite> = {},
|
||||
): AppDetailWithSite {
|
||||
return {
|
||||
access_mode: null,
|
||||
api_base_url: 'https://api.example.test/v1',
|
||||
app_id: null,
|
||||
bound_agent_id: null,
|
||||
created_at: 1,
|
||||
created_by: null,
|
||||
deleted_tools: [],
|
||||
description: '',
|
||||
enable_api: true,
|
||||
enable_site: true,
|
||||
icon: null,
|
||||
icon_background: null,
|
||||
icon_type: null,
|
||||
icon_url: null,
|
||||
id: 'app-1',
|
||||
maintainer: null,
|
||||
max_active_requests: null,
|
||||
mode: 'chat',
|
||||
model_config: null,
|
||||
name: 'App',
|
||||
permission_keys: [],
|
||||
site: null,
|
||||
tags: [],
|
||||
tracing: null,
|
||||
updated_at: 1,
|
||||
updated_by: null,
|
||||
use_icon_as_answer_icon: false,
|
||||
workflow: null,
|
||||
...overrides,
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user