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

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -81,39 +81,60 @@ const EMPTY_SUBBLOCK_VALUES = {} as Record<string, any>
/** Stable empty map for rows that never resolve MCP tool names */
const EMPTY_MCP_TOOL_NAMES: ReadonlyMap<string, string> = new Map()

interface BlockDeprecation {
interface BlockSunset {
status: 'legacy' | 'deprecated'
kind: 'block' | 'model'
tooltip: string
prompt: string
}

/** Instruction for the agent to migrate a block instance to its successor. */
function migrationPrompt(name: string, target: BlockConfig): string {
return `Migrate the "${name}" block to the current ${target.name} block: change the block type, then set the new block's required inputs as a separate edit (inputs are validated against the old type when sent in the same edit), or delete it and re-add ${target.name} and rewire the connections.`
}

/**
* Deprecation state for a placed block: the block type itself (via
* `config.deprecated.replacedBy`) or its selected model. `null` when neither
* applies or in diff mode. Drives the canvas badge + click-to-fix prompt.
* Sunset state for a placed block: the block type itself (via `config.sunset`)
* or its selected model. `legacy` (amber) is superseded-but-supported and needs
* a resolvable successor; `deprecated` (red) is no longer supported and badges
* with or without one. `null` when neither applies or in diff mode.
*/
function getBlockDeprecation(
function getBlockSunset(
config: BlockConfig,
name: string,
model: unknown,
isDiffMode: boolean
): BlockDeprecation | null {
): BlockSunset | null {
if (isDiffMode) return null

const replacedBy = config.deprecated?.replacedBy
if (replacedBy) {
const target = getBlock(replacedBy)
if (!target) return null
const hasModel = config.subBlocks?.some((sub) => sub.id === 'model')
const sunset = config.sunset
if (sunset) {
const target = sunset.replacedBy ? getBlock(sunset.replacedBy) : undefined

if (sunset.status === 'legacy') {
if (!target) return null
const hasModel = config.subBlocks?.some((sub) => sub.id === 'model')
return {
status: 'legacy',
kind: 'block',
tooltip: 'This is a legacy block. Click to upgrade',
prompt: `The "${name}" block is legacy. ${migrationPrompt(name, target)}${hasModel ? ' Also pick a current, non-deprecated model.' : ''}`,
}
}

return {
status: 'deprecated',
kind: 'block',
tooltip: 'This block is deprecated. Click to upgrade',
prompt: `The "${name}" block is deprecated. Migrate it to the current ${target.name} block: change the block type, then set the new block's required inputs as a separate edit (inputs are validated against the old type when sent in the same edit), or delete it and re-add ${target.name} and rewire the connections.${hasModel ? ' Also pick a current, non-deprecated model.' : ''}`,
tooltip: 'This block is no longer supported. Click to replace',
prompt: target
? `The "${name}" block is no longer supported. ${migrationPrompt(name, target)}`
: `The "${name}" block is no longer supported and has no direct successor. Replace it with current blocks that achieve the same result and rewire the connections.`,

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing model tip on deprecated path

Low Severity

The deprecated sunset branch with a resolvable successor drops the model migration tip that the legacy branch still appends when the block has a model subblock. Click-to-fix prompts for red-tier blocks that both name a successor and expose a model field will omit guidance to switch to a current model.

Additional Locations (1)
Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 0240e68. Configure here.

}
}

if (typeof model === 'string' && isModelDeprecated(model)) {
return {
status: 'legacy',
kind: 'model',
tooltip: `${model} is deprecated. Click to upgrade`,
prompt: `The "${name}" block uses the deprecated model "${model}". Switch it to the latest equivalent model.`,
Expand Down Expand Up @@ -533,21 +554,16 @@ export const WorkflowBlock = memo(function WorkflowBlock({

const posthog = usePostHog()

const deprecation = getBlockDeprecation(
config,
name,
blockSubBlockValues.model,
currentWorkflow.isDiffMode
)
const sunset = getBlockSunset(config, name, blockSubBlockValues.model, currentWorkflow.isDiffMode)

const onFixDeprecation = () => {
if (!deprecation) return
const onFixSunset = () => {
if (!sunset) return
captureEvent(posthog, 'deprecated_block_fix_clicked', {
block_type: type,
workflow_id: currentWorkflowId,
kind: deprecation.kind,
kind: sunset.kind,
})
sendMothershipMessage(deprecation.prompt, [
sendMothershipMessage(sunset.prompt, [
{ kind: 'workflow_block', workflowId: currentWorkflowId, blockId: id, label: name },
])
}
Expand Down Expand Up @@ -871,9 +887,10 @@ export const WorkflowBlock = memo(function WorkflowBlock({
deployChildWorkflow({ workflowId: childWorkflowId })
}
}}
deprecationTooltip={deprecation?.tooltip}
canFixDeprecation={canEditWorkflow}
onFixDeprecation={onFixDeprecation}
sunsetStatus={sunset?.status}
sunsetTooltip={sunset?.tooltip}
canFixSunset={canEditWorkflow}
onFixSunset={onFixSunset}
shouldShowScheduleBadge={shouldShowScheduleBadge}
scheduleIsDisabled={Boolean(scheduleInfo?.isDisabled)}
onReactivateSchedule={() => {
Expand Down
2 changes: 1 addition & 1 deletion apps/sim/blocks/blocks/api_trigger.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ export const ApiTriggerBlock: BlockConfig = {
`,
category: 'triggers',
hideFromToolbar: true,
deprecated: { replacedBy: 'start_trigger' },
sunset: { status: 'legacy', replacedBy: 'start_trigger' },
bgColor: '#2F55FF',
icon: ApiIcon,
subBlocks: [
Expand Down
2 changes: 1 addition & 1 deletion apps/sim/blocks/blocks/chat_trigger.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ export const ChatTriggerBlock: BlockConfig = {
`,
category: 'triggers',
hideFromToolbar: true,
deprecated: { replacedBy: 'start_trigger' },
sunset: { status: 'legacy', replacedBy: 'start_trigger' },
bgColor: '#6F3DFA',
icon: ChatTriggerIcon,
subBlocks: [],
Expand Down
4 changes: 2 additions & 2 deletions apps/sim/blocks/blocks/confluence.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ export const ConfluenceBlock: BlockConfig<ConfluenceResponse> = {
name: 'Confluence (Legacy)',
description: 'Interact with Confluence',
hideFromToolbar: true,
deprecated: { replacedBy: 'confluence_v2' },
sunset: { status: 'legacy', replacedBy: 'confluence_v2' },
authMode: AuthMode.OAuth,
longDescription:
'Integrate Confluence into the workflow. Can read, create, update, delete pages, manage comments, attachments, labels, and search content.',
Expand Down Expand Up @@ -361,7 +361,7 @@ export const ConfluenceBlock: BlockConfig<ConfluenceResponse> = {

export const ConfluenceV2Block: BlockConfig<ConfluenceResponse> = {
...ConfluenceBlock,
deprecated: undefined,
sunset: undefined,
type: 'confluence_v2',
name: 'Confluence',
hideFromToolbar: false,
Expand Down
4 changes: 2 additions & 2 deletions apps/sim/blocks/blocks/cursor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ export const CursorBlock: BlockConfig<CursorResponse> = {
icon: CursorIcon,
authMode: AuthMode.ApiKey,
hideFromToolbar: true,
deprecated: { replacedBy: 'cursor_v2' },
sunset: { status: 'legacy', replacedBy: 'cursor_v2' },
subBlocks: [
{
id: 'operation',
Expand Down Expand Up @@ -224,7 +224,7 @@ export const CursorBlock: BlockConfig<CursorResponse> = {

export const CursorV2Block: BlockConfig<CursorResponse> = {
...CursorBlock,
deprecated: undefined,
sunset: undefined,
type: 'cursor_v2',
name: 'Cursor',
description: 'Launch and manage Cursor cloud agents to work on GitHub repositories',
Expand Down
4 changes: 2 additions & 2 deletions apps/sim/blocks/blocks/extend.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ export const ExtendBlock: BlockConfig<ExtendParserOutput> = {
name: 'Extend',
description: 'Parse and extract content from documents',
hideFromToolbar: true,
deprecated: { replacedBy: 'extend_v2' },
sunset: { status: 'legacy', replacedBy: 'extend_v2' },
authMode: AuthMode.ApiKey,
longDescription:
'Integrate Extend AI into the workflow. Parse and extract structured content from documents including PDFs, images, and Office files.',
Expand Down Expand Up @@ -166,7 +166,7 @@ const extendV2SubBlocks = (ExtendBlock.subBlocks || []).flatMap((subBlock) => {

export const ExtendV2Block: BlockConfig<ExtendParserOutput> = {
...ExtendBlock,
deprecated: undefined,
sunset: undefined,
type: 'extend_v2',
name: 'Extend',
hideFromToolbar: false,
Expand Down
10 changes: 5 additions & 5 deletions apps/sim/blocks/blocks/file.ts
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ export const FileBlock: BlockConfig<FileParserOutput> = {
bgColor: '#40916C',
icon: DocumentIcon,
hideFromToolbar: true,
deprecated: { replacedBy: 'file_v5' },
sunset: { status: 'legacy', replacedBy: 'file_v5' },
subBlocks: [
{
id: 'inputMethod',
Expand Down Expand Up @@ -186,7 +186,7 @@ export const FileV2Block: BlockConfig<FileParserOutput> = {
name: 'File (Legacy)',
description: 'Read and parse multiple files',
hideFromToolbar: true,
deprecated: { replacedBy: 'file_v5' },
sunset: { status: 'legacy', replacedBy: 'file_v5' },
subBlocks: [
{
id: 'file',
Expand Down Expand Up @@ -280,7 +280,7 @@ export const FileV3Block: BlockConfig<FileParserV3Output> = {
bgColor: '#40916C',
icon: DocumentIcon,
hideFromToolbar: true,
deprecated: { replacedBy: 'file_v5' },
sunset: { status: 'legacy', replacedBy: 'file_v5' },
subBlocks: [
{
id: 'operation',
Expand Down Expand Up @@ -571,7 +571,7 @@ export const FileV4Block: BlockConfig<FileParserV3Output> = {
longDescription:
'Read workspace files by picker or canonical ID, fetch and parse files from URLs with optional headers, write new workspace files, or append content to existing files.',
hideFromToolbar: true,
deprecated: { replacedBy: 'file_v5' },
sunset: { status: 'legacy', replacedBy: 'file_v5' },
bestPractices: `
- Use Read when you need an existing workspace file object by picker selection or canonical file ID.
- Use Fetch for external file URLs. Add headers for authenticated downloads, for example Slack private file URLs require an Authorization Bearer token.
Expand Down Expand Up @@ -824,7 +824,7 @@ export const FileV4Block: BlockConfig<FileParserV3Output> = {

export const FileV5Block: BlockConfig<FileParserV3Output> = {
...FileV4Block,
deprecated: undefined,
sunset: undefined,
type: 'file_v5',
name: 'File',
description:
Expand Down
4 changes: 2 additions & 2 deletions apps/sim/blocks/blocks/fireflies.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ export const FirefliesBlock: BlockConfig<FirefliesResponse> = {
name: 'Fireflies (Legacy)',
description: 'Interact with Fireflies.ai meeting transcripts and recordings',
hideFromToolbar: true,
deprecated: { replacedBy: 'fireflies_v2' },
sunset: { status: 'legacy', replacedBy: 'fireflies_v2' },
authMode: AuthMode.ApiKey,
triggerAllowed: true,
longDescription:
Expand Down Expand Up @@ -647,7 +647,7 @@ const firefliesV2Inputs = FirefliesBlock.inputs

export const FirefliesV2Block: BlockConfig<FirefliesResponse> = {
...FirefliesBlock,
deprecated: undefined,
sunset: undefined,
type: 'fireflies_v2',
name: 'Fireflies',
description: 'Interact with Fireflies.ai meeting transcripts and recordings',
Expand Down
4 changes: 2 additions & 2 deletions apps/sim/blocks/blocks/github.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ export const GitHubBlock: BlockConfig<GitHubResponse> = {
icon: GithubIcon,
triggerAllowed: true,
hideFromToolbar: true,
deprecated: { replacedBy: 'github_v2' },
sunset: { status: 'legacy', replacedBy: 'github_v2' },
subBlocks: [
{
id: 'operation',
Expand Down Expand Up @@ -2103,7 +2103,7 @@ Return ONLY the timestamp string - no explanations, no quotes, no extra text.`,

export const GitHubV2Block: BlockConfig<GitHubResponse> = {
...GitHubBlock,
deprecated: undefined,
sunset: undefined,
type: 'github_v2',
name: 'GitHub',
hideFromToolbar: false,
Expand Down
4 changes: 2 additions & 2 deletions apps/sim/blocks/blocks/gmail.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ export const GmailBlock: BlockConfig<GmailToolResponse> = {
bgColor: '#FFFFFF',
icon: GmailIcon,
hideFromToolbar: true,
deprecated: { replacedBy: 'gmail_v2' },
sunset: { status: 'legacy', replacedBy: 'gmail_v2' },
triggerAllowed: true,
subBlocks: [
// Operation selector
Expand Down Expand Up @@ -576,7 +576,7 @@ Return ONLY the search query - no explanations, no extra text.`,

export const GmailV2Block: BlockConfig<GmailToolResponse> = {
...GmailBlock,
deprecated: undefined,
sunset: undefined,
type: 'gmail_v2',
name: 'Gmail',
hideFromToolbar: false,
Expand Down
4 changes: 2 additions & 2 deletions apps/sim/blocks/blocks/google_calendar.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ export const GoogleCalendarBlock: BlockConfig<GoogleCalendarResponse> = {
bgColor: '#FFFFFF',
icon: GoogleCalendarIcon,
hideFromToolbar: true,
deprecated: { replacedBy: 'google_calendar_v2' },
sunset: { status: 'legacy', replacedBy: 'google_calendar_v2' },
subBlocks: [
{
id: 'operation',
Expand Down Expand Up @@ -926,7 +926,7 @@ Return ONLY the timestamp string - no explanations, no quotes, no extra text.`,

export const GoogleCalendarV2Block: BlockConfig<GoogleCalendarResponse> = {
...GoogleCalendarBlock,
deprecated: undefined,
sunset: undefined,
type: 'google_calendar_v2',
name: 'Google Calendar',
hideFromToolbar: false,
Expand Down
2 changes: 1 addition & 1 deletion apps/sim/blocks/blocks/google_sheets.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ export const GoogleSheetsBlock: BlockConfig<GoogleSheetsResponse> = {
description: 'Read, write, and update data',
authMode: AuthMode.OAuth,
hideFromToolbar: true,
deprecated: { replacedBy: 'google_sheets_v2' },
sunset: { status: 'legacy', replacedBy: 'google_sheets_v2' },
longDescription:
'Integrate Google Sheets into the workflow. Can read, write, append, and update data.',
docsLink: 'https://docs.sim.ai/integrations/google_sheets',
Expand Down
4 changes: 2 additions & 2 deletions apps/sim/blocks/blocks/google_slides.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ export const GoogleSlidesBlock: BlockConfig<GoogleSlidesResponse> = {
name: 'Google Slides (Legacy)',
description: 'Read, write, and create presentations',
hideFromToolbar: true,
deprecated: { replacedBy: 'google_slides_v2' },
sunset: { status: 'legacy', replacedBy: 'google_slides_v2' },
authMode: AuthMode.OAuth,
longDescription:
'Build, edit, and export branded Google Slides presentations end-to-end. Copy a template, replace text and image tokens, embed Sheets charts, style text and shapes with brand fonts and colors, manage tables and layouts, group elements, run atomic batch updates, and export to PDF or PPTX.',
Expand Down Expand Up @@ -3455,7 +3455,7 @@ const googleSlidesV2Inputs = GoogleSlidesBlock.inputs

export const GoogleSlidesV2Block: BlockConfig<GoogleSlidesResponse> = {
...GoogleSlidesBlock,
deprecated: undefined,
sunset: undefined,
type: 'google_slides_v2',
name: 'Google Slides',
description: 'Read, write, and create presentations',
Expand Down
4 changes: 2 additions & 2 deletions apps/sim/blocks/blocks/grain.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ export const GrainBlock: BlockConfig = {
// Superseded by grain_v2 (Grain API v1 sunsets 2026-09-07); existing blocks
// keep rendering, new blocks come from the v2 entry.
hideFromToolbar: true,
deprecated: { replacedBy: 'grain_v2' },
sunset: { status: 'legacy', replacedBy: 'grain_v2' },
longDescription:
'Integrate Grain into your workflow. Access meeting recordings, transcripts, highlights, and AI-generated summaries. Can also trigger workflows based on Grain webhook events.',
category: 'tools',
Expand Down Expand Up @@ -502,7 +502,7 @@ Return ONLY the search term - no explanations, no quotes, no extra text.`,
*/
export const GrainV2Block: BlockConfig = {
...GrainBlock,
deprecated: undefined,
sunset: undefined,
type: 'grain_v2',
hideFromToolbar: false,
subBlocks: [
Expand Down
2 changes: 1 addition & 1 deletion apps/sim/blocks/blocks/image_generator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ export const ImageGeneratorBlock: BlockConfig<DalleResponse> = {
name: 'Image Generator',
description: 'Generate images',
hideFromToolbar: true,
deprecated: { replacedBy: 'image_generator_v2' },
sunset: { status: 'legacy', replacedBy: 'image_generator_v2' },
authMode: AuthMode.ApiKey,
longDescription:
'Integrate Image Generator into the workflow. Can generate images using DALL-E 3 and GPT Image models.',
Expand Down
2 changes: 1 addition & 1 deletion apps/sim/blocks/blocks/input_trigger.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ export const InputTriggerBlock: BlockConfig = {
`,
category: 'triggers',
hideFromToolbar: true,
deprecated: { replacedBy: 'start_trigger' },
sunset: { status: 'legacy', replacedBy: 'start_trigger' },
bgColor: '#3B82F6',
icon: InputTriggerIcon,
subBlocks: [
Expand Down
4 changes: 2 additions & 2 deletions apps/sim/blocks/blocks/intercom.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ export const IntercomBlock: BlockConfig = {
type: 'intercom',
name: 'Intercom (Legacy)',
hideFromToolbar: true,
deprecated: { replacedBy: 'intercom_v2' },
sunset: { status: 'legacy', replacedBy: 'intercom_v2' },
description: 'Manage contacts, companies, conversations, tickets, and messages in Intercom',
longDescription:
'Integrate Intercom into the workflow. Can create, get, update, list, search, and delete contacts; create, get, and list companies; get, list, reply, and search conversations; create and get tickets; and create messages.',
Expand Down Expand Up @@ -1405,7 +1405,7 @@ Return ONLY the numeric timestamp.`,

export const IntercomV2Block: BlockConfig = {
...IntercomBlock,
deprecated: undefined,
sunset: undefined,
type: 'intercom_v2',
name: 'Intercom',
integrationType: IntegrationType.Support,
Expand Down
Loading
Loading