open-mcp-app 0.1.3 → 0.1.4

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.
@@ -1,5 +1,5 @@
1
1
  // src/react/useHost.ts
2
- import { useSyncExternalStore, useEffect, useRef, useMemo } from "react";
2
+ import { useSyncExternalStore, useEffect as useEffect2, useRef as useRef2, useMemo, useState, useCallback } from "react";
3
3
 
4
4
  // src/core/base/Subscribable.ts
5
5
  var Subscribable = class {
@@ -278,6 +278,24 @@ var ChatGptAdapter = class _ChatGptAdapter {
278
278
  get isCreature() {
279
279
  return false;
280
280
  }
281
+ /**
282
+ * Experimental APIs for ChatGPT.
283
+ * Most are no-ops since ChatGPT doesn't support MCP Apps extensions.
284
+ */
285
+ get experimental() {
286
+ return {
287
+ sendNotification: (_method, _params) => {
288
+ },
289
+ setWidgetState: (state) => {
290
+ this.base.setWidgetState(state);
291
+ },
292
+ setTitle: (_title) => {
293
+ },
294
+ getCreatureStyles: () => {
295
+ return null;
296
+ }
297
+ };
298
+ }
281
299
  /**
282
300
  * Get host context - returns null for ChatGPT as it doesn't use MCP Apps protocol.
283
301
  */
@@ -293,19 +311,6 @@ var ChatGptAdapter = class _ChatGptAdapter {
293
311
  async callTool(toolName, args) {
294
312
  return this.base.callTool(toolName, args);
295
313
  }
296
- /**
297
- * Send notification - not supported on ChatGPT.
298
- */
299
- sendNotification(_method, _params) {
300
- }
301
- setWidgetState(state) {
302
- this.base.setWidgetState(state);
303
- }
304
- /**
305
- * Set pip/widget title - not supported on ChatGPT.
306
- */
307
- setTitle(_title) {
308
- }
309
314
  async requestDisplayMode(params) {
310
315
  return this.base.requestDisplayMode(params);
311
316
  }
@@ -460,6 +465,26 @@ var StandaloneAdapter = class _StandaloneAdapter {
460
465
  get isCreature() {
461
466
  return false;
462
467
  }
468
+ /**
469
+ * Experimental APIs for standalone mode.
470
+ * All methods are logged for development/debugging purposes.
471
+ */
472
+ get experimental() {
473
+ return {
474
+ sendNotification: (method, params) => {
475
+ console.debug(`[Standalone] experimental.sendNotification("${method}")`, params);
476
+ },
477
+ setWidgetState: (state) => {
478
+ this.base.setWidgetState(state);
479
+ },
480
+ setTitle: (title) => {
481
+ console.debug(`[Standalone] experimental.setTitle("${title}")`);
482
+ },
483
+ getCreatureStyles: () => {
484
+ return null;
485
+ }
486
+ };
487
+ }
463
488
  /**
464
489
  * Get host context - returns null for standalone mode.
465
490
  */
@@ -475,21 +500,6 @@ var StandaloneAdapter = class _StandaloneAdapter {
475
500
  async callTool(toolName, args) {
476
501
  return this.base.callTool(toolName, args);
477
502
  }
478
- /**
479
- * Send notification - logged in standalone mode.
480
- */
481
- sendNotification(method, params) {
482
- console.debug(`[Standalone] sendNotification("${method}")`, params);
483
- }
484
- setWidgetState(state) {
485
- this.base.setWidgetState(state);
486
- }
487
- /**
488
- * Set pip/widget title - logged in standalone mode.
489
- */
490
- setTitle(title) {
491
- console.debug(`[Standalone] setTitle("${title}")`);
492
- }
493
503
  async requestDisplayMode(params) {
494
504
  return this.base.requestDisplayMode(params);
495
505
  }
@@ -10156,14 +10166,29 @@ var UpgradingMcpAppsClient = class _UpgradingMcpAppsClient {
10156
10166
  return this.base.getState().environment;
10157
10167
  }
10158
10168
  // ============================================================================
10159
- // Creature-Specific Extensions (gracefully no-op when not in Creature)
10169
+ // Experimental APIs
10160
10170
  // ============================================================================
10161
10171
  /**
10162
- * Get Creature-specific styles if available.
10163
- * Returns null when not running in Creature.
10172
+ * Experimental APIs with dynamic Creature support.
10173
+ * Methods like setTitle will only work when isCreature is true.
10164
10174
  */
10165
- getCreatureStyles() {
10166
- return this.base.getCreatureStyles();
10175
+ get experimental() {
10176
+ return {
10177
+ sendNotification: (method, params) => {
10178
+ this.base.sendNotification(method, params);
10179
+ },
10180
+ setWidgetState: (state) => {
10181
+ this.base.setWidgetState(state);
10182
+ },
10183
+ setTitle: (title) => {
10184
+ if (this.isCreature) {
10185
+ this.base.sendNotification("ui/notifications/title-changed", { title });
10186
+ }
10187
+ },
10188
+ getCreatureStyles: () => {
10189
+ return this.base.getCreatureStyles();
10190
+ }
10191
+ };
10167
10192
  }
10168
10193
  // ============================================================================
10169
10194
  // UnifiedHostClient Implementation
@@ -10180,19 +10205,6 @@ var UpgradingMcpAppsClient = class _UpgradingMcpAppsClient {
10180
10205
  async callTool(toolName, args) {
10181
10206
  return this.base.callTool(toolName, args);
10182
10207
  }
10183
- sendNotification(method, params) {
10184
- this.base.sendNotification(method, params);
10185
- }
10186
- setWidgetState(state) {
10187
- this.base.setWidgetState(state);
10188
- }
10189
- /**
10190
- * Set pip/widget title.
10191
- * Sends a notification - hosts that support it will update the title.
10192
- */
10193
- setTitle(title) {
10194
- this.base.sendNotification("ui/notifications/title-changed", { title });
10195
- }
10196
10208
  async requestDisplayMode(params) {
10197
10209
  return this.base.requestDisplayMode(params);
10198
10210
  }
@@ -10262,6 +10274,25 @@ var McpAppsAdapter = class _McpAppsAdapter {
10262
10274
  get isCreature() {
10263
10275
  return false;
10264
10276
  }
10277
+ /**
10278
+ * Experimental APIs for non-spec extensions.
10279
+ * Base MCP Apps adapter provides minimal implementations - CreatureAdapter overrides.
10280
+ */
10281
+ get experimental() {
10282
+ return {
10283
+ sendNotification: (method, params) => {
10284
+ this.base.sendNotification(method, params);
10285
+ },
10286
+ setWidgetState: (state) => {
10287
+ this.base.setWidgetState(state);
10288
+ },
10289
+ setTitle: (_title) => {
10290
+ },
10291
+ getCreatureStyles: () => {
10292
+ return null;
10293
+ }
10294
+ };
10295
+ }
10265
10296
  /**
10266
10297
  * Get the host context received from the host.
10267
10298
  * Useful for checking host-specific capabilities.
@@ -10278,19 +10309,6 @@ var McpAppsAdapter = class _McpAppsAdapter {
10278
10309
  async callTool(toolName, args) {
10279
10310
  return this.base.callTool(toolName, args);
10280
10311
  }
10281
- sendNotification(method, params) {
10282
- this.base.sendNotification(method, params);
10283
- }
10284
- setWidgetState(state) {
10285
- this.base.setWidgetState(state);
10286
- }
10287
- /**
10288
- * Set pip/widget title.
10289
- * Sends a notification - hosts that support it will update the title.
10290
- */
10291
- setTitle(title) {
10292
- this.base.sendNotification("ui/notifications/title-changed", { title });
10293
- }
10294
10312
  async requestDisplayMode(params) {
10295
10313
  return this.base.requestDisplayMode(params);
10296
10314
  }
@@ -10388,11 +10406,25 @@ var CreatureAdapter = class _CreatureAdapter extends McpAppsAdapter {
10388
10406
  return this.base.isCreatureHost();
10389
10407
  }
10390
10408
  /**
10391
- * Get Creature-specific styles if available.
10392
- * Returns null when not running in Creature.
10409
+ * Experimental APIs with Creature-specific implementations.
10393
10410
  */
10394
- getCreatureStyles() {
10395
- return this.base.getCreatureStyles();
10411
+ get experimental() {
10412
+ return {
10413
+ sendNotification: (method, params) => {
10414
+ this.base.sendNotification(method, params);
10415
+ },
10416
+ setWidgetState: (state) => {
10417
+ this.base.setWidgetState(state);
10418
+ },
10419
+ setTitle: (title) => {
10420
+ if (this.isCreature) {
10421
+ this.base.sendNotification("ui/notifications/title-changed", { title });
10422
+ }
10423
+ },
10424
+ getCreatureStyles: () => {
10425
+ return this.base.getCreatureStyles();
10426
+ }
10427
+ };
10396
10428
  }
10397
10429
  };
10398
10430
 
@@ -10539,13 +10571,164 @@ async function createHostAsync(config) {
10539
10571
  });
10540
10572
  }
10541
10573
 
10542
- // src/react/useHost.ts
10543
- function useHost(config) {
10574
+ // src/react/HostContext.tsx
10575
+ import { createContext, useContext, useRef, useEffect } from "react";
10576
+ import { jsx } from "react/jsx-runtime";
10577
+ var HostContext = createContext(null);
10578
+ function useHostClient() {
10579
+ const client = useContext(HostContext);
10580
+ if (!client) {
10581
+ throw new Error(
10582
+ 'useHostClient must be used within a HostProvider. Wrap your app with <HostProvider name="..." version="...">.'
10583
+ );
10584
+ }
10585
+ return client;
10586
+ }
10587
+ function useHostClientOptional() {
10588
+ return useContext(HostContext);
10589
+ }
10590
+ function HostProvider({
10591
+ name,
10592
+ version,
10593
+ children,
10594
+ onToolInput,
10595
+ onThemeChange,
10596
+ onTeardown
10597
+ }) {
10544
10598
  const clientRef = useRef(null);
10545
10599
  if (!clientRef.current) {
10546
- clientRef.current = createHost({ name: config.name, version: config.version });
10600
+ clientRef.current = createHost({ name, version });
10547
10601
  }
10548
10602
  const client = clientRef.current;
10603
+ const callbacksRef = useRef({ onToolInput, onThemeChange, onTeardown });
10604
+ useEffect(() => {
10605
+ callbacksRef.current = { onToolInput, onThemeChange, onTeardown };
10606
+ });
10607
+ useEffect(() => {
10608
+ const unsubs = [];
10609
+ if (callbacksRef.current.onToolInput) {
10610
+ unsubs.push(
10611
+ client.on("tool-input", (args) => callbacksRef.current.onToolInput?.(args))
10612
+ );
10613
+ }
10614
+ unsubs.push(
10615
+ client.on("theme-change", (theme) => callbacksRef.current.onThemeChange?.(theme))
10616
+ );
10617
+ unsubs.push(
10618
+ client.on("teardown", () => callbacksRef.current.onTeardown?.())
10619
+ );
10620
+ client.connect();
10621
+ return () => {
10622
+ unsubs.forEach((unsub) => unsub());
10623
+ client.disconnect();
10624
+ };
10625
+ }, [client]);
10626
+ return /* @__PURE__ */ jsx(HostContext.Provider, { value: client, children });
10627
+ }
10628
+
10629
+ // src/react/useHost.ts
10630
+ var INITIAL_TOOL_STATE = {
10631
+ status: "idle",
10632
+ data: null,
10633
+ result: null,
10634
+ error: null,
10635
+ isError: false,
10636
+ text: null,
10637
+ title: null,
10638
+ instanceId: null
10639
+ };
10640
+ function extractResultMetadata(result) {
10641
+ const structured = result.structuredContent;
10642
+ let data = null;
10643
+ let title = null;
10644
+ let instanceId = null;
10645
+ if (structured) {
10646
+ const { title: resultTitle, instanceId: resultInstanceId, ...rest } = structured;
10647
+ data = rest;
10648
+ if (resultTitle) title = resultTitle;
10649
+ if (resultInstanceId) instanceId = resultInstanceId;
10650
+ }
10651
+ const text = result.content?.[0]?.text ?? null;
10652
+ return { data, title, instanceId, text };
10653
+ }
10654
+ function useHost(config) {
10655
+ const contextClient = useHostClientOptional();
10656
+ const useContext2 = !config && contextClient !== null;
10657
+ const clientRef = useRef2(null);
10658
+ if (!useContext2) {
10659
+ if (!config) {
10660
+ throw new Error(
10661
+ 'useHost() requires either a HostProvider wrapper or config argument. Either wrap your app with <HostProvider name="..." version="..."> or pass { name, version } to useHost().'
10662
+ );
10663
+ }
10664
+ if (!clientRef.current) {
10665
+ clientRef.current = createHost({ name: config.name, version: config.version });
10666
+ }
10667
+ }
10668
+ const client = useContext2 ? contextClient : clientRef.current;
10669
+ const [toolStates, setToolStates] = useState(
10670
+ () => /* @__PURE__ */ new Map()
10671
+ );
10672
+ const toolFunctionsRef = useRef2(/* @__PURE__ */ new Map());
10673
+ const updateToolState = useCallback(
10674
+ (toolName, newState) => {
10675
+ setToolStates((prev) => {
10676
+ const current = prev.get(toolName) ?? INITIAL_TOOL_STATE;
10677
+ const updated = { ...current, ...newState };
10678
+ const next = new Map(prev);
10679
+ next.set(toolName, updated);
10680
+ return next;
10681
+ });
10682
+ },
10683
+ []
10684
+ );
10685
+ const getOrCreateToolFunction = useCallback(
10686
+ (toolName) => {
10687
+ const existing = toolFunctionsRef.current.get(toolName);
10688
+ if (existing) {
10689
+ return existing;
10690
+ }
10691
+ const runFn = async (args = {}) => {
10692
+ updateToolState(toolName, {
10693
+ status: "loading",
10694
+ error: null
10695
+ });
10696
+ try {
10697
+ const result = await client.callTool(toolName, args);
10698
+ const { data, title, instanceId, text } = extractResultMetadata(result);
10699
+ updateToolState(toolName, {
10700
+ status: "success",
10701
+ data,
10702
+ result,
10703
+ error: null,
10704
+ isError: result.isError ?? false,
10705
+ text,
10706
+ title,
10707
+ instanceId
10708
+ });
10709
+ return result;
10710
+ } catch (err) {
10711
+ updateToolState(toolName, {
10712
+ status: "error",
10713
+ error: err,
10714
+ isError: true
10715
+ });
10716
+ throw err;
10717
+ }
10718
+ };
10719
+ toolFunctionsRef.current.set(toolName, runFn);
10720
+ return runFn;
10721
+ },
10722
+ [client, updateToolState]
10723
+ );
10724
+ const callTool = useCallback(
10725
+ (toolName) => {
10726
+ const runFn = getOrCreateToolFunction(toolName);
10727
+ const currentState = toolStates.get(toolName) ?? INITIAL_TOOL_STATE;
10728
+ return [runFn, currentState];
10729
+ },
10730
+ [getOrCreateToolFunction, toolStates]
10731
+ );
10549
10732
  const log = useMemo(() => {
10550
10733
  const logFn = (message, data) => {
10551
10734
  client.log("info", message, data);
@@ -10567,13 +10750,16 @@ function useHost(config) {
10567
10750
  };
10568
10751
  return logFn;
10569
10752
  }, [client]);
10570
- const boundMethods = useMemo(
10753
+ const requestDisplayMode = useMemo(
10754
+ () => client.requestDisplayMode.bind(client),
10755
+ [client]
10756
+ );
10757
+ const experimental = useMemo(
10571
10758
  () => ({
10572
- callTool: client.callTool.bind(client),
10573
- sendNotification: client.sendNotification.bind(client),
10574
- setWidgetState: client.setWidgetState.bind(client),
10575
- setTitle: client.setTitle.bind(client),
10576
- requestDisplayMode: client.requestDisplayMode.bind(client)
10759
+ sendNotification: client.experimental.sendNotification.bind(client.experimental),
10760
+ setWidgetState: client.experimental.setWidgetState.bind(client.experimental),
10761
+ setTitle: client.experimental.setTitle.bind(client.experimental),
10762
+ getCreatureStyles: client.experimental.getCreatureStyles.bind(client.experimental)
10577
10763
  }),
10578
10764
  [client]
10579
10765
  );
@@ -10582,23 +10768,33 @@ function useHost(config) {
10582
10768
  () => client.getState(),
10583
10769
  () => client.getState()
10584
10770
  );
10585
- const callbacksRef = useRef({
10586
- onToolInput: config.onToolInput,
10587
- onToolResult: config.onToolResult,
10588
- onThemeChange: config.onThemeChange,
10589
- onTeardown: config.onTeardown,
10590
- onWidgetStateChange: config.onWidgetStateChange
10771
+ const experimental_widgetState = useCallback(
10772
+ () => {
10773
+ const currentState = state.widgetState;
10774
+ const setState = (newState) => {
10775
+ client.experimental.setWidgetState(newState);
10776
+ };
10777
+ return [currentState, setState];
10778
+ },
10779
+ [state.widgetState, client]
10780
+ );
10781
+ const callbacksRef = useRef2({
10782
+ onToolInput: config?.onToolInput,
10783
+ onToolResult: config?.onToolResult,
10784
+ onThemeChange: config?.onThemeChange,
10785
+ onTeardown: config?.onTeardown,
10786
+ onWidgetStateChange: config?.onWidgetStateChange
10591
10787
  });
10592
- useEffect(() => {
10788
+ useEffect2(() => {
10593
10789
  callbacksRef.current = {
10594
- onToolInput: config.onToolInput,
10595
- onToolResult: config.onToolResult,
10596
- onThemeChange: config.onThemeChange,
10597
- onTeardown: config.onTeardown,
10598
- onWidgetStateChange: config.onWidgetStateChange
10790
+ onToolInput: config?.onToolInput,
10791
+ onToolResult: config?.onToolResult,
10792
+ onThemeChange: config?.onThemeChange,
10793
+ onTeardown: config?.onTeardown,
10794
+ onWidgetStateChange: config?.onWidgetStateChange
10599
10795
  };
10600
10796
  });
10601
- useEffect(() => {
10797
+ useEffect2(() => {
10602
10798
  const unsubs = [];
10603
10799
  unsubs.push(
10604
10800
  client.on("tool-input", (args) => callbacksRef.current.onToolInput?.(args))
@@ -10618,38 +10814,42 @@ function useHost(config) {
10618
10814
  (widgetState) => callbacksRef.current.onWidgetStateChange?.(widgetState)
10619
10815
  )
10620
10816
  );
10621
- client.connect();
10817
+ if (!useContext2) {
10818
+ client.connect();
10819
+ }
10622
10820
  return () => {
10623
10821
  unsubs.forEach((unsub) => unsub());
10624
- client.disconnect();
10822
+ if (!useContext2) {
10823
+ client.disconnect();
10824
+ }
10625
10825
  };
10626
- }, [client]);
10826
+ }, [client, useContext2]);
10627
10827
  return {
10628
10828
  isReady: state.isReady,
10629
10829
  environment: state.environment,
10630
10830
  widgetState: state.widgetState,
10631
- callTool: boundMethods.callTool,
10632
- sendNotification: boundMethods.sendNotification,
10633
- setWidgetState: boundMethods.setWidgetState,
10634
- setTitle: boundMethods.setTitle,
10635
- requestDisplayMode: boundMethods.requestDisplayMode,
10831
+ callTool,
10832
+ requestDisplayMode,
10636
10833
  log,
10637
10834
  // Host detection properties (may change after connection for MCP Apps)
10638
10835
  adapterKind: client.adapterKind,
10639
10836
  isCreature: client.isCreature,
10640
- hostContext: client.getHostContext()
10837
+ hostContext: client.getHostContext(),
10838
+ // Experimental APIs (non-spec extensions)
10839
+ experimental,
10840
+ experimental_widgetState
10641
10841
  };
10642
10842
  }
10643
10843
 
10644
10844
  // src/react/useToolResult.ts
10645
- import { useState as useState2, useCallback } from "react";
10845
+ import { useState as useState2, useCallback as useCallback2 } from "react";
10646
10846
  function useToolResult() {
10647
10847
  const [data, setData] = useState2(null);
10648
10848
  const [instanceId, setInstanceId] = useState2(null);
10649
10849
  const [title, setTitle] = useState2(null);
10650
10850
  const [isError, setIsError] = useState2(false);
10651
10851
  const [text, setText] = useState2(null);
10652
- const onToolResult = useCallback((result) => {
10852
+ const onToolResult = useCallback2((result) => {
10653
10853
  const structured = result.structuredContent;
10654
10854
  if (structured) {
10655
10855
  const { title: resultTitle, instanceId: resultInstanceId, ...rest } = structured;
@@ -10666,7 +10866,7 @@ function useToolResult() {
10666
10866
  setText(result.content[0].text);
10667
10867
  }
10668
10868
  }, []);
10669
- const reset = useCallback(() => {
10869
+ const reset = useCallback2(() => {
10670
10870
  setData(null);
10671
10871
  setInstanceId(null);
10672
10872
  setTitle(null);
@@ -10685,23 +10885,23 @@ function useToolResult() {
10685
10885
  }
10686
10886
 
10687
10887
  // src/react/useWebSocket.ts
10688
- import { useEffect as useEffect2, useRef as useRef2, useMemo as useMemo2, useCallback as useCallback2, useSyncExternalStore as useSyncExternalStore2 } from "react";
10888
+ import { useEffect as useEffect3, useRef as useRef3, useMemo as useMemo2, useCallback as useCallback3, useSyncExternalStore as useSyncExternalStore2 } from "react";
10689
10889
  function useWebSocket(url, config = {}) {
10690
10890
  const { onMessage, enabled = true } = config;
10691
- const onMessageRef = useRef2(onMessage);
10891
+ const onMessageRef = useRef3(onMessage);
10692
10892
  onMessageRef.current = onMessage;
10693
- const stateRef = useRef2({ status: "disconnected", error: void 0 });
10694
- const listenersRef = useRef2(/* @__PURE__ */ new Set());
10695
- const clientRef = useRef2(null);
10696
- const subscribe = useCallback2((listener) => {
10893
+ const stateRef = useRef3({ status: "disconnected", error: void 0 });
10894
+ const listenersRef = useRef3(/* @__PURE__ */ new Set());
10895
+ const clientRef = useRef3(null);
10896
+ const subscribe = useCallback3((listener) => {
10697
10897
  listenersRef.current.add(listener);
10698
10898
  return () => {
10699
10899
  listenersRef.current.delete(listener);
10700
10900
  };
10701
10901
  }, []);
10702
- const getSnapshot = useCallback2(() => stateRef.current, []);
10902
+ const getSnapshot = useCallback3(() => stateRef.current, []);
10703
10903
  const state = useSyncExternalStore2(subscribe, getSnapshot, getSnapshot);
10704
- useEffect2(() => {
10904
+ useEffect3(() => {
10705
10905
  if (!url || !enabled) {
10706
10906
  if (clientRef.current) {
10707
10907
  clientRef.current.disconnect();
@@ -10738,8 +10938,8 @@ function useWebSocket(url, config = {}) {
10738
10938
  }
10739
10939
 
10740
10940
  // src/react/CreatureIcon.tsx
10741
- import { useState as useState3, useEffect as useEffect3, useRef as useRef3 } from "react";
10742
- import { Fragment, jsx, jsxs } from "react/jsx-runtime";
10941
+ import { useState as useState3, useEffect as useEffect4, useRef as useRef4 } from "react";
10942
+ import { Fragment, jsx as jsx2, jsxs } from "react/jsx-runtime";
10743
10943
  function CreatureIcon({
10744
10944
  isDarkMode,
10745
10945
  showEyes = true,
@@ -10750,8 +10950,8 @@ function CreatureIcon({
10750
10950
  }) {
10751
10951
  const fillColor = isDarkMode ? "#F8F7F6" : "#0D0D0C";
10752
10952
  const [isBlinking, setIsBlinking] = useState3(false);
10753
- const timeoutRef = useRef3(null);
10754
- useEffect3(() => {
10953
+ const timeoutRef = useRef4(null);
10954
+ useEffect4(() => {
10755
10955
  if (!enableBlink || !showEyes) {
10756
10956
  return;
10757
10957
  }
@@ -10782,7 +10982,7 @@ function CreatureIcon({
10782
10982
  xmlns: "http://www.w3.org/2000/svg",
10783
10983
  className,
10784
10984
  children: [
10785
- /* @__PURE__ */ jsx(
10985
+ /* @__PURE__ */ jsx2(
10786
10986
  "path",
10787
10987
  {
10788
10988
  fillRule: "evenodd",
@@ -10792,7 +10992,7 @@ function CreatureIcon({
10792
10992
  }
10793
10993
  ),
10794
10994
  showEyes && /* @__PURE__ */ jsxs(Fragment, { children: [
10795
- /* @__PURE__ */ jsx(
10995
+ /* @__PURE__ */ jsx2(
10796
10996
  "g",
10797
10997
  {
10798
10998
  style: {
@@ -10800,7 +11000,7 @@ function CreatureIcon({
10800
11000
  transform: isBlinking ? "scaleY(0.1)" : "scaleY(1)",
10801
11001
  transition: "transform 0.1s ease-out"
10802
11002
  },
10803
- children: /* @__PURE__ */ jsx(
11003
+ children: /* @__PURE__ */ jsx2(
10804
11004
  "path",
10805
11005
  {
10806
11006
  d: "M65.6051 34.48C66.4951 32.97 66.6051 31.3799 65.8451 30.9299C65.0851 30.4899 63.7451 31.3499 62.8551 32.8699C61.9651 34.3799 61.8551 35.97 62.6151 36.42C63.3751 36.86 64.7151 36 65.6051 34.48Z",
@@ -10809,7 +11009,7 @@ function CreatureIcon({
10809
11009
  )
10810
11010
  }
10811
11011
  ),
10812
- /* @__PURE__ */ jsx(
11012
+ /* @__PURE__ */ jsx2(
10813
11013
  "g",
10814
11014
  {
10815
11015
  style: {
@@ -10817,7 +11017,7 @@ function CreatureIcon({
10817
11017
  transform: isBlinking ? "scaleY(0.1)" : "scaleY(1)",
10818
11018
  transition: "transform 0.1s ease-out"
10819
11019
  },
10820
- children: /* @__PURE__ */ jsx(
11020
+ children: /* @__PURE__ */ jsx2(
10821
11021
  "path",
10822
11022
  {
10823
11023
  d: "M71.7651 37.0999C72.6951 35.1499 72.6551 33.1899 71.6751 32.73C70.6951 32.27 69.1551 33.4799 68.2351 35.4299C67.3051 37.3799 67.3451 39.3399 68.3251 39.7999C69.3051 40.2599 70.8451 39.0499 71.7651 37.0999Z",
@@ -10831,10 +11031,50 @@ function CreatureIcon({
10831
11031
  }
10832
11032
  );
10833
11033
  }
11034
+
11035
+ // src/react/experimental.ts
11036
+ import { useState as useState4, useEffect as useEffect5, useCallback as useCallback4, useSyncExternalStore as useSyncExternalStore3 } from "react";
11037
+ function experimental_useWidgetState() {
11038
+ const client = useHostClient();
11039
+ const state = useSyncExternalStore3(
11040
+ (onStoreChange) => client.subscribe(onStoreChange),
11041
+ () => client.getState().widgetState,
11042
+ () => client.getState().widgetState
11043
+ );
11044
+ const setState = useCallback4(
11045
+ (newState) => {
11046
+ client.experimental.setWidgetState(newState);
11047
+ },
11048
+ [client]
11049
+ );
11050
+ return [state, setState];
11051
+ }
11052
+ function experimental_useTitle() {
11053
+ const client = useHostClient();
11054
+ const setTitle = useCallback4(
11055
+ (title) => {
11056
+ client.experimental.setTitle(title);
11057
+ },
11058
+ [client]
11059
+ );
11060
+ return setTitle;
11061
+ }
11062
+ function experimental_useCreatureStyles() {
11063
+ const client = useHostClient();
11064
+ const [styles, setStyles] = useState4(() => client.experimental.getCreatureStyles());
11065
+ useEffect5(() => {
11066
+ const unsub = client.on("theme-change", () => {
11067
+ setStyles(client.experimental.getCreatureStyles());
11068
+ });
11069
+ return unsub;
11070
+ }, [client]);
11071
+ return styles;
11072
+ }
10834
11073
  export {
10835
11074
  ChatGptAdapter,
10836
11075
  CreatureAdapter,
10837
11076
  CreatureIcon,
11077
+ HostProvider,
10838
11078
  KNOWN_HOSTS,
10839
11079
  McpAppsAdapter,
10840
11080
  StandaloneAdapter,
@@ -10846,11 +11086,16 @@ export {
10846
11086
  createHostAsync,
10847
11087
  createWebSocket,
10848
11088
  detectEnvironment,
11089
+ experimental_useCreatureStyles,
11090
+ experimental_useTitle,
11091
+ experimental_useWidgetState,
10849
11092
  VU as getDocumentTheme,
10850
11093
  getHostIdentity,
10851
11094
  isHost,
10852
11095
  parseHostUserAgent,
10853
11096
  useHost,
11097
+ useHostClient,
11098
+ useHostClientOptional,
10854
11099
  useToolResult,
10855
11100
  useWebSocket
10856
11101
  };