Skip to content

Let file openers handle opens without a file tab - #5614

Open
patleeman wants to merge 2 commits into
get-bb:mainfrom
patleeman:fileopener-handle-open
Open

patleeman wants to merge 2 commits into
get-bb:mainfrom
patleeman:fileopener-handle-open

Conversation

@patleeman

Copy link
Copy Markdown
Contributor

Human comments

What was wrong

A plugin fileOpener can only show a file by rendering its component inside a new panel file tab. Openers that show files somewhere else have no way to claim the open. Studio Code's VS Code opener sends code files to the thread's single "VS Code" panel tab, so every file open also leaves a useless file tab ("Opened in VS Code beside this thread") next to it. The SDK has no way for an opener to skip the tab or close its own tab.

What changed

  • Plugin SDK (app-contract.ts, collector): PluginFileOpenerRegistration gets an optional experimental_handleOpen?: (args: PluginFileOpenerOpenArgs) => boolean | Promise<boolean>, where PluginFileOpenerOpenArgs is { path, source, lineRange }. The collector checks that it is a function.
  • App (file-opener-tabs.ts, useThreadFileTabs.ts): createFileOpenerOpenForRequest resolves the opener exactly as before (Open with, Settings → Files pin, slot order) and returns the tab plus a bound handler. openResolvedTab calls the handler before inserting the tab:
    • true: no tab is created or focused.
    • false, a throw/rejection, or no answer within 3 seconds: the normal opener tab is inserted, as today.
    • Not called for an explicit "Open with" choice, for New Tab file search (which fills the New Tab in place), or when BB's preview wins through the user's pin.
  • openTab still returns the tab synchronously, so callers like openFilePreview keep revealing the panel; the tab is inserted once the handler declines.
  • Docs: frontend-core-slots.md, docs/api_to_audit.md entry, Plugin Guide surface symbols.

No server/daemon wire changes. Plugins built against older hosts are unaffected; on older hosts the field is ignored and component remains the fallback.

How you verified

  • New tests: useThreadFileTabs.test.ts (handled → no tab and handler args include source and line range; declined/throwing → opener tab; explicit Open with → handler skipped), file-opener-tabs.test.ts (callFileOpenerHandleOpen: true/false, throw/reject, timeout).
  • pnpm exec turbo run typecheck --filter=@bb/app --filter=@get-bb/plugin-sdk --filter=bb-plugin-plugin-api-docs: passed.
  • vitest run src/components/plugin/file-opener-tabs.test.ts src/components/secondary-panel in apps/app: 57 files, 531 tests passed.
  • turbo run test --filter=@get-bb/plugin-sdk --filter=bb-plugin-plugin-api-docs: 371 + 72 passed.

AGENT GENERATED

🤖 Generated with Claude Code

patleeman and others added 2 commits October 16, 2026 19:52
Add experimental_handleOpen to fileOpener registrations. When BB is about
to open a tab for that opener through default resolution or the Settings
pin, it asks the handler first; true means no tab, while false, a throw
or a 3 second timeout open the normal tab. Explicit Open with choices and
New Tab file search skip the handler.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@patleeman
patleeman force-pushed the fileopener-handle-open branch from 16c8f54 to 3edd1d2 Compare October 16, 2026 23:53

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant