@ethisyscore/extension-runtime 1.9.2 → 1.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -526,12 +526,216 @@ function abortError() {
526
526
  return e;
527
527
  }
528
528
 
529
+ // src/host/worker/bridge-envelopes.ts
530
+ var BRIDGE_PUSH_THEME = "ethisys:bridge:theme";
531
+ var BRIDGE_PUSH_LOCALE = "ethisys:bridge:locale";
532
+ var BRIDGE_PUSH_DENSITY = "ethisys:bridge:density";
533
+ var BRIDGE_PUSH_A11Y = "ethisys:bridge:a11y";
534
+ var BRIDGE_NAV_PUSH = "ethisys:bridge:nav";
535
+ var BRIDGE_CHROME_REQUEST = "ethisys:bridge:chrome:request";
536
+ var BRIDGE_CHROME_RESPONSE = "ethisys:bridge:chrome:response";
537
+ var BRIDGE_SESSION_TOKEN_PUSH = "ethisys:bridge:token";
538
+ var BRIDGE_A11Y_ANNOUNCE = "ethisys:bridge:a11y:announce";
539
+ function isObj(v) {
540
+ return v !== null && typeof v === "object";
541
+ }
542
+ function isBridgePushTheme(v) {
543
+ return isObj(v) && v["type"] === BRIDGE_PUSH_THEME && typeof v["mode"] === "string";
544
+ }
545
+ function isBridgePushLocale(v) {
546
+ return isObj(v) && v["type"] === BRIDGE_PUSH_LOCALE && typeof v["locale"] === "string";
547
+ }
548
+ function isBridgePushDensity(v) {
549
+ return isObj(v) && v["type"] === BRIDGE_PUSH_DENSITY && typeof v["density"] === "string";
550
+ }
551
+ function isBridgePushA11y(v) {
552
+ return isObj(v) && v["type"] === BRIDGE_PUSH_A11Y && typeof v["reducedMotion"] === "boolean" && typeof v["highContrast"] === "boolean";
553
+ }
554
+ function isBridgeNavPush(v) {
555
+ return isObj(v) && v["type"] === BRIDGE_NAV_PUSH && typeof v["path"] === "string";
556
+ }
557
+ function isBridgeChromeResponse(v) {
558
+ return isObj(v) && v["type"] === BRIDGE_CHROME_RESPONSE && typeof v["id"] === "string";
559
+ }
560
+ function isBridgeSessionTokenPush(v) {
561
+ return isObj(v) && v["type"] === BRIDGE_SESSION_TOKEN_PUSH && typeof v["token"] === "string" && typeof v["expiresAtMs"] === "number";
562
+ }
563
+
564
+ // src/plugin/bridge-client.ts
565
+ var _requestCounter = 0;
566
+ function nextId2() {
567
+ _requestCounter += 1;
568
+ return `br-${_requestCounter}`;
569
+ }
570
+ function createPortBridgeClient(port) {
571
+ let themeCb;
572
+ let localeCb;
573
+ let densityCb;
574
+ let a11yCb;
575
+ let navCb;
576
+ let tokenCb;
577
+ const pending = /* @__PURE__ */ new Map();
578
+ port.onmessage = (ev) => {
579
+ const msg = ev.data;
580
+ if (isBridgePushTheme(msg)) {
581
+ themeCb?.({ mode: msg.mode, tokens: msg.tokens });
582
+ return;
583
+ }
584
+ if (isBridgePushLocale(msg)) {
585
+ localeCb?.({ locale: msg.locale, dir: msg.dir });
586
+ return;
587
+ }
588
+ if (isBridgePushDensity(msg)) {
589
+ densityCb?.({ density: msg.density });
590
+ return;
591
+ }
592
+ if (isBridgePushA11y(msg)) {
593
+ a11yCb?.({ reducedMotion: msg.reducedMotion, highContrast: msg.highContrast });
594
+ return;
595
+ }
596
+ if (isBridgeNavPush(msg)) {
597
+ navCb?.({ path: msg.path, historyLength: msg.historyLength });
598
+ return;
599
+ }
600
+ if (isBridgeSessionTokenPush(msg)) {
601
+ tokenCb?.({ token: msg.token, expiresAtMs: msg.expiresAtMs });
602
+ return;
603
+ }
604
+ if (isBridgeChromeResponse(msg)) {
605
+ const p = pending.get(msg.id);
606
+ if (p === void 0) {
607
+ return;
608
+ }
609
+ pending.delete(msg.id);
610
+ if (msg.ok) {
611
+ p.resolve(msg.result ?? null);
612
+ } else {
613
+ p.reject(new Error(typeof msg.error === "string" ? msg.error : "Chrome request failed"));
614
+ }
615
+ }
616
+ };
617
+ return {
618
+ onTheme(cb) {
619
+ themeCb = cb;
620
+ },
621
+ onLocale(cb) {
622
+ localeCb = cb;
623
+ },
624
+ onDensity(cb) {
625
+ densityCb = cb;
626
+ },
627
+ onA11y(cb) {
628
+ a11yCb = cb;
629
+ },
630
+ onNav(cb) {
631
+ navCb = cb;
632
+ },
633
+ onSessionToken(cb) {
634
+ tokenCb = cb;
635
+ },
636
+ requestChrome(action, payload) {
637
+ const id = nextId2();
638
+ return new Promise((resolve, reject) => {
639
+ pending.set(id, { resolve, reject });
640
+ port.postMessage({ type: BRIDGE_CHROME_REQUEST, id, action, payload });
641
+ });
642
+ },
643
+ announceA11y(message, politeness) {
644
+ port.postMessage({ type: BRIDGE_A11Y_ANNOUNCE, message, politeness });
645
+ }
646
+ };
647
+ }
648
+ var BridgeClientContext = react.createContext(null);
649
+ function useBridgeClient() {
650
+ const client = react.useContext(BridgeClientContext);
651
+ if (client === null) {
652
+ throw new Error(
653
+ "No PortBridgeClient available. Wrap your plugin in <BridgeClientProvider> or ensure the host mount wires a BridgeClientContext.Provider."
654
+ );
655
+ }
656
+ return client;
657
+ }
658
+ function useBridgeTheme() {
659
+ const client = useBridgeClient();
660
+ const [theme, setTheme] = react.useState(void 0);
661
+ react.useEffect(() => {
662
+ client.onTheme((payload) => setTheme(payload));
663
+ }, [client]);
664
+ return theme;
665
+ }
666
+ function useBridgeLocale() {
667
+ const client = useBridgeClient();
668
+ const [locale, setLocale] = react.useState(void 0);
669
+ react.useEffect(() => {
670
+ client.onLocale((payload) => setLocale(payload));
671
+ }, [client]);
672
+ return locale;
673
+ }
674
+ var SESSION_TOKEN_URI = "ethisys:session-token";
675
+ var REFRESH_SKEW_MS = 3e4;
676
+ function useFrontendSessionToken(transport) {
677
+ const [token, setToken] = react.useState(null);
678
+ const [isLoading, setIsLoading] = react.useState(true);
679
+ const [error, setError] = react.useState(null);
680
+ const refreshTimerRef = react.useRef(null);
681
+ const mountedRef = react.useRef(true);
682
+ const fetch = react.useCallback(async () => {
683
+ if (refreshTimerRef.current !== null) {
684
+ clearTimeout(refreshTimerRef.current);
685
+ refreshTimerRef.current = null;
686
+ }
687
+ try {
688
+ const { data } = await transport.getResource(
689
+ SESSION_TOKEN_URI
690
+ );
691
+ if (!mountedRef.current) {
692
+ return;
693
+ }
694
+ setToken(data.accessToken);
695
+ setError(null);
696
+ setIsLoading(false);
697
+ const expiresAtMs = Date.parse(data.expiresAtUtc);
698
+ const refreshIn = expiresAtMs - Date.now() - REFRESH_SKEW_MS;
699
+ if (refreshIn > 0) {
700
+ refreshTimerRef.current = setTimeout(() => {
701
+ void fetch();
702
+ }, refreshIn);
703
+ }
704
+ } catch (err) {
705
+ if (!mountedRef.current) {
706
+ return;
707
+ }
708
+ setError(err instanceof Error ? err : new Error(String(err)));
709
+ setToken(null);
710
+ setIsLoading(false);
711
+ }
712
+ }, [transport]);
713
+ react.useEffect(() => {
714
+ mountedRef.current = true;
715
+ setIsLoading(true);
716
+ void fetch();
717
+ return () => {
718
+ mountedRef.current = false;
719
+ if (refreshTimerRef.current !== null) {
720
+ clearTimeout(refreshTimerRef.current);
721
+ }
722
+ };
723
+ }, [fetch]);
724
+ return { token, isLoading, error };
725
+ }
726
+
727
+ exports.BridgeClientContext = BridgeClientContext;
529
728
  exports.ExtensionRuntimeProvider = ExtensionRuntimeProvider;
729
+ exports.createPortBridgeClient = createPortBridgeClient;
530
730
  exports.createPortMcpTransport = createPortMcpTransport;
531
731
  exports.createRemoteRoot = createRemoteRoot;
532
732
  exports.defineDeclarativePlugin = defineDeclarativePlugin;
533
733
  exports.defineEthisysPlugin = defineEthisysPlugin;
534
734
  exports.unwrapItems = unwrapItems;
735
+ exports.useBridgeClient = useBridgeClient;
736
+ exports.useBridgeLocale = useBridgeLocale;
737
+ exports.useBridgeTheme = useBridgeTheme;
738
+ exports.useFrontendSessionToken = useFrontendSessionToken;
535
739
  exports.useMcpQuery = useMcpQuery;
536
740
  exports.useMcpResource = useMcpResource;
