ux(canvas/files): "Files not available" banner for external runtimes (#2999 PR-B) - #3003
Merged
Merged
Conversation
…2999 PR-B) ## Why Reported by user (issue #2999): external workspaces (mac laptop, mac mini, hermes-on-home-server — runtime="external") render the FilesTab identically to the SaaS empty-listing bug, showing "0 files / No config files yet" even though the platform doesn't actually own the filesystem of these workspaces. Visually indistinguishable from the broken state, reads as a bug. ## Fix Mirror the affordance TerminalTab adopted in PR #2830 for runtimes without a TTY: 1. New `NotAvailablePanel` in `canvas/src/components/tabs/FilesTab/` — folder-with-slash icon + "Files not available" headline + body text that names the runtime and points the user at Chat. 2. `FilesTab` now takes optional `data?: WorkspaceNodeData`. When `data.runtime` is in `RUNTIMES_WITHOUT_FILES` (currently just "external"), early-return the placeholder before mounting the useFilesApi hook. Mirrors TerminalTab's prop shape exactly so the review pattern is uniform across tabs. 3. SidePanel passes `node.data` to FilesTab (matches existing pattern for ChatTab / TerminalTab). ## Test coverage `FilesTab.notAvailable.test.tsx` (4 tests): - external runtime → banner renders with runtime name + Chat-tab guidance copy. - external runtime → NO `/files` API request fires (asserted by inspecting the mocked api.get call log). - claude-code runtime → no banner, normal mount proceeds (toolbar's root selector is the discriminator). - data prop omitted → falls through to normal mount (back-compat with any caller that doesn't thread data through, e.g. legacy tests). Each branch is independent and discriminating — none would pass on a code-deleted version of the early-return. ## Three weakest spots (hostile self-review) 1. `RUNTIMES_WITHOUT_FILES` is a hardcoded set in this file. If a future runtime joins (e.g. a "byok-claude" that runs on user hardware), someone has to remember to add it here. Reviewed alternatives: pull from a runtime-capabilities registry — same shape as `RUNTIMES_WITHOUT_TERMINAL` already in TerminalTab. We chose the parallel pattern over a new abstraction; consolidating into a shared registry can land if/when a third tab grows the same gate (rule of three). Documented inline. 2. The placeholder is a static panel — no retry, no "report bug" link. Same as TerminalTab's. Acceptable because the absence is intentional, not transient. 3. Chat-tab guidance is hardcoded English. No i18n in canvas yet; matches the rest of the codebase. Will move with the i18n migration when that lands. ## Verification - `npx tsc --noEmit` clean - 54/54 canvas tab + SidePanel tests pass - Will be live-verified on staging post-merge: open Files tab on an external workspace (mac laptop) → expect placeholder; open on a platform-owned workspace (Hongming Personal Brand Agent) → expect normal tree (assuming PR-A also lands). Refs #2999. Pairs with PR-A (backend EIC fix) — without PR-A the platform-owned path still shows "0 files" because the backend never returns rows. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
HongmingWang-Rabbit
requested a review
from hongmingwang-moleculeai
as a code owner
May 6, 2026 03:22
HongmingWang-Rabbit
enabled auto-merge
May 6, 2026 03:23
6 tasks
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.
Why
Reported by user (issue #2999): external workspaces (mac laptop, mac mini, hermes-on-home-server —
runtime="external") render the FilesTab identically to the SaaS empty-listing bug, showing "0 files / No config files yet" even though the platform doesn't actually own the filesystem of these workspaces. Visually indistinguishable from the broken state, reads as a bug.Fix
Mirror the affordance TerminalTab adopted in PR #2830 for runtimes without a TTY:
NotAvailablePanelincanvas/src/components/tabs/FilesTab/— folder-with-slash icon + "Files not available" headline + body text that names the runtime and points the user at Chat.FilesTabnow takes optionaldata?: WorkspaceNodeData. Whendata.runtimeis inRUNTIMES_WITHOUT_FILES(currently just"external"), early-return the placeholder before mounting theuseFilesApihook.node.datato FilesTab (matches existing pattern for ChatTab / TerminalTab).Test coverage
FilesTab.notAvailable.test.tsx(4 tests):/filesAPI request fires (asserted by inspecting the mockedapi.getcall log — discriminating: would fail without the early-return).dataprop omitted → falls through to normal mount (back-compat with legacy callers).Three weakest spots (hostile self-review)
RUNTIMES_WITHOUT_FILESis hardcoded. Reviewed alternative: pull from a shared runtime-capabilities registry (same shape as TerminalTab'sRUNTIMES_WITHOUT_TERMINAL). Chose parallel pattern; consolidating into a shared registry can land if/when a third tab grows the same gate (rule of three).Verification
npx tsc --noEmitcleanPairing
Pairs with PR #3002 (PR-A, backend EIC fix). Without PR-A the platform-owned path still shows "0 files" because the backend never returns rows. Both can merge in either order; PR-B alone fixes the external-workspace UX, PR-A alone fixes the SaaS listing.
Refs #2999.
🤖 Generated with Claude Code