From e572fd2477f8770e13c626757d52a95bb76c2d07 Mon Sep 17 00:00:00 2001 From: Waleed Latif Date: Mon, 6 Apr 2026 21:13:59 -0700 Subject: [PATCH 01/11] refactor(triggers): consolidate v2 Linear triggers into same files as v1 Move v2 trigger exports from separate _v2.ts files into their corresponding v1 files, matching the block v2 convention where LinearV2Block lives alongside LinearBlock in the same file. --- apps/sim/blocks/registry.ts | 2 - apps/sim/lib/webhooks/providers/linear.ts | 113 ++++----------- apps/sim/triggers/linear/comment_created.ts | 30 +++- .../sim/triggers/linear/comment_created_v2.ts | 30 ---- apps/sim/triggers/linear/comment_updated.ts | 30 +++- .../sim/triggers/linear/comment_updated_v2.ts | 30 ---- .../linear/customer_request_created.ts | 30 +++- .../linear/customer_request_created_v2.ts | 30 ---- .../linear/customer_request_updated.ts | 30 +++- .../linear/customer_request_updated_v2.ts | 30 ---- apps/sim/triggers/linear/cycle_created.ts | 30 +++- apps/sim/triggers/linear/cycle_created_v2.ts | 30 ---- apps/sim/triggers/linear/cycle_updated.ts | 30 +++- apps/sim/triggers/linear/cycle_updated_v2.ts | 30 ---- apps/sim/triggers/linear/index.ts | 54 +++---- apps/sim/triggers/linear/issue_created.ts | 26 ++++ apps/sim/triggers/linear/issue_created_v2.ts | 37 ----- apps/sim/triggers/linear/issue_removed.ts | 30 +++- apps/sim/triggers/linear/issue_removed_v2.ts | 30 ---- apps/sim/triggers/linear/issue_updated.ts | 30 +++- apps/sim/triggers/linear/issue_updated_v2.ts | 30 ---- apps/sim/triggers/linear/label_created.ts | 30 +++- apps/sim/triggers/linear/label_created_v2.ts | 30 ---- apps/sim/triggers/linear/label_updated.ts | 30 +++- apps/sim/triggers/linear/label_updated_v2.ts | 30 ---- apps/sim/triggers/linear/project_created.ts | 30 +++- .../sim/triggers/linear/project_created_v2.ts | 30 ---- .../triggers/linear/project_update_created.ts | 30 +++- .../linear/project_update_created_v2.ts | 30 ---- apps/sim/triggers/linear/project_updated.ts | 30 +++- .../sim/triggers/linear/project_updated_v2.ts | 30 ---- apps/sim/triggers/linear/utils.ts | 61 +------- apps/sim/triggers/linear/webhook.ts | 71 ++++++++- apps/sim/triggers/linear/webhook_v2.ts | 71 --------- apps/sim/triggers/registry.ts | 137 ------------------ 35 files changed, 527 insertions(+), 825 deletions(-) delete mode 100644 apps/sim/triggers/linear/comment_created_v2.ts delete mode 100644 apps/sim/triggers/linear/comment_updated_v2.ts delete mode 100644 apps/sim/triggers/linear/customer_request_created_v2.ts delete mode 100644 apps/sim/triggers/linear/customer_request_updated_v2.ts delete mode 100644 apps/sim/triggers/linear/cycle_created_v2.ts delete mode 100644 apps/sim/triggers/linear/cycle_updated_v2.ts delete mode 100644 apps/sim/triggers/linear/issue_created_v2.ts delete mode 100644 apps/sim/triggers/linear/issue_removed_v2.ts delete mode 100644 apps/sim/triggers/linear/issue_updated_v2.ts delete mode 100644 apps/sim/triggers/linear/label_created_v2.ts delete mode 100644 apps/sim/triggers/linear/label_updated_v2.ts delete mode 100644 apps/sim/triggers/linear/project_created_v2.ts delete mode 100644 apps/sim/triggers/linear/project_update_created_v2.ts delete mode 100644 apps/sim/triggers/linear/project_updated_v2.ts delete mode 100644 apps/sim/triggers/linear/webhook_v2.ts diff --git a/apps/sim/blocks/registry.ts b/apps/sim/blocks/registry.ts index e78578b176b..dd9ea3f72e5 100644 --- a/apps/sim/blocks/registry.ts +++ b/apps/sim/blocks/registry.ts @@ -171,7 +171,6 @@ import { SftpBlock } from '@/blocks/blocks/sftp' import { SharepointBlock } from '@/blocks/blocks/sharepoint' import { ShopifyBlock } from '@/blocks/blocks/shopify' import { SimilarwebBlock } from '@/blocks/blocks/similarweb' -import { SixtyfourBlock } from '@/blocks/blocks/sixtyfour' import { SlackBlock } from '@/blocks/blocks/slack' import { SmtpBlock } from '@/blocks/blocks/smtp' import { SpotifyBlock } from '@/blocks/blocks/spotify' @@ -409,7 +408,6 @@ export const registry: Record = { sharepoint: SharepointBlock, shopify: ShopifyBlock, similarweb: SimilarwebBlock, - sixtyfour: SixtyfourBlock, slack: SlackBlock, smtp: SmtpBlock, spotify: SpotifyBlock, diff --git a/apps/sim/lib/webhooks/providers/linear.ts b/apps/sim/lib/webhooks/providers/linear.ts index 97e9d79a877..255691effb2 100644 --- a/apps/sim/lib/webhooks/providers/linear.ts +++ b/apps/sim/lib/webhooks/providers/linear.ts @@ -1,11 +1,9 @@ import crypto from 'crypto' import { createLogger } from '@sim/logger' -import { NextResponse } from 'next/server' import { safeCompare } from '@/lib/core/security/encryption' import { generateId } from '@/lib/core/utils/uuid' import { getNotificationUrl, getProviderConfig } from '@/lib/webhooks/provider-subscription-utils' import type { - AuthContext, DeleteSubscriptionContext, EventMatchContext, FormatInputContext, @@ -14,6 +12,7 @@ import type { SubscriptionResult, WebhookProviderHandler, } from '@/lib/webhooks/providers/types' +import { createHmacVerifier } from '@/lib/webhooks/providers/utils' const logger = createLogger('WebhookProvider:Linear') @@ -42,73 +41,16 @@ function validateLinearSignature(secret: string, signature: string, body: string } } -const LINEAR_WEBHOOK_TIMESTAMP_SKEW_MS = 5 * 60 * 1000 - export const linearHandler: WebhookProviderHandler = { - async verifyAuth({ - request, - rawBody, - requestId, - providerConfig, - }: AuthContext): Promise { - const secret = providerConfig.webhookSecret as string | undefined - if (!secret) { - return null - } - - const signature = request.headers.get('Linear-Signature') - if (!signature) { - logger.warn(`[${requestId}] Linear webhook missing signature header`) - return new NextResponse('Unauthorized - Missing Linear signature', { status: 401 }) - } - - if (!validateLinearSignature(secret, signature, rawBody)) { - logger.warn(`[${requestId}] Linear signature verification failed`) - return new NextResponse('Unauthorized - Invalid Linear signature', { status: 401 }) - } - - try { - const parsed = JSON.parse(rawBody) as Record - const ts = parsed.webhookTimestamp - if (typeof ts !== 'number' || !Number.isFinite(ts)) { - logger.warn(`[${requestId}] Linear webhookTimestamp missing or invalid`) - return new NextResponse('Unauthorized - Invalid webhook timestamp', { - status: 401, - }) - } - - if (Math.abs(Date.now() - ts) > LINEAR_WEBHOOK_TIMESTAMP_SKEW_MS) { - logger.warn( - `[${requestId}] Linear webhookTimestamp outside allowed skew (${LINEAR_WEBHOOK_TIMESTAMP_SKEW_MS}ms)` - ) - return new NextResponse('Unauthorized - Webhook timestamp skew too large', { - status: 401, - }) - } - } catch (error) { - logger.warn( - `[${requestId}] Linear webhook body parse failed after signature verification`, - error - ) - return new NextResponse('Unauthorized - Invalid webhook body', { status: 401 }) - } - - return null - }, + verifyAuth: createHmacVerifier({ + configKey: 'webhookSecret', + headerName: 'Linear-Signature', + validateFn: validateLinearSignature, + providerLabel: 'Linear', + }), async formatInput({ body }: FormatInputContext): Promise { const b = body as Record - const rawActor = b.actor - let actor: unknown = null - if (rawActor && typeof rawActor === 'object' && !Array.isArray(rawActor)) { - const a = rawActor as Record - const { type: linearActorType, ...rest } = a - actor = { - ...rest, - actorType: typeof linearActorType === 'string' ? linearActorType : null, - } - } - return { input: { action: b.action || '', @@ -117,8 +59,7 @@ export const linearHandler: WebhookProviderHandler = { webhookTimestamp: b.webhookTimestamp || 0, organizationId: b.organizationId || '', createdAt: b.createdAt || '', - url: typeof b.url === 'string' ? b.url : '', - actor, + actor: b.actor || null, data: b.data || null, updatedFrom: b.updatedFrom || null, }, @@ -167,20 +108,6 @@ export const linearHandler: WebhookProviderHandler = { const notificationUrl = getNotificationUrl(ctx.webhook) const webhookSecret = generateId() - const teamId = config.teamId as string | undefined - - const input: Record = { - url: notificationUrl, - resourceTypes, - secret: webhookSecret, - enabled: true, - } - - if (teamId) { - input.teamId = teamId - } else { - input.allPublicTeams = true - } try { const response = await fetch('https://api.linear.app/graphql', { @@ -196,7 +123,14 @@ export const linearHandler: WebhookProviderHandler = { webhook { id enabled } } }`, - variables: { input }, + variables: { + input: { + url: notificationUrl, + resourceTypes, + secret: webhookSecret, + enabled: true, + }, + }, }), }) @@ -219,12 +153,6 @@ export const linearHandler: WebhookProviderHandler = { } const externalId = result.webhook?.id - if (typeof externalId !== 'string' || !externalId.trim()) { - throw new Error( - 'Linear webhook was created but the API response did not include a webhook id.' - ) - } - logger.info( `[${ctx.requestId}] Created Linear webhook ${externalId} for webhook ${ctx.webhook.id}` ) @@ -293,4 +221,13 @@ export const linearHandler: WebhookProviderHandler = { }) } }, + + extractIdempotencyId(body: unknown) { + const obj = body as Record + const data = obj.data as Record | undefined + if (obj.action && data?.id) { + return `${obj.action}:${data.id}` + } + return null + }, } diff --git a/apps/sim/triggers/linear/comment_created.ts b/apps/sim/triggers/linear/comment_created.ts index 893061cc5ea..f4d9e779011 100644 --- a/apps/sim/triggers/linear/comment_created.ts +++ b/apps/sim/triggers/linear/comment_created.ts @@ -1,5 +1,9 @@ import { LinearIcon } from '@/components/icons' -import { buildCommentOutputs, linearSetupInstructions } from '@/triggers/linear/utils' +import { + buildCommentOutputs, + buildLinearV2SubBlocks, + linearSetupInstructions, +} from '@/triggers/linear/utils' import type { TriggerConfig } from '@/triggers/types' export const linearCommentCreatedTrigger: TriggerConfig = { @@ -78,3 +82,27 @@ export const linearCommentCreatedTrigger: TriggerConfig = { }, }, } + +export const linearCommentCreatedV2Trigger: TriggerConfig = { + id: 'linear_comment_created_v2', + name: 'Linear Comment Created', + provider: 'linear', + description: 'Trigger workflow when a new comment is created in Linear', + version: '2.0.0', + icon: LinearIcon, + subBlocks: buildLinearV2SubBlocks({ + triggerId: 'linear_comment_created_v2', + eventType: 'Comment (create)', + }), + outputs: buildCommentOutputs(), + webhook: { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + 'Linear-Event': 'Comment', + 'Linear-Delivery': 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx', + 'Linear-Signature': 'sha256...', + 'User-Agent': 'Linear-Webhook', + }, + }, +} diff --git a/apps/sim/triggers/linear/comment_created_v2.ts b/apps/sim/triggers/linear/comment_created_v2.ts deleted file mode 100644 index 4db96a236f3..00000000000 --- a/apps/sim/triggers/linear/comment_created_v2.ts +++ /dev/null @@ -1,30 +0,0 @@ -import { LinearIcon } from '@/components/icons' -import { buildCommentOutputs, buildLinearV2SubBlocks } from '@/triggers/linear/utils' -import type { TriggerConfig } from '@/triggers/types' - -export const linearCommentCreatedV2Trigger: TriggerConfig = { - id: 'linear_comment_created_v2', - name: 'Linear Comment Created', - provider: 'linear', - description: 'Trigger workflow when a new comment is created in Linear', - version: '2.0.0', - icon: LinearIcon, - - subBlocks: buildLinearV2SubBlocks({ - triggerId: 'linear_comment_created_v2', - eventType: 'Comment (create)', - }), - - outputs: buildCommentOutputs(), - - webhook: { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - 'Linear-Event': 'Comment', - 'Linear-Delivery': 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx', - 'Linear-Signature': 'sha256...', - 'User-Agent': 'Linear-Webhook', - }, - }, -} diff --git a/apps/sim/triggers/linear/comment_updated.ts b/apps/sim/triggers/linear/comment_updated.ts index d837d714944..6bd1761beba 100644 --- a/apps/sim/triggers/linear/comment_updated.ts +++ b/apps/sim/triggers/linear/comment_updated.ts @@ -1,5 +1,9 @@ import { LinearIcon } from '@/components/icons' -import { buildCommentOutputs, linearSetupInstructions } from '@/triggers/linear/utils' +import { + buildCommentOutputs, + buildLinearV2SubBlocks, + linearSetupInstructions, +} from '@/triggers/linear/utils' import type { TriggerConfig } from '@/triggers/types' export const linearCommentUpdatedTrigger: TriggerConfig = { @@ -78,3 +82,27 @@ export const linearCommentUpdatedTrigger: TriggerConfig = { }, }, } + +export const linearCommentUpdatedV2Trigger: TriggerConfig = { + id: 'linear_comment_updated_v2', + name: 'Linear Comment Updated', + provider: 'linear', + description: 'Trigger workflow when a comment is updated in Linear', + version: '2.0.0', + icon: LinearIcon, + subBlocks: buildLinearV2SubBlocks({ + triggerId: 'linear_comment_updated_v2', + eventType: 'Comment (update)', + }), + outputs: buildCommentOutputs(), + webhook: { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + 'Linear-Event': 'Comment', + 'Linear-Delivery': 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx', + 'Linear-Signature': 'sha256...', + 'User-Agent': 'Linear-Webhook', + }, + }, +} diff --git a/apps/sim/triggers/linear/comment_updated_v2.ts b/apps/sim/triggers/linear/comment_updated_v2.ts deleted file mode 100644 index 6496534933a..00000000000 --- a/apps/sim/triggers/linear/comment_updated_v2.ts +++ /dev/null @@ -1,30 +0,0 @@ -import { LinearIcon } from '@/components/icons' -import { buildCommentOutputs, buildLinearV2SubBlocks } from '@/triggers/linear/utils' -import type { TriggerConfig } from '@/triggers/types' - -export const linearCommentUpdatedV2Trigger: TriggerConfig = { - id: 'linear_comment_updated_v2', - name: 'Linear Comment Updated', - provider: 'linear', - description: 'Trigger workflow when a comment is updated in Linear', - version: '2.0.0', - icon: LinearIcon, - - subBlocks: buildLinearV2SubBlocks({ - triggerId: 'linear_comment_updated_v2', - eventType: 'Comment (update)', - }), - - outputs: buildCommentOutputs(), - - webhook: { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - 'Linear-Event': 'Comment', - 'Linear-Delivery': 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx', - 'Linear-Signature': 'sha256...', - 'User-Agent': 'Linear-Webhook', - }, - }, -} diff --git a/apps/sim/triggers/linear/customer_request_created.ts b/apps/sim/triggers/linear/customer_request_created.ts index b08b16985d6..b8c17da527d 100644 --- a/apps/sim/triggers/linear/customer_request_created.ts +++ b/apps/sim/triggers/linear/customer_request_created.ts @@ -1,5 +1,9 @@ import { LinearIcon } from '@/components/icons' -import { buildCustomerRequestOutputs, linearSetupInstructions } from '@/triggers/linear/utils' +import { + buildCustomerRequestOutputs, + buildLinearV2SubBlocks, + linearSetupInstructions, +} from '@/triggers/linear/utils' import type { TriggerConfig } from '@/triggers/types' export const linearCustomerRequestCreatedTrigger: TriggerConfig = { @@ -78,3 +82,27 @@ export const linearCustomerRequestCreatedTrigger: TriggerConfig = { }, }, } + +export const linearCustomerRequestCreatedV2Trigger: TriggerConfig = { + id: 'linear_customer_request_created_v2', + name: 'Linear Customer Request Created', + provider: 'linear', + description: 'Trigger workflow when a new customer request is created in Linear', + version: '2.0.0', + icon: LinearIcon, + subBlocks: buildLinearV2SubBlocks({ + triggerId: 'linear_customer_request_created_v2', + eventType: 'Customer Requests', + }), + outputs: buildCustomerRequestOutputs(), + webhook: { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + 'Linear-Event': 'CustomerNeed', + 'Linear-Delivery': 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx', + 'Linear-Signature': 'sha256...', + 'User-Agent': 'Linear-Webhook', + }, + }, +} diff --git a/apps/sim/triggers/linear/customer_request_created_v2.ts b/apps/sim/triggers/linear/customer_request_created_v2.ts deleted file mode 100644 index dd5d91663b7..00000000000 --- a/apps/sim/triggers/linear/customer_request_created_v2.ts +++ /dev/null @@ -1,30 +0,0 @@ -import { LinearIcon } from '@/components/icons' -import { buildCustomerRequestOutputs, buildLinearV2SubBlocks } from '@/triggers/linear/utils' -import type { TriggerConfig } from '@/triggers/types' - -export const linearCustomerRequestCreatedV2Trigger: TriggerConfig = { - id: 'linear_customer_request_created_v2', - name: 'Linear Customer Request Created', - provider: 'linear', - description: 'Trigger workflow when a new customer request is created in Linear', - version: '2.0.0', - icon: LinearIcon, - - subBlocks: buildLinearV2SubBlocks({ - triggerId: 'linear_customer_request_created_v2', - eventType: 'Customer Requests', - }), - - outputs: buildCustomerRequestOutputs(), - - webhook: { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - 'Linear-Event': 'CustomerNeed', - 'Linear-Delivery': 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx', - 'Linear-Signature': 'sha256...', - 'User-Agent': 'Linear-Webhook', - }, - }, -} diff --git a/apps/sim/triggers/linear/customer_request_updated.ts b/apps/sim/triggers/linear/customer_request_updated.ts index e4f91cfa8f1..a76b8c22cab 100644 --- a/apps/sim/triggers/linear/customer_request_updated.ts +++ b/apps/sim/triggers/linear/customer_request_updated.ts @@ -1,5 +1,9 @@ import { LinearIcon } from '@/components/icons' -import { buildCustomerRequestOutputs, linearSetupInstructions } from '@/triggers/linear/utils' +import { + buildCustomerRequestOutputs, + buildLinearV2SubBlocks, + linearSetupInstructions, +} from '@/triggers/linear/utils' import type { TriggerConfig } from '@/triggers/types' export const linearCustomerRequestUpdatedTrigger: TriggerConfig = { @@ -78,3 +82,27 @@ export const linearCustomerRequestUpdatedTrigger: TriggerConfig = { }, }, } + +export const linearCustomerRequestUpdatedV2Trigger: TriggerConfig = { + id: 'linear_customer_request_updated_v2', + name: 'Linear Customer Request Updated', + provider: 'linear', + description: 'Trigger workflow when a customer request is updated in Linear', + version: '2.0.0', + icon: LinearIcon, + subBlocks: buildLinearV2SubBlocks({ + triggerId: 'linear_customer_request_updated_v2', + eventType: 'CustomerNeed (update)', + }), + outputs: buildCustomerRequestOutputs(), + webhook: { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + 'Linear-Event': 'CustomerNeed', + 'Linear-Delivery': 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx', + 'Linear-Signature': 'sha256...', + 'User-Agent': 'Linear-Webhook', + }, + }, +} diff --git a/apps/sim/triggers/linear/customer_request_updated_v2.ts b/apps/sim/triggers/linear/customer_request_updated_v2.ts deleted file mode 100644 index b06696b580f..00000000000 --- a/apps/sim/triggers/linear/customer_request_updated_v2.ts +++ /dev/null @@ -1,30 +0,0 @@ -import { LinearIcon } from '@/components/icons' -import { buildCustomerRequestOutputs, buildLinearV2SubBlocks } from '@/triggers/linear/utils' -import type { TriggerConfig } from '@/triggers/types' - -export const linearCustomerRequestUpdatedV2Trigger: TriggerConfig = { - id: 'linear_customer_request_updated_v2', - name: 'Linear Customer Request Updated', - provider: 'linear', - description: 'Trigger workflow when a customer request is updated in Linear', - version: '2.0.0', - icon: LinearIcon, - - subBlocks: buildLinearV2SubBlocks({ - triggerId: 'linear_customer_request_updated_v2', - eventType: 'CustomerNeed (update)', - }), - - outputs: buildCustomerRequestOutputs(), - - webhook: { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - 'Linear-Event': 'CustomerNeed', - 'Linear-Delivery': 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx', - 'Linear-Signature': 'sha256...', - 'User-Agent': 'Linear-Webhook', - }, - }, -} diff --git a/apps/sim/triggers/linear/cycle_created.ts b/apps/sim/triggers/linear/cycle_created.ts index dc80861ab0d..3238dce74fe 100644 --- a/apps/sim/triggers/linear/cycle_created.ts +++ b/apps/sim/triggers/linear/cycle_created.ts @@ -1,5 +1,9 @@ import { LinearIcon } from '@/components/icons' -import { buildCycleOutputs, linearSetupInstructions } from '@/triggers/linear/utils' +import { + buildCycleOutputs, + buildLinearV2SubBlocks, + linearSetupInstructions, +} from '@/triggers/linear/utils' import type { TriggerConfig } from '@/triggers/types' export const linearCycleCreatedTrigger: TriggerConfig = { @@ -78,3 +82,27 @@ export const linearCycleCreatedTrigger: TriggerConfig = { }, }, } + +export const linearCycleCreatedV2Trigger: TriggerConfig = { + id: 'linear_cycle_created_v2', + name: 'Linear Cycle Created', + provider: 'linear', + description: 'Trigger workflow when a new cycle is created in Linear', + version: '2.0.0', + icon: LinearIcon, + subBlocks: buildLinearV2SubBlocks({ + triggerId: 'linear_cycle_created_v2', + eventType: 'Cycle (create)', + }), + outputs: buildCycleOutputs(), + webhook: { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + 'Linear-Event': 'Cycle', + 'Linear-Delivery': 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx', + 'Linear-Signature': 'sha256...', + 'User-Agent': 'Linear-Webhook', + }, + }, +} diff --git a/apps/sim/triggers/linear/cycle_created_v2.ts b/apps/sim/triggers/linear/cycle_created_v2.ts deleted file mode 100644 index 8204331c22e..00000000000 --- a/apps/sim/triggers/linear/cycle_created_v2.ts +++ /dev/null @@ -1,30 +0,0 @@ -import { LinearIcon } from '@/components/icons' -import { buildCycleOutputs, buildLinearV2SubBlocks } from '@/triggers/linear/utils' -import type { TriggerConfig } from '@/triggers/types' - -export const linearCycleCreatedV2Trigger: TriggerConfig = { - id: 'linear_cycle_created_v2', - name: 'Linear Cycle Created', - provider: 'linear', - description: 'Trigger workflow when a new cycle is created in Linear', - version: '2.0.0', - icon: LinearIcon, - - subBlocks: buildLinearV2SubBlocks({ - triggerId: 'linear_cycle_created_v2', - eventType: 'Cycle (create)', - }), - - outputs: buildCycleOutputs(), - - webhook: { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - 'Linear-Event': 'Cycle', - 'Linear-Delivery': 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx', - 'Linear-Signature': 'sha256...', - 'User-Agent': 'Linear-Webhook', - }, - }, -} diff --git a/apps/sim/triggers/linear/cycle_updated.ts b/apps/sim/triggers/linear/cycle_updated.ts index 7922adafcd6..fc996c3a8e8 100644 --- a/apps/sim/triggers/linear/cycle_updated.ts +++ b/apps/sim/triggers/linear/cycle_updated.ts @@ -1,5 +1,9 @@ import { LinearIcon } from '@/components/icons' -import { buildCycleOutputs, linearSetupInstructions } from '@/triggers/linear/utils' +import { + buildCycleOutputs, + buildLinearV2SubBlocks, + linearSetupInstructions, +} from '@/triggers/linear/utils' import type { TriggerConfig } from '@/triggers/types' export const linearCycleUpdatedTrigger: TriggerConfig = { @@ -78,3 +82,27 @@ export const linearCycleUpdatedTrigger: TriggerConfig = { }, }, } + +export const linearCycleUpdatedV2Trigger: TriggerConfig = { + id: 'linear_cycle_updated_v2', + name: 'Linear Cycle Updated', + provider: 'linear', + description: 'Trigger workflow when a cycle is updated in Linear', + version: '2.0.0', + icon: LinearIcon, + subBlocks: buildLinearV2SubBlocks({ + triggerId: 'linear_cycle_updated_v2', + eventType: 'Cycle (update)', + }), + outputs: buildCycleOutputs(), + webhook: { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + 'Linear-Event': 'Cycle', + 'Linear-Delivery': 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx', + 'Linear-Signature': 'sha256...', + 'User-Agent': 'Linear-Webhook', + }, + }, +} diff --git a/apps/sim/triggers/linear/cycle_updated_v2.ts b/apps/sim/triggers/linear/cycle_updated_v2.ts deleted file mode 100644 index 341f1261236..00000000000 --- a/apps/sim/triggers/linear/cycle_updated_v2.ts +++ /dev/null @@ -1,30 +0,0 @@ -import { LinearIcon } from '@/components/icons' -import { buildCycleOutputs, buildLinearV2SubBlocks } from '@/triggers/linear/utils' -import type { TriggerConfig } from '@/triggers/types' - -export const linearCycleUpdatedV2Trigger: TriggerConfig = { - id: 'linear_cycle_updated_v2', - name: 'Linear Cycle Updated', - provider: 'linear', - description: 'Trigger workflow when a cycle is updated in Linear', - version: '2.0.0', - icon: LinearIcon, - - subBlocks: buildLinearV2SubBlocks({ - triggerId: 'linear_cycle_updated_v2', - eventType: 'Cycle (update)', - }), - - outputs: buildCycleOutputs(), - - webhook: { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - 'Linear-Event': 'Cycle', - 'Linear-Delivery': 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx', - 'Linear-Signature': 'sha256...', - 'User-Agent': 'Linear-Webhook', - }, - }, -} diff --git a/apps/sim/triggers/linear/index.ts b/apps/sim/triggers/linear/index.ts index 1a6e9ebe2a1..05b35bd39db 100644 --- a/apps/sim/triggers/linear/index.ts +++ b/apps/sim/triggers/linear/index.ts @@ -1,30 +1,24 @@ -export { linearCommentCreatedTrigger } from './comment_created' -export { linearCommentCreatedV2Trigger } from './comment_created_v2' -export { linearCommentUpdatedTrigger } from './comment_updated' -export { linearCommentUpdatedV2Trigger } from './comment_updated_v2' -export { linearCustomerRequestCreatedTrigger } from './customer_request_created' -export { linearCustomerRequestCreatedV2Trigger } from './customer_request_created_v2' -export { linearCustomerRequestUpdatedTrigger } from './customer_request_updated' -export { linearCustomerRequestUpdatedV2Trigger } from './customer_request_updated_v2' -export { linearCycleCreatedTrigger } from './cycle_created' -export { linearCycleCreatedV2Trigger } from './cycle_created_v2' -export { linearCycleUpdatedTrigger } from './cycle_updated' -export { linearCycleUpdatedV2Trigger } from './cycle_updated_v2' -export { linearIssueCreatedTrigger } from './issue_created' -export { linearIssueCreatedV2Trigger } from './issue_created_v2' -export { linearIssueRemovedTrigger } from './issue_removed' -export { linearIssueRemovedV2Trigger } from './issue_removed_v2' -export { linearIssueUpdatedTrigger } from './issue_updated' -export { linearIssueUpdatedV2Trigger } from './issue_updated_v2' -export { linearLabelCreatedTrigger } from './label_created' -export { linearLabelCreatedV2Trigger } from './label_created_v2' -export { linearLabelUpdatedTrigger } from './label_updated' -export { linearLabelUpdatedV2Trigger } from './label_updated_v2' -export { linearProjectCreatedTrigger } from './project_created' -export { linearProjectCreatedV2Trigger } from './project_created_v2' -export { linearProjectUpdateCreatedTrigger } from './project_update_created' -export { linearProjectUpdateCreatedV2Trigger } from './project_update_created_v2' -export { linearProjectUpdatedTrigger } from './project_updated' -export { linearProjectUpdatedV2Trigger } from './project_updated_v2' -export { linearWebhookTrigger } from './webhook' -export { linearWebhookV2Trigger } from './webhook_v2' +export { linearCommentCreatedTrigger, linearCommentCreatedV2Trigger } from './comment_created' +export { linearCommentUpdatedTrigger, linearCommentUpdatedV2Trigger } from './comment_updated' +export { + linearCustomerRequestCreatedTrigger, + linearCustomerRequestCreatedV2Trigger, +} from './customer_request_created' +export { + linearCustomerRequestUpdatedTrigger, + linearCustomerRequestUpdatedV2Trigger, +} from './customer_request_updated' +export { linearCycleCreatedTrigger, linearCycleCreatedV2Trigger } from './cycle_created' +export { linearCycleUpdatedTrigger, linearCycleUpdatedV2Trigger } from './cycle_updated' +export { linearIssueCreatedTrigger, linearIssueCreatedV2Trigger } from './issue_created' +export { linearIssueRemovedTrigger, linearIssueRemovedV2Trigger } from './issue_removed' +export { linearIssueUpdatedTrigger, linearIssueUpdatedV2Trigger } from './issue_updated' +export { linearLabelCreatedTrigger, linearLabelCreatedV2Trigger } from './label_created' +export { linearLabelUpdatedTrigger, linearLabelUpdatedV2Trigger } from './label_updated' +export { linearProjectCreatedTrigger, linearProjectCreatedV2Trigger } from './project_created' +export { + linearProjectUpdateCreatedTrigger, + linearProjectUpdateCreatedV2Trigger, +} from './project_update_created' +export { linearProjectUpdatedTrigger, linearProjectUpdatedV2Trigger } from './project_updated' +export { linearWebhookTrigger, linearWebhookV2Trigger } from './webhook' diff --git a/apps/sim/triggers/linear/issue_created.ts b/apps/sim/triggers/linear/issue_created.ts index e10b00663f9..4a95974a1e7 100644 --- a/apps/sim/triggers/linear/issue_created.ts +++ b/apps/sim/triggers/linear/issue_created.ts @@ -1,6 +1,7 @@ import { LinearIcon } from '@/components/icons' import { buildIssueOutputs, + buildLinearV2SubBlocks, linearSetupInstructions, linearTriggerOptions, } from '@/triggers/linear/utils' @@ -91,3 +92,28 @@ export const linearIssueCreatedTrigger: TriggerConfig = { }, }, } + +export const linearIssueCreatedV2Trigger: TriggerConfig = { + id: 'linear_issue_created_v2', + name: 'Linear Issue Created', + provider: 'linear', + description: 'Trigger workflow when a new issue is created in Linear', + version: '2.0.0', + icon: LinearIcon, + subBlocks: buildLinearV2SubBlocks({ + triggerId: 'linear_issue_created_v2', + eventType: 'Issue (create)', + includeDropdown: true, + }), + outputs: buildIssueOutputs(), + webhook: { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + 'Linear-Event': 'Issue', + 'Linear-Delivery': 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx', + 'Linear-Signature': 'sha256...', + 'User-Agent': 'Linear-Webhook', + }, + }, +} diff --git a/apps/sim/triggers/linear/issue_created_v2.ts b/apps/sim/triggers/linear/issue_created_v2.ts deleted file mode 100644 index b6eb9cc5945..00000000000 --- a/apps/sim/triggers/linear/issue_created_v2.ts +++ /dev/null @@ -1,37 +0,0 @@ -import { LinearIcon } from '@/components/icons' -import { buildIssueOutputs, buildLinearV2SubBlocks } from '@/triggers/linear/utils' -import type { TriggerConfig } from '@/triggers/types' - -/** - * Linear Issue Created Trigger (v2) - * - * Primary trigger - includes the dropdown for selecting trigger type. - * Uses automatic webhook registration via the Linear GraphQL API. - */ -export const linearIssueCreatedV2Trigger: TriggerConfig = { - id: 'linear_issue_created_v2', - name: 'Linear Issue Created', - provider: 'linear', - description: 'Trigger workflow when a new issue is created in Linear', - version: '2.0.0', - icon: LinearIcon, - - subBlocks: buildLinearV2SubBlocks({ - triggerId: 'linear_issue_created_v2', - eventType: 'Issue (create)', - includeDropdown: true, - }), - - outputs: buildIssueOutputs(), - - webhook: { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - 'Linear-Event': 'Issue', - 'Linear-Delivery': 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx', - 'Linear-Signature': 'sha256...', - 'User-Agent': 'Linear-Webhook', - }, - }, -} diff --git a/apps/sim/triggers/linear/issue_removed.ts b/apps/sim/triggers/linear/issue_removed.ts index 8f1361acbf8..ca1431ecaeb 100644 --- a/apps/sim/triggers/linear/issue_removed.ts +++ b/apps/sim/triggers/linear/issue_removed.ts @@ -1,5 +1,9 @@ import { LinearIcon } from '@/components/icons' -import { buildIssueOutputs, linearSetupInstructions } from '@/triggers/linear/utils' +import { + buildIssueOutputs, + buildLinearV2SubBlocks, + linearSetupInstructions, +} from '@/triggers/linear/utils' import type { TriggerConfig } from '@/triggers/types' export const linearIssueRemovedTrigger: TriggerConfig = { @@ -78,3 +82,27 @@ export const linearIssueRemovedTrigger: TriggerConfig = { }, }, } + +export const linearIssueRemovedV2Trigger: TriggerConfig = { + id: 'linear_issue_removed_v2', + name: 'Linear Issue Removed', + provider: 'linear', + description: 'Trigger workflow when an issue is removed/deleted in Linear', + version: '2.0.0', + icon: LinearIcon, + subBlocks: buildLinearV2SubBlocks({ + triggerId: 'linear_issue_removed_v2', + eventType: 'Issue (remove)', + }), + outputs: buildIssueOutputs(), + webhook: { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + 'Linear-Event': 'Issue', + 'Linear-Delivery': 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx', + 'Linear-Signature': 'sha256...', + 'User-Agent': 'Linear-Webhook', + }, + }, +} diff --git a/apps/sim/triggers/linear/issue_removed_v2.ts b/apps/sim/triggers/linear/issue_removed_v2.ts deleted file mode 100644 index 152e1d5504f..00000000000 --- a/apps/sim/triggers/linear/issue_removed_v2.ts +++ /dev/null @@ -1,30 +0,0 @@ -import { LinearIcon } from '@/components/icons' -import { buildIssueOutputs, buildLinearV2SubBlocks } from '@/triggers/linear/utils' -import type { TriggerConfig } from '@/triggers/types' - -export const linearIssueRemovedV2Trigger: TriggerConfig = { - id: 'linear_issue_removed_v2', - name: 'Linear Issue Removed', - provider: 'linear', - description: 'Trigger workflow when an issue is removed/deleted in Linear', - version: '2.0.0', - icon: LinearIcon, - - subBlocks: buildLinearV2SubBlocks({ - triggerId: 'linear_issue_removed_v2', - eventType: 'Issue (remove)', - }), - - outputs: buildIssueOutputs(), - - webhook: { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - 'Linear-Event': 'Issue', - 'Linear-Delivery': 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx', - 'Linear-Signature': 'sha256...', - 'User-Agent': 'Linear-Webhook', - }, - }, -} diff --git a/apps/sim/triggers/linear/issue_updated.ts b/apps/sim/triggers/linear/issue_updated.ts index 75460268293..2893331a184 100644 --- a/apps/sim/triggers/linear/issue_updated.ts +++ b/apps/sim/triggers/linear/issue_updated.ts @@ -1,5 +1,9 @@ import { LinearIcon } from '@/components/icons' -import { buildIssueOutputs, linearSetupInstructions } from '@/triggers/linear/utils' +import { + buildIssueOutputs, + buildLinearV2SubBlocks, + linearSetupInstructions, +} from '@/triggers/linear/utils' import type { TriggerConfig } from '@/triggers/types' export const linearIssueUpdatedTrigger: TriggerConfig = { @@ -78,3 +82,27 @@ export const linearIssueUpdatedTrigger: TriggerConfig = { }, }, } + +export const linearIssueUpdatedV2Trigger: TriggerConfig = { + id: 'linear_issue_updated_v2', + name: 'Linear Issue Updated', + provider: 'linear', + description: 'Trigger workflow when an issue is updated in Linear', + version: '2.0.0', + icon: LinearIcon, + subBlocks: buildLinearV2SubBlocks({ + triggerId: 'linear_issue_updated_v2', + eventType: 'Issue (update)', + }), + outputs: buildIssueOutputs(), + webhook: { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + 'Linear-Event': 'Issue', + 'Linear-Delivery': 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx', + 'Linear-Signature': 'sha256...', + 'User-Agent': 'Linear-Webhook', + }, + }, +} diff --git a/apps/sim/triggers/linear/issue_updated_v2.ts b/apps/sim/triggers/linear/issue_updated_v2.ts deleted file mode 100644 index 6fc6b04e2b9..00000000000 --- a/apps/sim/triggers/linear/issue_updated_v2.ts +++ /dev/null @@ -1,30 +0,0 @@ -import { LinearIcon } from '@/components/icons' -import { buildIssueOutputs, buildLinearV2SubBlocks } from '@/triggers/linear/utils' -import type { TriggerConfig } from '@/triggers/types' - -export const linearIssueUpdatedV2Trigger: TriggerConfig = { - id: 'linear_issue_updated_v2', - name: 'Linear Issue Updated', - provider: 'linear', - description: 'Trigger workflow when an issue is updated in Linear', - version: '2.0.0', - icon: LinearIcon, - - subBlocks: buildLinearV2SubBlocks({ - triggerId: 'linear_issue_updated_v2', - eventType: 'Issue (update)', - }), - - outputs: buildIssueOutputs(), - - webhook: { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - 'Linear-Event': 'Issue', - 'Linear-Delivery': 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx', - 'Linear-Signature': 'sha256...', - 'User-Agent': 'Linear-Webhook', - }, - }, -} diff --git a/apps/sim/triggers/linear/label_created.ts b/apps/sim/triggers/linear/label_created.ts index f3e9638aebf..369825c83aa 100644 --- a/apps/sim/triggers/linear/label_created.ts +++ b/apps/sim/triggers/linear/label_created.ts @@ -1,5 +1,9 @@ import { LinearIcon } from '@/components/icons' -import { buildLabelOutputs, linearSetupInstructions } from '@/triggers/linear/utils' +import { + buildLabelOutputs, + buildLinearV2SubBlocks, + linearSetupInstructions, +} from '@/triggers/linear/utils' import type { TriggerConfig } from '@/triggers/types' export const linearLabelCreatedTrigger: TriggerConfig = { @@ -78,3 +82,27 @@ export const linearLabelCreatedTrigger: TriggerConfig = { }, }, } + +export const linearLabelCreatedV2Trigger: TriggerConfig = { + id: 'linear_label_created_v2', + name: 'Linear Label Created', + provider: 'linear', + description: 'Trigger workflow when a new label is created in Linear', + version: '2.0.0', + icon: LinearIcon, + subBlocks: buildLinearV2SubBlocks({ + triggerId: 'linear_label_created_v2', + eventType: 'IssueLabel (create)', + }), + outputs: buildLabelOutputs(), + webhook: { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + 'Linear-Event': 'IssueLabel', + 'Linear-Delivery': 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx', + 'Linear-Signature': 'sha256...', + 'User-Agent': 'Linear-Webhook', + }, + }, +} diff --git a/apps/sim/triggers/linear/label_created_v2.ts b/apps/sim/triggers/linear/label_created_v2.ts deleted file mode 100644 index d32c1593e95..00000000000 --- a/apps/sim/triggers/linear/label_created_v2.ts +++ /dev/null @@ -1,30 +0,0 @@ -import { LinearIcon } from '@/components/icons' -import { buildLabelOutputs, buildLinearV2SubBlocks } from '@/triggers/linear/utils' -import type { TriggerConfig } from '@/triggers/types' - -export const linearLabelCreatedV2Trigger: TriggerConfig = { - id: 'linear_label_created_v2', - name: 'Linear Label Created', - provider: 'linear', - description: 'Trigger workflow when a new label is created in Linear', - version: '2.0.0', - icon: LinearIcon, - - subBlocks: buildLinearV2SubBlocks({ - triggerId: 'linear_label_created_v2', - eventType: 'IssueLabel (create)', - }), - - outputs: buildLabelOutputs(), - - webhook: { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - 'Linear-Event': 'IssueLabel', - 'Linear-Delivery': 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx', - 'Linear-Signature': 'sha256...', - 'User-Agent': 'Linear-Webhook', - }, - }, -} diff --git a/apps/sim/triggers/linear/label_updated.ts b/apps/sim/triggers/linear/label_updated.ts index 2f0941f72e0..9009165bf5b 100644 --- a/apps/sim/triggers/linear/label_updated.ts +++ b/apps/sim/triggers/linear/label_updated.ts @@ -1,5 +1,9 @@ import { LinearIcon } from '@/components/icons' -import { buildLabelOutputs, linearSetupInstructions } from '@/triggers/linear/utils' +import { + buildLabelOutputs, + buildLinearV2SubBlocks, + linearSetupInstructions, +} from '@/triggers/linear/utils' import type { TriggerConfig } from '@/triggers/types' export const linearLabelUpdatedTrigger: TriggerConfig = { @@ -78,3 +82,27 @@ export const linearLabelUpdatedTrigger: TriggerConfig = { }, }, } + +export const linearLabelUpdatedV2Trigger: TriggerConfig = { + id: 'linear_label_updated_v2', + name: 'Linear Label Updated', + provider: 'linear', + description: 'Trigger workflow when a label is updated in Linear', + version: '2.0.0', + icon: LinearIcon, + subBlocks: buildLinearV2SubBlocks({ + triggerId: 'linear_label_updated_v2', + eventType: 'IssueLabel (update)', + }), + outputs: buildLabelOutputs(), + webhook: { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + 'Linear-Event': 'IssueLabel', + 'Linear-Delivery': 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx', + 'Linear-Signature': 'sha256...', + 'User-Agent': 'Linear-Webhook', + }, + }, +} diff --git a/apps/sim/triggers/linear/label_updated_v2.ts b/apps/sim/triggers/linear/label_updated_v2.ts deleted file mode 100644 index f55f61f1eff..00000000000 --- a/apps/sim/triggers/linear/label_updated_v2.ts +++ /dev/null @@ -1,30 +0,0 @@ -import { LinearIcon } from '@/components/icons' -import { buildLabelOutputs, buildLinearV2SubBlocks } from '@/triggers/linear/utils' -import type { TriggerConfig } from '@/triggers/types' - -export const linearLabelUpdatedV2Trigger: TriggerConfig = { - id: 'linear_label_updated_v2', - name: 'Linear Label Updated', - provider: 'linear', - description: 'Trigger workflow when a label is updated in Linear', - version: '2.0.0', - icon: LinearIcon, - - subBlocks: buildLinearV2SubBlocks({ - triggerId: 'linear_label_updated_v2', - eventType: 'IssueLabel (update)', - }), - - outputs: buildLabelOutputs(), - - webhook: { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - 'Linear-Event': 'IssueLabel', - 'Linear-Delivery': 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx', - 'Linear-Signature': 'sha256...', - 'User-Agent': 'Linear-Webhook', - }, - }, -} diff --git a/apps/sim/triggers/linear/project_created.ts b/apps/sim/triggers/linear/project_created.ts index 4175b78170f..6758466c701 100644 --- a/apps/sim/triggers/linear/project_created.ts +++ b/apps/sim/triggers/linear/project_created.ts @@ -1,5 +1,9 @@ import { LinearIcon } from '@/components/icons' -import { buildProjectOutputs, linearSetupInstructions } from '@/triggers/linear/utils' +import { + buildLinearV2SubBlocks, + buildProjectOutputs, + linearSetupInstructions, +} from '@/triggers/linear/utils' import type { TriggerConfig } from '@/triggers/types' export const linearProjectCreatedTrigger: TriggerConfig = { @@ -78,3 +82,27 @@ export const linearProjectCreatedTrigger: TriggerConfig = { }, }, } + +export const linearProjectCreatedV2Trigger: TriggerConfig = { + id: 'linear_project_created_v2', + name: 'Linear Project Created', + provider: 'linear', + description: 'Trigger workflow when a new project is created in Linear', + version: '2.0.0', + icon: LinearIcon, + subBlocks: buildLinearV2SubBlocks({ + triggerId: 'linear_project_created_v2', + eventType: 'Project (create)', + }), + outputs: buildProjectOutputs(), + webhook: { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + 'Linear-Event': 'Project', + 'Linear-Delivery': 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx', + 'Linear-Signature': 'sha256...', + 'User-Agent': 'Linear-Webhook', + }, + }, +} diff --git a/apps/sim/triggers/linear/project_created_v2.ts b/apps/sim/triggers/linear/project_created_v2.ts deleted file mode 100644 index 392cc57d894..00000000000 --- a/apps/sim/triggers/linear/project_created_v2.ts +++ /dev/null @@ -1,30 +0,0 @@ -import { LinearIcon } from '@/components/icons' -import { buildLinearV2SubBlocks, buildProjectOutputs } from '@/triggers/linear/utils' -import type { TriggerConfig } from '@/triggers/types' - -export const linearProjectCreatedV2Trigger: TriggerConfig = { - id: 'linear_project_created_v2', - name: 'Linear Project Created', - provider: 'linear', - description: 'Trigger workflow when a new project is created in Linear', - version: '2.0.0', - icon: LinearIcon, - - subBlocks: buildLinearV2SubBlocks({ - triggerId: 'linear_project_created_v2', - eventType: 'Project (create)', - }), - - outputs: buildProjectOutputs(), - - webhook: { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - 'Linear-Event': 'Project', - 'Linear-Delivery': 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx', - 'Linear-Signature': 'sha256...', - 'User-Agent': 'Linear-Webhook', - }, - }, -} diff --git a/apps/sim/triggers/linear/project_update_created.ts b/apps/sim/triggers/linear/project_update_created.ts index 9d845480255..83321dbf80c 100644 --- a/apps/sim/triggers/linear/project_update_created.ts +++ b/apps/sim/triggers/linear/project_update_created.ts @@ -1,5 +1,9 @@ import { LinearIcon } from '@/components/icons' -import { buildProjectUpdateOutputs, linearSetupInstructions } from '@/triggers/linear/utils' +import { + buildLinearV2SubBlocks, + buildProjectUpdateOutputs, + linearSetupInstructions, +} from '@/triggers/linear/utils' import type { TriggerConfig } from '@/triggers/types' export const linearProjectUpdateCreatedTrigger: TriggerConfig = { @@ -78,3 +82,27 @@ export const linearProjectUpdateCreatedTrigger: TriggerConfig = { }, }, } + +export const linearProjectUpdateCreatedV2Trigger: TriggerConfig = { + id: 'linear_project_update_created_v2', + name: 'Linear Project Update Created', + provider: 'linear', + description: 'Trigger workflow when a new project update is posted in Linear', + version: '2.0.0', + icon: LinearIcon, + subBlocks: buildLinearV2SubBlocks({ + triggerId: 'linear_project_update_created_v2', + eventType: 'ProjectUpdate (create)', + }), + outputs: buildProjectUpdateOutputs(), + webhook: { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + 'Linear-Event': 'ProjectUpdate', + 'Linear-Delivery': 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx', + 'Linear-Signature': 'sha256...', + 'User-Agent': 'Linear-Webhook', + }, + }, +} diff --git a/apps/sim/triggers/linear/project_update_created_v2.ts b/apps/sim/triggers/linear/project_update_created_v2.ts deleted file mode 100644 index cf872edd76a..00000000000 --- a/apps/sim/triggers/linear/project_update_created_v2.ts +++ /dev/null @@ -1,30 +0,0 @@ -import { LinearIcon } from '@/components/icons' -import { buildLinearV2SubBlocks, buildProjectUpdateOutputs } from '@/triggers/linear/utils' -import type { TriggerConfig } from '@/triggers/types' - -export const linearProjectUpdateCreatedV2Trigger: TriggerConfig = { - id: 'linear_project_update_created_v2', - name: 'Linear Project Update Created', - provider: 'linear', - description: 'Trigger workflow when a new project update is posted in Linear', - version: '2.0.0', - icon: LinearIcon, - - subBlocks: buildLinearV2SubBlocks({ - triggerId: 'linear_project_update_created_v2', - eventType: 'ProjectUpdate (create)', - }), - - outputs: buildProjectUpdateOutputs(), - - webhook: { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - 'Linear-Event': 'ProjectUpdate', - 'Linear-Delivery': 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx', - 'Linear-Signature': 'sha256...', - 'User-Agent': 'Linear-Webhook', - }, - }, -} diff --git a/apps/sim/triggers/linear/project_updated.ts b/apps/sim/triggers/linear/project_updated.ts index 1e569e6cbfd..e79eb4cd58a 100644 --- a/apps/sim/triggers/linear/project_updated.ts +++ b/apps/sim/triggers/linear/project_updated.ts @@ -1,5 +1,9 @@ import { LinearIcon } from '@/components/icons' -import { buildProjectOutputs, linearSetupInstructions } from '@/triggers/linear/utils' +import { + buildLinearV2SubBlocks, + buildProjectOutputs, + linearSetupInstructions, +} from '@/triggers/linear/utils' import type { TriggerConfig } from '@/triggers/types' export const linearProjectUpdatedTrigger: TriggerConfig = { @@ -78,3 +82,27 @@ export const linearProjectUpdatedTrigger: TriggerConfig = { }, }, } + +export const linearProjectUpdatedV2Trigger: TriggerConfig = { + id: 'linear_project_updated_v2', + name: 'Linear Project Updated', + provider: 'linear', + description: 'Trigger workflow when a project is updated in Linear', + version: '2.0.0', + icon: LinearIcon, + subBlocks: buildLinearV2SubBlocks({ + triggerId: 'linear_project_updated_v2', + eventType: 'Project (update)', + }), + outputs: buildProjectOutputs(), + webhook: { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + 'Linear-Event': 'Project', + 'Linear-Delivery': 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx', + 'Linear-Signature': 'sha256...', + 'User-Agent': 'Linear-Webhook', + }, + }, +} diff --git a/apps/sim/triggers/linear/project_updated_v2.ts b/apps/sim/triggers/linear/project_updated_v2.ts deleted file mode 100644 index 71a83211881..00000000000 --- a/apps/sim/triggers/linear/project_updated_v2.ts +++ /dev/null @@ -1,30 +0,0 @@ -import { LinearIcon } from '@/components/icons' -import { buildLinearV2SubBlocks, buildProjectOutputs } from '@/triggers/linear/utils' -import type { TriggerConfig } from '@/triggers/types' - -export const linearProjectUpdatedV2Trigger: TriggerConfig = { - id: 'linear_project_updated_v2', - name: 'Linear Project Updated', - provider: 'linear', - description: 'Trigger workflow when a project is updated in Linear', - version: '2.0.0', - icon: LinearIcon, - - subBlocks: buildLinearV2SubBlocks({ - triggerId: 'linear_project_updated_v2', - eventType: 'Project (update)', - }), - - outputs: buildProjectOutputs(), - - webhook: { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - 'Linear-Event': 'Project', - 'Linear-Delivery': 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx', - 'Linear-Signature': 'sha256...', - 'User-Agent': 'Linear-Webhook', - }, - }, -} diff --git a/apps/sim/triggers/linear/utils.ts b/apps/sim/triggers/linear/utils.ts index de9f9122275..ffc2ab0c385 100644 --- a/apps/sim/triggers/linear/utils.ts +++ b/apps/sim/triggers/linear/utils.ts @@ -84,7 +84,6 @@ export function linearSetupInstructions(eventType: string, additionalNotes?: str export function linearV2SetupInstructions(eventType: string, additionalNotes?: string): string { const instructions = [ 'Enter your Linear API Key above. You can create one in Linear at Settings > API > Personal API keys.', - 'Optionally enter a Team ID to scope the webhook to a single team. Leave it empty to receive events from all public teams. You can find Team IDs in Linear under Settings > Teams or via the API.', `Click "Save Configuration" to automatically create the webhook in Linear for ${eventType} events.`, 'The webhook will be automatically deleted when you remove this trigger.', ] @@ -161,15 +160,6 @@ export function buildLinearV2SubBlocks(options: { condition: { field: 'selectedTriggerId', value: triggerId }, }) - blocks.push({ - id: 'teamId', - title: 'Team ID', - type: 'short-input', - placeholder: 'All teams (optional)', - mode: 'trigger', - condition: { field: 'selectedTriggerId', value: triggerId }, - }) - blocks.push({ id: 'triggerSave', title: '', @@ -194,8 +184,8 @@ export function buildLinearV2SubBlocks(options: { } /** - * Shared user/actor output schema (Linear data-change webhook `actor` object). - * @see https://linear.app/developers/webhooks — actor may be a User, OauthClient, or Integration; `type` is mapped to `actorType` (TriggerOutput reserves nested `type` for field kinds). + * Shared user/actor output schema + * Note: Linear webhooks only include id, name, and type in actor objects */ export const userOutputs = { id: { @@ -206,18 +196,9 @@ export const userOutputs = { type: 'string', description: 'User display name', }, - /** Linear sends this as `actor.type`; exposed as `actorType` here (TriggerOutput reserves `type`). */ - actorType: { - type: 'string', - description: 'Actor type from Linear (e.g. user, OauthClient, Integration)', - }, - email: { - type: 'string', - description: 'Actor email (present for user actors in Linear webhook payloads)', - }, - url: { + user_type: { type: 'string', - description: 'Actor profile URL in Linear (distinct from the top-level subject entity `url`)', + description: 'Actor type (user, bot, etc.)', }, } as const @@ -306,10 +287,6 @@ export function buildIssueOutputs(): Record { type: 'string', description: 'Event creation timestamp', }, - url: { - type: 'string', - description: 'URL of the subject entity in Linear (top-level webhook payload)', - }, actor: userOutputs, data: { id: { @@ -489,10 +466,6 @@ export function buildCommentOutputs(): Record { type: 'string', description: 'Event creation timestamp', }, - url: { - type: 'string', - description: 'URL of the subject entity in Linear (top-level webhook payload)', - }, actor: userOutputs, data: { id: { @@ -503,10 +476,6 @@ export function buildCommentOutputs(): Record { type: 'string', description: 'Comment body text', }, - edited: { - type: 'boolean', - description: 'Whether the comment body has been edited (Linear webhook payload field)', - }, url: { type: 'string', description: 'Comment URL', @@ -584,10 +553,6 @@ export function buildProjectOutputs(): Record { type: 'string', description: 'Event creation timestamp', }, - url: { - type: 'string', - description: 'URL of the subject entity in Linear (top-level webhook payload)', - }, actor: userOutputs, data: { id: { @@ -731,10 +696,6 @@ export function buildCycleOutputs(): Record { type: 'string', description: 'Event creation timestamp', }, - url: { - type: 'string', - description: 'URL of the subject entity in Linear (top-level webhook payload)', - }, actor: userOutputs, data: { id: { @@ -838,10 +799,6 @@ export function buildLabelOutputs(): Record { type: 'string', description: 'Event creation timestamp', }, - url: { - type: 'string', - description: 'URL of the subject entity in Linear (top-level webhook payload)', - }, actor: userOutputs, data: { id: { @@ -929,10 +886,6 @@ export function buildProjectUpdateOutputs(): Record { type: 'string', description: 'Event creation timestamp', }, - url: { - type: 'string', - description: 'URL of the subject entity in Linear (top-level webhook payload)', - }, actor: userOutputs, data: { id: { @@ -1008,10 +961,6 @@ export function buildCustomerRequestOutputs(): Record { type: 'string', description: 'Event creation timestamp', }, - url: { - type: 'string', - description: 'URL of the subject entity in Linear (top-level webhook payload)', - }, actor: userOutputs, data: { id: { @@ -1090,7 +1039,7 @@ export function isLinearEventMatch(triggerId: string, eventType: string, action? const normalizedId = triggerId.replace(/_v2$/, '') const config = eventMap[normalizedId] if (!config) { - return false + return true // Unknown trigger, allow through } // Check event type diff --git a/apps/sim/triggers/linear/webhook.ts b/apps/sim/triggers/linear/webhook.ts index cf6eef2d09a..83ad6d6a25d 100644 --- a/apps/sim/triggers/linear/webhook.ts +++ b/apps/sim/triggers/linear/webhook.ts @@ -1,5 +1,9 @@ import { LinearIcon } from '@/components/icons' -import { linearSetupInstructions, userOutputs } from '@/triggers/linear/utils' +import { + buildLinearV2SubBlocks, + linearSetupInstructions, + userOutputs, +} from '@/triggers/linear/utils' import type { TriggerConfig } from '@/triggers/types' export const linearWebhookTrigger: TriggerConfig = { @@ -120,3 +124,68 @@ export const linearWebhookTrigger: TriggerConfig = { }, }, } + +export const linearWebhookV2Trigger: TriggerConfig = { + id: 'linear_webhook_v2', + name: 'Linear Webhook', + provider: 'linear', + description: + 'Trigger workflow from Linear events you select when creating the webhook in Linear (not guaranteed to be every model or event type).', + version: '2.0.0', + icon: LinearIcon, + subBlocks: buildLinearV2SubBlocks({ + triggerId: 'linear_webhook_v2', + eventType: 'All Events', + additionalNotes: + 'This webhook will receive all Linear events. Use the type and action fields in the payload to filter and handle different event types.', + }), + outputs: { + action: { + type: 'string', + description: 'Action performed (create, update, remove)', + }, + type: { + type: 'string', + description: 'Entity type (Issue, Comment, Project, Cycle, IssueLabel, ProjectUpdate, etc.)', + }, + webhookId: { + type: 'string', + description: 'Webhook ID', + }, + webhookTimestamp: { + type: 'number', + description: 'Webhook timestamp (milliseconds)', + }, + organizationId: { + type: 'string', + description: 'Organization ID', + }, + createdAt: { + type: 'string', + description: 'Event creation timestamp', + }, + url: { + type: 'string', + description: 'URL of the subject entity in Linear (top-level webhook payload)', + }, + actor: userOutputs, + data: { + type: 'object', + description: 'Complete entity data object', + }, + updatedFrom: { + type: 'object', + description: 'Previous values for changed fields (only present on update)', + }, + }, + webhook: { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + 'Linear-Event': 'Issue', + 'Linear-Delivery': 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx', + 'Linear-Signature': 'sha256...', + 'User-Agent': 'Linear-Webhook', + }, + }, +} diff --git a/apps/sim/triggers/linear/webhook_v2.ts b/apps/sim/triggers/linear/webhook_v2.ts deleted file mode 100644 index 567c47213bb..00000000000 --- a/apps/sim/triggers/linear/webhook_v2.ts +++ /dev/null @@ -1,71 +0,0 @@ -import { LinearIcon } from '@/components/icons' -import { buildLinearV2SubBlocks, userOutputs } from '@/triggers/linear/utils' -import type { TriggerConfig } from '@/triggers/types' - -export const linearWebhookV2Trigger: TriggerConfig = { - id: 'linear_webhook_v2', - name: 'Linear Webhook', - provider: 'linear', - description: - 'Trigger workflow from Linear data-change events included in this webhook subscription (Issues, Comments, Projects, etc.—not every Linear model).', - version: '2.0.0', - icon: LinearIcon, - - subBlocks: buildLinearV2SubBlocks({ - triggerId: 'linear_webhook_v2', - eventType: 'All Events', - additionalNotes: - 'Sim registers this webhook for Issues, Comments, Projects, Cycles, Issue labels, Project updates, and Customer requests—matching what the Linear API allows in one subscription. It does not include every model Linear documents separately (e.g. Documents, Reactions). Use type and action in the payload to filter.', - }), - - outputs: { - action: { - type: 'string', - description: 'Action performed (create, update, remove)', - }, - type: { - type: 'string', - description: 'Entity type (Issue, Comment, Project, Cycle, IssueLabel, ProjectUpdate, etc.)', - }, - webhookId: { - type: 'string', - description: 'Webhook ID', - }, - webhookTimestamp: { - type: 'number', - description: 'Webhook timestamp (milliseconds)', - }, - organizationId: { - type: 'string', - description: 'Organization ID', - }, - createdAt: { - type: 'string', - description: 'Event creation timestamp', - }, - url: { - type: 'string', - description: 'URL of the subject entity in Linear (top-level webhook payload)', - }, - actor: userOutputs, - data: { - type: 'object', - description: 'Complete entity data object', - }, - updatedFrom: { - type: 'object', - description: 'Previous values for changed fields (only present on update)', - }, - }, - - webhook: { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - 'Linear-Event': 'Issue', - 'Linear-Delivery': '234d1a4e-b617-4388-90fe-adc3633d6b72', - 'Linear-Signature': '766e1d90a96e2f5ecec342a99c5552999dd95d49250171b902d703fd674f5086', - 'User-Agent': 'Linear-Webhook', - }, - }, -} diff --git a/apps/sim/triggers/registry.ts b/apps/sim/triggers/registry.ts index 6db1582457c..424a0a6abb4 100644 --- a/apps/sim/triggers/registry.ts +++ b/apps/sim/triggers/registry.ts @@ -89,7 +89,6 @@ import { githubWorkflowRunTrigger, } from '@/triggers/github' import { gmailPollingTrigger } from '@/triggers/gmail' -import { gongCallCompletedTrigger, gongWebhookTrigger } from '@/triggers/gong' import { googleFormsWebhookTrigger } from '@/triggers/googleforms' import { grainHighlightCreatedTrigger, @@ -101,28 +100,14 @@ import { grainStoryCreatedTrigger, grainWebhookTrigger, } from '@/triggers/grain' -import { - greenhouseCandidateHiredTrigger, - greenhouseCandidateRejectedTrigger, - greenhouseCandidateStageChangeTrigger, - greenhouseJobCreatedTrigger, - greenhouseJobUpdatedTrigger, - greenhouseNewApplicationTrigger, - greenhouseOfferCreatedTrigger, - greenhouseWebhookTrigger, -} from '@/triggers/greenhouse' import { hubspotCompanyCreatedTrigger, hubspotCompanyDeletedTrigger, - hubspotCompanyMergedTrigger, hubspotCompanyPropertyChangedTrigger, - hubspotCompanyRestoredTrigger, hubspotContactCreatedTrigger, hubspotContactDeletedTrigger, - hubspotContactMergedTrigger, hubspotContactPrivacyDeletedTrigger, hubspotContactPropertyChangedTrigger, - hubspotContactRestoredTrigger, hubspotConversationCreationTrigger, hubspotConversationDeletionTrigger, hubspotConversationNewMessageTrigger, @@ -130,25 +115,12 @@ import { hubspotConversationPropertyChangedTrigger, hubspotDealCreatedTrigger, hubspotDealDeletedTrigger, - hubspotDealMergedTrigger, hubspotDealPropertyChangedTrigger, - hubspotDealRestoredTrigger, hubspotTicketCreatedTrigger, hubspotTicketDeletedTrigger, - hubspotTicketMergedTrigger, hubspotTicketPropertyChangedTrigger, - hubspotTicketRestoredTrigger, - hubspotWebhookTrigger, } from '@/triggers/hubspot' import { imapPollingTrigger } from '@/triggers/imap' -import { - intercomContactCreatedTrigger, - intercomConversationClosedTrigger, - intercomConversationCreatedTrigger, - intercomConversationReplyTrigger, - intercomUserCreatedTrigger, - intercomWebhookTrigger, -} from '@/triggers/intercom' import { jiraIssueCommentedTrigger, jiraIssueCreatedTrigger, @@ -204,53 +176,14 @@ import { microsoftTeamsChatSubscriptionTrigger, microsoftTeamsWebhookTrigger, } from '@/triggers/microsoftteams' -import { - notionCommentCreatedTrigger, - notionDatabaseCreatedTrigger, - notionDatabaseDeletedTrigger, - notionDatabaseSchemaUpdatedTrigger, - notionPageContentUpdatedTrigger, - notionPageCreatedTrigger, - notionPageDeletedTrigger, - notionPagePropertiesUpdatedTrigger, - notionWebhookTrigger, -} from '@/triggers/notion' import { outlookPollingTrigger } from '@/triggers/outlook' -import { - resendEmailBouncedTrigger, - resendEmailClickedTrigger, - resendEmailComplainedTrigger, - resendEmailDeliveredTrigger, - resendEmailFailedTrigger, - resendEmailOpenedTrigger, - resendEmailSentTrigger, - resendWebhookTrigger, -} from '@/triggers/resend' import { rssPollingTrigger } from '@/triggers/rss' -import { - salesforceCaseStatusChangedTrigger, - salesforceOpportunityStageChangedTrigger, - salesforceRecordCreatedTrigger, - salesforceRecordDeletedTrigger, - salesforceRecordUpdatedTrigger, - salesforceWebhookTrigger, -} from '@/triggers/salesforce' import { slackWebhookTrigger } from '@/triggers/slack' import { stripeWebhookTrigger } from '@/triggers/stripe' import { telegramWebhookTrigger } from '@/triggers/telegram' import { twilioVoiceWebhookTrigger } from '@/triggers/twilio_voice' import { typeformWebhookTrigger } from '@/triggers/typeform' import type { TriggerRegistry } from '@/triggers/types' -import { - vercelDeploymentCanceledTrigger, - vercelDeploymentCreatedTrigger, - vercelDeploymentErrorTrigger, - vercelDeploymentReadyTrigger, - vercelDomainCreatedTrigger, - vercelProjectCreatedTrigger, - vercelProjectRemovedTrigger, - vercelWebhookTrigger, -} from '@/triggers/vercel' import { webflowCollectionItemChangedTrigger, webflowCollectionItemCreatedTrigger, @@ -258,14 +191,6 @@ import { webflowFormSubmissionTrigger, } from '@/triggers/webflow' import { whatsappWebhookTrigger } from '@/triggers/whatsapp' -import { - zoomMeetingEndedTrigger, - zoomMeetingStartedTrigger, - zoomParticipantJoinedTrigger, - zoomParticipantLeftTrigger, - zoomRecordingCompletedTrigger, - zoomWebhookTrigger, -} from '@/triggers/zoom' export const TRIGGER_REGISTRY: TriggerRegistry = { slack_webhook: slackWebhookTrigger, @@ -328,14 +253,6 @@ export const TRIGGER_REGISTRY: TriggerRegistry = { confluence_label_added: confluenceLabelAddedTrigger, confluence_label_removed: confluenceLabelRemovedTrigger, generic_webhook: genericWebhookTrigger, - greenhouse_candidate_hired: greenhouseCandidateHiredTrigger, - greenhouse_new_application: greenhouseNewApplicationTrigger, - greenhouse_candidate_stage_change: greenhouseCandidateStageChangeTrigger, - greenhouse_candidate_rejected: greenhouseCandidateRejectedTrigger, - greenhouse_offer_created: greenhouseOfferCreatedTrigger, - greenhouse_job_created: greenhouseJobCreatedTrigger, - greenhouse_job_updated: greenhouseJobUpdatedTrigger, - greenhouse_webhook: greenhouseWebhookTrigger, github_webhook: githubWebhookTrigger, github_issue_opened: githubIssueOpenedTrigger, github_issue_closed: githubIssueClosedTrigger, @@ -352,8 +269,6 @@ export const TRIGGER_REGISTRY: TriggerRegistry = { fathom_new_meeting: fathomNewMeetingTrigger, fathom_webhook: fathomWebhookTrigger, gmail_poller: gmailPollingTrigger, - gong_call_completed: gongCallCompletedTrigger, - gong_webhook: gongWebhookTrigger, grain_webhook: grainWebhookTrigger, grain_item_added: grainItemAddedTrigger, grain_item_updated: grainItemUpdatedTrigger, @@ -412,60 +327,25 @@ export const TRIGGER_REGISTRY: TriggerRegistry = { linear_customer_request_updated_v2: linearCustomerRequestUpdatedV2Trigger, microsoftteams_webhook: microsoftTeamsWebhookTrigger, microsoftteams_chat_subscription: microsoftTeamsChatSubscriptionTrigger, - notion_page_created: notionPageCreatedTrigger, - notion_page_properties_updated: notionPagePropertiesUpdatedTrigger, - notion_page_content_updated: notionPageContentUpdatedTrigger, - notion_page_deleted: notionPageDeletedTrigger, - notion_database_created: notionDatabaseCreatedTrigger, - notion_database_schema_updated: notionDatabaseSchemaUpdatedTrigger, - notion_database_deleted: notionDatabaseDeletedTrigger, - notion_comment_created: notionCommentCreatedTrigger, - notion_webhook: notionWebhookTrigger, outlook_poller: outlookPollingTrigger, - resend_email_sent: resendEmailSentTrigger, - resend_email_delivered: resendEmailDeliveredTrigger, - resend_email_bounced: resendEmailBouncedTrigger, - resend_email_complained: resendEmailComplainedTrigger, - resend_email_opened: resendEmailOpenedTrigger, - resend_email_clicked: resendEmailClickedTrigger, - resend_email_failed: resendEmailFailedTrigger, - resend_webhook: resendWebhookTrigger, rss_poller: rssPollingTrigger, - salesforce_record_created: salesforceRecordCreatedTrigger, - salesforce_record_updated: salesforceRecordUpdatedTrigger, - salesforce_record_deleted: salesforceRecordDeletedTrigger, - salesforce_opportunity_stage_changed: salesforceOpportunityStageChangedTrigger, - salesforce_case_status_changed: salesforceCaseStatusChangedTrigger, - salesforce_webhook: salesforceWebhookTrigger, stripe_webhook: stripeWebhookTrigger, telegram_webhook: telegramWebhookTrigger, typeform_webhook: typeformWebhookTrigger, whatsapp_webhook: whatsappWebhookTrigger, google_forms_webhook: googleFormsWebhookTrigger, twilio_voice_webhook: twilioVoiceWebhookTrigger, - vercel_deployment_created: vercelDeploymentCreatedTrigger, - vercel_deployment_ready: vercelDeploymentReadyTrigger, - vercel_deployment_error: vercelDeploymentErrorTrigger, - vercel_deployment_canceled: vercelDeploymentCanceledTrigger, - vercel_project_created: vercelProjectCreatedTrigger, - vercel_project_removed: vercelProjectRemovedTrigger, - vercel_domain_created: vercelDomainCreatedTrigger, - vercel_webhook: vercelWebhookTrigger, webflow_collection_item_created: webflowCollectionItemCreatedTrigger, webflow_collection_item_changed: webflowCollectionItemChangedTrigger, webflow_collection_item_deleted: webflowCollectionItemDeletedTrigger, webflow_form_submission: webflowFormSubmissionTrigger, hubspot_contact_created: hubspotContactCreatedTrigger, hubspot_contact_deleted: hubspotContactDeletedTrigger, - hubspot_contact_merged: hubspotContactMergedTrigger, hubspot_contact_privacy_deleted: hubspotContactPrivacyDeletedTrigger, hubspot_contact_property_changed: hubspotContactPropertyChangedTrigger, - hubspot_contact_restored: hubspotContactRestoredTrigger, hubspot_company_created: hubspotCompanyCreatedTrigger, hubspot_company_deleted: hubspotCompanyDeletedTrigger, - hubspot_company_merged: hubspotCompanyMergedTrigger, hubspot_company_property_changed: hubspotCompanyPropertyChangedTrigger, - hubspot_company_restored: hubspotCompanyRestoredTrigger, hubspot_conversation_creation: hubspotConversationCreationTrigger, hubspot_conversation_deletion: hubspotConversationDeletionTrigger, hubspot_conversation_new_message: hubspotConversationNewMessageTrigger, @@ -473,26 +353,9 @@ export const TRIGGER_REGISTRY: TriggerRegistry = { hubspot_conversation_property_changed: hubspotConversationPropertyChangedTrigger, hubspot_deal_created: hubspotDealCreatedTrigger, hubspot_deal_deleted: hubspotDealDeletedTrigger, - hubspot_deal_merged: hubspotDealMergedTrigger, hubspot_deal_property_changed: hubspotDealPropertyChangedTrigger, - hubspot_deal_restored: hubspotDealRestoredTrigger, hubspot_ticket_created: hubspotTicketCreatedTrigger, hubspot_ticket_deleted: hubspotTicketDeletedTrigger, - hubspot_ticket_merged: hubspotTicketMergedTrigger, hubspot_ticket_property_changed: hubspotTicketPropertyChangedTrigger, - hubspot_ticket_restored: hubspotTicketRestoredTrigger, - hubspot_webhook: hubspotWebhookTrigger, imap_poller: imapPollingTrigger, - intercom_conversation_created: intercomConversationCreatedTrigger, - intercom_conversation_reply: intercomConversationReplyTrigger, - intercom_conversation_closed: intercomConversationClosedTrigger, - intercom_contact_created: intercomContactCreatedTrigger, - intercom_user_created: intercomUserCreatedTrigger, - intercom_webhook: intercomWebhookTrigger, - zoom_meeting_started: zoomMeetingStartedTrigger, - zoom_meeting_ended: zoomMeetingEndedTrigger, - zoom_participant_joined: zoomParticipantJoinedTrigger, - zoom_participant_left: zoomParticipantLeftTrigger, - zoom_recording_completed: zoomRecordingCompletedTrigger, - zoom_webhook: zoomWebhookTrigger, } From 6ab4485a0bb50ec722db0d19186eb1df587af769 Mon Sep 17 00:00:00 2001 From: Waleed Latif Date: Mon, 6 Apr 2026 21:16:21 -0700 Subject: [PATCH 02/11] updated --- .../integrations/data/integrations.json | 80 +------------------ 1 file changed, 2 insertions(+), 78 deletions(-) diff --git a/apps/sim/app/(landing)/integrations/data/integrations.json b/apps/sim/app/(landing)/integrations/data/integrations.json index 9a89658f1ff..14c3999d291 100644 --- a/apps/sim/app/(landing)/integrations/data/integrations.json +++ b/apps/sim/app/(landing)/integrations/data/integrations.json @@ -7182,84 +7182,8 @@ } ], "operationCount": 78, - "triggers": [ - { - "id": "linear_issue_created_v2", - "name": "Linear Issue Created", - "description": "Trigger workflow when a new issue is created in Linear" - }, - { - "id": "linear_issue_updated_v2", - "name": "Linear Issue Updated", - "description": "Trigger workflow when an issue is updated in Linear" - }, - { - "id": "linear_issue_removed_v2", - "name": "Linear Issue Removed", - "description": "Trigger workflow when an issue is removed/deleted in Linear" - }, - { - "id": "linear_comment_created_v2", - "name": "Linear Comment Created", - "description": "Trigger workflow when a new comment is created in Linear" - }, - { - "id": "linear_comment_updated_v2", - "name": "Linear Comment Updated", - "description": "Trigger workflow when a comment is updated in Linear" - }, - { - "id": "linear_project_created_v2", - "name": "Linear Project Created", - "description": "Trigger workflow when a new project is created in Linear" - }, - { - "id": "linear_project_updated_v2", - "name": "Linear Project Updated", - "description": "Trigger workflow when a project is updated in Linear" - }, - { - "id": "linear_cycle_created_v2", - "name": "Linear Cycle Created", - "description": "Trigger workflow when a new cycle is created in Linear" - }, - { - "id": "linear_cycle_updated_v2", - "name": "Linear Cycle Updated", - "description": "Trigger workflow when a cycle is updated in Linear" - }, - { - "id": "linear_label_created_v2", - "name": "Linear Label Created", - "description": "Trigger workflow when a new label is created in Linear" - }, - { - "id": "linear_label_updated_v2", - "name": "Linear Label Updated", - "description": "Trigger workflow when a label is updated in Linear" - }, - { - "id": "linear_project_update_created_v2", - "name": "Linear Project Update Created", - "description": "Trigger workflow when a new project update is posted in Linear" - }, - { - "id": "linear_customer_request_created_v2", - "name": "Linear Customer Request Created", - "description": "Trigger workflow when a new customer request is created in Linear" - }, - { - "id": "linear_customer_request_updated_v2", - "name": "Linear Customer Request Updated", - "description": "Trigger workflow when a customer request is updated in Linear" - }, - { - "id": "linear_webhook_v2", - "name": "Linear Webhook", - "description": "Trigger workflow from Linear data-change events included in this webhook subscription (Issues, Comments, Projects, etc.—not every Linear model)." - } - ], - "triggerCount": 15, + "triggers": [], + "triggerCount": 0, "authType": "oauth", "category": "tools", "integrationType": "productivity", From cb605d7353c675107fbc64cdc0529a9bc0c0883a Mon Sep 17 00:00:00 2001 From: Waleed Latif Date: Mon, 6 Apr 2026 21:19:39 -0700 Subject: [PATCH 03/11] fix: restore staging registry entries accidentally removed Co-Authored-By: Claude Opus 4.6 --- .../integrations/data/integrations.json | 80 +++++++++- apps/sim/blocks/registry.ts | 2 + apps/sim/triggers/registry.ts | 137 ++++++++++++++++++ 3 files changed, 217 insertions(+), 2 deletions(-) diff --git a/apps/sim/app/(landing)/integrations/data/integrations.json b/apps/sim/app/(landing)/integrations/data/integrations.json index 14c3999d291..9a89658f1ff 100644 --- a/apps/sim/app/(landing)/integrations/data/integrations.json +++ b/apps/sim/app/(landing)/integrations/data/integrations.json @@ -7182,8 +7182,84 @@ } ], "operationCount": 78, - "triggers": [], - "triggerCount": 0, + "triggers": [ + { + "id": "linear_issue_created_v2", + "name": "Linear Issue Created", + "description": "Trigger workflow when a new issue is created in Linear" + }, + { + "id": "linear_issue_updated_v2", + "name": "Linear Issue Updated", + "description": "Trigger workflow when an issue is updated in Linear" + }, + { + "id": "linear_issue_removed_v2", + "name": "Linear Issue Removed", + "description": "Trigger workflow when an issue is removed/deleted in Linear" + }, + { + "id": "linear_comment_created_v2", + "name": "Linear Comment Created", + "description": "Trigger workflow when a new comment is created in Linear" + }, + { + "id": "linear_comment_updated_v2", + "name": "Linear Comment Updated", + "description": "Trigger workflow when a comment is updated in Linear" + }, + { + "id": "linear_project_created_v2", + "name": "Linear Project Created", + "description": "Trigger workflow when a new project is created in Linear" + }, + { + "id": "linear_project_updated_v2", + "name": "Linear Project Updated", + "description": "Trigger workflow when a project is updated in Linear" + }, + { + "id": "linear_cycle_created_v2", + "name": "Linear Cycle Created", + "description": "Trigger workflow when a new cycle is created in Linear" + }, + { + "id": "linear_cycle_updated_v2", + "name": "Linear Cycle Updated", + "description": "Trigger workflow when a cycle is updated in Linear" + }, + { + "id": "linear_label_created_v2", + "name": "Linear Label Created", + "description": "Trigger workflow when a new label is created in Linear" + }, + { + "id": "linear_label_updated_v2", + "name": "Linear Label Updated", + "description": "Trigger workflow when a label is updated in Linear" + }, + { + "id": "linear_project_update_created_v2", + "name": "Linear Project Update Created", + "description": "Trigger workflow when a new project update is posted in Linear" + }, + { + "id": "linear_customer_request_created_v2", + "name": "Linear Customer Request Created", + "description": "Trigger workflow when a new customer request is created in Linear" + }, + { + "id": "linear_customer_request_updated_v2", + "name": "Linear Customer Request Updated", + "description": "Trigger workflow when a customer request is updated in Linear" + }, + { + "id": "linear_webhook_v2", + "name": "Linear Webhook", + "description": "Trigger workflow from Linear data-change events included in this webhook subscription (Issues, Comments, Projects, etc.—not every Linear model)." + } + ], + "triggerCount": 15, "authType": "oauth", "category": "tools", "integrationType": "productivity", diff --git a/apps/sim/blocks/registry.ts b/apps/sim/blocks/registry.ts index dd9ea3f72e5..e78578b176b 100644 --- a/apps/sim/blocks/registry.ts +++ b/apps/sim/blocks/registry.ts @@ -171,6 +171,7 @@ import { SftpBlock } from '@/blocks/blocks/sftp' import { SharepointBlock } from '@/blocks/blocks/sharepoint' import { ShopifyBlock } from '@/blocks/blocks/shopify' import { SimilarwebBlock } from '@/blocks/blocks/similarweb' +import { SixtyfourBlock } from '@/blocks/blocks/sixtyfour' import { SlackBlock } from '@/blocks/blocks/slack' import { SmtpBlock } from '@/blocks/blocks/smtp' import { SpotifyBlock } from '@/blocks/blocks/spotify' @@ -408,6 +409,7 @@ export const registry: Record = { sharepoint: SharepointBlock, shopify: ShopifyBlock, similarweb: SimilarwebBlock, + sixtyfour: SixtyfourBlock, slack: SlackBlock, smtp: SmtpBlock, spotify: SpotifyBlock, diff --git a/apps/sim/triggers/registry.ts b/apps/sim/triggers/registry.ts index 424a0a6abb4..6db1582457c 100644 --- a/apps/sim/triggers/registry.ts +++ b/apps/sim/triggers/registry.ts @@ -89,6 +89,7 @@ import { githubWorkflowRunTrigger, } from '@/triggers/github' import { gmailPollingTrigger } from '@/triggers/gmail' +import { gongCallCompletedTrigger, gongWebhookTrigger } from '@/triggers/gong' import { googleFormsWebhookTrigger } from '@/triggers/googleforms' import { grainHighlightCreatedTrigger, @@ -100,14 +101,28 @@ import { grainStoryCreatedTrigger, grainWebhookTrigger, } from '@/triggers/grain' +import { + greenhouseCandidateHiredTrigger, + greenhouseCandidateRejectedTrigger, + greenhouseCandidateStageChangeTrigger, + greenhouseJobCreatedTrigger, + greenhouseJobUpdatedTrigger, + greenhouseNewApplicationTrigger, + greenhouseOfferCreatedTrigger, + greenhouseWebhookTrigger, +} from '@/triggers/greenhouse' import { hubspotCompanyCreatedTrigger, hubspotCompanyDeletedTrigger, + hubspotCompanyMergedTrigger, hubspotCompanyPropertyChangedTrigger, + hubspotCompanyRestoredTrigger, hubspotContactCreatedTrigger, hubspotContactDeletedTrigger, + hubspotContactMergedTrigger, hubspotContactPrivacyDeletedTrigger, hubspotContactPropertyChangedTrigger, + hubspotContactRestoredTrigger, hubspotConversationCreationTrigger, hubspotConversationDeletionTrigger, hubspotConversationNewMessageTrigger, @@ -115,12 +130,25 @@ import { hubspotConversationPropertyChangedTrigger, hubspotDealCreatedTrigger, hubspotDealDeletedTrigger, + hubspotDealMergedTrigger, hubspotDealPropertyChangedTrigger, + hubspotDealRestoredTrigger, hubspotTicketCreatedTrigger, hubspotTicketDeletedTrigger, + hubspotTicketMergedTrigger, hubspotTicketPropertyChangedTrigger, + hubspotTicketRestoredTrigger, + hubspotWebhookTrigger, } from '@/triggers/hubspot' import { imapPollingTrigger } from '@/triggers/imap' +import { + intercomContactCreatedTrigger, + intercomConversationClosedTrigger, + intercomConversationCreatedTrigger, + intercomConversationReplyTrigger, + intercomUserCreatedTrigger, + intercomWebhookTrigger, +} from '@/triggers/intercom' import { jiraIssueCommentedTrigger, jiraIssueCreatedTrigger, @@ -176,14 +204,53 @@ import { microsoftTeamsChatSubscriptionTrigger, microsoftTeamsWebhookTrigger, } from '@/triggers/microsoftteams' +import { + notionCommentCreatedTrigger, + notionDatabaseCreatedTrigger, + notionDatabaseDeletedTrigger, + notionDatabaseSchemaUpdatedTrigger, + notionPageContentUpdatedTrigger, + notionPageCreatedTrigger, + notionPageDeletedTrigger, + notionPagePropertiesUpdatedTrigger, + notionWebhookTrigger, +} from '@/triggers/notion' import { outlookPollingTrigger } from '@/triggers/outlook' +import { + resendEmailBouncedTrigger, + resendEmailClickedTrigger, + resendEmailComplainedTrigger, + resendEmailDeliveredTrigger, + resendEmailFailedTrigger, + resendEmailOpenedTrigger, + resendEmailSentTrigger, + resendWebhookTrigger, +} from '@/triggers/resend' import { rssPollingTrigger } from '@/triggers/rss' +import { + salesforceCaseStatusChangedTrigger, + salesforceOpportunityStageChangedTrigger, + salesforceRecordCreatedTrigger, + salesforceRecordDeletedTrigger, + salesforceRecordUpdatedTrigger, + salesforceWebhookTrigger, +} from '@/triggers/salesforce' import { slackWebhookTrigger } from '@/triggers/slack' import { stripeWebhookTrigger } from '@/triggers/stripe' import { telegramWebhookTrigger } from '@/triggers/telegram' import { twilioVoiceWebhookTrigger } from '@/triggers/twilio_voice' import { typeformWebhookTrigger } from '@/triggers/typeform' import type { TriggerRegistry } from '@/triggers/types' +import { + vercelDeploymentCanceledTrigger, + vercelDeploymentCreatedTrigger, + vercelDeploymentErrorTrigger, + vercelDeploymentReadyTrigger, + vercelDomainCreatedTrigger, + vercelProjectCreatedTrigger, + vercelProjectRemovedTrigger, + vercelWebhookTrigger, +} from '@/triggers/vercel' import { webflowCollectionItemChangedTrigger, webflowCollectionItemCreatedTrigger, @@ -191,6 +258,14 @@ import { webflowFormSubmissionTrigger, } from '@/triggers/webflow' import { whatsappWebhookTrigger } from '@/triggers/whatsapp' +import { + zoomMeetingEndedTrigger, + zoomMeetingStartedTrigger, + zoomParticipantJoinedTrigger, + zoomParticipantLeftTrigger, + zoomRecordingCompletedTrigger, + zoomWebhookTrigger, +} from '@/triggers/zoom' export const TRIGGER_REGISTRY: TriggerRegistry = { slack_webhook: slackWebhookTrigger, @@ -253,6 +328,14 @@ export const TRIGGER_REGISTRY: TriggerRegistry = { confluence_label_added: confluenceLabelAddedTrigger, confluence_label_removed: confluenceLabelRemovedTrigger, generic_webhook: genericWebhookTrigger, + greenhouse_candidate_hired: greenhouseCandidateHiredTrigger, + greenhouse_new_application: greenhouseNewApplicationTrigger, + greenhouse_candidate_stage_change: greenhouseCandidateStageChangeTrigger, + greenhouse_candidate_rejected: greenhouseCandidateRejectedTrigger, + greenhouse_offer_created: greenhouseOfferCreatedTrigger, + greenhouse_job_created: greenhouseJobCreatedTrigger, + greenhouse_job_updated: greenhouseJobUpdatedTrigger, + greenhouse_webhook: greenhouseWebhookTrigger, github_webhook: githubWebhookTrigger, github_issue_opened: githubIssueOpenedTrigger, github_issue_closed: githubIssueClosedTrigger, @@ -269,6 +352,8 @@ export const TRIGGER_REGISTRY: TriggerRegistry = { fathom_new_meeting: fathomNewMeetingTrigger, fathom_webhook: fathomWebhookTrigger, gmail_poller: gmailPollingTrigger, + gong_call_completed: gongCallCompletedTrigger, + gong_webhook: gongWebhookTrigger, grain_webhook: grainWebhookTrigger, grain_item_added: grainItemAddedTrigger, grain_item_updated: grainItemUpdatedTrigger, @@ -327,25 +412,60 @@ export const TRIGGER_REGISTRY: TriggerRegistry = { linear_customer_request_updated_v2: linearCustomerRequestUpdatedV2Trigger, microsoftteams_webhook: microsoftTeamsWebhookTrigger, microsoftteams_chat_subscription: microsoftTeamsChatSubscriptionTrigger, + notion_page_created: notionPageCreatedTrigger, + notion_page_properties_updated: notionPagePropertiesUpdatedTrigger, + notion_page_content_updated: notionPageContentUpdatedTrigger, + notion_page_deleted: notionPageDeletedTrigger, + notion_database_created: notionDatabaseCreatedTrigger, + notion_database_schema_updated: notionDatabaseSchemaUpdatedTrigger, + notion_database_deleted: notionDatabaseDeletedTrigger, + notion_comment_created: notionCommentCreatedTrigger, + notion_webhook: notionWebhookTrigger, outlook_poller: outlookPollingTrigger, + resend_email_sent: resendEmailSentTrigger, + resend_email_delivered: resendEmailDeliveredTrigger, + resend_email_bounced: resendEmailBouncedTrigger, + resend_email_complained: resendEmailComplainedTrigger, + resend_email_opened: resendEmailOpenedTrigger, + resend_email_clicked: resendEmailClickedTrigger, + resend_email_failed: resendEmailFailedTrigger, + resend_webhook: resendWebhookTrigger, rss_poller: rssPollingTrigger, + salesforce_record_created: salesforceRecordCreatedTrigger, + salesforce_record_updated: salesforceRecordUpdatedTrigger, + salesforce_record_deleted: salesforceRecordDeletedTrigger, + salesforce_opportunity_stage_changed: salesforceOpportunityStageChangedTrigger, + salesforce_case_status_changed: salesforceCaseStatusChangedTrigger, + salesforce_webhook: salesforceWebhookTrigger, stripe_webhook: stripeWebhookTrigger, telegram_webhook: telegramWebhookTrigger, typeform_webhook: typeformWebhookTrigger, whatsapp_webhook: whatsappWebhookTrigger, google_forms_webhook: googleFormsWebhookTrigger, twilio_voice_webhook: twilioVoiceWebhookTrigger, + vercel_deployment_created: vercelDeploymentCreatedTrigger, + vercel_deployment_ready: vercelDeploymentReadyTrigger, + vercel_deployment_error: vercelDeploymentErrorTrigger, + vercel_deployment_canceled: vercelDeploymentCanceledTrigger, + vercel_project_created: vercelProjectCreatedTrigger, + vercel_project_removed: vercelProjectRemovedTrigger, + vercel_domain_created: vercelDomainCreatedTrigger, + vercel_webhook: vercelWebhookTrigger, webflow_collection_item_created: webflowCollectionItemCreatedTrigger, webflow_collection_item_changed: webflowCollectionItemChangedTrigger, webflow_collection_item_deleted: webflowCollectionItemDeletedTrigger, webflow_form_submission: webflowFormSubmissionTrigger, hubspot_contact_created: hubspotContactCreatedTrigger, hubspot_contact_deleted: hubspotContactDeletedTrigger, + hubspot_contact_merged: hubspotContactMergedTrigger, hubspot_contact_privacy_deleted: hubspotContactPrivacyDeletedTrigger, hubspot_contact_property_changed: hubspotContactPropertyChangedTrigger, + hubspot_contact_restored: hubspotContactRestoredTrigger, hubspot_company_created: hubspotCompanyCreatedTrigger, hubspot_company_deleted: hubspotCompanyDeletedTrigger, + hubspot_company_merged: hubspotCompanyMergedTrigger, hubspot_company_property_changed: hubspotCompanyPropertyChangedTrigger, + hubspot_company_restored: hubspotCompanyRestoredTrigger, hubspot_conversation_creation: hubspotConversationCreationTrigger, hubspot_conversation_deletion: hubspotConversationDeletionTrigger, hubspot_conversation_new_message: hubspotConversationNewMessageTrigger, @@ -353,9 +473,26 @@ export const TRIGGER_REGISTRY: TriggerRegistry = { hubspot_conversation_property_changed: hubspotConversationPropertyChangedTrigger, hubspot_deal_created: hubspotDealCreatedTrigger, hubspot_deal_deleted: hubspotDealDeletedTrigger, + hubspot_deal_merged: hubspotDealMergedTrigger, hubspot_deal_property_changed: hubspotDealPropertyChangedTrigger, + hubspot_deal_restored: hubspotDealRestoredTrigger, hubspot_ticket_created: hubspotTicketCreatedTrigger, hubspot_ticket_deleted: hubspotTicketDeletedTrigger, + hubspot_ticket_merged: hubspotTicketMergedTrigger, hubspot_ticket_property_changed: hubspotTicketPropertyChangedTrigger, + hubspot_ticket_restored: hubspotTicketRestoredTrigger, + hubspot_webhook: hubspotWebhookTrigger, imap_poller: imapPollingTrigger, + intercom_conversation_created: intercomConversationCreatedTrigger, + intercom_conversation_reply: intercomConversationReplyTrigger, + intercom_conversation_closed: intercomConversationClosedTrigger, + intercom_contact_created: intercomContactCreatedTrigger, + intercom_user_created: intercomUserCreatedTrigger, + intercom_webhook: intercomWebhookTrigger, + zoom_meeting_started: zoomMeetingStartedTrigger, + zoom_meeting_ended: zoomMeetingEndedTrigger, + zoom_participant_joined: zoomParticipantJoinedTrigger, + zoom_participant_left: zoomParticipantLeftTrigger, + zoom_recording_completed: zoomRecordingCompletedTrigger, + zoom_webhook: zoomWebhookTrigger, } From f3851f61046cb0037b5fb6aa4dddbdf598faa70e Mon Sep 17 00:00:00 2001 From: Waleed Latif Date: Mon, 6 Apr 2026 21:21:07 -0700 Subject: [PATCH 04/11] docs --- .../integrations/data/integrations.json | 80 +------------------ 1 file changed, 2 insertions(+), 78 deletions(-) diff --git a/apps/sim/app/(landing)/integrations/data/integrations.json b/apps/sim/app/(landing)/integrations/data/integrations.json index 9a89658f1ff..14c3999d291 100644 --- a/apps/sim/app/(landing)/integrations/data/integrations.json +++ b/apps/sim/app/(landing)/integrations/data/integrations.json @@ -7182,84 +7182,8 @@ } ], "operationCount": 78, - "triggers": [ - { - "id": "linear_issue_created_v2", - "name": "Linear Issue Created", - "description": "Trigger workflow when a new issue is created in Linear" - }, - { - "id": "linear_issue_updated_v2", - "name": "Linear Issue Updated", - "description": "Trigger workflow when an issue is updated in Linear" - }, - { - "id": "linear_issue_removed_v2", - "name": "Linear Issue Removed", - "description": "Trigger workflow when an issue is removed/deleted in Linear" - }, - { - "id": "linear_comment_created_v2", - "name": "Linear Comment Created", - "description": "Trigger workflow when a new comment is created in Linear" - }, - { - "id": "linear_comment_updated_v2", - "name": "Linear Comment Updated", - "description": "Trigger workflow when a comment is updated in Linear" - }, - { - "id": "linear_project_created_v2", - "name": "Linear Project Created", - "description": "Trigger workflow when a new project is created in Linear" - }, - { - "id": "linear_project_updated_v2", - "name": "Linear Project Updated", - "description": "Trigger workflow when a project is updated in Linear" - }, - { - "id": "linear_cycle_created_v2", - "name": "Linear Cycle Created", - "description": "Trigger workflow when a new cycle is created in Linear" - }, - { - "id": "linear_cycle_updated_v2", - "name": "Linear Cycle Updated", - "description": "Trigger workflow when a cycle is updated in Linear" - }, - { - "id": "linear_label_created_v2", - "name": "Linear Label Created", - "description": "Trigger workflow when a new label is created in Linear" - }, - { - "id": "linear_label_updated_v2", - "name": "Linear Label Updated", - "description": "Trigger workflow when a label is updated in Linear" - }, - { - "id": "linear_project_update_created_v2", - "name": "Linear Project Update Created", - "description": "Trigger workflow when a new project update is posted in Linear" - }, - { - "id": "linear_customer_request_created_v2", - "name": "Linear Customer Request Created", - "description": "Trigger workflow when a new customer request is created in Linear" - }, - { - "id": "linear_customer_request_updated_v2", - "name": "Linear Customer Request Updated", - "description": "Trigger workflow when a customer request is updated in Linear" - }, - { - "id": "linear_webhook_v2", - "name": "Linear Webhook", - "description": "Trigger workflow from Linear data-change events included in this webhook subscription (Issues, Comments, Projects, etc.—not every Linear model)." - } - ], - "triggerCount": 15, + "triggers": [], + "triggerCount": 0, "authType": "oauth", "category": "tools", "integrationType": "productivity", From eb19ec1c5fe3ab9ba2fe1c8ef69a81177862c869 Mon Sep 17 00:00:00 2001 From: Waleed Latif Date: Mon, 6 Apr 2026 21:23:34 -0700 Subject: [PATCH 05/11] fix: restore integrations.json to staging version Co-Authored-By: Claude Opus 4.6 --- .../integrations/data/integrations.json | 80 ++++++++++++++++++- 1 file changed, 78 insertions(+), 2 deletions(-) diff --git a/apps/sim/app/(landing)/integrations/data/integrations.json b/apps/sim/app/(landing)/integrations/data/integrations.json index 14c3999d291..9a89658f1ff 100644 --- a/apps/sim/app/(landing)/integrations/data/integrations.json +++ b/apps/sim/app/(landing)/integrations/data/integrations.json @@ -7182,8 +7182,84 @@ } ], "operationCount": 78, - "triggers": [], - "triggerCount": 0, + "triggers": [ + { + "id": "linear_issue_created_v2", + "name": "Linear Issue Created", + "description": "Trigger workflow when a new issue is created in Linear" + }, + { + "id": "linear_issue_updated_v2", + "name": "Linear Issue Updated", + "description": "Trigger workflow when an issue is updated in Linear" + }, + { + "id": "linear_issue_removed_v2", + "name": "Linear Issue Removed", + "description": "Trigger workflow when an issue is removed/deleted in Linear" + }, + { + "id": "linear_comment_created_v2", + "name": "Linear Comment Created", + "description": "Trigger workflow when a new comment is created in Linear" + }, + { + "id": "linear_comment_updated_v2", + "name": "Linear Comment Updated", + "description": "Trigger workflow when a comment is updated in Linear" + }, + { + "id": "linear_project_created_v2", + "name": "Linear Project Created", + "description": "Trigger workflow when a new project is created in Linear" + }, + { + "id": "linear_project_updated_v2", + "name": "Linear Project Updated", + "description": "Trigger workflow when a project is updated in Linear" + }, + { + "id": "linear_cycle_created_v2", + "name": "Linear Cycle Created", + "description": "Trigger workflow when a new cycle is created in Linear" + }, + { + "id": "linear_cycle_updated_v2", + "name": "Linear Cycle Updated", + "description": "Trigger workflow when a cycle is updated in Linear" + }, + { + "id": "linear_label_created_v2", + "name": "Linear Label Created", + "description": "Trigger workflow when a new label is created in Linear" + }, + { + "id": "linear_label_updated_v2", + "name": "Linear Label Updated", + "description": "Trigger workflow when a label is updated in Linear" + }, + { + "id": "linear_project_update_created_v2", + "name": "Linear Project Update Created", + "description": "Trigger workflow when a new project update is posted in Linear" + }, + { + "id": "linear_customer_request_created_v2", + "name": "Linear Customer Request Created", + "description": "Trigger workflow when a new customer request is created in Linear" + }, + { + "id": "linear_customer_request_updated_v2", + "name": "Linear Customer Request Updated", + "description": "Trigger workflow when a customer request is updated in Linear" + }, + { + "id": "linear_webhook_v2", + "name": "Linear Webhook", + "description": "Trigger workflow from Linear data-change events included in this webhook subscription (Issues, Comments, Projects, etc.—not every Linear model)." + } + ], + "triggerCount": 15, "authType": "oauth", "category": "tools", "integrationType": "productivity", From c48a704437f6fba2f06a989624e768fd63d7dfaa Mon Sep 17 00:00:00 2001 From: Waleed Latif Date: Mon, 6 Apr 2026 21:26:28 -0700 Subject: [PATCH 06/11] fix(generate-docs): extract all trigger configs from multi-export files The buildTriggerRegistry function used a single regex exec per file, which only captured the first TriggerConfig export. Files that export both v1 and v2 triggers (consolidated same-file convention) had their v2 triggers silently dropped from integrations.json. Split each file into segments per export and parse each independently. Co-Authored-By: Claude Opus 4.6 --- .../integrations/data/integrations.json | 22 +++++++--- scripts/generate-docs.ts | 40 ++++++++++++++----- 2 files changed, 46 insertions(+), 16 deletions(-) diff --git a/apps/sim/app/(landing)/integrations/data/integrations.json b/apps/sim/app/(landing)/integrations/data/integrations.json index 9a89658f1ff..1aedf79474f 100644 --- a/apps/sim/app/(landing)/integrations/data/integrations.json +++ b/apps/sim/app/(landing)/integrations/data/integrations.json @@ -4015,8 +4015,14 @@ } ], "operationCount": 12, - "triggers": [], - "triggerCount": 0, + "triggers": [ + { + "id": "gmail_poller", + "name": "Gmail Email Trigger", + "description": "Triggers when new emails are received in Gmail (requires Gmail credentials)" + } + ], + "triggerCount": 1, "authType": "oauth", "category": "tools", "integrationType": "email", @@ -7256,7 +7262,7 @@ { "id": "linear_webhook_v2", "name": "Linear Webhook", - "description": "Trigger workflow from Linear data-change events included in this webhook subscription (Issues, Comments, Projects, etc.—not every Linear model)." + "description": "Trigger workflow from Linear events you select when creating the webhook in Linear (not guaranteed to be every model or event type)." } ], "triggerCount": 15, @@ -8580,8 +8586,14 @@ } ], "operationCount": 9, - "triggers": [], - "triggerCount": 0, + "triggers": [ + { + "id": "outlook_poller", + "name": "Outlook Email Trigger", + "description": "Triggers when new emails are received in Outlook (requires Microsoft credentials)" + } + ], + "triggerCount": 1, "authType": "oauth", "category": "tools", "integrationType": "email", diff --git a/scripts/generate-docs.ts b/scripts/generate-docs.ts index 13a1c509dfa..49f2dcf8f1b 100755 --- a/scripts/generate-docs.ts +++ b/scripts/generate-docs.ts @@ -491,17 +491,35 @@ async function buildTriggerRegistry(): Promise> { try { const content = fs.readFileSync(file, 'utf-8') - // Each trigger file exports a single TriggerConfig with id, name, description - const idMatch = /\bid\s*:\s*['"]([^'"]+)['"]/.exec(content) - const nameMatch = /\bname\s*:\s*['"]([^'"]+)['"]/.exec(content) - const descMatch = /\bdescription\s*:\s*['"]([^'"]+)['"]/.exec(content) - - if (idMatch && nameMatch) { - registry.set(idMatch[1], { - id: idMatch[1], - name: nameMatch[1], - description: descMatch?.[1] ?? '', - }) + // A file may export multiple TriggerConfig objects (e.g. v1 + v2 in + // the same file). Extract all exported configs by splitting on the + // export boundaries and parsing each one independently. + const exportRegex = /export\s+const\s+\w+\s*:\s*TriggerConfig\s*=\s*\{/g + let exportMatch + const exportStarts: number[] = [] + + while ((exportMatch = exportRegex.exec(content)) !== null) { + exportStarts.push(exportMatch.index) + } + + // If no typed exports found, fall back to simple regex on whole file + const segments = + exportStarts.length > 0 + ? exportStarts.map((start, i) => content.substring(start, exportStarts[i + 1])) + : [content] + + for (const segment of segments) { + const idMatch = /\bid\s*:\s*['"]([^'"]+)['"]/.exec(segment) + const nameMatch = /\bname\s*:\s*['"]([^'"]+)['"]/.exec(segment) + const descMatch = /\bdescription\s*:\s*['"]([^'"]+)['"]/.exec(segment) + + if (idMatch && nameMatch) { + registry.set(idMatch[1], { + id: idMatch[1], + name: nameMatch[1], + description: descMatch?.[1] ?? '', + }) + } } } catch { // skip unreadable files silently From 9afb0bc34cdd70b7b128e5e4bf618308ed9ceba2 Mon Sep 17 00:00:00 2001 From: Waleed Latif Date: Mon, 6 Apr 2026 21:29:49 -0700 Subject: [PATCH 07/11] fix: restore staging linear handler and utils with teamId support Restores the staging version of linear provider handler and trigger utils that were accidentally regressed. Key restorations: - teamId sub-block and allPublicTeams fallback in createSubscription - Timestamp skew validation in verifyAuth - actorType renaming in formatInput (avoids TriggerOutput collision) - url field in formatInput and all output builders - edited field in comment outputs - externalId validation after webhook creation - isLinearEventMatch returns false (not true) for unknown triggers Adds extractIdempotencyId to the linear provider handler for webhook deduplication support. Co-Authored-By: Claude Opus 4.6 --- apps/sim/lib/webhooks/providers/linear.ts | 104 ++++++++++++++++++---- apps/sim/triggers/linear/utils.ts | 61 +++++++++++-- 2 files changed, 144 insertions(+), 21 deletions(-) diff --git a/apps/sim/lib/webhooks/providers/linear.ts b/apps/sim/lib/webhooks/providers/linear.ts index 255691effb2..07788b8059c 100644 --- a/apps/sim/lib/webhooks/providers/linear.ts +++ b/apps/sim/lib/webhooks/providers/linear.ts @@ -1,9 +1,11 @@ import crypto from 'crypto' import { createLogger } from '@sim/logger' +import { NextResponse } from 'next/server' import { safeCompare } from '@/lib/core/security/encryption' import { generateId } from '@/lib/core/utils/uuid' import { getNotificationUrl, getProviderConfig } from '@/lib/webhooks/provider-subscription-utils' import type { + AuthContext, DeleteSubscriptionContext, EventMatchContext, FormatInputContext, @@ -12,7 +14,6 @@ import type { SubscriptionResult, WebhookProviderHandler, } from '@/lib/webhooks/providers/types' -import { createHmacVerifier } from '@/lib/webhooks/providers/utils' const logger = createLogger('WebhookProvider:Linear') @@ -41,16 +42,73 @@ function validateLinearSignature(secret: string, signature: string, body: string } } +const LINEAR_WEBHOOK_TIMESTAMP_SKEW_MS = 5 * 60 * 1000 + export const linearHandler: WebhookProviderHandler = { - verifyAuth: createHmacVerifier({ - configKey: 'webhookSecret', - headerName: 'Linear-Signature', - validateFn: validateLinearSignature, - providerLabel: 'Linear', - }), + async verifyAuth({ + request, + rawBody, + requestId, + providerConfig, + }: AuthContext): Promise { + const secret = providerConfig.webhookSecret as string | undefined + if (!secret) { + return null + } + + const signature = request.headers.get('Linear-Signature') + if (!signature) { + logger.warn(`[${requestId}] Linear webhook missing signature header`) + return new NextResponse('Unauthorized - Missing Linear signature', { status: 401 }) + } + + if (!validateLinearSignature(secret, signature, rawBody)) { + logger.warn(`[${requestId}] Linear signature verification failed`) + return new NextResponse('Unauthorized - Invalid Linear signature', { status: 401 }) + } + + try { + const parsed = JSON.parse(rawBody) as Record + const ts = parsed.webhookTimestamp + if (typeof ts !== 'number' || !Number.isFinite(ts)) { + logger.warn(`[${requestId}] Linear webhookTimestamp missing or invalid`) + return new NextResponse('Unauthorized - Invalid webhook timestamp', { + status: 401, + }) + } + + if (Math.abs(Date.now() - ts) > LINEAR_WEBHOOK_TIMESTAMP_SKEW_MS) { + logger.warn( + `[${requestId}] Linear webhookTimestamp outside allowed skew (${LINEAR_WEBHOOK_TIMESTAMP_SKEW_MS}ms)` + ) + return new NextResponse('Unauthorized - Webhook timestamp skew too large', { + status: 401, + }) + } + } catch (error) { + logger.warn( + `[${requestId}] Linear webhook body parse failed after signature verification`, + error + ) + return new NextResponse('Unauthorized - Invalid webhook body', { status: 401 }) + } + + return null + }, async formatInput({ body }: FormatInputContext): Promise { const b = body as Record + const rawActor = b.actor + let actor: unknown = null + if (rawActor && typeof rawActor === 'object' && !Array.isArray(rawActor)) { + const a = rawActor as Record + const { type: linearActorType, ...rest } = a + actor = { + ...rest, + actorType: typeof linearActorType === 'string' ? linearActorType : null, + } + } + return { input: { action: b.action || '', @@ -59,7 +117,8 @@ export const linearHandler: WebhookProviderHandler = { webhookTimestamp: b.webhookTimestamp || 0, organizationId: b.organizationId || '', createdAt: b.createdAt || '', - actor: b.actor || null, + url: typeof b.url === 'string' ? b.url : '', + actor, data: b.data || null, updatedFrom: b.updatedFrom || null, }, @@ -108,6 +167,20 @@ export const linearHandler: WebhookProviderHandler = { const notificationUrl = getNotificationUrl(ctx.webhook) const webhookSecret = generateId() + const teamId = config.teamId as string | undefined + + const input: Record = { + url: notificationUrl, + resourceTypes, + secret: webhookSecret, + enabled: true, + } + + if (teamId) { + input.teamId = teamId + } else { + input.allPublicTeams = true + } try { const response = await fetch('https://api.linear.app/graphql', { @@ -123,14 +196,7 @@ export const linearHandler: WebhookProviderHandler = { webhook { id enabled } } }`, - variables: { - input: { - url: notificationUrl, - resourceTypes, - secret: webhookSecret, - enabled: true, - }, - }, + variables: { input }, }), }) @@ -153,6 +219,12 @@ export const linearHandler: WebhookProviderHandler = { } const externalId = result.webhook?.id + if (typeof externalId !== 'string' || !externalId.trim()) { + throw new Error( + 'Linear webhook was created but the API response did not include a webhook id.' + ) + } + logger.info( `[${ctx.requestId}] Created Linear webhook ${externalId} for webhook ${ctx.webhook.id}` ) diff --git a/apps/sim/triggers/linear/utils.ts b/apps/sim/triggers/linear/utils.ts index ffc2ab0c385..de9f9122275 100644 --- a/apps/sim/triggers/linear/utils.ts +++ b/apps/sim/triggers/linear/utils.ts @@ -84,6 +84,7 @@ export function linearSetupInstructions(eventType: string, additionalNotes?: str export function linearV2SetupInstructions(eventType: string, additionalNotes?: string): string { const instructions = [ 'Enter your Linear API Key above. You can create one in Linear at Settings > API > Personal API keys.', + 'Optionally enter a Team ID to scope the webhook to a single team. Leave it empty to receive events from all public teams. You can find Team IDs in Linear under Settings > Teams or via the API.', `Click "Save Configuration" to automatically create the webhook in Linear for ${eventType} events.`, 'The webhook will be automatically deleted when you remove this trigger.', ] @@ -160,6 +161,15 @@ export function buildLinearV2SubBlocks(options: { condition: { field: 'selectedTriggerId', value: triggerId }, }) + blocks.push({ + id: 'teamId', + title: 'Team ID', + type: 'short-input', + placeholder: 'All teams (optional)', + mode: 'trigger', + condition: { field: 'selectedTriggerId', value: triggerId }, + }) + blocks.push({ id: 'triggerSave', title: '', @@ -184,8 +194,8 @@ export function buildLinearV2SubBlocks(options: { } /** - * Shared user/actor output schema - * Note: Linear webhooks only include id, name, and type in actor objects + * Shared user/actor output schema (Linear data-change webhook `actor` object). + * @see https://linear.app/developers/webhooks — actor may be a User, OauthClient, or Integration; `type` is mapped to `actorType` (TriggerOutput reserves nested `type` for field kinds). */ export const userOutputs = { id: { @@ -196,9 +206,18 @@ export const userOutputs = { type: 'string', description: 'User display name', }, - user_type: { + /** Linear sends this as `actor.type`; exposed as `actorType` here (TriggerOutput reserves `type`). */ + actorType: { + type: 'string', + description: 'Actor type from Linear (e.g. user, OauthClient, Integration)', + }, + email: { + type: 'string', + description: 'Actor email (present for user actors in Linear webhook payloads)', + }, + url: { type: 'string', - description: 'Actor type (user, bot, etc.)', + description: 'Actor profile URL in Linear (distinct from the top-level subject entity `url`)', }, } as const @@ -287,6 +306,10 @@ export function buildIssueOutputs(): Record { type: 'string', description: 'Event creation timestamp', }, + url: { + type: 'string', + description: 'URL of the subject entity in Linear (top-level webhook payload)', + }, actor: userOutputs, data: { id: { @@ -466,6 +489,10 @@ export function buildCommentOutputs(): Record { type: 'string', description: 'Event creation timestamp', }, + url: { + type: 'string', + description: 'URL of the subject entity in Linear (top-level webhook payload)', + }, actor: userOutputs, data: { id: { @@ -476,6 +503,10 @@ export function buildCommentOutputs(): Record { type: 'string', description: 'Comment body text', }, + edited: { + type: 'boolean', + description: 'Whether the comment body has been edited (Linear webhook payload field)', + }, url: { type: 'string', description: 'Comment URL', @@ -553,6 +584,10 @@ export function buildProjectOutputs(): Record { type: 'string', description: 'Event creation timestamp', }, + url: { + type: 'string', + description: 'URL of the subject entity in Linear (top-level webhook payload)', + }, actor: userOutputs, data: { id: { @@ -696,6 +731,10 @@ export function buildCycleOutputs(): Record { type: 'string', description: 'Event creation timestamp', }, + url: { + type: 'string', + description: 'URL of the subject entity in Linear (top-level webhook payload)', + }, actor: userOutputs, data: { id: { @@ -799,6 +838,10 @@ export function buildLabelOutputs(): Record { type: 'string', description: 'Event creation timestamp', }, + url: { + type: 'string', + description: 'URL of the subject entity in Linear (top-level webhook payload)', + }, actor: userOutputs, data: { id: { @@ -886,6 +929,10 @@ export function buildProjectUpdateOutputs(): Record { type: 'string', description: 'Event creation timestamp', }, + url: { + type: 'string', + description: 'URL of the subject entity in Linear (top-level webhook payload)', + }, actor: userOutputs, data: { id: { @@ -961,6 +1008,10 @@ export function buildCustomerRequestOutputs(): Record { type: 'string', description: 'Event creation timestamp', }, + url: { + type: 'string', + description: 'URL of the subject entity in Linear (top-level webhook payload)', + }, actor: userOutputs, data: { id: { @@ -1039,7 +1090,7 @@ export function isLinearEventMatch(triggerId: string, eventType: string, action? const normalizedId = triggerId.replace(/_v2$/, '') const config = eventMap[normalizedId] if (!config) { - return true // Unknown trigger, allow through + return false } // Check event type From d69c50b31e1056742ec379ca58769f101164ccb0 Mon Sep 17 00:00:00 2001 From: Waleed Latif Date: Mon, 6 Apr 2026 21:30:41 -0700 Subject: [PATCH 08/11] fix: restore non-Linear files accidentally modified Co-Authored-By: Claude Opus 4.6 --- .../mothership-chat/mothership-chat.tsx | 30 ++----------------- .../home/components/user-input/user-input.tsx | 8 ++--- 2 files changed, 5 insertions(+), 33 deletions(-) diff --git a/apps/sim/app/workspace/[workspaceId]/home/components/mothership-chat/mothership-chat.tsx b/apps/sim/app/workspace/[workspaceId]/home/components/mothership-chat/mothership-chat.tsx index 21ff4756fcf..36e7d1348e6 100644 --- a/apps/sim/app/workspace/[workspaceId]/home/components/mothership-chat/mothership-chat.tsx +++ b/apps/sim/app/workspace/[workspaceId]/home/components/mothership-chat/mothership-chat.tsx @@ -1,6 +1,6 @@ 'use client' -import { useCallback, useEffect, useLayoutEffect, useRef } from 'react' +import { useCallback, useLayoutEffect, useRef } from 'react' import { cn } from '@/lib/core/utils/cn' import { MessageActions } from '@/app/workspace/[workspaceId]/components' import { ChatMessageAttachments } from '@/app/workspace/[workspaceId]/home/components/chat-message-attachments' @@ -99,41 +99,16 @@ export function MothershipChat({ const hasMessages = messages.length > 0 const initialScrollDoneRef = useRef(false) - const primedQueueIdRef = useRef(null) - const primeTimerRef = useRef | null>(null) const messageQueueRef = useRef(messageQueue) messageQueueRef.current = messageQueue const onSendQueuedMessageRef = useRef(onSendQueuedMessage) onSendQueuedMessageRef.current = onSendQueuedMessage - const clearPrimed = useCallback(() => { - primedQueueIdRef.current = null - if (primeTimerRef.current) { - clearTimeout(primeTimerRef.current) - primeTimerRef.current = null - } - }, []) - const handleEnterWhileEmpty = useCallback(() => { const topMessage = messageQueueRef.current[0] if (!topMessage) return false - - if (primedQueueIdRef.current === topMessage.id) { - clearPrimed() - void onSendQueuedMessageRef.current(topMessage.id) - return true - } - - primedQueueIdRef.current = topMessage.id - if (primeTimerRef.current) clearTimeout(primeTimerRef.current) - primeTimerRef.current = setTimeout(clearPrimed, 3000) + void onSendQueuedMessageRef.current(topMessage.id) return true - }, [clearPrimed]) - - useEffect(() => { - return () => { - if (primeTimerRef.current) clearTimeout(primeTimerRef.current) - } }, []) useLayoutEffect(() => { @@ -235,7 +210,6 @@ export function MothershipChat({ editValue={editValue} onEditValueConsumed={onEditValueConsumed} onEnterWhileEmpty={handleEnterWhileEmpty} - onPrimedDismiss={clearPrimed} /> diff --git a/apps/sim/app/workspace/[workspaceId]/home/components/user-input/user-input.tsx b/apps/sim/app/workspace/[workspaceId]/home/components/user-input/user-input.tsx index bbac9cbade5..d2415318b31 100644 --- a/apps/sim/app/workspace/[workspaceId]/home/components/user-input/user-input.tsx +++ b/apps/sim/app/workspace/[workspaceId]/home/components/user-input/user-input.tsx @@ -109,7 +109,6 @@ interface UserInputProps { userId?: string onContextAdd?: (context: ChatContext) => void onEnterWhileEmpty?: () => boolean - onPrimedDismiss?: () => void } export function UserInput({ @@ -123,7 +122,6 @@ export function UserInput({ userId, onContextAdd, onEnterWhileEmpty, - onPrimedDismiss, }: UserInputProps) { const { workspaceId } = useParams<{ workspaceId: string }>() const { data: workflowsById = {} } = useWorkflowMap(workspaceId) @@ -456,7 +454,8 @@ export function UserInput({ (e: React.KeyboardEvent) => { if (e.key === 'Enter' && !e.shiftKey && !e.nativeEvent.isComposing) { e.preventDefault() - if (isSendingRef.current && !valueRef.current.trim() && onEnterWhileEmptyRef.current?.()) { + if (isSendingRef.current && !valueRef.current.trim()) { + onEnterWhileEmptyRef.current?.() return } handleSubmit() @@ -551,9 +550,8 @@ export function UserInput({ setValue(newValue) restartRecognition(newValue) - if (newValue.trim()) onPrimedDismiss?.() }, - [restartRecognition, onPrimedDismiss] + [restartRecognition] ) const handleSelectAdjust = useCallback(() => { From 0c3121e720fcc335355b233e4e22d30730595482 Mon Sep 17 00:00:00 2001 From: Waleed Latif Date: Mon, 6 Apr 2026 21:42:37 -0700 Subject: [PATCH 09/11] refactor: remove redundant extractIdempotencyId from linear handler The idempotency service already uses the Linear-Delivery header (which Linear always sends) as the primary dedup key. The body-based fallback was unnecessary defensive code. Co-Authored-By: Claude Opus 4.6 --- apps/sim/lib/webhooks/providers/linear.ts | 9 --------- 1 file changed, 9 deletions(-) diff --git a/apps/sim/lib/webhooks/providers/linear.ts b/apps/sim/lib/webhooks/providers/linear.ts index 07788b8059c..97e9d79a877 100644 --- a/apps/sim/lib/webhooks/providers/linear.ts +++ b/apps/sim/lib/webhooks/providers/linear.ts @@ -293,13 +293,4 @@ export const linearHandler: WebhookProviderHandler = { }) } }, - - extractIdempotencyId(body: unknown) { - const obj = body as Record - const data = obj.data as Record | undefined - if (obj.action && data?.id) { - return `${obj.action}:${data.id}` - } - return null - }, } From ca3c7d0248da16fe0d4224437db06b494f903da7 Mon Sep 17 00:00:00 2001 From: Waleed Latif Date: Mon, 6 Apr 2026 22:01:39 -0700 Subject: [PATCH 10/11] idempotency --- apps/sim/lib/core/idempotency/service.ts | 4 ++- apps/sim/lib/webhooks/providers/ashby.ts | 9 +++++++ apps/sim/lib/webhooks/providers/gong.ts | 14 ++++++++++ apps/sim/lib/webhooks/providers/telegram.ts | 9 +++++++ apps/sim/lib/webhooks/providers/zoom.ts | 30 --------------------- 5 files changed, 35 insertions(+), 31 deletions(-) diff --git a/apps/sim/lib/core/idempotency/service.ts b/apps/sim/lib/core/idempotency/service.ts index 9c4961bd274..f5b59d3c8f8 100644 --- a/apps/sim/lib/core/idempotency/service.ts +++ b/apps/sim/lib/core/idempotency/service.ts @@ -422,7 +422,9 @@ export class IdempotencyService { normalizedHeaders?.['x-teams-notification-id'] || normalizedHeaders?.['svix-id'] || normalizedHeaders?.['linear-delivery'] || - normalizedHeaders?.['greenhouse-event-id'] + normalizedHeaders?.['greenhouse-event-id'] || + normalizedHeaders?.['x-zm-request-id'] || + normalizedHeaders?.['idempotency-key'] if (webhookIdHeader) { return `${webhookId}:${webhookIdHeader}` diff --git a/apps/sim/lib/webhooks/providers/ashby.ts b/apps/sim/lib/webhooks/providers/ashby.ts index b89d516c5cc..d7903af812f 100644 --- a/apps/sim/lib/webhooks/providers/ashby.ts +++ b/apps/sim/lib/webhooks/providers/ashby.ts @@ -33,6 +33,15 @@ function validateAshbySignature(secretToken: string, signature: string, body: st } export const ashbyHandler: WebhookProviderHandler = { + extractIdempotencyId(body: unknown): string | null { + const obj = body as Record + const webhookActionId = obj.webhookActionId + if (typeof webhookActionId === 'string' && webhookActionId) { + return `ashby:${webhookActionId}` + } + return null + }, + async formatInput({ body }: FormatInputContext): Promise { const b = body as Record return { diff --git a/apps/sim/lib/webhooks/providers/gong.ts b/apps/sim/lib/webhooks/providers/gong.ts index 428747cc3e8..6a45d60ff3f 100644 --- a/apps/sim/lib/webhooks/providers/gong.ts +++ b/apps/sim/lib/webhooks/providers/gong.ts @@ -123,6 +123,20 @@ export async function verifyGongJwtAuth(ctx: AuthContext): Promise + const callData = obj.callData as Record | undefined + const metaData = callData?.metaData as Record | undefined + const id = metaData?.id + if (typeof id === 'string' && id) { + return `gong:${id}` + } + if (typeof id === 'number') { + return `gong:${id}` + } + return null + }, + async formatInput({ body }: FormatInputContext): Promise { const b = body as Record const callData = b.callData as Record | undefined diff --git a/apps/sim/lib/webhooks/providers/telegram.ts b/apps/sim/lib/webhooks/providers/telegram.ts index 0bb2fd427f0..77bb623be16 100644 --- a/apps/sim/lib/webhooks/providers/telegram.ts +++ b/apps/sim/lib/webhooks/providers/telegram.ts @@ -23,6 +23,15 @@ export const telegramHandler: WebhookProviderHandler = { return null }, + extractIdempotencyId(body: unknown): string | null { + const obj = body as Record + const updateId = obj.update_id + if (typeof updateId === 'number') { + return `telegram:${updateId}` + } + return null + }, + async formatInput({ body }: FormatInputContext): Promise { const b = body as Record const rawMessage = (b?.message || diff --git a/apps/sim/lib/webhooks/providers/zoom.ts b/apps/sim/lib/webhooks/providers/zoom.ts index c78cf0c9386..ac687f14cbf 100644 --- a/apps/sim/lib/webhooks/providers/zoom.ts +++ b/apps/sim/lib/webhooks/providers/zoom.ts @@ -128,36 +128,6 @@ export const zoomHandler: WebhookProviderHandler = { return null }, - extractIdempotencyId(body: unknown): string | null { - const obj = body as Record - const event = obj.event - const ts = obj.event_ts - if (typeof event !== 'string' || ts === undefined || ts === null) { - return null - } - const payload = obj.payload as Record | undefined - const inner = payload?.object as Record | undefined - const participant = - inner?.participant && - typeof inner.participant === 'object' && - !Array.isArray(inner.participant) - ? (inner.participant as Record) - : null - const participantStable = - (typeof participant?.user_id === 'string' && participant.user_id) || - (typeof participant?.id === 'string' && participant.id) || - (typeof participant?.email === 'string' && participant.email) || - (typeof participant?.join_time === 'string' && participant.join_time) || - (typeof participant?.leave_time === 'string' && participant.leave_time) || - '' - const stable = - participantStable || - (typeof inner?.uuid === 'string' && inner.uuid) || - (inner?.id !== undefined && inner.id !== null ? String(inner.id) : '') || - '' - return `zoom:${event}:${String(ts)}:${stable}` - }, - async matchEvent({ webhook: wh, workflow, body, requestId, providerConfig }: EventMatchContext) { const triggerId = providerConfig.triggerId as string | undefined const obj = body as Record From 1ccf2581b223367f724806454d07a8f48b2102ab Mon Sep 17 00:00:00 2001 From: Waleed Latif Date: Mon, 6 Apr 2026 22:09:11 -0700 Subject: [PATCH 11/11] tets --- apps/sim/lib/webhooks/providers/zoom.test.ts | 25 ++------------------ 1 file changed, 2 insertions(+), 23 deletions(-) diff --git a/apps/sim/lib/webhooks/providers/zoom.test.ts b/apps/sim/lib/webhooks/providers/zoom.test.ts index 57ff95e8e36..57751e49cba 100644 --- a/apps/sim/lib/webhooks/providers/zoom.test.ts +++ b/apps/sim/lib/webhooks/providers/zoom.test.ts @@ -27,29 +27,8 @@ describe('Zoom webhook provider', () => { expect(validateZoomSignature(secret, hashA, timestamp, rawB)).toBe(false) }) - it('extractIdempotencyId prefers meeting uuid', () => { - const zid = zoomHandler.extractIdempotencyId!({ - event: 'meeting.started', - event_ts: 123, - payload: { object: { uuid: 'u1', id: 55 } }, - }) - expect(zid).toBe('zoom:meeting.started:123:u1') - }) - - it('extractIdempotencyId uses participant identity when available', () => { - const zid = zoomHandler.extractIdempotencyId!({ - event: 'meeting.participant_joined', - event_ts: 123, - payload: { - object: { - uuid: 'meeting-uuid', - participant: { - user_id: 'participant-1', - }, - }, - }, - }) - expect(zid).toBe('zoom:meeting.participant_joined:123:participant-1') + it('does not implement extractIdempotencyId (x-zm-request-id handled at service level)', () => { + expect(zoomHandler.extractIdempotencyId).toBeUndefined() }) it('formatInput passes through the Zoom webhook envelope', async () => {