537
741
  exports.useMcpTool = useMcpTool;
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/plugin/ExtensionRuntimeProvider.tsx","../../src/plugin/useMcpResource.ts","../../src/plugin/useMcpTool.ts","../../src/plugin/useMcpQuery.ts","../../src/plugin/define.ts","../../src/plugin/reconciler.ts","../../src/plugin/createRemoteRoot.ts","../../src/plugin/createPortMcpTransport.ts"],"names":["createContext","useMemo","jsx","useContext","useState","useRef","useEffect","useCallback","NODE_TYPE_TEXT","NODE_TYPE_ELEMENT","ReactReconciler","DefaultEventPriority","MUTATION_TYPE_REMOVE_CHILD","MUTATION_TYPE_INSERT_CHILD","MUTATION_TYPE_UPDATE_PROPERTY","MUTATION_TYPE_UPDATE_TEXT","ROOT_ID","BatchingRemoteConnection","LegacyRoot"],"mappings":"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","file":"index.cjs","sourcesContent":["import { createContext, useContext, useMemo, type ReactNode } from \"react\";\nimport type { McpTransport } from \"./transport\";\n\n/**\n * React context carrying the {@link McpTransport} the plugin should use to\n * reach the host. `null` is the explicit \"not provided\" sentinel so the hooks\n * can disambiguate from a transport that was provided but is incidentally\n * falsy in some other dimension.\n */\nconst ExtensionRuntimeContext = createContext<McpTransport | null>(null);\n\nexport interface ExtensionRuntimeProviderProps\n{\n transport: McpTransport;\n children?: ReactNode;\n}\n\n/**\n * Wrap a plugin's React tree so descendant {@link useMcpResource} and\n * {@link useMcpTool} calls resolve a default transport without having to\n * thread it through every component.\n *\n * Hooks still accept a per-call `transport` override, which takes precedence\n * over the context value — useful for tests and for plugins that want to\n * shard work across multiple hosts.\n */\nexport function ExtensionRuntimeProvider({ transport, children }: ExtensionRuntimeProviderProps): ReactNode\n{\n // Memoise so swapping `children` doesn't churn the context identity.\n const value = useMemo(() => transport, [transport]);\n return (\n <ExtensionRuntimeContext.Provider value={value}>\n {children}\n </ExtensionRuntimeContext.Provider>\n );\n}\n\n/**\n * Internal helper used by the hooks. Returns the explicit override when\n * supplied, otherwise falls back to the context. Throws a deterministic\n * error if neither is available so misconfiguration fails loudly at the\n * first render rather than producing silent no-ops.\n */\nexport function useExtensionRuntimeTransport(override?: McpTransport): McpTransport\n{\n const fromContext = useContext(ExtensionRuntimeContext);\n const resolved = override ?? fromContext;\n if (!resolved)\n {\n throw new Error(\n \"No McpTransport available. Wrap your plugin in <ExtensionRuntimeProvider transport={...}> \"\n + \"or pass `transport` directly to the hook.\",\n );\n }\n return resolved;\n}\n","import { useCallback, useEffect, useRef, useState } from \"react\";\nimport { useExtensionRuntimeTransport } from \"./ExtensionRuntimeProvider\";\nimport type { McpTransport } from \"./transport\";\n\nexport interface UseMcpResourceOptions\n{\n /**\n * Override the transport resolved from {@link ExtensionRuntimeProvider}.\n * Primarily intended for tests and advanced multi-host scenarios.\n */\n transport?: McpTransport;\n}\n\nexport interface UseMcpResourceResult<T>\n{\n data: T | undefined;\n error: Error | undefined;\n loading: boolean;\n /** Re-run the fetch against the current URI. Stable across renders. */\n refetch: () => void;\n}\n\n/**\n * Subscribe to an MCP resource by URI.\n *\n * The hook fetches via the resolved {@link McpTransport} on mount and whenever\n * the URI changes. Each fetch is cancellable: when the component unmounts or\n * the URI changes, the in-flight call is aborted via an {@link AbortController}\n * so stale responses cannot overwrite later state.\n *\n * `refetch` re-runs the fetch against the latest URI. The returned callback is\n * stable across renders so it is safe to include in `useEffect` dependency\n * arrays.\n */\nexport function useMcpResource<T>(\n uri: string,\n opts?: UseMcpResourceOptions,\n): UseMcpResourceResult<T>\n{\n const transport = useExtensionRuntimeTransport(opts?.transport);\n\n const [data, setData] = useState<T | undefined>(undefined);\n const [error, setError] = useState<Error | undefined>(undefined);\n const [loading, setLoading] = useState<boolean>(true);\n\n // Bump this counter to force a re-fetch from `refetch()`.\n const [refetchTick, setRefetchTick] = useState(0);\n\n // Track the active controller so `refetch` and unmount can abort it.\n const controllerRef = useRef<AbortController | null>(null);\n\n useEffect(() =>\n {\n const controller = new AbortController();\n controllerRef.current?.abort();\n controllerRef.current = controller;\n\n let cancelled = false;\n setLoading(true);\n setError(undefined);\n\n transport\n .getResource<T>(uri, controller.signal)\n .then((result) =>\n {\n if (cancelled || controller.signal.aborted)\n {\n return;\n }\n setData(result.data);\n setLoading(false);\n })\n .catch((err: unknown) =>\n {\n if (cancelled || controller.signal.aborted)\n {\n return;\n }\n setError(err instanceof Error ? err : new Error(String(err)));\n setLoading(false);\n });\n\n return () =>\n {\n cancelled = true;\n controller.abort();\n };\n }, [uri, transport, refetchTick]);\n\n const refetch = useCallback(() =>\n {\n setRefetchTick((tick) => tick + 1);\n }, []);\n\n return { data, error, loading, refetch };\n}\n","import { useCallback, useEffect, useRef, useState } from \"react\";\nimport { useExtensionRuntimeTransport } from \"./ExtensionRuntimeProvider\";\nimport type { McpTransport } from \"./transport\";\n\nexport interface UseMcpToolOptions\n{\n /**\n * Override the transport resolved from {@link ExtensionRuntimeProvider}.\n * Primarily intended for tests and advanced multi-host scenarios.\n */\n transport?: McpTransport;\n}\n\nexport interface UseMcpToolResult<TReq, TRes>\n{\n /**\n * Invoke the tool. Each call gets a fresh {@link AbortController} that is\n * aborted on unmount so unresolved promises cannot keep state alive after\n * the component is gone.\n */\n invoke: (req: TReq) => Promise<TRes>;\n loading: boolean;\n error: Error | undefined;\n}\n\n/**\n * Hook returning a callback that invokes an MCP tool by name through the\n * resolved {@link McpTransport}.\n *\n * `loading` and `error` track the most recent in-flight invocation. Callers\n * may also `await` the returned promise directly — failures are both rejected\n * to the caller AND surfaced via `error` so component-level UI can react.\n *\n * `invoke` is a stable reference across renders for the same `toolName` and\n * transport, making it safe to use inside `useEffect`/`useCallback` deps.\n */\nexport function useMcpTool<TReq, TRes>(\n toolName: string,\n opts?: UseMcpToolOptions,\n): UseMcpToolResult<TReq, TRes>\n{\n const transport = useExtensionRuntimeTransport(opts?.transport);\n\n const [loading, setLoading] = useState(false);\n const [error, setError] = useState<Error | undefined>(undefined);\n\n // Track the latest controller so unmount can abort an in-flight call.\n const controllerRef = useRef<AbortController | null>(null);\n const mountedRef = useRef(true);\n\n useEffect(() =>\n {\n mountedRef.current = true;\n return () =>\n {\n mountedRef.current = false;\n controllerRef.current?.abort();\n };\n }, []);\n\n const invoke = useCallback(\n async (req: TReq): Promise<TRes> =>\n {\n const controller = new AbortController();\n controllerRef.current?.abort();\n controllerRef.current = controller;\n\n setLoading(true);\n setError(undefined);\n\n try\n {\n const result = await transport.invokeTool<TReq, TRes>(\n toolName,\n req,\n controller.signal,\n );\n if (mountedRef.current && !controller.signal.aborted)\n {\n setLoading(false);\n }\n return result;\n }\n catch (err)\n {\n const wrapped = err instanceof Error ? err : new Error(String(err));\n if (mountedRef.current && !controller.signal.aborted)\n {\n setError(wrapped);\n setLoading(false);\n }\n throw wrapped;\n }\n },\n [transport, toolName],\n );\n\n return { invoke, loading, error };\n}\n","import { useEffect, useState } from \"react\";\nimport { useMcpTool } from \"./useMcpTool\";\n\n/**\n * Result shape returned by {@link useMcpQuery}. Mirrors the host-app\n * `react-query`-style envelope so consumers can render loading / error /\n * data states declaratively. `refetch` is stable across renders.\n */\nexport interface UseMcpQueryResult<TRes>\n{\n data: TRes | undefined;\n loading: boolean;\n error: Error | undefined;\n /** Re-run the fetch against the current args. Stable across renders. */\n refetch: () => void;\n}\n\n/**\n * Options for {@link useMcpQuery}.\n */\nexport interface UseMcpQueryOptions\n{\n /**\n * Gate the fetch on a guard. When false, the hook returns idle state and\n * never invokes — important because hooks must be called unconditionally\n * at the top of the component, so an `enabled` flag is the standard way\n * to express \"fetch only when a selection is present\" without violating\n * the rules of hooks. Defaults to `true`.\n */\n enabled?: boolean;\n}\n\n/**\n * Auto-fetch wrapper over the imperative {@link useMcpTool}. Fires the tool\n * call on mount AND whenever the serialised `args` change. Use for\n * read-shaped MCP tool calls that back a component's render data; for\n * mutations, call {@link useMcpTool} directly and trigger\n * `invoke(...)` from event handlers.\n *\n * Why this lives alongside {@link useMcpTool}: many plugin MCP tools are\n * effectively queries (`list-tasks`, `get-pending-approvals`, …) — paginated\n * lookups that change with filter inputs. The base hook's imperative\n * `invoke` signature is correct for mutations but ergonomically wrong for\n * reads, where every consumer ends up writing the same `useEffect` +\n * AbortController + cancellation-on-unmount boilerplate. This hook absorbs\n * that boilerplate once.\n *\n * @template TArgs The request shape sent to the tool.\n * @template TRes The response shape the tool returns.\n */\nexport function useMcpQuery<TArgs, TRes>(\n toolName: string,\n args: TArgs,\n options?: UseMcpQueryOptions,\n): UseMcpQueryResult<TRes>\n{\n const enabled = options?.enabled ?? true;\n const { invoke } = useMcpTool<TArgs, TRes>(toolName);\n const [data, setData] = useState<TRes | undefined>(undefined);\n const [loading, setLoading] = useState<boolean>(enabled);\n const [error, setError] = useState<Error | undefined>(undefined);\n const [tick, setTick] = useState(0);\n\n // Stringify args for the effect's dependency key so an args object with\n // new identity but unchanged contents does not force a refetch. The\n // shape JSON-serialises trivially because tool args are wire-bound (JSON\n // round-trips on the transport anyway).\n const argsKey = JSON.stringify(args);\n\n useEffect(() =>\n {\n if (!enabled)\n {\n setLoading(false);\n return;\n }\n let cancelled = false;\n setLoading(true);\n invoke(args)\n .then((result) =>\n {\n if (cancelled)\n {\n return;\n }\n setData(result);\n setError(undefined);\n setLoading(false);\n })\n .catch((err: unknown) =>\n {\n if (cancelled)\n {\n return;\n }\n setError(err instanceof Error ? err : new Error(String(err)));\n setLoading(false);\n });\n return () =>\n {\n cancelled = true;\n };\n // `args` is intentionally tracked via `argsKey` (serialised contents)\n // so reference-only changes don't refetch. eslint sees this as a\n // missing dep but the effect is correct as-is.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [argsKey, tick, invoke, enabled]);\n\n return {\n data,\n loading,\n error,\n refetch: () => setTick((t) => t + 1),\n };\n}\n\n// ── Response-envelope helpers ────────────────────────────────────\n//\n// MCP tool responses across the platform's BE conventions arrive in either\n// `{ items: T[] }` (raw lists) or `{ rows: T[] }` (paginated envelopes). The\n// envelope shape is a BE-side detail plugin authors don't want to encode at\n// every read site. {@link ItemsResponse} types the union and\n// {@link unwrapItems} normalises to a plain array.\n\n/**\n * Envelope shape that covers both `{ items: T[] }` and `{ rows: T[] }`\n * conventions emitted by platform / plugin MCP read tools. Optional both\n * sides so empty responses still type-check.\n */\nexport interface ItemsResponse<T>\n{\n items?: T[];\n rows?: T[];\n}\n\n/**\n * Normalise an {@link ItemsResponse} envelope to a plain array.\n * Returns `[]` when the response is `undefined` (typical pre-first-fetch\n * state) or when neither field is populated.\n */\nexport function unwrapItems<T>(response: ItemsResponse<T> | undefined): T[]\n{\n return response?.items ?? response?.rows ?? [];\n}\n","import type { RenderMode, SduiNode } from \"@ethisyscore/protocol\";\n\n/**\n * Configuration accepted by {@link defineDeclarativePlugin}.\n *\n * A Contract A (host-rendered) plugin contributes a map of resource URIs to\n * declarative SDUI trees. The host fetches a resource by URI and renders it\n * against the v1 vocabulary.\n */\nexport interface DeclarativePluginConfig\n{\n resources: Record<string, SduiNode>;\n}\n\n/**\n * Configuration accepted by {@link defineEthisysPlugin}.\n *\n * `renderMode` is constrained to the protocol's {@link RenderMode} enum so\n * authoring mistakes (`\"iframe\"`, `\"webview\"`, …) are caught at compile time.\n * `mount` is generic so Contract B remote-runtime authors can attach their\n * own mount surface without losing type information at the call site.\n */\nexport interface EthisysPluginConfig<TMount>\n{\n renderMode: RenderMode;\n mount?: TMount;\n}\n\n/**\n * Author-facing identity helper for a Contract A (host-rendered) declarative\n * plugin definition.\n *\n * The helper performs no runtime work — it exists purely so authoring sites\n * receive precise type inference and editor tooling against the protocol's\n * {@link SduiNode} contract. The returned value is the exact same reference\n * the caller passed in.\n */\nexport const defineDeclarativePlugin = (\n cfg: DeclarativePluginConfig,\n): DeclarativePluginConfig => cfg;\n\n/**\n * Author-facing identity helper for a generic EthisysCore plugin definition.\n *\n * The helper performs no runtime work. It constrains `renderMode` to the\n * protocol's {@link RenderMode} enum and preserves the inferred type of an\n * optional `mount` surface, so Contract B authors can pass through their own\n * mount object without widening it to `unknown`.\n */\nexport const defineEthisysPlugin = <TMount>(\n cfg: EthisysPluginConfig<TMount>,\n): EthisysPluginConfig<TMount> => cfg;\n","import ReactReconciler from \"react-reconciler\";\nimport {\n ConcurrentRoot,\n LegacyRoot,\n DefaultEventPriority,\n} from \"react-reconciler/constants.js\";\nimport {\n MUTATION_TYPE_INSERT_CHILD,\n MUTATION_TYPE_REMOVE_CHILD,\n MUTATION_TYPE_UPDATE_TEXT,\n MUTATION_TYPE_UPDATE_PROPERTY,\n NODE_TYPE_ELEMENT,\n NODE_TYPE_TEXT,\n ROOT_ID,\n type RemoteConnection,\n type RemoteNodeSerialization,\n} from \"@remote-dom/core\";\n\n// ── Internal node representation ───────────────────────────────────\n//\n// Lightweight JS-object stand-ins for the Remote DOM tree. Each node carries\n// a stable string id that the host uses to address mutations. We do NOT use\n// `@remote-dom/core`'s `RemoteElement` Custom Element classes because:\n// 1. They require `customElements` registration which the worker realm\n// does not have by default (would force every plugin to bundle a DOM\n// polyfill).\n// 2. The plain-object form serialises identically over the connection's\n// `RemoteNodeSerialization` contract — the host's `RemoteReceiver`\n// reconstructs proper elements on its side.\n\ninterface RemoteElementInstance {\n readonly id: string;\n readonly kind: \"element\";\n readonly type: string;\n properties: Record<string, unknown>;\n eventListeners: Record<string, (...args: unknown[]) => unknown>;\n children: RemoteNode[];\n parent: RemoteParent | null;\n}\n\ninterface RemoteTextInstance {\n readonly id: string;\n readonly kind: \"text\";\n text: string;\n parent: RemoteParent | null;\n}\n\ninterface RemoteRootContainer {\n readonly id: typeof ROOT_ID;\n readonly kind: \"root\";\n children: RemoteNode[];\n readonly connection: RemoteConnection;\n}\n\ntype RemoteNode = RemoteElementInstance | RemoteTextInstance;\ntype RemoteParent = RemoteElementInstance | RemoteRootContainer;\n\nlet nextId = 0;\nfunction newId(): string {\n nextId += 1;\n return `r-${nextId.toString(36)}`;\n}\n\nfunction serialize(node: RemoteNode): RemoteNodeSerialization {\n if (node.kind === \"text\") {\n return { id: node.id, type: NODE_TYPE_TEXT, data: node.text };\n }\n // Event-listener functions are intentionally NOT included in the\n // serialised payload — they can't be structured-cloned across a\n // MessagePort and would throw `DataCloneError` on the first commit.\n // Listeners are retained locally on the RemoteElementInstance for the\n // future `ethisys:remotedom:call` round-trip (see createRemoteRoot.ts's\n // top-of-file \"What's NOT plumbed yet\" note); until that channel lands,\n // worker-side `onClick`-style handlers are no-ops on the host. The host\n // RemoteReceiver tolerates the missing field — `eventListeners` is\n // optional on `RemoteNodeSerialization`.\n return {\n id: node.id,\n type: NODE_TYPE_ELEMENT,\n element: node.type,\n properties: node.properties,\n children: node.children.map(serialize),\n };\n}\n\nfunction indexInParent(parent: RemoteParent, child: RemoteNode): number {\n return parent.children.indexOf(child);\n}\n\n// ── Prop classification ────────────────────────────────────────────\n//\n// Children (the JSX content) are handled by the reconciler tree walk;\n// `ref` and `key` are React-internal. Everything else is forwarded as a\n// remote property OR an event listener. Convention: any prop starting with\n// `on` followed by an uppercase letter is treated as an event listener.\n\nfunction isEventListenerProp(key: string): boolean {\n return key.length > 2 && key.startsWith(\"on\") && key[2] >= \"A\" && key[2] <= \"Z\";\n}\n\nfunction eventNameFromProp(propName: string): string {\n // onClick → click. The host's RemoteReceiver expects lowercase event names.\n return propName.slice(2).toLowerCase();\n}\n\nfunction isReservedProp(key: string): boolean {\n return key === \"children\" || key === \"key\" || key === \"ref\";\n}\n\nfunction classifyProps(props: Record<string, unknown>): {\n properties: Record<string, unknown>;\n eventListeners: Record<string, (...args: unknown[]) => unknown>;\n} {\n const properties: Record<string, unknown> = {};\n const eventListeners: Record<string, (...args: unknown[]) => unknown> = {};\n for (const key of Object.keys(props)) {\n if (isReservedProp(key)) {\n continue;\n }\n const value = props[key];\n if (isEventListenerProp(key) && typeof value === \"function\") {\n eventListeners[eventNameFromProp(key)] = value as (...args: unknown[]) => unknown;\n } else if (value !== undefined) {\n properties[key] = value;\n }\n }\n return { properties, eventListeners };\n}\n\n// ── HostConfig factory ─────────────────────────────────────────────\n\n/**\n * Build the react-reconciler instance bound to the supplied `RemoteConnection`.\n * Every mutation the reconciler applies translates into a single\n * `connection.mutate([record])` call; the connection forwards the record over\n * the `MessagePort` set up by `createRemoteRoot`.\n */\nexport function createReactReconciler(connection: RemoteConnection): {\n reconciler: ReactReconciler.Reconciler<\n RemoteParent,\n RemoteElementInstance,\n RemoteTextInstance,\n never,\n RemoteElementInstance\n >;\n createContainer: () => RemoteRootContainer;\n} {\n const reconciler = ReactReconciler<\n string, // type\n Record<string, unknown>, // props\n RemoteParent, // container\n RemoteElementInstance, // instance\n RemoteTextInstance, // text instance\n never, // suspense instance\n never, // hydratable instance\n RemoteElementInstance, // public instance (returned from ref)\n object, // host context\n string[], // update payload (list of changed prop names)\n never, // child set (persistent mode only)\n ReturnType<typeof setTimeout>, // timeout handle\n -1 // no timeout sentinel\n >({\n supportsMutation: true,\n supportsPersistence: false,\n supportsHydration: false,\n isPrimaryRenderer: true,\n noTimeout: -1,\n scheduleTimeout: setTimeout,\n cancelTimeout: clearTimeout,\n getCurrentEventPriority: () => DefaultEventPriority,\n getRootHostContext: () => ({}),\n getChildHostContext: () => ({}),\n prepareForCommit: () => null,\n resetAfterCommit: () => {},\n preparePortalMount: () => {},\n shouldSetTextContent: (_type, props) =>\n typeof props.children === \"string\" || typeof props.children === \"number\",\n getPublicInstance: (instance) => instance as RemoteElementInstance,\n clearContainer: (container) => {\n // Remove every direct child from the root. The host receiver mirrors\n // each removal on its side.\n while (container.children.length > 0) {\n connection.mutate([[MUTATION_TYPE_REMOVE_CHILD, container.id, 0]]);\n container.children.shift();\n }\n },\n\n // ── createInstance / createTextInstance ────────────────────────\n createInstance: (type, props): RemoteElementInstance => {\n const { properties, eventListeners } = classifyProps(props);\n return {\n id: newId(),\n kind: \"element\",\n type,\n properties,\n eventListeners,\n children: [],\n parent: null,\n };\n },\n createTextInstance: (text): RemoteTextInstance => ({\n id: newId(),\n kind: \"text\",\n text,\n parent: null,\n }),\n\n // ── Initial mount: build the subtree before attaching to root ──\n appendInitialChild: (parent, child) => {\n parent.children.push(child);\n child.parent = parent;\n },\n finalizeInitialChildren: () => false,\n\n // ── Container-level mutations (root attach/detach) ─────────────\n appendChildToContainer: (container, child) => {\n const index = container.children.length;\n container.children.push(child);\n child.parent = container;\n connection.mutate([\n [MUTATION_TYPE_INSERT_CHILD, container.id, serialize(child), index],\n ]);\n },\n removeChildFromContainer: (container, child) => {\n const index = indexInParent(container, child);\n if (index < 0) {\n return;\n }\n container.children.splice(index, 1);\n child.parent = null;\n connection.mutate([[MUTATION_TYPE_REMOVE_CHILD, container.id, index]]);\n },\n insertInContainerBefore: (container, child, beforeChild) => {\n const beforeIndex = indexInParent(container, beforeChild);\n const insertAt = beforeIndex < 0 ? container.children.length : beforeIndex;\n container.children.splice(insertAt, 0, child);\n child.parent = container;\n connection.mutate([\n [MUTATION_TYPE_INSERT_CHILD, container.id, serialize(child), insertAt],\n ]);\n },\n\n // ── Sibling-level mutations (incremental tree updates) ─────────\n appendChild: (parent, child) => {\n const index = parent.children.length;\n parent.children.push(child);\n child.parent = parent;\n connection.mutate([\n [MUTATION_TYPE_INSERT_CHILD, parent.id, serialize(child), index],\n ]);\n },\n removeChild: (parent, child) => {\n const index = indexInParent(parent, child);\n if (index < 0) {\n return;\n }\n parent.children.splice(index, 1);\n child.parent = null;\n connection.mutate([[MUTATION_TYPE_REMOVE_CHILD, parent.id, index]]);\n },\n insertBefore: (parent, child, beforeChild) => {\n const beforeIndex = indexInParent(parent, beforeChild);\n const insertAt = beforeIndex < 0 ? parent.children.length : beforeIndex;\n parent.children.splice(insertAt, 0, child);\n child.parent = parent;\n connection.mutate([\n [MUTATION_TYPE_INSERT_CHILD, parent.id, serialize(child), insertAt],\n ]);\n },\n\n // ── Update path ────────────────────────────────────────────────\n prepareUpdate: (_instance, _type, oldProps, newProps): string[] | null => {\n const changed: string[] = [];\n const allKeys = new Set<string>([\n ...Object.keys(oldProps),\n ...Object.keys(newProps),\n ]);\n for (const key of allKeys) {\n if (isReservedProp(key)) {\n continue;\n }\n if (oldProps[key] !== newProps[key]) {\n changed.push(key);\n }\n }\n return changed.length > 0 ? changed : null;\n },\n commitUpdate: (instance, updatePayload, _type, _oldProps, newProps) => {\n if (updatePayload === null) {\n return;\n }\n for (const key of updatePayload) {\n const value = newProps[key];\n if (isEventListenerProp(key) && (typeof value === \"function\" || value === undefined)) {\n const eventName = eventNameFromProp(key);\n if (typeof value === \"function\") {\n instance.eventListeners[eventName] = value as (...args: unknown[]) => unknown;\n } else {\n delete instance.eventListeners[eventName];\n }\n // Functions can't cross a MessagePort via structured clone, so the\n // wire payload only signals whether the listener is now present or\n // cleared — `true` for \"listener exists, wire it on the host once\n // the call channel lands\", `null` for \"listener removed\". See the\n // serialize() comment for the broader Phase 1 limitation.\n connection.mutate([\n [\n MUTATION_TYPE_UPDATE_PROPERTY,\n instance.id,\n eventName,\n typeof value === \"function\" ? true : null,\n 3 /* event listener */,\n ],\n ]);\n } else {\n if (value === undefined) {\n delete instance.properties[key];\n } else {\n instance.properties[key] = value;\n }\n connection.mutate([\n [MUTATION_TYPE_UPDATE_PROPERTY, instance.id, key, value],\n ]);\n }\n }\n },\n commitTextUpdate: (textInstance, _oldText, newText) => {\n textInstance.text = newText;\n connection.mutate([[MUTATION_TYPE_UPDATE_TEXT, textInstance.id, newText]]);\n },\n\n // ── No-op methods required by the HostConfig contract ──────────\n detachDeletedInstance: () => {},\n beforeActiveInstanceBlur: () => {},\n afterActiveInstanceBlur: () => {},\n prepareScopeUpdate: () => {},\n getInstanceFromScope: () => null,\n getInstanceFromNode: () => null,\n\n // Microtask scheduling — use the platform's default queueing.\n supportsMicrotasks: true,\n scheduleMicrotask:\n typeof queueMicrotask === \"function\"\n ? queueMicrotask\n : (callback) => Promise.resolve().then(callback),\n });\n\n function createContainer(): RemoteRootContainer {\n return { id: ROOT_ID, kind: \"root\", children: [], connection };\n }\n\n return { reconciler, createContainer };\n}\n\nexport { ConcurrentRoot, LegacyRoot };\nexport type { RemoteRootContainer, RemoteElementInstance, RemoteTextInstance };\n","/**\n * Contract B (worker remote-runtime) plugin-side React root.\n *\n * # The problem this solves\n *\n * A Contract B plugin runs in a sandboxed Web Worker — no `document`, no\n * `window`, no DOM. The host owns rendering: the worker constructs a\n * `RemoteElement` tree via `@remote-dom/core`, mutations forward over a\n * `MessagePort`, the host receives them and commits them to a real React tree\n * (see `coreconnect-web/src/extensions/runtime/WorkerSurfaceMount.tsx` for the\n * receiver side).\n *\n * Until now plugin authors had to hand-author the `RemoteElement` construction\n * + mutation forwarding manually. `@remote-dom/react` ships only the host-side\n * primitives (`createRemoteComponent`, `RemoteRootRenderer`, etc.) — there is\n * no worker-side React reconciler in the package. This helper provides one.\n *\n * # What this is\n *\n * The public surface (`createRemoteRoot(port, options)`) plus a working\n * `react-reconciler` HostConfig that commits to a Remote DOM tree and\n * forwards mutation records over the `MessagePort` to the host receiver.\n * Authors call `root.render(<App />)` and the host's `WorkerSurfaceMount`\n * sees the result.\n *\n * # What's NOT plumbed yet (Phase 1 limitation)\n *\n * Event-listener round-trip. The host transport currently has no\n * `ethisys:remotedom:call` channel — `WorkerRemoteDomTransport` only\n * forwards `ethisys:remotedom` payloads from worker → host, never the\n * other direction. So a worker-side `onClick={() => ...}` is **registered\n * locally** but the host can't call it. The reconciler retains every\n * listener on its in-memory `RemoteElementInstance` so the wiring is ready\n * the moment the call channel lands; until then, plugin authors should\n * keep interactive surfaces on Contract A.\n *\n * # The API\n *\n * ```ts\n * import { createRemoteRoot } from \"@ethisyscore/extension-runtime/plugin\";\n *\n * export async function activate(port: MessagePort): Promise<void> {\n * const root = createRemoteRoot(port);\n * root.render(<App />);\n * }\n * ```\n *\n * `<App />` is plain React. Any component shipped by the host's frozen\n * import-map allowlist (the closed Contract B primitive vocabulary —\n * `Button`, `DataTable`, `Form`, `Card`, `Tabs`, `Select`, `Alert`, etc.)\n * renders. The reconciler walks the React tree and commits to a\n * `RemoteRootElement`; mutation records forward over the port; the host's\n * `RemoteReceiver` commits the result into the real React tree.\n *\n * # Wire shape\n *\n * Every reconciler mutation is posted as\n * `{ type: \"ethisys:remotedom\", payload: RemoteMutationRecord[] }` to match\n * `WorkerRemoteDomTransport`'s `RemoteDomMessage` contract — the host\n * extracts `payload` and feeds it straight into `receiver.mutate(records)`.\n * `BatchingRemoteConnection` (controlled via `options.batchMutations`)\n * collapses contiguous mutations into a single port post per commit.\n */\nimport type { RemoteConnection, RemoteMutationRecord } from \"@remote-dom/core\";\nimport { BatchingRemoteConnection } from \"@remote-dom/core/elements\";\nimport type { ReactNode } from \"react\";\nimport {\n createReactReconciler,\n LegacyRoot,\n type RemoteRootContainer,\n} from \"./reconciler\";\n\n/**\n * Options for {@link createRemoteRoot}. Reserved for forward compatibility —\n * Phase 1 ships with zero required options. Adding fields here is additive;\n * removing them is a breaking change.\n */\nexport interface CreateRemoteRootOptions\n{\n /**\n * When supplied, the reconciler batches contiguous mutations into a single\n * `port.postMessage` rather than firing one per mutation. Default `true`\n * — measurably reduces host-side commit cost on the first render of a\n * non-trivial tree.\n */\n batchMutations?: boolean;\n\n /**\n * Override the connection factory. Reserved for tests; production callers\n * never pass this. The factory's contract is \"build a RemoteConnection\n * that forwards mutations over the supplied port\"; the default uses\n * `createRemoteConnection` from `@remote-dom/core`.\n */\n connectionFactory?: (port: MessagePort) => RemoteConnection;\n}\n\n/**\n * Plugin-side React root. Mirrors the shape of `ReactDOMClient.Root` so\n * authors familiar with `createRoot().render(...)` find the same API on the\n * worker side.\n */\nexport interface RemoteRoot\n{\n /**\n * Render a React element tree against the worker's `RemoteRootElement`.\n * The reconciler commits to the root, the mutation observer forwards\n * mutations over the port, the host re-renders. Idempotent — calling\n * `render` twice with the same element is fine; the reconciler dedupes.\n */\n render(element: ReactNode): void;\n\n /**\n * Tear down the reconciled tree and stop forwarding mutations. Authors\n * should call this from a `Symbol.dispose` or equivalent when the worker\n * is shutting down — leaking the reconciler holds the `MessagePort` open\n * and prevents the worker from being collected.\n */\n unmount(): void;\n}\n\n/**\n * Construct a plugin-side React root that commits to a `RemoteRootElement`\n * and forwards mutations over the supplied `MessagePort`.\n *\n * **API stability:** the function signature is stable for Phase 1. The\n * options bag is forward-compatible (additive only).\n *\n * **Implementation status:** the connection + root construction lands in this\n * commit. The `react-reconciler` `HostConfig` is a scaffold — `render()`\n * throws a structured error directing authors to the W1A tracking issue.\n * Authors should treat this commit as \"the API is locked, the reconciler is\n * being authored.\" See follow-on commits on the `feature/contract-b-create-remote-root-w1a`\n * branch.\n */\nexport function createRemoteRoot(\n port: MessagePort,\n options: CreateRemoteRootOptions = {},\n): RemoteRoot\n{\n if (port === undefined || port === null)\n {\n throw new TypeError(\n \"[createRemoteRoot] `port` is required. Pass the MessagePort the host transferred via the worker's `activate(port)` entry point.\",\n );\n }\n\n // Build the connection that forwards Remote DOM mutations over the port.\n // The default factory uses `@remote-dom/core`'s `createRemoteConnection`;\n // tests inject their own factory via `options.connectionFactory`.\n const baseConnection = (options.connectionFactory ?? defaultConnectionFactory)(port);\n\n const connection: RemoteConnection = options.batchMutations === false\n ? baseConnection\n : new BatchingRemoteConnection(baseConnection);\n\n // W1A — lazy reconciler + container construction. The reconciler is built\n // once on first render(); subsequent calls reuse the same container so React\n // commits behave like ReactDOM.createRoot(...).render(...) — call render\n // multiple times to update; call unmount to tear down.\n const { reconciler, createContainer } = createReactReconciler(connection);\n let container: RemoteRootContainer | null = null;\n let fiberRoot: ReturnType<typeof reconciler.createContainer> | null = null;\n\n return {\n render(element: ReactNode): void\n {\n if (container === null)\n {\n container = createContainer();\n fiberRoot = reconciler.createContainer(\n container,\n LegacyRoot,\n null, // hydration callbacks\n false, // isStrictMode\n null, // concurrentUpdatesByDefaultOverride\n \"\", // identifierPrefix\n (error: Error) =>\n {\n // The host's SurfaceErrorBoundary catches render-time\n // failures via the connection's call() path; mirroring\n // them locally as a console.error is the best we can do\n // from inside the worker.\n // eslint-disable-next-line no-console -- worker console is pumped to the host logger.\n console.error(\"[createRemoteRoot] render error\", error);\n },\n null, // transitionCallbacks\n );\n }\n reconciler.updateContainer(element, fiberRoot!, null, null);\n },\n unmount(): void\n {\n if (fiberRoot !== null)\n {\n reconciler.updateContainer(null, fiberRoot, null, null);\n fiberRoot = null;\n container = null;\n }\n // The connection itself does NOT close the port — plugins may have\n // side-channel consumers. Authors that want a hard tear-down call\n // `port.close()` themselves after unmount().\n },\n };\n}\n\n// ── Internals ──────────────────────────────────────────────────────────\n\n/**\n * Default factory: build a `RemoteConnection` that posts mutation records\n * as the `payload` of a single `ethisys:remotedom` port message — the\n * wire shape `WorkerRemoteDomTransport`'s `RemoteDomMessage` declares\n * (see `host/worker/transport.ts`'s `handlePortMessage`: it forwards\n * `(message as RemoteDomMessage).payload` straight into the host's\n * `RemoteReceiver.mutate(records)` call).\n *\n * Going through `createRemoteConnection` (which fires per-op callbacks)\n * was the wrong abstraction for this wire — the host expects the raw\n * record list under `payload`, not bespoke `op`-suffixed envelopes. By\n * implementing the connection directly we hand the reconciler's\n * mutation records straight to the host receiver without translation.\n *\n * Wrapping in `BatchingRemoteConnection` (controlled via\n * `options.batchMutations`) collapses contiguous mutation calls into a\n * single `port.postMessage` payload, which is the difference between \"one\n * postMessage per appended child\" and \"one postMessage per React commit\"\n * — measurably cheaper for the first paint of a non-trivial tree.\n */\nfunction defaultConnectionFactory(port: MessagePort): RemoteConnection\n{\n return {\n mutate(records: readonly RemoteMutationRecord[]): void\n {\n // Snapshot to a plain array so the host receiver isn't handed a\n // reference into the reconciler's internal buffer (the BatchingRemoteConnection\n // wrapper recycles its own array between flushes).\n port.postMessage({ type: \"ethisys:remotedom\", payload: records.slice() });\n },\n call(_id, _method, ..._args): unknown\n {\n // Worker → host method invocation. Reserved for the future\n // `ethisys:remotedom:call` channel — `WorkerRemoteDomTransport`\n // doesn't yet handle a `call`-shaped reply path, so event-\n // listener round-trip is still on the Phase 1 follow-on list\n // (see this file's top-of-file \"What's NOT plumbed yet\" note).\n return undefined;\n },\n };\n}\n\n","/**\n * W1B — MessagePort-backed McpTransport for Contract B (worker remote-runtime)\n * plugins.\n *\n * The plugin-side React hooks (`useMcpResource`, `useMcpTool`) consume an\n * {@link McpTransport} — an abstraction over the host call. Contract A\n * (host-rendered) plugins pick up the host-injected transport via\n * `ExtensionRuntimeProvider`. Contract B plugins run in a Web Worker with\n * no shared object surface — the only channel is the `MessagePort` the\n * host transferred via `activate(port)`. This helper bridges the two\n * worlds: it exposes the {@link McpTransport} contract on the worker side\n * and serialises every call into a request/response envelope over the\n * port.\n *\n * # The protocol on the wire\n *\n * The wire shape mirrors `WorkerRemoteDomTransport` (in `host/worker/transport.ts`)\n * one-for-one — that transport is the host receiver and decides what a \"well-\n * formed\" message looks like. Two request shapes, two `:result`-suffixed reply\n * shapes, one abort envelope. Each call mints a fresh request id (`req-{n}`).\n *\n * ```jsonc\n * // worker → host\n * { type: \"ethisys:mcp:getResource\", id: \"req-3\", uri: \"tickets://home\" }\n * { type: \"ethisys:mcp:invokeTool\", id: \"req-4\", name: \"tickets:open\", args: { ... } }\n *\n * // host → worker (matching id, suffixed type)\n * { type: \"ethisys:mcp:getResource:result\", id: \"req-3\", ok: true, data: { uri, data } }\n * { type: \"ethisys:mcp:invokeTool:result\", id: \"req-4\", ok: false, error: \"...\" }\n * ```\n *\n * Requests honour the optional `AbortSignal`. On abort, the transport posts\n * a `{ type: \"ethisys:mcp:abort\", id }` envelope so the host can cancel\n * in-flight work, then rejects the pending promise with an `AbortError`-shaped\n * `Error` so the consuming hooks see the same shape as native fetch cancellation.\n *\n * # Authoring shape\n *\n * ```ts\n * export async function activate(port: MessagePort): Promise<void> {\n * const transport = createPortMcpTransport(port);\n * const root = createRemoteRoot(port);\n * root.render(\n * <ExtensionRuntimeProvider transport={transport}>\n * <App />\n * </ExtensionRuntimeProvider>,\n * );\n * }\n * ```\n *\n * `<App />` uses `useMcpResource` / `useMcpTool` as it would on the host\n * side; the transport translates each call into the port envelope.\n */\nimport type { McpTransport } from \"./transport\";\n\n/**\n * Options for {@link createPortMcpTransport}. Reserved for forward\n * compatibility — the public surface is empty in Phase 1.\n */\nexport interface CreatePortMcpTransportOptions\n{\n /**\n * Override the request-id generator. Reserved for tests so they can\n * make request ids deterministic. Production callers never pass this.\n */\n requestIdFactory?: () => string;\n\n /**\n * Override the port's `addEventListener` / `removeEventListener` /\n * `postMessage` triple. Reserved for tests so the transport can be\n * exercised without instantiating a real MessageChannel.\n */\n portShimForTests?: PortShim;\n}\n\n/**\n * Minimal subset of the MessagePort surface the transport actually uses.\n * Exposed so tests can construct a polyfill without faking the full\n * MessagePort.\n */\nexport interface PortShim\n{\n addEventListener(\n type: \"message\",\n listener: (event: { data: unknown }) => void,\n ): void;\n removeEventListener(\n type: \"message\",\n listener: (event: { data: unknown }) => void,\n ): void;\n postMessage(value: unknown): void;\n}\n\n// ── Wire-shape constants ────────────────────────────────────────────\n//\n// These four strings are the contract with `WorkerRemoteDomTransport`. Any\n// rename here breaks the host receiver silently — the unknown message hits\n// the host's default branch and is dropped. Keep these in sync with\n// `host/worker/transport.ts`'s `handlePortMessage` switch / result-type\n// strings.\nconst WIRE_INVOKE_TOOL_REQUEST = \"ethisys:mcp:invokeTool\";\nconst WIRE_INVOKE_TOOL_RESULT = \"ethisys:mcp:invokeTool:result\";\nconst WIRE_GET_RESOURCE_REQUEST = \"ethisys:mcp:getResource\";\nconst WIRE_GET_RESOURCE_RESULT = \"ethisys:mcp:getResource:result\";\nconst WIRE_ABORT = \"ethisys:mcp:abort\";\n\ntype McpResultType = typeof WIRE_INVOKE_TOOL_RESULT | typeof WIRE_GET_RESOURCE_RESULT;\n\ninterface McpResultEnvelope\n{\n type: McpResultType;\n id: string;\n ok?: boolean;\n error?: string;\n data?: unknown;\n}\n\nfunction isMcpResultEnvelope(value: unknown): value is McpResultEnvelope\n{\n if (value === null || typeof value !== \"object\")\n {\n return false;\n }\n const v = value as { type?: unknown; id?: unknown };\n return (v.type === WIRE_INVOKE_TOOL_RESULT || v.type === WIRE_GET_RESOURCE_RESULT)\n && typeof v.id === \"string\";\n}\n\n/**\n * Construct an {@link McpTransport} backed by a MessagePort.\n *\n * @param port The host-transferred MessagePort for the worker surface.\n * @param options Reserved for forward compatibility / test injection.\n *\n * @returns A transport implementation honouring the {@link McpTransport}\n * contract — fetch a resource, invoke a tool, observe abort\n * signals, settle the promise on the host's reply envelope.\n */\nexport function createPortMcpTransport(\n port: MessagePort | PortShim,\n options: CreatePortMcpTransportOptions = {},\n): McpTransport\n{\n if (port === undefined || port === null)\n {\n throw new TypeError(\n \"[createPortMcpTransport] `port` is required. Pass the MessagePort the host transferred via the worker's `activate(port)` entry point.\",\n );\n }\n\n const shim: PortShim = options.portShimForTests ?? port as PortShim;\n const factory = options.requestIdFactory ?? defaultRequestIdFactory();\n\n type Resolver = {\n resolve: (value: unknown) => void;\n reject: (reason: unknown) => void;\n };\n const pending = new Map<string, Resolver>();\n\n function onMessage(event: { data: unknown }): void\n {\n if (!isMcpResultEnvelope(event.data))\n {\n return;\n }\n const reply = event.data;\n const resolver = pending.get(reply.id);\n if (resolver === undefined)\n {\n return;\n }\n pending.delete(reply.id);\n if (reply.ok === true)\n {\n // Host posts the payload under `data` (matching\n // `WorkerRemoteDomTransport.safePostMessage`). For getResource\n // calls the data is the resource body; for invokeTool calls it\n // is the tool's return value.\n resolver.resolve(reply.data);\n }\n else\n {\n const error = new Error(\n typeof reply.error === \"string\" ? reply.error : \"Unknown host error\",\n );\n error.name = \"McpHostError\";\n resolver.reject(error);\n }\n }\n\n shim.addEventListener(\"message\", onMessage);\n // MessagePort.addEventListener doesn't auto-start the port — without an\n // explicit `start()`, the message queue stays paused and the host's\n // replies never reach `onMessage`. This is a no-op on plain\n // EventTarget-shaped shims used in tests (the type guard guarantees\n // safety) but is required on real MessagePort instances.\n const realPort = port as Partial<MessagePort>;\n if (!options.portShimForTests && typeof realPort.start === \"function\")\n {\n realPort.start();\n }\n\n function send(\n requestType: typeof WIRE_INVOKE_TOOL_REQUEST | typeof WIRE_GET_RESOURCE_REQUEST,\n body: Record<string, unknown>,\n signal?: AbortSignal,\n ): Promise<unknown>\n {\n const id = factory();\n return new Promise<unknown>((resolve, reject) =>\n {\n if (signal?.aborted === true)\n {\n reject(abortError());\n return;\n }\n pending.set(id, { resolve, reject });\n\n const onAbort = (): void =>\n {\n if (!pending.has(id))\n {\n return;\n }\n pending.delete(id);\n shim.postMessage({ type: WIRE_ABORT, id });\n reject(abortError());\n };\n signal?.addEventListener(\"abort\", onAbort, { once: true });\n\n shim.postMessage({ type: requestType, id, ...body });\n });\n }\n\n return {\n async getResource<T>(uri: string, signal?: AbortSignal): Promise<{ uri: string; data: T }>\n {\n // Host sends only the resource body under `data`. Reconstruct the\n // `{ uri, data }` envelope the McpTransport contract returns —\n // `uri` is round-tripped from the request because the resolver\n // only sees the reply.\n const data = await send(WIRE_GET_RESOURCE_REQUEST, { uri }, signal);\n return { uri, data: data as T };\n },\n async invokeTool<TReq, TRes>(name: string, args: TReq, signal?: AbortSignal): Promise<TRes>\n {\n const data = await send(WIRE_INVOKE_TOOL_REQUEST, { name, args: args as unknown }, signal);\n return data as TRes;\n },\n };\n}\n\nfunction defaultRequestIdFactory(): () => string\n{\n let counter = 0;\n return (): string =>\n {\n counter += 1;\n return `req-${counter}`;\n };\n}\n\nfunction abortError(): Error\n{\n const e = new Error(\"Aborted\");\n e.name = \"AbortError\";\n return e;\n}\n"]}
1
+ {"version":3,"sources":["../../src/plugin/ExtensionRuntimeProvider.tsx","../../src/plugin/useMcpResource.ts","../../src/plugin/useMcpTool.ts","../../src/plugin/useMcpQuery.ts","../../src/plugin/define.ts","../../src/plugin/reconciler.ts","../../src/plugin/createRemoteRoot.ts","../../src/plugin/createPortMcpTransport.ts","../../src/host/worker/bridge-envelopes.ts","../../src/plugin/bridge-client.ts","../../src/plugin/BridgeClientContext.ts","../../src/plugin/useBridgeTheme.ts","../../src/plugin/useBridgeLocale.ts","../../src/plugin/useFrontendSessionToken.ts"],"names":["createContext","useMemo","jsx","useContext","useState","useRef","useEffect","useCallback","NODE_TYPE_TEXT","NODE_TYPE_ELEMENT","ReactReconciler","DefaultEventPriority","MUTATION_TYPE_REMOVE_CHILD","MUTATION_TYPE_INSERT_CHILD","MUTATION_TYPE_UPDATE_PROPERTY","MUTATION_TYPE_UPDATE_TEXT","ROOT_ID","BatchingRemoteConnection","LegacyRoot","nextId"],"mappings":"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","file":"index.cjs","sourcesContent":["import { createContext, useContext, useMemo, type ReactNode } from \"react\";\nimport type { McpTransport } from \"./transport\";\n\n/**\n * React context carrying the {@link McpTransport} the plugin should use to\n * reach the host. `null` is the explicit \"not provided\" sentinel so the hooks\n * can disambiguate from a transport that was provided but is incidentally\n * falsy in some other dimension.\n */\nconst ExtensionRuntimeContext = createContext<McpTransport | null>(null);\n\nexport interface ExtensionRuntimeProviderProps\n{\n transport: McpTransport;\n children?: ReactNode;\n}\n\n/**\n * Wrap a plugin's React tree so descendant {@link useMcpResource} and\n * {@link useMcpTool} calls resolve a default transport without having to\n * thread it through every component.\n *\n * Hooks still accept a per-call `transport` override, which takes precedence\n * over the context value — useful for tests and for plugins that want to\n * shard work across multiple hosts.\n */\nexport function ExtensionRuntimeProvider({ transport, children }: ExtensionRuntimeProviderProps): ReactNode\n{\n // Memoise so swapping `children` doesn't churn the context identity.\n const value = useMemo(() => transport, [transport]);\n return (\n <ExtensionRuntimeContext.Provider value={value}>\n {children}\n </ExtensionRuntimeContext.Provider>\n );\n}\n\n/**\n * Internal helper used by the hooks. Returns the explicit override when\n * supplied, otherwise falls back to the context. Throws a deterministic\n * error if neither is available so misconfiguration fails loudly at the\n * first render rather than producing silent no-ops.\n */\nexport function useExtensionRuntimeTransport(override?: McpTransport): McpTransport\n{\n const fromContext = useContext(ExtensionRuntimeContext);\n const resolved = override ?? fromContext;\n if (!resolved)\n {\n throw new Error(\n \"No McpTransport available. Wrap your plugin in <ExtensionRuntimeProvider transport={...}> \"\n + \"or pass `transport` directly to the hook.\",\n );\n }\n return resolved;\n}\n","import { useCallback, useEffect, useRef, useState } from \"react\";\nimport { useExtensionRuntimeTransport } from \"./ExtensionRuntimeProvider\";\nimport type { McpTransport } from \"./transport\";\n\nexport interface UseMcpResourceOptions\n{\n /**\n * Override the transport resolved from {@link ExtensionRuntimeProvider}.\n * Primarily intended for tests and advanced multi-host scenarios.\n */\n transport?: McpTransport;\n}\n\nexport interface UseMcpResourceResult<T>\n{\n data: T | undefined;\n error: Error | undefined;\n loading: boolean;\n /** Re-run the fetch against the current URI. Stable across renders. */\n refetch: () => void;\n}\n\n/**\n * Subscribe to an MCP resource by URI.\n *\n * The hook fetches via the resolved {@link McpTransport} on mount and whenever\n * the URI changes. Each fetch is cancellable: when the component unmounts or\n * the URI changes, the in-flight call is aborted via an {@link AbortController}\n * so stale responses cannot overwrite later state.\n *\n * `refetch` re-runs the fetch against the latest URI. The returned callback is\n * stable across renders so it is safe to include in `useEffect` dependency\n * arrays.\n */\nexport function useMcpResource<T>(\n uri: string,\n opts?: UseMcpResourceOptions,\n): UseMcpResourceResult<T>\n{\n const transport = useExtensionRuntimeTransport(opts?.transport);\n\n const [data, setData] = useState<T | undefined>(undefined);\n const [error, setError] = useState<Error | undefined>(undefined);\n const [loading, setLoading] = useState<boolean>(true);\n\n // Bump this counter to force a re-fetch from `refetch()`.\n const [refetchTick, setRefetchTick] = useState(0);\n\n // Track the active controller so `refetch` and unmount can abort it.\n const controllerRef = useRef<AbortController | null>(null);\n\n useEffect(() =>\n {\n const controller = new AbortController();\n controllerRef.current?.abort();\n controllerRef.current = controller;\n\n let cancelled = false;\n setLoading(true);\n setError(undefined);\n\n transport\n .getResource<T>(uri, controller.signal)\n .then((result) =>\n {\n if (cancelled || controller.signal.aborted)\n {\n return;\n }\n setData(result.data);\n setLoading(false);\n })\n .catch((err: unknown) =>\n {\n if (cancelled || controller.signal.aborted)\n {\n return;\n }\n setError(err instanceof Error ? err : new Error(String(err)));\n setLoading(false);\n });\n\n return () =>\n {\n cancelled = true;\n controller.abort();\n };\n }, [uri, transport, refetchTick]);\n\n const refetch = useCallback(() =>\n {\n setRefetchTick((tick) => tick + 1);\n }, []);\n\n return { data, error, loading, refetch };\n}\n","import { useCallback, useEffect, useRef, useState } from \"react\";\nimport { useExtensionRuntimeTransport } from \"./ExtensionRuntimeProvider\";\nimport type { McpTransport } from \"./transport\";\n\nexport interface UseMcpToolOptions\n{\n /**\n * Override the transport resolved from {@link ExtensionRuntimeProvider}.\n * Primarily intended for tests and advanced multi-host scenarios.\n */\n transport?: McpTransport;\n}\n\nexport interface UseMcpToolResult<TReq, TRes>\n{\n /**\n * Invoke the tool. Each call gets a fresh {@link AbortController} that is\n * aborted on unmount so unresolved promises cannot keep state alive after\n * the component is gone.\n */\n invoke: (req: TReq) => Promise<TRes>;\n loading: boolean;\n error: Error | undefined;\n}\n\n/**\n * Hook returning a callback that invokes an MCP tool by name through the\n * resolved {@link McpTransport}.\n *\n * `loading` and `error` track the most recent in-flight invocation. Callers\n * may also `await` the returned promise directly — failures are both rejected\n * to the caller AND surfaced via `error` so component-level UI can react.\n *\n * `invoke` is a stable reference across renders for the same `toolName` and\n * transport, making it safe to use inside `useEffect`/`useCallback` deps.\n */\nexport function useMcpTool<TReq, TRes>(\n toolName: string,\n opts?: UseMcpToolOptions,\n): UseMcpToolResult<TReq, TRes>\n{\n const transport = useExtensionRuntimeTransport(opts?.transport);\n\n const [loading, setLoading] = useState(false);\n const [error, setError] = useState<Error | undefined>(undefined);\n\n // Track the latest controller so unmount can abort an in-flight call.\n const controllerRef = useRef<AbortController | null>(null);\n const mountedRef = useRef(true);\n\n useEffect(() =>\n {\n mountedRef.current = true;\n return () =>\n {\n mountedRef.current = false;\n controllerRef.current?.abort();\n };\n }, []);\n\n const invoke = useCallback(\n async (req: TReq): Promise<TRes> =>\n {\n const controller = new AbortController();\n controllerRef.current?.abort();\n controllerRef.current = controller;\n\n setLoading(true);\n setError(undefined);\n\n try\n {\n const result = await transport.invokeTool<TReq, TRes>(\n toolName,\n req,\n controller.signal,\n );\n if (mountedRef.current && !controller.signal.aborted)\n {\n setLoading(false);\n }\n return result;\n }\n catch (err)\n {\n const wrapped = err instanceof Error ? err : new Error(String(err));\n if (mountedRef.current && !controller.signal.aborted)\n {\n setError(wrapped);\n setLoading(false);\n }\n throw wrapped;\n }\n },\n [transport, toolName],\n );\n\n return { invoke, loading, error };\n}\n","import { useEffect, useState } from \"react\";\nimport { useMcpTool } from \"./useMcpTool\";\n\n/**\n * Result shape returned by {@link useMcpQuery}. Mirrors the host-app\n * `react-query`-style envelope so consumers can render loading / error /\n * data states declaratively. `refetch` is stable across renders.\n */\nexport interface UseMcpQueryResult<TRes>\n{\n data: TRes | undefined;\n loading: boolean;\n error: Error | undefined;\n /** Re-run the fetch against the current args. Stable across renders. */\n refetch: () => void;\n}\n\n/**\n * Options for {@link useMcpQuery}.\n */\nexport interface UseMcpQueryOptions\n{\n /**\n * Gate the fetch on a guard. When false, the hook returns idle state and\n * never invokes — important because hooks must be called unconditionally\n * at the top of the component, so an `enabled` flag is the standard way\n * to express \"fetch only when a selection is present\" without violating\n * the rules of hooks. Defaults to `true`.\n */\n enabled?: boolean;\n}\n\n/**\n * Auto-fetch wrapper over the imperative {@link useMcpTool}. Fires the tool\n * call on mount AND whenever the serialised `args` change. Use for\n * read-shaped MCP tool calls that back a component's render data; for\n * mutations, call {@link useMcpTool} directly and trigger\n * `invoke(...)` from event handlers.\n *\n * Why this lives alongside {@link useMcpTool}: many plugin MCP tools are\n * effectively queries (`list-tasks`, `get-pending-approvals`, …) — paginated\n * lookups that change with filter inputs. The base hook's imperative\n * `invoke` signature is correct for mutations but ergonomically wrong for\n * reads, where every consumer ends up writing the same `useEffect` +\n * AbortController + cancellation-on-unmount boilerplate. This hook absorbs\n * that boilerplate once.\n *\n * @template TArgs The request shape sent to the tool.\n * @template TRes The response shape the tool returns.\n */\nexport function useMcpQuery<TArgs, TRes>(\n toolName: string,\n args: TArgs,\n options?: UseMcpQueryOptions,\n): UseMcpQueryResult<TRes>\n{\n const enabled = options?.enabled ?? true;\n const { invoke } = useMcpTool<TArgs, TRes>(toolName);\n const [data, setData] = useState<TRes | undefined>(undefined);\n const [loading, setLoading] = useState<boolean>(enabled);\n const [error, setError] = useState<Error | undefined>(undefined);\n const [tick, setTick] = useState(0);\n\n // Stringify args for the effect's dependency key so an args object with\n // new identity but unchanged contents does not force a refetch. The\n // shape JSON-serialises trivially because tool args are wire-bound (JSON\n // round-trips on the transport anyway).\n const argsKey = JSON.stringify(args);\n\n useEffect(() =>\n {\n if (!enabled)\n {\n setLoading(false);\n return;\n }\n let cancelled = false;\n setLoading(true);\n invoke(args)\n .then((result) =>\n {\n if (cancelled)\n {\n return;\n }\n setData(result);\n setError(undefined);\n setLoading(false);\n })\n .catch((err: unknown) =>\n {\n if (cancelled)\n {\n return;\n }\n setError(err instanceof Error ? err : new Error(String(err)));\n setLoading(false);\n });\n return () =>\n {\n cancelled = true;\n };\n // `args` is intentionally tracked via `argsKey` (serialised contents)\n // so reference-only changes don't refetch. eslint sees this as a\n // missing dep but the effect is correct as-is.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [argsKey, tick, invoke, enabled]);\n\n return {\n data,\n loading,\n error,\n refetch: () => setTick((t) => t + 1),\n };\n}\n\n// ── Response-envelope helpers ────────────────────────────────────\n//\n// MCP tool responses across the platform's BE conventions arrive in either\n// `{ items: T[] }` (raw lists) or `{ rows: T[] }` (paginated envelopes). The\n// envelope shape is a BE-side detail plugin authors don't want to encode at\n// every read site. {@link ItemsResponse} types the union and\n// {@link unwrapItems} normalises to a plain array.\n\n/**\n * Envelope shape that covers both `{ items: T[] }` and `{ rows: T[] }`\n * conventions emitted by platform / plugin MCP read tools. Optional both\n * sides so empty responses still type-check.\n */\nexport interface ItemsResponse<T>\n{\n items?: T[];\n rows?: T[];\n}\n\n/**\n * Normalise an {@link ItemsResponse} envelope to a plain array.\n * Returns `[]` when the response is `undefined` (typical pre-first-fetch\n * state) or when neither field is populated.\n */\nexport function unwrapItems<T>(response: ItemsResponse<T> | undefined): T[]\n{\n return response?.items ?? response?.rows ?? [];\n}\n","import type { RenderMode, SduiNode } from \"@ethisyscore/protocol\";\n\n/**\n * Configuration accepted by {@link defineDeclarativePlugin}.\n *\n * A Contract A (host-rendered) plugin contributes a map of resource URIs to\n * declarative SDUI trees. The host fetches a resource by URI and renders it\n * against the v1 vocabulary.\n */\nexport interface DeclarativePluginConfig\n{\n resources: Record<string, SduiNode>;\n}\n\n/**\n * Configuration accepted by {@link defineEthisysPlugin}.\n *\n * `renderMode` is constrained to the protocol's {@link RenderMode} enum so\n * authoring mistakes (`\"iframe\"`, `\"webview\"`, …) are caught at compile time.\n * `mount` is generic so Contract B remote-runtime authors can attach their\n * own mount surface without losing type information at the call site.\n */\nexport interface EthisysPluginConfig<TMount>\n{\n renderMode: RenderMode;\n mount?: TMount;\n}\n\n/**\n * Author-facing identity helper for a Contract A (host-rendered) declarative\n * plugin definition.\n *\n * The helper performs no runtime work — it exists purely so authoring sites\n * receive precise type inference and editor tooling against the protocol's\n * {@link SduiNode} contract. The returned value is the exact same reference\n * the caller passed in.\n */\nexport const defineDeclarativePlugin = (\n cfg: DeclarativePluginConfig,\n): DeclarativePluginConfig => cfg;\n\n/**\n * Author-facing identity helper for a generic EthisysCore plugin definition.\n *\n * The helper performs no runtime work. It constrains `renderMode` to the\n * protocol's {@link RenderMode} enum and preserves the inferred type of an\n * optional `mount` surface, so Contract B authors can pass through their own\n * mount object without widening it to `unknown`.\n */\nexport const defineEthisysPlugin = <TMount>(\n cfg: EthisysPluginConfig<TMount>,\n): EthisysPluginConfig<TMount> => cfg;\n","import ReactReconciler from \"react-reconciler\";\nimport {\n ConcurrentRoot,\n LegacyRoot,\n DefaultEventPriority,\n} from \"react-reconciler/constants.js\";\nimport {\n MUTATION_TYPE_INSERT_CHILD,\n MUTATION_TYPE_REMOVE_CHILD,\n MUTATION_TYPE_UPDATE_TEXT,\n MUTATION_TYPE_UPDATE_PROPERTY,\n NODE_TYPE_ELEMENT,\n NODE_TYPE_TEXT,\n ROOT_ID,\n type RemoteConnection,\n type RemoteNodeSerialization,\n} from \"@remote-dom/core\";\n\n// ── Internal node representation ───────────────────────────────────\n//\n// Lightweight JS-object stand-ins for the Remote DOM tree. Each node carries\n// a stable string id that the host uses to address mutations. We do NOT use\n// `@remote-dom/core`'s `RemoteElement` Custom Element classes because:\n// 1. They require `customElements` registration which the worker realm\n// does not have by default (would force every plugin to bundle a DOM\n// polyfill).\n// 2. The plain-object form serialises identically over the connection's\n// `RemoteNodeSerialization` contract — the host's `RemoteReceiver`\n// reconstructs proper elements on its side.\n\ninterface RemoteElementInstance {\n readonly id: string;\n readonly kind: \"element\";\n readonly type: string;\n properties: Record<string, unknown>;\n eventListeners: Record<string, (...args: unknown[]) => unknown>;\n children: RemoteNode[];\n parent: RemoteParent | null;\n}\n\ninterface RemoteTextInstance {\n readonly id: string;\n readonly kind: \"text\";\n text: string;\n parent: RemoteParent | null;\n}\n\ninterface RemoteRootContainer {\n readonly id: typeof ROOT_ID;\n readonly kind: \"root\";\n children: RemoteNode[];\n readonly connection: RemoteConnection;\n}\n\ntype RemoteNode = RemoteElementInstance | RemoteTextInstance;\ntype RemoteParent = RemoteElementInstance | RemoteRootContainer;\n\nlet nextId = 0;\nfunction newId(): string {\n nextId += 1;\n return `r-${nextId.toString(36)}`;\n}\n\nfunction serialize(node: RemoteNode): RemoteNodeSerialization {\n if (node.kind === \"text\") {\n return { id: node.id, type: NODE_TYPE_TEXT, data: node.text };\n }\n // Event-listener functions are intentionally NOT included in the\n // serialised payload — they can't be structured-cloned across a\n // MessagePort and would throw `DataCloneError` on the first commit.\n // Listeners are retained locally on the RemoteElementInstance for the\n // future `ethisys:remotedom:call` round-trip (see createRemoteRoot.ts's\n // top-of-file \"What's NOT plumbed yet\" note); until that channel lands,\n // worker-side `onClick`-style handlers are no-ops on the host. The host\n // RemoteReceiver tolerates the missing field — `eventListeners` is\n // optional on `RemoteNodeSerialization`.\n return {\n id: node.id,\n type: NODE_TYPE_ELEMENT,\n element: node.type,\n properties: node.properties,\n children: node.children.map(serialize),\n };\n}\n\nfunction indexInParent(parent: RemoteParent, child: RemoteNode): number {\n return parent.children.indexOf(child);\n}\n\n// ── Prop classification ────────────────────────────────────────────\n//\n// Children (the JSX content) are handled by the reconciler tree walk;\n// `ref` and `key` are React-internal. Everything else is forwarded as a\n// remote property OR an event listener. Convention: any prop starting with\n// `on` followed by an uppercase letter is treated as an event listener.\n\nfunction isEventListenerProp(key: string): boolean {\n return key.length > 2 && key.startsWith(\"on\") && key[2] >= \"A\" && key[2] <= \"Z\";\n}\n\nfunction eventNameFromProp(propName: string): string {\n // onClick → click. The host's RemoteReceiver expects lowercase event names.\n return propName.slice(2).toLowerCase();\n}\n\nfunction isReservedProp(key: string): boolean {\n return key === \"children\" || key === \"key\" || key === \"ref\";\n}\n\nfunction classifyProps(props: Record<string, unknown>): {\n properties: Record<string, unknown>;\n eventListeners: Record<string, (...args: unknown[]) => unknown>;\n} {\n const properties: Record<string, unknown> = {};\n const eventListeners: Record<string, (...args: unknown[]) => unknown> = {};\n for (const key of Object.keys(props)) {\n if (isReservedProp(key)) {\n continue;\n }\n const value = props[key];\n if (isEventListenerProp(key) && typeof value === \"function\") {\n eventListeners[eventNameFromProp(key)] = value as (...args: unknown[]) => unknown;\n } else if (value !== undefined) {\n properties[key] = value;\n }\n }\n return { properties, eventListeners };\n}\n\n// ── HostConfig factory ─────────────────────────────────────────────\n\n/**\n * Build the react-reconciler instance bound to the supplied `RemoteConnection`.\n * Every mutation the reconciler applies translates into a single\n * `connection.mutate([record])` call; the connection forwards the record over\n * the `MessagePort` set up by `createRemoteRoot`.\n */\nexport function createReactReconciler(connection: RemoteConnection): {\n reconciler: ReactReconciler.Reconciler<\n RemoteParent,\n RemoteElementInstance,\n RemoteTextInstance,\n never,\n RemoteElementInstance\n >;\n createContainer: () => RemoteRootContainer;\n} {\n const reconciler = ReactReconciler<\n string, // type\n Record<string, unknown>, // props\n RemoteParent, // container\n RemoteElementInstance, // instance\n RemoteTextInstance, // text instance\n never, // suspense instance\n never, // hydratable instance\n RemoteElementInstance, // public instance (returned from ref)\n object, // host context\n string[], // update payload (list of changed prop names)\n never, // child set (persistent mode only)\n ReturnType<typeof setTimeout>, // timeout handle\n -1 // no timeout sentinel\n >({\n supportsMutation: true,\n supportsPersistence: false,\n supportsHydration: false,\n isPrimaryRenderer: true,\n noTimeout: -1,\n scheduleTimeout: setTimeout,\n cancelTimeout: clearTimeout,\n getCurrentEventPriority: () => DefaultEventPriority,\n getRootHostContext: () => ({}),\n getChildHostContext: () => ({}),\n prepareForCommit: () => null,\n resetAfterCommit: () => {},\n preparePortalMount: () => {},\n shouldSetTextContent: (_type, props) =>\n typeof props.children === \"string\" || typeof props.children === \"number\",\n getPublicInstance: (instance) => instance as RemoteElementInstance,\n clearContainer: (container) => {\n // Remove every direct child from the root. The host receiver mirrors\n // each removal on its side.\n while (container.children.length > 0) {\n connection.mutate([[MUTATION_TYPE_REMOVE_CHILD, container.id, 0]]);\n container.children.shift();\n }\n },\n\n // ── createInstance / createTextInstance ────────────────────────\n createInstance: (type, props): RemoteElementInstance => {\n const { properties, eventListeners } = classifyProps(props);\n return {\n id: newId(),\n kind: \"element\",\n type,\n properties,\n eventListeners,\n children: [],\n parent: null,\n };\n },\n createTextInstance: (text): RemoteTextInstance => ({\n id: newId(),\n kind: \"text\",\n text,\n parent: null,\n }),\n\n // ── Initial mount: build the subtree before attaching to root ──\n appendInitialChild: (parent, child) => {\n parent.children.push(child);\n child.parent = parent;\n },\n finalizeInitialChildren: () => false,\n\n // ── Container-level mutations (root attach/detach) ─────────────\n appendChildToContainer: (container, child) => {\n const index = container.children.length;\n container.children.push(child);\n child.parent = container;\n connection.mutate([\n [MUTATION_TYPE_INSERT_CHILD, container.id, serialize(child), index],\n ]);\n },\n removeChildFromContainer: (container, child) => {\n const index = indexInParent(container, child);\n if (index < 0) {\n return;\n }\n container.children.splice(index, 1);\n child.parent = null;\n connection.mutate([[MUTATION_TYPE_REMOVE_CHILD, container.id, index]]);\n },\n insertInContainerBefore: (container, child, beforeChild) => {\n const beforeIndex = indexInParent(container, beforeChild);\n const insertAt = beforeIndex < 0 ? container.children.length : beforeIndex;\n container.children.splice(insertAt, 0, child);\n child.parent = container;\n connection.mutate([\n [MUTATION_TYPE_INSERT_CHILD, container.id, serialize(child), insertAt],\n ]);\n },\n\n // ── Sibling-level mutations (incremental tree updates) ─────────\n appendChild: (parent, child) => {\n const index = parent.children.length;\n parent.children.push(child);\n child.parent = parent;\n connection.mutate([\n [MUTATION_TYPE_INSERT_CHILD, parent.id, serialize(child), index],\n ]);\n },\n removeChild: (parent, child) => {\n const index = indexInParent(parent, child);\n if (index < 0) {\n return;\n }\n parent.children.splice(index, 1);\n child.parent = null;\n connection.mutate([[MUTATION_TYPE_REMOVE_CHILD, parent.id, index]]);\n },\n insertBefore: (parent, child, beforeChild) => {\n const beforeIndex = indexInParent(parent, beforeChild);\n const insertAt = beforeIndex < 0 ? parent.children.length : beforeIndex;\n parent.children.splice(insertAt, 0, child);\n child.parent = parent;\n connection.mutate([\n [MUTATION_TYPE_INSERT_CHILD, parent.id, serialize(child), insertAt],\n ]);\n },\n\n // ── Update path ────────────────────────────────────────────────\n prepareUpdate: (_instance, _type, oldProps, newProps): string[] | null => {\n const changed: string[] = [];\n const allKeys = new Set<string>([\n ...Object.keys(oldProps),\n ...Object.keys(newProps),\n ]);\n for (const key of allKeys) {\n if (isReservedProp(key)) {\n continue;\n }\n if (oldProps[key] !== newProps[key]) {\n changed.push(key);\n }\n }\n return changed.length > 0 ? changed : null;\n },\n commitUpdate: (instance, updatePayload, _type, _oldProps, newProps) => {\n if (updatePayload === null) {\n return;\n }\n for (const key of updatePayload) {\n const value = newProps[key];\n if (isEventListenerProp(key) && (typeof value === \"function\" || value === undefined)) {\n const eventName = eventNameFromProp(key);\n if (typeof value === \"function\") {\n instance.eventListeners[eventName] = value as (...args: unknown[]) => unknown;\n } else {\n delete instance.eventListeners[eventName];\n }\n // Functions can't cross a MessagePort via structured clone, so the\n // wire payload only signals whether the listener is now present or\n // cleared — `true` for \"listener exists, wire it on the host once\n // the call channel lands\", `null` for \"listener removed\". See the\n // serialize() comment for the broader Phase 1 limitation.\n connection.mutate([\n [\n MUTATION_TYPE_UPDATE_PROPERTY,\n instance.id,\n eventName,\n typeof value === \"function\" ? true : null,\n 3 /* event listener */,\n ],\n ]);\n } else {\n if (value === undefined) {\n delete instance.properties[key];\n } else {\n instance.properties[key] = value;\n }\n connection.mutate([\n [MUTATION_TYPE_UPDATE_PROPERTY, instance.id, key, value],\n ]);\n }\n }\n },\n commitTextUpdate: (textInstance, _oldText, newText) => {\n textInstance.text = newText;\n connection.mutate([[MUTATION_TYPE_UPDATE_TEXT, textInstance.id, newText]]);\n },\n\n // ── No-op methods required by the HostConfig contract ──────────\n detachDeletedInstance: () => {},\n beforeActiveInstanceBlur: () => {},\n afterActiveInstanceBlur: () => {},\n prepareScopeUpdate: () => {},\n getInstanceFromScope: () => null,\n getInstanceFromNode: () => null,\n\n // Microtask scheduling — use the platform's default queueing.\n supportsMicrotasks: true,\n scheduleMicrotask:\n typeof queueMicrotask === \"function\"\n ? queueMicrotask\n : (callback) => Promise.resolve().then(callback),\n });\n\n function createContainer(): RemoteRootContainer {\n return { id: ROOT_ID, kind: \"root\", children: [], connection };\n }\n\n return { reconciler, createContainer };\n}\n\nexport { ConcurrentRoot, LegacyRoot };\nexport type { RemoteRootContainer, RemoteElementInstance, RemoteTextInstance };\n","/**\n * Contract B (worker remote-runtime) plugin-side React root.\n *\n * # The problem this solves\n *\n * A Contract B plugin runs in a sandboxed Web Worker — no `document`, no\n * `window`, no DOM. The host owns rendering: the worker constructs a\n * `RemoteElement` tree via `@remote-dom/core`, mutations forward over a\n * `MessagePort`, the host receives them and commits them to a real React tree\n * (see `coreconnect-web/src/extensions/runtime/WorkerSurfaceMount.tsx` for the\n * receiver side).\n *\n * Until now plugin authors had to hand-author the `RemoteElement` construction\n * + mutation forwarding manually. `@remote-dom/react` ships only the host-side\n * primitives (`createRemoteComponent`, `RemoteRootRenderer`, etc.) — there is\n * no worker-side React reconciler in the package. This helper provides one.\n *\n * # What this is\n *\n * The public surface (`createRemoteRoot(port, options)`) plus a working\n * `react-reconciler` HostConfig that commits to a Remote DOM tree and\n * forwards mutation records over the `MessagePort` to the host receiver.\n * Authors call `root.render(<App />)` and the host's `WorkerSurfaceMount`\n * sees the result.\n *\n * # What's NOT plumbed yet (Phase 1 limitation)\n *\n * Event-listener round-trip. The host transport currently has no\n * `ethisys:remotedom:call` channel — `WorkerRemoteDomTransport` only\n * forwards `ethisys:remotedom` payloads from worker → host, never the\n * other direction. So a worker-side `onClick={() => ...}` is **registered\n * locally** but the host can't call it. The reconciler retains every\n * listener on its in-memory `RemoteElementInstance` so the wiring is ready\n * the moment the call channel lands; until then, plugin authors should\n * keep interactive surfaces on Contract A.\n *\n * # The API\n *\n * ```ts\n * import { createRemoteRoot } from \"@ethisyscore/extension-runtime/plugin\";\n *\n * export async function activate(port: MessagePort): Promise<void> {\n * const root = createRemoteRoot(port);\n * root.render(<App />);\n * }\n * ```\n *\n * `<App />` is plain React. Any component shipped by the host's frozen\n * import-map allowlist (the closed Contract B primitive vocabulary —\n * `Button`, `DataTable`, `Form`, `Card`, `Tabs`, `Select`, `Alert`, etc.)\n * renders. The reconciler walks the React tree and commits to a\n * `RemoteRootElement`; mutation records forward over the port; the host's\n * `RemoteReceiver` commits the result into the real React tree.\n *\n * # Wire shape\n *\n * Every reconciler mutation is posted as\n * `{ type: \"ethisys:remotedom\", payload: RemoteMutationRecord[] }` to match\n * `WorkerRemoteDomTransport`'s `RemoteDomMessage` contract — the host\n * extracts `payload` and feeds it straight into `receiver.mutate(records)`.\n * `BatchingRemoteConnection` (controlled via `options.batchMutations`)\n * collapses contiguous mutations into a single port post per commit.\n */\nimport type { RemoteConnection, RemoteMutationRecord } from \"@remote-dom/core\";\nimport { BatchingRemoteConnection } from \"@remote-dom/core/elements\";\nimport type { ReactNode } from \"react\";\nimport {\n createReactReconciler,\n LegacyRoot,\n type RemoteRootContainer,\n} from \"./reconciler\";\n\n/**\n * Options for {@link createRemoteRoot}. Reserved for forward compatibility —\n * Phase 1 ships with zero required options. Adding fields here is additive;\n * removing them is a breaking change.\n */\nexport interface CreateRemoteRootOptions\n{\n /**\n * When supplied, the reconciler batches contiguous mutations into a single\n * `port.postMessage` rather than firing one per mutation. Default `true`\n * — measurably reduces host-side commit cost on the first render of a\n * non-trivial tree.\n */\n batchMutations?: boolean;\n\n /**\n * Override the connection factory. Reserved for tests; production callers\n * never pass this. The factory's contract is \"build a RemoteConnection\n * that forwards mutations over the supplied port\"; the default uses\n * `createRemoteConnection` from `@remote-dom/core`.\n */\n connectionFactory?: (port: MessagePort) => RemoteConnection;\n}\n\n/**\n * Plugin-side React root. Mirrors the shape of `ReactDOMClient.Root` so\n * authors familiar with `createRoot().render(...)` find the same API on the\n * worker side.\n */\nexport interface RemoteRoot\n{\n /**\n * Render a React element tree against the worker's `RemoteRootElement`.\n * The reconciler commits to the root, the mutation observer forwards\n * mutations over the port, the host re-renders. Idempotent — calling\n * `render` twice with the same element is fine; the reconciler dedupes.\n */\n render(element: ReactNode): void;\n\n /**\n * Tear down the reconciled tree and stop forwarding mutations. Authors\n * should call this from a `Symbol.dispose` or equivalent when the worker\n * is shutting down — leaking the reconciler holds the `MessagePort` open\n * and prevents the worker from being collected.\n */\n unmount(): void;\n}\n\n/**\n * Construct a plugin-side React root that commits to a `RemoteRootElement`\n * and forwards mutations over the supplied `MessagePort`.\n *\n * **API stability:** the function signature is stable for Phase 1. The\n * options bag is forward-compatible (additive only).\n *\n * **Implementation status:** the connection + root construction lands in this\n * commit. The `react-reconciler` `HostConfig` is a scaffold — `render()`\n * throws a structured error directing authors to the W1A tracking issue.\n * Authors should treat this commit as \"the API is locked, the reconciler is\n * being authored.\" See follow-on commits on the `feature/contract-b-create-remote-root-w1a`\n * branch.\n */\nexport function createRemoteRoot(\n port: MessagePort,\n options: CreateRemoteRootOptions = {},\n): RemoteRoot\n{\n if (port === undefined || port === null)\n {\n throw new TypeError(\n \"[createRemoteRoot] `port` is required. Pass the MessagePort the host transferred via the worker's `activate(port)` entry point.\",\n );\n }\n\n // Build the connection that forwards Remote DOM mutations over the port.\n // The default factory uses `@remote-dom/core`'s `createRemoteConnection`;\n // tests inject their own factory via `options.connectionFactory`.\n const baseConnection = (options.connectionFactory ?? defaultConnectionFactory)(port);\n\n const connection: RemoteConnection = options.batchMutations === false\n ? baseConnection\n : new BatchingRemoteConnection(baseConnection);\n\n // W1A — lazy reconciler + container construction. The reconciler is built\n // once on first render(); subsequent calls reuse the same container so React\n // commits behave like ReactDOM.createRoot(...).render(...) — call render\n // multiple times to update; call unmount to tear down.\n const { reconciler, createContainer } = createReactReconciler(connection);\n let container: RemoteRootContainer | null = null;\n let fiberRoot: ReturnType<typeof reconciler.createContainer> | null = null;\n\n return {\n render(element: ReactNode): void\n {\n if (container === null)\n {\n container = createContainer();\n fiberRoot = reconciler.createContainer(\n container,\n LegacyRoot,\n null, // hydration callbacks\n false, // isStrictMode\n null, // concurrentUpdatesByDefaultOverride\n \"\", // identifierPrefix\n (error: Error) =>\n {\n // The host's SurfaceErrorBoundary catches render-time\n // failures via the connection's call() path; mirroring\n // them locally as a console.error is the best we can do\n // from inside the worker.\n // eslint-disable-next-line no-console -- worker console is pumped to the host logger.\n console.error(\"[createRemoteRoot] render error\", error);\n },\n null, // transitionCallbacks\n );\n }\n reconciler.updateContainer(element, fiberRoot!, null, null);\n },\n unmount(): void\n {\n if (fiberRoot !== null)\n {\n reconciler.updateContainer(null, fiberRoot, null, null);\n fiberRoot = null;\n container = null;\n }\n // The connection itself does NOT close the port — plugins may have\n // side-channel consumers. Authors that want a hard tear-down call\n // `port.close()` themselves after unmount().\n },\n };\n}\n\n// ── Internals ──────────────────────────────────────────────────────────\n\n/**\n * Default factory: build a `RemoteConnection` that posts mutation records\n * as the `payload` of a single `ethisys:remotedom` port message — the\n * wire shape `WorkerRemoteDomTransport`'s `RemoteDomMessage` declares\n * (see `host/worker/transport.ts`'s `handlePortMessage`: it forwards\n * `(message as RemoteDomMessage).payload` straight into the host's\n * `RemoteReceiver.mutate(records)` call).\n *\n * Going through `createRemoteConnection` (which fires per-op callbacks)\n * was the wrong abstraction for this wire — the host expects the raw\n * record list under `payload`, not bespoke `op`-suffixed envelopes. By\n * implementing the connection directly we hand the reconciler's\n * mutation records straight to the host receiver without translation.\n *\n * Wrapping in `BatchingRemoteConnection` (controlled via\n * `options.batchMutations`) collapses contiguous mutation calls into a\n * single `port.postMessage` payload, which is the difference between \"one\n * postMessage per appended child\" and \"one postMessage per React commit\"\n * — measurably cheaper for the first paint of a non-trivial tree.\n */\nfunction defaultConnectionFactory(port: MessagePort): RemoteConnection\n{\n return {\n mutate(records: readonly RemoteMutationRecord[]): void\n {\n // Snapshot to a plain array so the host receiver isn't handed a\n // reference into the reconciler's internal buffer (the BatchingRemoteConnection\n // wrapper recycles its own array between flushes).\n port.postMessage({ type: \"ethisys:remotedom\", payload: records.slice() });\n },\n call(_id, _method, ..._args): unknown\n {\n // Worker → host method invocation. Reserved for the future\n // `ethisys:remotedom:call` channel — `WorkerRemoteDomTransport`\n // doesn't yet handle a `call`-shaped reply path, so event-\n // listener round-trip is still on the Phase 1 follow-on list\n // (see this file's top-of-file \"What's NOT plumbed yet\" note).\n return undefined;\n },\n };\n}\n\n","/**\n * W1B — MessagePort-backed McpTransport for Contract B (worker remote-runtime)\n * plugins.\n *\n * The plugin-side React hooks (`useMcpResource`, `useMcpTool`) consume an\n * {@link McpTransport} — an abstraction over the host call. Contract A\n * (host-rendered) plugins pick up the host-injected transport via\n * `ExtensionRuntimeProvider`. Contract B plugins run in a Web Worker with\n * no shared object surface — the only channel is the `MessagePort` the\n * host transferred via `activate(port)`. This helper bridges the two\n * worlds: it exposes the {@link McpTransport} contract on the worker side\n * and serialises every call into a request/response envelope over the\n * port.\n *\n * # The protocol on the wire\n *\n * The wire shape mirrors `WorkerRemoteDomTransport` (in `host/worker/transport.ts`)\n * one-for-one — that transport is the host receiver and decides what a \"well-\n * formed\" message looks like. Two request shapes, two `:result`-suffixed reply\n * shapes, one abort envelope. Each call mints a fresh request id (`req-{n}`).\n *\n * ```jsonc\n * // worker → host\n * { type: \"ethisys:mcp:getResource\", id: \"req-3\", uri: \"tickets://home\" }\n * { type: \"ethisys:mcp:invokeTool\", id: \"req-4\", name: \"tickets:open\", args: { ... } }\n *\n * // host → worker (matching id, suffixed type)\n * { type: \"ethisys:mcp:getResource:result\", id: \"req-3\", ok: true, data: { uri, data } }\n * { type: \"ethisys:mcp:invokeTool:result\", id: \"req-4\", ok: false, error: \"...\" }\n * ```\n *\n * Requests honour the optional `AbortSignal`. On abort, the transport posts\n * a `{ type: \"ethisys:mcp:abort\", id }` envelope so the host can cancel\n * in-flight work, then rejects the pending promise with an `AbortError`-shaped\n * `Error` so the consuming hooks see the same shape as native fetch cancellation.\n *\n * # Authoring shape\n *\n * ```ts\n * export async function activate(port: MessagePort): Promise<void> {\n * const transport = createPortMcpTransport(port);\n * const root = createRemoteRoot(port);\n * root.render(\n * <ExtensionRuntimeProvider transport={transport}>\n * <App />\n * </ExtensionRuntimeProvider>,\n * );\n * }\n * ```\n *\n * `<App />` uses `useMcpResource` / `useMcpTool` as it would on the host\n * side; the transport translates each call into the port envelope.\n */\nimport type { McpTransport } from \"./transport\";\n\n/**\n * Options for {@link createPortMcpTransport}. Reserved for forward\n * compatibility — the public surface is empty in Phase 1.\n */\nexport interface CreatePortMcpTransportOptions\n{\n /**\n * Override the request-id generator. Reserved for tests so they can\n * make request ids deterministic. Production callers never pass this.\n */\n requestIdFactory?: () => string;\n\n /**\n * Override the port's `addEventListener` / `removeEventListener` /\n * `postMessage` triple. Reserved for tests so the transport can be\n * exercised without instantiating a real MessageChannel.\n */\n portShimForTests?: PortShim;\n}\n\n/**\n * Minimal subset of the MessagePort surface the transport actually uses.\n * Exposed so tests can construct a polyfill without faking the full\n * MessagePort.\n */\nexport interface PortShim\n{\n addEventListener(\n type: \"message\",\n listener: (event: { data: unknown }) => void,\n ): void;\n removeEventListener(\n type: \"message\",\n listener: (event: { data: unknown }) => void,\n ): void;\n postMessage(value: unknown): void;\n}\n\n// ── Wire-shape constants ────────────────────────────────────────────\n//\n// These four strings are the contract with `WorkerRemoteDomTransport`. Any\n// rename here breaks the host receiver silently — the unknown message hits\n// the host's default branch and is dropped. Keep these in sync with\n// `host/worker/transport.ts`'s `handlePortMessage` switch / result-type\n// strings.\nconst WIRE_INVOKE_TOOL_REQUEST = \"ethisys:mcp:invokeTool\";\nconst WIRE_INVOKE_TOOL_RESULT = \"ethisys:mcp:invokeTool:result\";\nconst WIRE_GET_RESOURCE_REQUEST = \"ethisys:mcp:getResource\";\nconst WIRE_GET_RESOURCE_RESULT = \"ethisys:mcp:getResource:result\";\nconst WIRE_ABORT = \"ethisys:mcp:abort\";\n\ntype McpResultType = typeof WIRE_INVOKE_TOOL_RESULT | typeof WIRE_GET_RESOURCE_RESULT;\n\ninterface McpResultEnvelope\n{\n type: McpResultType;\n id: string;\n ok?: boolean;\n error?: string;\n data?: unknown;\n}\n\nfunction isMcpResultEnvelope(value: unknown): value is McpResultEnvelope\n{\n if (value === null || typeof value !== \"object\")\n {\n return false;\n }\n const v = value as { type?: unknown; id?: unknown };\n return (v.type === WIRE_INVOKE_TOOL_RESULT || v.type === WIRE_GET_RESOURCE_RESULT)\n && typeof v.id === \"string\";\n}\n\n/**\n * Construct an {@link McpTransport} backed by a MessagePort.\n *\n * @param port The host-transferred MessagePort for the worker surface.\n * @param options Reserved for forward compatibility / test injection.\n *\n * @returns A transport implementation honouring the {@link McpTransport}\n * contract — fetch a resource, invoke a tool, observe abort\n * signals, settle the promise on the host's reply envelope.\n */\nexport function createPortMcpTransport(\n port: MessagePort | PortShim,\n options: CreatePortMcpTransportOptions = {},\n): McpTransport\n{\n if (port === undefined || port === null)\n {\n throw new TypeError(\n \"[createPortMcpTransport] `port` is required. Pass the MessagePort the host transferred via the worker's `activate(port)` entry point.\",\n );\n }\n\n const shim: PortShim = options.portShimForTests ?? port as PortShim;\n const factory = options.requestIdFactory ?? defaultRequestIdFactory();\n\n type Resolver = {\n resolve: (value: unknown) => void;\n reject: (reason: unknown) => void;\n };\n const pending = new Map<string, Resolver>();\n\n function onMessage(event: { data: unknown }): void\n {\n if (!isMcpResultEnvelope(event.data))\n {\n return;\n }\n const reply = event.data;\n const resolver = pending.get(reply.id);\n if (resolver === undefined)\n {\n return;\n }\n pending.delete(reply.id);\n if (reply.ok === true)\n {\n // Host posts the payload under `data` (matching\n // `WorkerRemoteDomTransport.safePostMessage`). For getResource\n // calls the data is the resource body; for invokeTool calls it\n // is the tool's return value.\n resolver.resolve(reply.data);\n }\n else\n {\n const error = new Error(\n typeof reply.error === \"string\" ? reply.error : \"Unknown host error\",\n );\n error.name = \"McpHostError\";\n resolver.reject(error);\n }\n }\n\n shim.addEventListener(\"message\", onMessage);\n // MessagePort.addEventListener doesn't auto-start the port — without an\n // explicit `start()`, the message queue stays paused and the host's\n // replies never reach `onMessage`. This is a no-op on plain\n // EventTarget-shaped shims used in tests (the type guard guarantees\n // safety) but is required on real MessagePort instances.\n const realPort = port as Partial<MessagePort>;\n if (!options.portShimForTests && typeof realPort.start === \"function\")\n {\n realPort.start();\n }\n\n function send(\n requestType: typeof WIRE_INVOKE_TOOL_REQUEST | typeof WIRE_GET_RESOURCE_REQUEST,\n body: Record<string, unknown>,\n signal?: AbortSignal,\n ): Promise<unknown>\n {\n const id = factory();\n return new Promise<unknown>((resolve, reject) =>\n {\n if (signal?.aborted === true)\n {\n reject(abortError());\n return;\n }\n pending.set(id, { resolve, reject });\n\n const onAbort = (): void =>\n {\n if (!pending.has(id))\n {\n return;\n }\n pending.delete(id);\n shim.postMessage({ type: WIRE_ABORT, id });\n reject(abortError());\n };\n signal?.addEventListener(\"abort\", onAbort, { once: true });\n\n shim.postMessage({ type: requestType, id, ...body });\n });\n }\n\n return {\n async getResource<T>(uri: string, signal?: AbortSignal): Promise<{ uri: string; data: T }>\n {\n // Host sends only the resource body under `data`. Reconstruct the\n // `{ uri, data }` envelope the McpTransport contract returns —\n // `uri` is round-tripped from the request because the resolver\n // only sees the reply.\n const data = await send(WIRE_GET_RESOURCE_REQUEST, { uri }, signal);\n return { uri, data: data as T };\n },\n async invokeTool<TReq, TRes>(name: string, args: TReq, signal?: AbortSignal): Promise<TRes>\n {\n const data = await send(WIRE_INVOKE_TOOL_REQUEST, { name, args: args as unknown }, signal);\n return data as TRes;\n },\n };\n}\n\nfunction defaultRequestIdFactory(): () => string\n{\n let counter = 0;\n return (): string =>\n {\n counter += 1;\n return `req-${counter}`;\n };\n}\n\nfunction abortError(): Error\n{\n const e = new Error(\"Aborted\");\n e.name = \"AbortError\";\n return e;\n}\n","/**\n * Wire-shape constants and type guards for host→plugin bridge push messages\n * (WI 4858 sub-plan 2). These types ride the existing MessagePort channel\n * alongside the `ethisys:mcp:*` and `ethisys:remotedom` envelopes — the\n * `type` discriminant keeps them fully separate at the dispatch site.\n *\n * The host posts bridge pushes through `WorkerRemoteDomTransport.hostPort`;\n * the plugin side reads them in `createPortBridgeClient` (plugin-ui package).\n * In-realm (Tier T) plugins use `InMemoryBridgeTransport` which calls the\n * subscriber callbacks directly — no serialisation needed.\n */\n\n// ── Type constants ───────────────────────────────────────────────────────────\n\nexport const BRIDGE_PUSH_THEME = \"ethisys:bridge:theme\" as const;\nexport const BRIDGE_PUSH_LOCALE = \"ethisys:bridge:locale\" as const;\nexport const BRIDGE_PUSH_DENSITY = \"ethisys:bridge:density\" as const;\nexport const BRIDGE_PUSH_A11Y = \"ethisys:bridge:a11y\" as const;\nexport const BRIDGE_NAV_PUSH = \"ethisys:bridge:nav\" as const;\nexport const BRIDGE_CHROME_REQUEST = \"ethisys:bridge:chrome:request\" as const;\nexport const BRIDGE_CHROME_RESPONSE = \"ethisys:bridge:chrome:response\" as const;\nexport const BRIDGE_SESSION_TOKEN_PUSH = \"ethisys:bridge:token\" as const;\nexport const BRIDGE_LIFECYCLE_EVENT = \"ethisys:bridge:lifecycle\" as const;\nexport const BRIDGE_A11Y_ANNOUNCE = \"ethisys:bridge:a11y:announce\" as const;\n\n// ── Envelope shapes ──────────────────────────────────────────────────────────\n\n/** Theme push: host → plugin whenever the host theme changes. */\nexport interface BridgePushThemeEnvelope {\n readonly type: typeof BRIDGE_PUSH_THEME;\n /** \"light\" | \"dark\" | \"high-contrast\" */\n readonly mode: string;\n /** Flat design-token map (CSS-variable-name → value). May be empty. */\n readonly tokens: Readonly<Record<string, string>>;\n}\n\n/** Locale push: host → plugin whenever the active locale changes. */\nexport interface BridgePushLocaleEnvelope {\n readonly type: typeof BRIDGE_PUSH_LOCALE;\n /** BCP 47 tag, e.g. \"en-GB\". */\n readonly locale: string;\n /** \"ltr\" | \"rtl\" */\n readonly dir: \"ltr\" | \"rtl\";\n}\n\n/** Density push: host → plugin when the UI density preference changes. */\nexport interface BridgePushDensityEnvelope {\n readonly type: typeof BRIDGE_PUSH_DENSITY;\n /** \"comfortable\" | \"compact\" */\n readonly density: string;\n}\n\n/** A11y push: host → plugin when accessibility prefs change. */\nexport interface BridgePushA11yEnvelope {\n readonly type: typeof BRIDGE_PUSH_A11Y;\n readonly reducedMotion: boolean;\n readonly highContrast: boolean;\n}\n\n/** Nav push: host → plugin when the SPA location changes. */\nexport interface BridgeNavPushEnvelope {\n readonly type: typeof BRIDGE_NAV_PUSH;\n /** Current SPA path (pathname + search). */\n readonly path: string;\n /** `window.history.length` at the time of push. */\n readonly historyLength: number;\n}\n\n/** Plugin → host: request a chrome action (e.g. toast, modal). */\nexport interface BridgeChromeRequestEnvelope {\n readonly type: typeof BRIDGE_CHROME_REQUEST;\n /** Correlation id — matched against the response. */\n readonly id: string;\n /** \"toast\" | \"confirm\" | \"openUrl\" */\n readonly action: string;\n readonly payload: Readonly<Record<string, unknown>>;\n}\n\n/** Host → plugin: response to a chrome request. */\nexport interface BridgeChromeResponseEnvelope {\n readonly type: typeof BRIDGE_CHROME_RESPONSE;\n readonly id: string;\n readonly ok: boolean;\n readonly result?: unknown;\n readonly error?: string;\n}\n\n/** Host → plugin: push a short-lived frontend-session token. */\nexport interface BridgeSessionTokenPushEnvelope {\n readonly type: typeof BRIDGE_SESSION_TOKEN_PUSH;\n /** Opaque JWT string — audience-restricted to the plugin's own backend. */\n readonly token: string;\n /** Absolute epoch-ms at which the token expires. Refresh fires 30 s before. */\n readonly expiresAtMs: number;\n}\n\n/** Host ↔ plugin lifecycle event. */\nexport type BridgeLifecyclePhase = \"load\" | \"ready\" | \"error\" | \"unload\";\n\nexport interface BridgeLifecycleEventEnvelope {\n readonly type: typeof BRIDGE_LIFECYCLE_EVENT;\n readonly phase: BridgeLifecyclePhase;\n /** Present when phase === \"error\". */\n readonly message?: string;\n}\n\n/** Plugin → host: a11y live-region announcement request. */\nexport interface BridgeA11yAnnounceEnvelope {\n readonly type: typeof BRIDGE_A11Y_ANNOUNCE;\n readonly message: string;\n /** \"polite\" | \"assertive\" */\n readonly politeness: \"polite\" | \"assertive\";\n}\n\n// ── Type guards ──────────────────────────────────────────────────────────────\n\nfunction isObj(v: unknown): v is Record<string, unknown> {\n return v !== null && typeof v === \"object\";\n}\n\nexport function isBridgePushTheme(v: unknown): v is BridgePushThemeEnvelope {\n return isObj(v) && v[\"type\"] === BRIDGE_PUSH_THEME && typeof v[\"mode\"] === \"string\";\n}\n\nexport function isBridgePushLocale(v: unknown): v is BridgePushLocaleEnvelope {\n return isObj(v) && v[\"type\"] === BRIDGE_PUSH_LOCALE && typeof v[\"locale\"] === \"string\";\n}\n\nexport function isBridgePushDensity(v: unknown): v is BridgePushDensityEnvelope {\n return isObj(v) && v[\"type\"] === BRIDGE_PUSH_DENSITY && typeof v[\"density\"] === \"string\";\n}\n\nexport function isBridgePushA11y(v: unknown): v is BridgePushA11yEnvelope {\n return isObj(v) && v[\"type\"] === BRIDGE_PUSH_A11Y\n && typeof v[\"reducedMotion\"] === \"boolean\"\n && typeof v[\"highContrast\"] === \"boolean\";\n}\n\nexport function isBridgeNavPush(v: unknown): v is BridgeNavPushEnvelope {\n return isObj(v) && v[\"type\"] === BRIDGE_NAV_PUSH && typeof v[\"path\"] === \"string\";\n}\n\nexport function isBridgeChromeRequest(v: unknown): v is BridgeChromeRequestEnvelope {\n return isObj(v) && v[\"type\"] === BRIDGE_CHROME_REQUEST && typeof v[\"id\"] === \"string\";\n}\n\nexport function isBridgeChromeResponse(v: unknown): v is BridgeChromeResponseEnvelope {\n return isObj(v) && v[\"type\"] === BRIDGE_CHROME_RESPONSE && typeof v[\"id\"] === \"string\";\n}\n\nexport function isBridgeSessionTokenPush(v: unknown): v is BridgeSessionTokenPushEnvelope {\n return isObj(v) && v[\"type\"] === BRIDGE_SESSION_TOKEN_PUSH\n && typeof v[\"token\"] === \"string\"\n && typeof v[\"expiresAtMs\"] === \"number\";\n}\n\nexport function isBridgeLifecycleEvent(v: unknown): v is BridgeLifecycleEventEnvelope {\n return isObj(v) && v[\"type\"] === BRIDGE_LIFECYCLE_EVENT && typeof v[\"phase\"] === \"string\";\n}\n\nexport function isBridgeA11yAnnounce(v: unknown): v is BridgeA11yAnnounceEnvelope {\n return isObj(v) && v[\"type\"] === BRIDGE_A11Y_ANNOUNCE && typeof v[\"message\"] === \"string\";\n}\n","/**\n * Plugin-side bridge client for the host ↔ plugin platform contract\n * (WI 4858 sub-plan 2).\n *\n * `createPortBridgeClient` wraps a MessagePort (or an in-realm shim) and\n * exposes typed subscription callbacks for each host push (theme, locale,\n * density, a11y, nav, session token) and typed fire-and-wait calls for\n * chrome requests and a11y live-region announcements.\n *\n * For in-realm (Tier T) plugins, use `InMemoryBridgeTransport` from the\n * mock-host package instead — it calls callbacks synchronously without\n * any serialisation.\n */\nimport {\n BRIDGE_CHROME_REQUEST,\n BRIDGE_A11Y_ANNOUNCE,\n isBridgePushTheme,\n isBridgePushLocale,\n isBridgePushDensity,\n isBridgePushA11y,\n isBridgeNavPush,\n isBridgeChromeResponse,\n isBridgeSessionTokenPush,\n type BridgePushThemeEnvelope,\n type BridgePushLocaleEnvelope,\n type BridgePushDensityEnvelope,\n type BridgePushA11yEnvelope,\n type BridgeNavPushEnvelope,\n type BridgeSessionTokenPushEnvelope,\n} from \"../host/worker/bridge-envelopes\";\n\n// ── Subscriber payload types (strips the `type` discriminant) ────────────────\n\nexport type ThemePayload = Omit<BridgePushThemeEnvelope, \"type\">;\nexport type LocalePayload = Omit<BridgePushLocaleEnvelope, \"type\">;\nexport type DensityPayload = Omit<BridgePushDensityEnvelope, \"type\">;\nexport type A11yPayload = Omit<BridgePushA11yEnvelope, \"type\">;\nexport type NavPayload = Omit<BridgeNavPushEnvelope, \"type\">;\nexport type SessionTokenPayload = Omit<BridgeSessionTokenPushEnvelope, \"type\">;\n\n// ── Port shim (test injection) ───────────────────────────────────────────────\n\n/**\n * Minimal port surface `createPortBridgeClient` actually uses. Matches\n * `PortShim` in `createPortMcpTransport` — same test-injection pattern.\n */\nexport interface BridgePortShim {\n onmessage: ((ev: { data: unknown }) => void) | null;\n postMessage(msg: unknown): void;\n}\n\n// ── Public client interface ──────────────────────────────────────────────────\n\nexport interface PortBridgeClient {\n /** Replace the theme subscriber. Only the latest subscriber is called. */\n onTheme(cb: (payload: ThemePayload) => void): void;\n /** Replace the locale subscriber. */\n onLocale(cb: (payload: LocalePayload) => void): void;\n /** Replace the density subscriber. */\n onDensity(cb: (payload: DensityPayload) => void): void;\n /** Replace the a11y-preferences subscriber. */\n onA11y(cb: (payload: A11yPayload) => void): void;\n /** Replace the nav-state subscriber. */\n onNav(cb: (payload: NavPayload) => void): void;\n /** Replace the session-token subscriber. */\n onSessionToken(cb: (payload: SessionTokenPayload) => void): void;\n /**\n * Request a host chrome action. Returns the host's result or rejects with\n * the host's error string. Callers should catch and surface gracefully.\n *\n * @param action \"toast\" | \"confirm\" | \"openUrl\"\n * @param payload Action-specific payload.\n */\n requestChrome(action: string, payload: Record<string, unknown>): Promise<unknown>;\n /**\n * Ask the host to make a live-region announcement on behalf of the plugin.\n * Prefers this over writing directly to the DOM so the host can manage\n * ARIA live regions centrally.\n */\n announceA11y(message: string, politeness: \"polite\" | \"assertive\"): void;\n}\n\n// ── Implementation ───────────────────────────────────────────────────────────\n\nlet _requestCounter = 0;\nfunction nextId(): string {\n _requestCounter += 1;\n return `br-${_requestCounter}`;\n}\n\n/**\n * Construct a bridge client backed by a `MessagePort` (or shim).\n *\n * Registers a single `onmessage` handler on the port that dispatches each\n * bridge push to the appropriate subscriber. Unknown message types are\n * silently ignored — the port carries MCP traffic on the same channel and\n * those messages must not trigger an error here.\n */\nexport function createPortBridgeClient(port: BridgePortShim): PortBridgeClient {\n let themeCb: ((p: ThemePayload) => void) | undefined;\n let localeCb: ((p: LocalePayload) => void) | undefined;\n let densityCb: ((p: DensityPayload) => void) | undefined;\n let a11yCb: ((p: A11yPayload) => void) | undefined;\n let navCb: ((p: NavPayload) => void) | undefined;\n let tokenCb: ((p: SessionTokenPayload) => void) | undefined;\n\n type PendingChrome = { resolve: (v: unknown) => void; reject: (e: Error) => void };\n const pending = new Map<string, PendingChrome>();\n\n port.onmessage = (ev: { data: unknown }): void => {\n const msg = ev.data;\n if (isBridgePushTheme(msg)) { themeCb?.({ mode: msg.mode, tokens: msg.tokens }); return; }\n if (isBridgePushLocale(msg)) { localeCb?.({ locale: msg.locale, dir: msg.dir }); return; }\n if (isBridgePushDensity(msg)) { densityCb?.({ density: msg.density }); return; }\n if (isBridgePushA11y(msg)) { a11yCb?.({ reducedMotion: msg.reducedMotion, highContrast: msg.highContrast }); return; }\n if (isBridgeNavPush(msg)) { navCb?.({ path: msg.path, historyLength: msg.historyLength }); return; }\n if (isBridgeSessionTokenPush(msg)) { tokenCb?.({ token: msg.token, expiresAtMs: msg.expiresAtMs }); return; }\n if (isBridgeChromeResponse(msg)) {\n const p = pending.get(msg.id);\n if (p === undefined) { return; }\n pending.delete(msg.id);\n if (msg.ok) { p.resolve(msg.result ?? null); }\n else { p.reject(new Error(typeof msg.error === \"string\" ? msg.error : \"Chrome request failed\")); }\n }\n };\n\n return {\n onTheme(cb) { themeCb = cb; },\n onLocale(cb) { localeCb = cb; },\n onDensity(cb) { densityCb = cb; },\n onA11y(cb) { a11yCb = cb; },\n onNav(cb) { navCb = cb; },\n onSessionToken(cb) { tokenCb = cb; },\n\n requestChrome(action, payload): Promise<unknown> {\n const id = nextId();\n return new Promise<unknown>((resolve, reject) => {\n pending.set(id, { resolve, reject });\n port.postMessage({ type: BRIDGE_CHROME_REQUEST, id, action, payload });\n });\n },\n\n announceA11y(message, politeness): void {\n port.postMessage({ type: BRIDGE_A11Y_ANNOUNCE, message, politeness });\n },\n };\n}\n","import { createContext, useContext } from \"react\";\nimport type { PortBridgeClient } from \"./bridge-client\";\n\n/**\n * React context carrying the plugin's active {@link PortBridgeClient}.\n * Provided by the host mount (WorkerMockHost in dev, real bridge in production)\n * and consumed by `useBridgeTheme`, `useBridgeLocale`, and the `plugin-ui` hooks.\n */\nexport const BridgeClientContext = createContext<PortBridgeClient | null>(null);\n\n/**\n * Returns the bridge client from context, throwing a clear error when missing.\n * Used by the `useBridge*` hooks to fail loudly on misconfiguration.\n */\nexport function useBridgeClient(): PortBridgeClient {\n const client = useContext(BridgeClientContext);\n if (client === null) {\n throw new Error(\n \"No PortBridgeClient available. Wrap your plugin in <BridgeClientProvider> \"\n + \"or ensure the host mount wires a BridgeClientContext.Provider.\",\n );\n }\n return client;\n}\n","import { useEffect, useState } from \"react\";\nimport { useBridgeClient } from \"./BridgeClientContext\";\nimport type { ThemePayload } from \"./bridge-client\";\n\n/**\n * Subscribe to host theme pushes. Returns the most recently pushed theme,\n * or `undefined` before the first push (e.g. during initial render before\n * the host has sent its first `BRIDGE_PUSH_THEME` message).\n *\n * The hook re-registers with the bridge client if the client identity changes\n * (e.g. on hot-reload of the mock host in dev), keeping state consistent.\n */\nexport function useBridgeTheme(): ThemePayload | undefined {\n const client = useBridgeClient();\n const [theme, setTheme] = useState<ThemePayload | undefined>(undefined);\n\n useEffect(() => {\n client.onTheme((payload) => setTheme(payload));\n // No cleanup needed — `onTheme` replaces the subscriber; unmounting\n // drops the hook's closure reference, preventing stale-state updates.\n }, [client]);\n\n return theme;\n}\n","import { useEffect, useState } from \"react\";\nimport { useBridgeClient } from \"./BridgeClientContext\";\nimport type { LocalePayload } from \"./bridge-client\";\n\n/**\n * Subscribe to host locale pushes. Returns the most recently pushed locale\n * and text direction, or `undefined` before the first push.\n */\nexport function useBridgeLocale(): LocalePayload | undefined {\n const client = useBridgeClient();\n const [locale, setLocale] = useState<LocalePayload | undefined>(undefined);\n\n useEffect(() => {\n client.onLocale((payload) => setLocale(payload));\n }, [client]);\n\n return locale;\n}\n","/**\n * W4A — Bridge-mediated frontend-session token hook (WI 4858 sub-plan 4).\n *\n * # What this does\n * Fetches the audience-restricted FE-session token from the host bridge\n * (resource URI: `\"ethisys:session-token\"`) and manages silent refresh.\n * The token is delivered to this hook; it is NEVER the capability JWT\n * (that stays brokered host-side and never reaches plugin JS).\n *\n * # Refresh policy\n * Refresh fires 30 s before `expiresAtUtc`. The timer is cleared on\n * unmount; no stale async operations survive component teardown.\n *\n * # Transport\n * The hook is transport-agnostic — it accepts any {@link McpTransport}.\n * Pass the context transport in production; a mock in tests.\n *\n * This is the canonical FE-session-token hook; `@ethisyscore/plugin-ui/token`\n * re-exports it so plugin authors take a single dependency on plugin-ui.\n */\nimport { useState, useEffect, useRef, useCallback } from \"react\";\nimport type { McpTransport } from \"./transport\";\n\nconst SESSION_TOKEN_URI = \"ethisys:session-token\";\nconst REFRESH_SKEW_MS = 30_000; // refresh 30 s before expiry\n\ninterface FrontendSessionTokenPayload\n{\n accessToken: string;\n expiresAtUtc: string; // ISO-8601\n jti: string;\n}\n\nexport interface UseFrontendSessionTokenResult\n{\n /** The compact-serialised JWT, or null while loading / on error. */\n token: string | null;\n /** True while the first fetch (or a refresh) is in-flight. */\n isLoading: boolean;\n /** Set when the bridge rejects; null otherwise. */\n error: Error | null;\n}\n\n/**\n * Returns the current FE-session token fetched from the host bridge.\n * Schedules silent refresh 30 s before the token expires.\n *\n * @param transport The {@link McpTransport} to use. Typically the context\n * transport from the extension runtime provider.\n */\nexport function useFrontendSessionToken(\n transport: McpTransport,\n): UseFrontendSessionTokenResult\n{\n const [token, setToken] = useState<string | null>(null);\n const [isLoading, setIsLoading] = useState(true);\n const [error, setError] = useState<Error | null>(null);\n const refreshTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n const mountedRef = useRef(true);\n\n const fetch = useCallback(async (): Promise<void> =>\n {\n if (refreshTimerRef.current !== null)\n {\n clearTimeout(refreshTimerRef.current);\n refreshTimerRef.current = null;\n }\n try\n {\n const { data } = await transport.getResource<FrontendSessionTokenPayload>(\n SESSION_TOKEN_URI,\n );\n\n if (!mountedRef.current)\n {\n return;\n }\n\n setToken(data.accessToken);\n setError(null);\n setIsLoading(false);\n\n // Schedule refresh 30 s before expiry.\n const expiresAtMs = Date.parse(data.expiresAtUtc);\n const refreshIn = expiresAtMs - Date.now() - REFRESH_SKEW_MS;\n if (refreshIn > 0)\n {\n refreshTimerRef.current = setTimeout(() =>\n {\n void fetch();\n }, refreshIn);\n }\n }\n catch (err)\n {\n if (!mountedRef.current)\n {\n return;\n }\n setError(err instanceof Error ? err : new Error(String(err)));\n setToken(null);\n setIsLoading(false);\n }\n }, [transport]);\n\n useEffect(() =>\n {\n mountedRef.current = true;\n setIsLoading(true);\n void fetch();\n\n return (): void =>\n {\n mountedRef.current = false;\n if (refreshTimerRef.current !== null)\n {\n clearTimeout(refreshTimerRef.current);\n }\n };\n }, [fetch]);\n\n return { token, isLoading, error };\n}\n"]}