@ai-sdk/react 4.0.0-canary.167 → 4.0.0-canary.169

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.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,36 @@
1
1
  # @ai-sdk/react
2
2
 
3
+ ## 4.0.0-canary.169
4
+
5
+ ### Patch Changes
6
+
7
+ - Updated dependencies [19736ee]
8
+ - Updated dependencies [d66ae02]
9
+ - Updated dependencies [e4182bd]
10
+ - ai@7.0.0-canary.166
11
+
12
+ ## 4.0.0-canary.168
13
+
14
+ ### Patch Changes
15
+
16
+ - ce769dd: feat(provider): add experimental Realtime API support for voice conversations
17
+
18
+ Adds first-class support for realtime (speech-to-speech) APIs:
19
+
20
+ - `Experimental_RealtimeModelV4` spec in `@ai-sdk/provider` with normalized event types and factory
21
+ - OpenAI, Google, and xAI realtime provider implementations
22
+ - `openai.experimental_realtime()` / `google.experimental_realtime()` / `xai.experimental_realtime()` work in both server and browser
23
+ - `.getToken()` static method on each provider for server-side ephemeral token creation
24
+ - `experimental_getRealtimeToolDefinitions` helper for provider session tool definitions
25
+ - `experimental_useRealtime` hook in `@ai-sdk/react` returning `UIMessage[]` (aligned with `useChat`), with `onToolCall` and `addToolOutput` for client-driven tool execution
26
+ - `inputAudioTranscription` session config for showing transcribed user audio messages when supported by the provider
27
+
28
+ - Updated dependencies [ce769dd]
29
+ - @ai-sdk/provider@4.0.0-canary.18
30
+ - ai@7.0.0-canary.165
31
+ - @ai-sdk/mcp@2.0.0-canary.59
32
+ - @ai-sdk/provider-utils@5.0.0-canary.46
33
+
3
34
  ## 4.0.0-canary.167
4
35
 
5
36
  ### Patch Changes
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { UIMessage, AbstractChat, ChatInit, CompletionRequestOptions, UseCompletionOptions, DeepPartial, ToolUIPart, UITools, DynamicToolUIPart } from 'ai';
2
- export { CreateUIMessage, UIMessage, UseCompletionOptions } from 'ai';
1
+ import { UIMessage, AbstractChat, ChatInit, CompletionRequestOptions, UseCompletionOptions, DeepPartial, Experimental_RealtimeSessionOptions, Experimental_RealtimeStatus, Experimental_RealtimeServerEvent, Experimental_AbstractRealtimeSession, Experimental_RealtimeState, ToolUIPart, UITools, DynamicToolUIPart } from 'ai';
2
+ export { CreateUIMessage, Experimental_RealtimeStatus, UIMessage, UseCompletionOptions } from 'ai';
3
3
  import { FlexibleSchema, FetchFunction, Resolvable, InferSchema } from '@ai-sdk/provider-utils';
4
4
  import * as react_jsx_runtime from 'react/jsx-runtime';
5
5
  import * as react from 'react';
@@ -180,6 +180,47 @@ declare function useObject<SCHEMA extends FlexibleSchema, RESULT = InferSchema<S
180
180
  initialValue, fetch, onError, onFinish, headers, credentials, }: Experimental_UseObjectOptions<SCHEMA, RESULT>): Experimental_UseObjectHelpers<RESULT, INPUT>;
181
181
  declare const experimental_useObject: typeof useObject;
182
182
 
183
+ type UseRealtimeOptions = Experimental_RealtimeSessionOptions;
184
+ type RealtimeStateKey = keyof Experimental_RealtimeState;
185
+ declare class RealtimeStore extends Experimental_AbstractRealtimeSession {
186
+ protected state: Experimental_RealtimeState;
187
+ private callbacks;
188
+ get status(): Experimental_RealtimeStatus;
189
+ get messages(): UIMessage[];
190
+ get events(): Experimental_RealtimeServerEvent[];
191
+ get isCapturing(): boolean;
192
+ get isPlaying(): boolean;
193
+ subscribe(key: RealtimeStateKey, onChange: () => void): () => void;
194
+ protected setState<K extends RealtimeStateKey>(key: K, value: Experimental_RealtimeState[K]): void;
195
+ protected pushMessage(message: UIMessage): void;
196
+ protected updateMessages(updater: (messages: UIMessage[]) => UIMessage[]): void;
197
+ protected pushEvent(event: Experimental_RealtimeServerEvent): void;
198
+ }
199
+ type UseRealtimeReturn = {
200
+ status: Experimental_RealtimeStatus;
201
+ messages: UIMessage[];
202
+ events: Experimental_RealtimeServerEvent[];
203
+ isCapturing: boolean;
204
+ isPlaying: boolean;
205
+ connect: () => Promise<void>;
206
+ disconnect: () => void;
207
+ addToolOutput: (callId: string, result: unknown) => void;
208
+ sendEvent: RealtimeStore['sendEvent'];
209
+ sendTextMessage: (text: string) => void;
210
+ sendAudio: (base64Audio: string) => void;
211
+ commitAudio: () => void;
212
+ clearAudioBuffer: () => void;
213
+ requestResponse: (options?: {
214
+ modalities?: string[];
215
+ }) => void;
216
+ cancelResponse: () => void;
217
+ startAudioCapture: (stream: MediaStream) => void;
218
+ stopAudioCapture: () => void;
219
+ stopPlayback: () => void;
220
+ };
221
+ declare function useRealtime(options: UseRealtimeOptions): UseRealtimeReturn;
222
+ declare const experimental_useRealtime: typeof useRealtime;
223
+
183
224
  type MCPAppDisplayMode = 'inline' | 'fullscreen' | 'pip';
