Make plugin file openers reachable and give them a real height - #2026
Merged
Conversation
A plugin `fileOpener` could not work end to end. Three independent defects, each of which alone made the slot unusable: The file search built its tab through `createTabForFileSearchSelection` and never called `createFileOpenerTabForRequest`, so every file picked from the "+"/quick-open screen got the built-in preview no matter what Settings → File openers said. Diversion applied only to file links and `bb thread open`, contradicting the comment on `openTab` that claims every file-open flow funnels through it. `fileTabContentFillsRegion` resolved the active tab's `actionId` against `threadPanelActions`, but a file-opener tab's actionId is `file-opener:<id>` and never matched, so opener tabs always landed in the preview's scroll container instead of the definite-height region. The file-opener wrapper was `min-h-0 flex-1` where the action-tab wrapper is `h-full min-h-0 flex-1`. That region is a block box, so `flex-1` was inert and the wrapper collapsed to content height — an opener sizing itself with `flex-1` got zero height. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The search path had no coverage, which is why it could silently skip opener diversion while the link and `bb thread open` paths were tested. The first test fails before the fix and passes after; the other two pin the fallbacks (unmatched extension, pinned built-in) so a future change cannot start diverting files the user asked BB to keep. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
andrewkchan
force-pushed
the
fix/plugin-file-opener-slot
branch
from
August 20, 2026 09:00
69f5329 to
0faccf7
Compare
andrewkchan
added a commit
to andrewkchan/bb-plugin-monaco
that referenced
this pull request
Aug 20, 2026
The [monaco-plugin] tracing existed to find why BB never routed files to the opener; that turned out to be a host bug (get-bb/bb#2026) and the logs have served their purpose. Failures already surface in the UI — open errors become the editor's error notice, and loader failures reject the boot promise into that same path — so nothing observable is lost. Keeps one console.warn for the case where Monaco's typescript defaults cannot be found at either the current or deprecated path. That one is silent on success and otherwise invisible: the symptom would be an editor full of false "Cannot find module" errors with no stated cause. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This was referenced Aug 20, 2026
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.
Human comments
Before this, (1) custom file openers did not work on files opened via CMD+P, and (2) a custom file opener would render with nearly 0px height:

What was wrong
The
fileOpenerplugin slot could not work end to end — three independent defects, each of which alone made the slot unusable. Reachability: the secondary panel's file search built its tab throughcreateTabForFileSearchSelectionand never calledcreateFileOpenerTabForRequest, so a file picked from the "+"/quick-open screen always got the built-in preview regardless of the user's Settings → File openers choice; diversion applied only to file links andbb thread open, contradicting the comment onopenTabthat claims every file-open flow funnels through it. Sizing:fileTabContentFillsRegionresolved the active tab'sactionIdagainstthreadPanelActions, but a file-opener tab's actionId isfile-opener:<id>(FILE_OPENER_ACTION_ID_PREFIX) and never matched, so opener tabs always landed in the preview's scroll container rather than the definite-height region; and the file-opener wrapper wasmin-h-0 flex-1where the action-tab wrapper 90 lines above it ish-full min-h-0 flex-1. Since that region is a block box,flex-1was inert and the wrapper collapsed to content height, so an opener that sizes itself withflex-1rendered at zero height.Found while building a Monaco-based editor plugin against the slot: the opener registered, appeared in Settings, was explicitly selected for
.tsand.json, and still never rendered — and once forced to render, occupied ~10px.What changed
apps/app/src/components/secondary-panel/useThreadFileTabs.ts—selectFileSearchResultnow runs the same opener diversion asopenTab, falling back to the built-in tab when no opener matches. The replace-the-new-tab-screen behavior is unchanged.apps/app/src/views/thread-detail/ThreadDetailView.tsx,apps/app/src/views/RootComposeView.tsx—fileTabContentFillsRegionnow also returns true for file-opener tabs, keyed offfileOpenerOwner(already set on exactly these tabs). A plugin opener owns its own layout and scrolling, so it gets the definite-height region, matching alayout: "flush"action tab.apps/app/src/components/plugin/PluginPanelActions.tsx— the file-opener wrapper gainsh-full, matching the action-tab wrapper.No wire changes, so
HOST_DAEMON_PROTOCOL_VERSIONis untouched. No CLI, guide, or doc surfaces are affected: this restores documented behavior rather than adding any.Both sizing changes are required. Without the region fix the opener fills a scroll container and overflows by its
pb-3; withouth-fullthe wrapper stays content-sized however tall the region is.How you verified
Three tests added to
useThreadFileTabs.test.ts, alongside the existingopenTabdiversion coverage:diverts a workspace file picked from the file search— fails before, passes after. Verified by restoring the pre-fixuseThreadFileTabs.tswith the new tests in place: 17 pass, this one fails; with the fix, 18 pass.keeps the built-in preview for an unmatched file search extensionandhonors a pinned built-in preference from the file search— pass both before and after. They are guards, not regression proofs: they pin the fallbacks so a future change cannot start diverting files the user asked BB to keep.The two sizing defects are not covered by automated tests. They are CSS-in-DOM-context failures — the wrapper collapses only because its ancestor is a block box — and the only cheap unit test available would assert a Tailwind class string, which is the kind of test AGENTS.md discourages. Testing them for real would mean extracting the
fileTabContentFillsRegioncomputation out of both views into a helper; happy to do that if reviewers want it covered.Verified manually against a dev server on this checkout with a Monaco
fileOpenerplugin installed. Before: quick-open a.tsfile → built-in preview, with the plugin's registration confirmed live in the console and "Automatic (Monaco)" selected in Settings; pinning.jsonto Monaco explicitly changed nothing. Walking the DOM from[data-testid="plugin-file-opener-tab-content"]showed the wrapper atclientHeight: 38inside adisplay: blockscroll container at 775px. After: quick-open renders the plugin editor, filling the panel, with editing, saving, and find working.Fixes #