import { ReactNode } from 'react'; import { PluginCapabilities, PluginErrorPayload, PluginEventEmitPayload, PluginResizeRequestPayload, PluginSetBadgePayload, PluginSetTitlePayload } from './protocol/index.js'; export interface PluginIframeRpcContext { capabilities: PluginCapabilities; /** Reflects the iframe iframe back through for downstream handlers. */ iframe: HTMLIFrameElement; } export type PluginIframeRpcHandler = (method: string, args: unknown, ctx: PluginIframeRpcContext) => Promise; export interface PluginIframeProps { /** Absolute or relative URL the iframe loads. */ src: string; /** Origin the iframe is allowed to postMessage to / from. */ origin: string; /** Mount point id passed to the plugin in `host:init`. */ mountPoint: string; /** Context payload passed to the plugin in `host:init` (e.g. `{ vibeId }`). */ context: Record; /** Agent id whose tunnel serves the iframe. */ agentId: string; /** Profile name (CLI segment on the agent). */ profile: string; /** Tunnel base URL the plugin should call for REST. */ tunnelUrl: string; /** Iframe token scoped to the plugin's `capabilities.restPaths`. */ iframeToken: string; /** Capabilities the plugin declared in its manifest. Used to derive sandbox. */ capabilities: PluginCapabilities; /** Theme broadcast to the plugin. Updates re-flow into the iframe via host:theme-change. */ theme: { colorMode: 'light' | 'dark'; tokens: Record; }; /** Locale broadcast to the plugin. */ locale: string; /** Feature-flag snapshot broadcast to the plugin. */ featureFlags: Record; /** Host version surfaced via `host:init`. */ hostVersion: string; /** RPC handler the host wires up. Method allow-list is enforced separately. */ onRpcRequest: PluginIframeRpcHandler; /** Called when the plugin emits an event UP to the host EventBus. */ onPluginEvent?: (payload: PluginEventEmitPayload) => void; /** Called when the plugin asks to update its tab/widget badge. */ onBadgeRequest?: (value: PluginSetBadgePayload['value']) => void; /** Called when the plugin asks to update its tab/widget title. */ onTitleRequest?: (value: PluginSetTitlePayload['value']) => void; /** Called when the plugin asks the host to resize the iframe. Host decides. */ onResizeRequest?: (opts: PluginResizeRequestPayload) => void; /** Called when the plugin self-reports a runtime error. */ onPluginError?: (payload: PluginErrorPayload) => void; /** Rendered while the iframe is loading / before `plugin:ready`. */ loadingFallback?: ReactNode; /** Rendered when the handshake times out. Receives the error message. */ errorFallback?: (error: { message: string; }) => ReactNode; /** Override the 10s ready timeout. */ readyTimeoutMs?: number; /** Forwarded `