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
219 changes: 198 additions & 21 deletions apps/docs/content/docs/en/tools/linear.mdx

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -491,6 +491,13 @@ export function useWorkflowExecution() {
updateActiveBlocks(data.blockId, false)
setBlockRunStatus(data.blockId, 'error')

executedBlockIds.add(data.blockId)
accumulatedBlockStates.set(data.blockId, {
output: { error: data.error },
executed: true,
executionTime: data.durationMs || 0,
})

accumulatedBlockLogs.push(
createBlockLogEntry(data, { success: false, output: {}, error: data.error })
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -349,7 +349,15 @@ export function PreviewWorkflow({
if (block.type === 'loop' || block.type === 'parallel') {
const isSelected = selectedBlockId === blockId
const dimensions = calculateContainerDimensions(blockId, workflowState.blocks)
const subflowExecutionStatus = getSubflowExecutionStatus(blockId)

// Check for direct error on the subflow block itself (e.g., loop resolution errors)
// before falling back to children-derived status
const directExecution = blockExecutionMap.get(blockId)
const subflowExecutionStatus: ExecutionStatus | undefined =
directExecution?.status === 'error'
? 'error'
: (getSubflowExecutionStatus(blockId) ??
(directExecution ? (directExecution.status as ExecutionStatus) : undefined))

nodeArray.push({
id: blockId,
Expand Down
30 changes: 28 additions & 2 deletions apps/sim/background/webhook-execution.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import { executeWorkflowCore } from '@/lib/workflows/executor/execution-core'
import { PauseResumeManager } from '@/lib/workflows/executor/human-in-the-loop-manager'
import { loadDeployedWorkflowState } from '@/lib/workflows/persistence/utils'
import { getWorkflowById } from '@/lib/workflows/utils'
import { getBlock } from '@/blocks'
import { ExecutionSnapshot } from '@/executor/execution/snapshot'
import type { ExecutionMetadata } from '@/executor/execution/types'
import { hasExecutionResult } from '@/executor/utils/errors'
Expand Down Expand Up @@ -74,8 +75,21 @@ async function processTriggerFileOutputs(
logger.error(`[${context.requestId}] Error processing ${currentPath}:`, error)
processed[key] = val
}
} else if (
outputDef &&
typeof outputDef === 'object' &&
(outputDef.type === 'object' || outputDef.type === 'json') &&
outputDef.properties
) {
// Explicit object schema with properties - recurse into properties
processed[key] = await processTriggerFileOutputs(
val,
outputDef.properties,
context,
currentPath
)
} else if (outputDef && typeof outputDef === 'object' && !outputDef.type) {
// Nested object in schema - recurse with the nested schema
// Nested object in schema (flat pattern) - recurse with the nested schema
processed[key] = await processTriggerFileOutputs(val, outputDef, context, currentPath)
} else {
// Not a file output - keep as is
Expand Down Expand Up @@ -405,11 +419,23 @@ async function executeWebhookJobInternal(
const rawSelectedTriggerId = triggerBlock?.subBlocks?.selectedTriggerId?.value
const rawTriggerId = triggerBlock?.subBlocks?.triggerId?.value

const resolvedTriggerId = [rawSelectedTriggerId, rawTriggerId].find(
let resolvedTriggerId = [rawSelectedTriggerId, rawTriggerId].find(
(candidate): candidate is string =>
typeof candidate === 'string' && isTriggerValid(candidate)
)

if (!resolvedTriggerId) {
const blockConfig = getBlock(triggerBlock.type)
if (blockConfig?.category === 'triggers' && isTriggerValid(triggerBlock.type)) {
resolvedTriggerId = triggerBlock.type
} else if (triggerBlock.triggerMode && blockConfig?.triggers?.enabled) {
const available = blockConfig.triggers?.available?.[0]
if (available && isTriggerValid(available)) {
resolvedTriggerId = available
}
}
}

if (resolvedTriggerId) {
const triggerConfig = getTrigger(resolvedTriggerId)

Expand Down
130 changes: 99 additions & 31 deletions apps/sim/blocks/blocks/linear.ts
Original file line number Diff line number Diff line change
Expand Up @@ -810,7 +810,29 @@ Return ONLY the date string in YYYY-MM-DD format - no explanations, no quotes, n
placeholder: 'Number of items to return (default: 50)',
condition: {
field: 'operation',
value: ['linear_list_favorites'],
value: [
'linear_read_issues',
'linear_search_issues',
'linear_list_comments',
'linear_list_projects',
'linear_list_users',
'linear_list_teams',
'linear_list_labels',
'linear_list_workflow_states',
'linear_list_cycles',
'linear_list_attachments',
'linear_list_issue_relations',
'linear_list_favorites',
'linear_list_project_updates',
'linear_list_notifications',
'linear_list_customer_statuses',
'linear_list_customer_tiers',
'linear_list_customers',
'linear_list_customer_requests',
'linear_list_project_labels',
'linear_list_project_milestones',
'linear_list_project_statuses',
],
},
},
// Pagination - After (for list operations)
Expand All @@ -821,7 +843,29 @@ Return ONLY the date string in YYYY-MM-DD format - no explanations, no quotes, n
placeholder: 'Cursor for pagination',
condition: {
field: 'operation',
value: ['linear_list_favorites'],
value: [
'linear_read_issues',
'linear_search_issues',
'linear_list_comments',
'linear_list_projects',
'linear_list_users',
'linear_list_teams',
'linear_list_labels',
'linear_list_workflow_states',
'linear_list_cycles',
'linear_list_attachments',
'linear_list_issue_relations',
'linear_list_favorites',
'linear_list_project_updates',
'linear_list_notifications',
'linear_list_customers',
'linear_list_customer_requests',
'linear_list_customer_statuses',
'linear_list_customer_tiers',
'linear_list_project_labels',
'linear_list_project_milestones',
'linear_list_project_statuses',
],
},
},
// Project health (for project updates)
Expand Down Expand Up @@ -1053,28 +1097,6 @@ Return ONLY the description text - no explanations.`,
value: ['linear_create_customer_request', 'linear_update_customer_request'],
},
},
// Pagination - first
{
id: 'first',
title: 'Limit',
type: 'short-input',
placeholder: 'Number of items (default: 50)',
condition: {
field: 'operation',
value: ['linear_list_customers', 'linear_list_customer_requests'],
},
},
// Pagination - after
{
id: 'after',
title: 'After Cursor',
type: 'short-input',
placeholder: 'Cursor for pagination',
condition: {
field: 'operation',
value: ['linear_list_customers', 'linear_list_customer_requests'],
},
},
// Customer ID for get/update/delete/merge operations
{
id: 'customerIdTarget',
Expand Down Expand Up @@ -1493,6 +1515,8 @@ Return ONLY the date string in YYYY-MM-DD format - no explanations, no quotes, n
teamId: effectiveTeamId || undefined,
projectId: effectiveProjectId || undefined,
includeArchived: params.includeArchived,
first: params.first ? Number(params.first) : undefined,
after: params.after,
}

case 'linear_get_issue':
Expand Down Expand Up @@ -1558,6 +1582,8 @@ Return ONLY the date string in YYYY-MM-DD format - no explanations, no quotes, n
query: params.query.trim(),
teamId: effectiveTeamId,
includeArchived: params.includeArchived,
first: params.first ? Number(params.first) : undefined,
after: params.after,
}

case 'linear_add_label_to_issue':
Expand Down Expand Up @@ -1607,13 +1633,17 @@ Return ONLY the date string in YYYY-MM-DD format - no explanations, no quotes, n
return {
...baseParams,
issueId: params.issueId.trim(),
first: params.first ? Number(params.first) : undefined,
after: params.after,
}

case 'linear_list_projects':
return {
...baseParams,
teamId: effectiveTeamId,
includeArchived: params.includeArchived,
first: params.first ? Number(params.first) : undefined,
after: params.after,
}

case 'linear_get_project':
Expand Down Expand Up @@ -1665,13 +1695,21 @@ Return ONLY the date string in YYYY-MM-DD format - no explanations, no quotes, n

case 'linear_list_users':
case 'linear_list_teams':
return {
...baseParams,
first: params.first ? Number(params.first) : undefined,
after: params.after,
}

case 'linear_get_viewer':
return baseParams

case 'linear_list_labels':
return {
...baseParams,
teamId: effectiveTeamId,
first: params.first ? Number(params.first) : undefined,
after: params.after,
}

case 'linear_create_label':
Expand Down Expand Up @@ -1709,6 +1747,8 @@ Return ONLY the date string in YYYY-MM-DD format - no explanations, no quotes, n
return {
...baseParams,
teamId: effectiveTeamId,
first: params.first ? Number(params.first) : undefined,
after: params.after,
}

case 'linear_create_workflow_state':
Expand Down Expand Up @@ -1738,6 +1778,8 @@ Return ONLY the date string in YYYY-MM-DD format - no explanations, no quotes, n
return {
...baseParams,
teamId: effectiveTeamId,
first: params.first ? Number(params.first) : undefined,
after: params.after,
}

case 'linear_get_cycle':
Expand Down Expand Up @@ -1801,6 +1843,8 @@ Return ONLY the date string in YYYY-MM-DD format - no explanations, no quotes, n
return {
...baseParams,
issueId: params.issueId.trim(),
first: params.first ? Number(params.first) : undefined,
after: params.after,
}

case 'linear_update_attachment':
Expand Down Expand Up @@ -1840,6 +1884,8 @@ Return ONLY the date string in YYYY-MM-DD format - no explanations, no quotes, n
return {
...baseParams,
issueId: params.issueId.trim(),
first: params.first ? Number(params.first) : undefined,
after: params.after,
}

case 'linear_delete_issue_relation':
Expand Down Expand Up @@ -1886,10 +1932,16 @@ Return ONLY the date string in YYYY-MM-DD format - no explanations, no quotes, n
return {
...baseParams,
projectId: effectiveProjectId,
first: params.first ? Number(params.first) : undefined,
after: params.after,
}

case 'linear_list_notifications':
return baseParams
return {
...baseParams,
first: params.first ? Number(params.first) : undefined,
after: params.after,
}

case 'linear_update_notification':
if (!params.notificationId?.trim()) {
Expand Down Expand Up @@ -2018,9 +2070,9 @@ Return ONLY the date string in YYYY-MM-DD format - no explanations, no quotes, n
return {
...baseParams,
name: params.statusName.trim(),
displayName: params.statusDisplayName?.trim() || params.statusName.trim(),
color: params.statusColor.trim(),
description: params.statusDescription?.trim() || undefined,
displayName: params.statusDisplayName?.trim() || undefined,
}

case 'linear_update_customer_status':
Expand All @@ -2031,9 +2083,9 @@ Return ONLY the date string in YYYY-MM-DD format - no explanations, no quotes, n
...baseParams,
statusId: params.statusId.trim(),
name: params.statusName?.trim() || undefined,
displayName: params.statusDisplayName?.trim() || undefined,
color: params.statusColor?.trim() || undefined,
description: params.statusDescription?.trim() || undefined,
displayName: params.statusDisplayName?.trim() || undefined,
}

case 'linear_delete_customer_status':
Expand All @@ -2046,7 +2098,11 @@ Return ONLY the date string in YYYY-MM-DD format - no explanations, no quotes, n
}

case 'linear_list_customer_statuses':
return baseParams
return {
...baseParams,
first: params.first ? Number(params.first) : undefined,
after: params.after,
}

// Customer Tier Operations
case 'linear_create_customer_tier':
Expand Down Expand Up @@ -2084,7 +2140,11 @@ Return ONLY the date string in YYYY-MM-DD format - no explanations, no quotes, n
}

case 'linear_list_customer_tiers':
return baseParams
return {
...baseParams,
first: params.first ? Number(params.first) : undefined,
after: params.after,
}

// Project Management Operations
case 'linear_delete_project':
Expand Down Expand Up @@ -2135,6 +2195,8 @@ Return ONLY the date string in YYYY-MM-DD format - no explanations, no quotes, n
return {
...baseParams,
projectId: effectiveProjectId || undefined,
first: params.first ? Number(params.first) : undefined,
after: params.after,
}

case 'linear_add_label_to_project':
Expand Down Expand Up @@ -2198,6 +2260,8 @@ Return ONLY the date string in YYYY-MM-DD format - no explanations, no quotes, n
return {
...baseParams,
projectId: params.projectIdForMilestone.trim(),
first: params.first ? Number(params.first) : undefined,
after: params.after,
}

// Project Status Operations
Expand Down Expand Up @@ -2245,7 +2309,11 @@ Return ONLY the date string in YYYY-MM-DD format - no explanations, no quotes, n
}

case 'linear_list_project_statuses':
return baseParams
return {
...baseParams,
first: params.first ? Number(params.first) : undefined,
after: params.after,
}

default:
return baseParams
Expand Down Expand Up @@ -2321,9 +2389,9 @@ Return ONLY the date string in YYYY-MM-DD format - no explanations, no quotes, n
// Customer status and tier inputs
statusId: { type: 'string', description: 'Status identifier' },
statusName: { type: 'string', description: 'Status name' },
statusDisplayName: { type: 'string', description: 'Status display name' },
statusColor: { type: 'string', description: 'Status color in hex format' },
statusDescription: { type: 'string', description: 'Status description' },
statusDisplayName: { type: 'string', description: 'Status display name' },
tierId: { type: 'string', description: 'Tier identifier' },
tierName: { type: 'string', description: 'Tier name' },
tierDisplayName: { type: 'string', description: 'Tier display name' },
Expand Down
1 change: 1 addition & 0 deletions apps/sim/blocks/blocks/workflow.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ export const WorkflowBlock: BlockConfig = {
outputs: {
success: { type: 'boolean', description: 'Execution success status' },
childWorkflowName: { type: 'string', description: 'Child workflow name' },
childWorkflowId: { type: 'string', description: 'Child workflow ID' },
result: { type: 'json', description: 'Workflow execution result' },
error: { type: 'string', description: 'Error message' },
childTraceSpans: {
Expand Down
1 change: 1 addition & 0 deletions apps/sim/blocks/blocks/workflow_input.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ export const WorkflowInputBlock: BlockConfig = {
outputs: {
success: { type: 'boolean', description: 'Execution success status' },
childWorkflowName: { type: 'string', description: 'Child workflow name' },
childWorkflowId: { type: 'string', description: 'Child workflow ID' },
result: { type: 'json', description: 'Workflow execution result' },
error: { type: 'string', description: 'Error message' },
childTraceSpans: {
Expand Down
Loading
Loading