Lazily load the file tree per directory instead of scanning it whole - #1
Open
yazydzhi wants to merge 2 commits into
Open
Lazily load the file tree per directory instead of scanning it whole#1yazydzhi wants to merge 2 commits into
yazydzhi wants to merge 2 commits into
Conversation
…whole listTree fetched the entire workspace recursively (host.list_paths, capped at TREE_LIMIT=10,000) on every mount, and again every 10s on the background poll. Expand/collapse only filtered that in-memory flat list — collapsing a folder never freed anything. On a large workspace (tens of thousands of files) this was slow, wasteful, and after a host-daemon bugfix landed, still routinely hit the plugin's 10k display cap on every load. Add a new listDirectory RPC (single-level, via bb.sdk.hosts.directory / host.browse_directory) alongside the existing listTree. useFilesWorkspace now keeps loaded children keyed by directory path: - Mount fetches only the root directory. - Expanding a folder fetches its children with one shallow call. - Collapsing a folder drops its subtree from state so it's re-fetched fresh next time, instead of just being hidden. - Opening a path (e.g. after creating a file) expands every ancestor folder to reveal it, fetching each lazily. - The 10s background refresh and post-mutation refresh now re-fetch only the root plus whatever's currently expanded, not the whole tree. listTree is unchanged and still does a full recursive host-side search when the search box has a query — full-depth search is still exactly what search should do. Updated app.test.tsx's initial-mount mocks from listTree to listDirectory (they were exercising the eager root load, now served by the new endpoint), and added a test covering expand fetching children and collapse dropping them from state. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Reopen workspace files via threads.open so Settings → File openers apply. Add Open in SQL when the sql plugin is available, plus Open with preferred for any file, and document the Files vs host-preview distinction. Co-authored-by: Cursor <cursoragent@cursor.com>
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.
Problem
`listTree` fetches the entire workspace recursively (`host.list_paths`, capped at `TREE_LIMIT = 10_000`) on every mount of the Files panel, and again every 10 seconds via the background poll (`useFilesWorkspace`'s `setInterval`). Expanding/collapsing a folder in `TreePane` only filters that already-fully-loaded flat list client-side (`filterVisibleEntries`) — collapsing never actually frees anything, because everything was already in memory.
On a large workspace (tens of thousands of files — e.g. a big Obsidian vault, a big monorepo) this means:
Fix
Add a new `listDirectory` RPC — a single-level directory read via `bb.sdk.hosts.directory` (`host.browse_directory`), which BB already exposes for exactly this "interactive path browser" use case. Unlike `host.list_paths`, it reads exactly one directory, so its cost is independent of workspace size.
`useFilesWorkspace` now keeps loaded children keyed by directory path (`Map<path, FileTreeEntry[]>`) instead of one big flat array:
`listTree` is unchanged and still does a full recursive host-side search when the search box has a query — that's still exactly the right tool for search, since search has to look at everything regardless of what's expanded.
Testing
Test plan