Ship the Monaco editor as a builtin plugin - #2127
Open
andrewkchan wants to merge 2 commits into
Open
Conversation
Replaces BB's read-only file preview with Monaco for ~86 text and code extensions: editing with compare-and-swap saves, find, syntax highlighting, and a file tree with filtering and copy actions. Enabled by default under the Interface category, so the panel becomes an editor rather than a viewer; per-extension opt-out stays in Settings → File openers, and binaries still fall through to BB's preview via experimental_Original. Monaco loads its prebuilt AMD bundle from disk rather than being bundled: the plugin build has no loader for its font asset, cannot code split, and inlining it would add ~4.4 MB to every app boot. Packaging copies only a builtin's dist/, so scripts/stage-assets.mjs stages monaco-editor/min/vs into dist/vs and the server serves it over a files.createPreview lease. copy-builtin-plugins.ts gains a generic hook that runs a plugin's stage-assets.mjs when it has one — the mechanism any plugin needing runtime files on disk would use. This adds ~25 MB to the packaged app. Ported from the standalone plugin: imports @bb/shared-ui instead of vendored components, resolves project-backed workspace sources (which carry no environment and may name a host), and accepts the experimental_hostId field main added to PluginFileOpenerSource. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
A 400 KB PNG in the repo for a README heading is weight the tree does not need to carry; the standalone plugin keeps it. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.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.
Human comments
This basically upstreams https://github.com/andrewkchan/bb-plugin-monaco as a built-in plugin.
Likely the big thing to be aware of is that it adds 25MB to the packaged app. We should be able to optimize later if needed
What was wrong
BB's file panel is read-only. Opening a file from chat, the file search, or
bb thread opengives a preview, so any edit means leaving BB for an editor — even for a one-line change to a file the agent just wrote. Sawyer asked to upstream the Monaco plugin I built out-of-tree (andrewkchan/bb-plugin-monaco) so the panel can edit as well as show.What changed
New builtin:
plugins/monaco. AfileOpenerthat replaces the preview with Monaco for ~86 text and code extensions:expectedSha256, so a save that would clobber a concurrent write (usually the agent's) stops and offers Reload or Overwrite.font-mono text-xs leading-5,--font-mono, light/dark).Registered
defaultEnabled: trueunderInterface. That is the significant product change: the file panel becomes an editor for nearly every text file by default. Per-extension opt-out lives in Settings → File openers, and binaries fall through to BB's preview viaexperimental_Original.Monaco is served from disk, not bundled. The plugin build has no loader for Monaco's
codicon.ttfand cannot code split, so bundling would fail outright and, if patched around, add ~4.4 MB to every app boot for all users. Instead the server hands the frontend afiles.createPreviewlease over Monaco's prebuilt AMD build, and nothing loads until a file tab opens.A generic staging hook (
apps/server/scripts/copy-builtin-plugins.ts). Packaging copies only a builtin'sdist/andskills/, and builds plugins itself without running per-plugin scripts — so a plugin needing runtime files on disk has nowhere to put them.copyBuiltinPluginnow runs<pluginRoot>/scripts/stage-assets.mjswhen present;plugins/monacouses it to copymonaco-editor/min/vsintodist/vs. Running from source there is nodist/, and the server falls back to resolvingmonaco-editorfromnode_modules.min/vs). Worth an explicit decision. Roughly 14 MB of it is the TypeScript language service and its worker, which this plugin deliberately disables — Monaco's checker can only see the open file, so every import reads as unresolved and the diagnostics are simply wrong. A curated subset could cut it to ~7-8 MB, but the AMD loader fetches lazily and omitting a file it later requests is a runtime 404, so I did not want to guess at the boundary without testing each claimed language. Happy to do that work if the size matters.Also updated:
smoke-tarball.mjs, and the two "declare metadata for every builtin" tables in the server tests (both failed before I added the entries, which is them working as intended).How you verified
New unit tests cover the tree logic that is easy to get subtly wrong: nesting flat paths, synthesising directories a truncated listing omitted, case-insensitive sorting, and filtering (which must expand every ancestor of a match, or the match stays hidden behind a collapsed row).
Ran the real packaging path (
tsx apps/server/scripts/copy-builtin-plugins.ts) and confirmed the shipped builtin containsdist/vs/loader.js,dist/vs/editor/editor.main.js,dist/vs/editor/editor.main.css,dist/server.js, anddist/app.js— 25 MB total.Not yet verified live as a builtin. Everything above is build-and-test; the editor has been exercised extensively as a path-installed plugin but not once loaded through the builtin registry. Two paths in particular are new in this port and untested: project-backed workspace sources (no environment, resolved through the project's
sources[]) and theexperimental_hostIdfieldmainadded toPluginFileOpenerSource— my schema was.strict()and would have rejected those files outright before this change.Known gaps
Documented in the plugin README, with upstream issues where the fix is not ours:
node_modules(Path listing hides every dotfile and node_modules unconditionally, so file search cannot find .github/workflows/ci.yml #2093), and is read-only — no rename/create/delete.Fixes #