From 815929516653012efde25cf16f90e11510e49666 Mon Sep 17 00:00:00 2001 From: Waleed Latif Date: Fri, 1 May 2026 22:08:05 -0700 Subject: [PATCH 1/3] improvement(home): consolidate chat context kind icon registry --- .../components/chat-context-kind-registry.tsx | 83 +++++++++++++++++++ .../home/components/context-mention-icon.tsx | 40 ++------- .../user-input/components/constants.ts | 50 +++++------ 3 files changed, 116 insertions(+), 57 deletions(-) create mode 100644 apps/sim/app/workspace/[workspaceId]/home/components/chat-context-kind-registry.tsx diff --git a/apps/sim/app/workspace/[workspaceId]/home/components/chat-context-kind-registry.tsx b/apps/sim/app/workspace/[workspaceId]/home/components/chat-context-kind-registry.tsx new file mode 100644 index 00000000000..efcae7e3394 --- /dev/null +++ b/apps/sim/app/workspace/[workspaceId]/home/components/chat-context-kind-registry.tsx @@ -0,0 +1,83 @@ +import type { ReactNode } from 'react' +import { + Blimp, + Database, + Folder as FolderIcon, + Library, + Table as TableIcon, +} from '@/components/emcn/icons' +import { getDocumentIcon } from '@/components/icons/document-icons' +import { cn } from '@/lib/core/utils/cn' +import { workflowBorderColor } from '@/lib/workspaces/colors' +import type { ChatContextKind, ChatMessageContext } from '@/app/workspace/[workspaceId]/home/types' + +interface RenderIconArgs { + context: ChatMessageContext + className: string + workflowColor?: string | null +} + +interface ChatContextKindConfig { + /** Human label for the kind (used in tooltips / accessible names). */ + label: string + /** Renders the chip icon. Returns null when no icon should be shown for this kind. */ + renderIcon: (args: RenderIconArgs) => ReactNode | null +} + +function renderWorkflowSquare({ className, workflowColor }: RenderIconArgs): ReactNode | null { + if (!workflowColor) return null + return ( + + ) +} + +/** + * Single source of truth for the icon and label associated with each + * {@link ChatContextKind}. The `Record` typing forces a + * compile error whenever a new kind is added to the union without a + * corresponding entry here, preventing the chip from silently rendering + * without an icon. + */ +export const CHAT_CONTEXT_KIND_REGISTRY: Record = { + workflow: { label: 'Workflow', renderIcon: renderWorkflowSquare }, + current_workflow: { label: 'Current workflow', renderIcon: renderWorkflowSquare }, + workflow_block: { label: 'Block', renderIcon: renderWorkflowSquare }, + blocks: { label: 'Blocks', renderIcon: () => null }, + knowledge: { + label: 'Knowledge base', + renderIcon: ({ className }) => , + }, + table: { + label: 'Table', + renderIcon: ({ className }) => , + }, + file: { + label: 'File', + renderIcon: ({ context, className }) => { + const FileDocIcon = getDocumentIcon('', context.label) + return + }, + }, + folder: { + label: 'Folder', + renderIcon: ({ className }) => , + }, + past_chat: { + label: 'Past chat', + renderIcon: ({ className }) => , + }, + logs: { + label: 'Logs', + renderIcon: ({ className }) => , + }, + templates: { label: 'Templates', renderIcon: () => null }, + docs: { label: 'Docs', renderIcon: () => null }, + slash_command: { label: 'Command', renderIcon: () => null }, +} diff --git a/apps/sim/app/workspace/[workspaceId]/home/components/context-mention-icon.tsx b/apps/sim/app/workspace/[workspaceId]/home/components/context-mention-icon.tsx index 1e7a2514620..3f739bb0e40 100644 --- a/apps/sim/app/workspace/[workspaceId]/home/components/context-mention-icon.tsx +++ b/apps/sim/app/workspace/[workspaceId]/home/components/context-mention-icon.tsx @@ -1,7 +1,4 @@ -import { Blimp, Database, Folder as FolderIcon, Table as TableIcon } from '@/components/emcn/icons' -import { getDocumentIcon } from '@/components/icons/document-icons' -import { cn } from '@/lib/core/utils/cn' -import { workflowBorderColor } from '@/lib/workspaces/colors' +import { CHAT_CONTEXT_KIND_REGISTRY } from '@/app/workspace/[workspaceId]/home/components/chat-context-kind-registry' import type { ChatMessageContext } from '@/app/workspace/[workspaceId]/home/types' interface ContextMentionIconProps { @@ -14,32 +11,11 @@ interface ContextMentionIconProps { /** Renders the icon for a context mention chip. Returns null when no icon applies. */ export function ContextMentionIcon({ context, workflowColor, className }: ContextMentionIconProps) { - switch (context.kind) { - case 'workflow': - case 'current_workflow': - return workflowColor ? ( - - ) : null - case 'knowledge': - return - case 'table': - return - case 'file': { - const FileDocIcon = getDocumentIcon('', context.label) - return - } - case 'folder': - return - case 'past_chat': - return - default: - return null - } + return ( + CHAT_CONTEXT_KIND_REGISTRY[context.kind].renderIcon({ + context, + className, + workflowColor, + }) ?? null + ) } diff --git a/apps/sim/app/workspace/[workspaceId]/home/components/user-input/components/constants.ts b/apps/sim/app/workspace/[workspaceId]/home/components/user-input/components/constants.ts index a689fb98801..59d31ed8615 100644 --- a/apps/sim/app/workspace/[workspaceId]/home/components/user-input/components/constants.ts +++ b/apps/sim/app/workspace/[workspaceId]/home/components/user-input/components/constants.ts @@ -1,5 +1,8 @@ import { cn } from '@/lib/core/utils/cn' -import type { MothershipResource } from '@/app/workspace/[workspaceId]/home/types' +import type { + MothershipResource, + MothershipResourceType, +} from '@/app/workspace/[workspaceId]/home/types' import type { ChatContext } from '@/stores/panel' export interface SpeechRecognitionEvent extends Event { @@ -72,29 +75,26 @@ export function autoResizeTextarea(e: React.FormEvent, maxH target.style.height = `${Math.min(target.scrollHeight, maxHeight)}px` } +/** + * Maps a {@link MothershipResource} (resource-picker domain) to a + * {@link ChatContext} (chat-input domain). Keyed by `MothershipResourceType` + * so adding a new resource type fails compilation here until a conversion is + * supplied — preventing silent drift between the two taxonomies. + */ +const RESOURCE_TO_CONTEXT: Record< + MothershipResourceType, + (resource: MothershipResource) => ChatContext +> = { + workflow: (r) => ({ kind: 'workflow', workflowId: r.id, label: r.title }), + knowledgebase: (r) => ({ kind: 'knowledge', knowledgeId: r.id, label: r.title }), + table: (r) => ({ kind: 'table', tableId: r.id, label: r.title }), + file: (r) => ({ kind: 'file', fileId: r.id, label: r.title }), + folder: (r) => ({ kind: 'folder', folderId: r.id, label: r.title }), + task: (r) => ({ kind: 'past_chat', chatId: r.id, label: r.title }), + log: (r) => ({ kind: 'logs', executionId: r.id, label: r.title }), + generic: (r) => ({ kind: 'docs', label: r.title }), +} + export function mapResourceToContext(resource: MothershipResource): ChatContext { - switch (resource.type) { - case 'workflow': - return { - kind: 'workflow', - workflowId: resource.id, - label: resource.title, - } - case 'knowledgebase': - return { - kind: 'knowledge', - knowledgeId: resource.id, - label: resource.title, - } - case 'table': - return { kind: 'table', tableId: resource.id, label: resource.title } - case 'file': - return { kind: 'file', fileId: resource.id, label: resource.title } - case 'folder': - return { kind: 'folder', folderId: resource.id, label: resource.title } - case 'task': - return { kind: 'past_chat', chatId: resource.id, label: resource.title } - default: - return { kind: 'docs', label: resource.title } - } + return RESOURCE_TO_CONTEXT[resource.type](resource) } From 32aa646f4309b36bb1a00ce065a42fe1db44f484 Mon Sep 17 00:00:00 2001 From: Waleed Latif Date: Fri, 1 May 2026 22:14:07 -0700 Subject: [PATCH 2/3] fix(home): fallback to docs context for unknown resource types --- .../home/components/user-input/components/constants.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/apps/sim/app/workspace/[workspaceId]/home/components/user-input/components/constants.ts b/apps/sim/app/workspace/[workspaceId]/home/components/user-input/components/constants.ts index 59d31ed8615..065ec0f8089 100644 --- a/apps/sim/app/workspace/[workspaceId]/home/components/user-input/components/constants.ts +++ b/apps/sim/app/workspace/[workspaceId]/home/components/user-input/components/constants.ts @@ -96,5 +96,7 @@ const RESOURCE_TO_CONTEXT: Record< } export function mapResourceToContext(resource: MothershipResource): ChatContext { - return RESOURCE_TO_CONTEXT[resource.type](resource) + const converter = RESOURCE_TO_CONTEXT[resource.type] + if (!converter) return { kind: 'docs', label: resource.title } + return converter(resource) } From 13409d7d46d590920038aeb346ef6bba5ab4c89b Mon Sep 17 00:00:00 2001 From: Waleed Latif Date: Fri, 1 May 2026 22:16:59 -0700 Subject: [PATCH 3/3] revert(home): drop unneeded mapResourceToContext fallback --- .../home/components/user-input/components/constants.ts | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/apps/sim/app/workspace/[workspaceId]/home/components/user-input/components/constants.ts b/apps/sim/app/workspace/[workspaceId]/home/components/user-input/components/constants.ts index 065ec0f8089..59d31ed8615 100644 --- a/apps/sim/app/workspace/[workspaceId]/home/components/user-input/components/constants.ts +++ b/apps/sim/app/workspace/[workspaceId]/home/components/user-input/components/constants.ts @@ -96,7 +96,5 @@ const RESOURCE_TO_CONTEXT: Record< } export function mapResourceToContext(resource: MothershipResource): ChatContext { - const converter = RESOURCE_TO_CONTEXT[resource.type] - if (!converter) return { kind: 'docs', label: resource.title } - return converter(resource) + return RESOURCE_TO_CONTEXT[resource.type](resource) }