From 451ebc51c9027eed10c1bf5e85d407ffe60cdb0b Mon Sep 17 00:00:00 2001 From: Vikhyath Mondreti Date: Fri, 27 Feb 2026 02:30:54 -0800 Subject: [PATCH 1/5] fix(webflow): resolution for selectors --- apps/sim/hooks/selectors/resolution.ts | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/apps/sim/hooks/selectors/resolution.ts b/apps/sim/hooks/selectors/resolution.ts index d90df1c21a..0b0bb339e0 100644 --- a/apps/sim/hooks/selectors/resolution.ts +++ b/apps/sim/hooks/selectors/resolution.ts @@ -118,14 +118,16 @@ function resolveFileSelector( } case 'sharepoint': return { key: 'sharepoint.sites', context, allowSearch: true } - case 'webflow': - if (subBlock.id === 'collectionId') { + case 'webflow': { + const paramId = subBlock.canonicalParamId ?? subBlock.id + if (paramId === 'collectionId') { return { key: 'webflow.collections', context, allowSearch: false } } - if (subBlock.id === 'itemId') { + if (paramId === 'itemId') { return { key: 'webflow.items', context, allowSearch: true } } return { key: null, context, allowSearch: true } + } default: return { key: null, context, allowSearch: true } } From d118f3ec26e6faab99b30b890ba18907b2b924bb Mon Sep 17 00:00:00 2001 From: Vikhyath Mondreti Date: Fri, 27 Feb 2026 02:34:59 -0800 Subject: [PATCH 2/5] remove unecessary fallback' --- apps/sim/hooks/selectors/resolution.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/sim/hooks/selectors/resolution.ts b/apps/sim/hooks/selectors/resolution.ts index 0b0bb339e0..4d1c689e1d 100644 --- a/apps/sim/hooks/selectors/resolution.ts +++ b/apps/sim/hooks/selectors/resolution.ts @@ -119,7 +119,7 @@ function resolveFileSelector( case 'sharepoint': return { key: 'sharepoint.sites', context, allowSearch: true } case 'webflow': { - const paramId = subBlock.canonicalParamId ?? subBlock.id + const paramId = subBlock.canonicalParamId if (paramId === 'collectionId') { return { key: 'webflow.collections', context, allowSearch: false } } From 77633a7899b339e359cea1a948dff3dce0edef38 Mon Sep 17 00:00:00 2001 From: Vikhyath Mondreti Date: Fri, 27 Feb 2026 06:08:35 -0800 Subject: [PATCH 3/5] fix teams selector resolution --- apps/sim/hooks/selectors/resolution.ts | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/apps/sim/hooks/selectors/resolution.ts b/apps/sim/hooks/selectors/resolution.ts index 4d1c689e1d..73be5a2c32 100644 --- a/apps/sim/hooks/selectors/resolution.ts +++ b/apps/sim/hooks/selectors/resolution.ts @@ -84,16 +84,16 @@ function resolveFileSelector( return { key: 'confluence.pages', context, allowSearch: true } case 'jira': return { key: 'jira.issues', context, allowSearch: true } - case 'microsoft-teams': - // Route to the correct selector based on what type of resource is being selected - if (subBlock.id === 'chatId') { + case 'microsoft-teams': { + const paramId = subBlock.canonicalParamId + if (paramId === 'chatId') { return { key: 'microsoft.chats', context, allowSearch: false } } - if (subBlock.id === 'channelId') { + if (paramId === 'channelId') { return { key: 'microsoft.channels', context, allowSearch: false } } - // Default to teams selector for teamId return { key: 'microsoft.teams', context, allowSearch: false } + } case 'wealthbox': return { key: 'wealthbox.contacts', context, allowSearch: true } case 'microsoft-planner': @@ -205,7 +205,7 @@ function resolveProjectSelector( ): SelectorResolution { const serviceId = subBlock.serviceId const context = buildBaseContext(args) - const selectorId = subBlock.canonicalParamId ?? subBlock.id + const selectorId = subBlock.canonicalParamId switch (serviceId) { case 'linear': { From 71645808f85ee785de6a1a74cad077af16cc0e97 Mon Sep 17 00:00:00 2001 From: Vikhyath Mondreti Date: Fri, 27 Feb 2026 06:37:32 -0800 Subject: [PATCH 4/5] make selector keys declarative --- apps/sim/blocks/blocks/confluence.ts | 2 + apps/sim/blocks/blocks/gmail.ts | 4 + apps/sim/blocks/blocks/google_calendar.ts | 4 + apps/sim/blocks/blocks/google_docs.ts | 2 + apps/sim/blocks/blocks/google_drive.ts | 13 ++ apps/sim/blocks/blocks/google_forms.ts | 1 + apps/sim/blocks/blocks/google_sheets.ts | 4 + apps/sim/blocks/blocks/google_slides.ts | 2 + apps/sim/blocks/blocks/jira.ts | 2 + apps/sim/blocks/blocks/knowledge.ts | 1 + apps/sim/blocks/blocks/linear.ts | 2 + apps/sim/blocks/blocks/microsoft_excel.ts | 4 + apps/sim/blocks/blocks/microsoft_planner.ts | 1 + apps/sim/blocks/blocks/microsoft_teams.ts | 6 + apps/sim/blocks/blocks/onedrive.ts | 5 + apps/sim/blocks/blocks/outlook.ts | 3 + apps/sim/blocks/blocks/sharepoint.ts | 1 + apps/sim/blocks/blocks/slack.ts | 2 + apps/sim/blocks/blocks/wealthbox.ts | 1 + apps/sim/blocks/blocks/webflow.ts | 5 + apps/sim/blocks/types.ts | 4 + apps/sim/hooks/selectors/resolution.ts | 220 ++------------------ 22 files changed, 85 insertions(+), 204 deletions(-) diff --git a/apps/sim/blocks/blocks/confluence.ts b/apps/sim/blocks/blocks/confluence.ts index c17f44b89b..39cf87bae9 100644 --- a/apps/sim/blocks/blocks/confluence.ts +++ b/apps/sim/blocks/blocks/confluence.ts @@ -103,6 +103,7 @@ export const ConfluenceBlock: BlockConfig = { type: 'file-selector', canonicalParamId: 'pageId', serviceId: 'confluence', + selectorKey: 'confluence.pages', placeholder: 'Select Confluence page', dependsOn: ['credential', 'domain'], mode: 'basic', @@ -498,6 +499,7 @@ export const ConfluenceV2Block: BlockConfig = { type: 'file-selector', canonicalParamId: 'pageId', serviceId: 'confluence', + selectorKey: 'confluence.pages', placeholder: 'Select Confluence page', dependsOn: ['credential', 'domain'], mode: 'basic', diff --git a/apps/sim/blocks/blocks/gmail.ts b/apps/sim/blocks/blocks/gmail.ts index d0ab76a8eb..b5c1fc29dc 100644 --- a/apps/sim/blocks/blocks/gmail.ts +++ b/apps/sim/blocks/blocks/gmail.ts @@ -221,6 +221,7 @@ Return ONLY the email body - no explanations, no extra text.`, type: 'folder-selector', canonicalParamId: 'folder', serviceId: 'gmail', + selectorKey: 'gmail.labels', requiredScopes: ['https://www.googleapis.com/auth/gmail.labels'], placeholder: 'Select Gmail label/folder', dependsOn: ['credential'], @@ -301,6 +302,7 @@ Return ONLY the search query - no explanations, no extra text.`, type: 'folder-selector', canonicalParamId: 'addLabelIds', serviceId: 'gmail', + selectorKey: 'gmail.labels', requiredScopes: ['https://www.googleapis.com/auth/gmail.labels'], placeholder: 'Select destination label', dependsOn: ['credential'], @@ -326,6 +328,7 @@ Return ONLY the search query - no explanations, no extra text.`, type: 'folder-selector', canonicalParamId: 'removeLabelIds', serviceId: 'gmail', + selectorKey: 'gmail.labels', requiredScopes: ['https://www.googleapis.com/auth/gmail.labels'], placeholder: 'Select label to remove', dependsOn: ['credential'], @@ -378,6 +381,7 @@ Return ONLY the search query - no explanations, no extra text.`, type: 'folder-selector', canonicalParamId: 'manageLabelId', serviceId: 'gmail', + selectorKey: 'gmail.labels', requiredScopes: ['https://www.googleapis.com/auth/gmail.labels'], placeholder: 'Select label', dependsOn: ['credential'], diff --git a/apps/sim/blocks/blocks/google_calendar.ts b/apps/sim/blocks/blocks/google_calendar.ts index abbce2f181..bd2ba6265b 100644 --- a/apps/sim/blocks/blocks/google_calendar.ts +++ b/apps/sim/blocks/blocks/google_calendar.ts @@ -62,6 +62,8 @@ export const GoogleCalendarBlock: BlockConfig = { type: 'file-selector', canonicalParamId: 'calendarId', serviceId: 'google-calendar', + selectorKey: 'google.calendar', + selectorAllowSearch: false, requiredScopes: ['https://www.googleapis.com/auth/calendar'], placeholder: 'Select calendar', dependsOn: ['credential'], @@ -326,6 +328,8 @@ Return ONLY the timestamp string - no explanations, no quotes, no extra text.`, type: 'file-selector', canonicalParamId: 'destinationCalendarId', serviceId: 'google-calendar', + selectorKey: 'google.calendar', + selectorAllowSearch: false, requiredScopes: ['https://www.googleapis.com/auth/calendar'], placeholder: 'Select destination calendar', dependsOn: ['credential'], diff --git a/apps/sim/blocks/blocks/google_docs.ts b/apps/sim/blocks/blocks/google_docs.ts index 83449a2524..380d969463 100644 --- a/apps/sim/blocks/blocks/google_docs.ts +++ b/apps/sim/blocks/blocks/google_docs.ts @@ -58,6 +58,7 @@ export const GoogleDocsBlock: BlockConfig = { type: 'file-selector', canonicalParamId: 'documentId', serviceId: 'google-docs', + selectorKey: 'google.drive', requiredScopes: [], mimeType: 'application/vnd.google-apps.document', placeholder: 'Select a document', @@ -100,6 +101,7 @@ Return ONLY the document title - no explanations, no extra text.`, type: 'file-selector', canonicalParamId: 'folderId', serviceId: 'google-docs', + selectorKey: 'google.drive', requiredScopes: [], mimeType: 'application/vnd.google-apps.folder', placeholder: 'Select a parent folder', diff --git a/apps/sim/blocks/blocks/google_drive.ts b/apps/sim/blocks/blocks/google_drive.ts index 182246bc30..7f8481898f 100644 --- a/apps/sim/blocks/blocks/google_drive.ts +++ b/apps/sim/blocks/blocks/google_drive.ts @@ -137,6 +137,7 @@ Return ONLY the file content - no explanations, no markdown code blocks, no extr type: 'file-selector', canonicalParamId: 'uploadFolderId', serviceId: 'google-drive', + selectorKey: 'google.drive', requiredScopes: [ 'https://www.googleapis.com/auth/drive.file', 'https://www.googleapis.com/auth/drive', @@ -209,6 +210,7 @@ Return ONLY the file content - no explanations, no markdown code blocks, no extr type: 'file-selector', canonicalParamId: 'createFolderParentId', serviceId: 'google-drive', + selectorKey: 'google.drive', requiredScopes: [ 'https://www.googleapis.com/auth/drive.file', 'https://www.googleapis.com/auth/drive', @@ -236,6 +238,7 @@ Return ONLY the file content - no explanations, no markdown code blocks, no extr type: 'file-selector', canonicalParamId: 'listFolderId', serviceId: 'google-drive', + selectorKey: 'google.drive', requiredScopes: [ 'https://www.googleapis.com/auth/drive.file', 'https://www.googleapis.com/auth/drive', @@ -295,6 +298,7 @@ Return ONLY the query string - no explanations, no quotes around the whole thing type: 'file-selector', canonicalParamId: 'downloadFileId', serviceId: 'google-drive', + selectorKey: 'google.drive', requiredScopes: [ 'https://www.googleapis.com/auth/drive.file', 'https://www.googleapis.com/auth/drive', @@ -356,6 +360,7 @@ Return ONLY the query string - no explanations, no quotes around the whole thing type: 'file-selector', canonicalParamId: 'getFileId', serviceId: 'google-drive', + selectorKey: 'google.drive', requiredScopes: [ 'https://www.googleapis.com/auth/drive.file', 'https://www.googleapis.com/auth/drive', @@ -383,6 +388,7 @@ Return ONLY the query string - no explanations, no quotes around the whole thing type: 'file-selector', canonicalParamId: 'copyFileId', serviceId: 'google-drive', + selectorKey: 'google.drive', requiredScopes: [ 'https://www.googleapis.com/auth/drive.file', 'https://www.googleapis.com/auth/drive', @@ -416,6 +422,7 @@ Return ONLY the query string - no explanations, no quotes around the whole thing type: 'file-selector', canonicalParamId: 'copyDestFolderId', serviceId: 'google-drive', + selectorKey: 'google.drive', requiredScopes: [ 'https://www.googleapis.com/auth/drive.file', 'https://www.googleapis.com/auth/drive', @@ -442,6 +449,7 @@ Return ONLY the query string - no explanations, no quotes around the whole thing type: 'file-selector', canonicalParamId: 'updateFileId', serviceId: 'google-drive', + selectorKey: 'google.drive', requiredScopes: [ 'https://www.googleapis.com/auth/drive.file', 'https://www.googleapis.com/auth/drive', @@ -520,6 +528,7 @@ Return ONLY the description text - no explanations, no quotes, no extra text.`, type: 'file-selector', canonicalParamId: 'trashFileId', serviceId: 'google-drive', + selectorKey: 'google.drive', requiredScopes: [ 'https://www.googleapis.com/auth/drive.file', 'https://www.googleapis.com/auth/drive', @@ -547,6 +556,7 @@ Return ONLY the description text - no explanations, no quotes, no extra text.`, type: 'file-selector', canonicalParamId: 'deleteFileId', serviceId: 'google-drive', + selectorKey: 'google.drive', requiredScopes: [ 'https://www.googleapis.com/auth/drive.file', 'https://www.googleapis.com/auth/drive', @@ -574,6 +584,7 @@ Return ONLY the description text - no explanations, no quotes, no extra text.`, type: 'file-selector', canonicalParamId: 'shareFileId', serviceId: 'google-drive', + selectorKey: 'google.drive', requiredScopes: [ 'https://www.googleapis.com/auth/drive.file', 'https://www.googleapis.com/auth/drive', @@ -688,6 +699,7 @@ Return ONLY the message text - no subject line, no greetings/signatures, no extr type: 'file-selector', canonicalParamId: 'unshareFileId', serviceId: 'google-drive', + selectorKey: 'google.drive', requiredScopes: [ 'https://www.googleapis.com/auth/drive.file', 'https://www.googleapis.com/auth/drive', @@ -723,6 +735,7 @@ Return ONLY the message text - no subject line, no greetings/signatures, no extr type: 'file-selector', canonicalParamId: 'listPermissionsFileId', serviceId: 'google-drive', + selectorKey: 'google.drive', requiredScopes: [ 'https://www.googleapis.com/auth/drive.file', 'https://www.googleapis.com/auth/drive', diff --git a/apps/sim/blocks/blocks/google_forms.ts b/apps/sim/blocks/blocks/google_forms.ts index 840dbe2eb8..280e13c73f 100644 --- a/apps/sim/blocks/blocks/google_forms.ts +++ b/apps/sim/blocks/blocks/google_forms.ts @@ -64,6 +64,7 @@ export const GoogleFormsBlock: BlockConfig = { canonicalParamId: 'formId', required: true, serviceId: 'google-forms', + selectorKey: 'google.drive', requiredScopes: [], mimeType: 'application/vnd.google-apps.form', placeholder: 'Select a form', diff --git a/apps/sim/blocks/blocks/google_sheets.ts b/apps/sim/blocks/blocks/google_sheets.ts index bde2bec45d..d2ac11927d 100644 --- a/apps/sim/blocks/blocks/google_sheets.ts +++ b/apps/sim/blocks/blocks/google_sheets.ts @@ -62,6 +62,7 @@ export const GoogleSheetsBlock: BlockConfig = { type: 'file-selector', canonicalParamId: 'spreadsheetId', serviceId: 'google-sheets', + selectorKey: 'google.drive', requiredScopes: [ 'https://www.googleapis.com/auth/drive.file', 'https://www.googleapis.com/auth/drive', @@ -360,6 +361,7 @@ export const GoogleSheetsV2Block: BlockConfig = { type: 'file-selector', canonicalParamId: 'spreadsheetId', serviceId: 'google-sheets', + selectorKey: 'google.drive', requiredScopes: [ 'https://www.googleapis.com/auth/drive.file', 'https://www.googleapis.com/auth/drive', @@ -388,6 +390,8 @@ export const GoogleSheetsV2Block: BlockConfig = { type: 'sheet-selector', canonicalParamId: 'sheetName', serviceId: 'google-sheets', + selectorKey: 'google.sheets', + selectorAllowSearch: false, placeholder: 'Select a sheet', required: true, dependsOn: { all: ['credential'], any: ['spreadsheetId', 'manualSpreadsheetId'] }, diff --git a/apps/sim/blocks/blocks/google_slides.ts b/apps/sim/blocks/blocks/google_slides.ts index b341d2cfbc..100314d855 100644 --- a/apps/sim/blocks/blocks/google_slides.ts +++ b/apps/sim/blocks/blocks/google_slides.ts @@ -72,6 +72,7 @@ export const GoogleSlidesBlock: BlockConfig = { type: 'file-selector', canonicalParamId: 'presentationId', serviceId: 'google-drive', + selectorKey: 'google.drive', requiredScopes: [], mimeType: 'application/vnd.google-apps.presentation', placeholder: 'Select a presentation', @@ -185,6 +186,7 @@ Return ONLY the title - no explanations, no quotes, no extra text.`, type: 'file-selector', canonicalParamId: 'folderId', serviceId: 'google-drive', + selectorKey: 'google.drive', requiredScopes: [], mimeType: 'application/vnd.google-apps.folder', placeholder: 'Select a parent folder', diff --git a/apps/sim/blocks/blocks/jira.ts b/apps/sim/blocks/blocks/jira.ts index 96eb7eebba..b5c25317af 100644 --- a/apps/sim/blocks/blocks/jira.ts +++ b/apps/sim/blocks/blocks/jira.ts @@ -114,6 +114,7 @@ export const JiraBlock: BlockConfig = { type: 'project-selector', canonicalParamId: 'projectId', serviceId: 'jira', + selectorKey: 'jira.projects', placeholder: 'Select Jira project', dependsOn: ['credential', 'domain'], mode: 'basic', @@ -137,6 +138,7 @@ export const JiraBlock: BlockConfig = { type: 'file-selector', canonicalParamId: 'issueKey', serviceId: 'jira', + selectorKey: 'jira.issues', placeholder: 'Select Jira issue', dependsOn: ['credential', 'domain', 'projectId'], condition: { diff --git a/apps/sim/blocks/blocks/knowledge.ts b/apps/sim/blocks/blocks/knowledge.ts index 387723de55..bb5e20f3f9 100644 --- a/apps/sim/blocks/blocks/knowledge.ts +++ b/apps/sim/blocks/blocks/knowledge.ts @@ -75,6 +75,7 @@ export const KnowledgeBlock: BlockConfig = { id: 'documentId', title: 'Document', type: 'document-selector', + selectorKey: 'knowledge.documents', placeholder: 'Select document', dependsOn: ['knowledgeBaseId'], required: true, diff --git a/apps/sim/blocks/blocks/linear.ts b/apps/sim/blocks/blocks/linear.ts index 2f50d70db2..c72348754b 100644 --- a/apps/sim/blocks/blocks/linear.ts +++ b/apps/sim/blocks/blocks/linear.ts @@ -152,6 +152,7 @@ export const LinearBlock: BlockConfig = { type: 'project-selector', canonicalParamId: 'teamId', serviceId: 'linear', + selectorKey: 'linear.teams', placeholder: 'Select a team', dependsOn: ['credential'], mode: 'basic', @@ -228,6 +229,7 @@ export const LinearBlock: BlockConfig = { type: 'project-selector', canonicalParamId: 'projectId', serviceId: 'linear', + selectorKey: 'linear.projects', placeholder: 'Select a project', dependsOn: ['credential', 'teamId'], mode: 'basic', diff --git a/apps/sim/blocks/blocks/microsoft_excel.ts b/apps/sim/blocks/blocks/microsoft_excel.ts index 6d8a7c301f..7e22b6757e 100644 --- a/apps/sim/blocks/blocks/microsoft_excel.ts +++ b/apps/sim/blocks/blocks/microsoft_excel.ts @@ -65,6 +65,7 @@ export const MicrosoftExcelBlock: BlockConfig = { type: 'file-selector', canonicalParamId: 'spreadsheetId', serviceId: 'microsoft-excel', + selectorKey: 'microsoft.excel', requiredScopes: [], mimeType: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', placeholder: 'Select a spreadsheet', @@ -392,6 +393,7 @@ export const MicrosoftExcelV2Block: BlockConfig = { type: 'file-selector', canonicalParamId: 'spreadsheetId', serviceId: 'microsoft-excel', + selectorKey: 'microsoft.excel', requiredScopes: [], mimeType: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', placeholder: 'Select a spreadsheet', @@ -415,6 +417,8 @@ export const MicrosoftExcelV2Block: BlockConfig = { type: 'sheet-selector', canonicalParamId: 'sheetName', serviceId: 'microsoft-excel', + selectorKey: 'microsoft.excel.sheets', + selectorAllowSearch: false, placeholder: 'Select a sheet', required: true, dependsOn: { all: ['credential'], any: ['spreadsheetId', 'manualSpreadsheetId'] }, diff --git a/apps/sim/blocks/blocks/microsoft_planner.ts b/apps/sim/blocks/blocks/microsoft_planner.ts index 48771c3b68..a73d01b48d 100644 --- a/apps/sim/blocks/blocks/microsoft_planner.ts +++ b/apps/sim/blocks/blocks/microsoft_planner.ts @@ -108,6 +108,7 @@ export const MicrosoftPlannerBlock: BlockConfig = { type: 'file-selector', placeholder: 'Select a task', serviceId: 'microsoft-planner', + selectorKey: 'microsoft.planner', condition: { field: 'operation', value: ['read_task'] }, dependsOn: ['credential', 'planId'], mode: 'basic', diff --git a/apps/sim/blocks/blocks/microsoft_teams.ts b/apps/sim/blocks/blocks/microsoft_teams.ts index 5f6481f701..3285eeace1 100644 --- a/apps/sim/blocks/blocks/microsoft_teams.ts +++ b/apps/sim/blocks/blocks/microsoft_teams.ts @@ -87,6 +87,8 @@ export const MicrosoftTeamsBlock: BlockConfig = { type: 'file-selector', canonicalParamId: 'teamId', serviceId: 'microsoft-teams', + selectorKey: 'microsoft.teams', + selectorAllowSearch: false, requiredScopes: [], placeholder: 'Select a team', dependsOn: ['credential'], @@ -132,6 +134,8 @@ export const MicrosoftTeamsBlock: BlockConfig = { type: 'file-selector', canonicalParamId: 'chatId', serviceId: 'microsoft-teams', + selectorKey: 'microsoft.chats', + selectorAllowSearch: false, requiredScopes: [], placeholder: 'Select a chat', dependsOn: ['credential'], @@ -161,6 +165,8 @@ export const MicrosoftTeamsBlock: BlockConfig = { type: 'file-selector', canonicalParamId: 'channelId', serviceId: 'microsoft-teams', + selectorKey: 'microsoft.channels', + selectorAllowSearch: false, requiredScopes: [], placeholder: 'Select a channel', dependsOn: ['credential', 'teamSelector'], diff --git a/apps/sim/blocks/blocks/onedrive.ts b/apps/sim/blocks/blocks/onedrive.ts index e2e1451072..0912da950e 100644 --- a/apps/sim/blocks/blocks/onedrive.ts +++ b/apps/sim/blocks/blocks/onedrive.ts @@ -155,6 +155,7 @@ export const OneDriveBlock: BlockConfig = { type: 'file-selector', canonicalParamId: 'uploadFolderId', serviceId: 'onedrive', + selectorKey: 'onedrive.folders', requiredScopes: [ 'openid', 'profile', @@ -192,6 +193,7 @@ export const OneDriveBlock: BlockConfig = { type: 'file-selector', canonicalParamId: 'createFolderParentId', serviceId: 'onedrive', + selectorKey: 'onedrive.folders', requiredScopes: [ 'openid', 'profile', @@ -224,6 +226,7 @@ export const OneDriveBlock: BlockConfig = { type: 'file-selector', canonicalParamId: 'listFolderId', serviceId: 'onedrive', + selectorKey: 'onedrive.folders', requiredScopes: [ 'openid', 'profile', @@ -270,6 +273,7 @@ export const OneDriveBlock: BlockConfig = { type: 'file-selector', canonicalParamId: 'downloadFileId', serviceId: 'onedrive', + selectorKey: 'onedrive.files', requiredScopes: [ 'openid', 'profile', @@ -310,6 +314,7 @@ export const OneDriveBlock: BlockConfig = { type: 'file-selector', canonicalParamId: 'deleteFileId', serviceId: 'onedrive', + selectorKey: 'onedrive.files', requiredScopes: [ 'openid', 'profile', diff --git a/apps/sim/blocks/blocks/outlook.ts b/apps/sim/blocks/blocks/outlook.ts index 8c1b5372bb..11997034cb 100644 --- a/apps/sim/blocks/blocks/outlook.ts +++ b/apps/sim/blocks/blocks/outlook.ts @@ -187,6 +187,7 @@ export const OutlookBlock: BlockConfig = { type: 'folder-selector', canonicalParamId: 'folder', serviceId: 'outlook', + selectorKey: 'outlook.folders', requiredScopes: ['Mail.ReadWrite', 'Mail.ReadBasic', 'Mail.Read'], placeholder: 'Select Outlook folder', dependsOn: ['credential'], @@ -232,6 +233,7 @@ export const OutlookBlock: BlockConfig = { type: 'folder-selector', canonicalParamId: 'destinationId', serviceId: 'outlook', + selectorKey: 'outlook.folders', requiredScopes: ['Mail.ReadWrite', 'Mail.ReadBasic', 'Mail.Read'], placeholder: 'Select destination folder', dependsOn: ['credential'], @@ -278,6 +280,7 @@ export const OutlookBlock: BlockConfig = { type: 'folder-selector', canonicalParamId: 'copyDestinationId', serviceId: 'outlook', + selectorKey: 'outlook.folders', requiredScopes: ['Mail.ReadWrite', 'Mail.ReadBasic', 'Mail.Read'], placeholder: 'Select destination folder', dependsOn: ['credential'], diff --git a/apps/sim/blocks/blocks/sharepoint.ts b/apps/sim/blocks/blocks/sharepoint.ts index 9863dce349..af54dc2f75 100644 --- a/apps/sim/blocks/blocks/sharepoint.ts +++ b/apps/sim/blocks/blocks/sharepoint.ts @@ -67,6 +67,7 @@ export const SharepointBlock: BlockConfig = { type: 'file-selector', canonicalParamId: 'siteId', serviceId: 'sharepoint', + selectorKey: 'sharepoint.sites', requiredScopes: [ 'openid', 'profile', diff --git a/apps/sim/blocks/blocks/slack.ts b/apps/sim/blocks/blocks/slack.ts index 8bba8e9b86..9eca653406 100644 --- a/apps/sim/blocks/blocks/slack.ts +++ b/apps/sim/blocks/blocks/slack.ts @@ -130,6 +130,7 @@ export const SlackBlock: BlockConfig = { type: 'channel-selector', canonicalParamId: 'channel', serviceId: 'slack', + selectorKey: 'slack.channels', placeholder: 'Select Slack channel', mode: 'basic', dependsOn: { all: ['authMethod'], any: ['credential', 'botToken'] }, @@ -182,6 +183,7 @@ export const SlackBlock: BlockConfig = { type: 'user-selector', canonicalParamId: 'dmUserId', serviceId: 'slack', + selectorKey: 'slack.users', placeholder: 'Select Slack user', mode: 'basic', dependsOn: { all: ['authMethod'], any: ['credential', 'botToken'] }, diff --git a/apps/sim/blocks/blocks/wealthbox.ts b/apps/sim/blocks/blocks/wealthbox.ts index 29acc0f1b9..6454ac9a6a 100644 --- a/apps/sim/blocks/blocks/wealthbox.ts +++ b/apps/sim/blocks/blocks/wealthbox.ts @@ -61,6 +61,7 @@ export const WealthboxBlock: BlockConfig = { title: 'Select Contact', type: 'file-selector', serviceId: 'wealthbox', + selectorKey: 'wealthbox.contacts', requiredScopes: ['login', 'data'], placeholder: 'Enter Contact ID', mode: 'basic', diff --git a/apps/sim/blocks/blocks/webflow.ts b/apps/sim/blocks/blocks/webflow.ts index 4cb3aa26c1..86a549724d 100644 --- a/apps/sim/blocks/blocks/webflow.ts +++ b/apps/sim/blocks/blocks/webflow.ts @@ -56,6 +56,8 @@ export const WebflowBlock: BlockConfig = { type: 'project-selector', canonicalParamId: 'siteId', serviceId: 'webflow', + selectorKey: 'webflow.sites', + selectorAllowSearch: false, placeholder: 'Select Webflow site', dependsOn: ['credential'], mode: 'basic', @@ -76,6 +78,8 @@ export const WebflowBlock: BlockConfig = { type: 'file-selector', canonicalParamId: 'collectionId', serviceId: 'webflow', + selectorKey: 'webflow.collections', + selectorAllowSearch: false, placeholder: 'Select collection', dependsOn: ['credential', 'siteSelector'], mode: 'basic', @@ -96,6 +100,7 @@ export const WebflowBlock: BlockConfig = { type: 'file-selector', canonicalParamId: 'itemId', serviceId: 'webflow', + selectorKey: 'webflow.items', placeholder: 'Select item', dependsOn: ['credential', 'collectionSelector'], mode: 'basic', diff --git a/apps/sim/blocks/types.ts b/apps/sim/blocks/types.ts index e751feef02..fe486a8e05 100644 --- a/apps/sim/blocks/types.ts +++ b/apps/sim/blocks/types.ts @@ -1,4 +1,5 @@ import type { JSX, SVGProps } from 'react' +import type { SelectorKey } from '@/hooks/selectors/types' import type { ToolResponse } from '@/tools/types' export type BlockIcon = (props: SVGProps) => JSX.Element @@ -290,6 +291,9 @@ export interface SubBlockConfig { requiredScopes?: string[] // Whether this credential selector supports credential sets (for trigger blocks) supportsCredentialSets?: boolean + // Selector properties — declarative mapping to a SelectorKey + selectorKey?: SelectorKey + selectorAllowSearch?: boolean // File selector specific properties mimeType?: string // File upload specific properties diff --git a/apps/sim/hooks/selectors/resolution.ts b/apps/sim/hooks/selectors/resolution.ts index 73be5a2c32..9f299d99d8 100644 --- a/apps/sim/hooks/selectors/resolution.ts +++ b/apps/sim/hooks/selectors/resolution.ts @@ -20,214 +20,26 @@ export interface SelectorResolutionArgs { spreadsheetId?: string } -const defaultContext: SelectorContext = {} - export function resolveSelectorForSubBlock( subBlock: SubBlockConfig, args: SelectorResolutionArgs ): SelectorResolution | null { - switch (subBlock.type) { - case 'file-selector': - return resolveFileSelector(subBlock, args) - case 'sheet-selector': - return resolveSheetSelector(subBlock, args) - case 'folder-selector': - return resolveFolderSelector(subBlock, args) - case 'channel-selector': - return resolveChannelSelector(subBlock, args) - case 'user-selector': - return resolveUserSelector(subBlock, args) - case 'project-selector': - return resolveProjectSelector(subBlock, args) - case 'document-selector': - return resolveDocumentSelector(subBlock, args) - default: - return null - } -} - -function buildBaseContext( - args: SelectorResolutionArgs, - extra?: Partial -): SelectorContext { - return { - ...defaultContext, - workflowId: args.workflowId, - credentialId: args.credentialId, - domain: args.domain, - projectId: args.projectId, - planId: args.planId, - teamId: args.teamId, - knowledgeBaseId: args.knowledgeBaseId, - siteId: args.siteId, - collectionId: args.collectionId, - spreadsheetId: args.spreadsheetId, - ...extra, - } -} - -function resolveFileSelector( - subBlock: SubBlockConfig, - args: SelectorResolutionArgs -): SelectorResolution { - const context = buildBaseContext(args, { - mimeType: subBlock.mimeType, - }) - - // Use serviceId as the canonical identifier - const serviceId = subBlock.serviceId || '' - - switch (serviceId) { - case 'google-calendar': - return { key: 'google.calendar', context, allowSearch: false } - case 'confluence': - return { key: 'confluence.pages', context, allowSearch: true } - case 'jira': - return { key: 'jira.issues', context, allowSearch: true } - case 'microsoft-teams': { - const paramId = subBlock.canonicalParamId - if (paramId === 'chatId') { - return { key: 'microsoft.chats', context, allowSearch: false } - } - if (paramId === 'channelId') { - return { key: 'microsoft.channels', context, allowSearch: false } - } - return { key: 'microsoft.teams', context, allowSearch: false } - } - case 'wealthbox': - return { key: 'wealthbox.contacts', context, allowSearch: true } - case 'microsoft-planner': - return { key: 'microsoft.planner', context, allowSearch: true } - case 'microsoft-excel': - return { key: 'microsoft.excel', context, allowSearch: true } - case 'microsoft-word': - return { key: 'microsoft.word', context, allowSearch: true } - case 'google-drive': - return { key: 'google.drive', context, allowSearch: true } - case 'google-sheets': - return { key: 'google.drive', context, allowSearch: true } - case 'google-docs': - return { key: 'google.drive', context, allowSearch: true } - case 'google-slides': - return { key: 'google.drive', context, allowSearch: true } - case 'google-forms': - return { key: 'google.drive', context, allowSearch: true } - case 'onedrive': { - const key: SelectorKey = subBlock.mimeType === 'file' ? 'onedrive.files' : 'onedrive.folders' - return { key, context, allowSearch: true } - } - case 'sharepoint': - return { key: 'sharepoint.sites', context, allowSearch: true } - case 'webflow': { - const paramId = subBlock.canonicalParamId - if (paramId === 'collectionId') { - return { key: 'webflow.collections', context, allowSearch: false } - } - if (paramId === 'itemId') { - return { key: 'webflow.items', context, allowSearch: true } - } - return { key: null, context, allowSearch: true } - } - default: - return { key: null, context, allowSearch: true } - } -} - -function resolveSheetSelector( - subBlock: SubBlockConfig, - args: SelectorResolutionArgs -): SelectorResolution { - const serviceId = subBlock.serviceId - const context = buildBaseContext(args) - - switch (serviceId) { - case 'google-sheets': - return { key: 'google.sheets', context, allowSearch: false } - case 'microsoft-excel': - return { key: 'microsoft.excel.sheets', context, allowSearch: false } - default: - return { key: null, context, allowSearch: false } - } -} - -function resolveFolderSelector( - subBlock: SubBlockConfig, - args: SelectorResolutionArgs -): SelectorResolution { - const serviceId = subBlock.serviceId?.toLowerCase() - if (!serviceId) { - return { key: null, context: buildBaseContext(args), allowSearch: true } - } - - switch (serviceId) { - case 'gmail': - return { key: 'gmail.labels', context: buildBaseContext(args), allowSearch: true } - case 'outlook': - return { key: 'outlook.folders', context: buildBaseContext(args), allowSearch: true } - default: - return { key: null, context: buildBaseContext(args), allowSearch: true } - } -} - -function resolveChannelSelector( - subBlock: SubBlockConfig, - args: SelectorResolutionArgs -): SelectorResolution { - const serviceId = subBlock.serviceId - if (serviceId !== 'slack') { - return { key: null, context: buildBaseContext(args), allowSearch: true } - } - return { - key: 'slack.channels', - context: buildBaseContext(args), - allowSearch: true, - } -} - -function resolveUserSelector( - subBlock: SubBlockConfig, - args: SelectorResolutionArgs -): SelectorResolution { - const serviceId = subBlock.serviceId - if (serviceId !== 'slack') { - return { key: null, context: buildBaseContext(args), allowSearch: true } - } - return { - key: 'slack.users', - context: buildBaseContext(args), - allowSearch: true, - } -} - -function resolveProjectSelector( - subBlock: SubBlockConfig, - args: SelectorResolutionArgs -): SelectorResolution { - const serviceId = subBlock.serviceId - const context = buildBaseContext(args) - const selectorId = subBlock.canonicalParamId - - switch (serviceId) { - case 'linear': { - const key: SelectorKey = selectorId === 'teamId' ? 'linear.teams' : 'linear.projects' - return { key, context, allowSearch: true } - } - case 'jira': - return { key: 'jira.projects', context, allowSearch: true } - case 'webflow': - return { key: 'webflow.sites', context, allowSearch: false } - default: - return { key: null, context, allowSearch: true } - } -} - -function resolveDocumentSelector( - _subBlock: SubBlockConfig, - args: SelectorResolutionArgs -): SelectorResolution { + if (!subBlock.selectorKey) return null return { - key: 'knowledge.documents', - context: buildBaseContext(args), - allowSearch: true, + key: subBlock.selectorKey, + context: { + workflowId: args.workflowId, + credentialId: args.credentialId, + domain: args.domain, + projectId: args.projectId, + planId: args.planId, + teamId: args.teamId, + knowledgeBaseId: args.knowledgeBaseId, + siteId: args.siteId, + collectionId: args.collectionId, + spreadsheetId: args.spreadsheetId, + mimeType: subBlock.mimeType, + }, + allowSearch: subBlock.selectorAllowSearch ?? true, } } From 7c293415b2bb3039f2f8d31f3619c34484b283a1 Mon Sep 17 00:00:00 2001 From: Vikhyath Mondreti Date: Fri, 27 Feb 2026 06:48:26 -0800 Subject: [PATCH 5/5] selectors fixes --- .../document-selector/document-selector.tsx | 40 ++++++++++++++++--- .../document-tag-entry/document-tag-entry.tsx | 36 +++++++++++++++-- .../knowledge-tag-filters.tsx | 38 +++++++++++++++--- 3 files changed, 100 insertions(+), 14 deletions(-) diff --git a/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/components/document-selector/document-selector.tsx b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/components/document-selector/document-selector.tsx index f1e47ab710..49a6f903d5 100644 --- a/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/components/document-selector/document-selector.tsx +++ b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/components/document-selector/document-selector.tsx @@ -2,12 +2,16 @@ import { useCallback, useMemo } from 'react' import { Tooltip } from '@/components/emcn' +import { buildCanonicalIndex, resolveDependencyValue } from '@/lib/workflows/subblocks/visibility' import { SelectorCombobox } from '@/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/components/selector-combobox/selector-combobox' import { useDependsOnGate } from '@/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/hooks/use-depends-on-gate' -import { useSubBlockValue } from '@/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/hooks/use-sub-block-value' import { resolvePreviewContextValue } from '@/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/utils' +import { getBlock } from '@/blocks/registry' import type { SubBlockConfig } from '@/blocks/types' import type { SelectorContext } from '@/hooks/selectors/types' +import { useWorkflowRegistry } from '@/stores/workflows/registry/store' +import { useSubBlockStore } from '@/stores/workflows/subblock/store' +import { useWorkflowStore } from '@/stores/workflows/workflow/store' interface DocumentSelectorProps { blockId: string @@ -28,15 +32,41 @@ export function DocumentSelector({ previewValue, previewContextValues, }: DocumentSelectorProps) { + const { activeWorkflowId } = useWorkflowRegistry() + const { finalDisabled } = useDependsOnGate(blockId, subBlock, { disabled, isPreview, previewContextValues, }) - const [knowledgeBaseIdFromStore] = useSubBlockValue(blockId, 'knowledgeBaseId') - const knowledgeBaseIdValue = previewContextValues - ? resolvePreviewContextValue(previewContextValues.knowledgeBaseId) - : knowledgeBaseIdFromStore + + const blockState = useWorkflowStore((state) => state.blocks[blockId]) + const blockConfig = blockState?.type ? getBlock(blockState.type) : null + const canonicalIndex = useMemo( + () => buildCanonicalIndex(blockConfig?.subBlocks || []), + [blockConfig?.subBlocks] + ) + const canonicalModeOverrides = blockState?.data?.canonicalModes + + const blockValues = useSubBlockStore((state) => { + if (!activeWorkflowId) return {} + const workflowValues = state.workflowValues[activeWorkflowId] || {} + return (workflowValues as Record>)[blockId] || {} + }) + + const knowledgeBaseIdValue = useMemo( + () => + previewContextValues + ? resolvePreviewContextValue(previewContextValues.knowledgeBaseId) + : resolveDependencyValue( + 'knowledgeBaseId', + blockValues, + canonicalIndex, + canonicalModeOverrides + ), + [previewContextValues, blockValues, canonicalIndex, canonicalModeOverrides] + ) + const normalizedKnowledgeBaseId = typeof knowledgeBaseIdValue === 'string' && knowledgeBaseIdValue.trim().length > 0 ? knowledgeBaseIdValue diff --git a/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/components/document-tag-entry/document-tag-entry.tsx b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/components/document-tag-entry/document-tag-entry.tsx index 7a6fa78fef..5fd3f929fc 100644 --- a/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/components/document-tag-entry/document-tag-entry.tsx +++ b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/components/document-tag-entry/document-tag-entry.tsx @@ -13,15 +13,20 @@ import { } from '@/components/emcn' import { cn } from '@/lib/core/utils/cn' import { FIELD_TYPE_LABELS, getPlaceholderForFieldType } from '@/lib/knowledge/constants' +import { buildCanonicalIndex, resolveDependencyValue } from '@/lib/workflows/subblocks/visibility' import { formatDisplayText } from '@/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/components/formatted-text' import { TagDropdown } from '@/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/components/tag-dropdown/tag-dropdown' import { useSubBlockInput } from '@/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/hooks/use-sub-block-input' import { useSubBlockValue } from '@/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/hooks/use-sub-block-value' import { resolvePreviewContextValue } from '@/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/utils' import { useAccessibleReferencePrefixes } from '@/app/workspace/[workspaceId]/w/[workflowId]/hooks/use-accessible-reference-prefixes' +import { getBlock } from '@/blocks/registry' import type { SubBlockConfig } from '@/blocks/types' import { useKnowledgeBaseTagDefinitions } from '@/hooks/kb/use-knowledge-base-tag-definitions' import { useTagSelection } from '@/hooks/kb/use-tag-selection' +import { useWorkflowRegistry } from '@/stores/workflows/registry/store' +import { useSubBlockStore } from '@/stores/workflows/subblock/store' +import { useWorkflowStore } from '@/stores/workflows/workflow/store' interface DocumentTag { id: string @@ -60,11 +65,26 @@ export function DocumentTagEntry({ previewValue, previewContextValues, }: DocumentTagEntryProps) { + const { activeWorkflowId } = useWorkflowRegistry() const [storeValue, setStoreValue] = useSubBlockValue(blockId, subBlock.id) const accessiblePrefixes = useAccessibleReferencePrefixes(blockId) const valueInputRefs = useRef>({}) const overlayRefs = useRef>({}) + const blockState = useWorkflowStore((state) => state.blocks[blockId]) + const blockConfig = blockState?.type ? getBlock(blockState.type) : null + const canonicalIndex = useMemo( + () => buildCanonicalIndex(blockConfig?.subBlocks || []), + [blockConfig?.subBlocks] + ) + const canonicalModeOverrides = blockState?.data?.canonicalModes + + const blockValues = useSubBlockStore((state) => { + if (!activeWorkflowId) return {} + const workflowValues = state.workflowValues[activeWorkflowId] || {} + return (workflowValues as Record>)[blockId] || {} + }) + const inputController = useSubBlockInput({ blockId, subBlockId: subBlock.id, @@ -77,10 +97,18 @@ export function DocumentTagEntry({ disabled, }) - const [knowledgeBaseIdFromStore] = useSubBlockValue(blockId, 'knowledgeBaseId') - const knowledgeBaseIdValue = previewContextValues - ? resolvePreviewContextValue(previewContextValues.knowledgeBaseId) - : knowledgeBaseIdFromStore + const knowledgeBaseIdValue = useMemo( + () => + previewContextValues + ? resolvePreviewContextValue(previewContextValues.knowledgeBaseId) + : resolveDependencyValue( + 'knowledgeBaseId', + blockValues, + canonicalIndex, + canonicalModeOverrides + ), + [previewContextValues, blockValues, canonicalIndex, canonicalModeOverrides] + ) const knowledgeBaseId = typeof knowledgeBaseIdValue === 'string' && knowledgeBaseIdValue.trim().length > 0 ? knowledgeBaseIdValue diff --git a/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/components/knowledge-tag-filters/knowledge-tag-filters.tsx b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/components/knowledge-tag-filters/knowledge-tag-filters.tsx index 3ea3baa167..1c8cd577bc 100644 --- a/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/components/knowledge-tag-filters/knowledge-tag-filters.tsx +++ b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/components/knowledge-tag-filters/knowledge-tag-filters.tsx @@ -1,6 +1,6 @@ 'use client' -import { useRef } from 'react' +import { useMemo, useRef } from 'react' import { Plus } from 'lucide-react' import { Badge, @@ -14,14 +14,19 @@ import { import { cn } from '@/lib/core/utils/cn' import { FIELD_TYPE_LABELS, getPlaceholderForFieldType } from '@/lib/knowledge/constants' import { type FilterFieldType, getOperatorsForFieldType } from '@/lib/knowledge/filters/types' +import { buildCanonicalIndex, resolveDependencyValue } from '@/lib/workflows/subblocks/visibility' import { formatDisplayText } from '@/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/components/formatted-text' import { TagDropdown } from '@/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/components/tag-dropdown/tag-dropdown' import { useSubBlockInput } from '@/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/hooks/use-sub-block-input' import { resolvePreviewContextValue } from '@/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/utils' import { useAccessibleReferencePrefixes } from '@/app/workspace/[workspaceId]/w/[workflowId]/hooks/use-accessible-reference-prefixes' +import { getBlock } from '@/blocks/registry' import type { SubBlockConfig } from '@/blocks/types' import { useKnowledgeBaseTagDefinitions } from '@/hooks/kb/use-knowledge-base-tag-definitions' import { useTagSelection } from '@/hooks/kb/use-tag-selection' +import { useWorkflowRegistry } from '@/stores/workflows/registry/store' +import { useSubBlockStore } from '@/stores/workflows/subblock/store' +import { useWorkflowStore } from '@/stores/workflows/workflow/store' import { useSubBlockValue } from '../../hooks/use-sub-block-value' interface TagFilter { @@ -64,15 +69,38 @@ export function KnowledgeTagFilters({ previewValue, previewContextValues, }: KnowledgeTagFiltersProps) { + const { activeWorkflowId } = useWorkflowRegistry() const [storeValue, setStoreValue] = useSubBlockValue(blockId, subBlock.id) const emitTagSelection = useTagSelection(blockId, subBlock.id) const valueInputRefs = useRef>({}) const overlayRefs = useRef>({}) - const [knowledgeBaseIdFromStore] = useSubBlockValue(blockId, 'knowledgeBaseId') - const knowledgeBaseIdValue = previewContextValues - ? resolvePreviewContextValue(previewContextValues.knowledgeBaseId) - : knowledgeBaseIdFromStore + const blockState = useWorkflowStore((state) => state.blocks[blockId]) + const blockConfig = blockState?.type ? getBlock(blockState.type) : null + const canonicalIndex = useMemo( + () => buildCanonicalIndex(blockConfig?.subBlocks || []), + [blockConfig?.subBlocks] + ) + const canonicalModeOverrides = blockState?.data?.canonicalModes + + const blockValues = useSubBlockStore((state) => { + if (!activeWorkflowId) return {} + const workflowValues = state.workflowValues[activeWorkflowId] || {} + return (workflowValues as Record>)[blockId] || {} + }) + + const knowledgeBaseIdValue = useMemo( + () => + previewContextValues + ? resolvePreviewContextValue(previewContextValues.knowledgeBaseId) + : resolveDependencyValue( + 'knowledgeBaseId', + blockValues, + canonicalIndex, + canonicalModeOverrides + ), + [previewContextValues, blockValues, canonicalIndex, canonicalModeOverrides] + ) const knowledgeBaseId = typeof knowledgeBaseIdValue === 'string' && knowledgeBaseIdValue.trim().length > 0 ? knowledgeBaseIdValue