Skip to content

fix(agent-bridge): strip real implementation from production Metro bundles - #412

Open
V3RON wants to merge 2 commits into
mainfrom
fix/agent-bridge-production-shim
Open

fix(agent-bridge): strip real implementation from production Metro bundles#412
V3RON wants to merge 2 commits into
mainfrom
fix/agent-bridge-production-shim

Conversation

@V3RON

@V3RON V3RON commented Aug 17, 2026

Copy link
Copy Markdown
Contributor

Summary

@rozenite/agent-bridge required @rozenite/plugin-bridge unconditionally at its module top level. Unlike every other devtools plugin, it had no react-native.ts entry point gating its real implementation behind NODE_ENV !== 'production', so its RPC/protocol code (error classes, ROZENITE_RPC_MESSAGE_TYPE, etc.) always ended up in production/release Metro bundles for any app using an in-app agent tool.

This applies the same shim pattern used by the other 14 plugins:

  • Added react-native.ts at the package root, exporting useRozenitePluginAgentTool/useRozeniteInAppAgentTool as let bindings, require()d from ./src/react-native/useRozeniteAgentTool only when NODE_ENV !== 'production', and no-ops otherwise.
  • Moved the real hook implementation to src/react-native/useRozeniteAgentTool.ts.
  • Switched the package to build via @rozenite/vite-plugin's react-native target (requirePlugin + rozeniteReactNativePlugin), which splits the gated require() into its own chunk so Metro's minifier can drop it — and its @rozenite/plugin-bridge dependency — entirely from release builds. Since agent-bridge has no devtools panel, its vite.config.ts only builds that one target; a separate vitest.config.ts keeps tests off the panel-oriented plugin branches.
  • Updated package.json main/module/types/exports to point at dist/react-native/index.*, matching the other plugins, so consumers get correct type hints for useRozenitePluginAgentTool/useRozeniteInAppAgentTool resolved straight from the published .d.ts (verified end-to-end below).
  • agent-bridge is no longer part of the root/playground TS project-reference graph (it now builds via vite instead of tsc emit, like the other plugins), and 6 sibling plugins drop their now-unnecessary TS project reference to it — they already resolve its types via normal package exports.

Follow-up cleanup: several plugin tsconfig.json files hand-mapped @rozenite/agent-shared (and, in a few cases, plugin-bridge/agent-bridge/ui) to sibling source files via "paths", bypassing the real pnpm workspace symlink and each package's own conditional exports map. Two of them (feature-flags-plugin, storage-plugin) had gone stale, still pointing at agent-bridge/src/index.ts, which no longer exists now that agent-bridge builds through react-native.ts. Replaced all of these with "customConditions": ["development"], so resolution goes through the normal node_modules symlink + package.json exports conditions instead (falling through to each package's "development" condition where it declares one, e.g. agent-shared, and to "types"/dist otherwise).

Test plan

  • pnpm build:all — all 32 packages build successfully
  • pnpm typecheck:all — all 63 typecheck tasks pass
  • turbo run test — all 54 test tasks pass (agent-bridge's own 6 tests included)
  • Bundled apps/playground (installs all 14 plugins + agent-bridge) via expo export --platform ios (production/release mode) and grepped the output bundle:
    • All @rozenite/*-plugin package identifiers: 0 occurrences (unchanged, already correct)
    • plugin-bridge RPC/error identifiers (RozeniteProtocolError, MissingRozeniteForWebError, RozeniteHandlerError, ROZENITE_RPC_MESSAGE_TYPE): now 0 occurrences (previously present via agent-bridge's unconditional import)
  • Verified agent-bridge's published types resolve and type-check correctly for consumers: from apps/playground, confirmed require.resolve('@rozenite/agent-bridge/package.json') and the types/exports map resolve through the real workspace symlink to dist/react-native/index.d.ts, and that a deliberate type error (a useRozeniteInAppAgentTool() call missing the required tool field) is correctly caught by tsc (TS2345: Property 'tool' is missing...), proving real (non-any) type hints flow through to consumers.

V3RON added 2 commits August 17, 2026 08:35
…ndles

@rozenite/agent-bridge required @rozenite/plugin-bridge unconditionally,
so its RPC protocol code (error classes, ROZENITE_RPC_MESSAGE_TYPE, etc.)
always ended up in production/release bundles, unlike every other
devtools plugin. All other plugins gate their real implementation behind
a react-native.ts entry point that only require()s it when
NODE_ENV !== 'production', letting Metro's minifier dead-code-eliminate
the require and drop the whole real-implementation chunk (and its
plugin-bridge dependency) from release builds.

This applies the same react-native.ts + isDev-gated require() pattern to
agent-bridge, using @rozenite/vite-plugin's react-native build target to
produce the same NODE_ENV-gated require()/chunk-split output as the other
plugins. Since agent-bridge has no devtools panel, its own vite config
only builds that one target, with a separate vitest.config.ts so tests
don't go through the panel-oriented Vite plugin branches.

agent-bridge is no longer part of the root/playground TS project
reference graph (it now builds through vite instead of tsc emit, like
the other plugins) and drops its own project reference to
@rozenite/agent-bridge (already resolved via normal package exports).

Verified by bundling apps/playground (which installs all plugins,
including agent-bridge) via `expo export --platform ios`: all
@rozenite/*-plugin identifiers and plugin-bridge's RPC/error identifiers
(RozeniteProtocolError, MissingRozeniteForWebError, RozeniteHandlerError,
ROZENITE_RPC_MESSAGE_TYPE) are now absent from the release bundle.
Several plugin tsconfig.json files hand-mapped `@rozenite/agent-shared`
(and, in a few cases, plugin-bridge/agent-bridge/ui) to sibling source
files via "paths". This bypasses the real pnpm workspace symlink and each
package's own conditional `exports` map, and had gone stale: two of them
(feature-flags-plugin, storage-plugin) still pointed at
`agent-bridge/src/index.ts`, which no longer exists now that agent-bridge
builds through react-native.ts instead of a plain src/index.ts entry.

Replaced these with `"customConditions": ["development"]`, so resolution
goes through the normal node_modules symlink + package.json exports
conditions (falling through to the "development" condition where a
package declares one, e.g. agent-shared, and to "types"/dist otherwise) —
the same mechanism already used by packages extending tsconfig.base.json.

Verified with a fresh `pnpm build:all`, `pnpm typecheck:all` (63/63), and
`turbo run test` (54/54).
@vercel

vercel Bot commented Aug 17, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
Project Deployment Actions Updated (UTC)
rozenite Skipped Skipped Aug 17, 2026 6:45am

Request Review

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