feat: add trusted local plugin system - #8014
Conversation
Co-authored-by: Utkarsh Patil <73941998+UtkarshUsername@users.noreply.github.com>
Co-authored-by: Utkarsh Patil <73941998+UtkarshUsername@users.noreply.github.com>
Co-authored-by: Utkarsh Patil <73941998+UtkarshUsername@users.noreply.github.com>
Co-authored-by: Utkarsh Patil <73941998+UtkarshUsername@users.noreply.github.com>
Co-authored-by: Utkarsh Patil <73941998+UtkarshUsername@users.noreply.github.com>
Co-authored-by: Utkarsh Patil <73941998+UtkarshUsername@users.noreply.github.com>
Co-authored-by: Utkarsh Patil <73941998+UtkarshUsername@users.noreply.github.com>
Co-authored-by: Utkarsh Patil <73941998+UtkarshUsername@users.noreply.github.com>
Co-authored-by: Utkarsh Patil <73941998+UtkarshUsername@users.noreply.github.com>
Co-authored-by: Utkarsh Patil <73941998+UtkarshUsername@users.noreply.github.com>
Co-authored-by: Utkarsh Patil <73941998+UtkarshUsername@users.noreply.github.com>
Co-authored-by: Utkarsh Patil <73941998+UtkarshUsername@users.noreply.github.com>
…t-ui # Conflicts: # apps/server/src/auth/RpcAuthorization.test.ts # apps/server/src/ws.ts
|
Important Review skippedAuto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Repository UI Review profile: CHILL Plan: Pro Plus Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
A failed enable, disable, or reload still changes the server-side snapshot (package errors are set or cleared), but the settings panel only refreshed on success, leaving stale rows until a manual refresh. Refresh after any completed non-interrupted action and cover both outcomes with tests.
There was a problem hiding this comment.
One finding: the worker dispose path re-wraps an already structured PluginWorkerError and drops the underlying cause. Everything else previously raised (tagged manifest/contribution errors, catchTags for known tags, Effect-typed dispose, exported make, bounded network detail, interruption-preserving startup retry) looks addressed.
Posted via Macroscope — Effect Service Conventions
Co-authored-by: Utkarsh Patil <73941998+UtkarshUsername@users.noreply.github.com>
There was a problem hiding this comment.
Two findings in apps/server/src/plugins/PluginWorkerSupervisor.ts, both about the crash-reporting path losing/leaking error context. Everything flagged in earlier runs (worker dispose typing, catchTags for the invocation timeout, dispose pass-through, distinct package manifest error classes, catalog catchTags, exported broker make, URL-free network detail, startup retry with interruption preserved) looks addressed.
Posted via Macroscope — Effect Service Conventions
Co-authored-by: Utkarsh Patil <73941998+UtkarshUsername@users.noreply.github.com>
Co-authored-by: Utkarsh Patil <73941998+UtkarshUsername@users.noreply.github.com>
There was a problem hiding this comment.
Reviewed the declarative plugin UI kit added in cd7c496 (previous findings on the worker supervisor are already addressed or flagged). Four findings, all in the new server-side error modelling: a free-form detail field is being used both as the failure discriminator and as the wrapper message source.
Posted via Macroscope — Effect Service Conventions
There was a problem hiding this comment.
Three consistency findings in the new web plugin UI, all in apps/web/src/components/plugins/PluginUi.tsx. The rest of the changed web surface (settings panel, command palette, routes, settings nav) reuses the shared primitives correctly, and the permission/capability chips flagged in earlier runs now truncate inside Tooltip.
Posted via Macroscope — UI Consistency
Co-authored-by: Utkarsh Patil <73941998+UtkarshUsername@users.noreply.github.com>
There was a problem hiding this comment.
Reviewed the web UI changes in this PR (plugin composer/view rendering, plugin page route, sidebar nav, plugin settings). The three findings from the previous run are addressed: the tone tokens now use the -foreground roles, the sidebar entries match the icon-only utility-row contract with a Tooltip, and the setting controls route through Select/Input. Three new findings below, all in newly added markup.
Posted via Macroscope — UI Consistency
Co-authored-by: Utkarsh Patil <73941998+UtkarshUsername@users.noreply.github.com>
There was a problem hiding this comment.
Two new findings in the web plugin UI; the three items from earlier runs (composer placement in ChatView.tsx, unbounded status chips in PluginComposerContributions, the hand-rolled page frame in plugins.$pluginId.$viewId.tsx) are still present.
Posted via Macroscope — UI Consistency
Co-authored-by: Utkarsh Patil <73941998+UtkarshUsername@users.noreply.github.com>
There was a problem hiding this comment.
Reviewed the changed web UI surfaces (PluginUi.tsx, PluginsSettings.tsx, CommandPalette.tsx, SidebarChrome.tsx, plugins.$pluginId.$viewId.tsx). The earlier rounds' primitive/token/scroller findings look addressed. Three remaining items below; previously reported items that are unchanged are not repeated.
Posted via Macroscope — UI Consistency
Co-authored-by: Utkarsh Patil <73941998+UtkarshUsername@users.noreply.github.com>
There was a problem hiding this comment.
Two consistency findings in the newly moved composer row and the sidebar plugin entries. Everything else in this revision looks aligned with the shared contracts: the Select/Input primitives, SidebarMenuButton isActive, the -foreground tone tokens, the StatusBadge truncation + Tooltip, and the ScrollArea scrollFade scrollbarGutter props on the plugin page (which now apply the mask and gutter to the viewport the primitive owns rather than to the root).
Posted via Macroscope — UI Consistency
Co-authored-by: Utkarsh Patil <73941998+UtkarshUsername@users.noreply.github.com>
There was a problem hiding this comment.
One finding: the composer row now opts into the attached-drawer seam contract, but ChatView's externalComposerDrawerAttached flag does not account for it, so the composer glass shell keeps its continuous backdrop and closed top outline when plugin contributions are the only drawer above it.
The rest of this revision looks good — the sidebar item now reuses the shared SidebarUtilityItem primitive, the card treatment is a single local component consumed by both call sites, and the command toast matches CommandPalette's title/description split.
Posted via Macroscope — UI Consistency
Co-authored-by: Utkarsh Patil <73941998+UtkarshUsername@users.noreply.github.com>
There was a problem hiding this comment.
Reviewed the web UI surfaces in this PR against the shared component system. The composer seam issue raised on the previous commit is resolved: usePluginComposerContributionState().isAttached now feeds externalComposerDrawerAttached, so the plugin drawer row toggles chat-composer-glass-shell-attached / ChatComposer's externalDrawerAttached exactly like ComposerBannerStack and ThreadSyncStatusPill.
Two remaining consistency findings in apps/web/src/components/plugins/PluginUi.tsx, both commented inline.
Posted via Macroscope — UI Consistency
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes using high effort and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit 68c92fb. Configure here.
Co-authored-by: Utkarsh Patil <73941998+UtkarshUsername@users.noreply.github.com>

