From bbdf3d76347eb46c3bd9632b82cf50b597b9dd7d Mon Sep 17 00:00:00 2001 From: yyh <92089059+lyzno1@users.noreply.github.com> Date: Tue, 9 Jun 2026 12:40:32 +0800 Subject: [PATCH] fix(agent-v2): complete console API contract schemas (#37210) Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com> --- .../app/workflow_node_output_inspector.py | 23 ++ .../workflow/nodes/agent_v2/validators.py | 4 +- api/models/agent_config_entities.py | 56 ++++- api/openapi/markdown/console-swagger.md | 155 ++++++++++-- .../workflow/node_output_inspector_service.py | 4 +- .../agent_v2/test_runtime_request_builder.py | 22 ++ .../generated/api/console/agents/orpc.gen.ts | 16 -- .../generated/api/console/agents/types.gen.ts | 46 +++- .../generated/api/console/agents/zod.gen.ts | 82 +++++-- .../generated/api/console/apps/orpc.gen.ts | 128 +--------- .../generated/api/console/apps/types.gen.ts | 137 ++++++++--- .../generated/api/console/apps/zod.gen.ts | 232 +++++++++++++----- 12 files changed, 625 insertions(+), 280 deletions(-) diff --git a/api/controllers/console/app/workflow_node_output_inspector.py b/api/controllers/console/app/workflow_node_output_inspector.py index 7da3ebe32b..ed4dbe9b3e 100644 --- a/api/controllers/console/app/workflow_node_output_inspector.py +++ b/api/controllers/console/app/workflow_node_output_inspector.py @@ -30,6 +30,7 @@ from uuid import UUID from flask import Response from flask_restx import Resource +from controllers.common.schema import register_response_schema_models from controllers.console import console_ns from controllers.console.app.wraps import get_app_model from controllers.console.wraps import account_initialization_required, setup_required @@ -38,8 +39,13 @@ from libs.login import login_required from models import App, AppMode from services.workflow import inspector_events from services.workflow.node_output_inspector_service import ( + CheckResultView, NodeOutputInspectorError, NodeOutputInspectorService, + NodeOutputsView, + NodeOutputView, + OutputPreviewView, + WorkflowRunSnapshotView, ) logger = logging.getLogger(__name__) @@ -54,6 +60,15 @@ _HEARTBEAT_EVERY_TICKS = 15 # many ticks (= seconds). _STREAM_HARD_TIMEOUT_TICKS = 1800 # 30 min +register_response_schema_models( + console_ns, + CheckResultView, + NodeOutputView, + NodeOutputsView, + WorkflowRunSnapshotView, + OutputPreviewView, +) + def _service() -> NodeOutputInspectorService: """One-line factory so tests can monkeypatch a stub if needed.""" @@ -124,6 +139,7 @@ class WorkflowDraftRunNodeOutputsApi(Resource): @console_ns.doc("get_workflow_draft_run_node_outputs") @console_ns.doc(description="Snapshot of every node's declared outputs for a draft workflow run.") @console_ns.doc(params={"app_id": "Application ID", "run_id": "Workflow run ID"}) + @console_ns.response(200, "Workflow run node outputs", console_ns.models[WorkflowRunSnapshotView.__name__]) @console_ns.response(404, "Workflow run not found") @setup_required @login_required @@ -146,6 +162,7 @@ class WorkflowDraftRunNodeOutputDetailApi(Resource): "node_id": "Node ID inside the workflow graph", } ) + @console_ns.response(200, "Workflow run node output detail", console_ns.models[NodeOutputsView.__name__]) @console_ns.response(404, "Workflow run / node not found") @setup_required @login_required @@ -171,6 +188,7 @@ class WorkflowDraftRunNodeOutputPreviewApi(Resource): "output_name": "Declared output name as exposed by Composer", } ) + @console_ns.response(200, "Workflow run node output preview", console_ns.models[OutputPreviewView.__name__]) @console_ns.response(404, "Workflow run / node / output not found") @setup_required @login_required @@ -309,6 +327,7 @@ class WorkflowDraftRunNodeOutputEventsApi(Resource): @console_ns.doc("stream_workflow_draft_run_node_output_events") @console_ns.doc(description="Server-Sent Events stream of inspector deltas for a draft workflow run.") @console_ns.doc(params={"app_id": "Application ID", "run_id": "Workflow run ID"}) + @console_ns.response(200, "Workflow run node output event stream") @console_ns.response(404, "Workflow run not found") @setup_required @login_required @@ -338,6 +357,7 @@ class WorkflowPublishedRunNodeOutputsApi(Resource): @console_ns.doc("get_workflow_published_run_node_outputs") @console_ns.doc(description="Snapshot of every node's declared outputs for a published workflow run.") @console_ns.doc(params={"app_id": "Application ID", "run_id": "Workflow run ID"}) + @console_ns.response(200, "Workflow run node outputs", console_ns.models[WorkflowRunSnapshotView.__name__]) @console_ns.response(404, "Workflow run not found") @setup_required @login_required @@ -360,6 +380,7 @@ class WorkflowPublishedRunNodeOutputDetailApi(Resource): "node_id": "Node ID inside the workflow graph", } ) + @console_ns.response(200, "Workflow run node output detail", console_ns.models[NodeOutputsView.__name__]) @console_ns.response(404, "Workflow run / node not found") @setup_required @login_required @@ -386,6 +407,7 @@ class WorkflowPublishedRunNodeOutputPreviewApi(Resource): "output_name": "Declared output name as exposed by Composer", } ) + @console_ns.response(200, "Workflow run node output preview", console_ns.models[OutputPreviewView.__name__]) @console_ns.response(404, "Workflow run / node / output not found") @setup_required @login_required @@ -402,6 +424,7 @@ class WorkflowPublishedRunNodeOutputEventsApi(Resource): @console_ns.doc("stream_workflow_published_run_node_output_events") @console_ns.doc(description="Server-Sent Events stream of inspector deltas for a published workflow run.") @console_ns.doc(params={"app_id": "Application ID", "run_id": "Workflow run ID"}) + @console_ns.response(200, "Workflow run node output event stream") @console_ns.response(404, "Workflow run not found") @setup_required @login_required diff --git a/api/core/workflow/nodes/agent_v2/validators.py b/api/core/workflow/nodes/agent_v2/validators.py index 4fab746207..cb2e54bda7 100644 --- a/api/core/workflow/nodes/agent_v2/validators.py +++ b/api/core/workflow/nodes/agent_v2/validators.py @@ -265,7 +265,9 @@ class WorkflowAgentNodeValidator: binding: WorkflowAgentNodeBinding, node_job: WorkflowNodeJobConfig, ) -> None: - forbidden_paths = cls._find_locked_agent_soul_paths(node_job.metadata.model_dump(mode="python")) + forbidden_paths = cls._find_locked_agent_soul_paths( + node_job.metadata.model_dump(mode="python", exclude_none=True) + ) if forbidden_paths: raise WorkflowAgentNodeValidationError( f"Workflow Agent node {binding.node_id} cannot override locked Agent Soul fields: " diff --git a/api/models/agent_config_entities.py b/api/models/agent_config_entities.py index 4d8443b429..115bd180cd 100644 --- a/api/models/agent_config_entities.py +++ b/api/models/agent_config_entities.py @@ -73,7 +73,7 @@ RuntimeParameterValue = JsonPrimitive | list[str] | list[int] | list[float] | li class AgentFlexibleConfig(BaseModel): - model_config = ConfigDict(extra="allow") + model_config = ConfigDict(extra="allow", json_schema_extra={"x-dify-opaque": True}) def get(self, key: str, default: Any = None) -> Any: return self.model_dump(mode="python").get(key, default) @@ -87,10 +87,15 @@ class AgentFlexibleConfig(BaseModel): class AgentFileRefConfig(AgentFlexibleConfig): id: str | None = Field(default=None, max_length=255) + file_id: str | None = Field(default=None, max_length=255) + upload_file_id: str | None = Field(default=None, max_length=255) + reference: str | None = Field(default=None, max_length=255) + tenant_id: str | None = Field(default=None, max_length=255) name: str | None = Field(default=None, max_length=255) type: str | None = Field(default=None, max_length=64) transfer_method: str | None = Field(default=None, max_length=64) url: str | None = None + remote_url: str | None = None class AgentSkillRefConfig(AgentFlexibleConfig): @@ -101,17 +106,36 @@ class AgentSkillRefConfig(AgentFlexibleConfig): path: str | None = None +class AgentPermissionConfig(BaseModel): + model_config = ConfigDict(extra="ignore") + + allowed: bool | None = None + status: str | None = Field(default=None, max_length=64) + state: str | None = Field(default=None, max_length=64) + + class AgentCliToolConfig(AgentFlexibleConfig): enabled: bool = True name: str | None = Field(default=None, max_length=255) + tool_name: str | None = Field(default=None, max_length=255) + label: str | None = Field(default=None, max_length=255) description: str | None = None command: str | None = None - invoke_metadata: dict[str, Any] = Field(default_factory=dict) + install_commands: list[str] = Field(default_factory=list) + install_command: str | None = None + install: str | None = None + setup_command: str | None = None + invoke_metadata: dict[str, Any] = Field(default_factory=dict, json_schema_extra={"x-dify-opaque": True}) pre_authorized: bool | None = None authorization_status: AgentCliToolAuthorizationStatus | None = None - permission: dict[str, Any] = Field(default_factory=dict) + permission: AgentPermissionConfig | None = None dangerous: bool = False + dangerous_command: bool = False + requires_confirmation: bool = False dangerous_acknowledged: bool = False + dangerous_accepted: bool = False + risk_accepted: bool = False + approved: bool = False risk_level: AgentCliToolRiskLevel | None = None @@ -132,8 +156,12 @@ class AgentHumanContactConfig(AgentFlexibleConfig): id: str | None = Field(default=None, max_length=255) contact_id: str | None = Field(default=None, max_length=255) human_id: str | None = Field(default=None, max_length=255) + tenant_id: str | None = Field(default=None, max_length=255) name: str | None = Field(default=None, max_length=255) email: str | None = Field(default=None, max_length=255) + channel: str | None = Field(default=None, max_length=64) + method: str | None = Field(default=None, max_length=64) + contact_method: str | None = Field(default=None, max_length=64) class AgentHumanToolConfig(AgentFlexibleConfig): @@ -144,17 +172,27 @@ class AgentHumanToolConfig(AgentFlexibleConfig): class AgentEnvVariableConfig(AgentFlexibleConfig): name: str | None = Field(default=None, max_length=255) + key: str | None = Field(default=None, max_length=255) + env_name: str | None = Field(default=None, max_length=255) + variable: str | None = Field(default=None, max_length=255) type: str | None = Field(default=None, max_length=64) value: RuntimeParameterValue = None + default: RuntimeParameterValue = None required: bool = False class AgentSecretRefConfig(AgentFlexibleConfig): name: str | None = Field(default=None, max_length=255) + key: str | None = Field(default=None, max_length=255) + env_name: str | None = Field(default=None, max_length=255) + variable: str | None = Field(default=None, max_length=255) type: str | None = Field(default=None, max_length=64) id: str | None = Field(default=None, max_length=255) + ref: str | None = Field(default=None, max_length=255) + credential_id: str | None = Field(default=None, max_length=255) + provider_credential_id: str | None = Field(default=None, max_length=255) provider: str | None = Field(default=None, max_length=255) - permission: dict[str, Any] = Field(default_factory=dict) + permission: AgentPermissionConfig | None = None permission_status: str | None = Field(default=None, max_length=64) @@ -162,6 +200,7 @@ class AgentSandboxProviderConfig(AgentFlexibleConfig): image: str | None = None working_dir: str | None = None env: list[AgentEnvVariableConfig] = Field(default_factory=list) + cpu: int | None = Field(default=None, ge=1) class AgentMemoryArtifactConfig(AgentFlexibleConfig): @@ -176,7 +215,7 @@ class AgentModelResponseFormatConfig(AgentFlexibleConfig): class AgentSoulModelSettings(BaseModel): - model_config = ConfigDict(extra="allow") + model_config = ConfigDict(extra="ignore") temperature: float | None = None top_p: float | None = None @@ -241,9 +280,10 @@ class WorkflowPreviousNodeOutputRef(AgentFlexibleConfig): class WorkflowNodeJobMetadata(BaseModel): - model_config = ConfigDict(extra="allow") + model_config = ConfigDict(extra="ignore") file_refs: list[AgentFileRefConfig] | None = None + agent_soul: dict[str, Any] | None = Field(default=None, json_schema_extra={"x-dify-opaque": True}) class AgentSoulPromptConfig(BaseModel): @@ -391,7 +431,7 @@ class AppVariableConfig(BaseModel): name: str = Field(min_length=1, max_length=255) type: str = Field(min_length=1, max_length=64) required: bool = False - default: Any = None + default: Any = Field(default=None, json_schema_extra={"x-dify-opaque": True}) class AgentSoulConfig(BaseModel): @@ -490,7 +530,7 @@ class DeclaredOutputFailureStrategy(BaseModel): # When ``on_failure == DEFAULT_VALUE`` this value replaces the failed output. The # value's shape must match the owning ``DeclaredOutputConfig.type``; that match is # enforced at ``DeclaredOutputConfig`` level so the strategy stays type-agnostic. - default_value: Any = None + default_value: Any = Field(default=None, json_schema_extra={"x-dify-opaque": True}) @model_validator(mode="after") def _require_default_value_when_default_strategy(self) -> DeclaredOutputFailureStrategy: diff --git a/api/openapi/markdown/console-swagger.md b/api/openapi/markdown/console-swagger.md index ad216c0d9c..1610fd6bdf 100644 --- a/api/openapi/markdown/console-swagger.md +++ b/api/openapi/markdown/console-swagger.md @@ -3724,9 +3724,10 @@ Snapshot of every node's declared outputs for a draft workflow run. ##### Responses -| Code | Description | -| ---- | ----------- | -| 404 | Workflow run not found | +| Code | Description | Schema | +| ---- | ----------- | ------ | +| 200 | Workflow run node outputs | [WorkflowRunSnapshotView](#workflowrunsnapshotview) | +| 404 | Workflow run not found | | ### /apps/{app_id}/workflows/draft/runs/{run_id}/node-outputs/events @@ -3746,6 +3747,7 @@ Server-Sent Events stream of inspector deltas for a draft workflow run. | Code | Description | | ---- | ----------- | +| 200 | Workflow run node output event stream | | 404 | Workflow run not found | ### /apps/{app_id}/workflows/draft/runs/{run_id}/node-outputs/{node_id} @@ -3765,9 +3767,10 @@ One node's declared outputs for a draft workflow run. ##### Responses -| Code | Description | -| ---- | ----------- | -| 404 | Workflow run / node not found | +| Code | Description | Schema | +| ---- | ----------- | ------ | +| 200 | Workflow run node output detail | [NodeOutputsView](#nodeoutputsview) | +| 404 | Workflow run / node not found | | ### /apps/{app_id}/workflows/draft/runs/{run_id}/node-outputs/{node_id}/{output_name}/preview @@ -3787,9 +3790,10 @@ Full value for one declared output, including signed download URL for files. ##### Responses -| Code | Description | -| ---- | ----------- | -| 404 | Workflow run / node / output not found | +| Code | Description | Schema | +| ---- | ----------- | ------ | +| 200 | Workflow run node output preview | [OutputPreviewView](#outputpreviewview) | +| 404 | Workflow run / node / output not found | | ### /apps/{app_id}/workflows/draft/system-variables @@ -4044,9 +4048,10 @@ Snapshot of every node's declared outputs for a published workflow run. ##### Responses -| Code | Description | -| ---- | ----------- | -| 404 | Workflow run not found | +| Code | Description | Schema | +| ---- | ----------- | ------ | +| 200 | Workflow run node outputs | [WorkflowRunSnapshotView](#workflowrunsnapshotview) | +| 404 | Workflow run not found | | ### /apps/{app_id}/workflows/published/runs/{run_id}/node-outputs/events @@ -4066,6 +4071,7 @@ Server-Sent Events stream of inspector deltas for a published workflow run. | Code | Description | | ---- | ----------- | +| 200 | Workflow run node output event stream | | 404 | Workflow run not found | ### /apps/{app_id}/workflows/published/runs/{run_id}/node-outputs/{node_id} @@ -4085,9 +4091,10 @@ One node's declared outputs for a published workflow run. ##### Responses -| Code | Description | -| ---- | ----------- | -| 404 | Workflow run / node not found | +| Code | Description | Schema | +| ---- | ----------- | ------ | +| 200 | Workflow run node output detail | [NodeOutputsView](#nodeoutputsview) | +| 404 | Workflow run / node not found | | ### /apps/{app_id}/workflows/published/runs/{run_id}/node-outputs/{node_id}/{output_name}/preview @@ -4107,9 +4114,10 @@ Full value for one declared output of a published run. ##### Responses -| Code | Description | -| ---- | ----------- | -| 404 | Workflow run / node / output not found | +| Code | Description | Schema | +| ---- | ----------- | ------ | +| 200 | Workflow run node output preview | [OutputPreviewView](#outputpreviewview) | +| 404 | Workflow run / node / output not found | | ### /apps/{app_id}/workflows/triggers/webhook @@ -11835,17 +11843,28 @@ composer/publish validators and skipped by runtime request builders. | Name | Type | Description | Required | | ---- | ---- | ----------- | -------- | +| approved | boolean | | No | | authorization_status | [AgentCliToolAuthorizationStatus](#agentclitoolauthorizationstatus) | | No | | command | string | | No | | dangerous | boolean | | No | +| dangerous_accepted | boolean | | No | | dangerous_acknowledged | boolean | | No | +| dangerous_command | boolean | | No | | description | string | | No | | enabled | boolean | | No | +| install | string | | No | +| install_command | string | | No | +| install_commands | [ string ] | | No | | invoke_metadata | object | | No | +| label | string | | No | | name | string | | No | -| permission | object | | No | +| permission | [AgentPermissionConfig](#agentpermissionconfig) | | No | | pre_authorized | boolean | | No | +| requires_confirmation | boolean | | No | +| risk_accepted | boolean | | No | | risk_level | [AgentCliToolRiskLevel](#agentclitoolrisklevel) | | No | +| setup_command | string | | No | +| tool_name | string | | No | #### AgentCliToolRiskLevel @@ -12004,10 +12023,14 @@ Audit operation recorded for Agent Soul version/revision changes. | Name | Type | Description | Required | | ---- | ---- | ----------- | -------- | +| default | string
integer
number
boolean
[ string ]
[ integer ]
[ number ]
[ boolean ] | | No | +| env_name | string | | No | +| key | string | | No | | name | string | | No | | required | boolean | | No | | type | string | | No | | value | string
integer
number
boolean
[ string ]
[ integer ]
[ number ]
[ boolean ] | | No | +| variable | string | | No | #### AgentFeatureToggleConfig @@ -12019,21 +12042,30 @@ Audit operation recorded for Agent Soul version/revision changes. | Name | Type | Description | Required | | ---- | ---- | ----------- | -------- | +| file_id | string | | No | | id | string | | No | | name | string | | No | +| reference | string | | No | +| remote_url | string | | No | +| tenant_id | string | | No | | transfer_method | string | | No | | type | string | | No | +| upload_file_id | string | | No | | url | string | | No | #### AgentHumanContactConfig | Name | Type | Description | Required | | ---- | ---- | ----------- | -------- | +| channel | string | | No | | contact_id | string | | No | +| contact_method | string | | No | | email | string | | No | | human_id | string | | No | | id | string | | No | +| method | string | | No | | name | string | | No | +| tenant_id | string | | No | #### AgentHumanToolConfig @@ -12177,6 +12209,14 @@ the current roster/workflow APIs scoped to Dify Agent. | keywords | string | | No | | outputs_config | [AgentModerationIOConfig](#agentmoderationioconfig) | | No | +#### AgentPermissionConfig + +| Name | Type | Description | Required | +| ---- | ---- | ----------- | -------- | +| allowed | boolean | | No | +| state | string | | No | +| status | string | | No | + #### AgentReferencingWorkflowResponse | Name | Type | Description | Required | @@ -12233,6 +12273,7 @@ the current roster/workflow APIs scoped to Dify Agent. | Name | Type | Description | Required | | ---- | ---- | ----------- | -------- | +| cpu | integer | | No | | env | [ [AgentEnvVariableConfig](#agentenvvariableconfig) ] | | No | | image | string | | No | | working_dir | string | | No | @@ -12249,12 +12290,18 @@ Visibility and lifecycle scope of an Agent record. | Name | Type | Description | Required | | ---- | ---- | ----------- | -------- | +| credential_id | string | | No | +| env_name | string | | No | | id | string | | No | +| key | string | | No | | name | string | | No | -| permission | object | | No | +| permission | [AgentPermissionConfig](#agentpermissionconfig) | | No | | permission_status | string | | No | | provider | string | | No | +| provider_credential_id | string | | No | +| ref | string | | No | | type | string | | No | +| variable | string | | No | #### AgentSensitiveWordAvoidanceFeatureConfig @@ -13093,6 +13140,15 @@ Button styles for user actions. | ---- | ---- | ----------- | -------- | | email | string | | Yes | +#### CheckResultView + +``type_check`` / ``output_check`` per-output summary block. + +| Name | Type | Description | Required | +| ---- | ---- | ----------- | -------- | +| passed | boolean | | Yes | +| reason | string | | No | + #### ChildChunkBatchUpdatePayload | Name | Type | Description | Required | @@ -15535,6 +15591,38 @@ Enum class for model type. | ---- | ---- | ----------- | -------- | | node_id | string | | Yes | +#### NodeOutputStatus + +Lifecycle status of a single declared output within a run. + +| Name | Type | Description | Required | +| ---- | ---- | ----------- | -------- | +| NodeOutputStatus | string | Lifecycle status of a single declared output within a run. | | + +#### NodeOutputView + +| Name | Type | Description | Required | +| ---- | ---- | ----------- | -------- | +| name | string | | Yes | +| output_check | [CheckResultView](#checkresultview) | | No | +| retried | integer | | No | +| status | [NodeOutputStatus](#nodeoutputstatus) | | Yes | +| type | [DeclaredOutputType](#declaredoutputtype) | | No | +| type_check | [CheckResultView](#checkresultview) | | No | +| value_preview | | | No | + +#### NodeOutputsView + +| Name | Type | Description | Required | +| ---- | ---- | ----------- | -------- | +| node_completed_at | dateTime | | No | +| node_display_name | string | | Yes | +| node_id | string | | Yes | +| node_kind | string | | Yes | +| node_started_at | dateTime | | No | +| node_status | [NodeStatus](#nodestatus) | | Yes | +| outputs | [ [NodeOutputView](#nodeoutputview) ] | | No | + #### NodeRunPayload | Name | Type | Description | Required | @@ -15547,6 +15635,14 @@ Enum class for model type. | ---- | ---- | ----------- | -------- | | inputs | object | | Yes | +#### NodeStatus + +Coarse node-level status used by Inspector to pick a banner. + +| Name | Type | Description | Required | +| ---- | ---- | ----------- | -------- | +| NodeStatus | string | Coarse node-level status used by Inspector to pick a banner. | | + #### NotionEstimatePayload | Name | Type | Description | Required | @@ -15637,6 +15733,16 @@ output check fails and any configured retry attempts have been exhausted. | ---- | ---- | ----------- | -------- | | OutputErrorStrategy | string | Per-output failure handling strategy. Mirrors ``graphon.ErrorStrategy`` but scoped to a single declared output of a Workflow Agent Node. The runtime applies the strategy after type check or output check fails and any configured retry attempts have been exhausted. | | +#### OutputPreviewView + +| Name | Type | Description | Required | +| ---- | ---- | ----------- | -------- | +| node_id | string | | Yes | +| output_name | string | | Yes | +| status | [NodeOutputStatus](#nodeoutputstatus) | | Yes | +| type | [DeclaredOutputType](#declaredoutputtype) | | No | +| value | | | No | + #### OwnerTransferCheckPayload | Name | Type | Description | Required | @@ -17821,6 +17927,7 @@ can reuse its existing handler. | Name | Type | Description | Required | | ---- | ---- | ----------- | -------- | +| agent_soul | object | | No | | file_refs | [ [AgentFileRefConfig](#agentfilerefconfig) ] | | No | #### WorkflowNodeJobMode @@ -18078,6 +18185,14 @@ Query parameters for workflow runs. | files | [ ] | | No | | inputs | object | | Yes | +#### WorkflowRunSnapshotView + +| Name | Type | Description | Required | +| ---- | ---- | ----------- | -------- | +| node_outputs | [ [NodeOutputsView](#nodeoutputsview) ] | | No | +| workflow_run_id | string | | Yes | +| workflow_run_status | [WorkflowExecutionStatus](#workflowexecutionstatus) | | Yes | + #### WorkflowStatisticQuery | Name | Type | Description | Required | diff --git a/api/services/workflow/node_output_inspector_service.py b/api/services/workflow/node_output_inspector_service.py index c09bd9065e..cae5ed9c15 100644 --- a/api/services/workflow/node_output_inspector_service.py +++ b/api/services/workflow/node_output_inspector_service.py @@ -115,7 +115,7 @@ class NodeOutputView(BaseModel): name: str type: DeclaredOutputType | None = None status: NodeOutputStatus - value_preview: Any = None + value_preview: Any = Field(default=None, json_schema_extra={"x-dify-opaque": True}) type_check: CheckResultView | None = None output_check: CheckResultView | None = None retried: int = 0 @@ -148,7 +148,7 @@ class OutputPreviewView(BaseModel): output_name: str type: DeclaredOutputType | None = None status: NodeOutputStatus - value: Any = None # full value (with signed URL for file refs) + value: Any = Field(default=None, json_schema_extra={"x-dify-opaque": True}) class NodeOutputInspectorError(Exception): diff --git a/api/tests/unit_tests/core/workflow/nodes/agent_v2/test_runtime_request_builder.py b/api/tests/unit_tests/core/workflow/nodes/agent_v2/test_runtime_request_builder.py index 4790e77075..865707126c 100644 --- a/api/tests/unit_tests/core/workflow/nodes/agent_v2/test_runtime_request_builder.py +++ b/api/tests/unit_tests/core/workflow/nodes/agent_v2/test_runtime_request_builder.py @@ -44,6 +44,28 @@ class CapturingCredentialsProvider: return {"api_key": "secret-key"} +def test_agent_soul_round_trip_preserves_existing_app_feature_fields(): + config = AgentSoulConfig.model_validate( + { + "app_features": { + "file_upload": { + "enabled": True, + "allowed_file_upload_methods": ["local_file"], + }, + "annotation_reply": {"enabled": True}, + "more_like_this": {"enabled": False}, + } + } + ) + + dumped = config.model_dump(mode="json") + + assert dumped["app_features"]["file_upload"]["enabled"] is True + assert dumped["app_features"]["file_upload"]["allowed_file_upload_methods"] == ["local_file"] + assert dumped["app_features"]["annotation_reply"] == {"enabled": True} + assert dumped["app_features"]["more_like_this"] == {"enabled": False} + + class FakePluginToolsBuilder: def __init__(self) -> None: # Capture the runtime invocation source so tests can assert it was diff --git a/packages/contracts/generated/api/console/agents/orpc.gen.ts b/packages/contracts/generated/api/console/agents/orpc.gen.ts index 067dd6fc93..25c1ee7cc7 100644 --- a/packages/contracts/generated/api/console/agents/orpc.gen.ts +++ b/packages/contracts/generated/api/console/agents/orpc.gen.ts @@ -38,16 +38,8 @@ export const inviteOptions = { get, } -/** - * Generated contract types may be inaccurate because backend OpenAPI annotations are incomplete. Do not migrate callers until the generated contract is accurate. - * - * @deprecated - */ export const get2 = oc .route({ - deprecated: true, - description: - 'Generated contract types may be inaccurate because backend OpenAPI annotations are incomplete. Do not migrate callers until the generated contract is accurate.', inputStructure: 'detailed', method: 'GET', operationId: 'getAgentsByAgentIdVersionsByVersionId', @@ -129,16 +121,8 @@ export const get5 = oc .input(z.object({ query: zGetAgentsQuery.optional() })) .output(zGetAgentsResponse) -/** - * Generated contract types may be inaccurate because backend OpenAPI annotations are incomplete. Do not migrate callers until the generated contract is accurate. - * - * @deprecated - */ export const post = oc .route({ - deprecated: true, - description: - 'Generated contract types may be inaccurate because backend OpenAPI annotations are incomplete. Do not migrate callers until the generated contract is accurate.', inputStructure: 'detailed', method: 'POST', operationId: 'postAgents', diff --git a/packages/contracts/generated/api/console/agents/types.gen.ts b/packages/contracts/generated/api/console/agents/types.gen.ts index 06fb1aae6b..dc2b712fe5 100644 --- a/packages/contracts/generated/api/console/agents/types.gen.ts +++ b/packages/contracts/generated/api/console/agents/types.gen.ts @@ -255,31 +255,43 @@ export type AgentTextToSpeechFeatureConfig = { } export type AgentSecretRefConfig = { + credential_id?: string | null + env_name?: string | null id?: string | null + key?: string | null name?: string | null - permission?: { - [key: string]: unknown - } + permission?: AgentPermissionConfig permission_status?: string | null provider?: string | null + provider_credential_id?: string | null + ref?: string | null type?: string | null + variable?: string | null [key: string]: unknown } export type AgentEnvVariableConfig = { + default?: unknown + env_name?: string | null + key?: string | null name?: string | null required?: boolean type?: string | null value?: unknown + variable?: string | null [key: string]: unknown } export type AgentHumanContactConfig = { + channel?: string | null contact_id?: string | null + contact_method?: string | null email?: string | null human_id?: string | null id?: string | null + method?: string | null name?: string | null + tenant_id?: string | null [key: string]: unknown } @@ -329,10 +341,10 @@ export type AgentSoulModelSettings = { stop?: Array | null temperature?: number | null top_p?: number | null - [key: string]: unknown } export type AgentSandboxProviderConfig = { + cpu?: number | null env?: Array image?: string | null working_dir?: string | null @@ -340,10 +352,15 @@ export type AgentSandboxProviderConfig = { } export type AgentFileRefConfig = { + file_id?: string | null id?: string | null name?: string | null + reference?: string | null + remote_url?: string | null + tenant_id?: string | null transfer_method?: string | null type?: string | null + upload_file_id?: string | null url?: string | null [key: string]: unknown } @@ -358,21 +375,30 @@ export type AgentSkillRefConfig = { } export type AgentCliToolConfig = { + approved?: boolean authorization_status?: AgentCliToolAuthorizationStatus command?: string | null dangerous?: boolean + dangerous_accepted?: boolean dangerous_acknowledged?: boolean + dangerous_command?: boolean description?: string | null enabled?: boolean + install?: string | null + install_command?: string | null + install_commands?: Array invoke_metadata?: { [key: string]: unknown } + label?: string | null name?: string | null - permission?: { - [key: string]: unknown - } + permission?: AgentPermissionConfig pre_authorized?: boolean | null + requires_confirmation?: boolean + risk_accepted?: boolean risk_level?: AgentCliToolRiskLevel + setup_command?: string | null + tool_name?: string | null [key: string]: unknown } @@ -400,6 +426,12 @@ export type AgentModerationProviderConfig = { [key: string]: unknown } +export type AgentPermissionConfig = { + allowed?: boolean | null + state?: string | null + status?: string | null +} + export type AgentModelResponseFormatConfig = { type?: string | null [key: string]: unknown diff --git a/packages/contracts/generated/api/console/agents/zod.gen.ts b/packages/contracts/generated/api/console/agents/zod.gen.ts index 2c6262c7c4..b777fd35b9 100644 --- a/packages/contracts/generated/api/console/agents/zod.gen.ts +++ b/packages/contracts/generated/api/console/agents/zod.gen.ts @@ -212,45 +212,33 @@ export const zAgentTextToSpeechFeatureConfig = z.object({ voice: z.string().nullish(), }) -/** - * AgentSecretRefConfig - */ -export const zAgentSecretRefConfig = z.object({ - id: z.string().max(255).nullish(), - name: z.string().max(255).nullish(), - permission: z.record(z.string(), z.unknown()).optional(), - permission_status: z.string().max(64).nullish(), - provider: z.string().max(255).nullish(), - type: z.string().max(64).nullish(), -}) - /** * AgentEnvVariableConfig */ export const zAgentEnvVariableConfig = z.object({ + default: z.unknown().optional(), + env_name: z.string().max(255).nullish(), + key: z.string().max(255).nullish(), name: z.string().max(255).nullish(), required: z.boolean().optional().default(false), type: z.string().max(64).nullish(), value: z.unknown().optional(), -}) - -/** - * AgentSoulEnvConfig - */ -export const zAgentSoulEnvConfig = z.object({ - secret_refs: z.array(zAgentSecretRefConfig).optional(), - variables: z.array(zAgentEnvVariableConfig).optional(), + variable: z.string().max(255).nullish(), }) /** * AgentHumanContactConfig */ export const zAgentHumanContactConfig = z.object({ + channel: z.string().max(64).nullish(), contact_id: z.string().max(255).nullish(), + contact_method: z.string().max(64).nullish(), email: z.string().max(255).nullish(), human_id: z.string().max(255).nullish(), id: z.string().max(255).nullish(), + method: z.string().max(64).nullish(), name: z.string().max(255).nullish(), + tenant_id: z.string().max(255).nullish(), }) /** @@ -337,6 +325,7 @@ export const zAgentSoulModelCredentialRef = z.object({ * AgentSandboxProviderConfig */ export const zAgentSandboxProviderConfig = z.object({ + cpu: z.int().gte(1).nullish(), env: z.array(zAgentEnvVariableConfig).optional(), image: z.string().nullish(), working_dir: z.string().nullish(), @@ -354,10 +343,15 @@ export const zAgentSoulSandboxConfig = z.object({ * AgentFileRefConfig */ export const zAgentFileRefConfig = z.object({ + file_id: z.string().max(255).nullish(), id: z.string().max(255).nullish(), name: z.string().max(255).nullish(), + reference: z.string().max(255).nullish(), + remote_url: z.string().nullish(), + tenant_id: z.string().max(255).nullish(), transfer_method: z.string().max(64).nullish(), type: z.string().max(64).nullish(), + upload_file_id: z.string().max(255).nullish(), url: z.string().nullish(), }) @@ -380,6 +374,41 @@ export const zAgentSoulSkillsFilesConfig = z.object({ skills: z.array(zAgentSkillRefConfig).optional(), }) +/** + * AgentPermissionConfig + */ +export const zAgentPermissionConfig = z.object({ + allowed: z.boolean().nullish(), + state: z.string().max(64).nullish(), + status: z.string().max(64).nullish(), +}) + +/** + * AgentSecretRefConfig + */ +export const zAgentSecretRefConfig = z.object({ + credential_id: z.string().max(255).nullish(), + env_name: z.string().max(255).nullish(), + id: z.string().max(255).nullish(), + key: z.string().max(255).nullish(), + name: z.string().max(255).nullish(), + permission: zAgentPermissionConfig.optional(), + permission_status: z.string().max(64).nullish(), + provider: z.string().max(255).nullish(), + provider_credential_id: z.string().max(255).nullish(), + ref: z.string().max(255).nullish(), + type: z.string().max(64).nullish(), + variable: z.string().max(255).nullish(), +}) + +/** + * AgentSoulEnvConfig + */ +export const zAgentSoulEnvConfig = z.object({ + secret_refs: z.array(zAgentSecretRefConfig).optional(), + variables: z.array(zAgentEnvVariableConfig).optional(), +}) + /** * AgentModelResponseFormatConfig */ @@ -453,17 +482,28 @@ export const zAgentCliToolRiskLevel = z.enum(['dangerous', 'safe', 'unknown']) * AgentCliToolConfig */ export const zAgentCliToolConfig = z.object({ + approved: z.boolean().optional().default(false), authorization_status: zAgentCliToolAuthorizationStatus.optional(), command: z.string().nullish(), dangerous: z.boolean().optional().default(false), + dangerous_accepted: z.boolean().optional().default(false), dangerous_acknowledged: z.boolean().optional().default(false), + dangerous_command: z.boolean().optional().default(false), description: z.string().nullish(), enabled: z.boolean().optional().default(true), + install: z.string().nullish(), + install_command: z.string().nullish(), + install_commands: z.array(z.string()).optional(), invoke_metadata: z.record(z.string(), z.unknown()).optional(), + label: z.string().max(255).nullish(), name: z.string().max(255).nullish(), - permission: z.record(z.string(), z.unknown()).optional(), + permission: zAgentPermissionConfig.optional(), pre_authorized: z.boolean().nullish(), + requires_confirmation: z.boolean().optional().default(false), + risk_accepted: z.boolean().optional().default(false), risk_level: zAgentCliToolRiskLevel.optional(), + setup_command: z.string().nullish(), + tool_name: z.string().max(255).nullish(), }) /** diff --git a/packages/contracts/generated/api/console/apps/orpc.gen.ts b/packages/contracts/generated/api/console/apps/orpc.gen.ts index 80ad462299..2ce5e6efac 100644 --- a/packages/contracts/generated/api/console/apps/orpc.gen.ts +++ b/packages/contracts/generated/api/console/apps/orpc.gen.ts @@ -793,16 +793,8 @@ export const advancedChat = { workflows: workflows2, } -/** - * Generated contract types may be inaccurate because backend OpenAPI annotations are incomplete. Do not migrate callers until the generated contract is accurate. - * - * @deprecated - */ export const get4 = oc .route({ - deprecated: true, - description: - 'Generated contract types may be inaccurate because backend OpenAPI annotations are incomplete. Do not migrate callers until the generated contract is accurate.', inputStructure: 'detailed', method: 'GET', operationId: 'getAppsByAppIdAgentComposerCandidates', @@ -816,16 +808,8 @@ export const candidates = { get: get4, } -/** - * Generated contract types may be inaccurate because backend OpenAPI annotations are incomplete. Do not migrate callers until the generated contract is accurate. - * - * @deprecated - */ export const post9 = oc .route({ - deprecated: true, - description: - 'Generated contract types may be inaccurate because backend OpenAPI annotations are incomplete. Do not migrate callers until the generated contract is accurate.', inputStructure: 'detailed', method: 'POST', operationId: 'postAppsByAppIdAgentComposerValidate', @@ -844,16 +828,8 @@ export const validate = { post: post9, } -/** - * Generated contract types may be inaccurate because backend OpenAPI annotations are incomplete. Do not migrate callers until the generated contract is accurate. - * - * @deprecated - */ export const get5 = oc .route({ - deprecated: true, - description: - 'Generated contract types may be inaccurate because backend OpenAPI annotations are incomplete. Do not migrate callers until the generated contract is accurate.', inputStructure: 'detailed', method: 'GET', operationId: 'getAppsByAppIdAgentComposer', @@ -863,16 +839,8 @@ export const get5 = oc .input(z.object({ params: zGetAppsByAppIdAgentComposerPath })) .output(zGetAppsByAppIdAgentComposerResponse) -/** - * Generated contract types may be inaccurate because backend OpenAPI annotations are incomplete. Do not migrate callers until the generated contract is accurate. - * - * @deprecated - */ export const put = oc .route({ - deprecated: true, - description: - 'Generated contract types may be inaccurate because backend OpenAPI annotations are incomplete. Do not migrate callers until the generated contract is accurate.', inputStructure: 'detailed', method: 'PUT', operationId: 'putAppsByAppIdAgentComposer', @@ -3787,16 +3755,8 @@ export const loop2 = { nodes: nodes6, } -/** - * Generated contract types may be inaccurate because backend OpenAPI annotations are incomplete. Do not migrate callers until the generated contract is accurate. - * - * @deprecated - */ export const get62 = oc .route({ - deprecated: true, - description: - 'Generated contract types may be inaccurate because backend OpenAPI annotations are incomplete. Do not migrate callers until the generated contract is accurate.', inputStructure: 'detailed', method: 'GET', operationId: 'getAppsByAppIdWorkflowsDraftNodesByNodeIdAgentComposerCandidates', @@ -3812,16 +3772,8 @@ export const candidates2 = { get: get62, } -/** - * Generated contract types may be inaccurate because backend OpenAPI annotations are incomplete. Do not migrate callers until the generated contract is accurate. - * - * @deprecated - */ export const post50 = oc .route({ - deprecated: true, - description: - 'Generated contract types may be inaccurate because backend OpenAPI annotations are incomplete. Do not migrate callers until the generated contract is accurate.', inputStructure: 'detailed', method: 'POST', operationId: 'postAppsByAppIdWorkflowsDraftNodesByNodeIdAgentComposerImpact', @@ -3840,16 +3792,8 @@ export const impact = { post: post50, } -/** - * Generated contract types may be inaccurate because backend OpenAPI annotations are incomplete. Do not migrate callers until the generated contract is accurate. - * - * @deprecated - */ export const post51 = oc .route({ - deprecated: true, - description: - 'Generated contract types may be inaccurate because backend OpenAPI annotations are incomplete. Do not migrate callers until the generated contract is accurate.', inputStructure: 'detailed', method: 'POST', operationId: 'postAppsByAppIdWorkflowsDraftNodesByNodeIdAgentComposerSaveToRoster', @@ -3868,16 +3812,8 @@ export const saveToRoster = { post: post51, } -/** - * Generated contract types may be inaccurate because backend OpenAPI annotations are incomplete. Do not migrate callers until the generated contract is accurate. - * - * @deprecated - */ export const post52 = oc .route({ - deprecated: true, - description: - 'Generated contract types may be inaccurate because backend OpenAPI annotations are incomplete. Do not migrate callers until the generated contract is accurate.', inputStructure: 'detailed', method: 'POST', operationId: 'postAppsByAppIdWorkflowsDraftNodesByNodeIdAgentComposerValidate', @@ -3896,16 +3832,8 @@ export const validate2 = { post: post52, } -/** - * Generated contract types may be inaccurate because backend OpenAPI annotations are incomplete. Do not migrate callers until the generated contract is accurate. - * - * @deprecated - */ export const get63 = oc .route({ - deprecated: true, - description: - 'Generated contract types may be inaccurate because backend OpenAPI annotations are incomplete. Do not migrate callers until the generated contract is accurate.', inputStructure: 'detailed', method: 'GET', operationId: 'getAppsByAppIdWorkflowsDraftNodesByNodeIdAgentComposer', @@ -3915,16 +3843,8 @@ export const get63 = oc .input(z.object({ params: zGetAppsByAppIdWorkflowsDraftNodesByNodeIdAgentComposerPath })) .output(zGetAppsByAppIdWorkflowsDraftNodesByNodeIdAgentComposerResponse) -/** - * Generated contract types may be inaccurate because backend OpenAPI annotations are incomplete. Do not migrate callers until the generated contract is accurate. - * - * @deprecated - */ export const put5 = oc .route({ - deprecated: true, - description: - 'Generated contract types may be inaccurate because backend OpenAPI annotations are incomplete. Do not migrate callers until the generated contract is accurate.', inputStructure: 'detailed', method: 'PUT', operationId: 'putAppsByAppIdWorkflowsDraftNodesByNodeIdAgentComposer', @@ -4146,16 +4066,10 @@ export const events = { /** * Full value for one declared output, including signed download URL for files. - * - * Generated contract types may be inaccurate because backend OpenAPI annotations are incomplete. Do not migrate callers until the generated contract is accurate. - * - * @deprecated */ export const get67 = oc .route({ - deprecated: true, - description: - 'Full value for one declared output, including signed download URL for files.\n\nGenerated contract types may be inaccurate because backend OpenAPI annotations are incomplete. Do not migrate callers until the generated contract is accurate.', + description: 'Full value for one declared output, including signed download URL for files.', inputStructure: 'detailed', method: 'GET', operationId: 'getAppsByAppIdWorkflowsDraftRunsByRunIdNodeOutputsByNodeIdByOutputNamePreview', @@ -4179,16 +4093,10 @@ export const byOutputName = { /** * One node's declared outputs for a draft workflow run. - * - * Generated contract types may be inaccurate because backend OpenAPI annotations are incomplete. Do not migrate callers until the generated contract is accurate. - * - * @deprecated */ export const get68 = oc .route({ - deprecated: true, - description: - 'One node\'s declared outputs for a draft workflow run.\n\nGenerated contract types may be inaccurate because backend OpenAPI annotations are incomplete. Do not migrate callers until the generated contract is accurate.', + description: 'One node\'s declared outputs for a draft workflow run.', inputStructure: 'detailed', method: 'GET', operationId: 'getAppsByAppIdWorkflowsDraftRunsByRunIdNodeOutputsByNodeId', @@ -4205,16 +4113,10 @@ export const byNodeId9 = { /** * Snapshot of every node's declared outputs for a draft workflow run. - * - * Generated contract types may be inaccurate because backend OpenAPI annotations are incomplete. Do not migrate callers until the generated contract is accurate. - * - * @deprecated */ export const get69 = oc .route({ - deprecated: true, - description: - 'Snapshot of every node\'s declared outputs for a draft workflow run.\n\nGenerated contract types may be inaccurate because backend OpenAPI annotations are incomplete. Do not migrate callers until the generated contract is accurate.', + description: 'Snapshot of every node\'s declared outputs for a draft workflow run.', inputStructure: 'detailed', method: 'GET', operationId: 'getAppsByAppIdWorkflowsDraftRunsByRunIdNodeOutputs', @@ -4633,16 +4535,10 @@ export const events2 = { /** * Full value for one declared output of a published run. - * - * Generated contract types may be inaccurate because backend OpenAPI annotations are incomplete. Do not migrate callers until the generated contract is accurate. - * - * @deprecated */ export const get76 = oc .route({ - deprecated: true, - description: - 'Full value for one declared output of a published run.\n\nGenerated contract types may be inaccurate because backend OpenAPI annotations are incomplete. Do not migrate callers until the generated contract is accurate.', + description: 'Full value for one declared output of a published run.', inputStructure: 'detailed', method: 'GET', operationId: @@ -4670,16 +4566,10 @@ export const byOutputName2 = { /** * One node's declared outputs for a published workflow run. - * - * Generated contract types may be inaccurate because backend OpenAPI annotations are incomplete. Do not migrate callers until the generated contract is accurate. - * - * @deprecated */ export const get77 = oc .route({ - deprecated: true, - description: - 'One node\'s declared outputs for a published workflow run.\n\nGenerated contract types may be inaccurate because backend OpenAPI annotations are incomplete. Do not migrate callers until the generated contract is accurate.', + description: 'One node\'s declared outputs for a published workflow run.', inputStructure: 'detailed', method: 'GET', operationId: 'getAppsByAppIdWorkflowsPublishedRunsByRunIdNodeOutputsByNodeId', @@ -4696,16 +4586,10 @@ export const byNodeId10 = { /** * Snapshot of every node's declared outputs for a published workflow run. - * - * Generated contract types may be inaccurate because backend OpenAPI annotations are incomplete. Do not migrate callers until the generated contract is accurate. - * - * @deprecated */ export const get78 = oc .route({ - deprecated: true, - description: - 'Snapshot of every node\'s declared outputs for a published workflow run.\n\nGenerated contract types may be inaccurate because backend OpenAPI annotations are incomplete. Do not migrate callers until the generated contract is accurate.', + description: 'Snapshot of every node\'s declared outputs for a published workflow run.', inputStructure: 'detailed', method: 'GET', operationId: 'getAppsByAppIdWorkflowsPublishedRunsByRunIdNodeOutputs', diff --git a/packages/contracts/generated/api/console/apps/types.gen.ts b/packages/contracts/generated/api/console/apps/types.gen.ts index 7cc5a0bd5c..e18508defe 100644 --- a/packages/contracts/generated/api/console/apps/types.gen.ts +++ b/packages/contracts/generated/api/console/apps/types.gen.ts @@ -853,6 +853,30 @@ export type DraftWorkflowRunPayload = { start_node_id: string } +export type WorkflowRunSnapshotView = { + node_outputs?: Array + workflow_run_id: string + workflow_run_status: WorkflowExecutionStatus +} + +export type NodeOutputsView = { + node_completed_at?: string | null + node_display_name: string + node_id: string + node_kind: string + node_started_at?: string | null + node_status: NodeStatus + outputs?: Array +} + +export type OutputPreviewView = { + node_id: string + output_name: string + status: NodeOutputStatus + type?: DeclaredOutputType + value?: unknown +} + export type DraftWorkflowTriggerRunRequest = { node_id: string } @@ -1479,6 +1503,38 @@ export type AgentComposerImpactBindingResponse = { workflow_id: string } +export type WorkflowExecutionStatus + = | 'failed' + | 'partial-succeeded' + | 'paused' + | 'running' + | 'scheduled' + | 'stopped' + | 'succeeded' + +export type NodeStatus = 'failed' | 'idle' | 'ready' | 'running' + +export type NodeOutputView = { + name: string + output_check?: CheckResultView + retried?: number + status: NodeOutputStatus + type?: DeclaredOutputType + type_check?: CheckResultView + value_preview?: unknown +} + +export type NodeOutputStatus + = | 'failed' + | 'not_produced' + | 'output_check_failed' + | 'pending' + | 'ready' + | 'running' + | 'type_check_failed' + +export type DeclaredOutputType = 'array' | 'boolean' | 'file' | 'number' | 'object' | 'string' + export type WorkflowDraftVariableWithoutValue = { description?: string edited?: boolean @@ -1599,17 +1655,23 @@ export type AgentSoulToolsConfig = { } export type AgentHumanContactConfig = { + channel?: string | null contact_id?: string | null + contact_method?: string | null email?: string | null human_id?: string | null id?: string | null + method?: string | null name?: string | null + tenant_id?: string | null [key: string]: unknown } export type WorkflowNodeJobMetadata = { + agent_soul?: { + [key: string]: unknown + } | null file_refs?: Array | null - [key: string]: unknown } export type WorkflowNodeJobMode = 'let_agent_figure_it_out' | 'tell_agent_what_to_do' @@ -1626,24 +1688,31 @@ export type WorkflowPreviousNodeOutputRef = { [key: string]: unknown } -export type DeclaredOutputType = 'array' | 'boolean' | 'file' | 'number' | 'object' | 'string' - export type AgentCliToolConfig = { + approved?: boolean authorization_status?: AgentCliToolAuthorizationStatus command?: string | null dangerous?: boolean + dangerous_accepted?: boolean dangerous_acknowledged?: boolean + dangerous_command?: boolean description?: string | null enabled?: boolean + install?: string | null + install_command?: string | null + install_commands?: Array invoke_metadata?: { [key: string]: unknown } + label?: string | null name?: string | null - permission?: { - [key: string]: unknown - } + permission?: AgentPermissionConfig pre_authorized?: boolean | null + requires_confirmation?: boolean + risk_accepted?: boolean risk_level?: AgentCliToolRiskLevel + setup_command?: string | null + tool_name?: string | null [key: string]: unknown } @@ -1776,23 +1845,36 @@ export type DeclaredOutputFileConfig = { mime_types?: Array } +export type CheckResultView = { + passed: boolean + reason?: string | null +} + export type AgentSecretRefConfig = { + credential_id?: string | null + env_name?: string | null id?: string | null + key?: string | null name?: string | null - permission?: { - [key: string]: unknown - } + permission?: AgentPermissionConfig permission_status?: string | null provider?: string | null + provider_credential_id?: string | null + ref?: string | null type?: string | null + variable?: string | null [key: string]: unknown } export type AgentEnvVariableConfig = { + default?: unknown + env_name?: string | null + key?: string | null name?: string | null required?: boolean type?: string | null value?: unknown + variable?: string | null [key: string]: unknown } @@ -1835,10 +1917,10 @@ export type AgentSoulModelSettings = { stop?: Array | null temperature?: number | null top_p?: number | null - [key: string]: unknown } export type AgentSandboxProviderConfig = { + cpu?: number | null env?: Array image?: string | null working_dir?: string | null @@ -1846,10 +1928,15 @@ export type AgentSandboxProviderConfig = { } export type AgentFileRefConfig = { + file_id?: string | null id?: string | null name?: string | null + reference?: string | null + remote_url?: string | null + tenant_id?: string | null transfer_method?: string | null type?: string | null + upload_file_id?: string | null url?: string | null [key: string]: unknown } @@ -1880,6 +1967,12 @@ export type AgentCliToolAuthorizationStatus | 'pre_authorized' | 'unauthorized' +export type AgentPermissionConfig = { + allowed?: boolean | null + state?: string | null + status?: string | null +} + export type AgentCliToolRiskLevel = 'dangerous' | 'safe' | 'unknown' export type AgentModerationIoConfig = { @@ -5355,9 +5448,7 @@ export type GetAppsByAppIdWorkflowsDraftRunsByRunIdNodeOutputsError = GetAppsByAppIdWorkflowsDraftRunsByRunIdNodeOutputsErrors[keyof GetAppsByAppIdWorkflowsDraftRunsByRunIdNodeOutputsErrors] export type GetAppsByAppIdWorkflowsDraftRunsByRunIdNodeOutputsResponses = { - 200: { - [key: string]: unknown - } + 200: WorkflowRunSnapshotView } export type GetAppsByAppIdWorkflowsDraftRunsByRunIdNodeOutputsResponse @@ -5412,9 +5503,7 @@ export type GetAppsByAppIdWorkflowsDraftRunsByRunIdNodeOutputsByNodeIdError = GetAppsByAppIdWorkflowsDraftRunsByRunIdNodeOutputsByNodeIdErrors[keyof GetAppsByAppIdWorkflowsDraftRunsByRunIdNodeOutputsByNodeIdErrors] export type GetAppsByAppIdWorkflowsDraftRunsByRunIdNodeOutputsByNodeIdResponses = { - 200: { - [key: string]: unknown - } + 200: NodeOutputsView } export type GetAppsByAppIdWorkflowsDraftRunsByRunIdNodeOutputsByNodeIdResponse @@ -5443,9 +5532,7 @@ export type GetAppsByAppIdWorkflowsDraftRunsByRunIdNodeOutputsByNodeIdByOutputNa export type GetAppsByAppIdWorkflowsDraftRunsByRunIdNodeOutputsByNodeIdByOutputNamePreviewResponses = { - 200: { - [key: string]: unknown - } + 200: OutputPreviewView } export type GetAppsByAppIdWorkflowsDraftRunsByRunIdNodeOutputsByNodeIdByOutputNamePreviewResponse @@ -5727,9 +5814,7 @@ export type GetAppsByAppIdWorkflowsPublishedRunsByRunIdNodeOutputsError = GetAppsByAppIdWorkflowsPublishedRunsByRunIdNodeOutputsErrors[keyof GetAppsByAppIdWorkflowsPublishedRunsByRunIdNodeOutputsErrors] export type GetAppsByAppIdWorkflowsPublishedRunsByRunIdNodeOutputsResponses = { - 200: { - [key: string]: unknown - } + 200: WorkflowRunSnapshotView } export type GetAppsByAppIdWorkflowsPublishedRunsByRunIdNodeOutputsResponse @@ -5784,9 +5869,7 @@ export type GetAppsByAppIdWorkflowsPublishedRunsByRunIdNodeOutputsByNodeIdError = GetAppsByAppIdWorkflowsPublishedRunsByRunIdNodeOutputsByNodeIdErrors[keyof GetAppsByAppIdWorkflowsPublishedRunsByRunIdNodeOutputsByNodeIdErrors] export type GetAppsByAppIdWorkflowsPublishedRunsByRunIdNodeOutputsByNodeIdResponses = { - 200: { - [key: string]: unknown - } + 200: NodeOutputsView } export type GetAppsByAppIdWorkflowsPublishedRunsByRunIdNodeOutputsByNodeIdResponse @@ -5817,9 +5900,7 @@ export type GetAppsByAppIdWorkflowsPublishedRunsByRunIdNodeOutputsByNodeIdByOutp export type GetAppsByAppIdWorkflowsPublishedRunsByRunIdNodeOutputsByNodeIdByOutputNamePreviewResponses = { - 200: { - [key: string]: unknown - } + 200: OutputPreviewView } export type GetAppsByAppIdWorkflowsPublishedRunsByRunIdNodeOutputsByNodeIdByOutputNamePreviewResponse diff --git a/packages/contracts/generated/api/console/apps/zod.gen.ts b/packages/contracts/generated/api/console/apps/zod.gen.ts index 46f37b1b8e..b46ea93224 100644 --- a/packages/contracts/generated/api/console/apps/zod.gen.ts +++ b/packages/contracts/generated/api/console/apps/zod.gen.ts @@ -1356,6 +1356,64 @@ export const zAgentComposerImpactResponse = z.object({ workflow_node_count: z.int(), }) +/** + * WorkflowExecutionStatus + */ +export const zWorkflowExecutionStatus = z.enum([ + 'failed', + 'partial-succeeded', + 'paused', + 'running', + 'scheduled', + 'stopped', + 'succeeded', +]) + +/** + * NodeStatus + * + * Coarse node-level status used by Inspector to pick a banner. + */ +export const zNodeStatus = z.enum(['failed', 'idle', 'ready', 'running']) + +/** + * NodeOutputStatus + * + * Lifecycle status of a single declared output within a run. + */ +export const zNodeOutputStatus = z.enum([ + 'failed', + 'not_produced', + 'output_check_failed', + 'pending', + 'ready', + 'running', + 'type_check_failed', +]) + +/** + * DeclaredOutputType + */ +export const zDeclaredOutputType = z.enum([ + 'array', + 'boolean', + 'file', + 'number', + 'object', + 'string', +]) + +/** + * OutputPreviewView + */ +export const zOutputPreviewView = z.object({ + node_id: z.string(), + output_name: z.string(), + status: zNodeOutputStatus, + type: zDeclaredOutputType.optional(), + value: z.unknown().optional(), +}) + export const zWorkflowDraftVariableWithoutValue = z.object({ description: z.string().optional(), edited: z.boolean().optional(), @@ -1644,11 +1702,15 @@ export const zAgentSoulPromptConfig = z.object({ * AgentHumanContactConfig */ export const zAgentHumanContactConfig = z.object({ + channel: z.string().max(64).nullish(), contact_id: z.string().max(255).nullish(), + contact_method: z.string().max(64).nullish(), email: z.string().max(255).nullish(), human_id: z.string().max(255).nullish(), id: z.string().max(255).nullish(), + method: z.string().max(64).nullish(), name: z.string().max(255).nullish(), + tenant_id: z.string().max(255).nullish(), }) /** @@ -1670,18 +1732,6 @@ export const zWorkflowPreviousNodeOutputRef = z.object({ variable_selector: z.array(z.unknown()).nullish(), }) -/** - * DeclaredOutputType - */ -export const zDeclaredOutputType = z.enum([ - 'array', - 'boolean', - 'file', - 'number', - 'object', - 'string', -]) - /** * AgentComposerNodeJobCandidatesResponse */ @@ -1943,33 +1993,62 @@ export const zDeclaredOutputFileConfig = z.object({ }) /** - * AgentSecretRefConfig + * CheckResultView + * + * ``type_check`` / ``output_check`` per-output summary block. */ -export const zAgentSecretRefConfig = z.object({ - id: z.string().max(255).nullish(), - name: z.string().max(255).nullish(), - permission: z.record(z.string(), z.unknown()).optional(), - permission_status: z.string().max(64).nullish(), - provider: z.string().max(255).nullish(), - type: z.string().max(64).nullish(), +export const zCheckResultView = z.object({ + passed: z.boolean(), + reason: z.string().nullish(), +}) + +/** + * NodeOutputView + */ +export const zNodeOutputView = z.object({ + name: z.string(), + output_check: zCheckResultView.optional(), + retried: z.int().optional().default(0), + status: zNodeOutputStatus, + type: zDeclaredOutputType.optional(), + type_check: zCheckResultView.optional(), + value_preview: z.unknown().optional(), +}) + +/** + * NodeOutputsView + */ +export const zNodeOutputsView = z.object({ + node_completed_at: z.iso.datetime().nullish(), + node_display_name: z.string(), + node_id: z.string(), + node_kind: z.string(), + node_started_at: z.iso.datetime().nullish(), + node_status: zNodeStatus, + outputs: z.array(zNodeOutputView).optional(), +}) + +/** + * WorkflowRunSnapshotView + */ +export const zWorkflowRunSnapshotView = z.object({ + node_outputs: z.array(zNodeOutputsView).optional(), + workflow_run_id: z.string(), + workflow_run_status: zWorkflowExecutionStatus, }) /** * AgentEnvVariableConfig */ export const zAgentEnvVariableConfig = z.object({ + default: z.unknown().optional(), + env_name: z.string().max(255).nullish(), + key: z.string().max(255).nullish(), name: z.string().max(255).nullish(), required: z.boolean().optional().default(false), type: z.string().max(64).nullish(), value: z.unknown().optional(), -}) - -/** - * AgentSoulEnvConfig - */ -export const zAgentSoulEnvConfig = z.object({ - secret_refs: z.array(zAgentSecretRefConfig).optional(), - variables: z.array(zAgentEnvVariableConfig).optional(), + variable: z.string().max(255).nullish(), }) /** @@ -2047,6 +2126,7 @@ export const zAgentSoulModelCredentialRef = z.object({ * AgentSandboxProviderConfig */ export const zAgentSandboxProviderConfig = z.object({ + cpu: z.int().gte(1).nullish(), env: z.array(zAgentEnvVariableConfig).optional(), image: z.string().nullish(), working_dir: z.string().nullish(), @@ -2064,10 +2144,15 @@ export const zAgentSoulSandboxConfig = z.object({ * AgentFileRefConfig */ export const zAgentFileRefConfig = z.object({ + file_id: z.string().max(255).nullish(), id: z.string().max(255).nullish(), name: z.string().max(255).nullish(), + reference: z.string().max(255).nullish(), + remote_url: z.string().nullish(), + tenant_id: z.string().max(255).nullish(), transfer_method: z.string().max(64).nullish(), type: z.string().max(64).nullish(), + upload_file_id: z.string().max(255).nullish(), url: z.string().nullish(), }) @@ -2083,6 +2168,7 @@ export const zAgentSoulSkillsFilesConfig = z.object({ * WorkflowNodeJobMetadata */ export const zWorkflowNodeJobMetadata = z.object({ + agent_soul: z.record(z.string(), z.unknown()).nullish(), file_refs: z.array(zAgentFileRefConfig).nullish(), }) @@ -2106,6 +2192,41 @@ export const zAgentCliToolAuthorizationStatus = z.enum([ 'unauthorized', ]) +/** + * AgentPermissionConfig + */ +export const zAgentPermissionConfig = z.object({ + allowed: z.boolean().nullish(), + state: z.string().max(64).nullish(), + status: z.string().max(64).nullish(), +}) + +/** + * AgentSecretRefConfig + */ +export const zAgentSecretRefConfig = z.object({ + credential_id: z.string().max(255).nullish(), + env_name: z.string().max(255).nullish(), + id: z.string().max(255).nullish(), + key: z.string().max(255).nullish(), + name: z.string().max(255).nullish(), + permission: zAgentPermissionConfig.optional(), + permission_status: z.string().max(64).nullish(), + provider: z.string().max(255).nullish(), + provider_credential_id: z.string().max(255).nullish(), + ref: z.string().max(255).nullish(), + type: z.string().max(64).nullish(), + variable: z.string().max(255).nullish(), +}) + +/** + * AgentSoulEnvConfig + */ +export const zAgentSoulEnvConfig = z.object({ + secret_refs: z.array(zAgentSecretRefConfig).optional(), + variables: z.array(zAgentEnvVariableConfig).optional(), +}) + /** * AgentCliToolRiskLevel * @@ -2117,17 +2238,28 @@ export const zAgentCliToolRiskLevel = z.enum(['dangerous', 'safe', 'unknown']) * AgentCliToolConfig */ export const zAgentCliToolConfig = z.object({ + approved: z.boolean().optional().default(false), authorization_status: zAgentCliToolAuthorizationStatus.optional(), command: z.string().nullish(), dangerous: z.boolean().optional().default(false), + dangerous_accepted: z.boolean().optional().default(false), dangerous_acknowledged: z.boolean().optional().default(false), + dangerous_command: z.boolean().optional().default(false), description: z.string().nullish(), enabled: z.boolean().optional().default(true), + install: z.string().nullish(), + install_command: z.string().nullish(), + install_commands: z.array(z.string()).optional(), invoke_metadata: z.record(z.string(), z.unknown()).optional(), + label: z.string().max(255).nullish(), name: z.string().max(255).nullish(), - permission: z.record(z.string(), z.unknown()).optional(), + permission: zAgentPermissionConfig.optional(), pre_authorized: z.boolean().nullish(), + requires_confirmation: z.boolean().optional().default(false), + risk_accepted: z.boolean().optional().default(false), risk_level: zAgentCliToolRiskLevel.optional(), + setup_command: z.string().nullish(), + tool_name: z.string().max(255).nullish(), }) /** @@ -4515,12 +4647,9 @@ export const zGetAppsByAppIdWorkflowsDraftRunsByRunIdNodeOutputsPath = z.object( }) /** - * Success + * Workflow run node outputs */ -export const zGetAppsByAppIdWorkflowsDraftRunsByRunIdNodeOutputsResponse = z.record( - z.string(), - z.unknown(), -) +export const zGetAppsByAppIdWorkflowsDraftRunsByRunIdNodeOutputsResponse = zWorkflowRunSnapshotView export const zGetAppsByAppIdWorkflowsDraftRunsByRunIdNodeOutputsEventsPath = z.object({ app_id: z.string(), @@ -4528,7 +4657,7 @@ export const zGetAppsByAppIdWorkflowsDraftRunsByRunIdNodeOutputsEventsPath = z.o }) /** - * Success + * Workflow run node output event stream */ export const zGetAppsByAppIdWorkflowsDraftRunsByRunIdNodeOutputsEventsResponse = z.record( z.string(), @@ -4542,12 +4671,9 @@ export const zGetAppsByAppIdWorkflowsDraftRunsByRunIdNodeOutputsByNodeIdPath = z }) /** - * Success + * Workflow run node output detail */ -export const zGetAppsByAppIdWorkflowsDraftRunsByRunIdNodeOutputsByNodeIdResponse = z.record( - z.string(), - z.unknown(), -) +export const zGetAppsByAppIdWorkflowsDraftRunsByRunIdNodeOutputsByNodeIdResponse = zNodeOutputsView export const zGetAppsByAppIdWorkflowsDraftRunsByRunIdNodeOutputsByNodeIdByOutputNamePreviewPath = z.object({ @@ -4558,10 +4684,10 @@ export const zGetAppsByAppIdWorkflowsDraftRunsByRunIdNodeOutputsByNodeIdByOutput }) /** - * Success + * Workflow run node output preview */ export const zGetAppsByAppIdWorkflowsDraftRunsByRunIdNodeOutputsByNodeIdByOutputNamePreviewResponse - = z.record(z.string(), z.unknown()) + = zOutputPreviewView export const zGetAppsByAppIdWorkflowsDraftSystemVariablesPath = z.object({ app_id: z.string(), @@ -4689,12 +4815,10 @@ export const zGetAppsByAppIdWorkflowsPublishedRunsByRunIdNodeOutputsPath = z.obj }) /** - * Success + * Workflow run node outputs */ -export const zGetAppsByAppIdWorkflowsPublishedRunsByRunIdNodeOutputsResponse = z.record( - z.string(), - z.unknown(), -) +export const zGetAppsByAppIdWorkflowsPublishedRunsByRunIdNodeOutputsResponse + = zWorkflowRunSnapshotView export const zGetAppsByAppIdWorkflowsPublishedRunsByRunIdNodeOutputsEventsPath = z.object({ app_id: z.string(), @@ -4702,7 +4826,7 @@ export const zGetAppsByAppIdWorkflowsPublishedRunsByRunIdNodeOutputsEventsPath = }) /** - * Success + * Workflow run node output event stream */ export const zGetAppsByAppIdWorkflowsPublishedRunsByRunIdNodeOutputsEventsResponse = z.record( z.string(), @@ -4716,12 +4840,10 @@ export const zGetAppsByAppIdWorkflowsPublishedRunsByRunIdNodeOutputsByNodeIdPath }) /** - * Success + * Workflow run node output detail */ -export const zGetAppsByAppIdWorkflowsPublishedRunsByRunIdNodeOutputsByNodeIdResponse = z.record( - z.string(), - z.unknown(), -) +export const zGetAppsByAppIdWorkflowsPublishedRunsByRunIdNodeOutputsByNodeIdResponse + = zNodeOutputsView export const zGetAppsByAppIdWorkflowsPublishedRunsByRunIdNodeOutputsByNodeIdByOutputNamePreviewPath = z.object({ @@ -4732,10 +4854,10 @@ export const zGetAppsByAppIdWorkflowsPublishedRunsByRunIdNodeOutputsByNodeIdByOu }) /** - * Success + * Workflow run node output preview */ export const zGetAppsByAppIdWorkflowsPublishedRunsByRunIdNodeOutputsByNodeIdByOutputNamePreviewResponse - = z.record(z.string(), z.unknown()) + = zOutputPreviewView export const zGetAppsByAppIdWorkflowsTriggersWebhookPath = z.object({ app_id: z.string(),