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(),