diff --git a/api/controllers/console/explore/trial.py b/api/controllers/console/explore/trial.py index 0d54bf7f473..b28116c9a2d 100644 --- a/api/controllers/console/explore/trial.py +++ b/api/controllers/console/explore/trial.py @@ -13,7 +13,6 @@ import services from controllers.common.fields import ( AudioBinaryResponse, AudioTranscriptResponse, - GeneratedAppResponse, SimpleResultResponse, ) from controllers.common.fields import Parameters as ParametersResponse @@ -391,7 +390,6 @@ register_response_schema_models( ParametersResponse, AudioBinaryResponse, AudioTranscriptResponse, - GeneratedAppResponse, SimpleResultResponse, SiteResponse, SuggestedQuestionsResponse, @@ -406,7 +404,7 @@ simple_account_model = console_ns.models[TrialSimpleAccount.__name__] class TrialAppWorkflowRunApi(TrialAppResource): @trial_feature_enable @console_ns.expect(console_ns.models[WorkflowRunRequest.__name__]) - @console_ns.response(200, "Success", console_ns.models[GeneratedAppResponse.__name__]) + @console_ns.response(200, "Success") @with_current_user @with_session def post(self, session: Session, current_user: Account, trial_app): @@ -434,6 +432,7 @@ class TrialAppWorkflowRunApi(TrialAppResource): streaming=True, ) RecommendedAppService.add_trial_app_record(db.session, app_id, user_id) + # response-contract:ignore compact_generate_response return helper.compact_generate_response(response) except ProviderTokenNotInitError as ex: raise ProviderNotInitializeError(ex.description) @@ -478,7 +477,7 @@ class TrialAppWorkflowTaskStopApi(TrialAppResource): class TrialChatApi(TrialAppResource): @console_ns.expect(console_ns.models[ChatRequest.__name__]) - @console_ns.response(200, "Success", console_ns.models[GeneratedAppResponse.__name__]) + @console_ns.response(200, "Success") @trial_feature_enable @with_current_user @with_session @@ -513,6 +512,7 @@ class TrialChatApi(TrialAppResource): streaming=True, ) RecommendedAppService.add_trial_app_record(db.session, app_id, user_id) + # response-contract:ignore compact_generate_response return helper.compact_generate_response(response) except services.errors.conversation.ConversationNotExistsError: raise NotFound("Conversation Not Exists.") @@ -680,7 +680,7 @@ class TrialChatTextApi(TrialAppResource): class TrialCompletionApi(TrialAppResource): @console_ns.expect(console_ns.models[CompletionRequest.__name__]) - @console_ns.response(200, "Success", console_ns.models[GeneratedAppResponse.__name__]) + @console_ns.response(200, "Success") @trial_feature_enable @with_current_user @with_session @@ -710,6 +710,7 @@ class TrialCompletionApi(TrialAppResource): ) RecommendedAppService.add_trial_app_record(db.session, app_id, user_id) + # response-contract:ignore compact_generate_response return helper.compact_generate_response(response) except services.errors.conversation.ConversationNotExistsError: raise NotFound("Conversation Not Exists.") diff --git a/api/controllers/console/workspace/snippets.py b/api/controllers/console/workspace/snippets.py index 3a8db2dcaa1..c849336401c 100644 --- a/api/controllers/console/workspace/snippets.py +++ b/api/controllers/console/workspace/snippets.py @@ -4,7 +4,7 @@ from typing import Any from urllib.parse import quote from flask import Response, request -from flask_restx import Resource, marshal +from flask_restx import Resource from pydantic import Field as PydanticField from pydantic import field_validator from sqlalchemy.orm import Session, sessionmaker @@ -37,8 +37,7 @@ from controllers.console.wraps import ( from core.plugin.entities.plugin import PluginDependency from extensions.ext_database import db from fields.base import ResponseModel -from fields.snippet_fields import snippet_fields, snippet_list_fields -from libs.helper import to_timestamp +from libs.helper import dump_response, to_timestamp from libs.login import login_required from models import Account from models.snippet import SnippetType @@ -198,13 +197,16 @@ class CustomizedSnippetsApi(Resource): tag_ids=query.tag_ids, ) - return { - "data": marshal(snippets, snippet_list_fields), - "page": query.page, - "limit": query.limit, - "total": total, - "has_more": has_more, - }, 200 + return dump_response( + SnippetPaginationResponse, + { + "data": snippets, + "page": query.page, + "limit": query.limit, + "total": total, + "has_more": has_more, + }, + ), 200 @console_ns.doc("create_customized_snippet") @console_ns.expect(console_ns.models.get(CreateSnippetPayload.__name__)) @@ -245,7 +247,7 @@ class CustomizedSnippetsApi(Resource): except ValueError as e: return {"message": str(e)}, 400 - return marshal(snippet, snippet_fields), 201 + return dump_response(SnippetResponse, snippet), 201 @console_ns.route("/workspaces/current/customized-snippets/") @@ -268,7 +270,7 @@ class CustomizedSnippetDetailApi(Resource): if not snippet: raise NotFound("Snippet not found") - return marshal(snippet, snippet_fields), 200 + return dump_response(SnippetResponse, snippet), 200 @console_ns.doc("update_customized_snippet") @console_ns.expect(console_ns.models.get(UpdateSnippetPayload.__name__)) @@ -317,7 +319,7 @@ class CustomizedSnippetDetailApi(Resource): except ValueError as e: return {"message": str(e)}, 400 - return marshal(snippet, snippet_fields), 200 + return dump_response(SnippetResponse, snippet), 200 @console_ns.doc("delete_customized_snippet") @console_ns.response(204, "Snippet deleted successfully") @@ -533,4 +535,4 @@ class CustomizedSnippetUseCountIncrementApi(Resource): session.commit() session.refresh(snippet) - return {"result": "success", "use_count": snippet.use_count}, 200 + return SnippetUseCountResponse(result="success", use_count=snippet.use_count).model_dump(mode="json"), 200 diff --git a/api/core/plugin/entities/endpoint.py b/api/core/plugin/entities/endpoint.py index 64199636687..4aa1da8e918 100644 --- a/api/core/plugin/entities/endpoint.py +++ b/api/core/plugin/entities/endpoint.py @@ -32,6 +32,7 @@ class EndpointEntity(BasePluginEntity): entity of an endpoint """ + # TODO: Confirm daemon masks secret-input settings before endpoint list responses expose them. settings: dict[str, Any] tenant_id: str plugin_id: str diff --git a/api/fields/app_fields.py b/api/fields/app_fields.py deleted file mode 100644 index 96d8fbdf34c..00000000000 --- a/api/fields/app_fields.py +++ /dev/null @@ -1,271 +0,0 @@ -import json -from typing import override - -from flask_restx import fields - -from fields.workflow_fields import workflow_partial_fields -from libs.helper import AppIconUrlField, TimestampField - - -class JsonStringField(fields.Raw): - @override - def format(self, value): - if isinstance(value, str): - try: - return json.loads(value) - except (json.JSONDecodeError, TypeError): - return value - return value - - -class OpaqueRawField(fields.Raw): - @override - def schema(self) -> dict[str, object]: - return {"type": "object"} - - -class StringListRawField(fields.Raw): - @override - def schema(self) -> dict[str, object]: - return {"type": "array", "items": {"type": "string"}} - - -class ObjectListRawField(fields.Raw): - @override - def schema(self) -> dict[str, object]: - return {"type": "array", "items": {"type": "object"}} - - -app_detail_kernel_fields = { - "id": fields.String, - "name": fields.String, - "description": fields.String, - "mode": fields.String(attribute="mode_compatible_with_agent"), - "icon_type": fields.String, - "icon": fields.String, - "icon_background": fields.String, - "icon_url": AppIconUrlField, -} - -related_app_list = { - "data": fields.List(fields.Nested(app_detail_kernel_fields)), - "total": fields.Integer, -} - -model_config_fields = { - "opening_statement": fields.String, - "suggested_questions": StringListRawField(attribute="suggested_questions_list"), - "suggested_questions_after_answer": OpaqueRawField(attribute="suggested_questions_after_answer_dict"), - "speech_to_text": OpaqueRawField(attribute="speech_to_text_dict"), - "text_to_speech": OpaqueRawField(attribute="text_to_speech_dict"), - "retriever_resource": OpaqueRawField(attribute="retriever_resource_dict"), - "annotation_reply": OpaqueRawField(attribute="annotation_reply_dict"), - "more_like_this": OpaqueRawField(attribute="more_like_this_dict"), - "sensitive_word_avoidance": OpaqueRawField(attribute="sensitive_word_avoidance_dict"), - "external_data_tools": ObjectListRawField(attribute="external_data_tools_list"), - "model": OpaqueRawField(attribute="model_dict"), - "user_input_form": ObjectListRawField(attribute="user_input_form_list"), - "dataset_query_variable": fields.String, - "pre_prompt": fields.String, - "agent_mode": OpaqueRawField(attribute="agent_mode_dict"), - "prompt_type": fields.String, - "chat_prompt_config": OpaqueRawField(attribute="chat_prompt_config_dict"), - "completion_prompt_config": OpaqueRawField(attribute="completion_prompt_config_dict"), - "dataset_configs": OpaqueRawField(attribute="dataset_configs_dict"), - "file_upload": OpaqueRawField(attribute="file_upload_dict"), - "created_by": fields.String, - "created_at": TimestampField, - "updated_by": fields.String, - "updated_at": TimestampField, -} - -tag_fields = {"id": fields.String, "name": fields.String, "type": fields.String} - -app_detail_fields = { - "id": fields.String, - "name": fields.String, - "description": fields.String, - "mode": fields.String(attribute="mode_compatible_with_agent"), - "icon": fields.String, - "icon_background": fields.String, - "enable_site": fields.Boolean, - "enable_api": fields.Boolean, - "model_config": fields.Nested(model_config_fields, attribute="app_model_config", allow_null=True), - "workflow": fields.Nested(workflow_partial_fields, allow_null=True), - "tracing": OpaqueRawField, - "use_icon_as_answer_icon": fields.Boolean, - "created_by": fields.String, - "created_at": TimestampField, - "updated_by": fields.String, - "updated_at": TimestampField, - "access_mode": fields.String, - "tags": fields.List(fields.Nested(tag_fields)), - "permission_keys": fields.List(fields.String()), -} - -prompt_config_fields = { - "prompt_template": fields.String, -} - -model_config_partial_fields = { - "model": OpaqueRawField(attribute="model_dict"), - "pre_prompt": fields.String, - "created_by": fields.String, - "created_at": TimestampField, - "updated_by": fields.String, - "updated_at": TimestampField, -} - -app_partial_fields = { - "id": fields.String, - "name": fields.String, - "max_active_requests": OpaqueRawField(), - "description": fields.String(attribute="desc_or_prompt"), - "mode": fields.String(attribute="mode_compatible_with_agent"), - "icon_type": fields.String, - "icon": fields.String, - "icon_background": fields.String, - "icon_url": AppIconUrlField, - "model_config": fields.Nested(model_config_partial_fields, attribute="app_model_config", allow_null=True), - "workflow": fields.Nested(workflow_partial_fields, allow_null=True), - "use_icon_as_answer_icon": fields.Boolean, - "created_by": fields.String, - "created_at": TimestampField, - "updated_by": fields.String, - "updated_at": TimestampField, - "tags": fields.List(fields.Nested(tag_fields)), - "access_mode": fields.String, - "create_user_name": fields.String, - "author_name": fields.String, - "has_draft_trigger": fields.Boolean, - "permission_keys": fields.List(fields.String()), -} - - -app_pagination_fields = { - "page": fields.Integer, - "limit": fields.Integer(attribute="per_page"), - "total": fields.Integer, - "has_more": fields.Boolean(attribute="has_next"), - "data": fields.List(fields.Nested(app_partial_fields), attribute="items"), -} - -template_fields = { - "name": fields.String, - "icon": fields.String, - "icon_background": fields.String, - "description": fields.String, - "mode": fields.String, - "model_config": fields.Nested(model_config_fields), -} - -template_list_fields = { - "data": fields.List(fields.Nested(template_fields)), -} - -site_fields = { - "access_token": fields.String(attribute="code"), - "code": fields.String, - "title": fields.String, - "icon_type": fields.String, - "icon": fields.String, - "icon_background": fields.String, - "icon_url": AppIconUrlField, - "description": fields.String, - "default_language": fields.String, - "chat_color_theme": fields.String, - "chat_color_theme_inverted": fields.Boolean, - "customize_domain": fields.String, - "copyright": fields.String, - "privacy_policy": fields.String, - "custom_disclaimer": fields.String, - "customize_token_strategy": fields.String, - "prompt_public": fields.Boolean, - "app_base_url": fields.String, - "show_workflow_steps": fields.Boolean, - "use_icon_as_answer_icon": fields.Boolean, - "created_by": fields.String, - "created_at": TimestampField, - "updated_by": fields.String, - "updated_at": TimestampField, -} - -deleted_tool_fields = { - "type": fields.String, - "tool_name": fields.String, - "provider_id": fields.String, -} - -app_detail_fields_with_site = { - "id": fields.String, - "name": fields.String, - "description": fields.String, - "mode": fields.String(attribute="mode_compatible_with_agent"), - "icon_type": fields.String, - "icon": fields.String, - "icon_background": fields.String, - "icon_url": AppIconUrlField, - "enable_site": fields.Boolean, - "enable_api": fields.Boolean, - "model_config": fields.Nested(model_config_fields, attribute="app_model_config", allow_null=True), - "workflow": fields.Nested(workflow_partial_fields, allow_null=True), - "api_base_url": fields.String, - "use_icon_as_answer_icon": fields.Boolean, - "max_active_requests": fields.Integer, - "created_by": fields.String, - "created_at": TimestampField, - "updated_by": fields.String, - "updated_at": TimestampField, - "deleted_tools": fields.List(fields.Nested(deleted_tool_fields)), - "access_mode": fields.String, - "tags": fields.List(fields.Nested(tag_fields)), - "permission_keys": fields.List(fields.String()), - "site": fields.Nested(site_fields), -} - - -app_site_fields = { - "app_id": fields.String, - "access_token": fields.String(attribute="code"), - "code": fields.String, - "title": fields.String, - "icon": fields.String, - "icon_background": fields.String, - "description": fields.String, - "default_language": fields.String, - "customize_domain": fields.String, - "copyright": fields.String, - "privacy_policy": fields.String, - "custom_disclaimer": fields.String, - "customize_token_strategy": fields.String, - "prompt_public": fields.Boolean, - "show_workflow_steps": fields.Boolean, - "use_icon_as_answer_icon": fields.Boolean, -} - -leaked_dependency_fields = {"type": fields.String, "value": OpaqueRawField, "current_identifier": fields.String} - -app_import_fields = { - "id": fields.String, - "status": fields.String, - "app_id": fields.String, - "app_mode": fields.String, - "current_dsl_version": fields.String, - "imported_dsl_version": fields.String, - "error": fields.String, -} - -app_import_check_dependencies_fields = { - "leaked_dependencies": fields.List(fields.Nested(leaked_dependency_fields)), -} - -app_server_fields = { - "id": fields.String, - "name": fields.String, - "server_code": fields.String, - "description": fields.String, - "status": fields.String, - "parameters": JsonStringField, - "created_at": TimestampField, - "updated_at": TimestampField, -} diff --git a/api/fields/member_fields.py b/api/fields/member_fields.py index 80b93f0a24b..5108522af01 100644 --- a/api/fields/member_fields.py +++ b/api/fields/member_fields.py @@ -2,18 +2,11 @@ from __future__ import annotations from datetime import datetime -from flask_restx import fields from pydantic import Field, computed_field, field_validator from fields.base import ResponseModel from libs.helper import build_avatar_url, to_timestamp -simple_account_fields = { - "id": fields.String, - "name": fields.String, - "email": fields.String, -} - class SimpleAccountResponse(ResponseModel): id: str diff --git a/api/fields/snippet_fields.py b/api/fields/snippet_fields.py index 699a3687ac1..77aba3fe76e 100644 --- a/api/fields/snippet_fields.py +++ b/api/fields/snippet_fields.py @@ -1,61 +1,74 @@ -from typing import override +from datetime import datetime +from typing import Any -from flask_restx import fields +from pydantic import Field, field_validator -from fields.member_fields import simple_account_fields -from libs.helper import TimestampField +from fields.base import ResponseModel +from fields.member_fields import SimpleAccountResponse +from libs.helper import to_timestamp +from models.snippet import SnippetType -class OpaqueRawField(fields.Raw): - @override - def schema(self) -> dict[str, object]: - return {"type": "object"} +class SnippetTagResponse(ResponseModel): + id: str + name: str + type: str -tag_fields = {"id": fields.String, "name": fields.String, "type": fields.String} +class SnippetListItemResponse(ResponseModel): + id: str + name: str + description: str | None + type: SnippetType + version: int + use_count: int + is_published: bool + icon_info: dict[str, Any] | None + tags: list[SnippetTagResponse] + created_by: str | None + author_name: str | None + created_at: int + updated_by: str | None + updated_at: int -# Snippet list item fields (lightweight for list display) -snippet_list_fields = { - "id": fields.String, - "name": fields.String, - "description": fields.String, - "type": fields.String, - "version": fields.Integer, - "use_count": fields.Integer, - "is_published": fields.Boolean, - "icon_info": OpaqueRawField, - "tags": fields.List(fields.Nested(tag_fields)), - "created_by": fields.String, - "author_name": fields.String, - "created_at": TimestampField, - "updated_by": fields.String, - "updated_at": TimestampField, -} + @field_validator("created_at", "updated_at", mode="before") + @classmethod + def _normalize_timestamp(cls, value: datetime | int | None) -> int: + timestamp = to_timestamp(value) + if timestamp is None: + raise ValueError("timestamp is required") + return timestamp -# Full snippet fields (includes creator info and graph data) -snippet_fields = { - "id": fields.String, - "name": fields.String, - "description": fields.String, - "type": fields.String, - "version": fields.Integer, - "use_count": fields.Integer, - "is_published": fields.Boolean, - "icon_info": OpaqueRawField, - "graph": OpaqueRawField(attribute="graph_dict"), - "input_fields": OpaqueRawField(attribute="input_fields_list"), - "tags": fields.List(fields.Nested(tag_fields)), - "created_by": fields.Nested(simple_account_fields, attribute="created_by_account", allow_null=True), - "created_at": TimestampField, - "updated_by": fields.Nested(simple_account_fields, attribute="updated_by_account", allow_null=True), - "updated_at": TimestampField, -} -# Pagination response fields -snippet_pagination_fields = { - "data": fields.List(fields.Nested(snippet_list_fields)), - "page": fields.Integer, - "limit": fields.Integer, - "total": fields.Integer, - "has_more": fields.Boolean, -} +class SnippetResponse(ResponseModel): + id: str + name: str + description: str | None + type: SnippetType + version: int + use_count: int + is_published: bool + icon_info: dict[str, Any] | None + graph: dict[str, Any] = Field(validation_alias="graph_dict") + input_fields: list[dict[str, Any]] = Field(validation_alias="input_fields_list") + tags: list[SnippetTagResponse] + created_by: SimpleAccountResponse | None = Field(validation_alias="created_by_account") + created_at: int + updated_by: SimpleAccountResponse | None = Field(validation_alias="updated_by_account") + updated_at: int + + @field_validator("created_at", "updated_at", mode="before") + @classmethod + def _normalize_timestamp(cls, value: datetime | int | None) -> int: + timestamp = to_timestamp(value) + if timestamp is None: + raise ValueError("timestamp is required") + return timestamp + + +class SnippetPaginationResponse(ResponseModel): + data: list[SnippetListItemResponse] + page: int + limit: int + total: int + has_more: bool diff --git a/api/fields/workflow_fields.py b/api/fields/workflow_fields.py deleted file mode 100644 index 2d0d8f9f546..00000000000 --- a/api/fields/workflow_fields.py +++ /dev/null @@ -1,129 +0,0 @@ -from typing import override - -from flask_restx import fields - -from core.helper import encrypter -from fields.member_fields import simple_account_fields -from graphon.variables import SecretVariable, SegmentType, VariableBase -from libs.helper import TimestampField - -from ._value_type_serializer import serialize_value_type - -ENVIRONMENT_VARIABLE_SUPPORTED_TYPES = (SegmentType.STRING, SegmentType.NUMBER, SegmentType.SECRET) - - -class OpaqueRawField(fields.Raw): - @override - def schema(self) -> dict[str, object]: - return {"type": "object"} - - -class JsonValueRawField(fields.Raw): - @override - def schema(self) -> dict[str, object]: - return { - "anyOf": [ - {"type": "string"}, - {"type": "integer"}, - {"type": "number"}, - {"type": "boolean"}, - {"type": "object", "additionalProperties": True}, - {"type": "array", "items": {}}, - {"type": "null"}, - ] - } - - -class EnvironmentVariableField(fields.Raw): - @override - def schema(self) -> dict[str, object]: - return {"type": "object"} - - @override - def format(self, value): - # Mask secret variables values in environment_variables - if isinstance(value, SecretVariable): - return { - "id": value.id, - "name": value.name, - "value": encrypter.full_mask_token(), - "value_type": value.value_type.value, - "description": value.description, - } - if isinstance(value, VariableBase): - return { - "id": value.id, - "name": value.name, - "value": value.value, - "value_type": str(value.value_type.exposed_type()), - "description": value.description, - } - if isinstance(value, dict): - value_type_str = value.get("value_type") - if not isinstance(value_type_str, str): - raise TypeError( - f"unexpected type for value_type field, value={value_type_str}, type={type(value_type_str)}" - ) - value_type = SegmentType(value_type_str).exposed_type() - if value_type not in ENVIRONMENT_VARIABLE_SUPPORTED_TYPES: - raise ValueError(f"Unsupported environment variable value type: {value_type}") - return value - - -conversation_variable_fields = { - "id": fields.String, - "name": fields.String, - "value_type": fields.String(attribute=serialize_value_type), - "value": JsonValueRawField, - "description": fields.String, -} - -pipeline_variable_fields = { - "label": fields.String, - "variable": fields.String, - "type": fields.String, - "belong_to_node_id": fields.String, - "max_length": fields.Integer, - "required": fields.Boolean, - "unit": fields.String, - "default_value": JsonValueRawField, - "options": fields.List(fields.String), - "placeholder": fields.String, - "tooltips": fields.String, - "allowed_file_types": fields.List(fields.String), - "allow_file_extension": fields.List(fields.String), - "allow_file_upload_methods": fields.List(fields.String), -} - -workflow_fields = { - "id": fields.String, - "graph": OpaqueRawField(attribute="graph_dict"), - "features": OpaqueRawField(attribute="features_dict"), - "hash": fields.String(attribute="unique_hash"), - "version": fields.String, - "marked_name": fields.String, - "marked_comment": fields.String, - "created_by": fields.Nested(simple_account_fields, attribute="created_by_account"), - "created_at": TimestampField, - "updated_by": fields.Nested(simple_account_fields, attribute="updated_by_account", allow_null=True), - "updated_at": TimestampField, - "tool_published": fields.Boolean, - "environment_variables": fields.List(EnvironmentVariableField()), - "conversation_variables": fields.List(fields.Nested(conversation_variable_fields)), - "rag_pipeline_variables": fields.List(fields.Nested(pipeline_variable_fields)), -} - -workflow_partial_fields = { - "id": fields.String, - "created_by": fields.String, - "created_at": TimestampField, - "updated_by": fields.String, - "updated_at": TimestampField, -} - -workflow_pagination_fields = { - "items": fields.List(fields.Nested(workflow_fields), attribute="items"), - "page": fields.Integer, - "limit": fields.Integer(attribute="limit"), - "has_more": fields.Boolean(attribute="has_more"), -} diff --git a/api/openapi/markdown/console-openapi.md b/api/openapi/markdown/console-openapi.md index b47f3f7d410..f9db4ee1904 100644 --- a/api/openapi/markdown/console-openapi.md +++ b/api/openapi/markdown/console-openapi.md @@ -9432,9 +9432,9 @@ Bedrock retrieval test (internal use only) #### Responses -| Code | Description | Schema | -| ---- | ----------- | ------ | -| 200 | Success | **application/json**: [GeneratedAppResponse](#generatedappresponse)
| +| Code | Description | +| ---- | ----------- | +| 200 | Success | ### [POST] /trial-apps/{app_id}/completion-messages #### Parameters @@ -9451,9 +9451,9 @@ Bedrock retrieval test (internal use only) #### Responses -| Code | Description | Schema | -| ---- | ----------- | ------ | -| 200 | Success | **application/json**: [GeneratedAppResponse](#generatedappresponse)
| +| Code | Description | +| ---- | ----------- | +| 200 | Success | ### [GET] /trial-apps/{app_id}/datasets #### Parameters @@ -9568,9 +9568,9 @@ Returns the site configuration for the application including theme, icons, and t #### Responses -| Code | Description | Schema | -| ---- | ----------- | ------ | -| 200 | Success | **application/json**: [GeneratedAppResponse](#generatedappresponse)
| +| Code | Description | +| ---- | ----------- | +| 200 | Success | ### [POST] /trial-apps/{app_id}/workflows/tasks/{task_id}/stop **Stop workflow task** diff --git a/api/tests/unit_tests/fields/test_snippet_fields.py b/api/tests/unit_tests/fields/test_snippet_fields.py index 2d17a9e577a..97573908576 100644 --- a/api/tests/unit_tests/fields/test_snippet_fields.py +++ b/api/tests/unit_tests/fields/test_snippet_fields.py @@ -1,9 +1,8 @@ from datetime import UTC, datetime from types import SimpleNamespace -from flask_restx import marshal - -from fields.snippet_fields import snippet_list_fields +from fields.snippet_fields import SnippetListItemResponse +from libs.helper import dump_response def test_snippet_list_fields_include_author_name() -> None: @@ -24,6 +23,6 @@ def test_snippet_list_fields_include_author_name() -> None: updated_at=datetime.fromtimestamp(1704067201, tz=UTC), ) - result = marshal(snippet, snippet_list_fields) + result = dump_response(SnippetListItemResponse, snippet) assert result["author_name"] == "Alice" diff --git a/packages/contracts/generated/api/console/trial-apps/types.gen.ts b/packages/contracts/generated/api/console/trial-apps/types.gen.ts index 7a5f4f9f755..97c4400f1de 100644 --- a/packages/contracts/generated/api/console/trial-apps/types.gen.ts +++ b/packages/contracts/generated/api/console/trial-apps/types.gen.ts @@ -46,8 +46,6 @@ export type ChatRequest = { retriever_from?: string } -export type GeneratedAppResponse = JsonValue - export type CompletionRequest = { files?: Array | null inputs: { @@ -220,17 +218,6 @@ export type TrialWorkflowPartialResponse = { updated_by?: string | null } -export type JsonValue - = | string - | number - | number - | boolean - | { - [key: string]: unknown - } - | Array - | null - export type TrialDatasetResponse = { created_at?: number | null created_by?: string | null @@ -278,8 +265,6 @@ export type TrialAppModel = { provider: string } -export type GeneratedAppResponseWritable = JsonValue - export type SiteWritable = { chat_color_theme?: string | null chat_color_theme_inverted: boolean @@ -339,7 +324,9 @@ export type PostTrialAppsByAppIdChatMessagesData = { } export type PostTrialAppsByAppIdChatMessagesResponses = { - 200: GeneratedAppResponse + 200: { + [key: string]: unknown + } } export type PostTrialAppsByAppIdChatMessagesResponse @@ -355,7 +342,9 @@ export type PostTrialAppsByAppIdCompletionMessagesData = { } export type PostTrialAppsByAppIdCompletionMessagesResponses = { - 200: GeneratedAppResponse + 200: { + [key: string]: unknown + } } export type PostTrialAppsByAppIdCompletionMessagesResponse @@ -472,7 +461,9 @@ export type PostTrialAppsByAppIdWorkflowsRunData = { } export type PostTrialAppsByAppIdWorkflowsRunResponses = { - 200: GeneratedAppResponse + 200: { + [key: string]: unknown + } } export type PostTrialAppsByAppIdWorkflowsRunResponse diff --git a/packages/contracts/generated/api/console/trial-apps/zod.gen.ts b/packages/contracts/generated/api/console/trial-apps/zod.gen.ts index 5570ab88640..35cab33cabf 100644 --- a/packages/contracts/generated/api/console/trial-apps/zod.gen.ts +++ b/packages/contracts/generated/api/console/trial-apps/zod.gen.ts @@ -160,22 +160,6 @@ export const zTrialWorkflowPartialResponse = z.object({ updated_by: z.string().nullish(), }) -export const zJsonValue = z - .union([ - z.string(), - z.int(), - z.number(), - z.boolean(), - z.record(z.string(), z.unknown()), - z.array(z.unknown()), - ]) - .nullable() - -/** - * GeneratedAppResponse - */ -export const zGeneratedAppResponse = zJsonValue - /** * TrialDatasetResponse */ @@ -344,11 +328,6 @@ export const zTrialAppDetailResponse = z.object({ workflow: zTrialWorkflowPartialResponse.nullish(), }) -/** - * GeneratedAppResponse - */ -export const zGeneratedAppResponseWritable = zJsonValue - /** * Site */ @@ -396,7 +375,7 @@ export const zPostTrialAppsByAppIdChatMessagesPath = z.object({ /** * Success */ -export const zPostTrialAppsByAppIdChatMessagesResponse = zGeneratedAppResponse +export const zPostTrialAppsByAppIdChatMessagesResponse = z.record(z.string(), z.unknown()) export const zPostTrialAppsByAppIdCompletionMessagesBody = zCompletionRequest @@ -407,7 +386,7 @@ export const zPostTrialAppsByAppIdCompletionMessagesPath = z.object({ /** * Success */ -export const zPostTrialAppsByAppIdCompletionMessagesResponse = zGeneratedAppResponse +export const zPostTrialAppsByAppIdCompletionMessagesResponse = z.record(z.string(), z.unknown()) export const zGetTrialAppsByAppIdDatasetsPath = z.object({ app_id: z.uuid(), @@ -482,7 +461,7 @@ export const zPostTrialAppsByAppIdWorkflowsRunPath = z.object({ /** * Success */ -export const zPostTrialAppsByAppIdWorkflowsRunResponse = zGeneratedAppResponse +export const zPostTrialAppsByAppIdWorkflowsRunResponse = z.record(z.string(), z.unknown()) export const zPostTrialAppsByAppIdWorkflowsTasksByTaskIdStopPath = z.object({ app_id: z.uuid(),