From 47e24692d41eb01440f1455b74a9f907eff29c7e Mon Sep 17 00:00:00 2001 From: Waleed Latif Date: Sat, 8 Aug 2026 13:29:37 -0700 Subject: [PATCH 1/2] refactor(resources): one canonical view per resource, mounted on source/grants/host --- .claude/rules/canon.md | 50 + .claude/rules/sim-resource-views.md | 164 ++ .cursor/rules/sim-resource-views.mdc | 99 + CLAUDE.md | 17 +- apps/sim/AGENTS.md | 8 + apps/sim/app/(auth)/components/auth-shell.tsx | 19 +- .../(interfaces)/chat/[identifier]/chat.tsx | 4 +- .../chat/components/header/header.tsx | 87 +- .../chat/components/input/input.tsx | 2 +- apps/sim/app/(landing)/components/index.ts | 1 + .../landing-preview-home.tsx | 11 +- .../components/logo-shell/logo-shell.tsx | 25 +- .../components/navbar-shell/navbar-shell.tsx | 10 +- .../(landing)/components/navbar/navbar.tsx | 148 +- .../components/share-button/share-button.tsx | 7 +- .../components/share-link-button/index.ts | 1 + .../share-link-button/share-link-button.tsx | 84 + .../feature-graphics/deploy-graphic.tsx | 2 +- .../_shell/desktop-title-bar-surfaces.test.ts | 2 +- .../app/_shell/providers/theme-provider.tsx | 1 + apps/sim/app/api/chat/[identifier]/route.ts | 42 +- .../public/[token]/content/route.test.ts | 52 +- .../api/files/public/[token]/content/route.ts | 118 +- .../files/public/[token]/inline/route.test.ts | 65 +- .../api/files/public/[token]/inline/route.ts | 16 +- .../app/api/files/public/[token]/otp/route.ts | 15 +- .../api/files/public/[token]/route.test.ts | 22 +- .../sim/app/api/files/public/[token]/route.ts | 10 +- .../app/api/files/serve/[...path]/route.ts | 79 +- apps/sim/app/api/files/utils.test.ts | 138 ++ apps/sim/app/api/files/utils.ts | 130 +- apps/sim/app/api/logs/triggers/route.ts | 3 +- apps/sim/app/api/tools/file/manage/route.ts | 9 +- .../tools/tiktok/upload-video-draft/upload.ts | 5 +- .../app/api/workflows/[id]/execute/route.ts | 46 +- .../[id]/files/[fileId]/share/route.test.ts | 40 +- .../[id]/files/[fileId]/share/route.ts | 7 +- apps/sim/app/f/[token]/opengraph-image.tsx | 2 +- apps/sim/app/f/[token]/page.tsx | 56 +- apps/sim/app/f/[token]/public-file-view.tsx | 144 +- apps/sim/app/f/[token]/utils.ts | 9 - .../components/folders/folder-breadcrumbs.ts | 2 +- .../components/folders/folder-row.tsx | 5 +- .../folders/use-folder-row-drag-drop.ts | 2 +- .../[workspaceId]/components/index.ts | 74 +- .../invite-modal/invite-modal.test.tsx | 2 +- .../components/invite-modal/invite-modal.tsx | 2 +- .../message-actions/message-actions.tsx | 8 +- .../resource/components/owner-cell/index.ts | 1 - .../components/share-modal/index.ts | 1 + .../components/share-modal/share-modal.tsx | 210 ++ .../files/[fileId]/view/file-viewer.tsx | 36 - .../[fileId]/view/fullscreen-file-view.tsx | 35 + .../files/[fileId]/view/page.tsx | 4 +- .../file-row-context-menu.tsx | 76 +- .../file-viewer/editor-context-menu.tsx | 114 -- .../components/file-viewer/file-viewer.tsx | 428 ---- .../files/components/file-viewer/index.ts | 10 - .../rich-markdown-editor/image.test.ts | 42 - .../mention/mention-chip.test.tsx | 78 - .../mention/mention-chip.tsx | 69 - .../mention/sim-link.test.ts | 22 - .../rich-markdown-editor/mention/sim-link.ts | 38 - .../files-list-context-menu.tsx | 20 +- .../files/components/share-modal/index.ts | 1 - .../components/share-modal/share-modal.tsx | 248 --- .../workspace/[workspaceId]/files/files.tsx | 122 +- .../credits-chip/credits-chip.test.tsx | 2 +- .../components/credits-chip/credits-chip.tsx | 2 +- .../[workspaceId]/home/components/index.ts | 2 - .../components/chat-content/index.ts | 1 - .../message-content/components/index.ts | 3 +- .../components/special-tags/index.ts | 10 +- .../special-tags/special-tags.test.ts | 6 +- .../special-tags/special-tags.test.tsx | 8 +- .../components/special-tags/special-tags.tsx | 1391 +------------ .../message-content/message-content.tsx | 5 +- .../mothership-chat/mothership-chat.tsx | 23 +- .../add-resource-dropdown.tsx | 2 +- .../mothership-view/components/index.ts | 2 +- .../terminal-session/terminal-session.tsx | 2 +- .../components/resource-content/index.ts | 2 +- .../resource-content/resource-content.tsx | 925 +++++---- .../resource-tabs/resource-tabs.tsx | 2 +- .../mothership-view/mothership-view.tsx | 12 +- .../queued-messages/queued-messages.tsx | 2 +- .../suggested-actions/suggested-actions.tsx | 38 +- .../prompt-editor/prompt-editor.tsx | 2 +- .../app/workspace/[workspaceId]/home/home.tsx | 2 +- .../app/workspace/[workspaceId]/home/types.ts | 53 +- .../hooks/use-workspace-invalidation-room.ts | 2 +- .../[block]/integration-block-detail.tsx | 2 +- .../chunk-context-menu/chunk-context-menu.tsx | 136 +- .../[id]/[documentId]/components/index.ts | 1 - .../knowledge/[id]/[documentId]/document.tsx | 14 +- .../[workspaceId]/knowledge/[id]/base.tsx | 1731 ----------------- .../connector-config-fields/index.ts | 1 - .../connector-selector-field/index.ts | 1 - .../document-context-menu.tsx | 158 -- .../knowledge/[id]/knowledge-route.tsx | 49 + .../[workspaceId]/knowledge/[id]/page.tsx | 4 +- .../create-base-modal/create-base-modal.tsx | 2 +- .../components/icons/document-icons.tsx | 293 --- .../knowledge/components/icons/index.ts | 15 - .../knowledge/components/index.ts | 1 - .../knowledge-base-context-menu.tsx | 138 +- .../knowledge-list-context-menu.tsx | 52 +- .../[workspaceId]/knowledge/knowledge.tsx | 41 +- .../workspace/[workspaceId]/layout.test.tsx | 4 +- .../app/workspace/[workspaceId]/layout.tsx | 4 +- .../components/line-chart/line-chart.tsx | 3 +- .../workflows-list/workflows-list.tsx | 2 +- .../[workspaceId]/logs/components/index.ts | 5 +- .../logs/components/log-details/index.ts | 3 +- .../components/log-details/log-details.tsx | 729 +------ .../log-row-context-menu.tsx | 125 +- .../[workspaceId]/logs/hooks/index.ts | 1 - .../app/workspace/[workspaceId]/logs/logs.tsx | 24 +- .../app/workspace/[workspaceId]/logs/utils.ts | 192 +- .../workspace-permissions-provider.tsx | 2 +- .../settings/[section]/settings.tsx | 2 +- .../components/skill-fields/skill-fields.tsx | 3 +- .../components/skill-modal/skill-modal.tsx | 2 +- .../table-grid/cells/cell-content.tsx | 73 - .../[tableId]/components/table-grid/types.ts | 37 - .../[workspaceId]/tables/[tableId]/page.tsx | 10 +- .../tables/[tableId]/table-route.tsx | 53 + .../[workspaceId]/tables/[tableId]/types.ts | 38 - .../[workspaceId]/tables/components/index.ts | 2 - .../table-context-menu/table-context-menu.tsx | 144 +- .../tables-list-context-menu.tsx | 70 +- .../[workspaceId]/tables/prefetch.ts | 4 +- .../workspace/[workspaceId]/tables/tables.tsx | 46 +- .../[workspaceId]/upgrade/upgrade.tsx | 2 +- .../components/chat-message/chat-message.tsx | 2 +- .../components/cursors/cursors.tsx | 2 +- .../deploy-modal/components/chat/chat.tsx | 6 +- .../components/version-description-modal.tsx | 2 +- .../credential-selector.tsx | 2 +- .../components/tools/credential-selector.tsx | 2 +- .../workflow-selector-input.tsx | 2 +- .../panel/components/editor/editor.tsx | 3 +- .../panel/components/toolbar/toolbar.tsx | 3 +- .../w/[workflowId]/components/panel/panel.tsx | 2 +- .../components/subflows/loop/index.ts | 2 +- .../components/subflows/loop/loop-config.ts | 13 - .../components/subflows/parallel/index.ts | 2 +- .../subflows/parallel/parallel-config.ts | 13 - .../components/output-panel/output-panel.tsx | 2 +- .../components/terminal/terminal.tsx | 2 +- .../[workspaceId]/w/[workflowId]/workflow.tsx | 4 +- .../preview-editor/preview-editor.tsx | 4 +- .../components/search-modal/search-modal.tsx | 131 +- .../settings-sidebar/settings-sidebar.tsx | 2 +- .../sidebar-footer/sidebar-footer.tsx | 2 +- .../components/folder-item/folder-item.tsx | 2 +- .../workflow-item/avatars/avatars.tsx | 4 +- .../workflow-item/workflow-item.tsx | 2 +- .../workflow-list/workflow-list.tsx | 2 +- .../w/components/sidebar/hooks/index.ts | 1 - .../w/components/sidebar/sidebar.tsx | 2 +- apps/sim/app/workspace/layout.tsx | 2 +- apps/sim/blocks/subflow-tools.ts | 25 + apps/sim/components/action-row/action-row.tsx | 43 + apps/sim/components/action-row/index.ts | 1 + .../anchored-context-menu.tsx | 58 + .../components/anchored-context-menu/index.ts | 2 + .../use-context-menu.ts | 0 .../chat}/chat-content/chat-content.test.ts | 4 +- .../chat}/chat-content/chat-content.tsx | 76 +- .../chat}/chat-content/chat-sanitize.ts | 0 .../chat}/chat-content/external-link.tsx | 0 .../sim/components/chat/chat-content/index.ts | 2 + .../chat-context-kind-registry.tsx | 2 +- .../chat}/chat-context-kind-registry/index.ts | 0 .../chat-copy-button/chat-copy-button.tsx | 65 + .../components/chat/chat-copy-button/index.ts | 1 + .../chat-message-attachments.tsx | 2 +- .../chat}/chat-message-attachments/index.ts | 0 .../context-mention-icon.tsx | 4 +- .../chat}/context-mention-icon/index.ts | 0 apps/sim/components/chat/index.ts | 16 + .../chat/pending-tag-indicator/index.ts | 1 + .../pending-tag-indicator.tsx | 23 + .../components/chat/scaling-test-helpers.ts | 39 + .../sim/components/chat/special-tags/parse.ts | 1405 +++++++++++++ apps/sim/components/chat/turn-layout.ts | 50 + apps/sim/components/chat/types.ts | 54 + .../chat}/user-message-content/index.ts | 0 .../user-message-content.tsx | 4 +- .../connect-oauth-modal.tsx | 0 .../components/connect-oauth-modal/index.ts | 0 .../execution-status/execution-status.tsx | 79 + apps/sim/components/execution-status/index.ts | 6 + .../components/inline-rename-input/index.ts | 0 .../inline-rename-input.tsx | 0 apps/sim/components/presence/index.ts | 1 + .../components/presence/presence-avatars.tsx | 0 apps/sim/components/public-share/index.ts | 5 + .../public-share-auth-shell/index.ts | 1 + .../public-share-auth-shell.tsx} | 8 +- .../public-share-email-auth/index.ts | 1 + .../public-share-email-auth.tsx} | 34 +- .../public-share-password-auth/index.ts | 1 + .../public-share-password-auth.tsx} | 26 +- .../public-share-sso-auth/index.ts | 1 + .../public-share-sso-auth.tsx} | 41 +- apps/sim/components/public-share/types.ts | 13 + .../components/floating-overflow-text.tsx | 0 .../resource/components/owner-cell/index.ts | 1 + .../components/owner-cell/owner-cell.tsx | 24 +- .../resource-chrome-fallback/index.ts | 0 .../resource-chrome-fallback.tsx | 7 +- .../components/resource-header/index.ts | 0 .../resource-header/resource-header.tsx | 2 +- .../components/resource-options/index.ts | 0 .../resource-options.test.tsx | 2 +- .../resource-options/resource-options.tsx | 2 +- .../resource/components/time-cell.ts | 2 +- apps/sim/components/resource/index.ts | 45 + .../components/resource/resource.tsx | 8 +- .../resource/use-background-context-menu.ts | 31 + .../resources/MIGRATING-RESOURCES.md | 253 +++ .../csv-table-preview}/csv-table-preview.tsx | 23 +- .../components/csv-table-preview/index.ts | 1 + .../components/data-table}/data-table.tsx | 2 +- .../file-view/components/data-table/index.ts | 1 + .../file-view/components}/document-table.css | 0 .../components}/document-table.test.ts | 0 .../components/docx-preview}/docx-preview.tsx | 25 +- .../components/docx-preview/index.ts | 1 + .../editor-context-menu.tsx | 87 + .../components/editor-context-menu/index.ts | 1 + .../image-preview}/image-preview.test.tsx | 33 +- .../image-preview}/image-preview.tsx | 24 +- .../components/image-preview/index.ts | 1 + .../components/mermaid-diagram/index.ts | 1 + .../mermaid-diagram}/mermaid-diagram.test.ts | 0 .../mermaid-diagram}/mermaid-diagram.tsx | Bin 7062 -> 7178 bytes .../file-view/components/pdf-viewer/index.ts | 1 + .../components/pdf-viewer}/pdf-viewer.tsx | 6 +- .../components/pptx-preview/index.ts | 1 + .../components/pptx-preview}/pptx-preview.tsx | 18 +- .../components/pptx-sandbox-host/index.ts | 1 + .../pptx-sandbox-host}/pptx-sandbox-host.tsx | 4 +- .../components/preview-panel/index.ts | 1 + .../preview-panel}/preview-panel.tsx | 29 +- .../components/preview-shared/index.ts | 1 + .../preview-shared}/preview-shared.tsx | 42 +- .../components/preview-toolbar/index.ts | 1 + .../preview-toolbar}/preview-toolbar.tsx | 0 .../rich-markdown-editor/block-mover.ts | 0 .../rich-markdown-editor/code-block-schema.ts | 0 .../rich-markdown-editor/code-block.tsx | 5 +- .../code-highlight.test.ts | 0 .../rich-markdown-editor/code-highlight.ts | 0 .../code-languages.test.ts | 0 .../collaboration/agent-stream-leader.test.ts | 0 .../collaboration/agent-stream-leader.ts | 0 ...apply-streamed-markdown.concurrent.test.ts | 0 .../apply-streamed-markdown.test.ts | 0 .../collaboration/apply-streamed-markdown.ts | 0 .../collaboration/caret-presence.test.ts | 0 .../collaboration/caret-presence.ts | 0 .../collab-streaming-integration.test.ts | 0 .../collaboration/file-doc-avatars.tsx | 2 +- .../collaboration/file-doc-provider.test.ts | 0 .../collaboration/file-doc-provider.ts | 0 .../collaboration/file-doc-room-context.tsx | 2 +- .../collaboration/readiness.test.ts | 0 .../collaboration/readiness.ts | 0 .../use-file-doc-collaboration.ts | 2 +- .../detect-language.test.ts | 0 .../rich-markdown-editor/detect-language.ts | 0 .../dirty-on-open.test.ts | 0 .../rich-markdown-editor/dirty-signal.test.ts | 0 .../rich-markdown-editor/editor-extensions.ts | 6 +- .../rich-markdown-editor/embed/embed-dom.ts | 0 .../embed/link-embed.test.ts | 2 +- .../rich-markdown-editor/embed/link-embed.ts | 0 .../rich-markdown-editor/extensions.ts | 0 .../heading-anchors.test.ts | 0 .../rich-markdown-editor/heading-anchors.ts | 0 .../rich-markdown-editor/highlight.ts | 0 .../rich-markdown-editor/image-paste.test.ts | 31 +- .../rich-markdown-editor/image-paste.ts | 2 +- .../rich-markdown-editor/image-schema.ts | 0 .../rich-markdown-editor/image.test.ts | 44 + .../rich-markdown-editor/image.tsx | 26 +- .../rich-markdown-editor/keymap.test.ts | 2 +- .../rich-markdown-editor/keymap.ts | 2 +- .../link-input-rule.test.ts | 0 .../rich-markdown-editor/link-input-rule.ts | 0 .../link-mark-precedence.test.ts | 0 .../markdown-fidelity.test.ts | 0 .../rich-markdown-editor/markdown-fidelity.ts | 0 .../markdown-parse.test.ts | 0 .../rich-markdown-editor/markdown-parse.ts | 0 .../markdown-paste.test.ts | 0 .../rich-markdown-editor/markdown-paste.ts | 0 .../rich-markdown-editor/mention/index.ts | 0 .../mention/mention-chip.test.tsx | 176 ++ .../mention/mention-chip.tsx | 131 ++ .../mention/mention-icon.test.ts | 0 .../mention/mention-icon.ts | 0 .../mention/mention-list.test.tsx | 2 +- .../mention/mention-list.tsx | 4 +- .../mention/mention-node.test.ts | 5 +- .../mention/mention-node.ts | 0 .../mention/mention-store.ts | 0 .../rich-markdown-editor/mention/mention.ts | 2 +- .../mention/sim-link.test.ts | 36 + .../rich-markdown-editor/mention/sim-link.ts | 44 + .../rich-markdown-editor/mention/types.ts | 0 .../mention/use-editor-mentions.ts | 0 .../mention/use-markdown-mentions.ts | 0 .../menus/bubble-menu.tsx | 0 .../menus/link-editing.tsx | 2 +- .../menus/link-hover-card.tsx | 2 +- .../menus/suggestion-list.tsx | 0 .../menus/suggestion-menu-chrome.ts | 0 .../menus/suggestion-popup.ts | 0 .../menus/table-menu.test.ts | 2 +- .../rich-markdown-editor/menus/table-menu.tsx | 0 .../menus/toolbar-button.tsx | 0 .../menus/use-bubble-menu-floating.ts | 0 .../menus/use-suggestion-keyboard.ts | 0 .../rich-markdown-editor/normalize-content.ts | 0 .../raw-markdown-snippet-schema.ts | 0 .../raw-markdown-snippet-view.test.ts | 0 .../raw-markdown-snippet.test.ts | 0 .../raw-markdown-snippet.tsx | 0 .../rich-markdown-editor.css | 0 .../rich-markdown-editor.tsx | 98 +- .../rich-markdown-field.tsx | 4 +- .../round-trip-safety.test.ts | 0 .../rich-markdown-editor/round-trip-safety.ts | 0 .../rich-markdown-editor/round-trip.test.ts | 0 .../slash-command/commands.test.ts | 0 .../slash-command/commands.ts | 0 .../slash-command/slash-command-list.tsx | 4 +- .../slash-command/slash-command.ts | 2 +- .../stream-settle-selection.test.ts | 0 .../title-heading.test.ts | 0 .../rich-markdown-editor/title-heading.ts | 0 .../use-editor-editable.ts | 0 .../file-view/components/text-editor/index.ts | 1 + .../components/text-editor}/text-editor.tsx | 37 +- .../use-selection-copy-bridge.test.tsx | 0 .../components}/use-selection-copy-bridge.ts | 0 .../components/xlsx-preview/index.ts | 1 + .../components/xlsx-preview}/xlsx-preview.tsx | 22 +- .../components/zoomable-preview/index.ts | 1 + .../zoomable-preview}/zoomable-preview.tsx | 4 +- .../resources/file-view/file-view.tsx | 536 +++++ .../resources/file-view/hooks}/csv-import.ts | 8 +- .../hooks}/use-doc-preview-binary.test.ts | 0 .../hooks}/use-doc-preview-binary.ts | 10 +- .../hooks}/use-editable-file-content.test.tsx | 18 +- .../hooks}/use-editable-file-content.ts | 26 +- .../components/resources/file-view/index.ts | 16 + .../file-view/utils}/file-category.test.ts | 0 .../file-view/utils}/file-category.ts | 0 .../file-view/utils}/preview-wheel-zoom.ts | 0 .../utils}/text-editor-state.test.ts | 0 .../file-view/utils}/text-editor-state.ts | 0 .../components/action-bar/action-bar.tsx | 13 +- .../components/action-bar/index.ts | 0 .../add-connector-modal.tsx | 14 +- .../components/add-connector-modal/index.ts | 0 .../add-documents-modal.tsx | 14 +- .../components/add-documents-modal/index.ts | 0 .../base-tags-modal/base-tags-modal.tsx | 2 +- .../components/base-tags-modal/index.ts | 0 .../connector-config-fields.tsx | 7 +- .../connector-config-fields/index.ts | 1 + .../components/connector-entitlements.test.ts | 2 +- .../components/connector-entitlements.ts | 0 .../connector-selector-field.tsx | 5 +- .../connector-selector-field/index.ts | 1 + .../connectors-section/connectors-section.tsx | 4 +- .../components/connectors-section/index.ts | 0 .../knowledge-view}/components/consts.ts | 0 .../document-context-menu.tsx | 126 ++ .../components/document-context-menu/index.ts | 0 .../document-list/document-list.tsx | 395 ++++ .../components/document-list/index.ts | 7 + .../document-tags-cell/document-tags-cell.tsx | 41 + .../components/document-tags-cell/index.ts | 1 + .../document-tags-modal.tsx | 0 .../components/document-tags-modal/index.ts | 0 .../edit-connector-modal.tsx | 17 +- .../components/edit-connector-modal/index.ts | 0 .../knowledge-view}/components/index.ts | 1 - .../knowledge-view}/components/max-badge.tsx | 0 .../components/rename-document-modal/index.ts | 0 .../rename-document-modal.tsx | 0 .../components/search-highlight/index.ts | 0 .../search-highlight/search-highlight.tsx | 0 .../components/tag-filter-panel/index.ts | 7 + .../tag-filter-panel/tag-filter-panel.tsx | 297 +++ .../resources/knowledge-view/index.ts | 19 + .../knowledge-view/knowledge-view.tsx | 1003 ++++++++++ .../knowledge-view/utils/document-rows.tsx | 100 + .../execution-snapshot/execution-snapshot.tsx | 8 + .../components/execution-snapshot/index.ts | 0 .../file-download/file-download.tsx | 23 +- .../components/file-download/index.ts | 0 .../log-view}/components/trace-view/index.ts | 0 .../components/trace-view/trace-view.tsx | 4 +- .../components/resources/log-view/index.ts | 16 + .../resources/log-view/log-view.tsx | 745 +++++++ .../log-view/utils/log-presentation.ts | 91 + .../resources/log-view/utils/trace-utils.ts} | 3 +- .../resources/resource-empty-state/index.ts | 2 + .../resource-empty-state.tsx | 42 + .../resources/resource-provider/index.ts | 11 + .../resource-provider/resource-provider.tsx | 116 ++ .../components/cells/cell-content.tsx | 85 + .../components/cells/cell-formatting.test.ts | 75 + .../components/cells/cell-render.test.ts | 161 ++ .../components}/cells/cell-render.tsx | 16 +- .../table-view/components}/cells/index.ts | 3 +- .../components}/cells/sim-resource-cell.tsx | 4 +- .../column-config-sidebar.tsx | 12 +- .../column-config-sidebar/column-types.ts | 0 .../components/column-config-sidebar/index.ts | 0 .../components/columns-menu/columns-menu.tsx | 0 .../components/columns-menu/index.ts | 0 .../components/context-menu/context-menu.tsx | 155 +- .../components/context-menu/index.ts | 0 .../components/data-row}/data-row.tsx | 61 +- .../table-view/components/data-row/index.ts | 1 + .../enrichment-details/enrichment-details.tsx | 8 +- .../components/enrichment-details/index.ts | 0 .../enrichments-sidebar/enrichment-config.tsx | 4 +- .../enrichments-sidebar.tsx | 2 +- .../components/enrichments-sidebar/index.ts | 0 .../execution-slideout/execution-slideout.tsx | 114 ++ .../components/execution-slideout/index.ts | 1 + .../headers/column-header-menu.tsx | 10 +- .../components}/headers/column-type-icon.tsx | 2 +- .../components}/headers/header-label.tsx | 0 .../table-view/components}/headers/index.ts | 0 .../headers/workflow-group-meta-cell.tsx | 6 +- .../resources/table-view}/components/index.ts | 1 + .../components/lock-settings-modal/index.ts | 0 .../lock-settings-modal.tsx | 5 +- .../components/new-column-dropdown/index.ts | 0 .../new-column-dropdown.tsx | 12 +- .../remote-selection-overlay/index.ts | 1 + .../remote-selection-overlay.tsx | 6 +- .../table-view}/components/row-modal/index.ts | 0 .../components/row-modal/row-modal.tsx | 34 +- .../components/run-status-control/index.ts | 0 .../run-status-control/run-status-control.tsx | 0 .../components/save-view-modal/index.ts | 0 .../save-view-modal/save-view-modal.tsx | 0 .../components/select-field/index.ts | 1 - .../select-field/select-options-editor.tsx | 0 .../select-field/select-value-editor.tsx | 2 +- .../components/select-pill/index.ts | 6 + .../components/select-pill}/select-pill.tsx | 0 .../components/sidebar-fields/index.ts | 0 .../sidebar-fields/sidebar-fields.tsx | 0 .../components/table-action-bar/index.ts | 0 .../table-action-bar/table-action-bar.tsx | 0 .../components/table-filter/index.ts | 0 .../components/table-filter/table-filter.tsx | 0 .../table-view/components/table-find/index.ts | 1 + .../components/table-find}/table-find.tsx | 0 .../cells/expanded-cell-popover.tsx | 11 +- .../components/table-grid/cells/index.ts | 2 + .../table-grid/cells/inline-editors.tsx | 15 +- .../components/table-grid/index.ts | 0 .../components/table-grid/table-grid.tsx | 208 +- .../components/table-primitives/index.ts | 1 + .../table-primitives}/table-primitives.tsx | 8 +- .../components/views-menu/index.ts | 0 .../components/views-menu/views-menu.tsx | 0 .../components/workflow-sidebar/index.ts | 0 .../input-mapping-section.tsx | 0 .../workflow-sidebar/run-settings-section.tsx | 0 .../workflow-sidebar/workflow-sidebar.tsx | 24 +- .../resources/table-view}/hooks/index.ts | 0 .../table-view}/hooks/use-context-menu.ts | 2 +- .../hooks/use-table-event-stream.test.ts | 2 +- .../hooks/use-table-event-stream.ts | 0 .../table-view}/hooks/use-table-room.ts | 14 +- .../table-view}/hooks/use-table.test.ts | 2 +- .../resources/table-view}/hooks/use-table.ts | 4 +- .../components/resources/table-view/index.ts | 105 + .../resources/table-view/table-view.tsx} | 315 +-- .../components/resources/table-view/types.ts | 90 + .../resources/table-view/utils}/constants.ts | 0 .../resources/table-view/utils}/lock-copy.ts | 0 .../table-view/utils/selection.test.ts} | 14 +- .../resources/table-view/utils/selection.ts} | 2 +- .../table-view/utils/values.test.ts} | 2 +- .../resources/table-view/utils/values.ts} | 0 apps/sim/components/socket-provider/index.ts | 10 + .../socket-join-controller.test.ts | 2 +- .../socket-join-controller.ts | 0 .../socket-join-target.test.ts | 2 +- .../socket-provider}/socket-join-target.ts | 0 .../socket-provider}/socket-provider.tsx | 6 +- .../import-csv-dialog/import-csv-dialog.tsx | 0 .../table-import}/import-csv-dialog/index.ts | 0 .../import-progress-menu.tsx | 0 .../import-progress-menu/import-stage.ts | 0 .../import-progress-menu/index.ts | 0 .../use-workspace-imports.ts | 0 apps/sim/components/table-import/index.ts | 11 + ....test.tsx => chip-password-input.test.tsx} | 60 +- .../ui/generated-password-input.tsx | 163 -- apps/sim/components/ui/index.ts | 1 - .../workspace-host-provider/index.ts | 5 + .../workspace-access-denied.tsx | 0 .../workspace-host-provider.tsx | 2 +- apps/sim/executor/utils/start-block.test.ts | 122 ++ .../kb}/use-connector-config-fields.ts | 0 apps/sim/hooks/kb/use-knowledge-list-state.ts | 238 +++ .../kb}/use-knowledge-upload.ts | 0 apps/sim/hooks/queries/public-shares.ts | 79 +- apps/sim/hooks/queries/tables.test.ts | 2 +- apps/sim/hooks/queries/tables.ts | 61 +- .../queries/utils/mutation-error-toast.ts | 24 + .../hooks/queries/workspace-files.test.tsx | 5 +- apps/sim/hooks/queries/workspace-files.ts | 47 +- apps/sim/hooks/use-collaborative-workflow.ts | 2 +- apps/sim/hooks/use-drag-reorder.ts | 105 + apps/sim/hooks/use-execution-stream.ts | 47 +- apps/sim/hooks/use-file-content-source.tsx | 142 -- .../logs => }/hooks/use-log-details-resize.ts | 0 apps/sim/hooks/use-settings-navigation.ts | 2 +- apps/sim/hooks/use-share-modal-state.test.tsx | 327 ++++ apps/sim/hooks/use-share-modal-state.ts | 199 ++ .../sim/hooks/use-table-detail-state.test.tsx | 135 ++ apps/sim/hooks/use-table-detail-state.ts | 90 + apps/sim/lib/api/contracts/chats.ts | 2 + apps/sim/lib/api/contracts/primitives.ts | 16 +- apps/sim/lib/api/contracts/public-shares.ts | 12 + apps/sim/lib/api/contracts/tables.ts | 11 +- apps/sim/lib/collab-doc/converter.test.ts | 4 +- apps/sim/lib/collab-doc/converter.ts | 9 +- apps/sim/lib/collab-doc/merge.test.ts | 2 +- apps/sim/lib/collab-doc/merge.ts | 3 +- apps/sim/lib/collab-doc/seed.test.ts | 2 +- apps/sim/lib/collab-doc/seed.ts | 3 +- apps/sim/lib/compare/data/sim.ts | 4 +- apps/sim/lib/copilot/resources/types.ts | 1 + .../copilot/tools/handlers/resources.test.ts | 59 + .../sim/lib/copilot/tools/server/base-tool.ts | 21 + .../copilot/tools/server/files/share-file.ts | 9 +- .../copilot/tools/server/table/user-table.ts | 5 +- apps/sim/lib/copilot/tools/tool-display.ts | 2 + apps/sim/lib/copilot/vfs/path-utils.test.ts | 4 +- apps/sim/lib/copilot/vfs/path-utils.ts | 5 + apps/sim/lib/core/security/otp.ts | 3 +- apps/sim/lib/core/utils/response-format.ts | 21 + apps/sim/lib/core/utils/restore-name.ts | 39 + apps/sim/lib/core/utils/unique-name.test.ts | 41 + apps/sim/lib/core/utils/unique-name.ts | 29 + .../lib/execution/sandbox/bundles/docx.cjs | 42 +- .../lib/execution/sandbox/bundles/pdf-lib.cjs | 42 +- .../execution/sandbox/bundles/pptxgenjs.cjs | 125 +- .../knowledge/detail-search-params.ts} | 0 apps/sim/lib/knowledge/service.ts | 36 +- apps/sim/lib/posthog/events.ts | 18 + apps/sim/lib/public-shares/provenance.ts | 18 + apps/sim/lib/public-shares/rate-limit.ts | 105 +- apps/sim/lib/public-shares/share-gate.ts | 65 + apps/sim/lib/public-shares/share-manager.ts | 52 +- apps/sim/lib/public-shares/urls.ts | 24 + apps/sim/lib/social-share.ts | 24 + .../table/detail-search-params.ts} | 8 +- apps/sim/lib/table/import-runner.ts | 5 +- apps/sim/lib/table/service.ts | 40 +- .../workspace/workspace-file-manager.ts | 28 +- .../storage-service.local-atomicity.test.ts | 122 ++ apps/sim/lib/uploads/core/storage-service.ts | 66 +- apps/sim/lib/uploads/providers/blob/client.ts | 8 +- apps/sim/lib/uploads/providers/gcs/client.ts | 9 +- apps/sim/lib/uploads/providers/s3/client.ts | 15 +- apps/sim/lib/uploads/utils/byte-range.test.ts | 136 ++ apps/sim/lib/uploads/utils/byte-range.ts | 117 ++ apps/sim/lib/uploads/utils/file-utils.test.ts | 26 - apps/sim/lib/uploads/utils/file-utils.ts | 37 +- .../uploads/utils}/untitled-title.test.ts | 0 .../uploads/utils}/untitled-title.ts | 0 .../lib/workflows/executor/execution-core.ts | 19 +- .../executor/human-in-the-loop-manager.ts | 5 +- apps/sim/lib/workflows/labels.ts | 12 + .../streaming/logging-session-completion.ts | 29 + apps/sim/lib/workflows/streaming/streaming.ts | 32 +- apps/sim/lib/workflows/subblocks/display.ts | 2 +- apps/sim/resources/file-source.ts | 174 ++ apps/sim/resources/grants.test.ts | 129 ++ apps/sim/resources/grants.ts | 102 + apps/sim/resources/host.ts | 20 + apps/sim/resources/index.ts | 52 + apps/sim/resources/kinds.ts | 58 + apps/sim/resources/knowledge-source.ts | 45 + .../log-source.test.ts} | 21 +- apps/sim/resources/log-source.ts | 46 + apps/sim/resources/source.test.ts | 252 +++ apps/sim/resources/source.ts | 206 ++ apps/sim/resources/table-source.ts | 26 + package.json | 2 + packages/audit/src/types.ts | 2 + packages/db/schema.ts | 7 +- .../chip-copy-input/chip-copy-input.tsx | 7 +- .../chip-dropdown/chip-dropdown.tsx | 43 +- .../chip-password-input.tsx | 207 ++ .../components/chip-select/chip-select.tsx | 36 +- .../emcn/src/components/chip/chip-chevron.tsx | 7 +- .../emcn/src/components/chip/chip-chrome.ts | 9 + .../emcn/src/components/combobox/combobox.tsx | 25 +- packages/emcn/src/components/index.ts | 5 + .../src/components/tag-input/tag-input.tsx | 31 +- scripts/check-resource-views.ts | 1417 ++++++++++++++ scripts/run-audits.ts | 1 + scripts/sync-agent-stream-docs.ts | 3 +- 623 files changed, 16427 insertions(+), 9149 deletions(-) create mode 100644 .claude/rules/canon.md create mode 100644 .claude/rules/sim-resource-views.md create mode 100644 .cursor/rules/sim-resource-views.mdc create mode 100644 apps/sim/app/(landing)/components/share-link-button/index.ts create mode 100644 apps/sim/app/(landing)/components/share-link-button/share-link-button.tsx delete mode 100644 apps/sim/app/f/[token]/utils.ts delete mode 100644 apps/sim/app/workspace/[workspaceId]/components/resource/components/owner-cell/index.ts create mode 100644 apps/sim/app/workspace/[workspaceId]/components/share-modal/index.ts create mode 100644 apps/sim/app/workspace/[workspaceId]/components/share-modal/share-modal.tsx delete mode 100644 apps/sim/app/workspace/[workspaceId]/files/[fileId]/view/file-viewer.tsx create mode 100644 apps/sim/app/workspace/[workspaceId]/files/[fileId]/view/fullscreen-file-view.tsx delete mode 100644 apps/sim/app/workspace/[workspaceId]/files/components/file-viewer/editor-context-menu.tsx delete mode 100644 apps/sim/app/workspace/[workspaceId]/files/components/file-viewer/file-viewer.tsx delete mode 100644 apps/sim/app/workspace/[workspaceId]/files/components/file-viewer/index.ts delete mode 100644 apps/sim/app/workspace/[workspaceId]/files/components/file-viewer/rich-markdown-editor/image.test.ts delete mode 100644 apps/sim/app/workspace/[workspaceId]/files/components/file-viewer/rich-markdown-editor/mention/mention-chip.test.tsx delete mode 100644 apps/sim/app/workspace/[workspaceId]/files/components/file-viewer/rich-markdown-editor/mention/mention-chip.tsx delete mode 100644 apps/sim/app/workspace/[workspaceId]/files/components/file-viewer/rich-markdown-editor/mention/sim-link.test.ts delete mode 100644 apps/sim/app/workspace/[workspaceId]/files/components/file-viewer/rich-markdown-editor/mention/sim-link.ts delete mode 100644 apps/sim/app/workspace/[workspaceId]/files/components/share-modal/index.ts delete mode 100644 apps/sim/app/workspace/[workspaceId]/files/components/share-modal/share-modal.tsx delete mode 100644 apps/sim/app/workspace/[workspaceId]/home/components/message-content/components/chat-content/index.ts delete mode 100644 apps/sim/app/workspace/[workspaceId]/knowledge/[id]/base.tsx delete mode 100644 apps/sim/app/workspace/[workspaceId]/knowledge/[id]/components/connector-config-fields/index.ts delete mode 100644 apps/sim/app/workspace/[workspaceId]/knowledge/[id]/components/connector-selector-field/index.ts delete mode 100644 apps/sim/app/workspace/[workspaceId]/knowledge/[id]/components/document-context-menu/document-context-menu.tsx create mode 100644 apps/sim/app/workspace/[workspaceId]/knowledge/[id]/knowledge-route.tsx delete mode 100644 apps/sim/app/workspace/[workspaceId]/knowledge/components/icons/document-icons.tsx delete mode 100644 apps/sim/app/workspace/[workspaceId]/knowledge/components/icons/index.ts delete mode 100644 apps/sim/app/workspace/[workspaceId]/logs/hooks/index.ts delete mode 100644 apps/sim/app/workspace/[workspaceId]/tables/[tableId]/components/table-grid/cells/cell-content.tsx delete mode 100644 apps/sim/app/workspace/[workspaceId]/tables/[tableId]/components/table-grid/types.ts create mode 100644 apps/sim/app/workspace/[workspaceId]/tables/[tableId]/table-route.tsx delete mode 100644 apps/sim/app/workspace/[workspaceId]/tables/[tableId]/types.ts delete mode 100644 apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/subflows/loop/loop-config.ts delete mode 100644 apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/subflows/parallel/parallel-config.ts create mode 100644 apps/sim/blocks/subflow-tools.ts create mode 100644 apps/sim/components/action-row/action-row.tsx create mode 100644 apps/sim/components/action-row/index.ts create mode 100644 apps/sim/components/anchored-context-menu/anchored-context-menu.tsx create mode 100644 apps/sim/components/anchored-context-menu/index.ts rename apps/sim/{app/workspace/[workspaceId]/w/components/sidebar/hooks => components/anchored-context-menu}/use-context-menu.ts (100%) rename apps/sim/{app/workspace/[workspaceId]/home/components/message-content/components => components/chat}/chat-content/chat-content.test.ts (96%) rename apps/sim/{app/workspace/[workspaceId]/home/components/message-content/components => components/chat}/chat-content/chat-content.tsx (91%) rename apps/sim/{app/workspace/[workspaceId]/home/components/message-content/components => components/chat}/chat-content/chat-sanitize.ts (100%) rename apps/sim/{app/workspace/[workspaceId]/home/components/message-content/components => components/chat}/chat-content/external-link.tsx (100%) create mode 100644 apps/sim/components/chat/chat-content/index.ts rename apps/sim/{app/workspace/[workspaceId]/home/components => components/chat}/chat-context-kind-registry/chat-context-kind-registry.tsx (97%) rename apps/sim/{app/workspace/[workspaceId]/home/components => components/chat}/chat-context-kind-registry/index.ts (100%) create mode 100644 apps/sim/components/chat/chat-copy-button/chat-copy-button.tsx create mode 100644 apps/sim/components/chat/chat-copy-button/index.ts rename apps/sim/{app/workspace/[workspaceId]/home/components => components/chat}/chat-message-attachments/chat-message-attachments.tsx (96%) rename apps/sim/{app/workspace/[workspaceId]/home/components => components/chat}/chat-message-attachments/index.ts (100%) rename apps/sim/{app/workspace/[workspaceId]/home/components => components/chat}/context-mention-icon/context-mention-icon.tsx (70%) rename apps/sim/{app/workspace/[workspaceId]/home/components => components/chat}/context-mention-icon/index.ts (100%) create mode 100644 apps/sim/components/chat/index.ts create mode 100644 apps/sim/components/chat/pending-tag-indicator/index.ts create mode 100644 apps/sim/components/chat/pending-tag-indicator/pending-tag-indicator.tsx create mode 100644 apps/sim/components/chat/scaling-test-helpers.ts create mode 100644 apps/sim/components/chat/special-tags/parse.ts create mode 100644 apps/sim/components/chat/turn-layout.ts create mode 100644 apps/sim/components/chat/types.ts rename apps/sim/{app/workspace/[workspaceId]/home/components => components/chat}/user-message-content/index.ts (100%) rename apps/sim/{app/workspace/[workspaceId]/home/components => components/chat}/user-message-content/user-message-content.tsx (96%) rename apps/sim/{app/workspace/[workspaceId] => }/components/connect-oauth-modal/connect-oauth-modal.tsx (100%) rename apps/sim/{app/workspace/[workspaceId] => }/components/connect-oauth-modal/index.ts (100%) create mode 100644 apps/sim/components/execution-status/execution-status.tsx create mode 100644 apps/sim/components/execution-status/index.ts rename apps/sim/{app/workspace/[workspaceId] => }/components/inline-rename-input/index.ts (100%) rename apps/sim/{app/workspace/[workspaceId] => }/components/inline-rename-input/inline-rename-input.tsx (100%) create mode 100644 apps/sim/components/presence/index.ts rename apps/sim/{app/workspace/[workspaceId] => }/components/presence/presence-avatars.tsx (100%) create mode 100644 apps/sim/components/public-share/index.ts create mode 100644 apps/sim/components/public-share/public-share-auth-shell/index.ts rename apps/sim/{app/f/[token]/public-file-auth-shell.tsx => components/public-share/public-share-auth-shell/public-share-auth-shell.tsx} (81%) create mode 100644 apps/sim/components/public-share/public-share-email-auth/index.ts rename apps/sim/{app/f/[token]/public-file-email-auth.tsx => components/public-share/public-share-email-auth/public-share-email-auth.tsx} (86%) create mode 100644 apps/sim/components/public-share/public-share-password-auth/index.ts rename apps/sim/{app/f/[token]/public-file-auth.tsx => components/public-share/public-share-password-auth/public-share-password-auth.tsx} (75%) create mode 100644 apps/sim/components/public-share/public-share-sso-auth/index.ts rename apps/sim/{app/f/[token]/public-file-sso-auth.tsx => components/public-share/public-share-sso-auth/public-share-sso-auth.tsx} (69%) create mode 100644 apps/sim/components/public-share/types.ts rename apps/sim/{app/workspace/[workspaceId] => }/components/resource/components/floating-overflow-text.tsx (100%) create mode 100644 apps/sim/components/resource/components/owner-cell/index.ts rename apps/sim/{app/workspace/[workspaceId] => }/components/resource/components/owner-cell/owner-cell.tsx (66%) rename apps/sim/{app/workspace/[workspaceId] => }/components/resource/components/resource-chrome-fallback/index.ts (100%) rename apps/sim/{app/workspace/[workspaceId] => }/components/resource/components/resource-chrome-fallback/resource-chrome-fallback.tsx (93%) rename apps/sim/{app/workspace/[workspaceId] => }/components/resource/components/resource-header/index.ts (100%) rename apps/sim/{app/workspace/[workspaceId] => }/components/resource/components/resource-header/resource-header.tsx (99%) rename apps/sim/{app/workspace/[workspaceId] => }/components/resource/components/resource-options/index.ts (100%) rename apps/sim/{app/workspace/[workspaceId] => }/components/resource/components/resource-options/resource-options.test.tsx (93%) rename apps/sim/{app/workspace/[workspaceId] => }/components/resource/components/resource-options/resource-options.tsx (98%) rename apps/sim/{app/workspace/[workspaceId] => }/components/resource/components/time-cell.ts (95%) create mode 100644 apps/sim/components/resource/index.ts rename apps/sim/{app/workspace/[workspaceId] => }/components/resource/resource.tsx (98%) create mode 100644 apps/sim/components/resource/use-background-context-menu.ts create mode 100644 apps/sim/components/resources/MIGRATING-RESOURCES.md rename apps/sim/{app/workspace/[workspaceId]/files/components/file-viewer => components/resources/file-view/components/csv-table-preview}/csv-table-preview.tsx (65%) create mode 100644 apps/sim/components/resources/file-view/components/csv-table-preview/index.ts rename apps/sim/{app/workspace/[workspaceId]/files/components/file-viewer => components/resources/file-view/components/data-table}/data-table.tsx (99%) create mode 100644 apps/sim/components/resources/file-view/components/data-table/index.ts rename apps/sim/{app/workspace/[workspaceId]/files/components/file-viewer => components/resources/file-view/components}/document-table.css (100%) rename apps/sim/{app/workspace/[workspaceId]/files/components/file-viewer => components/resources/file-view/components}/document-table.test.ts (100%) rename apps/sim/{app/workspace/[workspaceId]/files/components/file-viewer => components/resources/file-view/components/docx-preview}/docx-preview.tsx (93%) create mode 100644 apps/sim/components/resources/file-view/components/docx-preview/index.ts create mode 100644 apps/sim/components/resources/file-view/components/editor-context-menu/editor-context-menu.tsx create mode 100644 apps/sim/components/resources/file-view/components/editor-context-menu/index.ts rename apps/sim/{app/workspace/[workspaceId]/files/components/file-viewer => components/resources/file-view/components/image-preview}/image-preview.test.tsx (68%) rename apps/sim/{app/workspace/[workspaceId]/files/components/file-viewer => components/resources/file-view/components/image-preview}/image-preview.tsx (54%) create mode 100644 apps/sim/components/resources/file-view/components/image-preview/index.ts create mode 100644 apps/sim/components/resources/file-view/components/mermaid-diagram/index.ts rename apps/sim/{app/workspace/[workspaceId]/files/components/file-viewer => components/resources/file-view/components/mermaid-diagram}/mermaid-diagram.test.ts (100%) rename apps/sim/{app/workspace/[workspaceId]/files/components/file-viewer => components/resources/file-view/components/mermaid-diagram}/mermaid-diagram.tsx (96%) create mode 100644 apps/sim/components/resources/file-view/components/pdf-viewer/index.ts rename apps/sim/{app/workspace/[workspaceId]/files/components/file-viewer => components/resources/file-view/components/pdf-viewer}/pdf-viewer.tsx (96%) create mode 100644 apps/sim/components/resources/file-view/components/pptx-preview/index.ts rename apps/sim/{app/workspace/[workspaceId]/files/components/file-viewer => components/resources/file-view/components/pptx-preview}/pptx-preview.tsx (74%) create mode 100644 apps/sim/components/resources/file-view/components/pptx-sandbox-host/index.ts rename apps/sim/{app/workspace/[workspaceId]/files/components/file-viewer => components/resources/file-view/components/pptx-sandbox-host}/pptx-sandbox-host.tsx (96%) create mode 100644 apps/sim/components/resources/file-view/components/preview-panel/index.ts rename apps/sim/{app/workspace/[workspaceId]/files/components/file-viewer => components/resources/file-view/components/preview-panel}/preview-panel.tsx (90%) create mode 100644 apps/sim/components/resources/file-view/components/preview-shared/index.ts rename apps/sim/{app/workspace/[workspaceId]/files/components/file-viewer => components/resources/file-view/components/preview-shared}/preview-shared.tsx (76%) create mode 100644 apps/sim/components/resources/file-view/components/preview-toolbar/index.ts rename apps/sim/{app/workspace/[workspaceId]/files/components/file-viewer => components/resources/file-view/components/preview-toolbar}/preview-toolbar.tsx (100%) rename apps/sim/{app/workspace/[workspaceId]/files/components/file-viewer => components/resources/file-view/components}/rich-markdown-editor/block-mover.ts (100%) rename apps/sim/{app/workspace/[workspaceId]/files/components/file-viewer => components/resources/file-view/components}/rich-markdown-editor/code-block-schema.ts (100%) rename apps/sim/{app/workspace/[workspaceId]/files/components/file-viewer => components/resources/file-view/components}/rich-markdown-editor/code-block.tsx (98%) rename apps/sim/{app/workspace/[workspaceId]/files/components/file-viewer => components/resources/file-view/components}/rich-markdown-editor/code-highlight.test.ts (100%) rename apps/sim/{app/workspace/[workspaceId]/files/components/file-viewer => components/resources/file-view/components}/rich-markdown-editor/code-highlight.ts (100%) rename apps/sim/{app/workspace/[workspaceId]/files/components/file-viewer => components/resources/file-view/components}/rich-markdown-editor/code-languages.test.ts (100%) rename apps/sim/{app/workspace/[workspaceId]/files/components/file-viewer => components/resources/file-view/components}/rich-markdown-editor/collaboration/agent-stream-leader.test.ts (100%) rename apps/sim/{app/workspace/[workspaceId]/files/components/file-viewer => components/resources/file-view/components}/rich-markdown-editor/collaboration/agent-stream-leader.ts (100%) rename apps/sim/{app/workspace/[workspaceId]/files/components/file-viewer => components/resources/file-view/components}/rich-markdown-editor/collaboration/apply-streamed-markdown.concurrent.test.ts (100%) rename apps/sim/{app/workspace/[workspaceId]/files/components/file-viewer => components/resources/file-view/components}/rich-markdown-editor/collaboration/apply-streamed-markdown.test.ts (100%) rename apps/sim/{app/workspace/[workspaceId]/files/components/file-viewer => components/resources/file-view/components}/rich-markdown-editor/collaboration/apply-streamed-markdown.ts (100%) rename apps/sim/{app/workspace/[workspaceId]/files/components/file-viewer => components/resources/file-view/components}/rich-markdown-editor/collaboration/caret-presence.test.ts (100%) rename apps/sim/{app/workspace/[workspaceId]/files/components/file-viewer => components/resources/file-view/components}/rich-markdown-editor/collaboration/caret-presence.ts (100%) rename apps/sim/{app/workspace/[workspaceId]/files/components/file-viewer => components/resources/file-view/components}/rich-markdown-editor/collaboration/collab-streaming-integration.test.ts (100%) rename apps/sim/{app/workspace/[workspaceId]/files/components/file-viewer => components/resources/file-view/components}/rich-markdown-editor/collaboration/file-doc-avatars.tsx (81%) rename apps/sim/{app/workspace/[workspaceId]/files/components/file-viewer => components/resources/file-view/components}/rich-markdown-editor/collaboration/file-doc-provider.test.ts (100%) rename apps/sim/{app/workspace/[workspaceId]/files/components/file-viewer => components/resources/file-view/components}/rich-markdown-editor/collaboration/file-doc-provider.ts (100%) rename apps/sim/{app/workspace/[workspaceId]/files/components/file-viewer => components/resources/file-view/components}/rich-markdown-editor/collaboration/file-doc-room-context.tsx (95%) rename apps/sim/{app/workspace/[workspaceId]/files/components/file-viewer => components/resources/file-view/components}/rich-markdown-editor/collaboration/readiness.test.ts (100%) rename apps/sim/{app/workspace/[workspaceId]/files/components/file-viewer => components/resources/file-view/components}/rich-markdown-editor/collaboration/readiness.ts (100%) rename apps/sim/{app/workspace/[workspaceId]/files/components/file-viewer => components/resources/file-view/components}/rich-markdown-editor/collaboration/use-file-doc-collaboration.ts (99%) rename apps/sim/{app/workspace/[workspaceId]/files/components/file-viewer => components/resources/file-view/components}/rich-markdown-editor/detect-language.test.ts (100%) rename apps/sim/{app/workspace/[workspaceId]/files/components/file-viewer => components/resources/file-view/components}/rich-markdown-editor/detect-language.ts (100%) rename apps/sim/{app/workspace/[workspaceId]/files/components/file-viewer => components/resources/file-view/components}/rich-markdown-editor/dirty-on-open.test.ts (100%) rename apps/sim/{app/workspace/[workspaceId]/files/components/file-viewer => components/resources/file-view/components}/rich-markdown-editor/dirty-signal.test.ts (100%) rename apps/sim/{app/workspace/[workspaceId]/files/components/file-viewer => components/resources/file-view/components}/rich-markdown-editor/editor-extensions.ts (91%) rename apps/sim/{app/workspace/[workspaceId]/files/components/file-viewer => components/resources/file-view/components}/rich-markdown-editor/embed/embed-dom.ts (100%) rename apps/sim/{app/workspace/[workspaceId]/files/components/file-viewer => components/resources/file-view/components}/rich-markdown-editor/embed/link-embed.test.ts (94%) rename apps/sim/{app/workspace/[workspaceId]/files/components/file-viewer => components/resources/file-view/components}/rich-markdown-editor/embed/link-embed.ts (100%) rename apps/sim/{app/workspace/[workspaceId]/files/components/file-viewer => components/resources/file-view/components}/rich-markdown-editor/extensions.ts (100%) rename apps/sim/{app/workspace/[workspaceId]/files/components/file-viewer => components/resources/file-view/components}/rich-markdown-editor/heading-anchors.test.ts (100%) rename apps/sim/{app/workspace/[workspaceId]/files/components/file-viewer => components/resources/file-view/components}/rich-markdown-editor/heading-anchors.ts (100%) rename apps/sim/{app/workspace/[workspaceId]/files/components/file-viewer => components/resources/file-view/components}/rich-markdown-editor/highlight.ts (100%) rename apps/sim/{app/workspace/[workspaceId]/files/components/file-viewer => components/resources/file-view/components}/rich-markdown-editor/image-paste.test.ts (95%) rename apps/sim/{app/workspace/[workspaceId]/files/components/file-viewer => components/resources/file-view/components}/rich-markdown-editor/image-paste.ts (99%) rename apps/sim/{app/workspace/[workspaceId]/files/components/file-viewer => components/resources/file-view/components}/rich-markdown-editor/image-schema.ts (100%) create mode 100644 apps/sim/components/resources/file-view/components/rich-markdown-editor/image.test.ts rename apps/sim/{app/workspace/[workspaceId]/files/components/file-viewer => components/resources/file-view/components}/rich-markdown-editor/image.tsx (89%) rename apps/sim/{app/workspace/[workspaceId]/files/components/file-viewer => components/resources/file-view/components}/rich-markdown-editor/keymap.test.ts (99%) rename apps/sim/{app/workspace/[workspaceId]/files/components/file-viewer => components/resources/file-view/components}/rich-markdown-editor/keymap.ts (99%) rename apps/sim/{app/workspace/[workspaceId]/files/components/file-viewer => components/resources/file-view/components}/rich-markdown-editor/link-input-rule.test.ts (100%) rename apps/sim/{app/workspace/[workspaceId]/files/components/file-viewer => components/resources/file-view/components}/rich-markdown-editor/link-input-rule.ts (100%) rename apps/sim/{app/workspace/[workspaceId]/files/components/file-viewer => components/resources/file-view/components}/rich-markdown-editor/link-mark-precedence.test.ts (100%) rename apps/sim/{app/workspace/[workspaceId]/files/components/file-viewer => components/resources/file-view/components}/rich-markdown-editor/markdown-fidelity.test.ts (100%) rename apps/sim/{app/workspace/[workspaceId]/files/components/file-viewer => components/resources/file-view/components}/rich-markdown-editor/markdown-fidelity.ts (100%) rename apps/sim/{app/workspace/[workspaceId]/files/components/file-viewer => components/resources/file-view/components}/rich-markdown-editor/markdown-parse.test.ts (100%) rename apps/sim/{app/workspace/[workspaceId]/files/components/file-viewer => components/resources/file-view/components}/rich-markdown-editor/markdown-parse.ts (100%) rename apps/sim/{app/workspace/[workspaceId]/files/components/file-viewer => components/resources/file-view/components}/rich-markdown-editor/markdown-paste.test.ts (100%) rename apps/sim/{app/workspace/[workspaceId]/files/components/file-viewer => components/resources/file-view/components}/rich-markdown-editor/markdown-paste.ts (100%) rename apps/sim/{app/workspace/[workspaceId]/files/components/file-viewer => components/resources/file-view/components}/rich-markdown-editor/mention/index.ts (100%) create mode 100644 apps/sim/components/resources/file-view/components/rich-markdown-editor/mention/mention-chip.test.tsx create mode 100644 apps/sim/components/resources/file-view/components/rich-markdown-editor/mention/mention-chip.tsx rename apps/sim/{app/workspace/[workspaceId]/files/components/file-viewer => components/resources/file-view/components}/rich-markdown-editor/mention/mention-icon.test.ts (100%) rename apps/sim/{app/workspace/[workspaceId]/files/components/file-viewer => components/resources/file-view/components}/rich-markdown-editor/mention/mention-icon.ts (100%) rename apps/sim/{app/workspace/[workspaceId]/files/components/file-viewer => components/resources/file-view/components}/rich-markdown-editor/mention/mention-list.test.tsx (97%) rename apps/sim/{app/workspace/[workspaceId]/files/components/file-viewer => components/resources/file-view/components}/rich-markdown-editor/mention/mention-list.tsx (94%) rename apps/sim/{app/workspace/[workspaceId]/files/components/file-viewer => components/resources/file-view/components}/rich-markdown-editor/mention/mention-node.test.ts (92%) rename apps/sim/{app/workspace/[workspaceId]/files/components/file-viewer => components/resources/file-view/components}/rich-markdown-editor/mention/mention-node.ts (100%) rename apps/sim/{app/workspace/[workspaceId]/files/components/file-viewer => components/resources/file-view/components}/rich-markdown-editor/mention/mention-store.ts (100%) rename apps/sim/{app/workspace/[workspaceId]/files/components/file-viewer => components/resources/file-view/components}/rich-markdown-editor/mention/mention.ts (96%) create mode 100644 apps/sim/components/resources/file-view/components/rich-markdown-editor/mention/sim-link.test.ts create mode 100644 apps/sim/components/resources/file-view/components/rich-markdown-editor/mention/sim-link.ts rename apps/sim/{app/workspace/[workspaceId]/files/components/file-viewer => components/resources/file-view/components}/rich-markdown-editor/mention/types.ts (100%) rename apps/sim/{app/workspace/[workspaceId]/files/components/file-viewer => components/resources/file-view/components}/rich-markdown-editor/mention/use-editor-mentions.ts (100%) rename apps/sim/{app/workspace/[workspaceId]/files/components/file-viewer => components/resources/file-view/components}/rich-markdown-editor/mention/use-markdown-mentions.ts (100%) rename apps/sim/{app/workspace/[workspaceId]/files/components/file-viewer => components/resources/file-view/components}/rich-markdown-editor/menus/bubble-menu.tsx (100%) rename apps/sim/{app/workspace/[workspaceId]/files/components/file-viewer => components/resources/file-view/components}/rich-markdown-editor/menus/link-editing.tsx (93%) rename apps/sim/{app/workspace/[workspaceId]/files/components/file-viewer => components/resources/file-view/components}/rich-markdown-editor/menus/link-hover-card.tsx (98%) rename apps/sim/{app/workspace/[workspaceId]/files/components/file-viewer => components/resources/file-view/components}/rich-markdown-editor/menus/suggestion-list.tsx (100%) rename apps/sim/{app/workspace/[workspaceId]/files/components/file-viewer => components/resources/file-view/components}/rich-markdown-editor/menus/suggestion-menu-chrome.ts (100%) rename apps/sim/{app/workspace/[workspaceId]/files/components/file-viewer => components/resources/file-view/components}/rich-markdown-editor/menus/suggestion-popup.ts (100%) rename apps/sim/{app/workspace/[workspaceId]/files/components/file-viewer => components/resources/file-view/components}/rich-markdown-editor/menus/table-menu.test.ts (97%) rename apps/sim/{app/workspace/[workspaceId]/files/components/file-viewer => components/resources/file-view/components}/rich-markdown-editor/menus/table-menu.tsx (100%) rename apps/sim/{app/workspace/[workspaceId]/files/components/file-viewer => components/resources/file-view/components}/rich-markdown-editor/menus/toolbar-button.tsx (100%) rename apps/sim/{app/workspace/[workspaceId]/files/components/file-viewer => components/resources/file-view/components}/rich-markdown-editor/menus/use-bubble-menu-floating.ts (100%) rename apps/sim/{app/workspace/[workspaceId]/files/components/file-viewer => components/resources/file-view/components}/rich-markdown-editor/menus/use-suggestion-keyboard.ts (100%) rename apps/sim/{app/workspace/[workspaceId]/files/components/file-viewer => components/resources/file-view/components}/rich-markdown-editor/normalize-content.ts (100%) rename apps/sim/{app/workspace/[workspaceId]/files/components/file-viewer => components/resources/file-view/components}/rich-markdown-editor/raw-markdown-snippet-schema.ts (100%) rename apps/sim/{app/workspace/[workspaceId]/files/components/file-viewer => components/resources/file-view/components}/rich-markdown-editor/raw-markdown-snippet-view.test.ts (100%) rename apps/sim/{app/workspace/[workspaceId]/files/components/file-viewer => components/resources/file-view/components}/rich-markdown-editor/raw-markdown-snippet.test.ts (100%) rename apps/sim/{app/workspace/[workspaceId]/files/components/file-viewer => components/resources/file-view/components}/rich-markdown-editor/raw-markdown-snippet.tsx (100%) rename apps/sim/{app/workspace/[workspaceId]/files/components/file-viewer => components/resources/file-view/components}/rich-markdown-editor/rich-markdown-editor.css (100%) rename apps/sim/{app/workspace/[workspaceId]/files/components/file-viewer => components/resources/file-view/components}/rich-markdown-editor/rich-markdown-editor.tsx (95%) rename apps/sim/{app/workspace/[workspaceId]/files/components/file-viewer => components/resources/file-view/components}/rich-markdown-editor/rich-markdown-field.tsx (97%) rename apps/sim/{app/workspace/[workspaceId]/files/components/file-viewer => components/resources/file-view/components}/rich-markdown-editor/round-trip-safety.test.ts (100%) rename apps/sim/{app/workspace/[workspaceId]/files/components/file-viewer => components/resources/file-view/components}/rich-markdown-editor/round-trip-safety.ts (100%) rename apps/sim/{app/workspace/[workspaceId]/files/components/file-viewer => components/resources/file-view/components}/rich-markdown-editor/round-trip.test.ts (100%) rename apps/sim/{app/workspace/[workspaceId]/files/components/file-viewer => components/resources/file-view/components}/rich-markdown-editor/slash-command/commands.test.ts (100%) rename apps/sim/{app/workspace/[workspaceId]/files/components/file-viewer => components/resources/file-view/components}/rich-markdown-editor/slash-command/commands.ts (100%) rename apps/sim/{app/workspace/[workspaceId]/files/components/file-viewer => components/resources/file-view/components}/rich-markdown-editor/slash-command/slash-command-list.tsx (91%) rename apps/sim/{app/workspace/[workspaceId]/files/components/file-viewer => components/resources/file-view/components}/rich-markdown-editor/slash-command/slash-command.ts (94%) rename apps/sim/{app/workspace/[workspaceId]/files/components/file-viewer => components/resources/file-view/components}/rich-markdown-editor/stream-settle-selection.test.ts (100%) rename apps/sim/{app/workspace/[workspaceId]/files/components/file-viewer => components/resources/file-view/components}/rich-markdown-editor/title-heading.test.ts (100%) rename apps/sim/{app/workspace/[workspaceId]/files/components/file-viewer => components/resources/file-view/components}/rich-markdown-editor/title-heading.ts (100%) rename apps/sim/{app/workspace/[workspaceId]/files/components/file-viewer => components/resources/file-view/components}/rich-markdown-editor/use-editor-editable.ts (100%) create mode 100644 apps/sim/components/resources/file-view/components/text-editor/index.ts rename apps/sim/{app/workspace/[workspaceId]/files/components/file-viewer => components/resources/file-view/components/text-editor}/text-editor.tsx (96%) rename apps/sim/{app/workspace/[workspaceId]/files/components/file-viewer => components/resources/file-view/components}/use-selection-copy-bridge.test.tsx (100%) rename apps/sim/{app/workspace/[workspaceId]/files/components/file-viewer => components/resources/file-view/components}/use-selection-copy-bridge.ts (100%) create mode 100644 apps/sim/components/resources/file-view/components/xlsx-preview/index.ts rename apps/sim/{app/workspace/[workspaceId]/files/components/file-viewer => components/resources/file-view/components/xlsx-preview}/xlsx-preview.tsx (87%) create mode 100644 apps/sim/components/resources/file-view/components/zoomable-preview/index.ts rename apps/sim/{app/workspace/[workspaceId]/files/components/file-viewer => components/resources/file-view/components/zoomable-preview}/zoomable-preview.tsx (97%) create mode 100644 apps/sim/components/resources/file-view/file-view.tsx rename apps/sim/{app/workspace/[workspaceId]/files/components/file-viewer => components/resources/file-view/hooks}/csv-import.ts (91%) rename apps/sim/{app/workspace/[workspaceId]/files/components/file-viewer => components/resources/file-view/hooks}/use-doc-preview-binary.test.ts (100%) rename apps/sim/{app/workspace/[workspaceId]/files/components/file-viewer => components/resources/file-view/hooks}/use-doc-preview-binary.ts (92%) rename apps/sim/{app/workspace/[workspaceId]/files/components/file-viewer => components/resources/file-view/hooks}/use-editable-file-content.test.tsx (91%) rename apps/sim/{app/workspace/[workspaceId]/files/components/file-viewer => components/resources/file-view/hooks}/use-editable-file-content.ts (95%) create mode 100644 apps/sim/components/resources/file-view/index.ts rename apps/sim/{app/workspace/[workspaceId]/files/components/file-viewer => components/resources/file-view/utils}/file-category.test.ts (100%) rename apps/sim/{app/workspace/[workspaceId]/files/components/file-viewer => components/resources/file-view/utils}/file-category.ts (100%) rename apps/sim/{app/workspace/[workspaceId]/files/components/file-viewer => components/resources/file-view/utils}/preview-wheel-zoom.ts (100%) rename apps/sim/{app/workspace/[workspaceId]/files/components/file-viewer => components/resources/file-view/utils}/text-editor-state.test.ts (100%) rename apps/sim/{app/workspace/[workspaceId]/files/components/file-viewer => components/resources/file-view/utils}/text-editor-state.ts (100%) rename apps/sim/{app/workspace/[workspaceId]/knowledge/[id] => components/resources/knowledge-view}/components/action-bar/action-bar.tsx (93%) rename apps/sim/{app/workspace/[workspaceId]/knowledge/[id] => components/resources/knowledge-view}/components/action-bar/index.ts (100%) rename apps/sim/{app/workspace/[workspaceId]/knowledge/[id] => components/resources/knowledge-view}/components/add-connector-modal/add-connector-modal.tsx (95%) rename apps/sim/{app/workspace/[workspaceId]/knowledge/[id] => components/resources/knowledge-view}/components/add-connector-modal/index.ts (100%) rename apps/sim/{app/workspace/[workspaceId]/knowledge/[id] => components/resources/knowledge-view}/components/add-documents-modal/add-documents-modal.tsx (94%) rename apps/sim/{app/workspace/[workspaceId]/knowledge/[id] => components/resources/knowledge-view}/components/add-documents-modal/index.ts (100%) rename apps/sim/{app/workspace/[workspaceId]/knowledge/[id] => components/resources/knowledge-view}/components/base-tags-modal/base-tags-modal.tsx (99%) rename apps/sim/{app/workspace/[workspaceId]/knowledge/[id] => components/resources/knowledge-view}/components/base-tags-modal/index.ts (100%) rename apps/sim/{app/workspace/[workspaceId]/knowledge/[id] => components/resources/knowledge-view}/components/connector-config-fields/connector-config-fields.tsx (96%) create mode 100644 apps/sim/components/resources/knowledge-view/components/connector-config-fields/index.ts rename apps/sim/{app/workspace/[workspaceId]/knowledge/[id] => components/resources/knowledge-view}/components/connector-entitlements.test.ts (94%) rename apps/sim/{app/workspace/[workspaceId]/knowledge/[id] => components/resources/knowledge-view}/components/connector-entitlements.ts (100%) rename apps/sim/{app/workspace/[workspaceId]/knowledge/[id] => components/resources/knowledge-view}/components/connector-selector-field/connector-selector-field.tsx (98%) create mode 100644 apps/sim/components/resources/knowledge-view/components/connector-selector-field/index.ts rename apps/sim/{app/workspace/[workspaceId]/knowledge/[id] => components/resources/knowledge-view}/components/connectors-section/connectors-section.tsx (99%) rename apps/sim/{app/workspace/[workspaceId]/knowledge/[id] => components/resources/knowledge-view}/components/connectors-section/index.ts (100%) rename apps/sim/{app/workspace/[workspaceId]/knowledge/[id] => components/resources/knowledge-view}/components/consts.ts (100%) create mode 100644 apps/sim/components/resources/knowledge-view/components/document-context-menu/document-context-menu.tsx rename apps/sim/{app/workspace/[workspaceId]/knowledge/[id] => components/resources/knowledge-view}/components/document-context-menu/index.ts (100%) create mode 100644 apps/sim/components/resources/knowledge-view/components/document-list/document-list.tsx create mode 100644 apps/sim/components/resources/knowledge-view/components/document-list/index.ts create mode 100644 apps/sim/components/resources/knowledge-view/components/document-tags-cell/document-tags-cell.tsx create mode 100644 apps/sim/components/resources/knowledge-view/components/document-tags-cell/index.ts rename apps/sim/{app/workspace/[workspaceId]/knowledge/[id]/[documentId] => components/resources/knowledge-view}/components/document-tags-modal/document-tags-modal.tsx (100%) rename apps/sim/{app/workspace/[workspaceId]/knowledge/[id]/[documentId] => components/resources/knowledge-view}/components/document-tags-modal/index.ts (100%) rename apps/sim/{app/workspace/[workspaceId]/knowledge/[id] => components/resources/knowledge-view}/components/edit-connector-modal/edit-connector-modal.tsx (95%) rename apps/sim/{app/workspace/[workspaceId]/knowledge/[id] => components/resources/knowledge-view}/components/edit-connector-modal/index.ts (100%) rename apps/sim/{app/workspace/[workspaceId]/knowledge/[id] => components/resources/knowledge-view}/components/index.ts (89%) rename apps/sim/{app/workspace/[workspaceId]/knowledge/[id] => components/resources/knowledge-view}/components/max-badge.tsx (100%) rename apps/sim/{app/workspace/[workspaceId]/knowledge/[id] => components/resources/knowledge-view}/components/rename-document-modal/index.ts (100%) rename apps/sim/{app/workspace/[workspaceId]/knowledge/[id] => components/resources/knowledge-view}/components/rename-document-modal/rename-document-modal.tsx (100%) rename apps/sim/{app/workspace/[workspaceId]/knowledge/[id] => components/resources/knowledge-view}/components/search-highlight/index.ts (100%) rename apps/sim/{app/workspace/[workspaceId]/knowledge/[id] => components/resources/knowledge-view}/components/search-highlight/search-highlight.tsx (100%) create mode 100644 apps/sim/components/resources/knowledge-view/components/tag-filter-panel/index.ts create mode 100644 apps/sim/components/resources/knowledge-view/components/tag-filter-panel/tag-filter-panel.tsx create mode 100644 apps/sim/components/resources/knowledge-view/index.ts create mode 100644 apps/sim/components/resources/knowledge-view/knowledge-view.tsx create mode 100644 apps/sim/components/resources/knowledge-view/utils/document-rows.tsx rename apps/sim/{app/workspace/[workspaceId]/logs/components/log-details => components/resources/log-view}/components/execution-snapshot/execution-snapshot.tsx (92%) rename apps/sim/{app/workspace/[workspaceId]/logs/components/log-details => components/resources/log-view}/components/execution-snapshot/index.ts (100%) rename apps/sim/{app/workspace/[workspaceId]/logs/components/log-details => components/resources/log-view}/components/file-download/file-download.tsx (87%) rename apps/sim/{app/workspace/[workspaceId]/logs/components/log-details => components/resources/log-view}/components/file-download/index.ts (100%) rename apps/sim/{app/workspace/[workspaceId]/logs/components/log-details => components/resources/log-view}/components/trace-view/index.ts (100%) rename apps/sim/{app/workspace/[workspaceId]/logs/components/log-details => components/resources/log-view}/components/trace-view/trace-view.tsx (99%) create mode 100644 apps/sim/components/resources/log-view/index.ts create mode 100644 apps/sim/components/resources/log-view/log-view.tsx create mode 100644 apps/sim/components/resources/log-view/utils/log-presentation.ts rename apps/sim/{app/workspace/[workspaceId]/logs/components/log-details/utils.ts => components/resources/log-view/utils/trace-utils.ts} (96%) create mode 100644 apps/sim/components/resources/resource-empty-state/index.ts create mode 100644 apps/sim/components/resources/resource-empty-state/resource-empty-state.tsx create mode 100644 apps/sim/components/resources/resource-provider/index.ts create mode 100644 apps/sim/components/resources/resource-provider/resource-provider.tsx create mode 100644 apps/sim/components/resources/table-view/components/cells/cell-content.tsx create mode 100644 apps/sim/components/resources/table-view/components/cells/cell-formatting.test.ts create mode 100644 apps/sim/components/resources/table-view/components/cells/cell-render.test.ts rename apps/sim/{app/workspace/[workspaceId]/tables/[tableId]/components/table-grid => components/resources/table-view/components}/cells/cell-render.tsx (97%) rename apps/sim/{app/workspace/[workspaceId]/tables/[tableId]/components/table-grid => components/resources/table-view/components}/cells/index.ts (53%) rename apps/sim/{app/workspace/[workspaceId]/tables/[tableId]/components/table-grid => components/resources/table-view/components}/cells/sim-resource-cell.tsx (94%) rename apps/sim/{app/workspace/[workspaceId]/tables/[tableId] => components/resources/table-view}/components/column-config-sidebar/column-config-sidebar.tsx (97%) rename apps/sim/{app/workspace/[workspaceId]/tables/[tableId] => components/resources/table-view}/components/column-config-sidebar/column-types.ts (100%) rename apps/sim/{app/workspace/[workspaceId]/tables/[tableId] => components/resources/table-view}/components/column-config-sidebar/index.ts (100%) rename apps/sim/{app/workspace/[workspaceId]/tables/[tableId] => components/resources/table-view}/components/columns-menu/columns-menu.tsx (100%) rename apps/sim/{app/workspace/[workspaceId]/tables/[tableId] => components/resources/table-view}/components/columns-menu/index.ts (100%) rename apps/sim/{app/workspace/[workspaceId]/tables/[tableId] => components/resources/table-view}/components/context-menu/context-menu.tsx (59%) rename apps/sim/{app/workspace/[workspaceId]/tables/[tableId] => components/resources/table-view}/components/context-menu/index.ts (100%) rename apps/sim/{app/workspace/[workspaceId]/tables/[tableId]/components/table-grid => components/resources/table-view/components/data-row}/data-row.tsx (90%) create mode 100644 apps/sim/components/resources/table-view/components/data-row/index.ts rename apps/sim/{app/workspace/[workspaceId]/tables/[tableId] => components/resources/table-view}/components/enrichment-details/enrichment-details.tsx (98%) rename apps/sim/{app/workspace/[workspaceId]/tables/[tableId] => components/resources/table-view}/components/enrichment-details/index.ts (100%) rename apps/sim/{app/workspace/[workspaceId]/tables/[tableId] => components/resources/table-view}/components/enrichments-sidebar/enrichment-config.tsx (98%) rename apps/sim/{app/workspace/[workspaceId]/tables/[tableId] => components/resources/table-view}/components/enrichments-sidebar/enrichments-sidebar.tsx (98%) rename apps/sim/{app/workspace/[workspaceId]/tables/[tableId] => components/resources/table-view}/components/enrichments-sidebar/index.ts (100%) create mode 100644 apps/sim/components/resources/table-view/components/execution-slideout/execution-slideout.tsx create mode 100644 apps/sim/components/resources/table-view/components/execution-slideout/index.ts rename apps/sim/{app/workspace/[workspaceId]/tables/[tableId]/components/table-grid => components/resources/table-view/components}/headers/column-header-menu.tsx (96%) rename apps/sim/{app/workspace/[workspaceId]/tables/[tableId]/components/table-grid => components/resources/table-view/components}/headers/column-type-icon.tsx (97%) rename apps/sim/{app/workspace/[workspaceId]/tables/[tableId]/components/table-grid => components/resources/table-view/components}/headers/header-label.tsx (100%) rename apps/sim/{app/workspace/[workspaceId]/tables/[tableId]/components/table-grid => components/resources/table-view/components}/headers/index.ts (100%) rename apps/sim/{app/workspace/[workspaceId]/tables/[tableId]/components/table-grid => components/resources/table-view/components}/headers/workflow-group-meta-cell.tsx (98%) rename apps/sim/{app/workspace/[workspaceId]/tables/[tableId] => components/resources/table-view}/components/index.ts (93%) rename apps/sim/{app/workspace/[workspaceId]/tables/[tableId] => components/resources/table-view}/components/lock-settings-modal/index.ts (100%) rename apps/sim/{app/workspace/[workspaceId]/tables/[tableId] => components/resources/table-view}/components/lock-settings-modal/lock-settings-modal.tsx (97%) rename apps/sim/{app/workspace/[workspaceId]/tables/[tableId] => components/resources/table-view}/components/new-column-dropdown/index.ts (100%) rename apps/sim/{app/workspace/[workspaceId]/tables/[tableId] => components/resources/table-view}/components/new-column-dropdown/new-column-dropdown.tsx (88%) create mode 100644 apps/sim/components/resources/table-view/components/remote-selection-overlay/index.ts rename apps/sim/{app/workspace/[workspaceId]/tables/[tableId]/components/table-grid => components/resources/table-view/components/remote-selection-overlay}/remote-selection-overlay.tsx (98%) rename apps/sim/{app/workspace/[workspaceId]/tables/[tableId] => components/resources/table-view}/components/row-modal/index.ts (100%) rename apps/sim/{app/workspace/[workspaceId]/tables/[tableId] => components/resources/table-view}/components/row-modal/row-modal.tsx (94%) rename apps/sim/{app/workspace/[workspaceId]/tables/[tableId] => components/resources/table-view}/components/run-status-control/index.ts (100%) rename apps/sim/{app/workspace/[workspaceId]/tables/[tableId] => components/resources/table-view}/components/run-status-control/run-status-control.tsx (100%) rename apps/sim/{app/workspace/[workspaceId]/tables/[tableId] => components/resources/table-view}/components/save-view-modal/index.ts (100%) rename apps/sim/{app/workspace/[workspaceId]/tables/[tableId] => components/resources/table-view}/components/save-view-modal/save-view-modal.tsx (100%) rename apps/sim/{app/workspace/[workspaceId]/tables/[tableId] => components/resources/table-view}/components/select-field/index.ts (54%) rename apps/sim/{app/workspace/[workspaceId]/tables/[tableId] => components/resources/table-view}/components/select-field/select-options-editor.tsx (100%) rename apps/sim/{app/workspace/[workspaceId]/tables/[tableId] => components/resources/table-view}/components/select-field/select-value-editor.tsx (96%) create mode 100644 apps/sim/components/resources/table-view/components/select-pill/index.ts rename apps/sim/{app/workspace/[workspaceId]/tables/[tableId]/components/select-field => components/resources/table-view/components/select-pill}/select-pill.tsx (100%) rename apps/sim/{app/workspace/[workspaceId]/tables/[tableId] => components/resources/table-view}/components/sidebar-fields/index.ts (100%) rename apps/sim/{app/workspace/[workspaceId]/tables/[tableId] => components/resources/table-view}/components/sidebar-fields/sidebar-fields.tsx (100%) rename apps/sim/{app/workspace/[workspaceId]/tables/[tableId] => components/resources/table-view}/components/table-action-bar/index.ts (100%) rename apps/sim/{app/workspace/[workspaceId]/tables/[tableId] => components/resources/table-view}/components/table-action-bar/table-action-bar.tsx (100%) rename apps/sim/{app/workspace/[workspaceId]/tables/[tableId] => components/resources/table-view}/components/table-filter/index.ts (100%) rename apps/sim/{app/workspace/[workspaceId]/tables/[tableId] => components/resources/table-view}/components/table-filter/table-filter.tsx (100%) create mode 100644 apps/sim/components/resources/table-view/components/table-find/index.ts rename apps/sim/{app/workspace/[workspaceId]/tables/[tableId]/components/table-grid => components/resources/table-view/components/table-find}/table-find.tsx (100%) rename apps/sim/{app/workspace/[workspaceId]/tables/[tableId] => components/resources/table-view}/components/table-grid/cells/expanded-cell-popover.tsx (98%) create mode 100644 apps/sim/components/resources/table-view/components/table-grid/cells/index.ts rename apps/sim/{app/workspace/[workspaceId]/tables/[tableId] => components/resources/table-view}/components/table-grid/cells/inline-editors.tsx (98%) rename apps/sim/{app/workspace/[workspaceId]/tables/[tableId] => components/resources/table-view}/components/table-grid/index.ts (100%) rename apps/sim/{app/workspace/[workspaceId]/tables/[tableId] => components/resources/table-view}/components/table-grid/table-grid.tsx (97%) create mode 100644 apps/sim/components/resources/table-view/components/table-primitives/index.ts rename apps/sim/{app/workspace/[workspaceId]/tables/[tableId]/components/table-grid => components/resources/table-view/components/table-primitives}/table-primitives.tsx (90%) rename apps/sim/{app/workspace/[workspaceId]/tables/[tableId] => components/resources/table-view}/components/views-menu/index.ts (100%) rename apps/sim/{app/workspace/[workspaceId]/tables/[tableId] => components/resources/table-view}/components/views-menu/views-menu.tsx (100%) rename apps/sim/{app/workspace/[workspaceId]/tables/[tableId] => components/resources/table-view}/components/workflow-sidebar/index.ts (100%) rename apps/sim/{app/workspace/[workspaceId]/tables/[tableId] => components/resources/table-view}/components/workflow-sidebar/input-mapping-section.tsx (100%) rename apps/sim/{app/workspace/[workspaceId]/tables/[tableId] => components/resources/table-view}/components/workflow-sidebar/run-settings-section.tsx (100%) rename apps/sim/{app/workspace/[workspaceId]/tables/[tableId] => components/resources/table-view}/components/workflow-sidebar/workflow-sidebar.tsx (97%) rename apps/sim/{app/workspace/[workspaceId]/tables/[tableId] => components/resources/table-view}/hooks/index.ts (100%) rename apps/sim/{app/workspace/[workspaceId]/tables/[tableId] => components/resources/table-view}/hooks/use-context-menu.ts (95%) rename apps/sim/{app/workspace/[workspaceId]/tables/[tableId] => components/resources/table-view}/hooks/use-table-event-stream.test.ts (98%) rename apps/sim/{app/workspace/[workspaceId]/tables/[tableId] => components/resources/table-view}/hooks/use-table-event-stream.ts (100%) rename apps/sim/{app/workspace/[workspaceId]/tables/[tableId] => components/resources/table-view}/hooks/use-table-room.ts (95%) rename apps/sim/{app/workspace/[workspaceId]/tables/[tableId] => components/resources/table-view}/hooks/use-table.test.ts (99%) rename apps/sim/{app/workspace/[workspaceId]/tables/[tableId] => components/resources/table-view}/hooks/use-table.ts (98%) create mode 100644 apps/sim/components/resources/table-view/index.ts rename apps/sim/{app/workspace/[workspaceId]/tables/[tableId]/table.tsx => components/resources/table-view/table-view.tsx} (90%) create mode 100644 apps/sim/components/resources/table-view/types.ts rename apps/sim/{app/workspace/[workspaceId]/tables/[tableId]/components/table-grid => components/resources/table-view/utils}/constants.ts (100%) rename apps/sim/{app/workspace/[workspaceId]/tables/[tableId] => components/resources/table-view/utils}/lock-copy.ts (100%) rename apps/sim/{app/workspace/[workspaceId]/tables/[tableId]/components/table-grid/utils.test.ts => components/resources/table-view/utils/selection.test.ts} (97%) rename apps/sim/{app/workspace/[workspaceId]/tables/[tableId]/components/table-grid/utils.ts => components/resources/table-view/utils/selection.ts} (99%) rename apps/sim/{app/workspace/[workspaceId]/tables/[tableId]/utils.test.ts => components/resources/table-view/utils/values.test.ts} (99%) rename apps/sim/{app/workspace/[workspaceId]/tables/[tableId]/utils.ts => components/resources/table-view/utils/values.ts} (100%) create mode 100644 apps/sim/components/socket-provider/index.ts rename apps/sim/{app/workspace/providers => components/socket-provider}/socket-join-controller.test.ts (99%) rename apps/sim/{app/workspace/providers => components/socket-provider}/socket-join-controller.ts (100%) rename apps/sim/{app/workspace/providers => components/socket-provider}/socket-join-target.test.ts (96%) rename apps/sim/{app/workspace/providers => components/socket-provider}/socket-join-target.ts (100%) rename apps/sim/{app/workspace/providers => components/socket-provider}/socket-provider.tsx (99%) rename apps/sim/{app/workspace/[workspaceId]/tables/components => components/table-import}/import-csv-dialog/import-csv-dialog.tsx (100%) rename apps/sim/{app/workspace/[workspaceId]/tables/components => components/table-import}/import-csv-dialog/index.ts (100%) rename apps/sim/{app/workspace/[workspaceId]/tables/components => components/table-import}/import-progress-menu/import-progress-menu.tsx (100%) rename apps/sim/{app/workspace/[workspaceId]/tables/components => components/table-import}/import-progress-menu/import-stage.ts (100%) rename apps/sim/{app/workspace/[workspaceId]/tables/components => components/table-import}/import-progress-menu/index.ts (100%) rename apps/sim/{app/workspace/[workspaceId]/tables/components => components/table-import}/import-progress-menu/use-workspace-imports.ts (100%) create mode 100644 apps/sim/components/table-import/index.ts rename apps/sim/components/ui/{generated-password-input.test.tsx => chip-password-input.test.tsx} (79%) delete mode 100644 apps/sim/components/ui/generated-password-input.tsx create mode 100644 apps/sim/components/workspace-host-provider/index.ts rename apps/sim/{app/workspace/[workspaceId]/components => components/workspace-host-provider}/workspace-access-denied.tsx (100%) rename apps/sim/{app/workspace/[workspaceId]/providers => components/workspace-host-provider}/workspace-host-provider.tsx (94%) rename apps/sim/{app/workspace/[workspaceId]/knowledge/[id]/hooks => hooks/kb}/use-connector-config-fields.ts (100%) create mode 100644 apps/sim/hooks/kb/use-knowledge-list-state.ts rename apps/sim/{app/workspace/[workspaceId]/knowledge/hooks => hooks/kb}/use-knowledge-upload.ts (100%) create mode 100644 apps/sim/hooks/queries/utils/mutation-error-toast.ts create mode 100644 apps/sim/hooks/use-drag-reorder.ts delete mode 100644 apps/sim/hooks/use-file-content-source.tsx rename apps/sim/{app/workspace/[workspaceId]/logs => }/hooks/use-log-details-resize.ts (100%) create mode 100644 apps/sim/hooks/use-share-modal-state.test.tsx create mode 100644 apps/sim/hooks/use-share-modal-state.ts create mode 100644 apps/sim/hooks/use-table-detail-state.test.tsx create mode 100644 apps/sim/hooks/use-table-detail-state.ts create mode 100644 apps/sim/lib/core/utils/unique-name.test.ts create mode 100644 apps/sim/lib/core/utils/unique-name.ts rename apps/sim/{app/workspace/[workspaceId]/knowledge/[id]/search-params.ts => lib/knowledge/detail-search-params.ts} (100%) create mode 100644 apps/sim/lib/public-shares/provenance.ts create mode 100644 apps/sim/lib/public-shares/share-gate.ts create mode 100644 apps/sim/lib/public-shares/urls.ts create mode 100644 apps/sim/lib/social-share.ts rename apps/sim/{app/workspace/[workspaceId]/tables/[tableId]/search-params.ts => lib/table/detail-search-params.ts} (84%) create mode 100644 apps/sim/lib/uploads/core/storage-service.local-atomicity.test.ts create mode 100644 apps/sim/lib/uploads/utils/byte-range.test.ts create mode 100644 apps/sim/lib/uploads/utils/byte-range.ts rename apps/sim/{app/workspace/[workspaceId]/files => lib/uploads/utils}/untitled-title.test.ts (100%) rename apps/sim/{app/workspace/[workspaceId]/files => lib/uploads/utils}/untitled-title.ts (100%) create mode 100644 apps/sim/lib/workflows/labels.ts create mode 100644 apps/sim/lib/workflows/streaming/logging-session-completion.ts create mode 100644 apps/sim/resources/file-source.ts create mode 100644 apps/sim/resources/grants.test.ts create mode 100644 apps/sim/resources/grants.ts create mode 100644 apps/sim/resources/host.ts create mode 100644 apps/sim/resources/index.ts create mode 100644 apps/sim/resources/kinds.ts create mode 100644 apps/sim/resources/knowledge-source.ts rename apps/sim/{app/workspace/[workspaceId]/logs/utils.test.ts => resources/log-source.test.ts} (68%) create mode 100644 apps/sim/resources/log-source.ts create mode 100644 apps/sim/resources/source.test.ts create mode 100644 apps/sim/resources/source.ts create mode 100644 apps/sim/resources/table-source.ts create mode 100644 packages/emcn/src/components/chip-password-input/chip-password-input.tsx create mode 100644 scripts/check-resource-views.ts diff --git a/.claude/rules/canon.md b/.claude/rules/canon.md new file mode 100644 index 00000000000..d7b9de3de64 --- /dev/null +++ b/.claude/rules/canon.md @@ -0,0 +1,50 @@ +# Canon — The 7 Canonical Concerns + +The non-negotiable conventions every change is measured against. This file is the index — the full rules live in the referenced files. When a canon rule and any other guidance conflict, canon wins. Known gaps are flagged so we close them deliberately instead of re-discovering them. + +## 1. Next.js best practices + +Server Components by default; `'use client'` only on the smallest leaf. `page.tsx` owns metadata. `next/image` with `priority` on the LCP element; `next/dynamic` for below-fold. Client refs are never called server-side (enforced by `scripts/check-client-boundary-imports.ts`). + +- Full rules: `apps/sim/app/(landing)/CLAUDE.md` (landing), `.claude/rules/sim-architecture.md` (server boundary) +- **Gap**: no general app-router conventions rule — when to add `error.tsx` / `loading.tsx` / `not-found.tsx`, `generateMetadata` vs static `metadata`, ISR/`revalidate`, Suspense/streaming. Landing doc covers landing only. + +## 2. SEO / GEO (landing only) + +One `