What Changed
architecture
orchestration:read; invocation and lifecycle mutations requireorchestration:operatetrusted local scope
Plugins run in supervised subprocesses under the same OS user as the environment server. This PR intentionally does not add a marketplace, registry, signing, a hostile-code OS sandbox, arbitrary renderer code, or unrestricted host access.
user journey
userdata/plugins/<plugin-id>/directoryUI Changes
Light
Dark
Demo Video
I asked an agent to create a plugin for me, and it created a plugin which gives two commands to show time and server info.
plugin-demo.mp4
validation
24.13.1, pnpm11.10.0mainmainmainmaingit diff --checkpassedChecklist
Note
High Risk
Plugins can run processes, fetch network, and access namespaced secrets/files after persisted grants, and new RPCs mutate orchestration state. Isolation is subprocess-based, not a full sandbox.
Overview
Adds a trusted local plugin system so environment packages under
userdata/plugins/can register commands and declarative UI without rebuilding T3.The server discovers manifests, persists
enabledPluginIds, and runs activation/commands in supervised child processes (PluginWorkerRuntime.mjs) over a strict JSONL protocol.PluginHostCapabilityBrokerrequires explicit grants before namespaced settings/state/cache, secrets, files, origin-locked HTTPS, and exact process names. Catalog publication is generation-bound with rollback on failed reload; new permissions need disable/re-enable.Clients get RPC list/invoke/subscribe plus package enable/disable/reload. Web/desktop expose palette commands, host-rendered views/cards/actions, notifications, and a Plugins settings page. Mobile shows home cards/status and native alerts. Read vs operate scopes are wired for discovery vs invocation/lifecycle.
Reviewed by Cursor Bugbot for commit 5501410. Bugbot is set up for automated code reviews on this repo. Configure here.
Note
Add trusted local plugin system
@t3tools/plugin-runtimepackage with core contracts, manifest schemas, planner, and runtime for composing and activating plugins.PluginWorkerSupervisor,PluginPackageManager,PluginCommandCatalog,PluginHostCapabilityBroker) handle plugin lifecycle, command/UI registration, and sandboxed host APIs including files, network, process execution, and settings.ServerSettingsschema addsenabledPluginIdsfield with a default empty array.Macroscope summarized 5501410.
request provenance
additional request provenance
additional request provenance