feat(files): folder operations for the File block, and folders as scope - #7388
Closed
mzxchandra wants to merge 11 commits into
Closed
feat(files): folder operations for the File block, and folders as scope#7388mzxchandra wants to merge 11 commits into
mzxchandra wants to merge 11 commits into
Conversation
Adds folder operations to file_v5 and the agent tool surface, and makes a folder a scope on the file operations that already existed rather than a second set of operations beside them. New operations: List, Create Folder, Move Folder, Delete Folder, Restore Folder, and Move File. List answers "what is in here" — subfolders and files together, direct children by default, the whole subtree under Recursive, subject to Max Depth and Search. Entries are a discriminated union on kind, and the listing is capped with a truncated flag rather than unbounded now that it includes files. Read, Get Content, Compress and Append gain an optional Folder above their file picker. It narrows what the picker offers; on the three read operations it also stands for that folder's files when none are picked, resolved when the workflow runs so a file added later is included. Append only narrows the picker, but the folder does travel when the advanced entry supplies a name rather than an id, because a name is only unique inside a folder. Write gains a folder destination, placed above File Name because it names where before it names what. Two things are worth a reviewer's attention. Path handling. Two spellings circulate: the stored display path, which backslash-escapes a slash inside a folder name, and the canonical percent-encoded path the tools take. A folder genuinely named "Q3/Q4" is one level in both and two if either is split on "/". folderPathSegments picks the parser by the leading slash the canonical form always carries, and resolveFolderIdsForPaths, isFileInFolderScope and selectDirectoryEntries are pure and tested against exactly that case. Where a folder is known, the code resolves by id and never builds a path-shaped reference at all. Delete Folder's recursive flag is a guard, not a scope. Without it, deleting a non-empty folder fails, and it is user-only so a model asked to clean up a folder cannot set it on a guess. This is deliberately the inverse of the read family's Include Subfolders, which is a scope and defaults on. Five file operations widen from copilot-only delegation to admit the executor, each justified by a tool in this change: files.list and files.folders.list for file_list, and files.folders.update / delete / restore for their tools. Principal kinds are unchanged and copilot keeps every operation it had.
|
The latest updates on your projects. Learn more about Vercel for GitHub. |
Contributor
Greptile SummaryThis PR expands the File block and agent tool surface with folder-aware file operations and folder scopes.
Confidence Score: 5/5The PR appears safe to merge. No blocking failure remains.
|
| Filename | Overview |
|---|---|
| apps/sim/blocks/blocks/file.ts | Extends File block configuration and parameter mapping with folder operations and folder-scoped file inputs. |
| apps/sim/lib/internal/file/operations.ts | Wires folder-aware file behavior and new folder-management operations into internal execution. |
| apps/sim/lib/workspace-files/application/workspace-file-folders.ts | Implements the workspace application layer for creating, moving, deleting, and restoring file folders. |
| apps/sim/lib/workspace-files/folder-path-selection.ts | Resolves canonical folder paths and evaluates file membership in folder scopes. |
| apps/sim/lib/workspace-files/directory-listing.ts | Produces bounded folder-and-file directory listings with recursive depth and search controls. |
| apps/sim/app/workspace/[workspaceId]/hooks/use-workspace-invalidation-room.ts | Reference-counts shared realtime room subscriptions so sibling consumers do not leave prematurely. |
| apps/sim/blocks/blocks/file-folders.test.ts | Exercises File block folder-operation mapping and validates mapped payloads against real contract schemas. |
Flowchart
%%{init: {'theme': 'neutral'}}%%
flowchart LR
UI[File block and agent tools] --> Contract[File operation contracts]
Contract --> Executor[Internal file executor]
Executor --> Paths[Canonical folder path resolution]
Paths --> Operations[Workspace file and folder operations]
Operations --> Storage[Workspace files and folders]
Storage --> Realtime[Workspace invalidation events]
Realtime --> UI
Reviews (4): Last reviewed commit: "fix(files): scope the picker from either..." | Re-trigger Greptile
Co-authored-by: cubic-dev-ai[bot] <191113872+cubic-dev-ai[bot]@users.noreply.github.com>
…s.test.ts Co-authored-by: cubic-dev-ai[bot] <191113872+cubic-dev-ai[bot]@users.noreply.github.com>
Co-authored-by: cubic-dev-ai[bot] <191113872+cubic-dev-ai[bot]@users.noreply.github.com>
This was referenced Sep 2, 2026
Merged
Contributor
Author
Contributor
Author
|
@cubic review |
Contributor
@mzxchandra I have started the AI code review. It will take a few minutes to complete. |
Contributor
Author
Contributor
Author
|
@cubic review |
Contributor
@mzxchandra I have started the AI code review. It will take a few minutes to complete. |
Contributor
Author
Contributor
Author
|
@cubic review |
Contributor
@mzxchandra I have started the AI code review. It will take a few minutes to complete. |
Collaborator
|
Will merge downstream one directly into staging |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Replaces #7377, which is the same change spread over 11 commits and two staging merges. Reviewers were reading a diff-of-diffs and finding issues in the fixes rather than in the change; this is one commit against current
staging.What
Adds folder operations to
file_v5and the agent tool surface, and makes a folder a scope on the file operations that already existed rather than a second set of operations beside them.New operations: List, Create Folder, Move Folder, Delete Folder, Restore Folder, Move File.
List answers "what is in here" — subfolders and files together, direct children by default, whole subtree under Recursive, subject to Max Depth and Search. Entries are a discriminated union on
kind; the listing is capped with atruncatedflag rather than unbounded now that it includes files.Read / Get Content / Compress / Append gain an optional Folder above their file picker. It narrows what the picker offers; on the three read operations it also stands for that folder's files when none are picked, resolved at run time so a file added later is included. Append only narrows the picker — but the folder does travel when the advanced entry supplies a name rather than an id, because a name is only unique inside a folder.
Write gains a folder destination, above File Name, because it names where before what.
Where to spend attention
Path handling. Two spellings circulate: the stored display path, which backslash-escapes a slash inside a folder name (
Reports/Q3\/Q4), and the canonical percent-encoded path the tools take (/Reports/Q3%2FQ4). A folder genuinely namedQ3/Q4is one level in both and two if either is split on/.folderPathSegmentspicks the parser by the leading slash;resolveFolderIdsForPaths,isFileInFolderScopeandselectDirectoryEntriesare pure and tested against that case. Where a folder is known, resolution goes by id and never builds a path-shaped reference.Delete's
recursiveis a guard, not a scope. Without it, deleting a non-empty folder fails, and it isuser-onlyso a model asked to "clean up" cannot set it on a guess. Deliberately the inverse of the read family's Include Subfolders, which is a scope and defaults on.The authz widening. Five operations move from copilot-only delegation to also admit the executor —
files.listandfiles.folders.listforfile_list, andfiles.folders.update/delete/restorefor their tools. Principal kinds are unchanged and copilot keeps everything it had; the only delta isdelegatedServicesgaining'executor', without which a workflow run cannot reach these at all.Canonical pairs. Every folder field is a single-select tree paired with a manual text entry. The pair is load-bearing, not a convenience:
<reference autocomplete comes fromTagDropdown, which scans for the last<before the cursor, so it can only live on a text surface. The one folder field that never travels (the picker-narrowing scope) deliberately has no pair.Known costs, already argued
listreads the workspace's full folder and file lists and filters in memory, matching ~10 existing callers oflistAllWorkspaceFiles. Output is capped withtruncated; the read is not.queryWorkspaceFilePageis the paged alternative, worth doing across all callers rather than only this one.Testing
tscclean; 4209 tests acrossblocks,tools/file,lib/internal/file,lib/workspace-files,lib/workflows; all 45 audits;check:api-validation;check:client-boundary; biome.Coverage is deliberately weighted at the wiring, because that is where this change broke repeatedly: a contract accepting a field is not the same as the operation reading it. Tests assert a folder-only read expands, a missing folder refuses rather than reading nothing, write lands in the chosen folder and still lands at root without one, an ambiguous name inside a scope refuses instead of picking, and a folder named
Q3/Q4survives both scope resolution and overwrite lookup.Browser end-to-end is in progress against this branch.