` (Hero), strict heading hierarchy, `
`, server-rendered navbar, JSON-LD, answer-first H2s, atomic extractable blocks, entity consistency ("Sim", never "the platform"), sr-only summaries, concrete numbers. Copy follows `.claude/rules/constitution.md`. + +- Full rules: `.claude/rules/landing-seo-geo.md`, `apps/sim/app/(landing)/CLAUDE.md` +- **Gap**: docs reference a single `structured-data.tsx` but code is split into `site-structured-data/`, `home-structured-data/`, `json-ld/`. `sitemap.ts` / `robots.ts` / `manifest.ts` conventions (app root) are undocumented. + +## 3. Feature file structure + +Every feature dir: `feature.tsx` + `page.tsx` (+ `error.tsx`, `loading.tsx`, `search-params.ts` where applicable) + `utils/` (only for 2+ consumers — single-consumer helpers stay in `feature.tsx`) + `hooks/` + `components/`. Every component lives in its own kebab-case folder holding `.tsx` + `index.ts` barrel; children nest under that folder's own `components/`, recursively. Never a bare `.tsx` flat inside a `components/` directory. Reference implementation: `apps/sim/app/workspace/[workspaceId]/scheduled-tasks/`. + +- Full rules: `apps/sim/app/(landing)/CLAUDE.md` "Structure", `.claude/rules/sim-architecture.md` +- **Gap**: the recursion + barrel rule is only fully written in the landing CLAUDE.md; `sim-architecture.md` shows a flatter sketch and omits `search-params.ts` / `error.tsx` / `loading.tsx` co-location. + +## 4. EMCN components only (platform) + +No custom buttons/inputs/menus — always the `@sim/emcn` chip-family equivalent. Components own their chrome; consumers pass props, never chrome via `className` (layout/sizing only). + +- Full rules: `.claude/rules/emcn-components.md` (authoring), `.claude/rules/sim-styling.md` (consumer) +- **Gap**: stale paths — EMCN moved to `packages/emcn/` but `emcn-components.md` frontmatter still scopes `apps/sim/components/emcn/**`, and the landing CLAUDE.md still says import from `@/components/emcn`. + +## 5. No ad-hoc animations or colors + +Colors come from tokens in `apps/sim/app/_styles/globals.css` / `tailwind.config.ts` — never raw hex in components. Animations: prefer CSS, respect `prefers-reduced-motion`, no new keyframes outside the Tailwind config / scoped `.module.css`. Never touch global styles. + +- Full rules: `.claude/rules/sim-styling.md` (tokens), `apps/sim/app/(landing)/CLAUDE.md` (motion) +- **Gap**: the positive rule ("declare custom keyframes/tokens HERE and nowhere else") is unwritten — only the prohibition exists. + +## 6. State placement (useState / Zustand / React Query / URL) + +One four-way decision: React Query = all server state · nuqs URL params = shareable view-state · Zustand = high-frequency, ephemeral, or socket-synced state · useState = purely local UI. Never `useState` + `fetch`; never store-synced-with-effects for view-state. + +- Full rules: `.claude/rules/sim-url-state.md` (the canonical 4-way table), `.claude/rules/sim-queries.md`, `.claude/rules/sim-stores.md` + +## 7. Meta — authoring skills, rules, and CLAUDE.md files + +How we write the docs themselves: CLAUDE.md stays a lean index; detailed conventions go in `.claude/rules/*.md` with `paths:` frontmatter globs so they load only when matching files are touched; repeatable multi-step procedures become skills (`.claude/skills/` or `.claude/commands/`); one-off preferences go in memory, not the repo. + +- **Gap**: no authoring guide exists — rule/skill conventions are learned by imitating existing files. Needs a short `.claude/rules/meta-authoring.md`. diff --git a/.claude/rules/sim-resource-views.md b/.claude/rules/sim-resource-views.md new file mode 100644 index 00000000000..5e0f44a6cbd --- /dev/null +++ b/.claude/rules/sim-resource-views.md @@ -0,0 +1,164 @@ +--- +paths: + - "apps/sim/resources/**/*.ts" + - "apps/sim/components/resources/**/*.ts" + - "apps/sim/components/resources/**/*.tsx" + - "apps/sim/app/workspace/[workspaceId]/**/*.tsx" + - "apps/sim/app/f/**/*.tsx" + - "apps/sim/app/i/**/*.tsx" + - "apps/sim/app/(interfaces)/**/*.tsx" + - "apps/sim/hooks/queries/workspace-files.ts" +--- + +# Resource Views + +A **resource** is a thing a workspace holds that can also be shared: a file, a table, an interface, a knowledge base, a log. A resource with a canonical view has **exactly one**, and every consumer mounts that one — the workspace route page, the mothership panel, an interface module, and the public share page. + +**One view per resource. Consumers construct the axes and mount it. They never wrap it.** + +Enforced by `bun run check:resources` (strict CI gate: `bun run check:resources:strict`), which is `scripts/check-resource-views.ts`. + +## The three axes + +`apps/sim/resources/**` is pure TypeScript — no React, no `'use client'` — because `app/i/[token]/page.tsx` builds a share source during SSR. + +| Axis | Type | Replaces | +| --- | --- | --- | +| `source` | `WorkspaceSource \| ShareSource`, discriminated on `via` | `workspaceId`, `token`, `contentSource`, `isPublic`, `isShared` | +| `grants` | `{ write; run; manage; settled }` | `canEdit`, `canRun`, `canAdmin`, `canDelete`, `disableEdit/Insert/Delete` | +| `host` | `'page' \| 'panel' \| 'public'` | `embedded`, `isEmbedded`, `compact`, `minimal` | + +There is no fourth axis. Agent streaming is **one optional prop on `FileView`** (`streaming?: FileViewStreaming`), because only files stream. + +`ShareSource` declares `workspaceId?: never` and `resourceId?: never`, and `WorkspaceSource` declares `token?: never` and `seed?: never`. A share source **cannot** carry a workspace id — that is a compile error, not a convention. A kind whose seed is typed `never` (`table`, `knowledge`, `log`) structurally cannot construct a share source at all: "no public surface" is a compile-time fact. + +``` +apps/sim/resources/ # kinds.ts · source.ts · grants.ts · host.ts — pure TS +apps/sim/components/resources// # 'use client' — THE view, one per resource +``` + +Every unit has the same layout, so moving between them costs nothing: + +``` +/ +├── .tsx # THE view — what consumers mount +├── index.ts # the barrel; the only entry point consumers use +├── components// # .tsx + index.ts, one folder per child +├── hooks/.ts # optional; tests colocated +├── utils/.ts # pure helpers; tests colocated +└── types.ts # optional; shared types the whole unit reads +``` + +A barrel may also export a **child** — but only one a surface outside the unit +genuinely renders against the same data, where forking it would be the drift the +unit exists to prevent (`knowledge-view` exports `ActionBar`, `BaseTagsModal` and +`DocumentTagsModal` for the knowledge list page and the document detail route). +Exporting a child to save an import hop is not that; the child stays private and +the consumer mounts the view. + +Imports **inside** a unit are absolute (`@/components/resources//...`) like +everywhere else in the app. The one exception is a folder's own `index.ts` +naming its siblings, which stays relative (`./`) — it is describing its +own directory, not reaching across the app. + +All four kinds have a canonical view: `FileView`, `TableView`, `LogView`, +`KnowledgeView`. A view reads **and** writes — `FileView` edits, `TableView` +edits — gated on `grants.write`. "The view is read-only and the shell writes" +was a staging point during the migration, never a rule. + +A kind with no canonical view would simply be **absent** from the view list in `CANONICAL_UNITS` — that is the correct state for an unmigrated kind, not a flag, a shim, or a placeholder entry. Every kind has one today, so the list is full. + +## Consume: construct the axes, then mount + +That is the whole job. Same component, same props; only the constructed values differ. + +```typescript +// app/f/[token]/public-file-view.tsx — anonymous share +const source = useMemo( + () => shareSource({ kind: 'file', token, grantId: token, seed: { name, type, size, version } }), + [token, name, type, size, version] +) +return +``` + +```typescript +// .../mothership-view/.../resource-content.tsx — panel, same view +const source = useMemo( + () => workspaceSource({ kind: 'file', workspaceId, resourceId: file.id }), + [workspaceId, file.id] +) +const grants = useMemo(() => grantsFromPermissions(permissions), [permissions]) +return +``` + +- Import from the **unit barrel** (`@/components/resources/file-view`), never a file inside it. +- Copy that differs between workspace and share belongs on the **source** (`source.unavailableCopy`), not in the view. A share must never say "workspace" — that is what stops the view becoming an existence oracle. +- Links belong on the source too (`source.hrefFor(link)`), which returns `null` in share scope so nobody hand-builds `/workspace/${token}/…`. Three destinations: `{ to: 'self' }`, `{ to: 'resource', kind, id }`, and `{ to: 'list' }` for the index route the kind lives under — a breadcrumb root, or where to go after the resource being shown is deleted. +- `grants.settled` says whether `write`/`run`/`manage` are final. A resolving membership and a denied one produce identical booleans, so a surface that renders an affordance disabled while permissions load — or fires a one-shot effect — must check it rather than reading `write === false` as a decision. +- `host` decides chrome and URL ownership. `hostOwnsUrl(host)` is the single place the "embedded views do not write nuqs keys" rule lives. + +## Never do this + +**Never wrap a view.** A component whose body is a canonical view with its own props forwarded in is a wrapper. `check:resources` fails on the first one (`wrapperMounts` is at `0`). + +```typescript +// ✗ Bad — adds a name, a file, and an import hop; adds no behavior. +export function EmbeddedFilePanel({ source, grants, host }: EmbeddedFilePanelProps) { + return +} + +// ✓ Good — the consumer constructs the axes and mounts the view itself. +const source = workspaceSource({ kind: 'file', workspaceId, resourceId }) +return +``` + +**Never add a fourth spelling.** If the view cannot express what you need, change `source` / `grants` / `host` — one place, every consumer — or collapse the need into an existing optional object (`streaming`, `editing`). Do not add a loose prop. + +```typescript +// ✗ Bad — three axes, spelled four wrong ways. + + +// ✓ Good + +``` + +**Never reimplement.** If a view has no seam for what you need, **add the seam**. A hand-rolled mini-table loses booleans, JSON, dates, links, resource chips, pinned columns and windowing — every one of which the real view already handles. + +**Never reach past the barrel.** + +```typescript +// ✗ Bad — binds you to the unit's private layout +import { resolveFileCategory } from '@/components/resources/file-view/file-category' + +// ✓ Good +import { resolveFileCategory } from '@/components/resources/file-view' +``` + +The one sanctioned exception is a `lazy()` code-split point, where routing through the barrel silently re-attaches the split chunk (`apps/sim` has no `sideEffects: false`). Those go in `INTERNAL_IMPORT_ALLOWLIST` in the check, keyed by importer **and** specifier. + +**Never import the workspace route tree from an anonymous surface.** `app/f/**`, `app/(interfaces)/**`, `app/(shared)/**` and public API routes may not import `@/app/workspace/[workspaceId]/**`. Shared units live in `apps/sim/components/resources/**`. Nesting under a `[workspaceId]` segment is exactly why `workspaceId: string` once read as natural on a component anonymous visitors mounted with a **share token**. + +**Never read route or permission context inside a unit.** No `useRouter`, `useParams`, `useSearchParams`, `usePathname`, `useQueryState(s)`, or `useUserPermissionsContext` under `apps/sim/components/resources/**`. Addressing is `source`, navigation targets are `source.hrefFor(link)`, capability is `grants`, URL ownership is `host`. A component that falls back to `useParams()` can only ever exist once per page. + +**Never put `'use client'` in `apps/sim/resources/**`.** Next rewrites every export of a `'use client'` module into a client reference in the server bundle, so the Server Component that builds a share source would throw at runtime. + +## Escape hatch + +Four annotations, reason mandatory, on the line directly above the offending mount / import / attribute (up to three preceding comment lines of extra context are tolerated): + +```typescript +// boundary-resource-wrapper: +// boundary-resource-internal: +// boundary-resource-tree: +// boundary-resource-prop: +``` + +An annotation with an empty reason is still a finding **and** trips `annotationsMissingReason`. Whole-file exceptions go through `INTERNAL_IMPORT_ALLOWLIST` / `CROSS_TREE_ALLOWLIST` in `scripts/check-resource-views.ts`, not per-line annotations. + +## Checklist before you add a component near a resource + +1. Does a canonical view already exist for this kind? Mount it. +2. Does it exist but lack a seam? Add the seam in the unit and thread it — do not fork the UI. +3. Is your new component only forwarding props into a view? Delete it; mount the view at the call site. +4. Are you about to write `embedded`, `canEdit`, `canRun`, `isPublic`, `token` or `workspaceId` on a view? Map it to `source` / `grants` / `host`. +5. Run `bun run check:resources`. The success metric is **consumers per view going up and component count going down**. diff --git a/.cursor/rules/sim-resource-views.mdc b/.cursor/rules/sim-resource-views.mdc new file mode 100644 index 00000000000..e27676d1394 --- /dev/null +++ b/.cursor/rules/sim-resource-views.mdc @@ -0,0 +1,99 @@ +--- +description: Resource views — one view per resource, many consumers, no wrappers +globs: ["apps/sim/resources/**/*.ts", "apps/sim/components/resources/**/*.ts", "apps/sim/components/resources/**/*.tsx", "apps/sim/app/workspace/[workspaceId]/**/*.tsx", "apps/sim/app/f/**/*.tsx", "apps/sim/app/(interfaces)/**/*.tsx"] +--- +# Resource Views + +A **resource** is a thing a workspace holds that can also be shared: a file, a table, an interface, a knowledge base, a log, a scheduled task. A resource with a canonical view has **exactly one**, and every consumer mounts that one — the workspace page, the mothership panel, an interface module, the public share page. + +**One view per resource. Consumers construct the axes and mount it. They never wrap it.** + +Enforced by `bun run check:resources`; strict gate `bun run check:resources:strict`. + +## Three axes, nothing else + +| Axis | Type | Replaces | +| --- | --- | --- | +| `source` | `WorkspaceSource \| ShareSource`, discriminated on `via` | `workspaceId`, `token`, `contentSource`, `isPublic` | +| `grants` | `{ write; run; manage; settled }` | `canEdit`, `canRun`, `canAdmin`, `disableEdit/Insert/Delete` | +| `host` | `'page' \| 'panel' \| 'public'` | `embedded`, `isEmbedded`, `compact`, `minimal` | + +There is no fourth axis. Agent streaming is one optional prop on `FileView` (`streaming?`), because only files stream. + +`ShareSource` declares `workspaceId?: never`; `WorkspaceSource` declares `token?: never`. A share source cannot carry a workspace id — compile error, not convention. + +``` +apps/sim/resources/ # kinds/source/grants/host — pure TS, NO 'use client' +apps/sim/components/resources// # 'use client' — THE view, one per resource +``` + +All four kinds have a canonical view. A kind without one would simply be absent from the view list in the check’s `CANONICAL_UNITS` — not a flag, shim, or placeholder. + +## Consume: construct, then mount + +```typescript +// Anonymous share +const source = shareSource({ kind: 'file', token, grantId: token, seed }) +return + +// Panel — same view, same props +const source = workspaceSource({ kind: 'file', workspaceId, resourceId: file.id }) +return +``` + +Import from the unit barrel (`@/components/resources/file-view`), never a file inside it. Scope-dependent copy lives on `source.unavailableCopy`; links on `source.hrefFor(link)` — `{ to: 'self' | 'resource' | 'list' }`, returning `null` in share scope. `hostOwnsUrl(host)` is the one place the "embedded views do not write nuqs keys" rule lives. + +## Never + +```typescript +// ✗ Wrapper — adds a name, a file, an import hop; adds no behavior. Fails check:resources. +export function EmbeddedFilePanel({ source, grants, host }: EmbeddedFilePanelProps) { + return +} + +// ✓ The consumer constructs the axes and mounts the view itself +const source = workspaceSource({ kind: 'file', workspaceId, resourceId }) +return +``` + +```typescript +// ✗ A fourth spelling for capability / chrome / address + + +// ✓ + +``` + +```typescript +// ✗ Reaching past the barrel +import { resolveFileCategory } from '@/components/resources/file-view/file-category' + +// ✓ +import { resolveFileCategory } from '@/components/resources/file-view' +``` + +- **Never reimplement** a resource's UI because the view has no seam — add the seam. A hand-rolled mini-table loses booleans, JSON, dates, links, chips, pinned columns and windowing. +- **Never import `@/app/workspace/[workspaceId]/**`** from `app/f/**`, `app/(interfaces)/**`, `app/(shared)/**`, or a public API route. Shared units live in `apps/sim/components/resources/**`. +- **Never** use `useRouter` / `useParams` / `useSearchParams` / `usePathname` / `useQueryState(s)` / `useUserPermissionsContext` inside `apps/sim/components/resources/**`. Addressing is `source`, navigation is `source.hrefFor`, capability is `grants`, URL ownership is `host`. +- **Never** put `'use client'` in `apps/sim/resources/**` — a Server Component builds a share source from it during SSR. + +## Escape hatch + +Reason mandatory, on the line directly above the offending mount / import / attribute: + +```typescript +// boundary-resource-wrapper: +// boundary-resource-internal: +// boundary-resource-tree: +// boundary-resource-prop: +``` + +An empty reason is still a finding. Whole-file exceptions go in `INTERNAL_IMPORT_ALLOWLIST` / `CROSS_TREE_ALLOWLIST` in `scripts/check-resource-views.ts`. The only sanctioned deep import is a `lazy()` split point, where the barrel would re-attach the split chunk. + +## Before adding a component near a resource + +1. Does a canonical view exist for this kind? Mount it. +2. Exists but lacks a seam? Add the seam in the unit — do not fork. +3. Only forwarding props into a view? Delete it; mount the view at the call site. +4. About to write `embedded` / `canEdit` / `canRun` / `isPublic` / `token` / `workspaceId` on a view? Map it to `source` / `grants` / `host`. +5. Run `bun run check:resources`. Success is consumers-per-view up, component count down. diff --git a/CLAUDE.md b/CLAUDE.md index 1a1e4671737..c60f9f7c283 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -4,7 +4,7 @@ You are a professional software engineer. All code must follow best practices: a ## Global Standards -- **Linting / Audit**: `bun run check:api-validation` must pass on PRs. Do not introduce route-local boundary Zod schemas, direct route Zod imports, or ad-hoc client wire types — see "API Contracts" and "API Route Pattern" below +- **Linting / Audit**: `bun run check:api-validation` and `bun run check:resources` must pass on PRs. Do not introduce route-local boundary Zod schemas, direct route Zod imports, ad-hoc client wire types, or wrappers over a canonical resource view — see "API Contracts", "API Route Pattern", and "Resource Views" below - **Logging**: Import `createLogger` from `@sim/logger`. Use `logger.info`, `logger.warn`, `logger.error` instead of `console.log`. Inside API routes wrapped with `withRouteHandler`, loggers automatically include the request ID — no manual `withMetadata({ requestId })` needed - **API Route Handlers**: All API route handlers (`GET`, `POST`, `PUT`, `DELETE`, `PATCH`) must be wrapped with `withRouteHandler` from `@/lib/core/utils/with-route-handler`. This provides request ID tracking, automatic error logging for 4xx/5xx responses, and unhandled error catching. See "API Route Pattern" section below - **Comments**: Use TSDoc for documentation. No `====` separators. No non-TSDoc comments @@ -42,6 +42,7 @@ apps/ │ ├── hooks/ # Shared hooks (queries/, selectors/) │ ├── lib/ # App-wide utilities │ ├── providers/ # LLM provider integrations +│ ├── resources/ # Resource axes (source/grants/host) — pure TS, server-importable │ ├── stores/ # Zustand stores │ ├── tools/ # Tool definitions │ └── triggers/ # Trigger definitions @@ -414,6 +415,20 @@ Principles when building or migrating shared UI: - Align consumers to the canonical defaults — normal weight, `--text-body` text, `--text-icon` icons. - Verify referenced CSS vars exist — an undefined var silently falls back to `currentColor` (black-bug). +## Resource Views + +A **resource** is a thing a workspace holds that can also be shared — a file, a table, a knowledge base, a log. A resource with a canonical view has exactly ONE, in `apps/sim/components/resources//`, mounted by every consumer: the workspace route page, the mothership panel, the public share page. + +Views are mounted against exactly **three axes**, defined in `apps/sim/resources/**` (pure TypeScript — no React, no `'use client'`, because a Server Component builds a share source during SSR): + +- `source` — where the data comes from and by what address: `WorkspaceSource | ShareSource`, discriminated on `via`. Replaces `workspaceId`, `token`, `contentSource`, `isPublic`. `ShareSource` declares `workspaceId?: never`, so a share token can no longer be laundered through a workspace-shaped slot. +- `grants` — what this viewer may do: `{ write, run, manage }`, plus `settled` (whether those three are final, or still resolving — a denied member and a loading one are otherwise indistinguishable). Replaces `canEdit`, `canRun`, `canAdmin`, `disableEdit/Insert/Delete`. +- `host` — who owns the URL, the router, the document frame: `'page' | 'panel' | 'public'`. Replaces `embedded`. `hostOwnsUrl(host)` is the one place the "embedded views do not write nuqs keys" rule lives. + +There is no fourth axis; agent streaming is one optional prop on `FileView`. Consumers CONSTRUCT the axes and MOUNT the view — never wrap it in a passthrough, never reach past its barrel, never reimplement its UI because it lacks a seam (add the seam), never import `@/app/workspace/[workspaceId]/**` from an anonymous surface (`app/f/**`, `app/(interfaces)/**`), and never read `useRouter`/`useParams`/`useQueryState`/`useUserPermissionsContext` inside a unit. All four kinds have a canonical view, and a view reads and writes (gated on `grants.write`) rather than deferring mutations to a shell. A kind without one would simply be absent from the view list in the check's `CANONICAL_UNITS` — no flag, shim, or placeholder. Every unit has the same layout (`.tsx` · `index.ts` · `components//` · `hooks/` · `utils/` · `types.ts`), so moving between them costs nothing. + +Enforced by `bun run check:resources` (strict: `check:resources:strict`), which ratchets counters for wrappers, imports past a barrel, cross-tree imports, unsanctioned props, token-as-`workspaceId`, and context leaks. Escape hatches — reason mandatory, on the line directly above: `// boundary-resource-wrapper:`, `// boundary-resource-internal:`, `// boundary-resource-tree:`, `// boundary-resource-prop:`. Full rules in `.claude/rules/sim-resource-views.md`. + ## Testing Use Vitest. Test files: `feature.ts` → `feature.test.ts`. See `.cursor/rules/sim-testing.mdc` for full details. diff --git a/apps/sim/AGENTS.md b/apps/sim/AGENTS.md index 6c52c2df02d..10227490ebd 100644 --- a/apps/sim/AGENTS.md +++ b/apps/sim/AGENTS.md @@ -229,3 +229,11 @@ export function useEntityList(workspaceId?: string) { - **Check existing sources** before duplicating (`lib/` has many utilities) - **Location**: `lib/` (app-wide) → `feature/utils/` (feature-scoped) → inline (single-use) + + +# This is NOT the Next.js you know + +This version has breaking changes — APIs, conventions, and file structure may all differ from your training data. Read the relevant guide in `node_modules/next/dist/docs/` (resolved from this file's directory; in monorepos the `next` package may not be visible from the repo root) before writing any code. Heed deprecation notices. + +This block is written and re-added by `next dev` — verify at `node_modules/next/dist/server/lib/generate-agent-files.js`. Removing it from a diff only re-creates the uncommitted change; committing it with your work keeps the tree clean. + diff --git a/apps/sim/app/(auth)/components/auth-shell.tsx b/apps/sim/app/(auth)/components/auth-shell.tsx index 36085dc52ad..40dc82ad5e4 100644 --- a/apps/sim/app/(auth)/components/auth-shell.tsx +++ b/apps/sim/app/(auth)/components/auth-shell.tsx @@ -1,7 +1,6 @@ import type { ReactNode } from 'react' -import Link from 'next/link' import { DesktopTitleBarLane } from '@/app/_shell/desktop-title-bar' -import { LogoMark, SimWordmark } from '@/app/(landing)/components/navbar/components' +import { Navbar } from '@/app/(landing)/components/navbar' interface AuthShellProps { /** Centered content column (the form, status copy, etc.). */ @@ -16,9 +15,9 @@ interface AuthShellProps { * * Mirrors the landing chrome: it pins the `light` token layer (so the platform's * light-mode `var(--*)` tokens resolve regardless of the visitor's theme), uses - * the canvas/`--text-primary` surface, and renders a logo-only header that reuses - * the landing {@link LogoMark} + {@link SimWordmark} at the same nav gutters. The - * single content column is centered and capped for a calm single-form layout. + * the canvas/`--text-primary` surface, and renders the shared {@link Navbar} in + * `logoOnly` mode — the same wordmark, geometry, and hover as the landing bar. + * The single content column is centered and capped for a calm single-form layout. * * The shell also owns the macOS traffic-light lane, unconditionally — every surface that * wears it (the `(auth)` routes, the CLI auth handoff, the invite pages) sits outside @@ -32,15 +31,7 @@ export function AuthShell({ children, footer }: AuthShellProps) { return (
-
- -
+
{children}
diff --git a/apps/sim/app/(interfaces)/chat/[identifier]/chat.tsx b/apps/sim/app/(interfaces)/chat/[identifier]/chat.tsx index f066279140d..dd0b9847eda 100644 --- a/apps/sim/app/(interfaces)/chat/[identifier]/chat.tsx +++ b/apps/sim/app/(interfaces)/chat/[identifier]/chat.tsx @@ -22,7 +22,6 @@ import { CHAT_ERROR_MESSAGES, CHAT_REQUEST_TIMEOUT_MS } from '@/app/(interfaces) import { useChatStreaming } from '@/app/(interfaces)/chat/hooks' import SSOAuth from '@/ee/sso/components/sso-auth' import { useDeployedChatConfig } from '@/hooks/queries/chats' -import { useGitHubStars } from '@/hooks/queries/github-stars' const logger = createLogger('ChatClient') @@ -63,7 +62,6 @@ export default function ChatClient({ identifier }: { identifier: string }) { const ignoreScrollRef = useRef(false) const { data: chatConfigResult, error: chatConfigError } = useDeployedChatConfig(identifier) - const { data: starCount } = useGitHubStars() const authRequired = chatConfigResult?.kind === 'auth' ? chatConfigResult.authType : null const chatConfig = chatConfigResult?.kind === 'config' ? chatConfigResult.config : null @@ -310,7 +308,7 @@ export default function ChatClient({ identifier }: { identifier: string }) { return (
- + -
-
- {customImage && ( - {`${chatConfig?.title - )} -

- {chatConfig?.customizations?.headerText || chatConfig?.title || 'Chat'} -

-
-
- - {!brand.logoUrl && ( -
- - - {/* Only show Sim logo if no custom branding is set */} - - - - -
- )} - + } + nameIcon={ + customImage ? ( + {`${chatConfig?.title + ) : undefined + } + /> ) } diff --git a/apps/sim/app/(interfaces)/chat/components/input/input.tsx b/apps/sim/app/(interfaces)/chat/components/input/input.tsx index abb1460c955..ee8bed551b3 100644 --- a/apps/sim/app/(interfaces)/chat/components/input/input.tsx +++ b/apps/sim/app/(interfaces)/chat/components/input/input.tsx @@ -142,7 +142,7 @@ export const ChatInput: React.FC<{ onClick={handleContainerClick} className={cn( 'relative z-10 cursor-text rounded-2xl border border-[var(--border-1)] bg-[var(--surface-2)] px-2.5 py-2', - isDragOver && 'border-purple-500' + isDragOver && 'border-[var(--text-muted)]' )} onDragEnter={(e) => { e.preventDefault() diff --git a/apps/sim/app/(landing)/components/index.ts b/apps/sim/app/(landing)/components/index.ts index 4181286a3a5..8e15831460a 100644 --- a/apps/sim/app/(landing)/components/index.ts +++ b/apps/sim/app/(landing)/components/index.ts @@ -21,6 +21,7 @@ export { Navbar } from './navbar' export { PlatformHeroVisual } from './platform-hero-visual' export { ProductDemo } from './product-demo' export { ShareButton } from './share-button' +export { ShareLinkButton } from './share-link-button' export { SiteStructuredData } from './site-structured-data' export type { SolutionsPageConfig } from './solutions-page' export { SolutionsPage } from './solutions-page' diff --git a/apps/sim/app/(landing)/components/landing-preview/components/landing-preview-home/landing-preview-home.tsx b/apps/sim/app/(landing)/components/landing-preview/components/landing-preview-home/landing-preview-home.tsx index 973c0bc26b4..8388b6f9300 100644 --- a/apps/sim/app/(landing)/components/landing-preview/components/landing-preview-home/landing-preview-home.tsx +++ b/apps/sim/app/(landing)/components/landing-preview/components/landing-preview-home/landing-preview-home.tsx @@ -253,7 +253,7 @@ export const LandingPreviewHome = memo(function LandingPreviewHome({ animate={{ width: '55%', opacity: 1 }} transition={{ duration: 0.35, ease: EASE_OUT }} > - + )} @@ -381,9 +381,14 @@ function ChatMarkdown({ } /** - * Mini Customer Leads table panel matching the resource panel pattern. + * The "Customer Leads" panel in the landing hero's static product mock. + * + * Named for what it is rather than `MiniTablePanel`: it is hardcoded marketing + * markup with no queries and no relationship to the table resource, and a + * `Mini` + resource-noun name reads to both a reader and the resource-view + * audit as a per-consumer fork of the real table view. */ -function MiniTablePanel() { +function LandingLeadsPanel() { return (
diff --git a/apps/sim/app/(landing)/components/logo-shell/logo-shell.tsx b/apps/sim/app/(landing)/components/logo-shell/logo-shell.tsx index 64c25cbc09d..da5ebfd47f7 100644 --- a/apps/sim/app/(landing)/components/logo-shell/logo-shell.tsx +++ b/apps/sim/app/(landing)/components/logo-shell/logo-shell.tsx @@ -1,16 +1,15 @@ import type { ReactNode } from 'react' import { cn } from '@sim/emcn' -import Link from 'next/link' import { DesktopTitleBarLane } from '@/app/_shell/desktop-title-bar' -import { LogoMark, SimWordmark } from '@/app/(landing)/components/navbar/components' +import { Navbar } from '@/app/(landing)/components/navbar' /** - * The canonical light, logo-only page frame - a Sim wordmark linking home, no - * marketing menus, on the platform's light tokens (the `light` class pins - * light mode regardless of visitor theme). It is the shared base for every - * surface that wants minimal chrome: the global 404, and the `(interfaces)` - * group (which adds a support footer). The `(auth)` group uses its own - * `AuthShell` with the same look. + * The canonical light, logo-only page frame - the shared {@link Navbar} in + * `logoOnly` mode (Sim wordmark linking home, no marketing menus) on the + * platform's light tokens (the `light` class pins light mode regardless of + * visitor theme). It is the shared base for every surface that wants minimal + * chrome: the global 404, and the `(interfaces)` group (which adds a support + * footer). The `(auth)` group uses its own `AuthShell` with the same navbar. * * Children decide their own layout: pass `center` for a single centered column * (404 message, simple gates); omit it for full-width content (the live chat @@ -29,15 +28,7 @@ export function LogoShell({ children, center = false, footer }: LogoShellProps) return (
-
- -
+
diff --git a/apps/sim/app/(landing)/components/navbar/components/navbar-shell/navbar-shell.tsx b/apps/sim/app/(landing)/components/navbar/components/navbar-shell/navbar-shell.tsx index 27ace3935de..be37dc1c569 100644 --- a/apps/sim/app/(landing)/components/navbar/components/navbar-shell/navbar-shell.tsx +++ b/apps/sim/app/(landing)/components/navbar/components/navbar-shell/navbar-shell.tsx @@ -94,7 +94,15 @@ export function NavbarShell({ children }: NavbarShellProps) { return (