Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
106 changes: 99 additions & 7 deletions apps/docs/openapi-v2-workflows.json
Original file line number Diff line number Diff line change
Expand Up @@ -549,6 +549,7 @@
"fieldIssues": [],
"unresolvedReferences": [],
"tableFieldIssues": [],
"manualRunIssue": null,
"notes": []
}
}
Expand Down Expand Up @@ -705,8 +706,20 @@
"agent-1": "a3f1c0b2-7a44-4c1d-9d3a-2b8e5f0a1c77"
},
"lint": {
"sources": [],
"sinks": [],
"sources": [
{
"blockId": "start-1",
"blockName": "Start",
"blockType": "start_trigger"
}
],
"sinks": [
{
"blockId": "a3f1c0b2-7a44-4c1d-9d3a-2b8e5f0a1c77",
"blockName": "Triage",
"blockType": "agent"
}
],
"orphanBlocks": [],
"emptyOutgoingPorts": [],
"invalidBranchPorts": [],
Expand All @@ -722,9 +735,12 @@
],
"unresolvedReferences": [],
"tableFieldIssues": [],
"manualRunIssue": null,
"notes": []
},
"warnings": [],
"warnings": [
Comment thread
waleedlatif1 marked this conversation as resolved.
Resolved
"Workflow lint found issues. Fix these before continuing: Blocks missing required fields: \"Triage\" (systemPrompt)"
],
"needsRedeployment": true,
"dryRun": false
}
Expand Down Expand Up @@ -2655,6 +2671,7 @@
"fieldIssues": [],
"unresolvedReferences": [],
"tableFieldIssues": [],
"manualRunIssue": null,
"notes": []
}
}
Expand Down Expand Up @@ -8813,6 +8830,63 @@
},
"description": "Table block `filter` and `order` fields checked against the bound table's live schema that name no column (nor the implicit `id`, `createdAt`, `updatedAt`). Such a run fails inside the block's error edge. A filter holding a `<block.output>` reference, or one that is not JSON, is not checked."
},
"manualRunIssue": {
"anyOf": [
{
"type": "object",
"properties": {
"reason": {
"type": "string",
"enum": ["no-trigger", "multiple-api-triggers", "trigger-not-connected"],
"description": "Why the run is refused."
},
"message": {
"type": "string",
"description": "The error the manual run raises."
},
"blockId": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"description": "Trigger the run would start from, when the problem is that trigger."
},
"blockName": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"description": "Display name of that trigger."
},
"blockType": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"description": "Registered type of that trigger."
}
},
"required": ["reason", "message", "blockId", "blockName", "blockType"],
"additionalProperties": false
},
{
"type": "null"
}
],
"description": "Why a manual run from the editor's Run button would be refused before it starts: no enabled trigger it can start from, more than one API trigger, or a selected trigger with no outgoing connection. `null` when no manual-run issue is reported: the run can begin, only a chat trigger can start the workflow, or the graph is empty (reported in `notes` instead)."
},
"notes": {
"type": "array",
"items": {
Expand All @@ -8831,6 +8905,7 @@
"fieldIssues",
"unresolvedReferences",
"tableFieldIssues",
"manualRunIssue",
"notes"
],
"additionalProperties": false,
Expand Down Expand Up @@ -8897,6 +8972,7 @@
"fieldIssues": [],
"unresolvedReferences": [],
"tableFieldIssues": [],
"manualRunIssue": null,
"notes": []
}
}
Expand Down Expand Up @@ -9461,7 +9537,7 @@
"items": {
"type": "string"
},
"description": "Non-fatal notes about blocks and edges that were normalized or dropped before persistence. Empty when there was nothing to report."
"description": "Non-fatal notes about blocks and edges that were normalized or dropped before persistence and, when `lint` has findings, one summary of them, so the findings are not lost to a caller that reads only `warnings`. Empty when there is nothing to report."
},
"needsRedeployment": {
"type": "boolean",
Expand Down Expand Up @@ -9564,8 +9640,20 @@
"agent-1": "a3f1c0b2-7a44-4c1d-9d3a-2b8e5f0a1c77"
},
"lint": {
"sources": [],
"sinks": [],
"sources": [
{
"blockId": "start-1",
"blockName": "Start",
"blockType": "start_trigger"
}
],
"sinks": [
{
"blockId": "a3f1c0b2-7a44-4c1d-9d3a-2b8e5f0a1c77",
"blockName": "Triage",
"blockType": "agent"
}
],
"orphanBlocks": [],
"emptyOutgoingPorts": [],
"invalidBranchPorts": [],
Expand All @@ -9581,9 +9669,12 @@
],
"unresolvedReferences": [],
"tableFieldIssues": [],
"manualRunIssue": null,
"notes": []
},
"warnings": [],
"warnings": [
"Workflow lint found issues. Fix these before continuing: Blocks missing required fields: \"Triage\" (systemPrompt)"
],
"needsRedeployment": true,
"dryRun": false
}
Expand Down Expand Up @@ -12554,6 +12645,7 @@
"fieldIssues": [],
"unresolvedReferences": [],
"tableFieldIssues": [],
"manualRunIssue": null,
"notes": []
}
}
Expand Down
9 changes: 9 additions & 0 deletions apps/sim/app/api/v2/lib/workflow-lint.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,15 @@ export function presentWorkflowLint(lint: WorkflowLintReport) {
field: issue.field,
tableName: issue.tableName,
})),
manualRunIssue: lint.manualRunIssue
? {
reason: lint.manualRunIssue.reason,
message: lint.manualRunIssue.message,
blockId: lint.manualRunIssue.blockId ?? null,
blockName: lint.manualRunIssue.blockName ?? null,
blockType: lint.manualRunIssue.blockType ?? null,
}
: null,
notes: lint.notes,
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ const unquotedRowJson = {
},
],
tableFieldIssues: [],
manualRunIssue: null,
notes: [],
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ const LINT = {
fieldIssues: [],
unresolvedReferences: [],
tableFieldIssues: [],
manualRunIssue: null,
notes: [],
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ const EMPTY_LINT = {
fieldIssues: [],
unresolvedReferences: [],
tableFieldIssues: [],
manualRunIssue: null,
notes: [],
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,16 +29,13 @@ import type {
StreamToolData,
} from '@/lib/workflows/executor/execution-events'
import { collectInputFormatFiles, isFileFieldType } from '@/lib/workflows/input-format'
import { resolveManualRunEntry } from '@/lib/workflows/triggers/manual-run'
import {
resolveStartCandidates,
StartBlockPath,
TriggerUtils,
} from '@/lib/workflows/triggers/triggers'
import {
extractTriggerMockPayload,
selectBestTrigger,
triggerNeedsMockPayload,
} from '@/lib/workflows/triggers/utils'
import { extractTriggerMockPayload, triggerNeedsMockPayload } from '@/lib/workflows/triggers/utils'
import { useCurrentWorkflow } from '@/app/workspace/[workspaceId]/w/[workflowId]/hooks/use-current-workflow'
import { getRunFromBlockDependencyState } from '@/app/workspace/[workspaceId]/w/[workflowId]/utils/run-from-block'
import {
Expand Down Expand Up @@ -1096,63 +1093,26 @@ export function useWorkflowExecution() {

startBlockId = startBlock.blockId
} else {
const candidates = resolveStartCandidates(enabledStates, {
execution: 'manual',
})

if (candidates.length === 0) {
const error = new WorkflowValidationError(
'Workflow requires at least one trigger block to execute',
'validation',
'validation',
'Workflow Validation'
)
logger.error('No trigger blocks found for manual run', {
const entry = resolveManualRunEntry(enabledStates, workflowEdges)
if (!entry.ok) {
logger.error('Manual run has no valid entry', {
reason: entry.issue.reason,
startBlockId: entry.issue.blockId,
allBlockTypes: Object.values(enabledStates).map((b) => b.type),
})
if (activeWorkflowId) finishOwnedExecution(activeWorkflowId, persistenceExecution)
throw error
}

// Check for multiple API triggers (still not allowed)
const apiCandidates = candidates.filter(
(candidate) => candidate.path === StartBlockPath.SPLIT_API
)
if (apiCandidates.length > 1) {
const error = new WorkflowValidationError(
'Multiple API Trigger blocks found. Keep only one.',
throw new WorkflowValidationError(
entry.issue.message,
'validation',
'validation',
'Workflow Validation'
)
logger.error('Multiple API triggers found')
if (activeWorkflowId) finishOwnedExecution(activeWorkflowId, persistenceExecution)
throw error
}

// Priority: Start Block > Schedules > External Triggers > Legacy
const selectedTriggers = selectBestTrigger(candidates, workflowEdges)

const selectedCandidate = selectedTriggers[0]
const selectedCandidate = entry.candidate
startBlockId = selectedCandidate.blockId
const selectedTrigger = selectedCandidate.block

if (selectedCandidate.path !== StartBlockPath.LEGACY_STARTER) {
const outgoingConnections = workflowEdges.filter((edge) => edge.source === startBlockId)
if (outgoingConnections.length === 0) {
const triggerName = selectedTrigger.name || selectedTrigger.type
const error = new WorkflowValidationError(
`${triggerName} must be connected to other blocks to execute`,
'validation',
'validation',
'Workflow Validation'
)
logger.error('Trigger has no outgoing connections', { triggerName, startBlockId })
if (activeWorkflowId) finishOwnedExecution(activeWorkflowId, persistenceExecution)
throw error
}
}

if (triggerNeedsMockPayload(selectedCandidate)) {
const mockPayload = extractTriggerMockPayload(selectedCandidate)
finalWorkflowInput = mockPayload
Expand Down
22 changes: 19 additions & 3 deletions apps/sim/lib/api/contracts/v2/openapi/workflows.ts
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,7 @@ const EMPTY_LINT_EXAMPLE = {
fieldIssues: [],
unresolvedReferences: [],
tableFieldIssues: [],
manualRunIssue: null,
notes: [],
} as const

Expand Down Expand Up @@ -402,8 +403,20 @@ const declaredRoutes = [
inputValidationErrors: [],
mintedBlockIds: { 'agent-1': 'a3f1c0b2-7a44-4c1d-9d3a-2b8e5f0a1c77' },
lint: {
sources: [],
sinks: [],
sources: [
{
blockId: 'start-1',
blockName: 'Start',
blockType: 'start_trigger',
},
],
sinks: [
{
blockId: 'a3f1c0b2-7a44-4c1d-9d3a-2b8e5f0a1c77',
blockName: 'Triage',
blockType: 'agent',
},
],
orphanBlocks: [],
emptyOutgoingPorts: [],
invalidBranchPorts: [],
Expand All @@ -419,9 +432,12 @@ const declaredRoutes = [
],
unresolvedReferences: [],
tableFieldIssues: [],
manualRunIssue: null,
notes: [],
},
warnings: [],
warnings: [
'Workflow lint found issues. Fix these before continuing: Blocks missing required fields: "Triage" (systemPrompt)',
],
needsRedeployment: true,
dryRun: false,
},
Expand Down
8 changes: 8 additions & 0 deletions apps/sim/lib/api/contracts/v2/workflow-graph.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@ const EMPTY_LINT = {
fieldIssues: [],
unresolvedReferences: [],
tableFieldIssues: [],
manualRunIssue: null,
notes: [],
}

Expand Down Expand Up @@ -174,6 +175,13 @@ const FULL_LINT = {
tableName: 'Leads',
},
],
manualRunIssue: {
reason: 'trigger-not-connected',
message: 'Start must be connected to other blocks to execute',
blockId: 'block-1',
blockName: 'Start',
blockType: 'start_trigger',
},
notes: ['lint note'],
}

Expand Down
Loading
Loading