@assistant-ui/react 0.15.17 → 0.15.19

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.
Files changed (169) hide show
  1. package/README.md +8 -2
  2. package/dist/context/providers/ThreadViewportProvider.js +2 -2
  3. package/dist/context/providers/ThreadViewportProvider.js.map +1 -1
  4. package/dist/hooks/useToolCallElapsed.js.map +1 -1
  5. package/dist/index.d.ts +7 -4
  6. package/dist/index.js +5 -3
  7. package/dist/mcp-apps/McpAppRenderer.d.ts +30 -8
  8. package/dist/mcp-apps/McpAppRenderer.d.ts.map +1 -1
  9. package/dist/mcp-apps/McpAppRenderer.js +91 -47
  10. package/dist/mcp-apps/McpAppRenderer.js.map +1 -1
  11. package/dist/mcp-apps/app-frame.d.ts.map +1 -1
  12. package/dist/mcp-apps/app-frame.js +57 -33
  13. package/dist/mcp-apps/app-frame.js.map +1 -1
  14. package/dist/mcp-apps/bridge.js +9 -4
  15. package/dist/mcp-apps/bridge.js.map +1 -1
  16. package/dist/mcp-apps/index.d.ts +2 -2
  17. package/dist/primitives/assistantModal/AssistantModalRoot.d.ts.map +1 -1
  18. package/dist/primitives/assistantModal/AssistantModalRoot.js +47 -79
  19. package/dist/primitives/assistantModal/AssistantModalRoot.js.map +1 -1
  20. package/dist/primitives/composer/ComposerAttachmentDropzone.d.ts.map +1 -1
  21. package/dist/primitives/composer/ComposerAttachmentDropzone.js +61 -138
  22. package/dist/primitives/composer/ComposerAttachmentDropzone.js.map +1 -1
  23. package/dist/primitives/composer/ComposerInput.js +3 -8
  24. package/dist/primitives/composer/ComposerInput.js.map +1 -1
  25. package/dist/primitives/composer/ComposerInputPluginContext.d.ts +1 -2
  26. package/dist/primitives/composer/ComposerInputPluginContext.d.ts.map +1 -1
  27. package/dist/primitives/composer/ComposerInputPluginContext.js +1 -6
  28. package/dist/primitives/composer/ComposerInputPluginContext.js.map +1 -1
  29. package/dist/primitives/composer/trigger/TriggerPopoverAction.js +46 -15
  30. package/dist/primitives/composer/trigger/TriggerPopoverAction.js.map +1 -1
  31. package/dist/primitives/composer/trigger/TriggerPopoverDirective.js +40 -10
  32. package/dist/primitives/composer/trigger/TriggerPopoverDirective.js.map +1 -1
  33. package/dist/primitives/composer/trigger/matchesTriggerItemQuery.d.ts +6 -0
  34. package/dist/primitives/composer/trigger/matchesTriggerItemQuery.d.ts.map +1 -0
  35. package/dist/primitives/composer/trigger/matchesTriggerItemQuery.js +9 -0
  36. package/dist/primitives/composer/trigger/matchesTriggerItemQuery.js.map +1 -0
  37. package/dist/primitives/composer/trigger/triggerKeyboardResource.d.ts.map +1 -1
  38. package/dist/primitives/composer/trigger/triggerKeyboardResource.js +53 -61
  39. package/dist/primitives/composer/trigger/triggerKeyboardResource.js.map +1 -1
  40. package/dist/primitives/composer/trigger/triggerNavigationResource.d.ts.map +1 -1
  41. package/dist/primitives/composer/trigger/triggerNavigationResource.js +129 -141
  42. package/dist/primitives/composer/trigger/triggerNavigationResource.js.map +1 -1
  43. package/dist/primitives/message/MessageParts.js +2 -14
  44. package/dist/primitives/message/MessageParts.js.map +1 -1
  45. package/dist/primitives/message/MessagePartsGrouped.d.ts +3 -3
  46. package/dist/primitives/message/MessagePartsGrouped.js +2 -2
  47. package/dist/primitives/message/MessagePartsGrouped.js.map +1 -1
  48. package/dist/primitives/messagePart/MessagePartText.d.ts +2 -0
  49. package/dist/primitives/messagePart/MessagePartText.d.ts.map +1 -1
  50. package/dist/primitives/messagePart/MessagePartText.js +13 -36
  51. package/dist/primitives/messagePart/MessagePartText.js.map +1 -1
  52. package/dist/primitives/reasoning/useScrollLock.js +3 -1
  53. package/dist/primitives/reasoning/useScrollLock.js.map +1 -1
  54. package/dist/primitives/thread/useThreadViewportAutoScroll.d.ts.map +1 -1
  55. package/dist/primitives/thread/useThreadViewportAutoScroll.js +3 -3
  56. package/dist/primitives/thread/useThreadViewportAutoScroll.js.map +1 -1
  57. package/dist/sandbox-host/SandboxHost.d.ts.map +1 -1
  58. package/dist/sandbox-host/SandboxHost.js +36 -9
  59. package/dist/sandbox-host/SandboxHost.js.map +1 -1
  60. package/dist/unstable/useLiveCompletionAdapter.js +24 -2
  61. package/dist/unstable/useLiveCompletionAdapter.js.map +1 -1
  62. package/dist/unstable/useMentionAdapter.d.ts +9 -3
  63. package/dist/unstable/useMentionAdapter.d.ts.map +1 -1
  64. package/dist/unstable/useMentionAdapter.js +50 -43
  65. package/dist/unstable/useMentionAdapter.js.map +1 -1
  66. package/dist/unstable/useMessageStallDetection.d.ts +4 -5
  67. package/dist/unstable/useMessageStallDetection.d.ts.map +1 -1
  68. package/dist/unstable/useMessageStallDetection.js +16 -15
  69. package/dist/unstable/useMessageStallDetection.js.map +1 -1
  70. package/dist/unstable/useModelContextSnapshot.d.ts +34 -0
  71. package/dist/unstable/useModelContextSnapshot.d.ts.map +1 -0
  72. package/dist/unstable/useModelContextSnapshot.js +61 -0
  73. package/dist/unstable/useModelContextSnapshot.js.map +1 -0
  74. package/dist/unstable/useSlashCommandAdapter.d.ts.map +1 -1
  75. package/dist/unstable/useSlashCommandAdapter.js +2 -8
  76. package/dist/unstable/useSlashCommandAdapter.js.map +1 -1
  77. package/dist/unstable/webmcp/WebMcpRegistrationResource.d.ts +14 -0
  78. package/dist/unstable/webmcp/WebMcpRegistrationResource.d.ts.map +1 -0
  79. package/dist/unstable/webmcp/WebMcpRegistrationResource.js +85 -0
  80. package/dist/unstable/webmcp/WebMcpRegistrationResource.js.map +1 -0
  81. package/dist/unstable/webmcp/convertTools.d.ts +21 -0
  82. package/dist/unstable/webmcp/convertTools.d.ts.map +1 -0
  83. package/dist/unstable/webmcp/convertTools.js +161 -0
  84. package/dist/unstable/webmcp/convertTools.js.map +1 -0
  85. package/dist/unstable/webmcp/useWebMcpProvider.d.ts +21 -0
  86. package/dist/unstable/webmcp/useWebMcpProvider.d.ts.map +1 -0
  87. package/dist/unstable/webmcp/useWebMcpProvider.js +106 -0
  88. package/dist/unstable/webmcp/useWebMcpProvider.js.map +1 -0
  89. package/dist/unstable/webmcp/webmcp-host.d.ts +39 -0
  90. package/dist/unstable/webmcp/webmcp-host.d.ts.map +1 -0
  91. package/dist/unstable/webmcp/webmcp-host.js +29 -0
  92. package/dist/unstable/webmcp/webmcp-host.js.map +1 -0
  93. package/dist/utils/Primitive.d.ts +10 -2
  94. package/dist/utils/Primitive.d.ts.map +1 -1
  95. package/dist/utils/Primitive.js +25 -6
  96. package/dist/utils/Primitive.js.map +1 -1
  97. package/dist/utils/getSelectionMessageId.d.ts.map +1 -1
  98. package/dist/utils/getSelectionMessageId.js +17 -3
  99. package/dist/utils/getSelectionMessageId.js.map +1 -1
  100. package/package.json +13 -13
  101. package/src/context/providers/ThreadViewportProvider.tsx +2 -2
  102. package/src/hooks/useToolCallElapsed.ts +3 -0
  103. package/src/index.ts +14 -1
  104. package/src/mcp-apps/McpAppRenderer.test.tsx +253 -5
  105. package/src/mcp-apps/McpAppRenderer.tsx +147 -52
  106. package/src/mcp-apps/app-frame.test.tsx +437 -1
  107. package/src/mcp-apps/app-frame.tsx +76 -21
  108. package/src/mcp-apps/bridge.test.ts +98 -0
  109. package/src/mcp-apps/bridge.ts +14 -3
  110. package/src/mcp-apps/index.ts +5 -1
  111. package/src/primitives/assistantModal/AssistantModalRoot.test.tsx +123 -0
  112. package/src/primitives/assistantModal/AssistantModalRoot.tsx +11 -31
  113. package/src/primitives/assistantModal/AssistantModalTrigger.test.tsx +1 -16
  114. package/src/primitives/composer/ComposerAttachmentDropzone.test.tsx +43 -0
  115. package/src/primitives/composer/ComposerAttachmentDropzone.tsx +2 -10
  116. package/src/primitives/composer/ComposerInput.test.tsx +22 -0
  117. package/src/primitives/composer/ComposerInput.tsx +5 -9
  118. package/src/primitives/composer/ComposerInputPluginContext.tsx +0 -10
  119. package/src/primitives/composer/trigger/TriggerPopoverAction.tsx +4 -2
  120. package/src/primitives/composer/trigger/TriggerPopoverBehavior.test.tsx +109 -0
  121. package/src/primitives/composer/trigger/TriggerPopoverDirective.tsx +4 -2
  122. package/src/primitives/composer/trigger/matchesTriggerItemQuery.test.ts +52 -0
  123. package/src/primitives/composer/trigger/matchesTriggerItemQuery.ts +13 -0
  124. package/src/primitives/composer/trigger/triggerKeyboardResource.ts +13 -7
  125. package/src/primitives/composer/trigger/triggerNavigationResource.ts +8 -13
  126. package/src/primitives/message/MessageParts.tsx +1 -21
  127. package/src/primitives/message/MessagePartsGrouped.test.tsx +93 -0
  128. package/src/primitives/message/MessagePartsGrouped.tsx +6 -6
  129. package/src/primitives/messagePart/MessagePartText.test.tsx +69 -0
  130. package/src/primitives/messagePart/MessagePartText.tsx +22 -9
  131. package/src/primitives/reasoning/useScrollLock.test.tsx +129 -0
  132. package/src/primitives/reasoning/useScrollLock.ts +15 -1
  133. package/src/primitives/thread/useThreadViewportAutoScroll.test.tsx +38 -1
  134. package/src/primitives/thread/useThreadViewportAutoScroll.ts +7 -6
  135. package/src/sandbox-host/SandboxHost.test.tsx +160 -2
  136. package/src/sandbox-host/SandboxHost.tsx +50 -10
  137. package/src/tests/MessageParts.rendererOptions.test.tsx +117 -0
  138. package/src/tests/toolCallTiming.test.tsx +55 -1
  139. package/src/unstable/useComposerInputHistory.test.tsx +2 -1
  140. package/src/unstable/useLiveCompletionAdapter.test.tsx +202 -1
  141. package/src/unstable/useLiveCompletionAdapter.ts +38 -8
  142. package/src/unstable/useMentionAdapter.test.tsx +383 -0
  143. package/src/unstable/useMentionAdapter.ts +94 -57
  144. package/src/unstable/useMessageStallDetection.ts +26 -19
  145. package/src/unstable/useModelContextSnapshot.test.tsx +132 -0
  146. package/src/unstable/useModelContextSnapshot.ts +67 -0
  147. package/src/unstable/useSlashCommandAdapter.ts +2 -9
  148. package/src/unstable/webmcp/WebMcpRegistrationResource.ts +92 -0
  149. package/src/unstable/webmcp/__tests__/webmcp.fake.tsx +168 -0
  150. package/src/unstable/webmcp/convertTools.test.ts +553 -0
  151. package/src/unstable/webmcp/convertTools.ts +260 -0
  152. package/src/unstable/webmcp/useWebMcpProvider.test.tsx +466 -0
  153. package/src/unstable/webmcp/useWebMcpProvider.ts +148 -0
  154. package/src/unstable/webmcp/webmcp-host.test.ts +142 -0
  155. package/src/unstable/webmcp/webmcp-host.ts +83 -0
  156. package/src/utils/Primitive.test.tsx +46 -1
  157. package/src/utils/Primitive.tsx +37 -7
  158. package/src/utils/getSelectionMessageId.test.ts +176 -1
  159. package/src/utils/getSelectionMessageId.ts +21 -3
  160. package/dist/utils/invokeCallbackSafely.d.ts +0 -5
  161. package/dist/utils/invokeCallbackSafely.d.ts.map +0 -1
  162. package/dist/utils/invokeCallbackSafely.js +0 -15
  163. package/dist/utils/invokeCallbackSafely.js.map +0 -1
  164. package/dist/utils/useToolArgsFieldStatus.d.ts +0 -19
  165. package/dist/utils/useToolArgsFieldStatus.d.ts.map +0 -1
  166. package/dist/utils/useToolArgsFieldStatus.js +0 -23
  167. package/dist/utils/useToolArgsFieldStatus.js.map +0 -1
  168. package/src/utils/invokeCallbackSafely.ts +0 -11
  169. package/src/utils/useToolArgsFieldStatus.ts +0 -18
@@ -4,18 +4,39 @@ import { SandboxHost } from "../sandbox-host/SandboxHost.js";
4
4
  import { c } from "@assistant-ui/tap/react-shim/compiler-runtime";
5
5
  import { useEffect, useLayoutEffect, useRef } from "@assistant-ui/tap/react-shim";
6
6
  import { jsx } from "react/jsx-runtime";
7
+ import { isRecord } from "@assistant-ui/core/internal";
7
8
  //#region src/mcp-apps/app-frame.tsx
8
9
  const DEFAULT_PRODUCT = "assistant-ui-mcp-app";
9
10
  const INIT_TIMEOUT_MS = 5e3;
10
11
  const DEFAULT_MAX_HEIGHT = 800;