184
225
  type MCPAppMetadata = {
185
226
  resourceUri: string;
@@ -249,4 +290,4 @@ type MCPAppRendererProps = {
249
290
 
250
291
  declare function MCPAppRenderer({ part, sandbox, resource: resourceProp, loadResource, handlers, hostInfo, hostContext, fallback, }: MCPAppRendererProps): string | number | boolean | Iterable<react.ReactNode> | react_jsx_runtime.JSX.Element | null;
251
292
 
252
- export { Chat, Experimental_UseObjectHelpers, Experimental_UseObjectOptions, MCPAppBridgeHandlers, MCPAppMetadata, MCPAppRendererProps, MCPAppSandboxConfig, UseChatHelpers, UseChatOptions, UseCompletionHelpers, MCPAppRenderer as experimental_MCPAppRenderer, experimental_useObject, useChat, useCompletion };
293
+ export { Chat, Experimental_UseObjectHelpers, Experimental_UseObjectOptions, UseRealtimeOptions as Experimental_UseRealtimeOptions, UseRealtimeReturn as Experimental_UseRealtimeReturn, MCPAppBridgeHandlers, MCPAppMetadata, MCPAppRendererProps, MCPAppSandboxConfig, UseChatHelpers, UseChatOptions, UseCompletionHelpers, MCPAppRenderer as experimental_MCPAppRenderer, experimental_useObject, experimental_useRealtime, useChat, useCompletion };
package/dist/index.js CHANGED
@@ -504,11 +504,182 @@ function useObject({
504
504
  }
505
505
  var experimental_useObject = useObject;
506
506
 
507
+ // src/use-realtime.ts
508
+ import {
509
+ Experimental_AbstractRealtimeSession as AbstractRealtimeSession
510
+ } from "ai";
511
+ import { useCallback as useCallback4, useEffect as useEffect3, useRef as useRef4, useSyncExternalStore as useSyncExternalStore2 } from "react";
512
+ function getRealtimeStoreKey(options) {
513
+ return {
514
+ model: options.model,
515
+ token: options.api.token,
516
+ sessionConfig: options.sessionConfig,
517
+ sampleRate: options.sampleRate,
518
+ maxEvents: options.maxEvents
519
+ };
520
+ }
521
+ function shouldCreateRealtimeStore(currentKey, nextOptions) {
522
+ return currentKey.model !== nextOptions.model || currentKey.token !== nextOptions.api.token || currentKey.sessionConfig !== nextOptions.sessionConfig || currentKey.sampleRate !== nextOptions.sampleRate || currentKey.maxEvents !== nextOptions.maxEvents;
523
+ }
524
+ var RealtimeStore = class extends AbstractRealtimeSession {
525
+ constructor() {
526
+ super(...arguments);
527
+ this.state = {
528
+ status: "disconnected",
529
+ messages: [],
530
+ events: [],
531
+ isCapturing: false,
532
+ isPlaying: false
533
+ };
534
+ this.callbacks = {
535
+ status: /* @__PURE__ */ new Set(),
536
+ messages: /* @__PURE__ */ new Set(),
537
+ events: /* @__PURE__ */ new Set(),
538
+ isCapturing: /* @__PURE__ */ new Set(),
539
+ isPlaying: /* @__PURE__ */ new Set()
540
+ };
541
+ }
542
+ get status() {
543
+ return this.state.status;
544
+ }
545
+ get messages() {
546
+ return this.state.messages;
547
+ }
548
+ get events() {
549
+ return this.state.events;
550
+ }
551
+ get isCapturing() {
552
+ return this.state.isCapturing;
553
+ }
554
+ get isPlaying() {
555
+ return this.state.isPlaying;
556
+ }
557
+ subscribe(key, onChange) {
558
+ this.callbacks[key].add(onChange);
559
+ return () => {
560
+ this.callbacks[key].delete(onChange);
561
+ };
562
+ }
563
+ setState(key, value) {
564
+ this.state = { ...this.state, [key]: value };
565
+ this.callbacks[key].forEach((callback) => callback());
566
+ }
567
+ pushMessage(message) {
568
+ this.state = {
569
+ ...this.state,
570
+ messages: [...this.state.messages, message]
571
+ };
572
+ this.callbacks.messages.forEach((callback) => callback());
573
+ }
574
+ updateMessages(updater) {
575
+ this.state = {
576
+ ...this.state,
577
+ messages: updater(this.state.messages)
578
+ };
579
+ this.callbacks.messages.forEach((callback) => callback());
580
+ }
581
+ pushEvent(event) {
582
+ const nextEvents = [...this.state.events, event];
583
+ this.state = {
584
+ ...this.state,
585
+ events: nextEvents.length > this.maxEvents ? nextEvents.slice(-this.maxEvents) : nextEvents
586
+ };
587
+ this.callbacks.events.forEach((callback) => callback());
588
+ }
589
+ };
590
+ function useRealtime(options) {
591
+ const callbacksRef = useRef4({
592
+ onToolCall: options.onToolCall,
593
+ onEvent: options.onEvent,
594
+ onError: options.onError
595
+ });
596
+ callbacksRef.current = {
597
+ onToolCall: options.onToolCall,
598
+ onEvent: options.onEvent,
599
+ onError: options.onError
600
+ };
601
+ const realtimeRef = useRef4(null);
602
+ let realtimeEntry = realtimeRef.current;
603
+ if (realtimeEntry == null || shouldCreateRealtimeStore(realtimeEntry.key, options)) {
604
+ realtimeEntry = {
605
+ store: new RealtimeStore({
606
+ ...options,
607
+ onToolCall: (...args) => {
608
+ var _a, _b;
609
+ return (_b = (_a = callbacksRef.current).onToolCall) == null ? void 0 : _b.call(_a, ...args);
610
+ },
611
+ onEvent: (...args) => {
612
+ var _a, _b;
613
+ return (_b = (_a = callbacksRef.current).onEvent) == null ? void 0 : _b.call(_a, ...args);
614
+ },
615
+ onError: (...args) => {
616
+ var _a, _b;
617
+ return (_b = (_a = callbacksRef.current).onError) == null ? void 0 : _b.call(_a, ...args);
618
+ }
619
+ }),
620
+ key: getRealtimeStoreKey(options)
621
+ };
622
+ realtimeRef.current = realtimeEntry;
623
+ } else {
624
+ realtimeEntry.key = getRealtimeStoreKey(options);
625
+ }
626
+ const rt = realtimeEntry.store;
627
+ const status = useSyncExternalStore2(
628
+ useCallback4((cb) => rt.subscribe("status", cb), [rt]),
629
+ () => rt.status,
630
+ () => rt.status
631
+ );
632
+ const messages = useSyncExternalStore2(
633
+ useCallback4((cb) => rt.subscribe("messages", cb), [rt]),
634
+ () => rt.messages,
635
+ () => rt.messages
636
+ );
637
+ const events = useSyncExternalStore2(
638
+ useCallback4((cb) => rt.subscribe("events", cb), [rt]),
639
+ () => rt.events,
640
+ () => rt.events
641
+ );
642
+ const isCapturing = useSyncExternalStore2(
643
+ useCallback4((cb) => rt.subscribe("isCapturing", cb), [rt]),
644
+ () => rt.isCapturing,
645
+ () => rt.isCapturing
646
+ );
647
+ const isPlaying = useSyncExternalStore2(
648
+ useCallback4((cb) => rt.subscribe("isPlaying", cb), [rt]),
649
+ () => rt.isPlaying,
650
+ () => rt.isPlaying
651
+ );
652
+ useEffect3(() => {
653
+ return () => rt.dispose();
654
+ }, [rt]);
655
+ return {
656
+ status,
657
+ messages,
658
+ events,
659
+ isCapturing,
660
+ isPlaying,
661
+ connect: rt.connect.bind(rt),
662
+ disconnect: rt.disconnect.bind(rt),
663
+ addToolOutput: rt.addToolOutput.bind(rt),
664
+ sendEvent: rt.sendEvent.bind(rt),
665
+ sendTextMessage: rt.sendTextMessage.bind(rt),
666
+ sendAudio: rt.sendAudio.bind(rt),
667
+ commitAudio: rt.commitAudio.bind(rt),
668
+ clearAudioBuffer: rt.clearAudioBuffer.bind(rt),
669
+ requestResponse: rt.requestResponse.bind(rt),
670
+ cancelResponse: rt.cancelResponse.bind(rt),
671
+ startAudioCapture: rt.startAudioCapture.bind(rt),
672
+ stopAudioCapture: rt.stopAudioCapture.bind(rt),
673
+ stopPlayback: rt.stopPlayback.bind(rt)
674
+ };
675
+ }
676
+ var experimental_useRealtime = useRealtime;
677
+
507
678
  // src/mcp-apps/app-renderer.tsx
508
- import { useEffect as useEffect4, useState as useState3 } from "react";
679
+ import { useEffect as useEffect5, useState as useState3 } from "react";
509
680
 
510
681
  // src/mcp-apps/app-frame.tsx
511
- import { useEffect as useEffect3, useMemo, useRef as useRef4 } from "react";
682
+ import { useEffect as useEffect4, useMemo, useRef as useRef5 } from "react";
512
683
 
513
684
  // src/mcp-apps/bridge.ts
514
685
  import { isJSONObject } from "@ai-sdk/provider";
@@ -887,12 +1058,12 @@ function MCPAppFrame({
887
1058
  hostContext
888
1059
  }) {
889
1060
  var _a, _b, _c, _d, _e, _f;
890
- const iframeRef = useRef4(null);
891
- const bridgeRef = useRef4(void 0);
892
- const inputRef = useRef4(input);
893
- const outputRef = useRef4(output);
894
- const hostContextRef = useRef4(hostContext);
895
- const initializedRef = useRef4(false);
1061
+ const iframeRef = useRef5(null);
1062
+ const bridgeRef = useRef5(void 0);
1063
+ const inputRef = useRef5(input);
1064
+ const outputRef = useRef5(output);
1065
+ const hostContextRef = useRef5(hostContext);
1066
+ const initializedRef = useRef5(false);
896
1067
  inputRef.current = input;
897
1068
  outputRef.current = output;
898
1069
  hostContextRef.current = hostContext;
@@ -917,9 +1088,9 @@ function MCPAppFrame({
917
1088
  }),
918
1089
  [handlers]
919
1090
  );
920
- const bridgeHandlersRef = useRef4(bridgeHandlers);
1091
+ const bridgeHandlersRef = useRef5(bridgeHandlers);
921
1092
  bridgeHandlersRef.current = bridgeHandlers;
922
- useEffect3(() => {
1093
+ useEffect4(() => {
923
1094
  const iframe = iframeRef.current;
924
1095
  const targetWindow = iframe == null ? void 0 : iframe.contentWindow;
925
1096
  if (targetWindow == null) {
@@ -965,23 +1136,23 @@ function MCPAppFrame({
965
1136
  sandboxUrl,
966
1137
  targetOrigin
967
1138
  ]);
968
- useEffect3(() => {
1139
+ useEffect4(() => {
969
1140
  var _a2;
970
1141
  (_a2 = bridgeRef.current) == null ? void 0 : _a2.setHandlers(bridgeHandlers);
971
1142
  }, [bridgeHandlers]);
972
- useEffect3(() => {
1143
+ useEffect4(() => {
973
1144
  var _a2;
974
1145
  if (hostContext != null) {
975
1146
  (_a2 = bridgeRef.current) == null ? void 0 : _a2.setHostContext(hostContext);
976
1147
  }
977
1148
  }, [hostContext]);
978
- useEffect3(() => {
1149
+ useEffect4(() => {
979
1150
  var _a2;
980
1151
  if (initializedRef.current && input !== void 0) {
981
1152
  (_a2 = bridgeRef.current) == null ? void 0 : _a2.sendToolInput(input);
982
1153
  }
983
1154
  }, [input]);
984
- useEffect3(() => {
1155
+ useEffect4(() => {
985
1156
  var _a2;
986
1157
  if (initializedRef.current && output !== void 0) {
987
1158
  (_a2 = bridgeRef.current) == null ? void 0 : _a2.sendToolResult(normalizeMCPAppToolResult(output));
@@ -1022,7 +1193,7 @@ function MCPAppRenderer({
1022
1193
  const app = getMCPAppFromToolPart(part);
1023
1194
  const [cachedApp, setCachedApp] = useState3();
1024
1195
  const [loadedResource, setLoadedResource] = useState3();
1025
- useEffect4(() => {
1196
+ useEffect5(() => {
1026
1197
  if (app != null) {
1027
1198
  setCachedApp(
1028
1199
  (previous) => (previous == null ? void 0 : previous.resourceUri) === app.resourceUri ? previous : app
@@ -1030,7 +1201,7 @@ function MCPAppRenderer({
1030
1201
  }
1031
1202
  }, [app == null ? void 0 : app.resourceUri]);
1032
1203
  const appForRender = app != null ? app : cachedApp;
1033
- useEffect4(() => {
1204
+ useEffect5(() => {
1034
1205
  if (appForRender == null || resourceProp != null || loadResource == null) {
1035
1206
  return;
1036
1207
  }
@@ -1076,6 +1247,7 @@ export {
1076
1247
  Chat,
1077
1248
  MCPAppRenderer as experimental_MCPAppRenderer,
1078
1249
  experimental_useObject,
1250
+ experimental_useRealtime,
1079
1251
  useChat,
1080
1252
  useCompletion
1081
1253
  };
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/use-chat.ts","../src/chat.react.ts","../src/throttle.ts","../src/use-completion.ts","../src/use-object.ts","../src/mcp-apps/app-renderer.tsx","../src/mcp-apps/app-frame.tsx","../src/mcp-apps/bridge.ts","../src/mcp-apps/sandbox.ts","../src/mcp-apps/utils.ts"],"sourcesContent":["import type { AbstractChat, ChatInit, CreateUIMessage, UIMessage } from 'ai';\nimport { useCallback, useEffect, useRef, useSyncExternalStore } from 'react';\nimport { Chat } from './chat.react';\n\nexport type { CreateUIMessage, UIMessage };\n\nexport type UseChatHelpers<UI_MESSAGE extends UIMessage> = {\n /**\n * The id of the chat.\n */\n readonly id: string;\n\n /**\n * Update the `messages` state locally. This is useful when you want to\n * edit the messages on the client, and then trigger the `reload` method\n * manually to regenerate the AI response.\n */\n setMessages: (\n messages: UI_MESSAGE[] | ((messages: UI_MESSAGE[]) => UI_MESSAGE[]),\n ) => void;\n\n error: Error | undefined;\n} & Pick<\n AbstractChat<UI_MESSAGE>,\n | 'sendMessage'\n | 'regenerate'\n | 'stop'\n | 'resumeStream'\n | 'addToolResult'\n | 'addToolOutput'\n | 'addToolApprovalResponse'\n | 'status'\n | 'messages'\n | 'clearError'\n>;\n\nexport type UseChatOptions<UI_MESSAGE extends UIMessage> = (\n | { chat: Chat<UI_MESSAGE> }\n | ChatInit<UI_MESSAGE>\n) & {\n /**\n * Custom throttle wait in ms for the chat messages and data updates.\n * Default is undefined, which disables throttling.\n */\n experimental_throttle?: number;\n\n /**\n * Whether to resume an ongoing chat generation stream.\n */\n resume?: boolean;\n};\n\nexport function useChat<UI_MESSAGE extends UIMessage = UIMessage>({\n experimental_throttle: throttleWaitMs,\n resume = false,\n ...options\n}: UseChatOptions<UI_MESSAGE> = {}): UseChatHelpers<UI_MESSAGE> {\n // Create a single ref for all callbacks to avoid stale closures\n const callbacksRef = useRef(\n !('chat' in options)\n ? {\n onToolCall: options.onToolCall,\n onData: options.onData,\n onFinish: options.onFinish,\n onError: options.onError,\n sendAutomaticallyWhen: options.sendAutomaticallyWhen,\n }\n : {},\n );\n\n // Update callbacks ref on each render to keep them current\n if (!('chat' in options)) {\n callbacksRef.current = {\n onToolCall: options.onToolCall,\n onData: options.onData,\n onFinish: options.onFinish,\n onError: options.onError,\n sendAutomaticallyWhen: options.sendAutomaticallyWhen,\n };\n }\n\n // Ensure the Chat instance has the latest callbacks\n const optionsWithCallbacks: typeof options = {\n ...options,\n onToolCall: arg => callbacksRef.current.onToolCall?.(arg),\n onData: arg => callbacksRef.current.onData?.(arg),\n onFinish: arg => callbacksRef.current.onFinish?.(arg),\n onError: arg => callbacksRef.current.onError?.(arg),\n sendAutomaticallyWhen: arg =>\n callbacksRef.current.sendAutomaticallyWhen?.(arg) ?? false,\n };\n\n const chatRef = useRef<Chat<UI_MESSAGE>>(\n 'chat' in options ? options.chat : new Chat(optionsWithCallbacks),\n );\n\n const shouldRecreateChat =\n ('chat' in options && options.chat !== chatRef.current) ||\n ('id' in options && chatRef.current.id !== options.id);\n\n if (shouldRecreateChat) {\n chatRef.current =\n 'chat' in options ? options.chat : new Chat(optionsWithCallbacks);\n }\n\n const subscribeToMessages = useCallback(\n (update: () => void) =>\n chatRef.current['~registerMessagesCallback'](update, throttleWaitMs),\n // `chatRef.current.id` is required to trigger re-subscription when the chat ID changes\n // eslint-disable-next-line react-hooks/exhaustive-deps\n [throttleWaitMs, chatRef.current.id],\n );\n\n const messages = useSyncExternalStore(\n subscribeToMessages,\n () => chatRef.current.messages,\n () => chatRef.current.messages,\n );\n\n const status = useSyncExternalStore(\n chatRef.current['~registerStatusCallback'],\n () => chatRef.current.status,\n () => chatRef.current.status,\n );\n\n const error = useSyncExternalStore(\n chatRef.current['~registerErrorCallback'],\n () => chatRef.current.error,\n () => chatRef.current.error,\n );\n\n const setMessages = useCallback(\n (\n messagesParam: UI_MESSAGE[] | ((messages: UI_MESSAGE[]) => UI_MESSAGE[]),\n ) => {\n if (typeof messagesParam === 'function') {\n messagesParam = messagesParam(chatRef.current.messages);\n }\n chatRef.current.messages = messagesParam;\n },\n [chatRef],\n );\n\n useEffect(() => {\n if (resume) {\n chatRef.current.resumeStream();\n }\n }, [resume, chatRef]);\n\n return {\n id: chatRef.current.id,\n messages,\n setMessages,\n sendMessage: chatRef.current.sendMessage,\n regenerate: chatRef.current.regenerate,\n clearError: chatRef.current.clearError,\n stop: chatRef.current.stop,\n error,\n resumeStream: chatRef.current.resumeStream,\n status,\n /**\n * @deprecated Use `addToolOutput` instead.\n */\n addToolResult: chatRef.current.addToolOutput,\n addToolOutput: chatRef.current.addToolOutput,\n addToolApprovalResponse: chatRef.current.addToolApprovalResponse,\n };\n}\n","import {\n AbstractChat,\n type ChatInit,\n type ChatState,\n type ChatStatus,\n type UIMessage,\n} from 'ai';\nimport { throttle } from './throttle';\n\nclass ReactChatState<\n UI_MESSAGE extends UIMessage,\n> implements ChatState<UI_MESSAGE> {\n #messages: UI_MESSAGE[];\n #status: ChatStatus = 'ready';\n #error: Error | undefined = undefined;\n\n #messagesCallbacks = new Set<() => void>();\n #statusCallbacks = new Set<() => void>();\n #errorCallbacks = new Set<() => void>();\n\n constructor(initialMessages: UI_MESSAGE[] = []) {\n this.#messages = initialMessages;\n }\n\n get status(): ChatStatus {\n return this.#status;\n }\n\n set status(newStatus: ChatStatus) {\n this.#status = newStatus;\n this.#callStatusCallbacks();\n }\n\n get error(): Error | undefined {\n return this.#error;\n }\n\n set error(newError: Error | undefined) {\n this.#error = newError;\n this.#callErrorCallbacks();\n }\n\n get messages(): UI_MESSAGE[] {\n return this.#messages;\n }\n\n set messages(newMessages: UI_MESSAGE[]) {\n this.#messages = [...newMessages];\n this.#callMessagesCallbacks();\n }\n\n pushMessage = (message: UI_MESSAGE) => {\n this.#messages = this.#messages.concat(message);\n this.#callMessagesCallbacks();\n };\n\n popMessage = () => {\n this.#messages = this.#messages.slice(0, -1);\n this.#callMessagesCallbacks();\n };\n\n replaceMessage = (index: number, message: UI_MESSAGE) => {\n this.#messages = [\n ...this.#messages.slice(0, index),\n // We deep clone the message here to ensure the new React Compiler (currently in RC) detects deeply nested parts/metadata changes:\n this.snapshot(message),\n ...this.#messages.slice(index + 1),\n ];\n this.#callMessagesCallbacks();\n };\n\n snapshot = <T>(value: T): T => structuredClone(value);\n\n '~registerMessagesCallback' = (\n onChange: () => void,\n throttleWaitMs?: number,\n ): (() => void) => {\n const callback = throttleWaitMs\n ? throttle(onChange, throttleWaitMs)\n : onChange;\n this.#messagesCallbacks.add(callback);\n return () => {\n this.#messagesCallbacks.delete(callback);\n };\n };\n\n '~registerStatusCallback' = (onChange: () => void): (() => void) => {\n this.#statusCallbacks.add(onChange);\n return () => {\n this.#statusCallbacks.delete(onChange);\n };\n };\n\n '~registerErrorCallback' = (onChange: () => void): (() => void) => {\n this.#errorCallbacks.add(onChange);\n return () => {\n this.#errorCallbacks.delete(onChange);\n };\n };\n\n #callMessagesCallbacks = () => {\n this.#messagesCallbacks.forEach(callback => callback());\n };\n\n #callStatusCallbacks = () => {\n this.#statusCallbacks.forEach(callback => callback());\n };\n\n #callErrorCallbacks = () => {\n this.#errorCallbacks.forEach(callback => callback());\n };\n}\n\nexport class Chat<\n UI_MESSAGE extends UIMessage,\n> extends AbstractChat<UI_MESSAGE> {\n #state: ReactChatState<UI_MESSAGE>;\n\n constructor({ messages, ...init }: ChatInit<UI_MESSAGE>) {\n const state = new ReactChatState(messages);\n super({ ...init, state });\n this.#state = state;\n }\n\n '~registerMessagesCallback' = (\n onChange: () => void,\n throttleWaitMs?: number,\n ): (() => void) =>\n this.#state['~registerMessagesCallback'](onChange, throttleWaitMs);\n\n '~registerStatusCallback' = (onChange: () => void): (() => void) =>\n this.#state['~registerStatusCallback'](onChange);\n\n '~registerErrorCallback' = (onChange: () => void): (() => void) =>\n this.#state['~registerErrorCallback'](onChange);\n}\n","import throttleFunction from 'throttleit';\n\nexport function throttle<T extends (...args: any[]) => any>(\n fn: T,\n waitMs: number | undefined,\n): T {\n return waitMs != null ? throttleFunction(fn, waitMs) : fn;\n}\n","import {\n callCompletionApi,\n type CompletionRequestOptions,\n type UseCompletionOptions,\n} from 'ai';\nimport { useCallback, useEffect, useId, useRef, useState } from 'react';\nimport useSWR from 'swr';\nimport { throttle } from './throttle';\n\nexport type { UseCompletionOptions };\n\nexport type UseCompletionHelpers = {\n /** The current completion result */\n completion: string;\n /**\n * Send a new prompt to the API endpoint and update the completion state.\n */\n complete: (\n prompt: string,\n options?: CompletionRequestOptions,\n ) => Promise<string | null | undefined>;\n /** The error object of the API request */\n error: undefined | Error;\n /**\n * Abort the current API request but keep the generated tokens.\n */\n stop: () => void;\n /**\n * Update the `completion` state locally.\n */\n setCompletion: (completion: string) => void;\n /** The current value of the input */\n input: string;\n /** setState-powered method to update the input value */\n setInput: React.Dispatch<React.SetStateAction<string>>;\n /**\n * An input/textarea-ready onChange handler to control the value of the input\n * @example\n * ```jsx\n * <input onChange={handleInputChange} value={input} />\n * ```\n */\n handleInputChange: (\n event:\n | React.ChangeEvent<HTMLInputElement>\n | React.ChangeEvent<HTMLTextAreaElement>,\n ) => void;\n\n /**\n * Form submission handler to automatically reset input and append a user message\n * @example\n * ```jsx\n * <form onSubmit={handleSubmit}>\n * <input onChange={handleInputChange} value={input} />\n * </form>\n * ```\n */\n handleSubmit: (event?: { preventDefault?: () => void }) => void;\n\n /** Whether the API request is in progress */\n isLoading: boolean;\n};\n\nexport function useCompletion({\n api = '/api/completion',\n id,\n initialCompletion = '',\n initialInput = '',\n credentials,\n headers,\n body,\n streamProtocol = 'data',\n fetch,\n onFinish,\n onError,\n experimental_throttle: throttleWaitMs,\n}: UseCompletionOptions & {\n /**\n * Custom throttle wait in ms for the completion and data updates.\n * Default is undefined, which disables throttling.\n */\n experimental_throttle?: number;\n} = {}): UseCompletionHelpers {\n // Generate an unique id for the completion if not provided.\n const hookId = useId();\n const completionId = id || hookId;\n\n // Store the completion state in SWR, using the completionId as the key to share states.\n const { data, mutate } = useSWR<string>([api, completionId], null, {\n fallbackData: initialCompletion,\n });\n\n const { data: isLoading = false, mutate: mutateLoading } = useSWR<boolean>(\n [completionId, 'loading'],\n null,\n );\n\n const [error, setError] = useState<undefined | Error>(undefined);\n const completion = data!;\n\n // Abort controller to cancel the current API call.\n const [abortController, setAbortController] =\n useState<AbortController | null>(null);\n\n const extraMetadataRef = useRef({\n credentials,\n headers,\n body,\n });\n\n useEffect(() => {\n extraMetadataRef.current = {\n credentials,\n headers,\n body,\n };\n }, [credentials, headers, body]);\n\n const triggerRequest = useCallback(\n async (prompt: string, options?: CompletionRequestOptions) =>\n callCompletionApi({\n api,\n prompt,\n credentials: extraMetadataRef.current.credentials,\n headers: { ...extraMetadataRef.current.headers, ...options?.headers },\n body: {\n ...extraMetadataRef.current.body,\n ...options?.body,\n },\n streamProtocol,\n fetch,\n // throttle streamed ui updates:\n setCompletion: throttle(\n (completion: string) => mutate(completion, false),\n throttleWaitMs,\n ),\n setLoading: mutateLoading,\n setError,\n setAbortController,\n onFinish,\n onError,\n }),\n [\n mutate,\n mutateLoading,\n api,\n extraMetadataRef,\n setAbortController,\n onFinish,\n onError,\n setError,\n streamProtocol,\n fetch,\n throttleWaitMs,\n ],\n );\n\n const stop = useCallback(() => {\n if (abortController) {\n abortController.abort();\n setAbortController(null);\n }\n }, [abortController]);\n\n const setCompletion = useCallback(\n (completion: string) => {\n mutate(completion, false);\n },\n [mutate],\n );\n\n const complete = useCallback<UseCompletionHelpers['complete']>(\n async (prompt, options) => {\n return triggerRequest(prompt, options);\n },\n [triggerRequest],\n );\n\n const [input, setInput] = useState(initialInput);\n\n const handleSubmit = useCallback(\n (event?: { preventDefault?: () => void }) => {\n event?.preventDefault?.();\n return input ? complete(input) : undefined;\n },\n [input, complete],\n );\n\n const handleInputChange = useCallback(\n (e: any) => {\n setInput(e.target.value);\n },\n [setInput],\n );\n\n return {\n completion,\n complete,\n error,\n setCompletion,\n stop,\n input,\n setInput,\n handleInputChange,\n handleSubmit,\n isLoading,\n };\n}\n","import {\n isAbortError,\n resolve,\n normalizeHeaders,\n safeValidateTypes,\n type FetchFunction,\n type FlexibleSchema,\n type InferSchema,\n type Resolvable,\n} from '@ai-sdk/provider-utils';\nimport {\n asSchema,\n isDeepEqualData,\n parsePartialJson,\n type DeepPartial,\n} from 'ai';\nimport { useCallback, useId, useRef, useState } from 'react';\nimport useSWR from 'swr';\n\n// use function to allow for mocking in tests:\nconst getOriginalFetch = () => fetch;\n\nexport type Experimental_UseObjectOptions<\n SCHEMA extends FlexibleSchema,\n RESULT,\n> = {\n /**\n * The API endpoint. It should stream JSON that matches the schema as chunked text.\n */\n api: string;\n\n /**\n * A schema that defines the shape of the complete object.\n */\n schema: SCHEMA;\n\n /**\n * An unique identifier. If not provided, a random one will be\n * generated. When provided, the `useObject` hook with the same `id` will\n * have shared states across components.\n */\n id?: string;\n\n /**\n * An optional value for the initial object.\n */\n initialValue?: DeepPartial<RESULT>;\n\n /**\n * Custom fetch implementation. You can use it as a middleware to intercept requests,\n * or to provide a custom fetch implementation for e.g. testing.\n */\n fetch?: FetchFunction;\n\n /**\n * Callback that is called when the stream has finished.\n */\n onFinish?: (event: {\n /**\n * The generated object (typed according to the schema).\n * Can be undefined if the final object does not match the schema.\n */\n object: RESULT | undefined;\n\n /**\n * Optional error object. This is e.g. a TypeValidationError when the final object does not match the schema.\n */\n error: Error | undefined;\n }) => Promise<void> | void;\n\n /**\n * Callback function to be called when an error is encountered.\n */\n onError?: (error: Error) => void;\n\n /**\n * Additional HTTP headers to be included in the request.\n * Can be a static object, a function that returns headers, or an async function\n * for dynamic auth tokens.\n */\n headers?: Resolvable<Record<string, string> | Headers>;\n\n /**\n * The credentials mode to be used for the fetch request.\n * Possible values are: 'omit', 'same-origin', 'include'.\n * Defaults to 'same-origin'.\n */\n credentials?: RequestCredentials;\n};\n\nexport type Experimental_UseObjectHelpers<RESULT, INPUT> = {\n /**\n * Calls the API with the provided input as JSON body.\n */\n submit: (input: INPUT) => void;\n\n /**\n * The current value for the generated object. Updated as the API streams JSON chunks.\n */\n object: DeepPartial<RESULT> | undefined;\n\n /**\n * The error object of the API request if any.\n */\n error: Error | undefined;\n\n /**\n * Flag that indicates whether an API request is in progress.\n */\n isLoading: boolean;\n\n /**\n * Abort the current request immediately, keep the current partial object if any.\n */\n stop: () => void;\n\n /**\n * Clear the object state.\n */\n clear: () => void;\n};\n\nfunction useObject<\n SCHEMA extends FlexibleSchema,\n RESULT = InferSchema<SCHEMA>,\n INPUT = any,\n>({\n api,\n id,\n schema, // required, in the future we will use it for validation\n initialValue,\n fetch,\n onError,\n onFinish,\n headers,\n credentials,\n}: Experimental_UseObjectOptions<\n SCHEMA,\n RESULT\n>): Experimental_UseObjectHelpers<RESULT, INPUT> {\n // Generate an unique id if not provided.\n const hookId = useId();\n const completionId = id ?? hookId;\n\n // Store the completion state in SWR, using the completionId as the key to share states.\n const { data, mutate } = useSWR<DeepPartial<RESULT>>(\n [api, completionId],\n null,\n { fallbackData: initialValue },\n );\n\n const [error, setError] = useState<undefined | Error>(undefined);\n const [isLoading, setIsLoading] = useState(false);\n\n // Abort controller to cancel the current API call.\n const abortControllerRef = useRef<AbortController | null>(null);\n\n const stop = useCallback(() => {\n try {\n abortControllerRef.current?.abort();\n } catch {\n } finally {\n setIsLoading(false);\n abortControllerRef.current = null;\n }\n }, []);\n\n const submit = async (input: INPUT) => {\n try {\n clearObject();\n\n setIsLoading(true);\n\n const abortController = new AbortController();\n abortControllerRef.current = abortController;\n\n // Resolve headers at request time (supports async functions for dynamic auth tokens)\n const resolvedHeaders = await resolve(headers);\n\n const actualFetch = fetch ?? getOriginalFetch();\n const response = await actualFetch(api, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n ...normalizeHeaders(resolvedHeaders),\n },\n credentials,\n signal: abortController.signal,\n body: JSON.stringify(input),\n });\n\n if (!response.ok) {\n throw new Error(\n (await response.text()) ?? 'Failed to fetch the response.',\n );\n }\n\n if (response.body == null) {\n throw new Error('The response body is empty.');\n }\n\n let accumulatedText = '';\n let latestObject: DeepPartial<RESULT> | undefined = undefined;\n\n await response.body.pipeThrough(new TextDecoderStream()).pipeTo(\n new WritableStream<string>({\n async write(chunk) {\n accumulatedText += chunk;\n\n const { value } = await parsePartialJson(accumulatedText);\n const currentObject = value as DeepPartial<RESULT>;\n\n if (!isDeepEqualData(latestObject, currentObject)) {\n latestObject = currentObject;\n\n mutate(currentObject);\n }\n },\n\n async close() {\n setIsLoading(false);\n abortControllerRef.current = null;\n\n if (onFinish != null) {\n const validationResult = await safeValidateTypes({\n value: latestObject,\n schema: asSchema(schema),\n });\n\n onFinish(\n validationResult.success\n ? { object: validationResult.value, error: undefined }\n : { object: undefined, error: validationResult.error },\n );\n }\n },\n }),\n );\n } catch (error) {\n if (isAbortError(error)) {\n return;\n }\n\n if (onError && error instanceof Error) {\n onError(error);\n }\n\n setIsLoading(false);\n setError(error instanceof Error ? error : new Error(String(error)));\n }\n };\n\n const clear = () => {\n stop();\n clearObject();\n };\n\n const clearObject = () => {\n setError(undefined);\n setIsLoading(false);\n mutate(undefined);\n };\n\n return {\n submit,\n object: data,\n error,\n isLoading,\n stop,\n clear,\n };\n}\n\nexport const experimental_useObject = useObject;\n","import type { MCPAppResource } from '@ai-sdk/mcp';\nimport { useEffect, useState } from 'react';\nimport { MCPAppFrame } from './app-frame';\nimport type { MCPAppMetadata, MCPAppRendererProps } from './types';\nimport { getMCPAppFromToolPart } from './utils';\n\ntype LoadedResourceState = {\n resourceUri: string;\n resource?: MCPAppResource;\n error?: Error;\n};\n\nfunction getToolPartOutput(part: MCPAppRendererProps['part']): unknown {\n return part.state === 'output-available' ? part.output : undefined;\n}\n\nfunction getToolPartInput(part: MCPAppRendererProps['part']): unknown {\n return part.state === 'input-available' || part.state === 'output-available'\n ? part.input\n : undefined;\n}\n\nexport function MCPAppRenderer({\n part,\n sandbox,\n resource: resourceProp,\n loadResource,\n handlers,\n hostInfo,\n hostContext,\n fallback = null,\n}: MCPAppRendererProps) {\n const app = getMCPAppFromToolPart(part);\n const [cachedApp, setCachedApp] = useState<MCPAppMetadata>();\n const [loadedResource, setLoadedResource] = useState<LoadedResourceState>();\n\n useEffect(() => {\n if (app != null) {\n setCachedApp(previous =>\n previous?.resourceUri === app.resourceUri ? previous : app,\n );\n }\n }, [app?.resourceUri]);\n\n const appForRender = app ?? cachedApp;\n\n useEffect(() => {\n if (appForRender == null || resourceProp != null || loadResource == null) {\n return;\n }\n\n let cancelled = false;\n const resourceUri = appForRender.resourceUri;\n\n loadResource(appForRender)\n .then(resource => {\n if (!cancelled) {\n setLoadedResource({ resourceUri, resource });\n }\n })\n .catch(error => {\n if (!cancelled) {\n setLoadedResource({\n resourceUri,\n error: error instanceof Error ? error : new Error(String(error)),\n });\n }\n });\n\n return () => {\n cancelled = true;\n };\n }, [appForRender?.resourceUri, loadResource, resourceProp]);\n\n const loadedResourceForApp =\n loadedResource?.resourceUri === appForRender?.resourceUri\n ? loadedResource\n : undefined;\n const resource = resourceProp ?? loadedResourceForApp?.resource;\n const error = resourceProp == null ? loadedResourceForApp?.error : undefined;\n\n if (appForRender == null || error != null || resource == null) {\n return fallback;\n }\n\n return (\n <MCPAppFrame\n app={appForRender}\n resource={resource}\n input={getToolPartInput(part)}\n output={getToolPartOutput(part)}\n sandbox={sandbox}\n handlers={handlers}\n hostInfo={hostInfo}\n hostContext={hostContext}\n />\n );\n}\n","import { useEffect, useMemo, useRef } from 'react';\nimport { MCPAppBridge } from './bridge';\nimport {\n MCP_APP_DEFAULT_INNER_SANDBOX,\n MCP_APP_DEFAULT_OUTER_SANDBOX,\n getMCPAppAllowAttribute,\n getMCPAppCSP,\n} from './sandbox';\nimport type { MCPAppFrameProps } from './types';\nimport { normalizeMCPAppToolResult } from './utils';\n\nfunction sendToolState({\n bridge,\n input,\n output,\n}: {\n bridge?: MCPAppBridge;\n input: unknown;\n output: unknown;\n}) {\n if (bridge == null) {\n return;\n }\n\n if (input !== undefined) {\n bridge.sendToolInput(input);\n }\n\n if (output !== undefined) {\n bridge.sendToolResult(normalizeMCPAppToolResult(output));\n }\n}\n\nexport function MCPAppFrame({\n app,\n resource,\n input,\n output,\n sandbox,\n handlers,\n hostInfo,\n hostContext,\n}: MCPAppFrameProps) {\n const iframeRef = useRef<HTMLIFrameElement>(null);\n const bridgeRef = useRef<MCPAppBridge | undefined>(undefined);\n const inputRef = useRef(input);\n const outputRef = useRef(output);\n const hostContextRef = useRef(hostContext);\n const initializedRef = useRef(false);\n inputRef.current = input;\n outputRef.current = output;\n hostContextRef.current = hostContext;\n const targetOrigin = sandbox.targetOrigin ?? '*';\n const sandboxUrl = String(sandbox.url);\n const resourceCSP = getMCPAppCSP(resource.meta?.csp);\n const resourceAllow = getMCPAppAllowAttribute(resource.meta?.permissions);\n const innerSandbox = sandbox.innerSandbox ?? MCP_APP_DEFAULT_INNER_SANDBOX;\n const bridgeHandlers = useMemo(\n () => ({\n ...handlers,\n onInitialized: () => {\n initializedRef.current = true;\n handlers?.onInitialized?.();\n sendToolState({\n bridge: bridgeRef.current,\n input: inputRef.current,\n output: outputRef.current,\n });\n },\n }),\n [handlers],\n );\n const bridgeHandlersRef = useRef(bridgeHandlers);\n bridgeHandlersRef.current = bridgeHandlers;\n\n useEffect(() => {\n const iframe = iframeRef.current;\n const targetWindow = iframe?.contentWindow;\n if (targetWindow == null) {\n return;\n }\n\n initializedRef.current = false;\n\n const bridge = new MCPAppBridge({\n targetWindow,\n targetOrigin,\n handlers: bridgeHandlersRef.current,\n hostInfo,\n hostContext: hostContextRef.current,\n });\n bridgeRef.current = bridge;\n\n const onMessage = (event: MessageEvent) => {\n if (\n event.source === targetWindow &&\n event.data?.jsonrpc === '2.0' &&\n event.data.method === 'ui/notifications/sandbox-proxy-ready'\n ) {\n bridge.sendSandboxResourceReady({\n html: resource.html,\n csp: resourceCSP,\n sandbox: innerSandbox,\n allow: resourceAllow,\n });\n return;\n }\n\n bridge.handleMessage(event);\n };\n\n window.addEventListener('message', onMessage);\n\n return () => {\n initializedRef.current = false;\n window.removeEventListener('message', onMessage);\n void bridge.teardownResource().catch(() => {});\n bridge.close();\n bridgeRef.current = undefined;\n };\n }, [\n hostInfo,\n innerSandbox,\n resource.html,\n resourceAllow,\n resourceCSP,\n sandboxUrl,\n targetOrigin,\n ]);\n\n useEffect(() => {\n bridgeRef.current?.setHandlers(bridgeHandlers);\n }, [bridgeHandlers]);\n\n useEffect(() => {\n if (hostContext != null) {\n bridgeRef.current?.setHostContext(hostContext);\n }\n }, [hostContext]);\n\n useEffect(() => {\n if (initializedRef.current && input !== undefined) {\n bridgeRef.current?.sendToolInput(input);\n }\n }, [input]);\n\n useEffect(() => {\n if (initializedRef.current && output !== undefined) {\n bridgeRef.current?.sendToolResult(normalizeMCPAppToolResult(output));\n }\n }, [output]);\n\n return (\n <iframe\n ref={iframeRef}\n title=\"MCP App\"\n aria-label={sandbox.title ?? app.resourceUri}\n src={sandboxUrl}\n className={sandbox.className}\n style={sandbox.style}\n sandbox={sandbox.outerSandbox ?? MCP_APP_DEFAULT_OUTER_SANDBOX}\n />\n );\n}\n","import { isJSONObject } from '@ai-sdk/provider';\nimport type {\n MCPAppBridgeHandlers,\n MCPAppHostContext,\n MCPAppJsonRpcMessage,\n MCPAppJsonRpcNotification,\n MCPAppJsonRpcRequest,\n MCPAppJsonRpcResponse,\n MCPAppToolCallParams,\n} from './types';\n\nconst MCP_APP_PROTOCOL_VERSION = '2026-01-26';\n\n/**\n * Checks whether an iframe message looks like a JSON-RPC 2.0 message.\n */\nfunction isJsonRpcMessage(value: unknown): value is MCPAppJsonRpcMessage {\n return (\n value != null &&\n typeof value === 'object' &&\n !Array.isArray(value) &&\n 'jsonrpc' in value &&\n value.jsonrpc === '2.0'\n );\n}\n\n/**\n * Checks whether a JSON-RPC message expects a response.\n */\nfunction isRequest(\n message: MCPAppJsonRpcMessage,\n): message is MCPAppJsonRpcRequest {\n return 'method' in message && 'id' in message;\n}\n\n/**\n * Checks whether a JSON-RPC message is a fire-and-forget notification.\n */\nfunction isNotification(\n message: MCPAppJsonRpcMessage,\n): message is MCPAppJsonRpcNotification {\n return 'method' in message && !('id' in message);\n}\n\n/**\n * Normalizes unknown thrown values into an `Error`.\n */\nfunction toError(error: unknown): Error {\n return error instanceof Error ? error : new Error(String(error));\n}\n\n/**\n * Validates the params for app-initiated `tools/call` requests.\n */\nfunction assertToolCallParams(params: unknown): MCPAppToolCallParams {\n if (!isJSONObject(params) || typeof params.name !== 'string') {\n throw new Error('Invalid tools/call params');\n }\n\n return {\n name: params.name,\n arguments: isJSONObject(params.arguments) ? params.arguments : undefined,\n };\n}\n\n/**\n * Host-side JSON-RPC bridge for one MCP App iframe.\n *\n * It handles the MCP Apps initialization handshake, sends tool input/result\n * notifications to the iframe, and proxies allowed iframe requests through\n * host-provided callbacks.\n *\n * @example\n * ```ts\n * const bridge = new MCPAppBridge({\n * targetWindow: iframe.contentWindow!,\n * handlers: {\n * allowedTools: ['refreshDashboardData'],\n * callTool: params => client.callTool(params),\n * },\n * });\n *\n * window.addEventListener('message', event => bridge.handleMessage(event));\n * bridge.sendToolInput({ topic: 'usage' });\n * ```\n */\nexport class MCPAppBridge {\n private initialized = false;\n private pendingNotifications: MCPAppJsonRpcNotification[] = [];\n private nextRequestId = 0;\n private pendingResponses = new Map<\n string | number,\n {\n resolve: (value: unknown) => void;\n reject: (error: Error) => void;\n }\n >();\n\n constructor({\n targetWindow,\n targetOrigin = '*',\n handlers = {},\n hostInfo = { name: 'ai-sdk-react', version: '1.0.0' },\n hostContext = { displayMode: 'inline' },\n }: {\n targetWindow: Window;\n targetOrigin?: string;\n handlers?: MCPAppBridgeHandlers;\n hostInfo?: { name: string; version: string };\n hostContext?: MCPAppHostContext;\n }) {\n this.targetWindow = targetWindow;\n this.targetOrigin = targetOrigin;\n this.handlers = handlers;\n this.hostInfo = hostInfo;\n this.hostContext = hostContext;\n }\n\n private targetWindow: Window;\n private targetOrigin: string;\n private handlers: MCPAppBridgeHandlers;\n private hostInfo: { name: string; version: string };\n private hostContext: MCPAppHostContext;\n\n /**\n * Replaces the callbacks used to serve iframe requests.\n */\n setHandlers(handlers: MCPAppBridgeHandlers): void {\n this.handlers = handlers;\n }\n\n /**\n * Updates host context and notifies the iframe after initialization.\n *\n * @example\n * ```ts\n * bridge.setHostContext({ theme: 'dark', displayMode: 'inline' });\n * ```\n */\n setHostContext(hostContext: MCPAppHostContext): void {\n this.hostContext = hostContext;\n this.sendNotification({\n method: 'ui/notifications/host-context-changed',\n params: hostContext,\n });\n }\n\n /**\n * Processes one `message` event from the sandbox proxy iframe.\n */\n handleMessage(event: MessageEvent): void {\n if (event.source !== this.targetWindow || !isJsonRpcMessage(event.data)) {\n return;\n }\n\n const message = event.data;\n\n if ('result' in message || 'error' in message) {\n this.handleResponse(message);\n return;\n }\n\n if (isRequest(message)) {\n void this.handleRequest(message);\n return;\n }\n\n if (isNotification(message)) {\n this.handleNotification(message);\n }\n }\n\n /**\n * Sends app HTML and sandbox settings to the sandbox proxy.\n */\n sendSandboxResourceReady(params: unknown): void {\n this.post({\n jsonrpc: '2.0',\n method: 'ui/notifications/sandbox-resource-ready',\n params,\n });\n }\n\n /**\n * Sends final tool arguments to the MCP App.\n */\n sendToolInput(input: unknown): void {\n this.sendNotification({\n method: 'ui/notifications/tool-input',\n params: { arguments: input },\n });\n }\n\n /**\n * Sends a completed MCP tool result to the MCP App.\n */\n sendToolResult(result: unknown): void {\n this.sendNotification({\n method: 'ui/notifications/tool-result',\n params: result,\n });\n }\n\n /**\n * Notifies the MCP App that the related tool call was cancelled.\n */\n sendToolCancelled(reason?: string): void {\n this.sendNotification({\n method: 'ui/notifications/tool-cancelled',\n params: reason != null ? { reason } : {},\n });\n }\n\n /**\n * Requests graceful teardown before the host removes the iframe.\n */\n teardownResource(): Promise<unknown> {\n return this.request('ui/resource-teardown', {});\n }\n\n /**\n * Rejects pending bridge requests and clears queued notifications.\n */\n close(): void {\n for (const pending of this.pendingResponses.values()) {\n pending.reject(new Error('MCP App bridge closed'));\n }\n this.pendingResponses.clear();\n this.pendingNotifications = [];\n }\n\n /**\n * Resolves or rejects a host-initiated request when the iframe responds.\n */\n private handleResponse(response: MCPAppJsonRpcResponse): void {\n const pending = this.pendingResponses.get(response.id);\n if (pending == null) {\n return;\n }\n\n this.pendingResponses.delete(response.id);\n\n if (response.error != null) {\n pending.reject(new Error(response.error.message));\n } else {\n pending.resolve(response.result);\n }\n }\n\n /**\n * Runs a handler for an iframe request and posts the JSON-RPC response.\n */\n private async handleRequest(request: MCPAppJsonRpcRequest): Promise<void> {\n try {\n const result = await this.getRequestResult(request);\n this.post({ jsonrpc: '2.0', id: request.id, result });\n } catch (error) {\n const normalizedError = toError(error);\n this.handlers.onError?.(normalizedError);\n this.post({\n jsonrpc: '2.0',\n id: request.id,\n error: { code: -32603, message: normalizedError.message },\n });\n }\n }\n\n /**\n * Maps supported iframe request methods to host callbacks.\n */\n private async getRequestResult(\n request: MCPAppJsonRpcRequest,\n ): Promise<unknown> {\n switch (request.method) {\n case 'ui/initialize':\n return {\n protocolVersion: MCP_APP_PROTOCOL_VERSION,\n hostCapabilities: {\n ...(this.handlers.callTool != null ? { serverTools: {} } : {}),\n ...(this.handlers.readResource != null\n ? { serverResources: {} }\n : {}),\n ...(this.handlers.onLog != null ? { logging: {} } : {}),\n },\n hostInfo: this.hostInfo,\n hostContext: this.hostContext,\n };\n\n case 'tools/call': {\n if (this.handlers.callTool == null) {\n throw new Error('No tools/call handler configured');\n }\n const params = assertToolCallParams(request.params);\n if (\n this.handlers.allowedTools != null &&\n !this.handlers.allowedTools.includes(params.name)\n ) {\n throw new Error(`Tool is not app-visible: ${params.name}`);\n }\n return this.handlers.callTool(params);\n }\n\n case 'resources/read':\n if (this.handlers.readResource == null) {\n throw new Error('No resources/read handler configured');\n }\n return this.handlers.readResource(request.params as { uri: string });\n\n case 'resources/list':\n if (this.handlers.listResources == null) {\n throw new Error('No resources/list handler configured');\n }\n return this.handlers.listResources(request.params);\n\n case 'ui/open-link':\n if (this.handlers.openLink == null) {\n throw new Error('No ui/open-link handler configured');\n }\n return this.handlers.openLink(request.params as { url: string });\n\n case 'ui/message':\n return this.handlers.sendMessage?.(request.params) ?? {};\n\n case 'ui/update-model-context':\n return this.handlers.updateModelContext?.(request.params) ?? {};\n\n case 'ui/request-display-mode':\n return (\n this.handlers.requestDisplayMode?.(\n request.params as { mode: 'inline' | 'fullscreen' | 'pip' },\n ) ?? { mode: this.hostContext.displayMode ?? 'inline' }\n );\n\n default:\n throw new Error(`Unsupported MCP App method: ${request.method}`);\n }\n }\n\n /**\n * Handles iframe lifecycle and telemetry notifications.\n */\n private handleNotification(notification: MCPAppJsonRpcNotification): void {\n switch (notification.method) {\n case 'ui/notifications/initialized':\n this.initialized = true;\n this.flushNotifications();\n this.handlers.onInitialized?.();\n break;\n case 'ui/notifications/size-changed':\n this.handlers.onSizeChange?.(\n notification.params as { width?: number; height?: number },\n );\n break;\n case 'ui/notifications/request-teardown':\n this.handlers.onRequestTeardown?.(notification.params);\n break;\n case 'notifications/message':\n this.handlers.onLog?.(notification.params);\n break;\n }\n }\n\n /**\n * Sends a host-to-iframe notification, queueing it until app initialization.\n */\n private sendNotification(\n notification: Omit<MCPAppJsonRpcNotification, 'jsonrpc'>,\n ) {\n const message = { jsonrpc: '2.0' as const, ...notification };\n if (!this.initialized && !notification.method.includes('sandbox')) {\n this.pendingNotifications.push(message);\n return;\n }\n this.post(message);\n }\n\n /**\n * Sends notifications that were queued before `ui/notifications/initialized`.\n */\n private flushNotifications(): void {\n const notifications = this.pendingNotifications;\n this.pendingNotifications = [];\n for (const notification of notifications) {\n this.post(notification);\n }\n }\n\n /**\n * Sends a host-initiated JSON-RPC request to the iframe.\n */\n private request(method: string, params: unknown): Promise<unknown> {\n const id = this.nextRequestId++;\n this.post({ jsonrpc: '2.0', id, method, params });\n return new Promise((resolve, reject) => {\n this.pendingResponses.set(id, { resolve, reject });\n });\n }\n\n /**\n * Posts a JSON-RPC message to the sandbox proxy iframe.\n */\n private post(message: MCPAppJsonRpcMessage): void {\n this.targetWindow.postMessage(message, this.targetOrigin);\n }\n}\n","import type { MCPAppResourceCSP } from '@ai-sdk/mcp';\n\n/**\n * Default sandbox permissions for the outer sandbox proxy iframe.\n */\nexport const MCP_APP_DEFAULT_OUTER_SANDBOX =\n 'allow-scripts allow-same-origin allow-forms';\n\n/**\n * Default sandbox permissions for the inner iframe that runs app HTML.\n */\nexport const MCP_APP_DEFAULT_INNER_SANDBOX = 'allow-scripts allow-forms';\n\n/**\n * Converts MCP App CSP metadata into a Content-Security-Policy string.\n *\n * The returned value is meant to be passed to a sandbox proxy, which can apply\n * it to the inner iframe document.\n *\n * @example\n * ```ts\n * const csp = getMCPAppCSP({\n * connectDomains: ['https://api.example.com'],\n * resourceDomains: ['https://cdn.example.com'],\n * });\n * ```\n */\nexport function getMCPAppCSP(csp?: MCPAppResourceCSP): string | undefined {\n if (csp == null) {\n return undefined;\n }\n\n const connectSrc = [\"'self'\", ...(csp.connectDomains ?? [])];\n const imgSrc = [\"'self'\", 'data:', ...(csp.resourceDomains ?? [])];\n const frameSrc = [\"'self'\", ...(csp.frameDomains ?? [])];\n\n return [\n \"default-src 'none'\",\n \"script-src 'unsafe-inline'\",\n \"style-src 'unsafe-inline'\",\n `connect-src ${connectSrc.join(' ')}`,\n `img-src ${imgSrc.join(' ')}`,\n `font-src ${imgSrc.join(' ')}`,\n `frame-src ${frameSrc.join(' ')}`,\n ].join('; ');\n}\n\n/**\n * Converts MCP App permission metadata into an iframe `allow` attribute.\n *\n * @example\n * ```ts\n * const allow = getMCPAppAllowAttribute({\n * microphone: {},\n * clipboardWrite: {},\n * });\n * // \"microphone; clipboard-write\"\n * ```\n */\nexport function getMCPAppAllowAttribute(\n permissions?: Record<string, unknown>,\n): string | undefined {\n if (permissions == null) {\n return undefined;\n }\n\n const allow = [];\n if (permissions.camera) allow.push('camera');\n if (permissions.microphone) allow.push('microphone');\n if (permissions.geolocation) allow.push('geolocation');\n if (permissions.clipboardWrite) allow.push('clipboard-write');\n\n return allow.length > 0 ? allow.join('; ') : undefined;\n}\n","import { isJSONObject } from '@ai-sdk/provider';\nimport type { MCPAppMetadata, MCPAppRendererProps } from './types';\n\n/**\n * Extracts MCP App metadata from an AI SDK tool UI part.\n *\n * @example\n * ```ts\n * const app = getMCPAppFromToolPart({\n * type: 'dynamic-tool',\n * toolName: 'showDashboard',\n * toolCallId: 'call-1',\n * state: 'input-available',\n * input: { topic: 'usage' },\n * toolMetadata: {\n * mcp: {\n * app: {\n * resourceUri: 'ui://example/dashboard',\n * mimeType: 'text/html;profile=mcp-app',\n * },\n * },\n * },\n * });\n * // { resourceUri: 'ui://example/dashboard', mimeType: 'text/html;profile=mcp-app' }\n * ```\n */\nexport function getMCPAppFromToolPart(\n part: MCPAppRendererProps['part'],\n): MCPAppMetadata | undefined {\n const mcpMetadata = part.toolMetadata?.mcp;\n const rawAppMetadata = isJSONObject(mcpMetadata)\n ? mcpMetadata.app\n : undefined;\n const appMetadata = isJSONObject(rawAppMetadata) ? rawAppMetadata : undefined;\n\n if (\n appMetadata == null ||\n appMetadata.mimeType !== 'text/html;profile=mcp-app' ||\n typeof appMetadata.resourceUri !== 'string' ||\n !appMetadata.resourceUri.startsWith('ui://') ||\n (appMetadata.visibility != null &&\n (!Array.isArray(appMetadata.visibility) ||\n appMetadata.visibility.some(\n value => value !== 'model' && value !== 'app',\n )))\n ) {\n return undefined;\n }\n\n return appMetadata as MCPAppMetadata;\n}\n\n/**\n * Converts an AI SDK tool output into the MCP Apps tool-result shape.\n *\n * MCP Apps expect tool results to have `content` and optional\n * `structuredContent`. MCP tools already return that shape, but typed AI SDK\n * tools may return only structured data. This helper wraps structured-only\n * outputs so the iframe can receive a valid tool result notification.\n *\n * @example\n * ```ts\n * normalizeMCPAppToolResult({ cards: [] });\n * // { content: [], structuredContent: { cards: [] } }\n * ```\n */\nexport function normalizeMCPAppToolResult(output: unknown): {\n content: unknown[];\n structuredContent?: unknown;\n isError?: boolean;\n} {\n if (output != null && typeof output === 'object' && 'content' in output) {\n return output as {\n content: unknown[];\n structuredContent?: unknown;\n isError?: boolean;\n };\n }\n\n return {\n content: [],\n structuredContent: output,\n };\n}\n"],"mappings":"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","names":["useCallback","useEffect","useRef","fetch","useRef","useEffect","useCallback","completion","useCallback","useId","useRef","useState","useSWR","fetch","error","useEffect","useState","useEffect","useRef","resolve","isJSONObject","useRef","_a","useEffect","jsx","useState","useEffect","resource","error"]}
1
+ {"version":3,"sources":["../src/use-chat.ts","../src/chat.react.ts","../src/throttle.ts","../src/use-completion.ts","../src/use-object.ts","../src/use-realtime.ts","../src/mcp-apps/app-renderer.tsx","../src/mcp-apps/app-frame.tsx","../src/mcp-apps/bridge.ts","../src/mcp-apps/sandbox.ts","../src/mcp-apps/utils.ts"],"sourcesContent":["import type { AbstractChat, ChatInit, CreateUIMessage, UIMessage } from 'ai';\nimport { useCallback, useEffect, useRef, useSyncExternalStore } from 'react';\nimport { Chat } from './chat.react';\n\nexport type { CreateUIMessage, UIMessage };\n\nexport type UseChatHelpers<UI_MESSAGE extends UIMessage> = {\n /**\n * The id of the chat.\n */\n readonly id: string;\n\n /**\n * Update the `messages` state locally. This is useful when you want to\n * edit the messages on the client, and then trigger the `reload` method\n * manually to regenerate the AI response.\n */\n setMessages: (\n messages: UI_MESSAGE[] | ((messages: UI_MESSAGE[]) => UI_MESSAGE[]),\n ) => void;\n\n error: Error | undefined;\n} & Pick<\n AbstractChat<UI_MESSAGE>,\n | 'sendMessage'\n | 'regenerate'\n | 'stop'\n | 'resumeStream'\n | 'addToolResult'\n | 'addToolOutput'\n | 'addToolApprovalResponse'\n | 'status'\n | 'messages'\n | 'clearError'\n>;\n\nexport type UseChatOptions<UI_MESSAGE extends UIMessage> = (\n | { chat: Chat<UI_MESSAGE> }\n | ChatInit<UI_MESSAGE>\n) & {\n /**\n * Custom throttle wait in ms for the chat messages and data updates.\n * Default is undefined, which disables throttling.\n */\n experimental_throttle?: number;\n\n /**\n * Whether to resume an ongoing chat generation stream.\n */\n resume?: boolean;\n};\n\nexport function useChat<UI_MESSAGE extends UIMessage = UIMessage>({\n experimental_throttle: throttleWaitMs,\n resume = false,\n ...options\n}: UseChatOptions<UI_MESSAGE> = {}): UseChatHelpers<UI_MESSAGE> {\n // Create a single ref for all callbacks to avoid stale closures\n const callbacksRef = useRef(\n !('chat' in options)\n ? {\n onToolCall: options.onToolCall,\n onData: options.onData,\n onFinish: options.onFinish,\n onError: options.onError,\n sendAutomaticallyWhen: options.sendAutomaticallyWhen,\n }\n : {},\n );\n\n // Update callbacks ref on each render to keep them current\n if (!('chat' in options)) {\n callbacksRef.current = {\n onToolCall: options.onToolCall,\n onData: options.onData,\n onFinish: options.onFinish,\n onError: options.onError,\n sendAutomaticallyWhen: options.sendAutomaticallyWhen,\n };\n }\n\n // Ensure the Chat instance has the latest callbacks\n const optionsWithCallbacks: typeof options = {\n ...options,\n onToolCall: arg => callbacksRef.current.onToolCall?.(arg),\n onData: arg => callbacksRef.current.onData?.(arg),\n onFinish: arg => callbacksRef.current.onFinish?.(arg),\n onError: arg => callbacksRef.current.onError?.(arg),\n sendAutomaticallyWhen: arg =>\n callbacksRef.current.sendAutomaticallyWhen?.(arg) ?? false,\n };\n\n const chatRef = useRef<Chat<UI_MESSAGE>>(\n 'chat' in options ? options.chat : new Chat(optionsWithCallbacks),\n );\n\n const shouldRecreateChat =\n ('chat' in options && options.chat !== chatRef.current) ||\n ('id' in options && chatRef.current.id !== options.id);\n\n if (shouldRecreateChat) {\n chatRef.current =\n 'chat' in options ? options.chat : new Chat(optionsWithCallbacks);\n }\n\n const subscribeToMessages = useCallback(\n (update: () => void) =>\n chatRef.current['~registerMessagesCallback'](update, throttleWaitMs),\n // `chatRef.current.id` is required to trigger re-subscription when the chat ID changes\n // eslint-disable-next-line react-hooks/exhaustive-deps\n [throttleWaitMs, chatRef.current.id],\n );\n\n const messages = useSyncExternalStore(\n subscribeToMessages,\n () => chatRef.current.messages,\n () => chatRef.current.messages,\n );\n\n const status = useSyncExternalStore(\n chatRef.current['~registerStatusCallback'],\n () => chatRef.current.status,\n () => chatRef.current.status,\n );\n\n const error = useSyncExternalStore(\n chatRef.current['~registerErrorCallback'],\n () => chatRef.current.error,\n () => chatRef.current.error,\n );\n\n const setMessages = useCallback(\n (\n messagesParam: UI_MESSAGE[] | ((messages: UI_MESSAGE[]) => UI_MESSAGE[]),\n ) => {\n if (typeof messagesParam === 'function') {\n messagesParam = messagesParam(chatRef.current.messages);\n }\n chatRef.current.messages = messagesParam;\n },\n [chatRef],\n );\n\n useEffect(() => {\n if (resume) {\n chatRef.current.resumeStream();\n }\n }, [resume, chatRef]);\n\n return {\n id: chatRef.current.id,\n messages,\n setMessages,\n sendMessage: chatRef.current.sendMessage,\n regenerate: chatRef.current.regenerate,\n clearError: chatRef.current.clearError,\n stop: chatRef.current.stop,\n error,\n resumeStream: chatRef.current.resumeStream,\n status,\n /**\n * @deprecated Use `addToolOutput` instead.\n */\n addToolResult: chatRef.current.addToolOutput,\n addToolOutput: chatRef.current.addToolOutput,\n addToolApprovalResponse: chatRef.current.addToolApprovalResponse,\n };\n}\n","import {\n AbstractChat,\n type ChatInit,\n type ChatState,\n type ChatStatus,\n type UIMessage,\n} from 'ai';\nimport { throttle } from './throttle';\n\nclass ReactChatState<\n UI_MESSAGE extends UIMessage,\n> implements ChatState<UI_MESSAGE> {\n #messages: UI_MESSAGE[];\n #status: ChatStatus = 'ready';\n #error: Error | undefined = undefined;\n\n #messagesCallbacks = new Set<() => void>();\n #statusCallbacks = new Set<() => void>();\n #errorCallbacks = new Set<() => void>();\n\n constructor(initialMessages: UI_MESSAGE[] = []) {\n this.#messages = initialMessages;\n }\n\n get status(): ChatStatus {\n return this.#status;\n }\n\n set status(newStatus: ChatStatus) {\n this.#status = newStatus;\n this.#callStatusCallbacks();\n }\n\n get error(): Error | undefined {\n return this.#error;\n }\n\n set error(newError: Error | undefined) {\n this.#error = newError;\n this.#callErrorCallbacks();\n }\n\n get messages(): UI_MESSAGE[] {\n return this.#messages;\n }\n\n set messages(newMessages: UI_MESSAGE[]) {\n this.#messages = [...newMessages];\n this.#callMessagesCallbacks();\n }\n\n pushMessage = (message: UI_MESSAGE) => {\n this.#messages = this.#messages.concat(message);\n this.#callMessagesCallbacks();\n };\n\n popMessage = () => {\n this.#messages = this.#messages.slice(0, -1);\n this.#callMessagesCallbacks();\n };\n\n replaceMessage = (index: number, message: UI_MESSAGE) => {\n this.#messages = [\n ...this.#messages.slice(0, index),\n // We deep clone the message here to ensure the new React Compiler (currently in RC) detects deeply nested parts/metadata changes:\n this.snapshot(message),\n ...this.#messages.slice(index + 1),\n ];\n this.#callMessagesCallbacks();\n };\n\n snapshot = <T>(value: T): T => structuredClone(value);\n\n '~registerMessagesCallback' = (\n onChange: () => void,\n throttleWaitMs?: number,\n ): (() => void) => {\n const callback = throttleWaitMs\n ? throttle(onChange, throttleWaitMs)\n : onChange;\n this.#messagesCallbacks.add(callback);\n return () => {\n this.#messagesCallbacks.delete(callback);\n };\n };\n\n '~registerStatusCallback' = (onChange: () => void): (() => void) => {\n this.#statusCallbacks.add(onChange);\n return () => {\n this.#statusCallbacks.delete(onChange);\n };\n };\n\n '~registerErrorCallback' = (onChange: () => void): (() => void) => {\n this.#errorCallbacks.add(onChange);\n return () => {\n this.#errorCallbacks.delete(onChange);\n };\n };\n\n #callMessagesCallbacks = () => {\n this.#messagesCallbacks.forEach(callback => callback());\n };\n\n #callStatusCallbacks = () => {\n this.#statusCallbacks.forEach(callback => callback());\n };\n\n #callErrorCallbacks = () => {\n this.#errorCallbacks.forEach(callback => callback());\n };\n}\n\nexport class Chat<\n UI_MESSAGE extends UIMessage,\n> extends AbstractChat<UI_MESSAGE> {\n #state: ReactChatState<UI_MESSAGE>;\n\n constructor({ messages, ...init }: ChatInit<UI_MESSAGE>) {\n const state = new ReactChatState(messages);\n super({ ...init, state });\n this.#state = state;\n }\n\n '~registerMessagesCallback' = (\n onChange: () => void,\n throttleWaitMs?: number,\n ): (() => void) =>\n this.#state['~registerMessagesCallback'](onChange, throttleWaitMs);\n\n '~registerStatusCallback' = (onChange: () => void): (() => void) =>\n this.#state['~registerStatusCallback'](onChange);\n\n '~registerErrorCallback' = (onChange: () => void): (() => void) =>\n this.#state['~registerErrorCallback'](onChange);\n}\n","import throttleFunction from 'throttleit';\n\nexport function throttle<T extends (...args: any[]) => any>(\n fn: T,\n waitMs: number | undefined,\n): T {\n return waitMs != null ? throttleFunction(fn, waitMs) : fn;\n}\n","import {\n callCompletionApi,\n type CompletionRequestOptions,\n type UseCompletionOptions,\n} from 'ai';\nimport { useCallback, useEffect, useId, useRef, useState } from 'react';\nimport useSWR from 'swr';\nimport { throttle } from './throttle';\n\nexport type { UseCompletionOptions };\n\nexport type UseCompletionHelpers = {\n /** The current completion result */\n completion: string;\n /**\n * Send a new prompt to the API endpoint and update the completion state.\n */\n complete: (\n prompt: string,\n options?: CompletionRequestOptions,\n ) => Promise<string | null | undefined>;\n /** The error object of the API request */\n error: undefined | Error;\n /**\n * Abort the current API request but keep the generated tokens.\n */\n stop: () => void;\n /**\n * Update the `completion` state locally.\n */\n setCompletion: (completion: string) => void;\n /** The current value of the input */\n input: string;\n /** setState-powered method to update the input value */\n setInput: React.Dispatch<React.SetStateAction<string>>;\n /**\n * An input/textarea-ready onChange handler to control the value of the input\n * @example\n * ```jsx\n * <input onChange={handleInputChange} value={input} />\n * ```\n */\n handleInputChange: (\n event:\n | React.ChangeEvent<HTMLInputElement>\n | React.ChangeEvent<HTMLTextAreaElement>,\n ) => void;\n\n /**\n * Form submission handler to automatically reset input and append a user message\n * @example\n * ```jsx\n * <form onSubmit={handleSubmit}>\n * <input onChange={handleInputChange} value={input} />\n * </form>\n * ```\n */\n handleSubmit: (event?: { preventDefault?: () => void }) => void;\n\n /** Whether the API request is in progress */\n isLoading: boolean;\n};\n\nexport function useCompletion({\n api = '/api/completion',\n id,\n initialCompletion = '',\n initialInput = '',\n credentials,\n headers,\n body,\n streamProtocol = 'data',\n fetch,\n onFinish,\n onError,\n experimental_throttle: throttleWaitMs,\n}: UseCompletionOptions & {\n /**\n * Custom throttle wait in ms for the completion and data updates.\n * Default is undefined, which disables throttling.\n */\n experimental_throttle?: number;\n} = {}): UseCompletionHelpers {\n // Generate an unique id for the completion if not provided.\n const hookId = useId();\n const completionId = id || hookId;\n\n // Store the completion state in SWR, using the completionId as the key to share states.\n const { data, mutate } = useSWR<string>([api, completionId], null, {\n fallbackData: initialCompletion,\n });\n\n const { data: isLoading = false, mutate: mutateLoading } = useSWR<boolean>(\n [completionId, 'loading'],\n null,\n );\n\n const [error, setError] = useState<undefined | Error>(undefined);\n const completion = data!;\n\n // Abort controller to cancel the current API call.\n const [abortController, setAbortController] =\n useState<AbortController | null>(null);\n\n const extraMetadataRef = useRef({\n credentials,\n headers,\n body,\n });\n\n useEffect(() => {\n extraMetadataRef.current = {\n credentials,\n headers,\n body,\n };\n }, [credentials, headers, body]);\n\n const triggerRequest = useCallback(\n async (prompt: string, options?: CompletionRequestOptions) =>\n callCompletionApi({\n api,\n prompt,\n credentials: extraMetadataRef.current.credentials,\n headers: { ...extraMetadataRef.current.headers, ...options?.headers },\n body: {\n ...extraMetadataRef.current.body,\n ...options?.body,\n },\n streamProtocol,\n fetch,\n // throttle streamed ui updates:\n setCompletion: throttle(\n (completion: string) => mutate(completion, false),\n throttleWaitMs,\n ),\n setLoading: mutateLoading,\n setError,\n setAbortController,\n onFinish,\n onError,\n }),\n [\n mutate,\n mutateLoading,\n api,\n extraMetadataRef,\n setAbortController,\n onFinish,\n onError,\n setError,\n streamProtocol,\n fetch,\n throttleWaitMs,\n ],\n );\n\n const stop = useCallback(() => {\n if (abortController) {\n abortController.abort();\n setAbortController(null);\n }\n }, [abortController]);\n\n const setCompletion = useCallback(\n (completion: string) => {\n mutate(completion, false);\n },\n [mutate],\n );\n\n const complete = useCallback<UseCompletionHelpers['complete']>(\n async (prompt, options) => {\n return triggerRequest(prompt, options);\n },\n [triggerRequest],\n );\n\n const [input, setInput] = useState(initialInput);\n\n const handleSubmit = useCallback(\n (event?: { preventDefault?: () => void }) => {\n event?.preventDefault?.();\n return input ? complete(input) : undefined;\n },\n [input, complete],\n );\n\n const handleInputChange = useCallback(\n (e: any) => {\n setInput(e.target.value);\n },\n [setInput],\n );\n\n return {\n completion,\n complete,\n error,\n setCompletion,\n stop,\n input,\n setInput,\n handleInputChange,\n handleSubmit,\n isLoading,\n };\n}\n","import {\n isAbortError,\n resolve,\n normalizeHeaders,\n safeValidateTypes,\n type FetchFunction,\n type FlexibleSchema,\n type InferSchema,\n type Resolvable,\n} from '@ai-sdk/provider-utils';\nimport {\n asSchema,\n isDeepEqualData,\n parsePartialJson,\n type DeepPartial,\n} from 'ai';\nimport { useCallback, useId, useRef, useState } from 'react';\nimport useSWR from 'swr';\n\n// use function to allow for mocking in tests:\nconst getOriginalFetch = () => fetch;\n\nexport type Experimental_UseObjectOptions<\n SCHEMA extends FlexibleSchema,\n RESULT,\n> = {\n /**\n * The API endpoint. It should stream JSON that matches the schema as chunked text.\n */\n api: string;\n\n /**\n * A schema that defines the shape of the complete object.\n */\n schema: SCHEMA;\n\n /**\n * An unique identifier. If not provided, a random one will be\n * generated. When provided, the `useObject` hook with the same `id` will\n * have shared states across components.\n */\n id?: string;\n\n /**\n * An optional value for the initial object.\n */\n initialValue?: DeepPartial<RESULT>;\n\n /**\n * Custom fetch implementation. You can use it as a middleware to intercept requests,\n * or to provide a custom fetch implementation for e.g. testing.\n */\n fetch?: FetchFunction;\n\n /**\n * Callback that is called when the stream has finished.\n */\n onFinish?: (event: {\n /**\n * The generated object (typed according to the schema).\n * Can be undefined if the final object does not match the schema.\n */\n object: RESULT | undefined;\n\n /**\n * Optional error object. This is e.g. a TypeValidationError when the final object does not match the schema.\n */\n error: Error | undefined;\n }) => Promise<void> | void;\n\n /**\n * Callback function to be called when an error is encountered.\n */\n onError?: (error: Error) => void;\n\n /**\n * Additional HTTP headers to be included in the request.\n * Can be a static object, a function that returns headers, or an async function\n * for dynamic auth tokens.\n */\n headers?: Resolvable<Record<string, string> | Headers>;\n\n /**\n * The credentials mode to be used for the fetch request.\n * Possible values are: 'omit', 'same-origin', 'include'.\n * Defaults to 'same-origin'.\n */\n credentials?: RequestCredentials;\n};\n\nexport type Experimental_UseObjectHelpers<RESULT, INPUT> = {\n /**\n * Calls the API with the provided input as JSON body.\n */\n submit: (input: INPUT) => void;\n\n /**\n * The current value for the generated object. Updated as the API streams JSON chunks.\n */\n object: DeepPartial<RESULT> | undefined;\n\n /**\n * The error object of the API request if any.\n */\n error: Error | undefined;\n\n /**\n * Flag that indicates whether an API request is in progress.\n */\n isLoading: boolean;\n\n /**\n * Abort the current request immediately, keep the current partial object if any.\n */\n stop: () => void;\n\n /**\n * Clear the object state.\n */\n clear: () => void;\n};\n\nfunction useObject<\n SCHEMA extends FlexibleSchema,\n RESULT = InferSchema<SCHEMA>,\n INPUT = any,\n>({\n api,\n id,\n schema, // required, in the future we will use it for validation\n initialValue,\n fetch,\n onError,\n onFinish,\n headers,\n credentials,\n}: Experimental_UseObjectOptions<\n SCHEMA,\n RESULT\n>): Experimental_UseObjectHelpers<RESULT, INPUT> {\n // Generate an unique id if not provided.\n const hookId = useId();\n const completionId = id ?? hookId;\n\n // Store the completion state in SWR, using the completionId as the key to share states.\n const { data, mutate } = useSWR<DeepPartial<RESULT>>(\n [api, completionId],\n null,\n { fallbackData: initialValue },\n );\n\n const [error, setError] = useState<undefined | Error>(undefined);\n const [isLoading, setIsLoading] = useState(false);\n\n // Abort controller to cancel the current API call.\n const abortControllerRef = useRef<AbortController | null>(null);\n\n const stop = useCallback(() => {\n try {\n abortControllerRef.current?.abort();\n } catch {\n } finally {\n setIsLoading(false);\n abortControllerRef.current = null;\n }\n }, []);\n\n const submit = async (input: INPUT) => {\n try {\n clearObject();\n\n setIsLoading(true);\n\n const abortController = new AbortController();\n abortControllerRef.current = abortController;\n\n // Resolve headers at request time (supports async functions for dynamic auth tokens)\n const resolvedHeaders = await resolve(headers);\n\n const actualFetch = fetch ?? getOriginalFetch();\n const response = await actualFetch(api, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n ...normalizeHeaders(resolvedHeaders),\n },\n credentials,\n signal: abortController.signal,\n body: JSON.stringify(input),\n });\n\n if (!response.ok) {\n throw new Error(\n (await response.text()) ?? 'Failed to fetch the response.',\n );\n }\n\n if (response.body == null) {\n throw new Error('The response body is empty.');\n }\n\n let accumulatedText = '';\n let latestObject: DeepPartial<RESULT> | undefined = undefined;\n\n await response.body.pipeThrough(new TextDecoderStream()).pipeTo(\n new WritableStream<string>({\n async write(chunk) {\n accumulatedText += chunk;\n\n const { value } = await parsePartialJson(accumulatedText);\n const currentObject = value as DeepPartial<RESULT>;\n\n if (!isDeepEqualData(latestObject, currentObject)) {\n latestObject = currentObject;\n\n mutate(currentObject);\n }\n },\n\n async close() {\n setIsLoading(false);\n abortControllerRef.current = null;\n\n if (onFinish != null) {\n const validationResult = await safeValidateTypes({\n value: latestObject,\n schema: asSchema(schema),\n });\n\n onFinish(\n validationResult.success\n ? { object: validationResult.value, error: undefined }\n : { object: undefined, error: validationResult.error },\n );\n }\n },\n }),\n );\n } catch (error) {\n if (isAbortError(error)) {\n return;\n }\n\n if (onError && error instanceof Error) {\n onError(error);\n }\n\n setIsLoading(false);\n setError(error instanceof Error ? error : new Error(String(error)));\n }\n };\n\n const clear = () => {\n stop();\n clearObject();\n };\n\n const clearObject = () => {\n setError(undefined);\n setIsLoading(false);\n mutate(undefined);\n };\n\n return {\n submit,\n object: data,\n error,\n isLoading,\n stop,\n clear,\n };\n}\n\nexport const experimental_useObject = useObject;\n","import {\n Experimental_AbstractRealtimeSession as AbstractRealtimeSession,\n type Experimental_RealtimeServerEvent as RealtimeServerEvent,\n type Experimental_RealtimeSessionOptions as RealtimeSessionOptions,\n type Experimental_RealtimeState as RealtimeState,\n type Experimental_RealtimeStatus as RealtimeStatus,\n type UIMessage,\n} from 'ai';\nimport { useCallback, useEffect, useRef, useSyncExternalStore } from 'react';\n\ntype UseRealtimeOptions = RealtimeSessionOptions;\n\ntype RealtimeStateKey = keyof RealtimeState;\ntype RealtimeStoreKey = {\n model: RealtimeSessionOptions['model'];\n token: RealtimeSessionOptions['api']['token'];\n sessionConfig: RealtimeSessionOptions['sessionConfig'];\n sampleRate: RealtimeSessionOptions['sampleRate'];\n maxEvents: RealtimeSessionOptions['maxEvents'];\n};\n\nfunction getRealtimeStoreKey(options: UseRealtimeOptions): RealtimeStoreKey {\n return {\n model: options.model,\n token: options.api.token,\n sessionConfig: options.sessionConfig,\n sampleRate: options.sampleRate,\n maxEvents: options.maxEvents,\n };\n}\n\nfunction shouldCreateRealtimeStore(\n currentKey: RealtimeStoreKey,\n nextOptions: UseRealtimeOptions,\n): boolean {\n return (\n currentKey.model !== nextOptions.model ||\n currentKey.token !== nextOptions.api.token ||\n currentKey.sessionConfig !== nextOptions.sessionConfig ||\n currentKey.sampleRate !== nextOptions.sampleRate ||\n currentKey.maxEvents !== nextOptions.maxEvents\n );\n}\n\nclass RealtimeStore extends AbstractRealtimeSession {\n protected state: RealtimeState = {\n status: 'disconnected',\n messages: [],\n events: [],\n isCapturing: false,\n isPlaying: false,\n };\n\n private callbacks: { [K in RealtimeStateKey]: Set<() => void> } = {\n status: new Set(),\n messages: new Set(),\n events: new Set(),\n isCapturing: new Set(),\n isPlaying: new Set(),\n };\n\n get status(): RealtimeStatus {\n return this.state.status;\n }\n\n get messages(): UIMessage[] {\n return this.state.messages;\n }\n\n get events(): RealtimeServerEvent[] {\n return this.state.events;\n }\n\n get isCapturing(): boolean {\n return this.state.isCapturing;\n }\n\n get isPlaying(): boolean {\n return this.state.isPlaying;\n }\n\n subscribe(key: RealtimeStateKey, onChange: () => void): () => void {\n this.callbacks[key].add(onChange);\n\n return () => {\n this.callbacks[key].delete(onChange);\n };\n }\n\n protected setState<K extends RealtimeStateKey>(\n key: K,\n value: RealtimeState[K],\n ): void {\n this.state = { ...this.state, [key]: value };\n this.callbacks[key].forEach(callback => callback());\n }\n\n protected pushMessage(message: UIMessage): void {\n this.state = {\n ...this.state,\n messages: [...this.state.messages, message],\n };\n this.callbacks.messages.forEach(callback => callback());\n }\n\n protected updateMessages(\n updater: (messages: UIMessage[]) => UIMessage[],\n ): void {\n this.state = {\n ...this.state,\n messages: updater(this.state.messages),\n };\n this.callbacks.messages.forEach(callback => callback());\n }\n\n protected pushEvent(event: RealtimeServerEvent): void {\n const nextEvents = [...this.state.events, event];\n this.state = {\n ...this.state,\n events:\n nextEvents.length > this.maxEvents\n ? nextEvents.slice(-this.maxEvents)\n : nextEvents,\n };\n this.callbacks.events.forEach(callback => callback());\n }\n}\n\ntype UseRealtimeReturn = {\n status: RealtimeStatus;\n messages: UIMessage[];\n events: RealtimeServerEvent[];\n isCapturing: boolean;\n isPlaying: boolean;\n\n connect: () => Promise<void>;\n disconnect: () => void;\n addToolOutput: (callId: string, result: unknown) => void;\n sendEvent: RealtimeStore['sendEvent'];\n sendTextMessage: (text: string) => void;\n sendAudio: (base64Audio: string) => void;\n commitAudio: () => void;\n clearAudioBuffer: () => void;\n requestResponse: (options?: { modalities?: string[] }) => void;\n cancelResponse: () => void;\n startAudioCapture: (stream: MediaStream) => void;\n stopAudioCapture: () => void;\n stopPlayback: () => void;\n};\n\nfunction useRealtime(options: UseRealtimeOptions): UseRealtimeReturn {\n const callbacksRef = useRef({\n onToolCall: options.onToolCall,\n onEvent: options.onEvent,\n onError: options.onError,\n });\n callbacksRef.current = {\n onToolCall: options.onToolCall,\n onEvent: options.onEvent,\n onError: options.onError,\n };\n\n const realtimeRef = useRef<{\n store: RealtimeStore;\n key: RealtimeStoreKey;\n } | null>(null);\n\n let realtimeEntry = realtimeRef.current;\n\n if (\n realtimeEntry == null ||\n shouldCreateRealtimeStore(realtimeEntry.key, options)\n ) {\n realtimeEntry = {\n store: new RealtimeStore({\n ...options,\n onToolCall: (...args) => callbacksRef.current.onToolCall?.(...args),\n onEvent: (...args) => callbacksRef.current.onEvent?.(...args),\n onError: (...args) => callbacksRef.current.onError?.(...args),\n }),\n key: getRealtimeStoreKey(options),\n };\n realtimeRef.current = realtimeEntry;\n } else {\n realtimeEntry.key = getRealtimeStoreKey(options);\n }\n\n const rt = realtimeEntry.store;\n\n const status = useSyncExternalStore(\n useCallback(cb => rt.subscribe('status', cb), [rt]),\n () => rt.status,\n () => rt.status,\n );\n\n const messages = useSyncExternalStore(\n useCallback(cb => rt.subscribe('messages', cb), [rt]),\n () => rt.messages,\n () => rt.messages,\n );\n\n const events = useSyncExternalStore(\n useCallback(cb => rt.subscribe('events', cb), [rt]),\n () => rt.events,\n () => rt.events,\n );\n\n const isCapturing = useSyncExternalStore(\n useCallback(cb => rt.subscribe('isCapturing', cb), [rt]),\n () => rt.isCapturing,\n () => rt.isCapturing,\n );\n\n const isPlaying = useSyncExternalStore(\n useCallback(cb => rt.subscribe('isPlaying', cb), [rt]),\n () => rt.isPlaying,\n () => rt.isPlaying,\n );\n\n useEffect(() => {\n return () => rt.dispose();\n }, [rt]);\n\n return {\n status,\n messages,\n events,\n isCapturing,\n isPlaying,\n connect: rt.connect.bind(rt),\n disconnect: rt.disconnect.bind(rt),\n addToolOutput: rt.addToolOutput.bind(rt),\n sendEvent: rt.sendEvent.bind(rt),\n sendTextMessage: rt.sendTextMessage.bind(rt),\n sendAudio: rt.sendAudio.bind(rt),\n commitAudio: rt.commitAudio.bind(rt),\n clearAudioBuffer: rt.clearAudioBuffer.bind(rt),\n requestResponse: rt.requestResponse.bind(rt),\n cancelResponse: rt.cancelResponse.bind(rt),\n startAudioCapture: rt.startAudioCapture.bind(rt),\n stopAudioCapture: rt.stopAudioCapture.bind(rt),\n stopPlayback: rt.stopPlayback.bind(rt),\n };\n}\n\nexport const experimental_useRealtime = useRealtime;\n\nexport type {\n RealtimeStatus as Experimental_RealtimeStatus,\n UseRealtimeOptions as Experimental_UseRealtimeOptions,\n UseRealtimeReturn as Experimental_UseRealtimeReturn,\n};\n","import type { MCPAppResource } from '@ai-sdk/mcp';\nimport { useEffect, useState } from 'react';\nimport { MCPAppFrame } from './app-frame';\nimport type { MCPAppMetadata, MCPAppRendererProps } from './types';\nimport { getMCPAppFromToolPart } from './utils';\n\ntype LoadedResourceState = {\n resourceUri: string;\n resource?: MCPAppResource;\n error?: Error;\n};\n\nfunction getToolPartOutput(part: MCPAppRendererProps['part']): unknown {\n return part.state === 'output-available' ? part.output : undefined;\n}\n\nfunction getToolPartInput(part: MCPAppRendererProps['part']): unknown {\n return part.state === 'input-available' || part.state === 'output-available'\n ? part.input\n : undefined;\n}\n\nexport function MCPAppRenderer({\n part,\n sandbox,\n resource: resourceProp,\n loadResource,\n handlers,\n hostInfo,\n hostContext,\n fallback = null,\n}: MCPAppRendererProps) {\n const app = getMCPAppFromToolPart(part);\n const [cachedApp, setCachedApp] = useState<MCPAppMetadata>();\n const [loadedResource, setLoadedResource] = useState<LoadedResourceState>();\n\n useEffect(() => {\n if (app != null) {\n setCachedApp(previous =>\n previous?.resourceUri === app.resourceUri ? previous : app,\n );\n }\n }, [app?.resourceUri]);\n\n const appForRender = app ?? cachedApp;\n\n useEffect(() => {\n if (appForRender == null || resourceProp != null || loadResource == null) {\n return;\n }\n\n let cancelled = false;\n const resourceUri = appForRender.resourceUri;\n\n loadResource(appForRender)\n .then(resource => {\n if (!cancelled) {\n setLoadedResource({ resourceUri, resource });\n }\n })\n .catch(error => {\n if (!cancelled) {\n setLoadedResource({\n resourceUri,\n error: error instanceof Error ? error : new Error(String(error)),\n });\n }\n });\n\n return () => {\n cancelled = true;\n };\n }, [appForRender?.resourceUri, loadResource, resourceProp]);\n\n const loadedResourceForApp =\n loadedResource?.resourceUri === appForRender?.resourceUri\n ? loadedResource\n : undefined;\n const resource = resourceProp ?? loadedResourceForApp?.resource;\n const error = resourceProp == null ? loadedResourceForApp?.error : undefined;\n\n if (appForRender == null || error != null || resource == null) {\n return fallback;\n }\n\n return (\n <MCPAppFrame\n app={appForRender}\n resource={resource}\n input={getToolPartInput(part)}\n output={getToolPartOutput(part)}\n sandbox={sandbox}\n handlers={handlers}\n hostInfo={hostInfo}\n hostContext={hostContext}\n />\n );\n}\n","import { useEffect, useMemo, useRef } from 'react';\nimport { MCPAppBridge } from './bridge';\nimport {\n MCP_APP_DEFAULT_INNER_SANDBOX,\n MCP_APP_DEFAULT_OUTER_SANDBOX,\n getMCPAppAllowAttribute,\n getMCPAppCSP,\n} from './sandbox';\nimport type { MCPAppFrameProps } from './types';\nimport { normalizeMCPAppToolResult } from './utils';\n\nfunction sendToolState({\n bridge,\n input,\n output,\n}: {\n bridge?: MCPAppBridge;\n input: unknown;\n output: unknown;\n}) {\n if (bridge == null) {\n return;\n }\n\n if (input !== undefined) {\n bridge.sendToolInput(input);\n }\n\n if (output !== undefined) {\n bridge.sendToolResult(normalizeMCPAppToolResult(output));\n }\n}\n\nexport function MCPAppFrame({\n app,\n resource,\n input,\n output,\n sandbox,\n handlers,\n hostInfo,\n hostContext,\n}: MCPAppFrameProps) {\n const iframeRef = useRef<HTMLIFrameElement>(null);\n const bridgeRef = useRef<MCPAppBridge | undefined>(undefined);\n const inputRef = useRef(input);\n const outputRef = useRef(output);\n const hostContextRef = useRef(hostContext);\n const initializedRef = useRef(false);\n inputRef.current = input;\n outputRef.current = output;\n hostContextRef.current = hostContext;\n const targetOrigin = sandbox.targetOrigin ?? '*';\n const sandboxUrl = String(sandbox.url);\n const resourceCSP = getMCPAppCSP(resource.meta?.csp);\n const resourceAllow = getMCPAppAllowAttribute(resource.meta?.permissions);\n const innerSandbox = sandbox.innerSandbox ?? MCP_APP_DEFAULT_INNER_SANDBOX;\n const bridgeHandlers = useMemo(\n () => ({\n ...handlers,\n onInitialized: () => {\n initializedRef.current = true;\n handlers?.onInitialized?.();\n sendToolState({\n bridge: bridgeRef.current,\n input: inputRef.current,\n output: outputRef.current,\n });\n },\n }),\n [handlers],\n );\n const bridgeHandlersRef = useRef(bridgeHandlers);\n bridgeHandlersRef.current = bridgeHandlers;\n\n useEffect(() => {\n const iframe = iframeRef.current;\n const targetWindow = iframe?.contentWindow;\n if (targetWindow == null) {\n return;\n }\n\n initializedRef.current = false;\n\n const bridge = new MCPAppBridge({\n targetWindow,\n targetOrigin,\n handlers: bridgeHandlersRef.current,\n hostInfo,\n hostContext: hostContextRef.current,\n });\n bridgeRef.current = bridge;\n\n const onMessage = (event: MessageEvent) => {\n if (\n event.source === targetWindow &&\n event.data?.jsonrpc === '2.0' &&\n event.data.method === 'ui/notifications/sandbox-proxy-ready'\n ) {\n bridge.sendSandboxResourceReady({\n html: resource.html,\n csp: resourceCSP,\n sandbox: innerSandbox,\n allow: resourceAllow,\n });\n return;\n }\n\n bridge.handleMessage(event);\n };\n\n window.addEventListener('message', onMessage);\n\n return () => {\n initializedRef.current = false;\n window.removeEventListener('message', onMessage);\n void bridge.teardownResource().catch(() => {});\n bridge.close();\n bridgeRef.current = undefined;\n };\n }, [\n hostInfo,\n innerSandbox,\n resource.html,\n resourceAllow,\n resourceCSP,\n sandboxUrl,\n targetOrigin,\n ]);\n\n useEffect(() => {\n bridgeRef.current?.setHandlers(bridgeHandlers);\n }, [bridgeHandlers]);\n\n useEffect(() => {\n if (hostContext != null) {\n bridgeRef.current?.setHostContext(hostContext);\n }\n }, [hostContext]);\n\n useEffect(() => {\n if (initializedRef.current && input !== undefined) {\n bridgeRef.current?.sendToolInput(input);\n }\n }, [input]);\n\n useEffect(() => {\n if (initializedRef.current && output !== undefined) {\n bridgeRef.current?.sendToolResult(normalizeMCPAppToolResult(output));\n }\n }, [output]);\n\n return (\n <iframe\n ref={iframeRef}\n title=\"MCP App\"\n aria-label={sandbox.title ?? app.resourceUri}\n src={sandboxUrl}\n className={sandbox.className}\n style={sandbox.style}\n sandbox={sandbox.outerSandbox ?? MCP_APP_DEFAULT_OUTER_SANDBOX}\n />\n );\n}\n","import { isJSONObject } from '@ai-sdk/provider';\nimport type {\n MCPAppBridgeHandlers,\n MCPAppHostContext,\n MCPAppJsonRpcMessage,\n MCPAppJsonRpcNotification,\n MCPAppJsonRpcRequest,\n MCPAppJsonRpcResponse,\n MCPAppToolCallParams,\n} from './types';\n\nconst MCP_APP_PROTOCOL_VERSION = '2026-01-26';\n\n/**\n * Checks whether an iframe message looks like a JSON-RPC 2.0 message.\n */\nfunction isJsonRpcMessage(value: unknown): value is MCPAppJsonRpcMessage {\n return (\n value != null &&\n typeof value === 'object' &&\n !Array.isArray(value) &&\n 'jsonrpc' in value &&\n value.jsonrpc === '2.0'\n );\n}\n\n/**\n * Checks whether a JSON-RPC message expects a response.\n */\nfunction isRequest(\n message: MCPAppJsonRpcMessage,\n): message is MCPAppJsonRpcRequest {\n return 'method' in message && 'id' in message;\n}\n\n/**\n * Checks whether a JSON-RPC message is a fire-and-forget notification.\n */\nfunction isNotification(\n message: MCPAppJsonRpcMessage,\n): message is MCPAppJsonRpcNotification {\n return 'method' in message && !('id' in message);\n}\n\n/**\n * Normalizes unknown thrown values into an `Error`.\n */\nfunction toError(error: unknown): Error {\n return error instanceof Error ? error : new Error(String(error));\n}\n\n/**\n * Validates the params for app-initiated `tools/call` requests.\n */\nfunction assertToolCallParams(params: unknown): MCPAppToolCallParams {\n if (!isJSONObject(params) || typeof params.name !== 'string') {\n throw new Error('Invalid tools/call params');\n }\n\n return {\n name: params.name,\n arguments: isJSONObject(params.arguments) ? params.arguments : undefined,\n };\n}\n\n/**\n * Host-side JSON-RPC bridge for one MCP App iframe.\n *\n * It handles the MCP Apps initialization handshake, sends tool input/result\n * notifications to the iframe, and proxies allowed iframe requests through\n * host-provided callbacks.\n *\n * @example\n * ```ts\n * const bridge = new MCPAppBridge({\n * targetWindow: iframe.contentWindow!,\n * handlers: {\n * allowedTools: ['refreshDashboardData'],\n * callTool: params => client.callTool(params),\n * },\n * });\n *\n * window.addEventListener('message', event => bridge.handleMessage(event));\n * bridge.sendToolInput({ topic: 'usage' });\n * ```\n */\nexport class MCPAppBridge {\n private initialized = false;\n private pendingNotifications: MCPAppJsonRpcNotification[] = [];\n private nextRequestId = 0;\n private pendingResponses = new Map<\n string | number,\n {\n resolve: (value: unknown) => void;\n reject: (error: Error) => void;\n }\n >();\n\n constructor({\n targetWindow,\n targetOrigin = '*',\n handlers = {},\n hostInfo = { name: 'ai-sdk-react', version: '1.0.0' },\n hostContext = { displayMode: 'inline' },\n }: {\n targetWindow: Window;\n targetOrigin?: string;\n handlers?: MCPAppBridgeHandlers;\n hostInfo?: { name: string; version: string };\n hostContext?: MCPAppHostContext;\n }) {\n this.targetWindow = targetWindow;\n this.targetOrigin = targetOrigin;\n this.handlers = handlers;\n this.hostInfo = hostInfo;\n this.hostContext = hostContext;\n }\n\n private targetWindow: Window;\n private targetOrigin: string;\n private handlers: MCPAppBridgeHandlers;\n private hostInfo: { name: string; version: string };\n private hostContext: MCPAppHostContext;\n\n /**\n * Replaces the callbacks used to serve iframe requests.\n */\n setHandlers(handlers: MCPAppBridgeHandlers): void {\n this.handlers = handlers;\n }\n\n /**\n * Updates host context and notifies the iframe after initialization.\n *\n * @example\n * ```ts\n * bridge.setHostContext({ theme: 'dark', displayMode: 'inline' });\n * ```\n */\n setHostContext(hostContext: MCPAppHostContext): void {\n this.hostContext = hostContext;\n this.sendNotification({\n method: 'ui/notifications/host-context-changed',\n params: hostContext,\n });\n }\n\n /**\n * Processes one `message` event from the sandbox proxy iframe.\n */\n handleMessage(event: MessageEvent): void {\n if (event.source !== this.targetWindow || !isJsonRpcMessage(event.data)) {\n return;\n }\n\n const message = event.data;\n\n if ('result' in message || 'error' in message) {\n this.handleResponse(message);\n return;\n }\n\n if (isRequest(message)) {\n void this.handleRequest(message);\n return;\n }\n\n if (isNotification(message)) {\n this.handleNotification(message);\n }\n }\n\n /**\n * Sends app HTML and sandbox settings to the sandbox proxy.\n */\n sendSandboxResourceReady(params: unknown): void {\n this.post({\n jsonrpc: '2.0',\n method: 'ui/notifications/sandbox-resource-ready',\n params,\n });\n }\n\n /**\n * Sends final tool arguments to the MCP App.\n */\n sendToolInput(input: unknown): void {\n this.sendNotification({\n method: 'ui/notifications/tool-input',\n params: { arguments: input },\n });\n }\n\n /**\n * Sends a completed MCP tool result to the MCP App.\n */\n sendToolResult(result: unknown): void {\n this.sendNotification({\n method: 'ui/notifications/tool-result',\n params: result,\n });\n }\n\n /**\n * Notifies the MCP App that the related tool call was cancelled.\n */\n sendToolCancelled(reason?: string): void {\n this.sendNotification({\n method: 'ui/notifications/tool-cancelled',\n params: reason != null ? { reason } : {},\n });\n }\n\n /**\n * Requests graceful teardown before the host removes the iframe.\n */\n teardownResource(): Promise<unknown> {\n return this.request('ui/resource-teardown', {});\n }\n\n /**\n * Rejects pending bridge requests and clears queued notifications.\n */\n close(): void {\n for (const pending of this.pendingResponses.values()) {\n pending.reject(new Error('MCP App bridge closed'));\n }\n this.pendingResponses.clear();\n this.pendingNotifications = [];\n }\n\n /**\n * Resolves or rejects a host-initiated request when the iframe responds.\n */\n private handleResponse(response: MCPAppJsonRpcResponse): void {\n const pending = this.pendingResponses.get(response.id);\n if (pending == null) {\n return;\n }\n\n this.pendingResponses.delete(response.id);\n\n if (response.error != null) {\n pending.reject(new Error(response.error.message));\n } else {\n pending.resolve(response.result);\n }\n }\n\n /**\n * Runs a handler for an iframe request and posts the JSON-RPC response.\n */\n private async handleRequest(request: MCPAppJsonRpcRequest): Promise<void> {\n try {\n const result = await this.getRequestResult(request);\n this.post({ jsonrpc: '2.0', id: request.id, result });\n } catch (error) {\n const normalizedError = toError(error);\n this.handlers.onError?.(normalizedError);\n this.post({\n jsonrpc: '2.0',\n id: request.id,\n error: { code: -32603, message: normalizedError.message },\n });\n }\n }\n\n /**\n * Maps supported iframe request methods to host callbacks.\n */\n private async getRequestResult(\n request: MCPAppJsonRpcRequest,\n ): Promise<unknown> {\n switch (request.method) {\n case 'ui/initialize':\n return {\n protocolVersion: MCP_APP_PROTOCOL_VERSION,\n hostCapabilities: {\n ...(this.handlers.callTool != null ? { serverTools: {} } : {}),\n ...(this.handlers.readResource != null\n ? { serverResources: {} }\n : {}),\n ...(this.handlers.onLog != null ? { logging: {} } : {}),\n },\n hostInfo: this.hostInfo,\n hostContext: this.hostContext,\n };\n\n case 'tools/call': {\n if (this.handlers.callTool == null) {\n throw new Error('No tools/call handler configured');\n }\n const params = assertToolCallParams(request.params);\n if (\n this.handlers.allowedTools != null &&\n !this.handlers.allowedTools.includes(params.name)\n ) {\n throw new Error(`Tool is not app-visible: ${params.name}`);\n }\n return this.handlers.callTool(params);\n }\n\n case 'resources/read':\n if (this.handlers.readResource == null) {\n throw new Error('No resources/read handler configured');\n }\n return this.handlers.readResource(request.params as { uri: string });\n\n case 'resources/list':\n if (this.handlers.listResources == null) {\n throw new Error('No resources/list handler configured');\n }\n return this.handlers.listResources(request.params);\n\n case 'ui/open-link':\n if (this.handlers.openLink == null) {\n throw new Error('No ui/open-link handler configured');\n }\n return this.handlers.openLink(request.params as { url: string });\n\n case 'ui/message':\n return this.handlers.sendMessage?.(request.params) ?? {};\n\n case 'ui/update-model-context':\n return this.handlers.updateModelContext?.(request.params) ?? {};\n\n case 'ui/request-display-mode':\n return (\n this.handlers.requestDisplayMode?.(\n request.params as { mode: 'inline' | 'fullscreen' | 'pip' },\n ) ?? { mode: this.hostContext.displayMode ?? 'inline' }\n );\n\n default:\n throw new Error(`Unsupported MCP App method: ${request.method}`);\n }\n }\n\n /**\n * Handles iframe lifecycle and telemetry notifications.\n */\n private handleNotification(notification: MCPAppJsonRpcNotification): void {\n switch (notification.method) {\n case 'ui/notifications/initialized':\n this.initialized = true;\n this.flushNotifications();\n this.handlers.onInitialized?.();\n break;\n case 'ui/notifications/size-changed':\n this.handlers.onSizeChange?.(\n notification.params as { width?: number; height?: number },\n );\n break;\n case 'ui/notifications/request-teardown':\n this.handlers.onRequestTeardown?.(notification.params);\n break;\n case 'notifications/message':\n this.handlers.onLog?.(notification.params);\n break;\n }\n }\n\n /**\n * Sends a host-to-iframe notification, queueing it until app initialization.\n */\n private sendNotification(\n notification: Omit<MCPAppJsonRpcNotification, 'jsonrpc'>,\n ) {\n const message = { jsonrpc: '2.0' as const, ...notification };\n if (!this.initialized && !notification.method.includes('sandbox')) {\n this.pendingNotifications.push(message);\n return;\n }\n this.post(message);\n }\n\n /**\n * Sends notifications that were queued before `ui/notifications/initialized`.\n */\n private flushNotifications(): void {\n const notifications = this.pendingNotifications;\n this.pendingNotifications = [];\n for (const notification of notifications) {\n this.post(notification);\n }\n }\n\n /**\n * Sends a host-initiated JSON-RPC request to the iframe.\n */\n private request(method: string, params: unknown): Promise<unknown> {\n const id = this.nextRequestId++;\n this.post({ jsonrpc: '2.0', id, method, params });\n return new Promise((resolve, reject) => {\n this.pendingResponses.set(id, { resolve, reject });\n });\n }\n\n /**\n * Posts a JSON-RPC message to the sandbox proxy iframe.\n */\n private post(message: MCPAppJsonRpcMessage): void {\n this.targetWindow.postMessage(message, this.targetOrigin);\n }\n}\n","import type { MCPAppResourceCSP } from '@ai-sdk/mcp';\n\n/**\n * Default sandbox permissions for the outer sandbox proxy iframe.\n */\nexport const MCP_APP_DEFAULT_OUTER_SANDBOX =\n 'allow-scripts allow-same-origin allow-forms';\n\n/**\n * Default sandbox permissions for the inner iframe that runs app HTML.\n */\nexport const MCP_APP_DEFAULT_INNER_SANDBOX = 'allow-scripts allow-forms';\n\n/**\n * Converts MCP App CSP metadata into a Content-Security-Policy string.\n *\n * The returned value is meant to be passed to a sandbox proxy, which can apply\n * it to the inner iframe document.\n *\n * @example\n * ```ts\n * const csp = getMCPAppCSP({\n * connectDomains: ['https://api.example.com'],\n * resourceDomains: ['https://cdn.example.com'],\n * });\n * ```\n */\nexport function getMCPAppCSP(csp?: MCPAppResourceCSP): string | undefined {\n if (csp == null) {\n return undefined;\n }\n\n const connectSrc = [\"'self'\", ...(csp.connectDomains ?? [])];\n const imgSrc = [\"'self'\", 'data:', ...(csp.resourceDomains ?? [])];\n const frameSrc = [\"'self'\", ...(csp.frameDomains ?? [])];\n\n return [\n \"default-src 'none'\",\n \"script-src 'unsafe-inline'\",\n \"style-src 'unsafe-inline'\",\n `connect-src ${connectSrc.join(' ')}`,\n `img-src ${imgSrc.join(' ')}`,\n `font-src ${imgSrc.join(' ')}`,\n `frame-src ${frameSrc.join(' ')}`,\n ].join('; ');\n}\n\n/**\n * Converts MCP App permission metadata into an iframe `allow` attribute.\n *\n * @example\n * ```ts\n * const allow = getMCPAppAllowAttribute({\n * microphone: {},\n * clipboardWrite: {},\n * });\n * // \"microphone; clipboard-write\"\n * ```\n */\nexport function getMCPAppAllowAttribute(\n permissions?: Record<string, unknown>,\n): string | undefined {\n if (permissions == null) {\n return undefined;\n }\n\n const allow = [];\n if (permissions.camera) allow.push('camera');\n if (permissions.microphone) allow.push('microphone');\n if (permissions.geolocation) allow.push('geolocation');\n if (permissions.clipboardWrite) allow.push('clipboard-write');\n\n return allow.length > 0 ? allow.join('; ') : undefined;\n}\n","import { isJSONObject } from '@ai-sdk/provider';\nimport type { MCPAppMetadata, MCPAppRendererProps } from './types';\n\n/**\n * Extracts MCP App metadata from an AI SDK tool UI part.\n *\n * @example\n * ```ts\n * const app = getMCPAppFromToolPart({\n * type: 'dynamic-tool',\n * toolName: 'showDashboard',\n * toolCallId: 'call-1',\n * state: 'input-available',\n * input: { topic: 'usage' },\n * toolMetadata: {\n * mcp: {\n * app: {\n * resourceUri: 'ui://example/dashboard',\n * mimeType: 'text/html;profile=mcp-app',\n * },\n * },\n * },\n * });\n * // { resourceUri: 'ui://example/dashboard', mimeType: 'text/html;profile=mcp-app' }\n * ```\n */\nexport function getMCPAppFromToolPart(\n part: MCPAppRendererProps['part'],\n): MCPAppMetadata | undefined {\n const mcpMetadata = part.toolMetadata?.mcp;\n const rawAppMetadata = isJSONObject(mcpMetadata)\n ? mcpMetadata.app\n : undefined;\n const appMetadata = isJSONObject(rawAppMetadata) ? rawAppMetadata : undefined;\n\n if (\n appMetadata == null ||\n appMetadata.mimeType !== 'text/html;profile=mcp-app' ||\n typeof appMetadata.resourceUri !== 'string' ||\n !appMetadata.resourceUri.startsWith('ui://') ||\n (appMetadata.visibility != null &&\n (!Array.isArray(appMetadata.visibility) ||\n appMetadata.visibility.some(\n value => value !== 'model' && value !== 'app',\n )))\n ) {\n return undefined;\n }\n\n return appMetadata as MCPAppMetadata;\n}\n\n/**\n * Converts an AI SDK tool output into the MCP Apps tool-result shape.\n *\n * MCP Apps expect tool results to have `content` and optional\n * `structuredContent`. MCP tools already return that shape, but typed AI SDK\n * tools may return only structured data. This helper wraps structured-only\n * outputs so the iframe can receive a valid tool result notification.\n *\n * @example\n * ```ts\n * normalizeMCPAppToolResult({ cards: [] });\n * // { content: [], structuredContent: { cards: [] } }\n * ```\n */\nexport function normalizeMCPAppToolResult(output: unknown): {\n content: unknown[];\n structuredContent?: unknown;\n isError?: boolean;\n} {\n if (output != null && typeof output === 'object' && 'content' in output) {\n return output as {\n content: unknown[];\n structuredContent?: unknown;\n isError?: boolean;\n };\n }\n\n return {\n content: [],\n structuredContent: output,\n };\n}\n"],"mappings":"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","names":["useCallback","useEffect","useRef","fetch","useRef","useEffect","useCallback","completion","useCallback","useId","useRef","useState","useSWR","fetch","error","useCallback","useEffect","useRef","useSyncExternalStore","useEffect","useState","useEffect","useRef","resolve","isJSONObject","useRef","_a","useEffect","jsx","useState","useEffect","resource","error"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ai-sdk/react",
3
- "version": "4.0.0-canary.167",
3
+ "version": "4.0.0-canary.169",
4
4
  "type": "module",
5
5
  "license": "Apache-2.0",
6
6
  "sideEffects": false,
@@ -28,10 +28,10 @@
28
28
  "dependencies": {
29
29
  "swr": "^2.4.1",
30
30
  "throttleit": "2.1.0",
31
- "@ai-sdk/mcp": "2.0.0-canary.58",
32
- "@ai-sdk/provider": "4.0.0-canary.17",
33
- "@ai-sdk/provider-utils": "5.0.0-canary.45",
34
- "ai": "7.0.0-canary.164"
31
+ "@ai-sdk/mcp": "2.0.0-canary.59",
32
+ "@ai-sdk/provider": "4.0.0-canary.18",
33
+ "@ai-sdk/provider-utils": "5.0.0-canary.46",
34
+ "ai": "7.0.0-canary.166"
35
35
  },
36
36
  "devDependencies": {
37
37
  "@testing-library/jest-dom": "^6.9.1",
package/src/index.ts CHANGED
@@ -2,4 +2,5 @@ export * from './use-chat';
2
2
  export { Chat } from './chat.react';
3
3
  export * from './use-completion';
4
4
  export * from './use-object';
5
+ export * from './use-realtime';
5
6
  export * from './mcp-apps';
@@ -0,0 +1,252 @@
1
+ import {
2
+ Experimental_AbstractRealtimeSession as AbstractRealtimeSession,
3
+ type Experimental_RealtimeServerEvent as RealtimeServerEvent,
4
+ type Experimental_RealtimeSessionOptions as RealtimeSessionOptions,
5
+ type Experimental_RealtimeState as RealtimeState,
6
+ type Experimental_RealtimeStatus as RealtimeStatus,
7
+ type UIMessage,
8
+ } from 'ai';
9
+ import { useCallback, useEffect, useRef, useSyncExternalStore } from 'react';
10
+
11
+ type UseRealtimeOptions = RealtimeSessionOptions;
12
+
13
+ type RealtimeStateKey = keyof RealtimeState;
14
+ type RealtimeStoreKey = {
15
+ model: RealtimeSessionOptions['model'];
16
+ token: RealtimeSessionOptions['api']['token'];
17
+ sessionConfig: RealtimeSessionOptions['sessionConfig'];
18
+ sampleRate: RealtimeSessionOptions['sampleRate'];
19
+ maxEvents: RealtimeSessionOptions['maxEvents'];
20
+ };
21
+
22
+ function getRealtimeStoreKey(options: UseRealtimeOptions): RealtimeStoreKey {
23
+ return {
24
+ model: options.model,
25
+ token: options.api.token,
26
+ sessionConfig: options.sessionConfig,
27
+ sampleRate: options.sampleRate,
28
+ maxEvents: options.maxEvents,
29
+ };
30
+ }
31
+
32
+ function shouldCreateRealtimeStore(
33
+ currentKey: RealtimeStoreKey,
34
+ nextOptions: UseRealtimeOptions,
35
+ ): boolean {
36
+ return (
37
+ currentKey.model !== nextOptions.model ||
38
+ currentKey.token !== nextOptions.api.token ||
39
+ currentKey.sessionConfig !== nextOptions.sessionConfig ||
40
+ currentKey.sampleRate !== nextOptions.sampleRate ||
41
+ currentKey.maxEvents !== nextOptions.maxEvents
42
+ );
43
+ }
44
+
45
+ class RealtimeStore extends AbstractRealtimeSession {
46
+ protected state: RealtimeState = {
47
+ status: 'disconnected',
48
+ messages: [],
49
+ events: [],
50
+ isCapturing: false,
51
+ isPlaying: false,
52
+ };
53
+
54
+ private callbacks: { [K in RealtimeStateKey]: Set<() => void> } = {
55
+ status: new Set(),
56
+ messages: new Set(),
57
+ events: new Set(),
58
+ isCapturing: new Set(),
59
+ isPlaying: new Set(),
60
+ };
61
+
62
+ get status(): RealtimeStatus {
63
+ return this.state.status;
64
+ }
65
+
66
+ get messages(): UIMessage[] {
67
+ return this.state.messages;
68
+ }
69
+
70
+ get events(): RealtimeServerEvent[] {
71
+ return this.state.events;
72
+ }
73
+
74
+ get isCapturing(): boolean {
75
+ return this.state.isCapturing;
76
+ }
77
+
78
+ get isPlaying(): boolean {
79
+ return this.state.isPlaying;
80
+ }
81
+
82
+ subscribe(key: RealtimeStateKey, onChange: () => void): () => void {
83
+ this.callbacks[key].add(onChange);
84
+
85
+ return () => {
86
+ this.callbacks[key].delete(onChange);
87
+ };
88
+ }
89
+
90
+ protected setState<K extends RealtimeStateKey>(
91
+ key: K,
92
+ value: RealtimeState[K],
93
+ ): void {
94
+ this.state = { ...this.state, [key]: value };
95
+ this.callbacks[key].forEach(callback => callback());
96
+ }
97
+
98
+ protected pushMessage(message: UIMessage): void {
99
+ this.state = {
100
+ ...this.state,
101
+ messages: [...this.state.messages, message],
102
+ };
103
+ this.callbacks.messages.forEach(callback => callback());
104
+ }
105
+
106
+ protected updateMessages(
107
+ updater: (messages: UIMessage[]) => UIMessage[],
108
+ ): void {
109
+ this.state = {
110
+ ...this.state,
111
+ messages: updater(this.state.messages),
112
+ };
113
+ this.callbacks.messages.forEach(callback => callback());
114
+ }
115
+
116
+ protected pushEvent(event: RealtimeServerEvent): void {
117
+ const nextEvents = [...this.state.events, event];
118
+ this.state = {
119
+ ...this.state,
120
+ events:
121
+ nextEvents.length > this.maxEvents
122
+ ? nextEvents.slice(-this.maxEvents)
123
+ : nextEvents,
124
+ };
125
+ this.callbacks.events.forEach(callback => callback());
126
+ }
127
+ }
128
+
129
+ type UseRealtimeReturn = {
130
+ status: RealtimeStatus;
131
+ messages: UIMessage[];
132
+ events: RealtimeServerEvent[];
133
+ isCapturing: boolean;
134
+ isPlaying: boolean;
135
+
136
+ connect: () => Promise<void>;
137
+ disconnect: () => void;
138
+ addToolOutput: (callId: string, result: unknown) => void;
139
+ sendEvent: RealtimeStore['sendEvent'];
140
+ sendTextMessage: (text: string) => void;
141
+ sendAudio: (base64Audio: string) => void;
142
+ commitAudio: () => void;
143
+ clearAudioBuffer: () => void;
144
+ requestResponse: (options?: { modalities?: string[] }) => void;
145
+ cancelResponse: () => void;
146
+ startAudioCapture: (stream: MediaStream) => void;
147
+ stopAudioCapture: () => void;
148
+ stopPlayback: () => void;
149
+ };
150
+
151
+ function useRealtime(options: UseRealtimeOptions): UseRealtimeReturn {
152
+ const callbacksRef = useRef({
153
+ onToolCall: options.onToolCall,
154
+ onEvent: options.onEvent,
155
+ onError: options.onError,
156
+ });
157
+ callbacksRef.current = {
158
+ onToolCall: options.onToolCall,
159
+ onEvent: options.onEvent,
160
+ onError: options.onError,
161
+ };
162
+
163
+ const realtimeRef = useRef<{
164
+ store: RealtimeStore;
165
+ key: RealtimeStoreKey;
166
+ } | null>(null);
167
+
168
+ let realtimeEntry = realtimeRef.current;
169
+
170
+ if (
171
+ realtimeEntry == null ||
172
+ shouldCreateRealtimeStore(realtimeEntry.key, options)
173
+ ) {
174
+ realtimeEntry = {
175
+ store: new RealtimeStore({
176
+ ...options,
177
+ onToolCall: (...args) => callbacksRef.current.onToolCall?.(...args),
178
+ onEvent: (...args) => callbacksRef.current.onEvent?.(...args),
179
+ onError: (...args) => callbacksRef.current.onError?.(...args),
180
+ }),
181
+ key: getRealtimeStoreKey(options),
182
+ };
183
+ realtimeRef.current = realtimeEntry;
184
+ } else {
185
+ realtimeEntry.key = getRealtimeStoreKey(options);
186
+ }
187
+
188
+ const rt = realtimeEntry.store;
189
+
190
+ const status = useSyncExternalStore(
191
+ useCallback(cb => rt.subscribe('status', cb), [rt]),
192
+ () => rt.status,
193
+ () => rt.status,
194
+ );
195
+
196
+ const messages = useSyncExternalStore(
197
+ useCallback(cb => rt.subscribe('messages', cb), [rt]),
198
+ () => rt.messages,
199
+ () => rt.messages,
200
+ );
201
+
202
+ const events = useSyncExternalStore(
203
+ useCallback(cb => rt.subscribe('events', cb), [rt]),
204
+ () => rt.events,
205
+ () => rt.events,
206
+ );
207
+
208
+ const isCapturing = useSyncExternalStore(
209
+ useCallback(cb => rt.subscribe('isCapturing', cb), [rt]),
210
+ () => rt.isCapturing,
211
+ () => rt.isCapturing,
212
+ );
213
+
214
+ const isPlaying = useSyncExternalStore(
215
+ useCallback(cb => rt.subscribe('isPlaying', cb), [rt]),
216
+ () => rt.isPlaying,
217
+ () => rt.isPlaying,
218
+ );
219
+
220
+ useEffect(() => {
221
+ return () => rt.dispose();
222
+ }, [rt]);
223
+
224
+ return {
225
+ status,
226
+ messages,
227
+ events,
228
+ isCapturing,
229
+ isPlaying,
230
+ connect: rt.connect.bind(rt),
231
+ disconnect: rt.disconnect.bind(rt),
232
+ addToolOutput: rt.addToolOutput.bind(rt),
233
+ sendEvent: rt.sendEvent.bind(rt),
234
+ sendTextMessage: rt.sendTextMessage.bind(rt),
235
+ sendAudio: rt.sendAudio.bind(rt),
236
+ commitAudio: rt.commitAudio.bind(rt),
237
+ clearAudioBuffer: rt.clearAudioBuffer.bind(rt),
238
+ requestResponse: rt.requestResponse.bind(rt),
239
+ cancelResponse: rt.cancelResponse.bind(rt),
240
+ startAudioCapture: rt.startAudioCapture.bind(rt),
241
+ stopAudioCapture: rt.stopAudioCapture.bind(rt),
242
+ stopPlayback: rt.stopPlayback.bind(rt),
243
+ };
244
+ }
245
+
246
+ export const experimental_useRealtime = useRealtime;
247
+
248
+ export type {
249
+ RealtimeStatus as Experimental_RealtimeStatus,
250
+ UseRealtimeOptions as Experimental_UseRealtimeOptions,
251
+ UseRealtimeReturn as Experimental_UseRealtimeReturn,
252
+ };