Commit c9118e7
feat(files): folders, multiselect, vfs update (#4572)
* v0.6.29: login improvements, posthog telemetry (#4026)
* feat(posthog): Add tracking on mothership abort (#4023)
Co-authored-by: Theodore Li <theo@sim.ai>
* fix(login): fix captcha headers for manual login (#4025)
* fix(signup): fix turnstile key loading
* fix(login): fix captcha header passing
* Catch user already exists, remove login form captcha
* feat(files): folders + vfs update
* address comments
* address comments
* cleanup unnused code
* address comments
* perf improvements
* address next set
* cycle detect
* error handling
* path improvements
* cleanup, best practices
* react query best practices: targeted invalidation, optimistic updates, key factory hierarchy
- Add workspaceLists(workspaceId) intermediate key level to both workspaceFilesKeys
and workspaceFileFolderKeys so invalidation targets only the affected workspace
instead of all workspaces
- Replace all lists() invalidation calls with workspaceLists(workspaceId) across
every mutation (upload, rename, delete, restore, update content, folder mutations)
- Add optimistic updates to useRenameWorkspaceFile and useUpdateWorkspaceFileFolder
with onMutate snapshot, onError rollback, onSettled reconciliation
- Move storage key into the content() factory as optional param so query keys are
always built through the factory (useWorkspaceFileContent, useWorkspaceFileBinary)
- Fix AnimatePresence wrapping in FilesActionBar so exit animation fires on deselect
- Fix ResourceColGroup to use percentage weights instead of pixel widths to prevent
horizontal scroll on narrow viewports
* add shift-click range selection and selection-aware context menu for files
- Extend SelectableConfig.onSelectRow with optional shiftKey param; DataRow captures shiftKey before onCheckedChange fires via a ref so the Radix Checkbox interaction chain stays intact
- Implement shift-click range selection in files.tsx using lastSelectedIndexRef; tracks last-selected index in visibleRowIds to compute the range
- Reset lastSelectedIndexRef on deselect and select-all
- Add selectedCount prop to FileRowContextMenu; hide Open and Rename when multiple items are selected, show "Delete N items" / "Download N items" labels in multi-select mode
* add Move submenu to file context menu and fix shift-click anchor update
- Add nested Move submenu to FileRowContextMenu using DropdownMenuSub/SubTrigger/SubContent; shows available folders filtered by selection, converts '__root__' -> null for moving to the root level
- Add handleContextMenuMove in files.tsx that calls moveItems.mutateAsync directly (no modal) and clears selection on success
- Fix shift-click range selection: update lastSelectedIndexRef after range select so chained shift-clicks extend from the new anchor point correctly
* fix move submenu: use folder names with tree-ordered indentation instead of stale paths
- Compute folder depth from parentId chain client-side (avoids stale server-computed path field)
- Tree-order folders so parents appear before their children, sorted by sortOrder then name
- Show folder.name instead of folder.path so optimistic renames are reflected immediately
- Indent each folder by depth * 12px in the submenu so po/shit renders as 'shit' indented under 'po'
- MoveOption gains optional depth field; contextMenuMoveOptions is a separate memo from moveFolderOptions (modal keeps its existing path-label behavior)
* fix shift-click anchor drift and remove dead stopPropagation constant
- Remove dead stopPropagation const in resource.tsx (replaced by handleSelectRowClick)
- Reset lastSelectedIndexRef when visibleRowIds changes so search/filter/folder navigation doesn't leave a stale anchor that produces wrong ranges on the next shift-click
- Update lastSelectedIndexRef in handleRowContextMenu when right-clicking resets selection to a single item, so the anchor matches the newly-selected row
- Add visibleRowIds to handleRowContextMenu deps (now reads it to compute anchor index)
- Remove moveItems.mutateAsync from handleContextMenuMove deps per project convention (.mutateAsync is stable in TanStack v5)
* complete workspace files feature: audit logs, posthog events, folder restore, empty state, keyboard shortcuts, storage indicator, breadcrumb rename
- Audit + PostHog: wire file_renamed, file_deleted, file_moved, file_bulk_deleted, folder_created, folder_renamed, folder_deleted, folder_moved events to all file/folder API routes
- Add AuditAction.FOLDER_UPDATED, FILE_MOVED, FOLDER_MOVED to audit types
- Folder restore: server function, contract, API route (POST /files/folders/[folderId]/restore), hook (useRestoreWorkspaceFileFolder), Recently Deleted integration with new File Folders tab
- Empty state: contextual emptyMessage passed to <Resource> based on search/filters/folder context
- Keyboard shortcuts: Delete/Backspace deletes selection, Escape deselects, Cmd+A selects all (list view only, input-aware guard)
- Storage indicator: useStorageInfo drives compact "used / limit" display in file list header via leadingActions
- Breadcrumb rename: current folder breadcrumb gains Rename dropdown + inline editing via breadcrumbRename (useInlineRename)
- Resource: thread leadingActions prop from ResourceProps to ResourceHeader
* cleanup: accessibility, emcn design tokens, react best practices across workspace UI
- Add sr-only ModalDescription to dialogs/modals for accessibility
- Replace hardcoded colors and z-indices with design token CSS variables
- Apply emcn design review fixes across tables, knowledge, logs, settings, workflows
* fix audit and posthog: FOLDER_RESTORED action on restore, fire folder_moved event separately from file_moved
* sidebar: add Files section with nested folder tree; polish move UX and cleanup
- Files section in sidebar shows folder/file tree with expand/collapse,
matching Workflows section structure; collapsed sidebar shows flyout menu
- Move action bar now uses nested DropdownMenuSub tree instead of flat modal
- Context menu and action bar share renderMoveOption from move-options.tsx
- FolderInput added to emcn icons barrel; all FolderInput imports migrated
- Drag ghost uses CSS vars (--border, --shadow-medium, --z-toast)
- Selection pruning converted from useEffect to render-time comparison
- Keyboard listener stabilized with handleBulkDeleteRef pattern
- toError() used consistently in restore and move route handlers
* remove Files section from sidebar
* restore Files nav item in sidebar workspace section
* fix infinite re-render on files page - revert selection pruning to useEffect
* add filefolder resource type for ingesting workspace file folders
* export filefolder tree types; add toast feedback for file/folder mutations
* regenerate migration as 0208 after rebase onto staging
* add workspaceFileFolder to schema mock
* add FILE_MOVED, FOLDER_MOVED, FOLDER_UPDATED to audit mock
* add filefolder ChatContext kind and wire through schema and resolver
* add filefolder to AgentContextType
* add filefolder to chat context kind registry; fix resolver to use workspaceFiles table
* add .deepsec to gitignore
* cleanup: effect, emcn tokens, mutation error handling
- Replace selection-pruning useEffect with inline state adjustment during render
- Fix drag overlay using invalid --accent HSL token → --brand-secondary; z-50 → z-[var(--z-dropdown)]
- Move static inline styles on context menu trigger div to className
- Add missing onError toast to useUpdateWorkspaceFileFolder, useRestoreWorkspaceFileFolder, useRestoreWorkspaceFile
* lint
* fix: remove duplicate handleCopilotStopGeneration from rebase
* feat(copilot): folder-aware file context in WORKSPACE.md
* feat(copilot): add move operation to file manage API
* fix(files): make targetFolder optional in move file contract
* perf(files): parallelize buffer fetches, fix N+1 folder queries, stabilize drag useMemo
- download route: fan out all fetchWorkspaceFileBuffer calls with Promise.all
before zip assembly so 100 files resolve in one round-trip instead of sequentially
- getWorkspaceFileFolder: replace per-ancestor SELECTs with a single workspace-wide
folder load + buildWorkspaceFileFolderPathMap, making depth irrelevant to query count
- ensureWorkspaceFileFolderPath: pre-load all workspace folders in one SELECT before
the segment loop; resolve existing segments from an in-memory map; only hit the DB
to CREATE missing segments; conflict retry path preserved and also updates the map
- files.tsx rowDragDropConfig: move activeDropTargetId into a ref so the useMemo
does not recompute on every drag-over event
* fix(files): remove files/ path stripping, fix stale path in optimistic update
- splitWorkspaceFilePath: remove the unconditional .replace(/^files\//, '')
that clobbered paths for files inside a folder literally named "files"
- useUpdateWorkspaceFileFolder: when a name update is in flight, recompute
the path field for the renamed folder (replace last segment) and propagate
the new prefix to all descendant folders so breadcrumbs stay correct
during the optimistic window
* fix(files): revert broken ref opt, clean 409 on restore, null parentId on orphaned restore
- files.tsx: revert the activeDropTargetId ref optimization — the ref doesn't
trigger re-renders so the drop-target highlight never updated during drag;
activeDropTargetId is back in state and in the rowDragDropConfig deps
- restore/route.ts: catch Postgres 23505 unique-constraint violation and
return a clean 409 instead of leaking the raw error as 400
- restoreWorkspaceFileFolder: check if the parent folder is still archived
before restoring; if it is, restore to root (parentId: null) so the folder
is never orphaned under an archived parent
* feat(search): show folder path for files in cmd-k modal, strip extraneous comments
- FileItem interface with folderPath?: string[] added to search modal utils
- MemoizedFileItem component renders folder breadcrumb identically to
MemoizedWorkflowItem — truncated path segments on the right with / separators
- FilesGroup rewritten as a dedicated memo component (was createIconGroup factory)
so it accepts FileItem[] and includes folderPath segments in the search value
- searchModalFiles in sidebar splits f.folderPath string into string[] segments
- search-modal.tsx typed to FileItem and includes folderPath in filterAndSort
- Remove self-explanatory "Phase 1" section label from download route
- Remove redundant TSDoc on the unique index in db schema
* fix(workspace-files): audit fixes — transaction, status codes, contract refinements, guards
* fix(vfs): pass folderPath separately so buildWorkspaceMd groups files correctly
* fix(types): narrow unknown fileInput with Record cast after object guard
* fix(routes): replace instanceof Error with toError() across new workspace file routes
* improvement(files): cleanup pass — remove unnecessary useCallbacks, consolidate emcn icon imports
- Remove useCallback from 5 drag-event handlers in DataRow (passed to native <tr> elements, no observer)
- Remove stable useCallback fns from 3 useMemo deps arrays in files.tsx (editingId/editValue remain)
- Merge all @/components/emcn/icons subpath imports into barrel (files.tsx, action-bar, file-row-context-menu)
* fix(files): apply activeSort to folders, reject drop onto current parent folder
- visibleFolders now respects activeSort column (name/updated/created) and direction
so folder ordering stays consistent with file ordering
- isInvalidDropTarget now returns true when all dragged items are already direct children
of the target folder, preventing a no-op move mutation
* fix breadcrumb
* add new tools to rename, create, delete folders
* move more ui actions into orchestration dir
* address comments
* fix params
* fix tests
* address comments
* improve error codes
* address comments
* address more nits
* fix mcp server error code
---------
Co-authored-by: Theodore Li <theodoreqili@gmail.com>
Co-authored-by: waleed <walif6@gmail.com>1 parent bad21cb commit c9118e7
205 files changed
Lines changed: 11101 additions & 3412 deletions
File tree
- apps/sim
- app
- (landing)
- components
- auth-modal
- demo-request
- integrations/components
- api
- credentials/[id]
- folders
- [id]
- knowledge/[id]/restore
- mcp
- servers
- [id]
- workflow-servers
- [id]
- tools
- [toolId]
- schedules
- [id]
- table
- [tableId]/restore
- tools/file/manage
- v1/files/[fileId]
- workflows
- [id]
- restore
- workspaces/[id]
- api-keys
- files
- [fileId]
- restore
- bulk-archive
- download
- folders
- [folderId]
- restore
- move
- presigned
- register
- playground
- workspace/[workspaceId]
- components
- message-actions
- resource
- files
- components
- action-bar
- delete-confirm-modal
- file-viewer
- home/components
- mothership-view/components
- add-resource-dropdown
- resource-registry
- user-input/components
- knowledge
- [id]
- [documentId]
- components
- delete-chunk-modal
- document-tags-modal
- components
- add-connector-modal
- add-documents-modal
- base-tags-modal
- connectors-section
- edit-connector-modal
- rename-document-modal
- components
- create-base-modal
- delete-knowledge-base-modal
- edit-knowledge-base-modal
- logs/components
- log-details/components/execution-snapshot
- logs-toolbar/components/notifications
- scheduled-tasks
- components/create-schedule-modal
- settings/components
- api-keys
- components/create-api-key-modal
- byok
- copilot
- credential-sets
- custom-tools
- general
- inbox
- integrations
- mcp
- components/mcp-server-form-modal
- recently-deleted
- secrets
- skills
- components
- subscription
- components/credit-balance
- team-management/components
- remove-member-dialog
- team-seats
- transfer-ownership-dialog
- workflow-mcp-servers
- tables
- [tableId]
- components/row-modal
- components/import-csv-dialog
- w
- [workflowId]/components/panel
- components
- deploy/components/deploy-modal
- components
- chat
- general
- components
- template
- editor/components/sub-block/components
- grouped-checkbox-list
- tool-input/components/custom-tool-modal
- components/sidebar
- components
- file-list
- help-modal
- search-modal
- components
- settings-sidebar
- workflow-list/components/delete-modal
- workspace-header
- components
- create-workspace-modal
- invite-modal
- components/emcn
- components/wizard
- icons
- ee
- access-control/components
- data-drains/components
- hooks/queries
- lib
- api-key/orchestration
- api/contracts
- tools
- copilot
- chat
- generated
- resources
- tools
- handlers
- deployment
- management
- workflow
- server
- files
- vfs
- credentials/orchestration
- knowledge/orchestration
- mcp
- orchestration
- posthog
- resources/orchestration
- table/orchestration
- uploads
- client
- contexts/workspace
- core
- server
- utils
- workflows
- orchestration
- schedules
- workspace-files/orchestration
- stores/panel
- packages
- audit/src
- db
- migrations
- meta
- testing/src/mocks
- scripts
Some content is hidden
Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
84 | 84 | | |
85 | 85 | | |
86 | 86 | | |
| 87 | + | |
Lines changed: 4 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
10 | 10 | | |
11 | 11 | | |
12 | 12 | | |
| 13 | + | |
13 | 14 | | |
14 | 15 | | |
15 | 16 | | |
| |||
134 | 135 | | |
135 | 136 | | |
136 | 137 | | |
| 138 | + | |
| 139 | + | |
| 140 | + | |
137 | 141 | | |
138 | 142 | | |
139 | 143 | | |
| |||
Lines changed: 4 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
8 | 8 | | |
9 | 9 | | |
10 | 10 | | |
| 11 | + | |
11 | 12 | | |
12 | 13 | | |
13 | 14 | | |
| |||
152 | 153 | | |
153 | 154 | | |
154 | 155 | | |
| 156 | + | |
| 157 | + | |
| 158 | + | |
155 | 159 | | |
156 | 160 | | |
157 | 161 | | |
| |||
Lines changed: 8 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
8 | 8 | | |
9 | 9 | | |
10 | 10 | | |
| 11 | + | |
11 | 12 | | |
12 | 13 | | |
13 | 14 | | |
| |||
83 | 84 | | |
84 | 85 | | |
85 | 86 | | |
| 87 | + | |
| 88 | + | |
| 89 | + | |
86 | 90 | | |
87 | 91 | | |
88 | 92 | | |
| |||
106 | 110 | | |
107 | 111 | | |
108 | 112 | | |
| 113 | + | |
| 114 | + | |
| 115 | + | |
| 116 | + | |
109 | 117 | | |
110 | 118 | | |
111 | 119 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1 | | - | |
2 | 1 | | |
3 | | - | |
| 2 | + | |
4 | 3 | | |
5 | | - | |
6 | 4 | | |
7 | 5 | | |
8 | 6 | | |
9 | 7 | | |
10 | 8 | | |
11 | | - | |
12 | 9 | | |
13 | 10 | | |
14 | | - | |
15 | | - | |
16 | | - | |
17 | | - | |
18 | | - | |
19 | | - | |
| 11 | + | |
20 | 12 | | |
21 | 13 | | |
22 | 14 | | |
| |||
93 | 85 | | |
94 | 86 | | |
95 | 87 | | |
96 | | - | |
97 | | - | |
98 | | - | |
99 | | - | |
100 | | - | |
101 | | - | |
102 | | - | |
103 | | - | |
104 | | - | |
105 | | - | |
106 | | - | |
107 | | - | |
108 | | - | |
109 | | - | |
110 | | - | |
111 | | - | |
112 | | - | |
113 | | - | |
114 | | - | |
115 | | - | |
116 | | - | |
117 | | - | |
118 | | - | |
119 | | - | |
120 | | - | |
121 | | - | |
122 | | - | |
123 | | - | |
124 | | - | |
125 | | - | |
126 | | - | |
127 | | - | |
128 | | - | |
129 | | - | |
130 | | - | |
131 | | - | |
132 | | - | |
133 | | - | |
134 | | - | |
135 | | - | |
136 | | - | |
137 | | - | |
138 | | - | |
139 | | - | |
140 | | - | |
141 | | - | |
142 | | - | |
143 | | - | |
144 | | - | |
145 | | - | |
146 | | - | |
147 | | - | |
148 | | - | |
149 | | - | |
150 | | - | |
151 | | - | |
152 | | - | |
153 | | - | |
154 | | - | |
155 | | - | |
156 | | - | |
157 | | - | |
158 | | - | |
159 | | - | |
| 88 | + | |
| 89 | + | |
| 90 | + | |
160 | 91 | | |
161 | 92 | | |
162 | | - | |
163 | | - | |
164 | | - | |
165 | | - | |
166 | | - | |
167 | | - | |
168 | | - | |
169 | | - | |
170 | | - | |
| 93 | + | |
| 94 | + | |
| 95 | + | |
171 | 96 | | |
172 | 97 | | |
| 98 | + | |
| 99 | + | |
| 100 | + | |
| 101 | + | |
| 102 | + | |
| 103 | + | |
| 104 | + | |
| 105 | + | |
| 106 | + | |
| 107 | + | |
| 108 | + | |
| 109 | + | |
| 110 | + | |
173 | 111 | | |
174 | 112 | | |
175 | 113 | | |
176 | 114 | | |
177 | | - | |
178 | | - | |
179 | | - | |
180 | | - | |
181 | | - | |
182 | | - | |
183 | 115 | | |
184 | 116 | | |
185 | 117 | | |
| |||
196 | 128 | | |
197 | 129 | | |
198 | 130 | | |
199 | | - | |
200 | | - | |
201 | | - | |
202 | | - | |
203 | | - | |
204 | | - | |
205 | | - | |
206 | | - | |
207 | | - | |
208 | | - | |
209 | | - | |
210 | | - | |
211 | | - | |
212 | | - | |
213 | | - | |
214 | | - | |
215 | | - | |
216 | | - | |
217 | | - | |
218 | | - | |
219 | | - | |
220 | | - | |
221 | | - | |
222 | | - | |
223 | | - | |
224 | | - | |
225 | | - | |
226 | | - | |
227 | | - | |
228 | | - | |
229 | | - | |
230 | | - | |
231 | | - | |
232 | | - | |
233 | | - | |
234 | | - | |
235 | | - | |
236 | | - | |
237 | | - | |
238 | | - | |
239 | | - | |
240 | | - | |
241 | | - | |
242 | | - | |
243 | | - | |
244 | | - | |
245 | | - | |
246 | | - | |
247 | | - | |
248 | | - | |
249 | | - | |
250 | | - | |
251 | | - | |
252 | | - | |
253 | | - | |
254 | | - | |
255 | | - | |
256 | | - | |
257 | | - | |
258 | | - | |
259 | | - | |
260 | | - | |
261 | | - | |
262 | | - | |
263 | | - | |
264 | | - | |
265 | | - | |
266 | | - | |
267 | | - | |
268 | | - | |
269 | | - | |
270 | | - | |
271 | | - | |
272 | | - | |
273 | | - | |
274 | | - | |
275 | | - | |
276 | | - | |
277 | | - | |
278 | | - | |
279 | | - | |
280 | | - | |
281 | | - | |
282 | | - | |
283 | | - | |
284 | | - | |
285 | | - | |
286 | | - | |
287 | | - | |
288 | | - | |
289 | | - | |
290 | | - | |
291 | | - | |
292 | | - | |
293 | | - | |
294 | | - | |
295 | | - | |
296 | | - | |
297 | | - | |
298 | | - | |
299 | | - | |
300 | | - | |
301 | | - | |
302 | | - | |
303 | | - | |
304 | | - | |
305 | | - | |
306 | | - | |
307 | | - | |
308 | | - | |
309 | | - | |
310 | | - | |
311 | | - | |
312 | | - | |
313 | | - | |
314 | | - | |
315 | | - | |
316 | | - | |
317 | | - | |
318 | | - | |
319 | | - | |
320 | | - | |
321 | | - | |
322 | | - | |
323 | | - | |
324 | | - | |
325 | | - | |
326 | | - | |
327 | | - | |
328 | | - | |
329 | | - | |
330 | | - | |
331 | | - | |
332 | | - | |
333 | | - | |
334 | | - | |
335 | | - | |
336 | | - | |
337 | | - | |
| 131 | + | |
338 | 132 | | |
339 | | - | |
| 133 | + | |
340 | 134 | | |
341 | 135 | | |
342 | | - | |
343 | 136 | | |
344 | 137 | | |
345 | | - | |
346 | | - | |
347 | | - | |
348 | | - | |
349 | | - | |
350 | | - | |
351 | | - | |
352 | | - | |
353 | | - | |
354 | | - | |
355 | | - | |
| 138 | + | |
| 139 | + | |
| 140 | + | |
| 141 | + | |
| 142 | + | |
| 143 | + | |
| 144 | + | |
| 145 | + | |
| 146 | + | |
| 147 | + | |
| 148 | + | |
356 | 149 | | |
357 | 150 | | |
358 | 151 | | |
| |||
0 commit comments