11
- function useBridgeNotify(value, bridgeRef, widgetReadyRef, pendingRef, lastSentRef, notify) {
12
- const $ = c(9);
13
- let t0;
14
- if ($[0] !== bridgeRef || $[1] !== lastSentRef || $[2] !== notify || $[3] !== pendingRef || $[4] !== value || $[5] !== widgetReadyRef) {
15
- t0 = () => {
12
+ const isPlainObject = (value) => {
13
+ if (!isRecord(value)) return false;
14
+ const prototype = Object.getPrototypeOf(value);
15
+ return prototype === null || prototype === Object.prototype;
16
+ };
17
+ const isSameHostContext = (a, b, depth = 0) => {
18
+ if (Object.is(a, b)) return true;
19
+ if (depth > 100) return false;
20
+ if (Array.isArray(a) || Array.isArray(b)) {
21
+ if (!Array.isArray(a) || !Array.isArray(b) || a.length !== b.length) return false;
22
+ for (let i = 0; i < a.length; i++) if (!isSameHostContext(a[i], b[i], depth + 1)) return false;
23
+ return true;
24
+ }
25
+ if (!isPlainObject(a) || !isPlainObject(b)) return false;
26
+ const aKeys = Object.keys(a);
27
+ return aKeys.length === Object.keys(b).length && aKeys.every((key) => Object.hasOwn(b, key) && isSameHostContext(a[key], b[key], depth + 1));
28
+ };
29
+ function useBridgeNotify(value, bridgeRef, widgetReadyRef, pendingRef, lastSentRef, notify, t0) {
30
+ const $ = c(10);
31
+ const isEqual = t0 === void 0 ? Object.is : t0;
32
+ let t1;
33
+ if ($[0] !== bridgeRef || $[1] !== isEqual || $[2] !== lastSentRef || $[3] !== notify || $[4] !== pendingRef || $[5] !== value || $[6] !== widgetReadyRef) {
34
+ t1 = () => {
16
35
  if (!bridgeRef.current) return;
17
- if (value === void 0) return;
18
- if (lastSentRef.current === value) return;
36
+ if (value === void 0 || isEqual(lastSentRef.current, value)) {
37
+ pendingRef.current = void 0;
38
+ return;
39
+ }
19
40
  if (!widgetReadyRef.current) {
20
41
  pendingRef.current = value;
21
42
  return;
@@ -24,26 +45,27 @@ function useBridgeNotify(value, bridgeRef, widgetReadyRef, pendingRef, lastSentR
24
45
  lastSentRef.current = value;
25
46
  };
26
47
  $[0] = bridgeRef;
27
- $[1] = lastSentRef;
28
- $[2] = notify;
29
- $[3] = pendingRef;
30
- $[4] = value;
31
- $[5] = widgetReadyRef;
32
- $[6] = t0;
33
- } else t0 = $[6];
34
- let t1;
35
- if ($[7] !== value) {
36
- t1 = [value];
37
- $[7] = value;
38
- $[8] = t1;
39
- } else t1 = $[8];
40
- useEffect(t0, t1);
48
+ $[1] = isEqual;
49
+ $[2] = lastSentRef;
50
+ $[3] = notify;
51
+ $[4] = pendingRef;
52
+ $[5] = value;
53
+ $[6] = widgetReadyRef;
54
+ $[7] = t1;
55
+ } else t1 = $[7];
56
+ let t2;
57
+ if ($[8] !== value) {
58
+ t2 = [value];
59
+ $[8] = value;
60
+ $[9] = t2;
61
+ } else t2 = $[9];
62
+ useEffect(t1, t2);
41
63
  }
42
- function buildLiveHandlers(initial, liveRef) {
64
+ function buildLiveHandlers(initial, liveRef, lifecycle) {
43
65
  const live = () => liveRef.current.handlers;
44
66
  const has = (key) => initial?.[key] !== void 0;
45
67
  const out = {};
46
- if (has("allowedTools")) Object.defineProperty(out, "allowedTools", {
68
+ Object.defineProperty(out, "allowedTools", {
47
69
  get: () => live()?.allowedTools,
48
70
  enumerable: true,
49
71
  configurable: true
@@ -60,8 +82,14 @@ function buildLiveHandlers(initial, liveRef) {
60
82
  if (has("sendMessage")) out.sendMessage = liveCall("sendMessage");
61
83
  if (has("updateModelContext")) out.updateModelContext = liveCall("updateModelContext");
62
84
  if (has("requestDisplayMode")) out.requestDisplayMode = liveCall("requestDisplayMode");
63
- out.onSizeChange = (p) => live()?.onSizeChange?.(p);
64
- out.onInitialized = () => live()?.onInitialized?.();
85
+ out.onSizeChange = (p) => {
86
+ lifecycle.onSizeChange(p);
87
+ live()?.onSizeChange?.(p);
88
+ };
89
+ out.onInitialized = () => {
90
+ lifecycle.onInitialized();
91
+ live()?.onInitialized?.();
92
+ };
65
93
  out.onRequestTeardown = (p) => live()?.onRequestTeardown?.(p);
66
94
  out.onLog = (p) => live()?.onLog?.(p);
67
95
  out.onError = (e) => live()?.onError?.(e);
@@ -153,23 +181,18 @@ function McpAppFrame(t0) {
153
181
  pendingHostContextRef.current = void 0;
154
182
  }
155
183
  };
156
- const liveHandlers = buildLiveHandlers(current.handlers, liveRef);
157
- const liveOnInitialized = liveHandlers.onInitialized;
158
- const wrappedHandlers = {
159
- ...liveHandlers,
184
+ const wrappedHandlers = buildLiveHandlers(current.handlers, liveRef, {
160
185
  onInitialized: () => {
161
186
  if (initTimeoutId !== null) {
162
187
  clearTimeout(initTimeoutId);
163
188
  initTimeoutId = null;
164
189
  }
165
190
  flushPending();
166
- liveOnInitialized?.();
167
191
  },
168
192
  onSizeChange: (p) => {
169
193
  if (p.height != null) host.setHeight(p.height);
170
- liveHandlers.onSizeChange?.(p);
171
194
  }
172
- };
195
+ });
173
196
  initTimeoutId = setTimeout(() => {
174
197
  initTimeoutId = null;
175
198
  flushPending();
@@ -183,6 +206,7 @@ function McpAppFrame(t0) {
183
206
  bridgeRef.current = bridge;
184
207
  if (current.input !== void 0) pendingInputRef.current = current.input;
185
208
  if (current.output !== void 0) pendingOutputRef.current = current.output;
209
+ lastSentHostContextRef.current = current.hostContext ?? {};
186
210
  return {
187
211
  onMessage: bridge.onMessage,
188
212
  dispose: () => {
@@ -207,7 +231,7 @@ function McpAppFrame(t0) {
207
231
  const createBridge = t5;
208
232
  useBridgeNotify(input, bridgeRef, widgetReadyRef, pendingInputRef, lastSentInputRef, _temp);
209
233
  useBridgeNotify(output, bridgeRef, widgetReadyRef, pendingOutputRef, lastSentOutputRef, _temp2);
210
- useBridgeNotify(hostContext, bridgeRef, widgetReadyRef, pendingHostContextRef, lastSentHostContextRef, _temp3);
234
+ useBridgeNotify(hostContext, bridgeRef, widgetReadyRef, pendingHostContextRef, lastSentHostContextRef, _temp3, isSameHostContext);
211
235
  let t6;
212
236
  if ($[14] !== resource.html) {
213
237
  t6 = { html: resource.html };
@@ -1 +1 @@
1
- {"version":3,"file":"app-frame.js","names":["c","_c","MutableRefObject","useEffect","useLayoutEffect","useRef","McpAppBridge","createMcpAppBridge","SandboxHost","SandboxBridge","SandboxHostApi","SandboxHostFrame","McpAppBridgeHandlers","McpAppFrameProps","McpAppHostContext","DEFAULT_PRODUCT","INIT_TIMEOUT_MS","DEFAULT_MAX_HEIGHT","useBridgeNotify","value","bridgeRef","widgetReadyRef","pendingRef","lastSentRef","notify","$","t0","current","undefined","t1","LiveSnapshot","handlers","hostInfo","hostContext","input","output","buildLiveHandlers","initial","liveRef","live","has","key","K","out","Object","defineProperty","get","allowedTools","enumerable","configurable","liveCall","NonNullable","p","fn","Error","callTool","readResource","listResources","openLink","sendMessage","updateModelContext","requestDisplayMode","onSizeChange","onInitialized","onRequestTeardown","onLog","onError","e","McpAppFrame","app","resource","sandbox","maxHeight","lastSentInputRef","lastSentOutputRef","lastSentHostContextRef","pendingInputRef","pendingOutputRef","pendingHostContextRef","t2","t3","t4","t5","Symbol","for","frame","host","initTimeoutId","flushPending","b","notifyToolInput","notifyToolResult","notifyHostContextChanged","liveHandlers","liveOnInitialized","wrappedHandlers","clearTimeout","height","setHeight","setTimeout","bridge","onMessage","dispose","createBridge","_temp","_temp2","_temp3","t6","html","t7","serverId","uri","t8","product","t9","t10","err","t11","meta","prefersBorder","t12","resourceUri","t13","b_2","v_1","v","b_1","v_0","b_0"],"sources":["../../src/mcp-apps/app-frame.tsx"],"sourcesContent":["\"use client\";\n\nimport {\n type MutableRefObject,\n useEffect,\n useLayoutEffect,\n useRef,\n} from \"react\";\nimport { type McpAppBridge, createMcpAppBridge } from \"./bridge\";\nimport {\n SandboxHost,\n type SandboxBridge,\n type SandboxHostApi,\n type SandboxHostFrame,\n} from \"../sandbox-host/SandboxHost\";\nimport type {\n McpAppBridgeHandlers,\n McpAppFrameProps,\n McpAppHostContext,\n} from \"./types\";\n\nconst DEFAULT_PRODUCT = \"assistant-ui-mcp-app\";\nconst INIT_TIMEOUT_MS = 5000;\nconst DEFAULT_MAX_HEIGHT = 800;\n\nfunction useBridgeNotify<T>(\n value: T | undefined,\n bridgeRef: MutableRefObject<McpAppBridge | null>,\n widgetReadyRef: MutableRefObject<boolean>,\n pendingRef: MutableRefObject<T | undefined>,\n lastSentRef: MutableRefObject<T | undefined>,\n notify: (bridge: McpAppBridge, v: T) => void,\n) {\n useEffect(() => {\n if (!bridgeRef.current) return;\n if (value === undefined) return;\n if (lastSentRef.current === value) return;\n if (!widgetReadyRef.current) {\n pendingRef.current = value;\n return;\n }\n notify(bridgeRef.current, value);\n lastSentRef.current = value;\n // oxlint-disable-next-line react/exhaustive-deps -- refs are stable; notify is assumed stable; re-run only when value changes\n }, [value]);\n}\n\ntype LiveSnapshot = {\n handlers: McpAppBridgeHandlers | undefined;\n hostInfo: McpAppFrameProps[\"hostInfo\"];\n hostContext: McpAppFrameProps[\"hostContext\"];\n input: unknown;\n output: unknown;\n};\n\n// Proxy each per-call handler through liveRef so the bridge always dispatches\n// to the latest handler reference (e.g. inline callbacks closing over state).\n// Capability presence is snapshot at mount: a handler added later requires a\n// remount (keyed on resource URI) to expose the capability to the widget.\nfunction buildLiveHandlers(\n initial: McpAppBridgeHandlers | undefined,\n liveRef: { readonly current: LiveSnapshot },\n): McpAppBridgeHandlers {\n const live = () => liveRef.current.handlers;\n const has = <K extends keyof McpAppBridgeHandlers>(key: K) =>\n initial?.[key] !== undefined;\n const out: McpAppBridgeHandlers = {};\n if (has(\"allowedTools\")) {\n Object.defineProperty(out, \"allowedTools\", {\n get: () => live()?.allowedTools,\n enumerable: true,\n configurable: true,\n });\n }\n const liveCall = <K extends keyof McpAppBridgeHandlers>(\n key: K,\n ): NonNullable<McpAppBridgeHandlers[K]> =>\n ((p: unknown) => {\n const fn = live()?.[key] as ((p: unknown) => unknown) | undefined;\n if (!fn) {\n throw new Error(`${key} handler is no longer available`);\n }\n return fn(p);\n }) as NonNullable<McpAppBridgeHandlers[K]>;\n if (has(\"callTool\")) out.callTool = liveCall(\"callTool\");\n if (has(\"readResource\")) out.readResource = liveCall(\"readResource\");\n if (has(\"listResources\")) out.listResources = liveCall(\"listResources\");\n if (has(\"openLink\")) out.openLink = liveCall(\"openLink\");\n if (has(\"sendMessage\")) out.sendMessage = liveCall(\"sendMessage\");\n if (has(\"updateModelContext\"))\n out.updateModelContext = liveCall(\"updateModelContext\");\n if (has(\"requestDisplayMode\"))\n out.requestDisplayMode = liveCall(\"requestDisplayMode\");\n out.onSizeChange = (p) => live()?.onSizeChange?.(p);\n out.onInitialized = () => live()?.onInitialized?.();\n out.onRequestTeardown = (p) => live()?.onRequestTeardown?.(p);\n out.onLog = (p) => live()?.onLog?.(p);\n out.onError = (e) => live()?.onError?.(e);\n return out;\n}\n\nexport function McpAppFrame({\n app,\n resource,\n input,\n output,\n sandbox,\n handlers,\n hostInfo,\n hostContext,\n maxHeight = DEFAULT_MAX_HEIGHT,\n}: McpAppFrameProps) {\n const bridgeRef = useRef<McpAppBridge | null>(null);\n const lastSentInputRef = useRef<unknown>(undefined);\n const lastSentOutputRef = useRef<unknown>(undefined);\n const lastSentHostContextRef = useRef<McpAppHostContext | undefined>(\n undefined,\n );\n // Per MCP Apps spec, the host should defer notifications until the widget\n // signals readiness via `notifications/initialized`. Until then, we record\n // pending values and flush them on init.\n const widgetReadyRef = useRef(false);\n const pendingInputRef = useRef<unknown>(undefined);\n const pendingOutputRef = useRef<unknown>(undefined);\n const pendingHostContextRef = useRef<McpAppHostContext | undefined>(\n undefined,\n );\n\n const liveRef = useRef<LiveSnapshot>({\n handlers,\n hostInfo,\n hostContext,\n input,\n output,\n });\n useLayoutEffect(() => {\n liveRef.current = {\n handlers,\n hostInfo,\n hostContext,\n input,\n output,\n };\n }, [handlers, hostInfo, hostContext, input, output]);\n\n const createBridge = (\n frame: SandboxHostFrame,\n host: SandboxHostApi,\n ): SandboxBridge => {\n const current = liveRef.current;\n let initTimeoutId: ReturnType<typeof setTimeout> | null = null;\n\n const flushPending = () => {\n if (widgetReadyRef.current) return;\n widgetReadyRef.current = true;\n const b = bridgeRef.current;\n if (!b) return;\n if (pendingInputRef.current !== undefined) {\n b.notifyToolInput(pendingInputRef.current);\n lastSentInputRef.current = pendingInputRef.current;\n pendingInputRef.current = undefined;\n }\n if (pendingOutputRef.current !== undefined) {\n b.notifyToolResult(pendingOutputRef.current);\n lastSentOutputRef.current = pendingOutputRef.current;\n pendingOutputRef.current = undefined;\n }\n if (pendingHostContextRef.current !== undefined) {\n b.notifyHostContextChanged(pendingHostContextRef.current);\n lastSentHostContextRef.current = pendingHostContextRef.current;\n pendingHostContextRef.current = undefined;\n }\n };\n\n const liveHandlers = buildLiveHandlers(current.handlers, liveRef);\n const liveOnInitialized = liveHandlers.onInitialized;\n const wrappedHandlers: McpAppBridgeHandlers = {\n ...liveHandlers,\n onInitialized: () => {\n if (initTimeoutId !== null) {\n clearTimeout(initTimeoutId);\n initTimeoutId = null;\n }\n flushPending();\n liveOnInitialized?.();\n },\n onSizeChange: (p) => {\n if (p.height != null) host.setHeight(p.height);\n liveHandlers.onSizeChange?.(p);\n },\n };\n\n // Safety net: if the widget never sends notifications/initialized (broken\n // or non-spec-compliant), flush the queue anyway so the host doesn't\n // appear hung.\n initTimeoutId = setTimeout(() => {\n initTimeoutId = null;\n flushPending();\n }, INIT_TIMEOUT_MS);\n\n const bridge = createMcpAppBridge({\n frame,\n handlers: wrappedHandlers,\n hostInfo: current.hostInfo,\n hostContext: current.hostContext,\n });\n bridgeRef.current = bridge;\n\n if (current.input !== undefined) pendingInputRef.current = current.input;\n if (current.output !== undefined) pendingOutputRef.current = current.output;\n // hostContext is delivered inside the ui/initialize response; subsequent\n // changes flow through useBridgeNotify's pending path.\n\n return {\n onMessage: bridge.onMessage,\n dispose: () => {\n if (initTimeoutId !== null) {\n clearTimeout(initTimeoutId);\n initTimeoutId = null;\n }\n bridge.dispose();\n bridgeRef.current = null;\n lastSentInputRef.current = undefined;\n lastSentOutputRef.current = undefined;\n lastSentHostContextRef.current = undefined;\n widgetReadyRef.current = false;\n pendingInputRef.current = undefined;\n pendingOutputRef.current = undefined;\n pendingHostContextRef.current = undefined;\n },\n };\n };\n\n useBridgeNotify(\n input,\n bridgeRef,\n widgetReadyRef,\n pendingInputRef,\n lastSentInputRef,\n (b, v) => b.notifyToolInput(v),\n );\n useBridgeNotify(\n output,\n bridgeRef,\n widgetReadyRef,\n pendingOutputRef,\n lastSentOutputRef,\n (b, v) => b.notifyToolResult(v),\n );\n useBridgeNotify(\n hostContext,\n bridgeRef,\n widgetReadyRef,\n pendingHostContextRef,\n lastSentHostContextRef,\n (b, v) => b.notifyHostContextChanged(v),\n );\n\n return (\n <SandboxHost\n content={{ html: resource.html }}\n contentKey={\n app.serverId ? `${app.serverId} ${resource.uri}` : resource.uri\n }\n sandbox={{ ...sandbox, product: sandbox?.product ?? DEFAULT_PRODUCT }}\n maxHeight={maxHeight}\n createBridge={createBridge}\n onError={(err) => liveRef.current.handlers?.onError?.(err)}\n containerProps={{\n \"data-mcp-app-resource\": app.resourceUri,\n \"data-mcp-app-prefers-border\": resource.meta?.prefersBorder\n ? \"\"\n : undefined,\n }}\n />\n );\n}\n"],"mappings":";;;;;;;AAqBA,MAAMe,kBAAkB;AACxB,MAAMC,kBAAkB;AACxB,MAAMC,qBAAqB;AAE3B,SAAAC,gBAAAC,OAAAC,WAAAC,gBAAAC,YAAAC,aAAAC,QAAA;CAAA,MAAAC,IAAAxB,EAAA,CAAA;CAAA,IAAAyB;CAAA,IAAAD,EAAA,OAAAL,aAAAK,EAAA,OAAAF,eAAAE,EAAA,OAAAD,UAAAC,EAAA,OAAAH,cAAAG,EAAA,OAAAN,SAAAM,EAAA,OAAAJ,gBAAA;EAQYK,WAAA;GACR,IAAI,CAACN,UAASO,SAAQ;GACtB,IAAIR,UAAUS,KAAAA,GAAS;GACvB,IAAIL,YAAWI,YAAaR,OAAK;GACjC,IAAI,CAACE,eAAcM,SAAQ;IACzBL,WAAUK,UAAWR;IAAH;GAAA;GAGpBK,OAAOJ,UAASO,SAAUR,KAAK;GAC/BI,YAAWI,UAAWR;EAAH;EAEpBM,EAAA,KAAAL;EAAAK,EAAA,KAAAF;EAAAE,EAAA,KAAAD;EAAAC,EAAA,KAAAH;EAAAG,EAAA,KAAAN;EAAAM,EAAA,KAAAJ;EAAAI,EAAA,KAAAC;CAAA,OAAAA,KAAAD,EAAA;CAAA,IAAAI;CAAA,IAAAJ,EAAA,OAAAN,OAAA;EAAEU,KAAA,CAACV,KAAK;EAACM,EAAA,KAAAN;EAAAM,EAAA,KAAAI;CAAA,OAAAA,KAAAJ,EAAA;CAXVtB,UAAUuB,IAWPG,EAAO;AAAC;AAeb,SAASO,kBACPC,SACAC,SACsB;CACtB,MAAMC,aAAaD,QAAQX,QAAQI;CACnC,MAAMS,OAA6CC,QACjDJ,UAAUI,SAASb,KAAAA;CACrB,MAAMe,MAA4B,CAAC;CACnC,IAAIH,IAAI,cAAc,GACpBI,OAAOC,eAAeF,KAAK,gBAAgB;EACzCG,WAAWP,KAAK,CAAC,EAAEQ;EACnBC,YAAY;EACZC,cAAc;CAChB,CAAC;CAEH,MAAMC,YACJT,UAEEW,MAAe;EACf,MAAMC,KAAKd,KAAK,CAAC,GAAGE;EACpB,IAAI,CAACY,IACH,MAAM,IAAIC,MAAM,GAAGb,IAAG,gCAAiC;EAEzD,OAAOY,GAAGD,CAAC;CACb;CACF,IAAIZ,IAAI,UAAU,GAAGG,IAAIY,WAAWL,SAAS,UAAU;CACvD,IAAIV,IAAI,cAAc,GAAGG,IAAIa,eAAeN,SAAS,cAAc;CACnE,IAAIV,IAAI,eAAe,GAAGG,IAAIc,gBAAgBP,SAAS,eAAe;CACtE,IAAIV,IAAI,UAAU,GAAGG,IAAIe,WAAWR,SAAS,UAAU;CACvD,IAAIV,IAAI,aAAa,GAAGG,IAAIgB,cAAcT,SAAS,aAAa;CAChE,IAAIV,IAAI,oBAAoB,GAC1BG,IAAIiB,qBAAqBV,SAAS,oBAAoB;CACxD,IAAIV,IAAI,oBAAoB,GAC1BG,IAAIkB,qBAAqBX,SAAS,oBAAoB;CACxDP,IAAImB,gBAAgBV,MAAMb,KAAK,CAAC,EAAEuB,eAAeV,CAAC;CAClDT,IAAIoB,sBAAsBxB,KAAK,CAAC,EAAEwB,gBAAgB;CAClDpB,IAAIqB,qBAAqBZ,MAAMb,KAAK,CAAC,EAAEyB,oBAAoBZ,CAAC;CAC5DT,IAAIsB,SAASb,MAAMb,KAAK,CAAC,EAAE0B,QAAQb,CAAC;CACpCT,IAAIuB,WAAWC,MAAM5B,KAAK,CAAC,EAAE2B,UAAUC,CAAC;CACxC,OAAOxB;AACT;AAEA,SAAOyB,YAAA1C,IAAA;CAAA,MAAAD,IAAAxB,EAAA,EAAA;CAAqB,MAAA,EAAAoE,KAAAC,UAAApC,OAAAC,QAAAoC,SAAAxC,UAAAC,UAAAC,aAAAuC,WAAA3C,OAAAH;CAS1B,MAAA8C,YAAA3C,OAAAD,KAAAA,IAAAX,qBAAAY;CAEA,MAAAT,YAAkBf,OAA4B,IAAI;CAClD,MAAAoE,mBAAyBpE,OAAgBuB,KAAAA,CAAS;CAClD,MAAA8C,oBAA0BrE,OAAgBuB,KAAAA,CAAS;CACnD,MAAA+C,yBAA+BtE,OAC7BuB,KAAAA,CACF;CAIA,MAAAP,iBAAuBhB,OAAO,KAAK;CACnC,MAAAuE,kBAAwBvE,OAAgBuB,KAAAA,CAAS;CACjD,MAAAiD,mBAAyBxE,OAAgBuB,KAAAA,CAAS;CAClD,MAAAkD,wBAA8BzE,OAC5BuB,KAAAA,CACF;CAAE,IAAAmD;CAAA,IAAAtD,EAAA,OAAAM,YAAAN,EAAA,OAAAQ,eAAAR,EAAA,OAAAO,YAAAP,EAAA,OAAAS,SAAAT,EAAA,OAAAU,QAAA;EAEmC4C,KAAA;GAAAhD;GAAAC;GAAAC;GAAAC;GAAAC;EAMrC;EAACV,EAAA,KAAAM;EAAAN,EAAA,KAAAQ;EAAAR,EAAA,KAAAO;EAAAP,EAAA,KAAAS;EAAAT,EAAA,KAAAU;EAAAV,EAAA,KAAAsD;CAAA,OAAAA,KAAAtD,EAAA;CAND,MAAAa,UAAgBjC,OAAqB0E,EAMpC;CAAE,IAAAC;CAAA,IAAAC;CAAA,IAAAxD,EAAA,OAAAM,YAAAN,EAAA,OAAAQ,eAAAR,EAAA,OAAAO,YAAAP,EAAA,OAAAS,SAAAT,EAAA,QAAAU,QAAA;EACa6C,WAAA;GACd1C,QAAOX,UAAW;IAAAI;IAAAC;IAAAC;IAAAC;IAAAC;GAMlB;EANe;EAOd8C,KAAA;GAAClD;GAAUC;GAAUC;GAAaC;GAAOC;EAAM;EAACV,EAAA,KAAAM;EAAAN,EAAA,KAAAQ;EAAAR,EAAA,KAAAO;EAAAP,EAAA,KAAAS;EAAAT,EAAA,MAAAU;EAAAV,EAAA,MAAAuD;EAAAvD,EAAA,MAAAwD;CAAA,OAAA;EAAAD,KAAAvD,EAAA;EAAAwD,KAAAxD,EAAA;CAAA;CARnDrB,gBAAgB4E,IAQbC,EAAgD;CAAC,IAAAC;CAAA,IAAAzD,EAAA,QAAA0D,OAAAC,IAAA,2BAAA,GAAA;EAE/BF,MAAAG,OAAAC,SAAA;GAInB,MAAA3D,UAAgBW,QAAOX;GACvB,IAAA4D,gBAA0D;GAE1D,MAAAC,qBAAqB;IACnB,IAAInE,eAAcM,SAAQ;IAC1BN,eAAcM,UAAW;IACzB,MAAA8D,IAAUrE,UAASO;IACnB,IAAI,CAAC8D,GAAC;IACN,IAAIb,gBAAejD,YAAaC,KAAAA,GAAS;KACvC6D,EAACC,gBAAiBd,gBAAejD,OAAQ;KACzC8C,iBAAgB9C,UAAWiD,gBAAejD;KAC1CiD,gBAAejD,UAAWC,KAAAA;IAAH;IAEzB,IAAIiD,iBAAgBlD,YAAaC,KAAAA,GAAS;KACxC6D,EAACE,iBAAkBd,iBAAgBlD,OAAQ;KAC3C+C,kBAAiB/C,UAAWkD,iBAAgBlD;KAC5CkD,iBAAgBlD,UAAWC,KAAAA;IAAH;IAE1B,IAAIkD,sBAAqBnD,YAAaC,KAAAA,GAAS;KAC7C6D,EAACG,yBAA0Bd,sBAAqBnD,OAAQ;KACxDgD,uBAAsBhD,UAAWmD,sBAAqBnD;KACtDmD,sBAAqBnD,UAAWC,KAAAA;IAAH;GAC9B;GAGH,MAAAiE,eAAqBzD,kBAAkBT,QAAOI,UAAWO,OAAO;GAChE,MAAAwD,oBAA0BD,aAAY9B;GACtC,MAAAgC,kBAA8C;IAAA,GACzCF;IAAY9B,qBACA;KACb,IAAIwB,kBAAkB,MAAI;MACxBS,aAAaT,aAAa;MAC1BA,gBAAgBA;KAAH;KAEfC,aAAa;KACbM,oBAAoB;IAAC;IACtBhC,eACaV,MAAA;KACZ,IAAIA,EAAC6C,UAAW,MAAMX,KAAIY,UAAW9C,EAAC6C,MAAO;KAC7CJ,aAAY/B,eAAgBV,CAAC;IAAC;GAElC;GAKAmC,gBAAgBY,iBAAW;IACzBZ,gBAAgBA;IAChBC,aAAa;GAAC,GACbxE,eAAe;GAElB,MAAAoF,SAAe7F,mBAAmB;IAAA8E;IAAAtD,UAEtBgE;IAAe/D,UACfL,QAAOK;IAASC,aACbN,QAAOM;GACtB,CAAC;GACDb,UAASO,UAAWyE;GAEpB,IAAIzE,QAAOO,UAAWN,KAAAA,GAAWgD,gBAAejD,UAAWA,QAAOO;GAClE,IAAIP,QAAOQ,WAAYP,KAAAA,GAAWiD,iBAAgBlD,UAAWA,QAAOQ;GAAQ,OAIrE;IAAAkE,WACMD,OAAMC;IAAUC,eAClB;KACP,IAAIf,kBAAkB,MAAI;MACxBS,aAAaT,aAAa;MAC1BA,gBAAgBA;KAAH;KAEfa,OAAME,QAAS;KACflF,UAASO,UAAW;KACpB8C,iBAAgB9C,UAAWC,KAAAA;KAC3B8C,kBAAiB/C,UAAWC,KAAAA;KAC5B+C,uBAAsBhD,UAAWC,KAAAA;KACjCP,eAAcM,UAAW;KACzBiD,gBAAejD,UAAWC,KAAAA;KAC1BiD,iBAAgBlD,UAAWC,KAAAA;KAC3BkD,sBAAqBnD,UAAWC,KAAAA;IAAH;GAEjC;EAAC;EACFH,EAAA,MAAAyD;CAAA,OAAAA,KAAAzD,EAAA;CAtFD,MAAA8E,eAAqBrB;CAwFrBhE,gBACEgB,OACAd,WACAC,gBACAuD,iBACAH,kBACA+B,KACF;CACAtF,gBACEiB,QACAf,WACAC,gBACAwD,kBACAH,mBACA+B,MACF;CACAvF,gBACEe,aACAb,WACAC,gBACAyD,uBACAH,wBACA+B,MACF;CAAC,IAAAC;CAAA,IAAAlF,EAAA,QAAA6C,SAAAsC,MAAA;EAIYD,KAAA,EAAAC,MAAQtC,SAAQsC,KAAM;EAACnF,EAAA,MAAA6C,SAAAsC;EAAAnF,EAAA,MAAAkF;CAAA,OAAAA,KAAAlF,EAAA;CAE9B,MAAAoF,KAAAxC,IAAGyC,WAAH,GAAkBzC,IAAGyC,SAAS,GAAIxC,SAAQyC,QAASzC,SAAQyC;CAE7B,MAAAC,KAAAzC,SAAO0C,WAAPlG;CAAmC,IAAAmG;CAAA,IAAAzF,EAAA,QAAA8C,WAAA9C,EAAA,QAAAuF,IAAA;EAA1DE,KAAA;GAAA,GAAK3C;GAAO0C,SAAWD;EAAoC;EAACvF,EAAA,MAAA8C;EAAA9C,EAAA,MAAAuF;EAAAvF,EAAA,MAAAyF;CAAA,OAAAA,KAAAzF,EAAA;CAAA,IAAA0F;CAAA,IAAA1F,EAAA,QAAA0D,OAAAC,IAAA,2BAAA,GAAA;EAG5D+B,OAAAC,QAAS9E,QAAOX,QAAQI,UAAkBmC,UAAGkD,GAAG;EAAC3F,EAAA,MAAA0F;CAAA,OAAAA,MAAA1F,EAAA;CAGzB,MAAA4F,MAAA/C,SAAQgD,MAAoBC,gBAA5B,KAAA3F,KAAAA;CAElB,IAAA4F;CAAA,IAAA/F,EAAA,QAAA4C,IAAAoD,eAAAhG,EAAA,QAAA4F,KAAA;EAJCG,MAAA;GAAA,yBACWnD,IAAGoD;GAAY,+BACTJ;EAGjC;EAAC5F,EAAA,MAAA4C,IAAAoD;EAAAhG,EAAA,MAAA4F;EAAA5F,EAAA,MAAA+F;CAAA,OAAAA,MAAA/F,EAAA;CAAA,IAAAiG;CAAA,IAAAjG,EAAA,QAAA+C,aAAA/C,EAAA,QAAA+F,OAAA/F,EAAA,QAAAkF,MAAAlF,EAAA,QAAAoF,MAAApF,EAAA,QAAAyF,IAAA;EAdHQ,MAAA,oBAAC,aAAD;GACW,SAAAf;GAEP,YAAAE;GAEO,SAAAK;GACE1C;GACG+B;GACL,SAAAY;GACO,gBAAAK;EAKf,CAAA;EACD/F,EAAA,MAAA+C;EAAA/C,EAAA,MAAA+F;EAAA/F,EAAA,MAAAkF;EAAAlF,EAAA,MAAAoF;EAAApF,EAAA,MAAAyF;EAAAzF,EAAA,MAAAiG;CAAA,OAAAA,MAAAjG,EAAA;CAAA,OAfFiG;AAeE;AA7KC,SAAAhB,OAAAiB,KAAAC,KAAA;CAAA,OA0JOnC,IAACG,yBAA0BiC,GAAC;AAAC;AA1JpC,SAAApB,OAAAqB,KAAAC,KAAA;CAAA,OAkJOtC,IAACE,iBAAkBkC,GAAC;AAAC;AAlJ5B,SAAArB,MAAAwB,KAAAH,GAAA;CAAA,OA0IOpC,IAACC,gBAAiBmC,CAAC;AAAC"}
1
+ {"version":3,"file":"app-frame.js","names":["c","_c","MutableRefObject","useEffect","useLayoutEffect","useRef","McpAppBridge","createMcpAppBridge","SandboxHost","SandboxBridge","SandboxHostApi","SandboxHostFrame","McpAppBridgeHandlers","McpAppFrameProps","McpAppHostContext","isRecord","DEFAULT_PRODUCT","INIT_TIMEOUT_MS","DEFAULT_MAX_HEIGHT","isPlainObject","value","Record","prototype","Object","getPrototypeOf","isSameHostContext","a","b","depth","is","Array","isArray","length","i","aKeys","keys","every","key","hasOwn","useBridgeNotify","bridgeRef","widgetReadyRef","pendingRef","lastSentRef","notify","t0","$","isEqual","undefined","t1","current","t2","LiveSnapshot","handlers","hostInfo","hostContext","input","output","FrameLifecycle","onInitialized","onSizeChange","params","width","height","buildLiveHandlers","initial","liveRef","lifecycle","live","has","K","out","defineProperty","get","allowedTools","enumerable","configurable","liveCall","NonNullable","p","fn","Error","callTool","readResource","listResources","openLink","sendMessage","updateModelContext","requestDisplayMode","onRequestTeardown","onLog","onError","e","McpAppFrame","app","resource","sandbox","maxHeight","lastSentInputRef","lastSentOutputRef","lastSentHostContextRef","pendingInputRef","pendingOutputRef","pendingHostContextRef","t3","t4","t5","Symbol","for","frame","host","initTimeoutId","flushPending","notifyToolInput","notifyToolResult","notifyHostContextChanged","wrappedHandlers","clearTimeout","setHeight","setTimeout","bridge","onMessage","dispose","createBridge","_temp","_temp2","_temp3","t6","html","t7","serverId","uri","t8","product","t9","t10","err","t11","meta","prefersBorder","t12","resourceUri","t13","b_2","v_1","v","b_1","v_0","b_0"],"sources":["../../src/mcp-apps/app-frame.tsx"],"sourcesContent":["\"use client\";\n\nimport {\n type MutableRefObject,\n useEffect,\n useLayoutEffect,\n useRef,\n} from \"react\";\nimport { type McpAppBridge, createMcpAppBridge } from \"./bridge\";\nimport {\n SandboxHost,\n type SandboxBridge,\n type SandboxHostApi,\n type SandboxHostFrame,\n} from \"../sandbox-host/SandboxHost\";\nimport type {\n McpAppBridgeHandlers,\n McpAppFrameProps,\n McpAppHostContext,\n} from \"./types\";\nimport { isRecord } from \"@assistant-ui/core/internal\";\n\nconst DEFAULT_PRODUCT = \"assistant-ui-mcp-app\";\nconst INIT_TIMEOUT_MS = 5000;\nconst DEFAULT_MAX_HEIGHT = 800;\n\n// Only a plain object can be compared by its own keys. Structured clone carries\n// a Date, Map, or class instance to the widget intact, and those expose no\n// enumerable keys, so walking them would report two different values as equal.\nconst isPlainObject = (value: unknown): value is Record<string, unknown> => {\n if (!isRecord(value)) return false;\n const prototype = Object.getPrototypeOf(value);\n return prototype === null || prototype === Object.prototype;\n};\n\n// Hosts commonly rebuild an equal context object on every render, and the\n// widget cannot tell a repeated notification apart from a real change. The\n// open index signature on McpAppHostContext admits values JSON rejects (an\n// undefined property value is enough), so leaves the walk cannot compare fall\n// back to identity rather than failing the whole comparison.\nconst isSameHostContext = (a: unknown, b: unknown, depth = 0): boolean => {\n if (Object.is(a, b)) return true;\n if (depth > 100) return false;\n if (Array.isArray(a) || Array.isArray(b)) {\n if (!Array.isArray(a) || !Array.isArray(b) || a.length !== b.length)\n return false;\n for (let i = 0; i < a.length; i++) {\n if (!isSameHostContext(a[i], b[i], depth + 1)) return false;\n }\n return true;\n }\n if (!isPlainObject(a) || !isPlainObject(b)) return false;\n const aKeys = Object.keys(a);\n return (\n aKeys.length === Object.keys(b).length &&\n aKeys.every(\n (key) =>\n Object.hasOwn(b, key) && isSameHostContext(a[key], b[key], depth + 1),\n )\n );\n};\n\nfunction useBridgeNotify<T>(\n value: T | undefined,\n bridgeRef: MutableRefObject<McpAppBridge | null>,\n widgetReadyRef: MutableRefObject<boolean>,\n pendingRef: MutableRefObject<T | undefined>,\n lastSentRef: MutableRefObject<T | undefined>,\n notify: (bridge: McpAppBridge, v: T) => void,\n isEqual: (sent: T | undefined, next: T) => boolean = Object.is,\n) {\n useEffect(() => {\n if (!bridgeRef.current) return;\n // Nothing to deliver, either because there is no value or because the\n // widget already holds it; a queued value here is superseded and would\n // otherwise flush after initialization as a stale update.\n if (value === undefined || isEqual(lastSentRef.current, value)) {\n pendingRef.current = undefined;\n return;\n }\n if (!widgetReadyRef.current) {\n pendingRef.current = value;\n return;\n }\n notify(bridgeRef.current, value);\n lastSentRef.current = value;\n // oxlint-disable-next-line react/exhaustive-deps -- refs are stable; notify and isEqual are assumed stable; re-run only when value changes\n }, [value]);\n}\n\ntype LiveSnapshot = {\n handlers: McpAppBridgeHandlers | undefined;\n hostInfo: McpAppFrameProps[\"hostInfo\"];\n hostContext: McpAppFrameProps[\"hostContext\"];\n input: unknown;\n output: unknown;\n};\n\ntype FrameLifecycle = {\n onInitialized: () => void;\n onSizeChange: (params: { width?: number; height?: number }) => void;\n};\n\n// Proxy each per-call handler through liveRef so the bridge always dispatches\n// to the latest handler reference (e.g. inline callbacks closing over state).\n// Capability presence is snapshot at mount: a handler added later requires a\n// remount (keyed on resource URI) to expose the capability to the widget.\n// allowedTools is the exception: it is never advertised in the ui/initialize\n// response, so it stays a live getter, which means this object must reach the\n// bridge uncopied and the frame passes its lifecycle work in rather than\n// wrapping the result.\nfunction buildLiveHandlers(\n initial: McpAppBridgeHandlers | undefined,\n liveRef: { readonly current: LiveSnapshot },\n lifecycle: FrameLifecycle,\n): McpAppBridgeHandlers {\n const live = () => liveRef.current.handlers;\n const has = <K extends keyof McpAppBridgeHandlers>(key: K) =>\n initial?.[key] !== undefined;\n const out: McpAppBridgeHandlers = {};\n Object.defineProperty(out, \"allowedTools\", {\n get: () => live()?.allowedTools,\n enumerable: true,\n configurable: true,\n });\n const liveCall = <K extends keyof McpAppBridgeHandlers>(\n key: K,\n ): NonNullable<McpAppBridgeHandlers[K]> =>\n ((p: unknown) => {\n const fn = live()?.[key] as ((p: unknown) => unknown) | undefined;\n if (!fn) {\n throw new Error(`${key} handler is no longer available`);\n }\n return fn(p);\n }) as NonNullable<McpAppBridgeHandlers[K]>;\n if (has(\"callTool\")) out.callTool = liveCall(\"callTool\");\n if (has(\"readResource\")) out.readResource = liveCall(\"readResource\");\n if (has(\"listResources\")) out.listResources = liveCall(\"listResources\");\n if (has(\"openLink\")) out.openLink = liveCall(\"openLink\");\n if (has(\"sendMessage\")) out.sendMessage = liveCall(\"sendMessage\");\n if (has(\"updateModelContext\"))\n out.updateModelContext = liveCall(\"updateModelContext\");\n if (has(\"requestDisplayMode\"))\n out.requestDisplayMode = liveCall(\"requestDisplayMode\");\n out.onSizeChange = (p) => {\n lifecycle.onSizeChange(p);\n live()?.onSizeChange?.(p);\n };\n out.onInitialized = () => {\n lifecycle.onInitialized();\n live()?.onInitialized?.();\n };\n out.onRequestTeardown = (p) => live()?.onRequestTeardown?.(p);\n out.onLog = (p) => live()?.onLog?.(p);\n out.onError = (e) => live()?.onError?.(e);\n return out;\n}\n\nexport function McpAppFrame({\n app,\n resource,\n input,\n output,\n sandbox,\n handlers,\n hostInfo,\n hostContext,\n maxHeight = DEFAULT_MAX_HEIGHT,\n}: McpAppFrameProps) {\n const bridgeRef = useRef<McpAppBridge | null>(null);\n const lastSentInputRef = useRef<unknown>(undefined);\n const lastSentOutputRef = useRef<unknown>(undefined);\n const lastSentHostContextRef = useRef<McpAppHostContext | undefined>(\n undefined,\n );\n // Per MCP Apps spec, the host should defer notifications until the widget\n // signals readiness via `notifications/initialized`. Until then, we record\n // pending values and flush them on init.\n const widgetReadyRef = useRef(false);\n const pendingInputRef = useRef<unknown>(undefined);\n const pendingOutputRef = useRef<unknown>(undefined);\n const pendingHostContextRef = useRef<McpAppHostContext | undefined>(\n undefined,\n );\n\n const liveRef = useRef<LiveSnapshot>({\n handlers,\n hostInfo,\n hostContext,\n input,\n output,\n });\n useLayoutEffect(() => {\n liveRef.current = {\n handlers,\n hostInfo,\n hostContext,\n input,\n output,\n };\n }, [handlers, hostInfo, hostContext, input, output]);\n\n const createBridge = (\n frame: SandboxHostFrame,\n host: SandboxHostApi,\n ): SandboxBridge => {\n const current = liveRef.current;\n let initTimeoutId: ReturnType<typeof setTimeout> | null = null;\n\n const flushPending = () => {\n if (widgetReadyRef.current) return;\n widgetReadyRef.current = true;\n const b = bridgeRef.current;\n if (!b) return;\n if (pendingInputRef.current !== undefined) {\n b.notifyToolInput(pendingInputRef.current);\n lastSentInputRef.current = pendingInputRef.current;\n pendingInputRef.current = undefined;\n }\n if (pendingOutputRef.current !== undefined) {\n b.notifyToolResult(pendingOutputRef.current);\n lastSentOutputRef.current = pendingOutputRef.current;\n pendingOutputRef.current = undefined;\n }\n if (pendingHostContextRef.current !== undefined) {\n b.notifyHostContextChanged(pendingHostContextRef.current);\n lastSentHostContextRef.current = pendingHostContextRef.current;\n pendingHostContextRef.current = undefined;\n }\n };\n\n const wrappedHandlers = buildLiveHandlers(current.handlers, liveRef, {\n onInitialized: () => {\n if (initTimeoutId !== null) {\n clearTimeout(initTimeoutId);\n initTimeoutId = null;\n }\n flushPending();\n },\n onSizeChange: (p) => {\n if (p.height != null) host.setHeight(p.height);\n },\n });\n\n // Safety net: if the widget never sends notifications/initialized (broken\n // or non-spec-compliant), flush the queue anyway so the host doesn't\n // appear hung.\n initTimeoutId = setTimeout(() => {\n initTimeoutId = null;\n flushPending();\n }, INIT_TIMEOUT_MS);\n\n const bridge = createMcpAppBridge({\n frame,\n handlers: wrappedHandlers,\n hostInfo: current.hostInfo,\n hostContext: current.hostContext,\n });\n bridgeRef.current = bridge;\n\n if (current.input !== undefined) pendingInputRef.current = current.input;\n if (current.output !== undefined) pendingOutputRef.current = current.output;\n // hostContext is delivered inside the ui/initialize response, where the\n // bridge defaults it to {}; recording that same normalized value keeps the\n // first later change from repeating what the widget already holds.\n lastSentHostContextRef.current = current.hostContext ?? {};\n\n return {\n onMessage: bridge.onMessage,\n dispose: () => {\n if (initTimeoutId !== null) {\n clearTimeout(initTimeoutId);\n initTimeoutId = null;\n }\n bridge.dispose();\n bridgeRef.current = null;\n lastSentInputRef.current = undefined;\n lastSentOutputRef.current = undefined;\n lastSentHostContextRef.current = undefined;\n widgetReadyRef.current = false;\n pendingInputRef.current = undefined;\n pendingOutputRef.current = undefined;\n pendingHostContextRef.current = undefined;\n },\n };\n };\n\n useBridgeNotify(\n input,\n bridgeRef,\n widgetReadyRef,\n pendingInputRef,\n lastSentInputRef,\n (b, v) => b.notifyToolInput(v),\n );\n useBridgeNotify(\n output,\n bridgeRef,\n widgetReadyRef,\n pendingOutputRef,\n lastSentOutputRef,\n (b, v) => b.notifyToolResult(v),\n );\n useBridgeNotify(\n hostContext,\n bridgeRef,\n widgetReadyRef,\n pendingHostContextRef,\n lastSentHostContextRef,\n (b, v) => b.notifyHostContextChanged(v),\n isSameHostContext,\n );\n\n return (\n <SandboxHost\n content={{ html: resource.html }}\n contentKey={\n app.serverId ? `${app.serverId} ${resource.uri}` : resource.uri\n }\n sandbox={{ ...sandbox, product: sandbox?.product ?? DEFAULT_PRODUCT }}\n maxHeight={maxHeight}\n createBridge={createBridge}\n onError={(err) => liveRef.current.handlers?.onError?.(err)}\n containerProps={{\n \"data-mcp-app-resource\": app.resourceUri,\n \"data-mcp-app-prefers-border\": resource.meta?.prefersBorder\n ? \"\"\n : undefined,\n }}\n />\n );\n}\n"],"mappings":";;;;;;;;AAsBA,MAAMgB,kBAAkB;AACxB,MAAMC,kBAAkB;AACxB,MAAMC,qBAAqB;AAK3B,MAAMC,iBAAiBC,UAAqD;CAC1E,IAAI,CAACL,SAASK,KAAK,GAAG,OAAO;CAC7B,MAAME,YAAYC,OAAOC,eAAeJ,KAAK;CAC7C,OAAOE,cAAc,QAAQA,cAAcC,OAAOD;AACpD;AAOA,MAAMG,qBAAqBC,GAAYC,GAAYC,QAAQ,MAAe;CACxE,IAAIL,OAAOM,GAAGH,GAAGC,CAAC,GAAG,OAAO;CAC5B,IAAIC,QAAQ,KAAK,OAAO;CACxB,IAAIE,MAAMC,QAAQL,CAAC,KAAKI,MAAMC,QAAQJ,CAAC,GAAG;EACxC,IAAI,CAACG,MAAMC,QAAQL,CAAC,KAAK,CAACI,MAAMC,QAAQJ,CAAC,KAAKD,EAAEM,WAAWL,EAAEK,QAC3D,OAAO;EACT,KAAK,IAAIC,IAAI,GAAGA,IAAIP,EAAEM,QAAQC,KAC5B,IAAI,CAACR,kBAAkBC,EAAEO,IAAIN,EAAEM,IAAIL,QAAQ,CAAC,GAAG,OAAO;EAExD,OAAO;CACT;CACA,IAAI,CAACT,cAAcO,CAAC,KAAK,CAACP,cAAcQ,CAAC,GAAG,OAAO;CACnD,MAAMO,QAAQX,OAAOY,KAAKT,CAAC;CAC3B,OACEQ,MAAMF,WAAWT,OAAOY,KAAKR,CAAC,CAAC,CAACK,UAChCE,MAAME,OACHC,QACCd,OAAOe,OAAOX,GAAGU,GAAG,KAAKZ,kBAAkBC,EAAEW,MAAMV,EAAEU,MAAMT,QAAQ,CAAC,CACxE;AAEJ;AAEA,SAAAW,gBAAAnB,OAAAoB,WAAAC,gBAAAC,YAAAC,aAAAC,QAAAC,IAAA;CAAA,MAAAC,IAAA7C,EAAA,EAAA;CAOE,MAAA8C,UAAAF,OAAAG,KAAAA,IAAqDzB,OAAMM,KAA3DgB;CAA8D,IAAAI;CAAA,IAAAH,EAAA,OAAAN,aAAAM,EAAA,OAAAC,WAAAD,EAAA,OAAAH,eAAAG,EAAA,OAAAF,UAAAE,EAAA,OAAAJ,cAAAI,EAAA,OAAA1B,SAAA0B,EAAA,OAAAL,gBAAA;EAEpDQ,WAAA;GACR,IAAI,CAACT,UAASU,SAAQ;GAItB,IAAI9B,UAAU4B,KAAAA,KAAaD,QAAQJ,YAAWO,SAAU9B,KAAK,GAAC;IAC5DsB,WAAUQ,UAAWF,KAAAA;IAAH;GAAA;GAGpB,IAAI,CAACP,eAAcS,SAAQ;IACzBR,WAAUQ,UAAW9B;IAAH;GAAA;GAGpBwB,OAAOJ,UAASU,SAAU9B,KAAK;GAC/BuB,YAAWO,UAAW9B;EAAH;EAEpB0B,EAAA,KAAAN;EAAAM,EAAA,KAAAC;EAAAD,EAAA,KAAAH;EAAAG,EAAA,KAAAF;EAAAE,EAAA,KAAAJ;EAAAI,EAAA,KAAA1B;EAAA0B,EAAA,KAAAL;EAAAK,EAAA,KAAAG;CAAA,OAAAA,KAAAH,EAAA;CAAA,IAAAK;CAAA,IAAAL,EAAA,OAAA1B,OAAA;EAAE+B,KAAA,CAAC/B,KAAK;EAAC0B,EAAA,KAAA1B;EAAA0B,EAAA,KAAAK;CAAA,OAAAA,KAAAL,EAAA;CAhBV3C,UAAU8C,IAgBPE,EAAO;AAAC;AAwBb,SAASa,kBACPC,SACAC,SACAC,WACsB;CACtB,MAAMC,aAAaF,QAAQhB,QAAQG;CACnC,MAAMgB,OAA6ChC,QACjD4B,UAAU5B,SAASW,KAAAA;CACrB,MAAMuB,MAA4B,CAAC;CACnChD,OAAOiD,eAAeD,KAAK,gBAAgB;EACzCE,WAAWL,KAAK,CAAC,EAAEM;EACnBC,YAAY;EACZC,cAAc;CAChB,CAAC;CACD,MAAMC,YACJxC,UAEE0C,MAAe;EACf,MAAMC,KAAKZ,KAAK,CAAC,GAAG/B;EACpB,IAAI,CAAC2C,IACH,MAAM,IAAIC,MAAM,GAAG5C,IAAG,gCAAiC;EAEzD,OAAO2C,GAAGD,CAAC;CACb;CACF,IAAIV,IAAI,UAAU,GAAGE,IAAIW,WAAWL,SAAS,UAAU;CACvD,IAAIR,IAAI,cAAc,GAAGE,IAAIY,eAAeN,SAAS,cAAc;CACnE,IAAIR,IAAI,eAAe,GAAGE,IAAIa,gBAAgBP,SAAS,eAAe;CACtE,IAAIR,IAAI,UAAU,GAAGE,IAAIc,WAAWR,SAAS,UAAU;CACvD,IAAIR,IAAI,aAAa,GAAGE,IAAIe,cAAcT,SAAS,aAAa;CAChE,IAAIR,IAAI,oBAAoB,GAC1BE,IAAIgB,qBAAqBV,SAAS,oBAAoB;CACxD,IAAIR,IAAI,oBAAoB,GAC1BE,IAAIiB,qBAAqBX,SAAS,oBAAoB;CACxDN,IAAIX,gBAAgBmB,MAAM;EACxBZ,UAAUP,aAAamB,CAAC;EACxBX,KAAK,CAAC,EAAER,eAAemB,CAAC;CAC1B;CACAR,IAAIZ,sBAAsB;EACxBQ,UAAUR,cAAc;EACxBS,KAAK,CAAC,EAAET,gBAAgB;CAC1B;CACAY,IAAIkB,qBAAqBV,MAAMX,KAAK,CAAC,EAAEqB,oBAAoBV,CAAC;CAC5DR,IAAImB,SAASX,MAAMX,KAAK,CAAC,EAAEsB,QAAQX,CAAC;CACpCR,IAAIoB,WAAWC,MAAMxB,KAAK,CAAC,EAAEuB,UAAUC,CAAC;CACxC,OAAOrB;AACT;AAEA,SAAOsB,YAAAhD,IAAA;CAAA,MAAAC,IAAA7C,EAAA,EAAA;CAAqB,MAAA,EAAA6F,KAAAC,UAAAvC,OAAAC,QAAAuC,SAAA3C,UAAAC,UAAAC,aAAA0C,WAAAhD,OAAAJ;CAS1B,MAAAoD,YAAAhD,OAAAD,KAAAA,IAAA9B,qBAAA+B;CAEA,MAAAT,YAAkBnC,OAA4B,IAAI;CAClD,MAAA6F,mBAAyB7F,OAAgB2C,KAAAA,CAAS;CAClD,MAAAmD,oBAA0B9F,OAAgB2C,KAAAA,CAAS;CACnD,MAAAoD,yBAA+B/F,OAC7B2C,KAAAA,CACF;CAIA,MAAAP,iBAAuBpC,OAAO,KAAK;CACnC,MAAAgG,kBAAwBhG,OAAgB2C,KAAAA,CAAS;CACjD,MAAAsD,mBAAyBjG,OAAgB2C,KAAAA,CAAS;CAClD,MAAAuD,wBAA8BlG,OAC5B2C,KAAAA,CACF;CAAE,IAAAG;CAAA,IAAAL,EAAA,OAAAO,YAAAP,EAAA,OAAAS,eAAAT,EAAA,OAAAQ,YAAAR,EAAA,OAAAU,SAAAV,EAAA,OAAAW,QAAA;EAEmCN,KAAA;GAAAE;GAAAC;GAAAC;GAAAC;GAAAC;EAMrC;EAACX,EAAA,KAAAO;EAAAP,EAAA,KAAAS;EAAAT,EAAA,KAAAQ;EAAAR,EAAA,KAAAU;EAAAV,EAAA,KAAAW;EAAAX,EAAA,KAAAK;CAAA,OAAAA,KAAAL,EAAA;CAND,MAAAoB,UAAgB7D,OAAqB8C,EAMpC;CAAE,IAAAqD;CAAA,IAAAC;CAAA,IAAA3D,EAAA,OAAAO,YAAAP,EAAA,OAAAS,eAAAT,EAAA,OAAAQ,YAAAR,EAAA,OAAAU,SAAAV,EAAA,QAAAW,QAAA;EACa+C,WAAA;GACdtC,QAAOhB,UAAW;IAAAG;IAAAC;IAAAC;IAAAC;IAAAC;GAMlB;EANe;EAOdgD,KAAA;GAACpD;GAAUC;GAAUC;GAAaC;GAAOC;EAAM;EAACX,EAAA,KAAAO;EAAAP,EAAA,KAAAS;EAAAT,EAAA,KAAAQ;EAAAR,EAAA,KAAAU;EAAAV,EAAA,MAAAW;EAAAX,EAAA,MAAA0D;EAAA1D,EAAA,MAAA2D;CAAA,OAAA;EAAAD,KAAA1D,EAAA;EAAA2D,KAAA3D,EAAA;CAAA;CARnD1C,gBAAgBoG,IAQbC,EAAgD;CAAC,IAAAC;CAAA,IAAA5D,EAAA,QAAA6D,OAAAC,IAAA,2BAAA,GAAA;EAE/BF,MAAAG,OAAAC,SAAA;GAInB,MAAA5D,UAAgBgB,QAAOhB;GACvB,IAAA6D,gBAA0D;GAE1D,MAAAC,qBAAqB;IACnB,IAAIvE,eAAcS,SAAQ;IAC1BT,eAAcS,UAAW;IACzB,MAAAvB,IAAUa,UAASU;IACnB,IAAI,CAACvB,GAAC;IACN,IAAI0E,gBAAenD,YAAaF,KAAAA,GAAS;KACvCrB,EAACsF,gBAAiBZ,gBAAenD,OAAQ;KACzCgD,iBAAgBhD,UAAWmD,gBAAenD;KAC1CmD,gBAAenD,UAAWF,KAAAA;IAAH;IAEzB,IAAIsD,iBAAgBpD,YAAaF,KAAAA,GAAS;KACxCrB,EAACuF,iBAAkBZ,iBAAgBpD,OAAQ;KAC3CiD,kBAAiBjD,UAAWoD,iBAAgBpD;KAC5CoD,iBAAgBpD,UAAWF,KAAAA;IAAH;IAE1B,IAAIuD,sBAAqBrD,YAAaF,KAAAA,GAAS;KAC7CrB,EAACwF,yBAA0BZ,sBAAqBrD,OAAQ;KACxDkD,uBAAsBlD,UAAWqD,sBAAqBrD;KACtDqD,sBAAqBrD,UAAWF,KAAAA;IAAH;GAC9B;GAGH,MAAAoE,kBAAwBpD,kBAAkBd,QAAOG,UAAWa,SAAS;IAAAP,qBACpD;KACb,IAAIoD,kBAAkB,MAAI;MACxBM,aAAaN,aAAa;MAC1BA,gBAAgBA;KAAH;KAEfC,aAAa;IAAC;IACfpD,eACamB,MAAA;KACZ,IAAIA,EAAChB,UAAW,MAAM+C,KAAIQ,UAAWvC,EAAChB,MAAO;IAAE;GAEnD,CAAC;GAKDgD,gBAAgBQ,iBAAW;IACzBR,gBAAgBA;IAChBC,aAAa;GAAC,GACb/F,eAAe;GAElB,MAAAuG,SAAejH,mBAAmB;IAAAsG;IAAAxD,UAEtB+D;IAAe9D,UACfJ,QAAOI;IAASC,aACbL,QAAOK;GACtB,CAAC;GACDf,UAASU,UAAWsE;GAEpB,IAAItE,QAAOM,UAAWR,KAAAA,GAAWqD,gBAAenD,UAAWA,QAAOM;GAClE,IAAIN,QAAOO,WAAYT,KAAAA,GAAWsD,iBAAgBpD,UAAWA,QAAOO;GAIpE2C,uBAAsBlD,UAAWA,QAAOK,eAAP,CAAwB;GAA3B,OAEvB;IAAAkE,WACMD,OAAMC;IAAUC,eAClB;KACP,IAAIX,kBAAkB,MAAI;MACxBM,aAAaN,aAAa;MAC1BA,gBAAgBA;KAAH;KAEfS,OAAME,QAAS;KACflF,UAASU,UAAW;KACpBgD,iBAAgBhD,UAAWF,KAAAA;KAC3BmD,kBAAiBjD,UAAWF,KAAAA;KAC5BoD,uBAAsBlD,UAAWF,KAAAA;KACjCP,eAAcS,UAAW;KACzBmD,gBAAenD,UAAWF,KAAAA;KAC1BsD,iBAAgBpD,UAAWF,KAAAA;KAC3BuD,sBAAqBrD,UAAWF,KAAAA;IAAH;GAEjC;EAAC;EACFF,EAAA,MAAA4D;CAAA,OAAAA,KAAA5D,EAAA;CAnFD,MAAA6E,eAAqBjB;CAqFrBnE,gBACEiB,OACAhB,WACAC,gBACA4D,iBACAH,kBACA0B,KACF;CACArF,gBACEkB,QACAjB,WACAC,gBACA6D,kBACAH,mBACA0B,MACF;CACAtF,gBACEgB,aACAf,WACAC,gBACA8D,uBACAH,wBACA0B,QACArG,iBACF;CAAC,IAAAsG;CAAA,IAAAjF,EAAA,QAAAiD,SAAAiC,MAAA;EAIYD,KAAA,EAAAC,MAAQjC,SAAQiC,KAAM;EAAClF,EAAA,MAAAiD,SAAAiC;EAAAlF,EAAA,MAAAiF;CAAA,OAAAA,KAAAjF,EAAA;CAE9B,MAAAmF,KAAAnC,IAAGoC,WAAH,GAAkBpC,IAAGoC,SAAS,GAAInC,SAAQoC,QAASpC,SAAQoC;CAE7B,MAAAC,KAAApC,SAAOqC,WAAPrH;CAAmC,IAAAsH;CAAA,IAAAxF,EAAA,QAAAkD,WAAAlD,EAAA,QAAAsF,IAAA;EAA1DE,KAAA;GAAA,GAAKtC;GAAOqC,SAAWD;EAAoC;EAACtF,EAAA,MAAAkD;EAAAlD,EAAA,MAAAsF;EAAAtF,EAAA,MAAAwF;CAAA,OAAAA,KAAAxF,EAAA;CAAA,IAAAyF;CAAA,IAAAzF,EAAA,QAAA6D,OAAAC,IAAA,2BAAA,GAAA;EAG5D2B,OAAAC,QAAStE,QAAOhB,QAAQG,UAAkBsC,UAAG6C,GAAG;EAAC1F,EAAA,MAAAyF;CAAA,OAAAA,MAAAzF,EAAA;CAGzB,MAAA2F,MAAA1C,SAAQ2C,MAAoBC,gBAA5B,KAAA3F,KAAAA;CAElB,IAAA4F;CAAA,IAAA9F,EAAA,QAAAgD,IAAA+C,eAAA/F,EAAA,QAAA2F,KAAA;EAJCG,MAAA;GAAA,yBACW9C,IAAG+C;GAAY,+BACTJ;EAGjC;EAAC3F,EAAA,MAAAgD,IAAA+C;EAAA/F,EAAA,MAAA2F;EAAA3F,EAAA,MAAA8F;CAAA,OAAAA,MAAA9F,EAAA;CAAA,IAAAgG;CAAA,IAAAhG,EAAA,QAAAmD,aAAAnD,EAAA,QAAA8F,OAAA9F,EAAA,QAAAiF,MAAAjF,EAAA,QAAAmF,MAAAnF,EAAA,QAAAwF,IAAA;EAdHQ,MAAA,oBAAC,aAAD;GACW,SAAAf;GAEP,YAAAE;GAEO,SAAAK;GACErC;GACG0B;GACL,SAAAY;GACO,gBAAAK;EAKf,CAAA;EACD9F,EAAA,MAAAmD;EAAAnD,EAAA,MAAA8F;EAAA9F,EAAA,MAAAiF;EAAAjF,EAAA,MAAAmF;EAAAnF,EAAA,MAAAwF;EAAAxF,EAAA,MAAAgG;CAAA,OAAAA,MAAAhG,EAAA;CAAA,OAfFgG;AAeE;AA3KC,SAAAhB,OAAAiB,KAAAC,KAAA;CAAA,OAuJOrH,IAACwF,yBAA0B8B,GAAC;AAAC;AAvJpC,SAAApB,OAAAqB,KAAAC,KAAA;CAAA,OA+IOxH,IAACuF,iBAAkB+B,GAAC;AAAC;AA/I5B,SAAArB,MAAAwB,KAAAH,GAAA;CAAA,OAuIOtH,IAACsF,gBAAiBgC,CAAC;AAAC"}
@@ -1,6 +1,5 @@
1
- import { invokeCallbackSafely } from "../utils/invokeCallbackSafely.js";
2
1
  import "./types.js";
3
- import { isRecord } from "@assistant-ui/core/internal";
2
+ import { invokeUserCallback, isRecord } from "@assistant-ui/core/internal";
4
3
  //#region src/mcp-apps/bridge.ts
5
4
  const VALID_DISPLAY_MODES = [
6
5
  "inline",
@@ -41,7 +40,9 @@ function isNotification(msg) {
41
40
  }
42
41
  function createMcpAppBridge(opts) {
43
42
  const { frame, handlers = {}, hostInfo = DEFAULT_HOST_INFO, hostContext = {} } = opts;
43
+ let disposed = false;
44
44
  const post = (msg) => {
45
+ if (disposed) return;
45
46
  frame.sendMessage(msg);
46
47
  };
47
48
  const respond = (id, payload) => {
@@ -60,7 +61,8 @@ function createMcpAppBridge(opts) {
60
61
  } });
61
62
  };
62
63
  const reportError = (error) => {
63
- invokeCallbackSafely(() => handlers.onError?.(error), "MCP App onError");
64
+ if (disposed) return;
65
+ invokeUserCallback("assistant-ui", "MCP App onError", handlers.onError?.bind(handlers), error);
64
66
  };
65
67
  const handleRequest = async (req) => {
66
68
  try {
@@ -235,6 +237,7 @@ function createMcpAppBridge(opts) {
235
237
  }
236
238
  };
237
239
  const onMessage = (event) => {
240
+ if (disposed) return;
238
241
  if (!isJsonRpcMessage(event.data)) return;
239
242
  const msg = event.data;
240
243
  if (isRequest(msg)) handleRequest(msg);
@@ -242,7 +245,9 @@ function createMcpAppBridge(opts) {
242
245
  };
243
246
  return {
244
247
  onMessage,
245
- dispose: () => {},
248
+ dispose: () => {
249
+ disposed = true;
250
+ },
246
251
  notifyToolInput: (input) => {
247
252
  post({
248
253
  jsonrpc: "2.0",
@@ -1 +1 @@
1
- {"version":3,"file":"bridge.js","names":["SandboxHostFrame","invokeCallbackSafely","MCP_APP_PROTOCOL_VERSION","McpAppBridgeHandlers","McpAppDisplayMode","McpAppHostContext","McpAppHostInfo","McpAppJsonRpcMessage","McpAppJsonRpcNotification","McpAppJsonRpcRequest","McpAppJsonRpcResponse","isRecord","VALID_DISPLAY_MODES","const","McpAppBridgeFrame","CreateMcpAppBridgeOptions","frame","handlers","hostInfo","hostContext","McpAppBridge","onMessage","event","MessageEvent","dispose","notifyToolInput","input","notifyToolResult","result","notifyHostContextChanged","DEFAULT_HOST_INFO","name","version","METHOD_ALIASES","Record","normalizeMethod","method","JSONRPC_ERROR","parseError","invalidRequest","methodNotFound","invalidParams","internalError","isJsonRpcMessage","value","v","jsonrpc","isRequest","msg","isNotification","createMcpAppBridge","opts","post","sendMessage","respond","id","payload","error","code","message","data","res","errorResponse","undefined","reportError","Error","onError","handleRequest","req","params","requestedProtocolVersion","protocolVersion","host","capabilities","tools","callTool","resources","readResource","listResources","ui","openLink","requestDisplayMode","updateModelContext","hostCapabilities","openLinks","serverTools","serverResources","text","onLog","logging","callParams","arguments","allowedTools","includes","callArgs","Array","isArray","readParams","uri","linkParams","url","linkProtocol","URL","protocol","modeParams","mode","err","String","handleNotification","note","onInitialized","p","width","height","onSizeChange","onRequestTeardown","content","type","ctx"],"sources":["../../src/mcp-apps/bridge.ts"],"sourcesContent":["import type { SandboxHostFrame } from \"../sandbox-host/SandboxHost\";\nimport { invokeCallbackSafely } from \"../utils/invokeCallbackSafely\";\nimport {\n MCP_APP_PROTOCOL_VERSION,\n type McpAppBridgeHandlers,\n type McpAppDisplayMode,\n type McpAppHostContext,\n type McpAppHostInfo,\n type McpAppJsonRpcMessage,\n type McpAppJsonRpcNotification,\n type McpAppJsonRpcRequest,\n type McpAppJsonRpcResponse,\n} from \"./types\";\nimport { isRecord } from \"@assistant-ui/core/internal\";\n\nconst VALID_DISPLAY_MODES = [\n \"inline\",\n \"fullscreen\",\n \"pip\",\n] as const satisfies readonly McpAppDisplayMode[];\n\nexport type McpAppBridgeFrame = SandboxHostFrame;\n\nexport type CreateMcpAppBridgeOptions = {\n frame: McpAppBridgeFrame;\n handlers?: McpAppBridgeHandlers | undefined;\n hostInfo?: McpAppHostInfo | undefined;\n hostContext?: McpAppHostContext | undefined;\n};\n\nexport type McpAppBridge = {\n onMessage: (event: MessageEvent) => void;\n dispose: () => void;\n notifyToolInput: (input: unknown) => void;\n notifyToolResult: (result: unknown) => void;\n notifyHostContextChanged: (hostContext: McpAppHostContext) => void;\n};\n\nconst DEFAULT_HOST_INFO: McpAppHostInfo = {\n name: \"assistant-ui\",\n version: \"0.1\",\n};\n\n// Accept both the legacy method names and the MCP-UI 2026-01-26 names that\n// `ui/*` capable widgets (e.g. xmcp's host-bridge) emit. Normalize on input\n// so downstream switch statements only need to know the legacy names.\nconst METHOD_ALIASES: Record<string, string> = {\n \"ui/notifications/initialized\": \"notifications/initialized\",\n \"ui/notifications/size-changed\": \"notifications/size_changed\",\n \"ui/request-display-mode\": \"requestDisplayMode\",\n \"ui/open-link\": \"openLink\",\n \"ui/update-model-context\": \"updateModelContext\",\n \"ui/message\": \"sendMessage\",\n \"notifications/message\": \"notifications/log\",\n};\n\nconst normalizeMethod = (method: string): string =>\n METHOD_ALIASES[method] ?? method;\n\nconst JSONRPC_ERROR = {\n parseError: -32700,\n invalidRequest: -32600,\n methodNotFound: -32601,\n invalidParams: -32602,\n internalError: -32603,\n} as const;\n\nfunction isJsonRpcMessage(value: unknown): value is McpAppJsonRpcMessage {\n if (!value || typeof value !== \"object\") return false;\n const v = value as Record<string, unknown>;\n return v.jsonrpc === \"2.0\" && typeof v.method === \"string\";\n}\n\nfunction isRequest(msg: McpAppJsonRpcMessage): msg is McpAppJsonRpcRequest {\n return \"id\" in msg;\n}\n\nfunction isNotification(\n msg: McpAppJsonRpcMessage,\n): msg is McpAppJsonRpcNotification {\n return !(\"id\" in msg);\n}\n\nexport function createMcpAppBridge(\n opts: CreateMcpAppBridgeOptions,\n): McpAppBridge {\n const {\n frame,\n handlers = {},\n hostInfo = DEFAULT_HOST_INFO,\n hostContext = {},\n } = opts;\n\n const post = (msg: McpAppJsonRpcMessage) => {\n frame.sendMessage(msg);\n };\n\n const respond = (\n id: McpAppJsonRpcRequest[\"id\"],\n payload:\n | { result: unknown }\n | { error: { code: number; message: string; data?: unknown } },\n ) => {\n const res: McpAppJsonRpcResponse = {\n jsonrpc: \"2.0\",\n id,\n ...payload,\n };\n post(res);\n };\n\n const errorResponse = (\n id: McpAppJsonRpcRequest[\"id\"],\n code: number,\n message: string,\n data?: unknown,\n ) => {\n respond(id, {\n error: {\n code,\n message,\n ...(data !== undefined ? { data } : {}),\n },\n });\n };\n\n const reportError = (error: Error) => {\n invokeCallbackSafely(() => handlers.onError?.(error), \"MCP App onError\");\n };\n\n const handleRequest = async (req: McpAppJsonRpcRequest) => {\n try {\n const params = req.params;\n\n switch (normalizeMethod(req.method)) {\n case \"ui/initialize\": {\n const requestedProtocolVersion =\n isRecord(params) && typeof params.protocolVersion === \"string\"\n ? params.protocolVersion\n : MCP_APP_PROTOCOL_VERSION;\n respond(req.id, {\n result: {\n protocolVersion: requestedProtocolVersion,\n host: hostInfo,\n hostInfo,\n hostContext,\n capabilities: {\n tools: handlers.callTool ? {} : undefined,\n resources:\n handlers.readResource || handlers.listResources\n ? {}\n : undefined,\n ui: {\n sendMessage: !!handlers.sendMessage,\n openLink: !!handlers.openLink,\n requestDisplayMode: !!handlers.requestDisplayMode,\n updateModelContext: !!handlers.updateModelContext,\n },\n },\n hostCapabilities: {\n ...(handlers.openLink ? { openLinks: {} } : {}),\n ...(handlers.callTool ? { serverTools: {} } : {}),\n ...(handlers.readResource || handlers.listResources\n ? { serverResources: {} }\n : {}),\n ...(handlers.updateModelContext\n ? { updateModelContext: { text: {} } }\n : {}),\n ...(handlers.sendMessage ? { message: { text: {} } } : {}),\n ...(handlers.onLog ? { logging: {} } : {}),\n },\n },\n });\n return;\n }\n\n case \"tools/call\": {\n if (!handlers.callTool) {\n errorResponse(\n req.id,\n JSONRPC_ERROR.methodNotFound,\n \"tools/call is not supported by this host\",\n );\n return;\n }\n const callParams = (params ?? {}) as {\n name?: unknown;\n arguments?: unknown;\n };\n if (typeof callParams.name !== \"string\") {\n errorResponse(\n req.id,\n JSONRPC_ERROR.invalidParams,\n \"tools/call requires a string 'name'\",\n );\n return;\n }\n if (\n handlers.allowedTools &&\n !handlers.allowedTools.includes(callParams.name)\n ) {\n errorResponse(\n req.id,\n JSONRPC_ERROR.invalidParams,\n `tool '${callParams.name}' is not allowed for this app`,\n );\n return;\n }\n let callArgs: Record<string, unknown> | undefined;\n if (callParams.arguments !== undefined) {\n if (\n callParams.arguments === null ||\n typeof callParams.arguments !== \"object\" ||\n Array.isArray(callParams.arguments)\n ) {\n errorResponse(\n req.id,\n JSONRPC_ERROR.invalidParams,\n \"tools/call 'arguments' must be an object\",\n );\n return;\n }\n callArgs = callParams.arguments as Record<string, unknown>;\n }\n const result = await handlers.callTool({\n name: callParams.name,\n ...(callArgs !== undefined ? { arguments: callArgs } : {}),\n });\n respond(req.id, { result });\n return;\n }\n\n case \"resources/read\": {\n if (!handlers.readResource) {\n errorResponse(\n req.id,\n JSONRPC_ERROR.methodNotFound,\n \"resources/read is not supported by this host\",\n );\n return;\n }\n const readParams = (params ?? {}) as { uri?: unknown };\n if (typeof readParams.uri !== \"string\") {\n errorResponse(\n req.id,\n JSONRPC_ERROR.invalidParams,\n \"resources/read requires a string 'uri'\",\n );\n return;\n }\n respond(req.id, {\n result: await handlers.readResource({ uri: readParams.uri }),\n });\n return;\n }\n\n case \"resources/list\": {\n if (!handlers.listResources) {\n errorResponse(\n req.id,\n JSONRPC_ERROR.methodNotFound,\n \"resources/list is not supported by this host\",\n );\n return;\n }\n respond(req.id, {\n result: (await handlers.listResources(params)) ?? null,\n });\n return;\n }\n\n case \"openLink\": {\n if (!handlers.openLink) {\n errorResponse(\n req.id,\n JSONRPC_ERROR.methodNotFound,\n \"openLink is not supported by this host\",\n );\n return;\n }\n const linkParams = (params ?? {}) as { url?: unknown };\n if (typeof linkParams.url !== \"string\") {\n errorResponse(\n req.id,\n JSONRPC_ERROR.invalidParams,\n \"openLink requires a string 'url'\",\n );\n return;\n }\n let linkProtocol: string;\n try {\n linkProtocol = new URL(linkParams.url).protocol;\n } catch {\n errorResponse(\n req.id,\n JSONRPC_ERROR.invalidParams,\n \"openLink requires a valid URL\",\n );\n return;\n }\n if (linkProtocol !== \"https:\" && linkProtocol !== \"http:\") {\n errorResponse(\n req.id,\n JSONRPC_ERROR.invalidParams,\n \"openLink only accepts http(s) URLs\",\n );\n return;\n }\n respond(req.id, {\n result: await handlers.openLink({ url: linkParams.url }),\n });\n return;\n }\n\n case \"sendMessage\": {\n if (!handlers.sendMessage) {\n errorResponse(\n req.id,\n JSONRPC_ERROR.methodNotFound,\n \"sendMessage is not supported by this host\",\n );\n return;\n }\n respond(req.id, {\n result: (await handlers.sendMessage(params)) ?? null,\n });\n return;\n }\n\n case \"updateModelContext\": {\n if (!handlers.updateModelContext) {\n errorResponse(\n req.id,\n JSONRPC_ERROR.methodNotFound,\n \"updateModelContext is not supported by this host\",\n );\n return;\n }\n respond(req.id, {\n result: (await handlers.updateModelContext(params)) ?? null,\n });\n return;\n }\n\n case \"requestDisplayMode\": {\n if (!handlers.requestDisplayMode) {\n errorResponse(\n req.id,\n JSONRPC_ERROR.methodNotFound,\n \"requestDisplayMode is not supported by this host\",\n );\n return;\n }\n const modeParams = (params ?? {}) as { mode?: unknown };\n if (\n typeof modeParams.mode !== \"string\" ||\n !VALID_DISPLAY_MODES.includes(modeParams.mode as McpAppDisplayMode)\n ) {\n errorResponse(\n req.id,\n JSONRPC_ERROR.invalidParams,\n \"requestDisplayMode requires a valid 'mode'\",\n );\n return;\n }\n respond(req.id, {\n result: await handlers.requestDisplayMode({\n mode: modeParams.mode as McpAppDisplayMode,\n }),\n });\n return;\n }\n\n default: {\n errorResponse(\n req.id,\n JSONRPC_ERROR.methodNotFound,\n `Unknown method: ${req.method}`,\n );\n }\n }\n } catch (err) {\n const error = err instanceof Error ? err : new Error(String(err));\n reportError(error);\n errorResponse(req.id, JSONRPC_ERROR.internalError, error.message);\n }\n };\n\n const handleNotification = (note: McpAppJsonRpcNotification) => {\n try {\n switch (normalizeMethod(note.method)) {\n case \"notifications/initialized\": {\n handlers.onInitialized?.();\n return;\n }\n case \"notifications/size_changed\": {\n const p = (note.params ?? {}) as { width?: number; height?: number };\n handlers.onSizeChange?.({\n ...(typeof p.width === \"number\" ? { width: p.width } : {}),\n ...(typeof p.height === \"number\" ? { height: p.height } : {}),\n });\n return;\n }\n case \"notifications/log\": {\n handlers.onLog?.(note.params);\n return;\n }\n case \"notifications/request_teardown\": {\n handlers.onRequestTeardown?.(note.params);\n return;\n }\n case \"notifications/error\": {\n const p = (note.params ?? {}) as { message?: string };\n reportError(\n new Error(\n typeof p.message === \"string\" ? p.message : \"Widget error\",\n ),\n );\n return;\n }\n default:\n return;\n }\n } catch (err) {\n const error = err instanceof Error ? err : new Error(String(err));\n reportError(error);\n }\n };\n\n // The host applies the cross-origin guard before delegating; this only\n // validates the JSON-RPC envelope.\n const onMessage = (event: MessageEvent) => {\n if (!isJsonRpcMessage(event.data)) return;\n\n const msg = event.data;\n if (isRequest(msg)) {\n void handleRequest(msg);\n } else if (isNotification(msg)) {\n handleNotification(msg);\n }\n };\n\n return {\n onMessage,\n dispose: () => {},\n notifyToolInput: (input: unknown) => {\n post({\n jsonrpc: \"2.0\",\n method: \"notifications/tools/call/input\",\n params: { input },\n });\n post({\n jsonrpc: \"2.0\",\n method: \"ui/notifications/tool-input\",\n params: isRecord(input) ? { arguments: input } : {},\n });\n },\n notifyToolResult: (result: unknown) => {\n post({\n jsonrpc: \"2.0\",\n method: \"notifications/tools/call/result\",\n params: { result },\n });\n post({\n jsonrpc: \"2.0\",\n method: \"ui/notifications/tool-result\",\n params: isRecord(result)\n ? result\n : { content: [{ type: \"text\", text: String(result) }] },\n });\n },\n notifyHostContextChanged: (ctx: McpAppHostContext) => {\n post({\n jsonrpc: \"2.0\",\n method: \"notifications/host_context/changed\",\n params: ctx,\n });\n post({\n jsonrpc: \"2.0\",\n method: \"ui/notifications/host-context-changed\",\n params: ctx,\n });\n },\n };\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"bridge.js","names":["SandboxHostFrame","invokeUserCallback","MCP_APP_PROTOCOL_VERSION","McpAppBridgeHandlers","McpAppDisplayMode","McpAppHostContext","McpAppHostInfo","McpAppJsonRpcMessage","McpAppJsonRpcNotification","McpAppJsonRpcRequest","McpAppJsonRpcResponse","isRecord","VALID_DISPLAY_MODES","const","McpAppBridgeFrame","CreateMcpAppBridgeOptions","frame","handlers","hostInfo","hostContext","McpAppBridge","onMessage","event","MessageEvent","dispose","notifyToolInput","input","notifyToolResult","result","notifyHostContextChanged","DEFAULT_HOST_INFO","name","version","METHOD_ALIASES","Record","normalizeMethod","method","JSONRPC_ERROR","parseError","invalidRequest","methodNotFound","invalidParams","internalError","isJsonRpcMessage","value","v","jsonrpc","isRequest","msg","isNotification","createMcpAppBridge","opts","disposed","post","sendMessage","respond","id","payload","error","code","message","data","res","errorResponse","undefined","reportError","Error","onError","bind","handleRequest","req","params","requestedProtocolVersion","protocolVersion","host","capabilities","tools","callTool","resources","readResource","listResources","ui","openLink","requestDisplayMode","updateModelContext","hostCapabilities","openLinks","serverTools","serverResources","text","onLog","logging","callParams","arguments","allowedTools","includes","callArgs","Array","isArray","readParams","uri","linkParams","url","linkProtocol","URL","protocol","modeParams","mode","err","String","handleNotification","note","onInitialized","p","width","height","onSizeChange","onRequestTeardown","content","type","ctx"],"sources":["../../src/mcp-apps/bridge.ts"],"sourcesContent":["import type { SandboxHostFrame } from \"../sandbox-host/SandboxHost\";\nimport { invokeUserCallback } from \"@assistant-ui/core/internal\";\nimport {\n MCP_APP_PROTOCOL_VERSION,\n type McpAppBridgeHandlers,\n type McpAppDisplayMode,\n type McpAppHostContext,\n type McpAppHostInfo,\n type McpAppJsonRpcMessage,\n type McpAppJsonRpcNotification,\n type McpAppJsonRpcRequest,\n type McpAppJsonRpcResponse,\n} from \"./types\";\nimport { isRecord } from \"@assistant-ui/core/internal\";\n\nconst VALID_DISPLAY_MODES = [\n \"inline\",\n \"fullscreen\",\n \"pip\",\n] as const satisfies readonly McpAppDisplayMode[];\n\nexport type McpAppBridgeFrame = SandboxHostFrame;\n\nexport type CreateMcpAppBridgeOptions = {\n frame: McpAppBridgeFrame;\n handlers?: McpAppBridgeHandlers | undefined;\n hostInfo?: McpAppHostInfo | undefined;\n hostContext?: McpAppHostContext | undefined;\n};\n\nexport type McpAppBridge = {\n onMessage: (event: MessageEvent) => void;\n dispose: () => void;\n notifyToolInput: (input: unknown) => void;\n notifyToolResult: (result: unknown) => void;\n notifyHostContextChanged: (hostContext: McpAppHostContext) => void;\n};\n\nconst DEFAULT_HOST_INFO: McpAppHostInfo = {\n name: \"assistant-ui\",\n version: \"0.1\",\n};\n\n// Accept both the legacy method names and the MCP-UI 2026-01-26 names that\n// `ui/*` capable widgets (e.g. xmcp's host-bridge) emit. Normalize on input\n// so downstream switch statements only need to know the legacy names.\nconst METHOD_ALIASES: Record<string, string> = {\n \"ui/notifications/initialized\": \"notifications/initialized\",\n \"ui/notifications/size-changed\": \"notifications/size_changed\",\n \"ui/request-display-mode\": \"requestDisplayMode\",\n \"ui/open-link\": \"openLink\",\n \"ui/update-model-context\": \"updateModelContext\",\n \"ui/message\": \"sendMessage\",\n \"notifications/message\": \"notifications/log\",\n};\n\nconst normalizeMethod = (method: string): string =>\n METHOD_ALIASES[method] ?? method;\n\nconst JSONRPC_ERROR = {\n parseError: -32700,\n invalidRequest: -32600,\n methodNotFound: -32601,\n invalidParams: -32602,\n internalError: -32603,\n} as const;\n\nfunction isJsonRpcMessage(value: unknown): value is McpAppJsonRpcMessage {\n if (!value || typeof value !== \"object\") return false;\n const v = value as Record<string, unknown>;\n return v.jsonrpc === \"2.0\" && typeof v.method === \"string\";\n}\n\nfunction isRequest(msg: McpAppJsonRpcMessage): msg is McpAppJsonRpcRequest {\n return \"id\" in msg;\n}\n\nfunction isNotification(\n msg: McpAppJsonRpcMessage,\n): msg is McpAppJsonRpcNotification {\n return !(\"id\" in msg);\n}\n\nexport function createMcpAppBridge(\n opts: CreateMcpAppBridgeOptions,\n): McpAppBridge {\n const {\n frame,\n handlers = {},\n hostInfo = DEFAULT_HOST_INFO,\n hostContext = {},\n } = opts;\n let disposed = false;\n\n const post = (msg: McpAppJsonRpcMessage) => {\n if (disposed) return;\n frame.sendMessage(msg);\n };\n\n const respond = (\n id: McpAppJsonRpcRequest[\"id\"],\n payload:\n | { result: unknown }\n | { error: { code: number; message: string; data?: unknown } },\n ) => {\n const res: McpAppJsonRpcResponse = {\n jsonrpc: \"2.0\",\n id,\n ...payload,\n };\n post(res);\n };\n\n const errorResponse = (\n id: McpAppJsonRpcRequest[\"id\"],\n code: number,\n message: string,\n data?: unknown,\n ) => {\n respond(id, {\n error: {\n code,\n message,\n ...(data !== undefined ? { data } : {}),\n },\n });\n };\n\n const reportError = (error: Error) => {\n if (disposed) return;\n invokeUserCallback(\n \"assistant-ui\",\n \"MCP App onError\",\n handlers.onError?.bind(handlers),\n error,\n );\n };\n\n const handleRequest = async (req: McpAppJsonRpcRequest) => {\n try {\n const params = req.params;\n\n switch (normalizeMethod(req.method)) {\n case \"ui/initialize\": {\n const requestedProtocolVersion =\n isRecord(params) && typeof params.protocolVersion === \"string\"\n ? params.protocolVersion\n : MCP_APP_PROTOCOL_VERSION;\n respond(req.id, {\n result: {\n protocolVersion: requestedProtocolVersion,\n host: hostInfo,\n hostInfo,\n hostContext,\n capabilities: {\n tools: handlers.callTool ? {} : undefined,\n resources:\n handlers.readResource || handlers.listResources\n ? {}\n : undefined,\n ui: {\n sendMessage: !!handlers.sendMessage,\n openLink: !!handlers.openLink,\n requestDisplayMode: !!handlers.requestDisplayMode,\n updateModelContext: !!handlers.updateModelContext,\n },\n },\n hostCapabilities: {\n ...(handlers.openLink ? { openLinks: {} } : {}),\n ...(handlers.callTool ? { serverTools: {} } : {}),\n ...(handlers.readResource || handlers.listResources\n ? { serverResources: {} }\n : {}),\n ...(handlers.updateModelContext\n ? { updateModelContext: { text: {} } }\n : {}),\n ...(handlers.sendMessage ? { message: { text: {} } } : {}),\n ...(handlers.onLog ? { logging: {} } : {}),\n },\n },\n });\n return;\n }\n\n case \"tools/call\": {\n if (!handlers.callTool) {\n errorResponse(\n req.id,\n JSONRPC_ERROR.methodNotFound,\n \"tools/call is not supported by this host\",\n );\n return;\n }\n const callParams = (params ?? {}) as {\n name?: unknown;\n arguments?: unknown;\n };\n if (typeof callParams.name !== \"string\") {\n errorResponse(\n req.id,\n JSONRPC_ERROR.invalidParams,\n \"tools/call requires a string 'name'\",\n );\n return;\n }\n if (\n handlers.allowedTools &&\n !handlers.allowedTools.includes(callParams.name)\n ) {\n errorResponse(\n req.id,\n JSONRPC_ERROR.invalidParams,\n `tool '${callParams.name}' is not allowed for this app`,\n );\n return;\n }\n let callArgs: Record<string, unknown> | undefined;\n if (callParams.arguments !== undefined) {\n if (\n callParams.arguments === null ||\n typeof callParams.arguments !== \"object\" ||\n Array.isArray(callParams.arguments)\n ) {\n errorResponse(\n req.id,\n JSONRPC_ERROR.invalidParams,\n \"tools/call 'arguments' must be an object\",\n );\n return;\n }\n callArgs = callParams.arguments as Record<string, unknown>;\n }\n const result = await handlers.callTool({\n name: callParams.name,\n ...(callArgs !== undefined ? { arguments: callArgs } : {}),\n });\n respond(req.id, { result });\n return;\n }\n\n case \"resources/read\": {\n if (!handlers.readResource) {\n errorResponse(\n req.id,\n JSONRPC_ERROR.methodNotFound,\n \"resources/read is not supported by this host\",\n );\n return;\n }\n const readParams = (params ?? {}) as { uri?: unknown };\n if (typeof readParams.uri !== \"string\") {\n errorResponse(\n req.id,\n JSONRPC_ERROR.invalidParams,\n \"resources/read requires a string 'uri'\",\n );\n return;\n }\n respond(req.id, {\n result: await handlers.readResource({ uri: readParams.uri }),\n });\n return;\n }\n\n case \"resources/list\": {\n if (!handlers.listResources) {\n errorResponse(\n req.id,\n JSONRPC_ERROR.methodNotFound,\n \"resources/list is not supported by this host\",\n );\n return;\n }\n respond(req.id, {\n result: (await handlers.listResources(params)) ?? null,\n });\n return;\n }\n\n case \"openLink\": {\n if (!handlers.openLink) {\n errorResponse(\n req.id,\n JSONRPC_ERROR.methodNotFound,\n \"openLink is not supported by this host\",\n );\n return;\n }\n const linkParams = (params ?? {}) as { url?: unknown };\n if (typeof linkParams.url !== \"string\") {\n errorResponse(\n req.id,\n JSONRPC_ERROR.invalidParams,\n \"openLink requires a string 'url'\",\n );\n return;\n }\n let linkProtocol: string;\n try {\n linkProtocol = new URL(linkParams.url).protocol;\n } catch {\n errorResponse(\n req.id,\n JSONRPC_ERROR.invalidParams,\n \"openLink requires a valid URL\",\n );\n return;\n }\n if (linkProtocol !== \"https:\" && linkProtocol !== \"http:\") {\n errorResponse(\n req.id,\n JSONRPC_ERROR.invalidParams,\n \"openLink only accepts http(s) URLs\",\n );\n return;\n }\n respond(req.id, {\n result: await handlers.openLink({ url: linkParams.url }),\n });\n return;\n }\n\n case \"sendMessage\": {\n if (!handlers.sendMessage) {\n errorResponse(\n req.id,\n JSONRPC_ERROR.methodNotFound,\n \"sendMessage is not supported by this host\",\n );\n return;\n }\n respond(req.id, {\n result: (await handlers.sendMessage(params)) ?? null,\n });\n return;\n }\n\n case \"updateModelContext\": {\n if (!handlers.updateModelContext) {\n errorResponse(\n req.id,\n JSONRPC_ERROR.methodNotFound,\n \"updateModelContext is not supported by this host\",\n );\n return;\n }\n respond(req.id, {\n result: (await handlers.updateModelContext(params)) ?? null,\n });\n return;\n }\n\n case \"requestDisplayMode\": {\n if (!handlers.requestDisplayMode) {\n errorResponse(\n req.id,\n JSONRPC_ERROR.methodNotFound,\n \"requestDisplayMode is not supported by this host\",\n );\n return;\n }\n const modeParams = (params ?? {}) as { mode?: unknown };\n if (\n typeof modeParams.mode !== \"string\" ||\n !VALID_DISPLAY_MODES.includes(modeParams.mode as McpAppDisplayMode)\n ) {\n errorResponse(\n req.id,\n JSONRPC_ERROR.invalidParams,\n \"requestDisplayMode requires a valid 'mode'\",\n );\n return;\n }\n respond(req.id, {\n result: await handlers.requestDisplayMode({\n mode: modeParams.mode as McpAppDisplayMode,\n }),\n });\n return;\n }\n\n default: {\n errorResponse(\n req.id,\n JSONRPC_ERROR.methodNotFound,\n `Unknown method: ${req.method}`,\n );\n }\n }\n } catch (err) {\n const error = err instanceof Error ? err : new Error(String(err));\n reportError(error);\n errorResponse(req.id, JSONRPC_ERROR.internalError, error.message);\n }\n };\n\n const handleNotification = (note: McpAppJsonRpcNotification) => {\n try {\n switch (normalizeMethod(note.method)) {\n case \"notifications/initialized\": {\n handlers.onInitialized?.();\n return;\n }\n case \"notifications/size_changed\": {\n const p = (note.params ?? {}) as { width?: number; height?: number };\n handlers.onSizeChange?.({\n ...(typeof p.width === \"number\" ? { width: p.width } : {}),\n ...(typeof p.height === \"number\" ? { height: p.height } : {}),\n });\n return;\n }\n case \"notifications/log\": {\n handlers.onLog?.(note.params);\n return;\n }\n case \"notifications/request_teardown\": {\n handlers.onRequestTeardown?.(note.params);\n return;\n }\n case \"notifications/error\": {\n const p = (note.params ?? {}) as { message?: string };\n reportError(\n new Error(\n typeof p.message === \"string\" ? p.message : \"Widget error\",\n ),\n );\n return;\n }\n default:\n return;\n }\n } catch (err) {\n const error = err instanceof Error ? err : new Error(String(err));\n reportError(error);\n }\n };\n\n // The host applies the cross-origin guard before delegating; this only\n // validates the JSON-RPC envelope.\n const onMessage = (event: MessageEvent) => {\n if (disposed) return;\n if (!isJsonRpcMessage(event.data)) return;\n\n const msg = event.data;\n if (isRequest(msg)) {\n void handleRequest(msg);\n } else if (isNotification(msg)) {\n handleNotification(msg);\n }\n };\n\n return {\n onMessage,\n dispose: () => {\n disposed = true;\n },\n notifyToolInput: (input: unknown) => {\n post({\n jsonrpc: \"2.0\",\n method: \"notifications/tools/call/input\",\n params: { input },\n });\n post({\n jsonrpc: \"2.0\",\n method: \"ui/notifications/tool-input\",\n params: isRecord(input) ? { arguments: input } : {},\n });\n },\n notifyToolResult: (result: unknown) => {\n post({\n jsonrpc: \"2.0\",\n method: \"notifications/tools/call/result\",\n params: { result },\n });\n post({\n jsonrpc: \"2.0\",\n method: \"ui/notifications/tool-result\",\n params: isRecord(result)\n ? result\n : { content: [{ type: \"text\", text: String(result) }] },\n });\n },\n notifyHostContextChanged: (ctx: McpAppHostContext) => {\n post({\n jsonrpc: \"2.0\",\n method: \"notifications/host_context/changed\",\n params: ctx,\n });\n post({\n jsonrpc: \"2.0\",\n method: \"ui/notifications/host-context-changed\",\n params: ctx,\n });\n },\n };\n}\n"],"mappings":"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"}
@@ -1,5 +1,5 @@
1
1
  import { McpAppBridgeHandlers, McpAppDisplayMode, McpAppHostContext, McpAppHostInfo, McpAppMetadata, McpAppResource, McpAppResourceCSP, McpAppResourceMeta, McpAppSandboxConfig, McpAppToolCallParams, McpAppsHost, McpAppsRemoteHostOptions, ToolCallMessagePartMcpMetadata } from "./types.js";
2
- import { McpAppRenderer, McpAppRendererOptions } from "./McpAppRenderer.js";
2
+ import { McpAppPartOptions, McpAppRenderer, McpAppRendererOptions } from "./McpAppRenderer.js";
3
3
  import { McpAppsRemoteHost } from "./McpAppsRemoteHost.js";
4
4
  import { getMcpAppFromToolPart } from "./utils.js";
5
- export { type McpAppBridgeHandlers, type McpAppDisplayMode, type McpAppHostContext, type McpAppHostInfo, type McpAppMetadata, McpAppRenderer, type McpAppRendererOptions, type McpAppResource, type McpAppResourceCSP, type McpAppResourceMeta, type McpAppSandboxConfig, type McpAppToolCallParams, type McpAppsHost, McpAppsRemoteHost, type McpAppsRemoteHostOptions, type ToolCallMessagePartMcpMetadata, getMcpAppFromToolPart };
5
+ export { type McpAppBridgeHandlers, type McpAppDisplayMode, type McpAppHostContext, type McpAppHostInfo, type McpAppMetadata, type McpAppPartOptions, McpAppRenderer, type McpAppRendererOptions, type McpAppResource, type McpAppResourceCSP, type McpAppResourceMeta, type McpAppSandboxConfig, type McpAppToolCallParams, type McpAppsHost, McpAppsRemoteHost, type McpAppsRemoteHostOptions, type ToolCallMessagePartMcpMetadata, getMcpAppFromToolPart };
@@ -1 +1 @@
1
- {"version":3,"file":"AssistantModalRoot.d.ts","names":[],"sources":["../../../src/primitives/assistantModal/AssistantModalRoot.tsx"],"mappings":";;;kBAOiB;OACH,QAAQ,QAAiB;IACnC;;;cA0BS,6BAA6B,GACxC,4BAA4B"}
1
+ {"version":3,"file":"AssistantModalRoot.d.ts","names":[],"sources":["../../../src/primitives/assistantModal/AssistantModalRoot.tsx"],"mappings":";;;kBAOiB;OACH,QAAQ,QAAiB;IACnC;;;cAIS,6BAA6B,GACxC,4BAA4B"}
@@ -1,109 +1,77 @@
1
1
  "use client";
2
2
  import { usePopoverScope } from "./scope.js";
3
3
  import { c } from "@assistant-ui/tap/react-shim/compiler-runtime";
4
- import { useAui } from "@assistant-ui/store";
5
- import { useEffect, useState } from "@assistant-ui/tap/react-shim";
4
+ import { useAuiEvent } from "@assistant-ui/store";
5
+ import { useState } from "@assistant-ui/tap/react-shim";
6
6
  import { jsx } from "react/jsx-runtime";
7
7
  import { Popover } from "radix-ui";
8
8
  //#region src/primitives/assistantModal/AssistantModalRoot.tsx
9
- const useAssistantModalOpenState = (t0) => {
10
- const $ = c(5);
11
- const { defaultOpen: t1, unstable_openOnRunStart: t2 } = t0;
12
- const defaultOpen = t1 === void 0 ? false : t1;
13
- const unstable_openOnRunStart = t2 === void 0 ? true : t2;
14
- const state = useState(defaultOpen);
15
- const [, setOpen] = state;
16
- const aui = useAui();
17
- let t3;
18
- let t4;
19
- if ($[0] !== aui || $[1] !== setOpen || $[2] !== unstable_openOnRunStart) {
20
- t3 = () => {
21
- if (!unstable_openOnRunStart) return;
22
- return aui.on("thread.runStart", () => {
23
- setOpen(true);
24
- });
25
- };
26
- t4 = [
27
- unstable_openOnRunStart,
28
- aui,
29
- setOpen
30
- ];
31
- $[0] = aui;
32
- $[1] = setOpen;
33
- $[2] = unstable_openOnRunStart;
34
- $[3] = t3;
35
- $[4] = t4;
36
- } else {
37
- t3 = $[3];
38
- t4 = $[4];
39
- }
40
- useEffect(t3, t4);
41
- return state;
42
- };
43
9
  const AssistantModalPrimitiveRoot = (t0) => {
44
10
  const $ = c(18);
45
11
  let __scopeAssistantModal;
46
- let defaultOpen;
47
12
  let onOpenChange;
48
13
  let open;
49
14
  let rest;
50
- let unstable_openOnRunStart;
15
+ let t1;
16
+ let t2;
51
17
  if ($[0] !== t0) {
52
- ({__scopeAssistantModal, defaultOpen, unstable_openOnRunStart, open, onOpenChange, ...rest} = t0);
18
+ ({__scopeAssistantModal, defaultOpen: t1, unstable_openOnRunStart: t2, open, onOpenChange, ...rest} = t0);
53
19
  $[0] = t0;
54
20
  $[1] = __scopeAssistantModal;
55
- $[2] = defaultOpen;
56
- $[3] = onOpenChange;
57
- $[4] = open;
58
- $[5] = rest;
59
- $[6] = unstable_openOnRunStart;
21
+ $[2] = onOpenChange;
22
+ $[3] = open;
23
+ $[4] = rest;
24
+ $[5] = t1;
25
+ $[6] = t2;
60
26
  } else {
61
27
  __scopeAssistantModal = $[1];
62
- defaultOpen = $[2];
63
- onOpenChange = $[3];
64
- open = $[4];
65
- rest = $[5];
66
- unstable_openOnRunStart = $[6];
28
+ onOpenChange = $[2];
29
+ open = $[3];
30
+ rest = $[4];
31
+ t1 = $[5];
32
+ t2 = $[6];
67
33
  }
34
+ const defaultOpen = t1 === void 0 ? false : t1;
35
+ const unstable_openOnRunStart = t2 === void 0 ? true : t2;
68
36
  const scope = usePopoverScope(__scopeAssistantModal);
69
- let t1;
70
- if ($[7] !== defaultOpen || $[8] !== unstable_openOnRunStart) {
71
- t1 = {
72
- defaultOpen,
73
- unstable_openOnRunStart
74
- };
75
- $[7] = defaultOpen;
76
- $[8] = unstable_openOnRunStart;
77
- $[9] = t1;
78
- } else t1 = $[9];
79
- const [modalOpen, setOpen] = useAssistantModalOpenState(t1);
80
- let t2;
81
- if ($[10] !== onOpenChange || $[11] !== setOpen) {
82
- t2 = (open_0) => {
37
+ const [modalOpen, setOpen] = useState(defaultOpen);
38
+ const isOpen = open ?? modalOpen;
39
+ let t3;
40
+ if ($[7] !== onOpenChange) {
41
+ t3 = (open_0) => {
83
42
  onOpenChange?.(open_0);
84
43
  setOpen(open_0);
85
44
  };
86
- $[10] = onOpenChange;
87
- $[11] = setOpen;
88
- $[12] = t2;
89
- } else t2 = $[12];
90
- const openChangeHandler = t2;
91
- const t3 = open === void 0 ? modalOpen : open;
45
+ $[7] = onOpenChange;
46
+ $[8] = t3;
47
+ } else t3 = $[8];
48
+ const openChangeHandler = t3;
92
49
  let t4;
93
- if ($[13] !== openChangeHandler || $[14] !== rest || $[15] !== scope || $[16] !== t3) {
94
- t4 = /* @__PURE__ */ jsx(Popover.Root, {
50
+ if ($[9] !== isOpen || $[10] !== openChangeHandler || $[11] !== unstable_openOnRunStart) {
51
+ t4 = () => {
52
+ if (unstable_openOnRunStart && !isOpen) openChangeHandler(true);
53
+ };
54
+ $[9] = isOpen;
55
+ $[10] = openChangeHandler;
56
+ $[11] = unstable_openOnRunStart;
57
+ $[12] = t4;
58
+ } else t4 = $[12];
59
+ useAuiEvent("thread.runStart", t4);
60
+ let t5;
61
+ if ($[13] !== isOpen || $[14] !== openChangeHandler || $[15] !== rest || $[16] !== scope) {
62
+ t5 = /* @__PURE__ */ jsx(Popover.Root, {
95
63
  ...scope,
96
- open: t3,
64
+ open: isOpen,
97
65
  onOpenChange: openChangeHandler,
98
66
  ...rest
99
67
  });
100
- $[13] = openChangeHandler;
101
- $[14] = rest;
102
- $[15] = scope;
103
- $[16] = t3;
104
- $[17] = t4;
105
- } else t4 = $[17];
106
- return t4;
68
+ $[13] = isOpen;
69
+ $[14] = openChangeHandler;
70
+ $[15] = rest;
71
+ $[16] = scope;
72
+ $[17] = t5;
73
+ } else t5 = $[17];
74
+ return t5;
107
75
  };
108
76
  AssistantModalPrimitiveRoot.displayName = "AssistantModalPrimitive.Root";
109
77
  //#endregion
@@ -1 +1 @@
1
- {"version":3,"file":"AssistantModalRoot.js","names":["c","_c","FC","useEffect","useState","Popover","PopoverPrimitive","ScopedProps","usePopoverScope","useAui","AssistantModalPrimitiveRoot","Props","PopoverProps","unstable_openOnRunStart","useAssistantModalOpenState","t0","$","defaultOpen","t1","t2","undefined","state","setOpen","aui","t3","t4","on","__scopeAssistantModal","onOpenChange","open","rest","scope","modalOpen","open_0","openChangeHandler","displayName"],"sources":["../../../src/primitives/assistantModal/AssistantModalRoot.tsx"],"sourcesContent":["\"use client\";\n\nimport { type FC, useEffect, useState } from \"react\";\nimport { Popover as PopoverPrimitive } from \"radix-ui\";\nimport { type ScopedProps, usePopoverScope } from \"./scope\";\nimport { useAui } from \"@assistant-ui/store\";\n\nexport namespace AssistantModalPrimitiveRoot {\n export type Props = PopoverPrimitive.PopoverProps & {\n unstable_openOnRunStart?: boolean | undefined;\n };\n}\n\nconst useAssistantModalOpenState = ({\n defaultOpen = false,\n unstable_openOnRunStart = true,\n}: {\n defaultOpen?: boolean | undefined;\n unstable_openOnRunStart?: boolean | undefined;\n}) => {\n const state = useState(defaultOpen);\n\n const [, setOpen] = state;\n const aui = useAui();\n useEffect(() => {\n if (!unstable_openOnRunStart) return undefined;\n\n return aui.on(\"thread.runStart\", () => {\n setOpen(true);\n });\n }, [unstable_openOnRunStart, aui, setOpen]);\n\n return state;\n};\n\nexport const AssistantModalPrimitiveRoot: FC<\n AssistantModalPrimitiveRoot.Props\n> = ({\n __scopeAssistantModal,\n defaultOpen,\n unstable_openOnRunStart,\n open,\n onOpenChange,\n ...rest\n}: ScopedProps<AssistantModalPrimitiveRoot.Props>) => {\n const scope = usePopoverScope(__scopeAssistantModal);\n\n const [modalOpen, setOpen] = useAssistantModalOpenState({\n defaultOpen,\n unstable_openOnRunStart,\n });\n\n const openChangeHandler = (open: boolean) => {\n onOpenChange?.(open);\n setOpen(open);\n };\n\n return (\n <PopoverPrimitive.Root\n {...scope}\n open={open === undefined ? modalOpen : open}\n onOpenChange={openChangeHandler}\n {...rest}\n />\n );\n};\n\nAssistantModalPrimitiveRoot.displayName = \"AssistantModalPrimitive.Root\";\n"],"mappings":";;;;;;;;AAaA,MAAMc,8BAA6BC,OAAA;CAAA,MAAAC,IAAAf,EAAA,CAAA;CAAC,MAAA,EAAAgB,aAAAC,IAAAL,yBAAAM,OAAAJ;CAClC,MAAAE,cAAAC,OAAAE,KAAAA,IAAA,QAAAF;CACA,MAAAL,0BAAAM,OAAAC,KAAAA,IAAA,OAAAD;CAKA,MAAAE,QAAcjB,SAASa,WAAW;CAElC,MAAA,GAAAK,WAAoBD;CACpB,MAAAE,MAAYd,OAAO;CAAE,IAAAe;CAAA,IAAAC;CAAA,IAAAT,EAAA,OAAAO,OAAAP,EAAA,OAAAM,WAAAN,EAAA,OAAAH,yBAAA;EACXW,WAAA;GACR,IAAI,CAACX,yBAAuB;GAAmB,OAExCU,IAAGG,GAAI,yBAAmB;IAC/BJ,QAAQ,IAAI;GAAC,CACd;EAAC;EACDG,KAAA;GAACZ;GAAyBU;GAAKD;EAAO;EAACN,EAAA,KAAAO;EAAAP,EAAA,KAAAM;EAAAN,EAAA,KAAAH;EAAAG,EAAA,KAAAQ;EAAAR,EAAA,KAAAS;CAAA,OAAA;EAAAD,KAAAR,EAAA;EAAAS,KAAAT,EAAA;CAAA;CAN1Cb,UAAUqB,IAMPC,EAAuC;CAAC,OAEpCJ;AAAK;AAGd,MAAaX,+BAETK,OAAA;CAAA,MAAAC,IAAAf,EAAA,EAAA;CAAA,IAAA0B;CAAA,IAAAV;CAAA,IAAAW;CAAA,IAAAC;CAAA,IAAAC;CAAA,IAAAjB;CAAA,IAAAG,EAAA,OAAAD,IAAA;EAAC,CAAA,CAAAY,uBAAAV,aAAAJ,yBAAAgB,MAAAD,cAAA,GAAAE,QAAAf;EAO4CC,EAAA,KAAAD;EAAAC,EAAA,KAAAW;EAAAX,EAAA,KAAAC;EAAAD,EAAA,KAAAY;EAAAZ,EAAA,KAAAa;EAAAb,EAAA,KAAAc;EAAAd,EAAA,KAAAH;CAAA,OAAA;EAAAc,wBAAAX,EAAA;EAAAC,cAAAD,EAAA;EAAAY,eAAAZ,EAAA;EAAAa,OAAAb,EAAA;EAAAc,OAAAd,EAAA;EAAAH,0BAAAG,EAAA;CAAA;CAC/C,MAAAe,QAAcvB,gBAAgBmB,qBAAqB;CAAE,IAAAT;CAAA,IAAAF,EAAA,OAAAC,eAAAD,EAAA,OAAAH,yBAAA;EAEGK,KAAA;GAAAD;GAAAJ;EAGxD;EAACG,EAAA,KAAAC;EAAAD,EAAA,KAAAH;EAAAG,EAAA,KAAAE;CAAA,OAAAA,KAAAF,EAAA;CAHD,MAAA,CAAAgB,WAAAV,WAA6BR,2BAA2BI,EAGvD;CAAE,IAAAC;CAAA,IAAAH,EAAA,QAAAY,gBAAAZ,EAAA,QAAAM,SAAA;EAEuBH,MAAAc,WAAA;GACxBL,eAAeC,MAAI;GACnBP,QAAQO,MAAI;EAAC;EACdb,EAAA,MAAAY;EAAAZ,EAAA,MAAAM;EAAAN,EAAA,MAAAG;CAAA,OAAAA,KAAAH,EAAA;CAHD,MAAAkB,oBAA0Bf;CAQhB,MAAAK,KAAAK,SAAST,KAAAA,IAATY,YAAAH;CAAqC,IAAAJ;CAAA,IAAAT,EAAA,QAAAkB,qBAAAlB,EAAA,QAAAc,QAAAd,EAAA,QAAAe,SAAAf,EAAA,QAAAQ,IAAA;EAF7CC,KAAA,oBAAA,QAAA,MAAA;GAAA,GACMM;GACE,MAAAP;GACQU,cAAAA;GAAiB,GAC3BJ;EAAI,CAAA;EACRd,EAAA,MAAAkB;EAAAlB,EAAA,MAAAc;EAAAd,EAAA,MAAAe;EAAAf,EAAA,MAAAQ;EAAAR,EAAA,MAAAS;CAAA,OAAAA,KAAAT,EAAA;CAAA,OALFS;AAKE;AAINf,4BAA4ByB,cAAc"}
1
+ {"version":3,"file":"AssistantModalRoot.js","names":["c","_c","FC","useState","Popover","PopoverPrimitive","ScopedProps","usePopoverScope","useAuiEvent","AssistantModalPrimitiveRoot","Props","PopoverProps","unstable_openOnRunStart","t0","$","__scopeAssistantModal","onOpenChange","open","rest","t1","t2","defaultOpen","undefined","scope","modalOpen","setOpen","isOpen","t3","open_0","openChangeHandler","t4","t5","displayName"],"sources":["../../../src/primitives/assistantModal/AssistantModalRoot.tsx"],"sourcesContent":["\"use client\";\n\nimport { type FC, useState } from \"react\";\nimport { Popover as PopoverPrimitive } from \"radix-ui\";\nimport { type ScopedProps, usePopoverScope } from \"./scope\";\nimport { useAuiEvent } from \"@assistant-ui/store\";\n\nexport namespace AssistantModalPrimitiveRoot {\n export type Props = PopoverPrimitive.PopoverProps & {\n unstable_openOnRunStart?: boolean | undefined;\n };\n}\n\nexport const AssistantModalPrimitiveRoot: FC<\n AssistantModalPrimitiveRoot.Props\n> = ({\n __scopeAssistantModal,\n defaultOpen = false,\n unstable_openOnRunStart = true,\n open,\n onOpenChange,\n ...rest\n}: ScopedProps<AssistantModalPrimitiveRoot.Props>) => {\n const scope = usePopoverScope(__scopeAssistantModal);\n\n const [modalOpen, setOpen] = useState(defaultOpen);\n const isOpen = open ?? modalOpen;\n\n const openChangeHandler = (open: boolean) => {\n onOpenChange?.(open);\n setOpen(open);\n };\n\n useAuiEvent(\"thread.runStart\", () => {\n if (unstable_openOnRunStart && !isOpen) openChangeHandler(true);\n });\n\n return (\n <PopoverPrimitive.Root\n {...scope}\n open={isOpen}\n onOpenChange={openChangeHandler}\n {...rest}\n />\n );\n};\n\nAssistantModalPrimitiveRoot.displayName = \"AssistantModalPrimitive.Root\";\n"],"mappings":";;;;;;;;AAaA,MAAaS,+BAETI,OAAA;CAAA,MAAAC,IAAAb,EAAA,EAAA;CAAA,IAAAc;CAAA,IAAAC;CAAA,IAAAC;CAAA,IAAAC;CAAA,IAAAC;CAAA,IAAAC;CAAA,IAAAN,EAAA,OAAAD,IAAA;EAAC,CAAA,CAAAE,uBAAAM,aAAAF,IAAAP,yBAAAQ,IAAAH,MAAAD,cAAA,GAAAE,QAAAL;EAO4CC,EAAA,KAAAD;EAAAC,EAAA,KAAAC;EAAAD,EAAA,KAAAE;EAAAF,EAAA,KAAAG;EAAAH,EAAA,KAAAI;EAAAJ,EAAA,KAAAK;EAAAL,EAAA,KAAAM;CAAA,OAAA;EAAAL,wBAAAD,EAAA;EAAAE,eAAAF,EAAA;EAAAG,OAAAH,EAAA;EAAAI,OAAAJ,EAAA;EAAAK,KAAAL,EAAA;EAAAM,KAAAN,EAAA;CAAA;CAL/C,MAAAO,cAAAF,OAAAG,KAAAA,IAAA,QAAAH;CACA,MAAAP,0BAAAQ,OAAAE,KAAAA,IAAA,OAAAF;CAKA,MAAAG,QAAchB,gBAAgBQ,qBAAqB;CAEnD,MAAA,CAAAS,WAAAC,WAA6BtB,SAASkB,WAAW;CACjD,MAAAK,SAAeT,QAAAO;CAAkB,IAAAG;CAAA,IAAAb,EAAA,OAAAE,cAAA;EAEPW,MAAAC,WAAA;GACxBZ,eAAeC,MAAI;GACnBQ,QAAQR,MAAI;EAAC;EACdH,EAAA,KAAAE;EAAAF,EAAA,KAAAa;CAAA,OAAAA,KAAAb,EAAA;CAHD,MAAAe,oBAA0BF;CAGxB,IAAAG;CAAA,IAAAhB,EAAA,OAAAY,UAAAZ,EAAA,QAAAe,qBAAAf,EAAA,QAAAF,yBAAA;EAE6BkB,WAAA;GAC7B,IAAIlB,2BAAA,CAA4Bc,QAAQG,kBAAkB,IAAI;EAAE;EACjEf,EAAA,KAAAY;EAAAZ,EAAA,MAAAe;EAAAf,EAAA,MAAAF;EAAAE,EAAA,MAAAgB;CAAA,OAAAA,KAAAhB,EAAA;CAFDN,YAAY,mBAAmBsB,EAE9B;CAAC,IAAAC;CAAA,IAAAjB,EAAA,QAAAY,UAAAZ,EAAA,QAAAe,qBAAAf,EAAA,QAAAI,QAAAJ,EAAA,QAAAS,OAAA;EAGAQ,KAAA,oBAAA,QAAA,MAAA;GAAA,GACMR;GACEG,MAAAA;GACQG,cAAAA;GAAiB,GAC3BX;EAAI,CAAA;EACRJ,EAAA,MAAAY;EAAAZ,EAAA,MAAAe;EAAAf,EAAA,MAAAI;EAAAJ,EAAA,MAAAS;EAAAT,EAAA,MAAAiB;CAAA,OAAAA,KAAAjB,EAAA;CAAA,OALFiB;AAKE;AAINtB,4BAA4BuB,cAAc"}
@@ -1 +1 @@
1
- {"version":3,"file":"ComposerAttachmentDropzone.d.ts","names":[],"sources":["../../../src/primitives/composer/ComposerAttachmentDropzone.tsx"],"mappings":";;kBAgBiB;OACH,UAAU;OACV,QAAQ,MAAM,eAAe;IACvC;IACA,SAAS;IACT;;;cAIS,qCAAmC,MAAA,0BAAA,MAAA,eAAA;EANlC;EACD,SAAA;EACE;IA8Gb,MAAA,cAAA"}
1
+ {"version":3,"file":"ComposerAttachmentDropzone.d.ts","names":[],"sources":["../../../src/primitives/composer/ComposerAttachmentDropzone.tsx"],"mappings":";;kBAgBiB;OACH,UAAU;OACV,QAAQ,MAAM,eAAe;IACvC;IACA,SAAS;IACT;;;cAIS,qCAAmC,MAAA,0BAAA,MAAA,eAAA;EANlC;EACD,SAAA;EACE;IAsGb,MAAA,cAAA"}