skybridge 0.0.0-dev.ca7a7e7 → 0.0.0-dev.cbadf52

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (62) hide show
  1. package/dist/src/web/bridges/apps-sdk-adapter.d.ts +13 -2
  2. package/dist/src/web/bridges/apps-sdk-adapter.js +32 -3
  3. package/dist/src/web/bridges/apps-sdk-adapter.js.map +1 -1
  4. package/dist/src/web/bridges/apps-sdk-bridge.d.ts +4 -2
  5. package/dist/src/web/bridges/apps-sdk-bridge.js +19 -14
  6. package/dist/src/web/bridges/apps-sdk-bridge.js.map +1 -1
  7. package/dist/src/web/bridges/get-bridge-method.d.ts +2 -0
  8. package/dist/src/web/bridges/get-bridge-method.js +9 -0
  9. package/dist/src/web/bridges/get-bridge-method.js.map +1 -0
  10. package/dist/src/web/bridges/hooks/use-bridge.js +4 -50
  11. package/dist/src/web/bridges/hooks/use-bridge.js.map +1 -1
  12. package/dist/src/web/bridges/hooks/use-mcp-app-bridge.d.ts +3 -2
  13. package/dist/src/web/bridges/hooks/use-mcp-app-bridge.js.map +1 -1
  14. package/dist/src/web/bridges/hooks/use-mcp-app-bridge.test.js +10 -26
  15. package/dist/src/web/bridges/hooks/use-mcp-app-bridge.test.js.map +1 -1
  16. package/dist/src/web/bridges/index.d.ts +1 -1
  17. package/dist/src/web/bridges/index.js +1 -1
  18. package/dist/src/web/bridges/index.js.map +1 -1
  19. package/dist/src/web/bridges/mcp-app-adapter.d.ts +16 -2
  20. package/dist/src/web/bridges/mcp-app-adapter.js +108 -9
  21. package/dist/src/web/bridges/mcp-app-adapter.js.map +1 -1
  22. package/dist/src/web/bridges/mcp-app-bridge.d.ts +15 -6
  23. package/dist/src/web/bridges/mcp-app-bridge.js +58 -26
  24. package/dist/src/web/bridges/mcp-app-bridge.js.map +1 -1
  25. package/dist/src/web/bridges/types.d.ts +40 -3
  26. package/dist/src/web/data-llm.js +4 -2
  27. package/dist/src/web/data-llm.js.map +1 -1
  28. package/dist/src/web/generate-helpers.test-d.js +4 -1
  29. package/dist/src/web/generate-helpers.test-d.js.map +1 -1
  30. package/dist/src/web/hooks/test/utils.d.ts +11 -0
  31. package/dist/src/web/hooks/test/utils.js +48 -0
  32. package/dist/src/web/hooks/test/utils.js.map +1 -0
  33. package/dist/src/web/hooks/use-call-tool.js +12 -4
  34. package/dist/src/web/hooks/use-call-tool.js.map +1 -1
  35. package/dist/src/web/hooks/use-call-tool.test.js +26 -0
  36. package/dist/src/web/hooks/use-call-tool.test.js.map +1 -1
  37. package/dist/src/web/hooks/use-display-mode.d.ts +1 -2
  38. package/dist/src/web/hooks/use-display-mode.js +2 -4
  39. package/dist/src/web/hooks/use-display-mode.js.map +1 -1
  40. package/dist/src/web/hooks/use-layout.test.js +84 -38
  41. package/dist/src/web/hooks/use-layout.test.js.map +1 -1
  42. package/dist/src/web/hooks/use-send-follow-up-message.js +2 -8
  43. package/dist/src/web/hooks/use-send-follow-up-message.js.map +1 -1
  44. package/dist/src/web/hooks/use-tool-info.d.ts +12 -1
  45. package/dist/src/web/hooks/use-tool-info.js +15 -9
  46. package/dist/src/web/hooks/use-tool-info.js.map +1 -1
  47. package/dist/src/web/hooks/use-tool-info.test-d.js +40 -4
  48. package/dist/src/web/hooks/use-tool-info.test-d.js.map +1 -1
  49. package/dist/src/web/hooks/use-tool-info.test.js +118 -47
  50. package/dist/src/web/hooks/use-tool-info.test.js.map +1 -1
  51. package/dist/src/web/hooks/use-user.js +2 -2
  52. package/dist/src/web/hooks/use-user.js.map +1 -1
  53. package/dist/src/web/hooks/use-user.test.js +84 -34
  54. package/dist/src/web/hooks/use-user.test.js.map +1 -1
  55. package/dist/src/web/plugin/transform-data-llm.js +6 -3
  56. package/dist/src/web/plugin/transform-data-llm.js.map +1 -1
  57. package/dist/src/web/types.d.ts +2 -4
  58. package/dist/src/web/types.js.map +1 -1
  59. package/package.json +2 -1
  60. package/dist/src/web/bridges/get-bridge-methods.d.ts +0 -2
  61. package/dist/src/web/bridges/get-bridge-methods.js +0 -8
  62. package/dist/src/web/bridges/get-bridge-methods.js.map +0 -1
@@ -1,2 +1,13 @@
1
- import type { Methods } from "./types.js";
2
- export declare const requestDisplayMode: Methods["requestDisplayMode"];
1
+ import type { Adapter, BridgeInterface, CallToolResponse, DisplayMode, ExternalStore, Methods } from "./types.js";
2
+ export declare class AppsSdkAdapter implements Adapter {
3
+ private static instance;
4
+ static getInstance(): AppsSdkAdapter;
5
+ static resetInstance(): void;
6
+ getExternalStore<K extends keyof BridgeInterface>(key: K): ExternalStore<K>;
7
+ callTool: <ToolArgs extends Record<string, unknown> | null = null, ToolResponse extends CallToolResponse = CallToolResponse>(name: string, args: ToolArgs) => Promise<ToolResponse>;
8
+ requestDisplayMode: (mode: DisplayMode) => Promise<{
9
+ mode: DisplayMode;
10
+ }>;
11
+ sendFollowUpMessage: (prompt: string) => Promise<void>;
12
+ getMethod<K extends keyof Methods>(key: K): this[K];
13
+ }
@@ -1,4 +1,33 @@
1
- export const requestDisplayMode = ({ mode }) => {
2
- return window.openai.requestDisplayMode({ mode });
3
- };
1
+ import { AppsSdkBridge } from "./apps-sdk-bridge.js";
2
+ export class AppsSdkAdapter {
3
+ static instance = null;
4
+ static getInstance() {
5
+ if (!AppsSdkAdapter.instance) {
6
+ AppsSdkAdapter.instance = new AppsSdkAdapter();
7
+ }
8
+ return AppsSdkAdapter.instance;
9
+ }
10
+ static resetInstance() {
11
+ AppsSdkAdapter.instance = null;
12
+ }
13
+ getExternalStore(key) {
14
+ const bridge = AppsSdkBridge.getInstance();
15
+ return {
16
+ subscribe: bridge.subscribe(key),
17
+ getSnapshot: () => bridge.getSnapshot(key),
18
+ };
19
+ }
20
+ callTool = async (name, args) => {
21
+ return window.openai.callTool(name, args);
22
+ };
23
+ requestDisplayMode = (mode) => {
24
+ return window.openai.requestDisplayMode({ mode });
25
+ };
26
+ sendFollowUpMessage = (prompt) => {
27
+ return window.openai.sendFollowUpMessage({ prompt });
28
+ };
29
+ getMethod(key) {
30
+ return this[key];
31
+ }
32
+ }
4
33
  //# sourceMappingURL=apps-sdk-adapter.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"apps-sdk-adapter.js","sourceRoot":"","sources":["../../../../src/web/bridges/apps-sdk-adapter.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,MAAM,kBAAkB,GAAkC,CAAC,EAAE,IAAI,EAAE,EAAE,EAAE;IAC5E,OAAO,MAAM,CAAC,MAAM,CAAC,kBAAkB,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC;AACpD,CAAC,CAAC"}
1
+ {"version":3,"file":"apps-sdk-adapter.js","sourceRoot":"","sources":["../../../../src/web/bridges/apps-sdk-adapter.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAUrD,MAAM,OAAO,cAAc;IACjB,MAAM,CAAC,QAAQ,GAA0B,IAAI,CAAC;IAE/C,MAAM,CAAC,WAAW;QACvB,IAAI,CAAC,cAAc,CAAC,QAAQ,EAAE,CAAC;YAC7B,cAAc,CAAC,QAAQ,GAAG,IAAI,cAAc,EAAE,CAAC;QACjD,CAAC;QACD,OAAO,cAAc,CAAC,QAAQ,CAAC;IACjC,CAAC;IAEM,MAAM,CAAC,aAAa;QACzB,cAAc,CAAC,QAAQ,GAAG,IAAI,CAAC;IACjC,CAAC;IAEM,gBAAgB,CACrB,GAAM;QAEN,MAAM,MAAM,GAAG,aAAa,CAAC,WAAW,EAAE,CAAC;QAC3C,OAAO;YACL,SAAS,EAAE,MAAM,CAAC,SAAS,CAAC,GAAG,CAAC;YAChC,WAAW,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,WAAW,CAAC,GAAG,CAAC;SAC3C,CAAC;IACJ,CAAC;IAEM,QAAQ,GAAG,KAAK,EAIrB,IAAY,EACZ,IAAc,EACS,EAAE;QACzB,OAAO,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAyB,IAAI,EAAE,IAAI,CAAC,CAAC;IACpE,CAAC,CAAC;IAEK,kBAAkB,GAAG,CAC1B,IAAiB,EACe,EAAE;QAClC,OAAO,MAAM,CAAC,MAAM,CAAC,kBAAkB,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC;IACpD,CAAC,CAAC;IAEK,mBAAmB,GAAG,CAAC,MAAc,EAAiB,EAAE;QAC7D,OAAO,MAAM,CAAC,MAAM,CAAC,mBAAmB,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC;IACvD,CAAC,CAAC;IAEK,SAAS,CAA0B,GAAM;QAC9C,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC;IACnB,CAAC"}
@@ -1,8 +1,10 @@
1
1
  import { type OpenAiProperties } from "../types.js";
2
- export declare class AppsSdkBridge {
2
+ import type { Bridge, Subscribe } from "./types.js";
3
+ export declare class AppsSdkBridge implements Bridge<OpenAiProperties> {
3
4
  private static instance;
4
5
  static getInstance(): AppsSdkBridge;
5
6
  static resetInstance(): void;
6
- subscribe: (key: keyof OpenAiProperties) => (onChange: () => void) => () => void;
7
+ subscribe(key: keyof OpenAiProperties): Subscribe;
8
+ subscribe(keys: readonly (keyof OpenAiProperties)[]): Subscribe;
7
9
  getSnapshot: <K extends keyof OpenAiProperties>(key: K) => (import("../types.js").OpenAiMethods<import("../types.js").UnknownObject> & OpenAiProperties<Record<never, unknown>, import("../types.js").UnknownObject, import("../types.js").UnknownObject, import("../types.js").UnknownObject>)[K];
8
10
  }
@@ -16,21 +16,26 @@ export class AppsSdkBridge {
16
16
  AppsSdkBridge.instance = null;
17
17
  }
18
18
  }
19
- subscribe = (key) => (onChange) => {
20
- const handleSetGlobal = (event) => {
21
- const value = event.detail.globals[key];
22
- if (value === undefined) {
23
- return;
24
- }
25
- onChange();
19
+ subscribe(keyOrKeys) {
20
+ const keys = Array.isArray(keyOrKeys)
21
+ ? keyOrKeys
22
+ : [keyOrKeys];
23
+ return (onChange) => {
24
+ const handleSetGlobal = (event) => {
25
+ const hasRelevantChange = keys.some((key) => event.detail.globals[key] !== undefined);
26
+ if (!hasRelevantChange) {
27
+ return;
28
+ }
29
+ onChange();
30
+ };
31
+ window.addEventListener(SET_GLOBALS_EVENT_TYPE, handleSetGlobal, {
32
+ passive: true,
33
+ });
34
+ return () => {
35
+ window.removeEventListener(SET_GLOBALS_EVENT_TYPE, handleSetGlobal);
36
+ };
26
37
  };
27
- window.addEventListener(SET_GLOBALS_EVENT_TYPE, handleSetGlobal, {
28
- passive: true,
29
- });
30
- return () => {
31
- window.removeEventListener(SET_GLOBALS_EVENT_TYPE, handleSetGlobal);
32
- };
33
- };
38
+ }
34
39
  getSnapshot = (key) => {
35
40
  if (window.openai === undefined) {
36
41
  throw new Error(`window.openai is not available. Make sure you're calling the hook requiring ${key} within the OpenAI iFrame skybridge runtime.`);
@@ -1 +1 @@
1
- {"version":3,"file":"apps-sdk-bridge.js","sourceRoot":"","sources":["../../../../src/web/bridges/apps-sdk-bridge.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,sBAAsB,GAEvB,MAAM,aAAa,CAAC;AAErB,MAAM,OAAO,aAAa;IAChB,MAAM,CAAC,QAAQ,GAAyB,IAAI,CAAC;IAE9C,MAAM,CAAC,WAAW;QACvB,IACE,MAAM,CAAC,SAAS,CAAC,QAAQ,KAAK,UAAU;YACxC,MAAM,CAAC,MAAM,KAAK,SAAS,EAC3B,CAAC;YACD,MAAM,IAAI,KAAK,CACb,0DAA0D,CAC3D,CAAC;QACJ,CAAC;QACD,IAAI,aAAa,CAAC,QAAQ,KAAK,IAAI,EAAE,CAAC;YACpC,aAAa,CAAC,QAAQ,GAAG,IAAI,aAAa,EAAE,CAAC;QAC/C,CAAC;QACD,OAAO,aAAa,CAAC,QAAQ,CAAC;IAChC,CAAC;IAEM,MAAM,CAAC,aAAa;QACzB,IAAI,aAAa,CAAC,QAAQ,EAAE,CAAC;YAC3B,aAAa,CAAC,QAAQ,GAAG,IAAI,CAAC;QAChC,CAAC;IACH,CAAC;IAEM,SAAS,GACd,CAAC,GAA2B,EAAE,EAAE,CAAC,CAAC,QAAoB,EAAE,EAAE;QACxD,MAAM,eAAe,GAAG,CAAC,KAAsB,EAAE,EAAE;YACjD,MAAM,KAAK,GAAG,KAAK,CAAC,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;YACxC,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;gBACxB,OAAO;YACT,CAAC;YAED,QAAQ,EAAE,CAAC;QACb,CAAC,CAAC;QAEF,MAAM,CAAC,gBAAgB,CAAC,sBAAsB,EAAE,eAAe,EAAE;YAC/D,OAAO,EAAE,IAAI;SACd,CAAC,CAAC;QAEH,OAAO,GAAG,EAAE;YACV,MAAM,CAAC,mBAAmB,CAAC,sBAAsB,EAAE,eAAe,CAAC,CAAC;QACtE,CAAC,CAAC;IACJ,CAAC,CAAC;IACG,WAAW,GAAG,CAAmC,GAAM,EAAE,EAAE;QAChE,IAAI,MAAM,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;YAChC,MAAM,IAAI,KAAK,CACb,+EAA+E,GAAG,8CAA8C,CACjI,CAAC;QACJ,CAAC;QAED,OAAO,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;IAC5B,CAAC,CAAC"}
1
+ {"version":3,"file":"apps-sdk-bridge.js","sourceRoot":"","sources":["../../../../src/web/bridges/apps-sdk-bridge.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,sBAAsB,GAEvB,MAAM,aAAa,CAAC;AAGrB,MAAM,OAAO,aAAa;IAChB,MAAM,CAAC,QAAQ,GAAyB,IAAI,CAAC;IAE9C,MAAM,CAAC,WAAW;QACvB,IACE,MAAM,CAAC,SAAS,CAAC,QAAQ,KAAK,UAAU;YACxC,MAAM,CAAC,MAAM,KAAK,SAAS,EAC3B,CAAC;YACD,MAAM,IAAI,KAAK,CACb,0DAA0D,CAC3D,CAAC;QACJ,CAAC;QACD,IAAI,aAAa,CAAC,QAAQ,KAAK,IAAI,EAAE,CAAC;YACpC,aAAa,CAAC,QAAQ,GAAG,IAAI,aAAa,EAAE,CAAC;QAC/C,CAAC;QACD,OAAO,aAAa,CAAC,QAAQ,CAAC;IAChC,CAAC;IAEM,MAAM,CAAC,aAAa;QACzB,IAAI,aAAa,CAAC,QAAQ,EAAE,CAAC;YAC3B,aAAa,CAAC,QAAQ,GAAG,IAAI,CAAC;QAChC,CAAC;IACH,CAAC;IAIM,SAAS,CACd,SAAuE;QAEvE,MAAM,IAAI,GAAwC,KAAK,CAAC,OAAO,CAAC,SAAS,CAAC;YACxE,CAAC,CAAC,SAAS;YACX,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;QAChB,OAAO,CAAC,QAAoB,EAAE,EAAE;YAC9B,MAAM,eAAe,GAAG,CAAC,KAAsB,EAAE,EAAE;gBACjD,MAAM,iBAAiB,GAAG,IAAI,CAAC,IAAI,CACjC,CAAC,GAAG,EAAE,EAAE,CAAC,KAAK,CAAC,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK,SAAS,CACjD,CAAC;gBACF,IAAI,CAAC,iBAAiB,EAAE,CAAC;oBACvB,OAAO;gBACT,CAAC;gBACD,QAAQ,EAAE,CAAC;YACb,CAAC,CAAC;YAEF,MAAM,CAAC,gBAAgB,CAAC,sBAAsB,EAAE,eAAe,EAAE;gBAC/D,OAAO,EAAE,IAAI;aACd,CAAC,CAAC;YAEH,OAAO,GAAG,EAAE;gBACV,MAAM,CAAC,mBAAmB,CAAC,sBAAsB,EAAE,eAAe,CAAC,CAAC;YACtE,CAAC,CAAC;QACJ,CAAC,CAAC;IACJ,CAAC;IAEM,WAAW,GAAG,CAAmC,GAAM,EAAE,EAAE;QAChE,IAAI,MAAM,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;YAChC,MAAM,IAAI,KAAK,CACb,+EAA+E,GAAG,8CAA8C,CACjI,CAAC;QACJ,CAAC;QAED,OAAO,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;IAC5B,CAAC,CAAC"}
@@ -0,0 +1,2 @@
1
+ import type { Methods } from "./types.js";
2
+ export declare const getBridgeMethod: <K extends keyof Methods>(key: K) => Methods[K];
@@ -0,0 +1,9 @@
1
+ import { AppsSdkAdapter } from "./apps-sdk-adapter.js";
2
+ import { McpAppAdapter } from "./mcp-app-adapter.js";
3
+ export const getBridgeMethod = (key) => {
4
+ const adapter = window.skybridge.hostType === "apps-sdk"
5
+ ? AppsSdkAdapter.getInstance()
6
+ : McpAppAdapter.getInstance();
7
+ return adapter.getMethod(key);
8
+ };
9
+ //# sourceMappingURL=get-bridge-method.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"get-bridge-method.js","sourceRoot":"","sources":["../../../../src/web/bridges/get-bridge-method.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAGrD,MAAM,CAAC,MAAM,eAAe,GAAG,CAC7B,GAAM,EACM,EAAE;IACd,MAAM,OAAO,GACX,MAAM,CAAC,SAAS,CAAC,QAAQ,KAAK,UAAU;QACtC,CAAC,CAAC,cAAc,CAAC,WAAW,EAAE;QAC9B,CAAC,CAAC,aAAa,CAAC,WAAW,EAAE,CAAC;IAElC,OAAO,OAAO,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC;AAChC,CAAC,CAAC"}
@@ -1,58 +1,12 @@
1
1
  import { useSyncExternalStore } from "react";
2
- import { AppsSdkBridge } from "../apps-sdk-bridge.js";
3
- import { McpAppBridge } from "../mcp-app-bridge.js";
4
- const getDefaultValueFromMcpAppBridge = (key) => {
5
- const DEFAULT_VALUES_FOR_MCP_APP_BRIDGE = {
6
- theme: "light",
7
- locale: "en-US",
8
- displayMode: "inline",
9
- safeArea: {
10
- insets: {
11
- top: 0,
12
- right: 0,
13
- bottom: 0,
14
- left: 0,
15
- },
16
- },
17
- maxHeight: window.innerHeight,
18
- };
19
- return DEFAULT_VALUES_FOR_MCP_APP_BRIDGE[key];
20
- };
2
+ import { AppsSdkAdapter } from "../apps-sdk-adapter.js";
3
+ import { McpAppAdapter } from "../mcp-app-adapter.js";
21
4
  const getExternalStore = (key) => {
22
- const defaultValue = getDefaultValueFromMcpAppBridge(key);
23
5
  const hostType = window.skybridge.hostType;
24
6
  if (hostType === "apps-sdk") {
25
- const bridge = AppsSdkBridge.getInstance();
26
- return {
27
- subscribe: bridge.subscribe(key),
28
- getSnapshot: () => bridge.getSnapshot(key),
29
- };
30
- }
31
- const bridge = McpAppBridge.getInstance();
32
- if (key === "safeArea") {
33
- return {
34
- subscribe: bridge.subscribe("safeAreaInsets"),
35
- getSnapshot: () => {
36
- const safeArea = bridge.getSnapshot("safeAreaInsets");
37
- return safeArea
38
- ? { insets: safeArea }
39
- : defaultValue;
40
- },
41
- };
42
- }
43
- if (key === "maxHeight") {
44
- return {
45
- subscribe: bridge.subscribe("viewport"),
46
- getSnapshot: () => {
47
- const viewport = bridge.getSnapshot("viewport");
48
- return (viewport?.maxHeight ?? defaultValue);
49
- },
50
- };
7
+ return AppsSdkAdapter.getInstance().getExternalStore(key);
51
8
  }
52
- return {
53
- subscribe: bridge.subscribe(key),
54
- getSnapshot: () => (bridge.getSnapshot(key) ?? defaultValue),
55
- };
9
+ return McpAppAdapter.getInstance().getExternalStore(key);
56
10
  };
57
11
  export const useBridge = (key) => {
58
12
  const externalStore = getExternalStore(key);
@@ -1 +1 @@
1
- {"version":3,"file":"use-bridge.js","sourceRoot":"","sources":["../../../../../src/web/bridges/hooks/use-bridge.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,MAAM,OAAO,CAAC;AAC7C,OAAO,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AACtD,OAAO,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAQpD,MAAM,+BAA+B,GAAG,CACtC,GAAM,EACc,EAAE;IACtB,MAAM,iCAAiC,GAAoB;QACzD,KAAK,EAAE,OAAO;QACd,MAAM,EAAE,OAAO;QACf,WAAW,EAAE,QAAQ;QACrB,QAAQ,EAAE;YACR,MAAM,EAAE;gBACN,GAAG,EAAE,CAAC;gBACN,KAAK,EAAE,CAAC;gBACR,MAAM,EAAE,CAAC;gBACT,IAAI,EAAE,CAAC;aACR;SACF;QACD,SAAS,EAAE,MAAM,CAAC,WAAW;KAC9B,CAAC;IAEF,OAAO,iCAAiC,CAAC,GAAG,CAAC,CAAC;AAChD,CAAC,CAAC;AAEF,MAAM,gBAAgB,GAAG,CACvB,GAAM,EACkB,EAAE;IAC1B,MAAM,YAAY,GAAG,+BAA+B,CAAC,GAAG,CAAC,CAAC;IAC1D,MAAM,QAAQ,GAAG,MAAM,CAAC,SAAS,CAAC,QAAQ,CAAC;IAC3C,IAAI,QAAQ,KAAK,UAAU,EAAE,CAAC;QAC5B,MAAM,MAAM,GAAG,aAAa,CAAC,WAAW,EAAE,CAAC;QAC3C,OAAO;YACL,SAAS,EAAE,MAAM,CAAC,SAAS,CAAC,GAAG,CAAC;YAChC,WAAW,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,WAAW,CAAC,GAAG,CAAC;SAC3C,CAAC;IACJ,CAAC;IACD,MAAM,MAAM,GAAG,YAAY,CAAC,WAAW,EAAE,CAAC;IAC1C,IAAI,GAAG,KAAK,UAAU,EAAE,CAAC;QACvB,OAAO;YACL,SAAS,EAAE,MAAM,CAAC,SAAS,CAAC,gBAAgB,CAAC;YAC7C,WAAW,EAAE,GAAG,EAAE;gBAChB,MAAM,QAAQ,GAAG,MAAM,CAAC,WAAW,CAAC,gBAAgB,CAAC,CAAC;gBACtD,OAAO,QAAQ;oBACb,CAAC,CAAE,EAAE,MAAM,EAAE,QAAQ,EAAyB;oBAC9C,CAAC,CAAC,YAAY,CAAC;YACnB,CAAC;SACF,CAAC;IACJ,CAAC;IACD,IAAI,GAAG,KAAK,WAAW,EAAE,CAAC;QACxB,OAAO;YACL,SAAS,EAAE,MAAM,CAAC,SAAS,CAAC,UAAU,CAAC;YACvC,WAAW,EAAE,GAAG,EAAE;gBAChB,MAAM,QAAQ,GAAG,MAAM,CAAC,WAAW,CAAC,UAAU,CAAC,CAAC;gBAChD,OAAO,CAAC,QAAQ,EAAE,SAAS,IAAI,YAAY,CAAuB,CAAC;YACrE,CAAC;SACF,CAAC;IACJ,CAAC;IACD,OAAO;QACL,SAAS,EAAE,MAAM,CAAC,SAAS,CAAC,GAAG,CAAC;QAChC,WAAW,EAAE,GAAG,EAAE,CAChB,CAAC,MAAM,CAAC,WAAW,CAAC,GAAG,CAAC,IAAI,YAAY,CAAuB;KAClE,CAAC;AACJ,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,SAAS,GAAG,CACvB,GAAM,EACc,EAAE;IACtB,MAAM,aAAa,GAAG,gBAAgB,CAAC,GAAG,CAAC,CAAC;IAE5C,OAAO,oBAAoB,CACzB,aAAa,CAAC,SAAS,EACvB,aAAa,CAAC,WAAW,CAC1B,CAAC;AACJ,CAAC,CAAC"}
1
+ {"version":3,"file":"use-bridge.js","sourceRoot":"","sources":["../../../../../src/web/bridges/hooks/use-bridge.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,MAAM,OAAO,CAAC;AAC7C,OAAO,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AACxD,OAAO,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAGtD,MAAM,gBAAgB,GAAG,CACvB,GAAM,EACY,EAAE;IACpB,MAAM,QAAQ,GAAG,MAAM,CAAC,SAAS,CAAC,QAAQ,CAAC;IAC3C,IAAI,QAAQ,KAAK,UAAU,EAAE,CAAC;QAC5B,OAAO,cAAc,CAAC,WAAW,EAAE,CAAC,gBAAgB,CAAC,GAAG,CAAC,CAAC;IAC5D,CAAC;IAED,OAAO,aAAa,CAAC,WAAW,EAAE,CAAC,gBAAgB,CAAC,GAAG,CAAC,CAAC;AAC3D,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,SAAS,GAAG,CACvB,GAAM,EACc,EAAE;IACtB,MAAM,aAAa,GAAG,gBAAgB,CAAC,GAAG,CAAC,CAAC;IAE5C,OAAO,oBAAoB,CACzB,aAAa,CAAC,SAAS,EACvB,aAAa,CAAC,WAAW,CAC1B,CAAC;AACJ,CAAC,CAAC"}
@@ -1,4 +1,5 @@
1
- import type { McpUiHostContext, McpUiInitializeRequest } from "@modelcontextprotocol/ext-apps";
1
+ import type { McpUiInitializeRequest } from "@modelcontextprotocol/ext-apps";
2
+ import { type McpAppBridgeContext } from "../mcp-app-bridge.js";
2
3
  type McpAppInitializationOptions = Pick<McpUiInitializeRequest["params"], "appInfo">;
3
- export declare function useMcpAppBridge<K extends keyof McpUiHostContext>(key: K, options?: Partial<McpAppInitializationOptions>, requestTimeout?: number): McpUiHostContext[K];
4
+ export declare function useMcpAppBridge<K extends keyof McpAppBridgeContext>(key: K, options?: Partial<McpAppInitializationOptions>, requestTimeout?: number): McpAppBridgeContext[K];
4
5
  export {};
@@ -1 +1 @@
1
- {"version":3,"file":"use-mcp-app-bridge.js","sourceRoot":"","sources":["../../../../../src/web/bridges/hooks/use-mcp-app-bridge.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,oBAAoB,EAAE,MAAM,OAAO,CAAC;AAC7C,OAAO,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAOpD,MAAM,UAAU,eAAe,CAC7B,GAAM,EACN,OAA8C,EAC9C,cAAuB;IAEvB,MAAM,MAAM,GAAG,YAAY,CAAC,WAAW,CAAC,OAAO,EAAE,cAAc,CAAC,CAAC;IACjE,OAAO,oBAAoB,CAAC,MAAM,CAAC,SAAS,CAAC,GAAG,CAAC,EAAE,GAAG,EAAE,CACtD,MAAM,CAAC,WAAW,CAAC,GAAG,CAAC,CACxB,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"use-mcp-app-bridge.js","sourceRoot":"","sources":["../../../../../src/web/bridges/hooks/use-mcp-app-bridge.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,oBAAoB,EAAE,MAAM,OAAO,CAAC;AAC7C,OAAO,EAAE,YAAY,EAA4B,MAAM,sBAAsB,CAAC;AAO9E,MAAM,UAAU,eAAe,CAC7B,GAAM,EACN,OAA8C,EAC9C,cAAuB;IAEvB,MAAM,MAAM,GAAG,YAAY,CAAC,WAAW,CAAC,OAAO,EAAE,cAAc,CAAC,CAAC;IACjE,OAAO,oBAAoB,CAAC,MAAM,CAAC,SAAS,CAAC,GAAG,CAAC,EAAE,GAAG,EAAE,CACtD,MAAM,CAAC,WAAW,CAAC,GAAG,CAAC,CACxB,CAAC;AACJ,CAAC"}
@@ -1,52 +1,36 @@
1
1
  import { act, renderHook, waitFor } from "@testing-library/react";
2
2
  import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
3
+ import { fireHostContextChangedNotification, MCPAppHostPostMessageMock, } from "../../hooks/test/utils.js";
3
4
  import { McpAppBridge } from "../mcp-app-bridge.js";
4
5
  import { useMcpAppBridge } from "./use-mcp-app-bridge.js";
5
6
  describe("useMcpAppBridge", () => {
6
- let mockPostMessage;
7
7
  beforeEach(async () => {
8
- mockPostMessage = vi.fn();
9
- Object.defineProperty(window, "parent", {
10
- value: { postMessage: mockPostMessage },
11
- writable: true,
12
- configurable: true,
13
- });
8
+ vi.stubGlobal("parent", { postMessage: MCPAppHostPostMessageMock });
14
9
  vi.stubGlobal("skybridge", { hostType: "mcp-app" });
15
10
  McpAppBridge.resetInstance();
16
11
  });
17
12
  afterEach(() => {
18
13
  vi.clearAllMocks();
19
14
  });
20
- it("should return the theme value from host context", async () => {
15
+ it("should return the theme value from host context and update on notification", async () => {
21
16
  const { result } = renderHook(() => useMcpAppBridge("theme"));
22
- const initCall = mockPostMessage.mock.calls.find((call) => call[0].method === "ui/initialize");
23
- if (initCall) {
24
- act(() => {
25
- window.dispatchEvent(new MessageEvent("message", {
26
- data: {
27
- jsonrpc: "2.0",
28
- id: initCall[0].id,
29
- result: {
30
- protocolVersion: "2025-06-18",
31
- hostInfo: { name: "test-host", version: "1.0.0" },
32
- hostCapabilities: {},
33
- hostContext: { theme: "light" },
34
- },
35
- },
36
- }));
37
- });
38
- }
39
17
  await waitFor(() => {
40
18
  expect(result.current).toBe("light");
41
19
  });
20
+ fireHostContextChangedNotification({ theme: "dark" });
21
+ await waitFor(() => {
22
+ expect(result.current).toBe("dark");
23
+ });
42
24
  });
43
25
  it("should reject the request after timeout", async () => {
44
26
  vi.useFakeTimers();
45
27
  const consoleErrorSpy = vi
46
28
  .spyOn(console, "error")
47
29
  .mockImplementation(() => { });
30
+ const nonRespondingMock = vi.fn();
31
+ vi.stubGlobal("parent", { postMessage: nonRespondingMock });
48
32
  renderHook(() => useMcpAppBridge("theme", undefined, 100));
49
- expect(mockPostMessage).toHaveBeenCalledWith(expect.objectContaining({ method: "ui/initialize" }), "*");
33
+ expect(nonRespondingMock).toHaveBeenCalledWith(expect.objectContaining({ method: "ui/initialize" }), "*");
50
34
  await act(async () => {
51
35
  await vi.advanceTimersByTimeAsync(100);
52
36
  });
@@ -1 +1 @@
1
- {"version":3,"file":"use-mcp-app-bridge.test.js","sourceRoot":"","sources":["../../../../../src/web/bridges/hooks/use-mcp-app-bridge.test.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"use-mcp-app-bridge.test.js","sourceRoot":"","sources":["../../../../../src/web/bridges/hooks/use-mcp-app-bridge.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,UAAU,EAAE,OAAO,EAAE,MAAM,wBAAwB,CAAC;AAClE,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AACzE,OAAO,EACL,kCAAkC,EAClC,yBAAyB,GAC1B,MAAM,2BAA2B,CAAC;AACnC,OAAO,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AACpD,OAAO,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAE1D,QAAQ,CAAC,iBAAiB,EAAE,GAAG,EAAE;IAC/B,UAAU,CAAC,KAAK,IAAI,EAAE;QACpB,EAAE,CAAC,UAAU,CAAC,QAAQ,EAAE,EAAE,WAAW,EAAE,yBAAyB,EAAE,CAAC,CAAC;QACpE,EAAE,CAAC,UAAU,CAAC,WAAW,EAAE,EAAE,QAAQ,EAAE,SAAS,EAAE,CAAC,CAAC;QACpD,YAAY,CAAC,aAAa,EAAE,CAAC;IAC/B,CAAC,CAAC,CAAC;IAEH,SAAS,CAAC,GAAG,EAAE;QACb,EAAE,CAAC,aAAa,EAAE,CAAC;IACrB,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,4EAA4E,EAAE,KAAK,IAAI,EAAE;QAC1F,MAAM,EAAE,MAAM,EAAE,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC,eAAe,CAAC,OAAO,CAAC,CAAC,CAAC;QAE9D,MAAM,OAAO,CAAC,GAAG,EAAE;YACjB,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QACvC,CAAC,CAAC,CAAC;QAEH,kCAAkC,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,CAAC;QAEtD,MAAM,OAAO,CAAC,GAAG,EAAE;YACjB,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QACtC,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,yCAAyC,EAAE,KAAK,IAAI,EAAE;QACvD,EAAE,CAAC,aAAa,EAAE,CAAC;QACnB,MAAM,eAAe,GAAG,EAAE;aACvB,KAAK,CAAC,OAAO,EAAE,OAAO,CAAC;aACvB,kBAAkB,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;QAEhC,MAAM,iBAAiB,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC;QAClC,EAAE,CAAC,UAAU,CAAC,QAAQ,EAAE,EAAE,WAAW,EAAE,iBAAiB,EAAE,CAAC,CAAC;QAE5D,UAAU,CAAC,GAAG,EAAE,CAAC,eAAe,CAAC,OAAO,EAAE,SAAS,EAAE,GAAG,CAAC,CAAC,CAAC;QAE3D,MAAM,CAAC,iBAAiB,CAAC,CAAC,oBAAoB,CAC5C,MAAM,CAAC,gBAAgB,CAAC,EAAE,MAAM,EAAE,eAAe,EAAE,CAAC,EACpD,GAAG,CACJ,CAAC;QAEF,MAAM,GAAG,CAAC,KAAK,IAAI,EAAE;YACnB,MAAM,EAAE,CAAC,wBAAwB,CAAC,GAAG,CAAC,CAAC;QACzC,CAAC,CAAC,CAAC;QAEH,MAAM,CAAC,eAAe,CAAC,CAAC,oBAAoB,CAC1C,IAAI,KAAK,CAAC,mBAAmB,CAAC,CAC/B,CAAC;QAEF,eAAe,CAAC,WAAW,EAAE,CAAC;QAC9B,EAAE,CAAC,aAAa,EAAE,CAAC;IACrB,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
@@ -1,4 +1,4 @@
1
- export { getBridgeMethods } from "./get-bridge-methods.js";
1
+ export { getBridgeMethod } from "./get-bridge-method.js";
2
2
  export { useAppsSdkBridge } from "./hooks/use-apps-sdk-bridge.js";
3
3
  export { useBridge } from "./hooks/use-bridge.js";
4
4
  export { useMcpAppBridge } from "./hooks/use-mcp-app-bridge.js";
@@ -1,4 +1,4 @@
1
- export { getBridgeMethods } from "./get-bridge-methods.js";
1
+ export { getBridgeMethod } from "./get-bridge-method.js";
2
2
  export { useAppsSdkBridge } from "./hooks/use-apps-sdk-bridge.js";
3
3
  export { useBridge } from "./hooks/use-bridge.js";
4
4
  export { useMcpAppBridge } from "./hooks/use-mcp-app-bridge.js";
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/web/bridges/index.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAC3D,OAAO,EAAE,gBAAgB,EAAE,MAAM,gCAAgC,CAAC;AAClE,OAAO,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAClD,OAAO,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/web/bridges/index.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AACzD,OAAO,EAAE,gBAAgB,EAAE,MAAM,gCAAgC,CAAC;AAClE,OAAO,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAClD,OAAO,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAC"}
@@ -1,2 +1,16 @@
1
- import type { Methods } from "./types.js";
2
- export declare const requestDisplayMode: Methods["requestDisplayMode"];
1
+ import type { McpUiRequestDisplayModeResult } from "@modelcontextprotocol/ext-apps";
2
+ import type { Adapter, BridgeInterface, CallToolResponse, DisplayMode, ExternalStore, Methods } from "./types.js";
3
+ export declare class McpAppAdapter implements Adapter {
4
+ private static instance;
5
+ private stores;
6
+ private constructor();
7
+ static getInstance(): McpAppAdapter;
8
+ static resetInstance(): void;
9
+ getExternalStore<K extends keyof BridgeInterface>(key: K): ExternalStore<K>;
10
+ getMethod<K extends keyof Methods>(key: K): this[K];
11
+ callTool: <ToolArgs extends Record<string, unknown> | null = null, ToolResponse extends CallToolResponse = CallToolResponse>(name: string, args: ToolArgs) => Promise<ToolResponse>;
12
+ requestDisplayMode: (mode: DisplayMode) => Promise<McpUiRequestDisplayModeResult>;
13
+ sendFollowUpMessage: (prompt: string) => Promise<void>;
14
+ private initializeStores;
15
+ private createExternalStore;
16
+ }
@@ -1,12 +1,111 @@
1
- import { McpAppBridge } from "./mcp-app-bridge.js";
2
- export const requestDisplayMode = ({ mode }) => {
3
- const bridge = McpAppBridge.getInstance();
4
- if (mode !== "modal") {
5
- return bridge.request({
6
- method: "ui/request-display-mode",
7
- params: { mode },
1
+ import { dequal } from "dequal/lite";
2
+ import { McpAppBridge, } from "./mcp-app-bridge.js";
3
+ export class McpAppAdapter {
4
+ static instance = null;
5
+ stores;
6
+ constructor() {
7
+ this.stores = this.initializeStores();
8
+ }
9
+ static getInstance() {
10
+ if (!McpAppAdapter.instance) {
11
+ McpAppAdapter.instance = new McpAppAdapter();
12
+ }
13
+ return McpAppAdapter.instance;
14
+ }
15
+ static resetInstance() {
16
+ McpAppAdapter.instance = null;
17
+ }
18
+ getExternalStore(key) {
19
+ return this.stores[key];
20
+ }
21
+ getMethod(key) {
22
+ return this[key];
23
+ }
24
+ callTool = async (name, args) => {
25
+ const bridge = McpAppBridge.getInstance();
26
+ const response = await bridge.request({
27
+ method: "tools/call",
28
+ params: {
29
+ name,
30
+ arguments: args ?? undefined,
31
+ },
32
+ });
33
+ const result = response.content
34
+ .filter((content) => content.type === "text")
35
+ .map(({ text }) => text)
36
+ .join("\n");
37
+ return {
38
+ content: response.content,
39
+ structuredContent: response.structuredContent ?? {},
40
+ isError: response.isError ?? false,
41
+ result,
42
+ meta: response._meta ?? {},
43
+ };
44
+ };
45
+ requestDisplayMode = (mode) => {
46
+ const bridge = McpAppBridge.getInstance();
47
+ if (mode !== "modal") {
48
+ return bridge.request({
49
+ method: "ui/request-display-mode",
50
+ params: { mode },
51
+ });
52
+ }
53
+ throw new Error("Modal display mode is not accessible in MCP App.");
54
+ };
55
+ sendFollowUpMessage = async (prompt) => {
56
+ const bridge = McpAppBridge.getInstance();
57
+ await bridge.request({
58
+ method: "ui/message",
59
+ params: {
60
+ role: "user",
61
+ content: [
62
+ {
63
+ type: "text",
64
+ text: prompt,
65
+ },
66
+ ],
67
+ },
8
68
  });
69
+ };
70
+ initializeStores() {
71
+ return {
72
+ theme: this.createExternalStore(["theme"], ({ theme }) => theme ?? "light"),
73
+ locale: this.createExternalStore(["locale"], ({ locale }) => locale ?? "en-US"),
74
+ safeArea: this.createExternalStore(["safeAreaInsets"], ({ safeAreaInsets }) => ({
75
+ insets: safeAreaInsets ?? { top: 0, right: 0, bottom: 0, left: 0 },
76
+ })),
77
+ displayMode: this.createExternalStore(["displayMode"], ({ displayMode }) => displayMode ?? "inline"),
78
+ maxHeight: this.createExternalStore(["viewport"], ({ viewport }) => viewport?.maxHeight ?? window.innerHeight),
79
+ userAgent: this.createExternalStore(["platform", "deviceCapabilities"], ({ platform, deviceCapabilities }) => ({
80
+ device: {
81
+ type: platform === "web" ? "desktop" : (platform ?? "unknown"),
82
+ },
83
+ capabilities: {
84
+ hover: true,
85
+ touch: true,
86
+ ...deviceCapabilities,
87
+ },
88
+ })),
89
+ toolInput: this.createExternalStore(["toolInput"], ({ toolInput }) => toolInput ?? null),
90
+ toolOutput: this.createExternalStore(["toolResult"], ({ toolResult }) => toolResult?.structuredContent ?? null),
91
+ toolResponseMetadata: this.createExternalStore(["toolResult"], ({ toolResult }) => toolResult?._meta ?? null),
92
+ };
93
+ }
94
+ createExternalStore(keys, computeSnapshot) {
95
+ const bridge = McpAppBridge.getInstance();
96
+ let cachedValue;
97
+ return {
98
+ subscribe: bridge.subscribe(keys),
99
+ getSnapshot: () => {
100
+ const context = Object.fromEntries(keys.map((k) => [k, bridge.getSnapshot(k)]));
101
+ const newValue = computeSnapshot(context);
102
+ if (cachedValue !== undefined && dequal(cachedValue, newValue)) {
103
+ return cachedValue;
104
+ }
105
+ cachedValue = newValue;
106
+ return newValue;
107
+ },
108
+ };
9
109
  }
10
- throw new Error("Modal display mode is not accessible in MCP App.");
11
- };
110
+ }
12
111
  //# sourceMappingURL=mcp-app-adapter.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"mcp-app-adapter.js","sourceRoot":"","sources":["../../../../src/web/bridges/mcp-app-adapter.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAGnD,MAAM,CAAC,MAAM,kBAAkB,GAAkC,CAAC,EAAE,IAAI,EAAE,EAAE,EAAE;IAC5E,MAAM,MAAM,GAAG,YAAY,CAAC,WAAW,EAAE,CAAC;IAC1C,IAAI,IAAI,KAAK,OAAO,EAAE,CAAC;QACrB,OAAO,MAAM,CAAC,OAAO,CAGnB;YACA,MAAM,EAAE,yBAAyB;YACjC,MAAM,EAAE,EAAE,IAAI,EAAE;SACjB,CAAC,CAAC;IACL,CAAC;IAED,MAAM,IAAI,KAAK,CAAC,kDAAkD,CAAC,CAAC;AACtE,CAAC,CAAC"}
1
+ {"version":3,"file":"mcp-app-adapter.js","sourceRoot":"","sources":["../../../../src/web/bridges/mcp-app-adapter.ts"],"names":[],"mappings":"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"}
@@ -1,8 +1,16 @@
1
- import type { McpUiHostContext, McpUiInitializeRequest } from "@modelcontextprotocol/ext-apps";
1
+ import type { McpUiHostContext, McpUiInitializeRequest, McpUiToolCancelledNotification, McpUiToolInputNotification, McpUiToolResultNotification } from "@modelcontextprotocol/ext-apps";
2
+ import type { Bridge, Subscribe } from "./types.js";
2
3
  type McpAppInitializationOptions = Pick<McpUiInitializeRequest["params"], "appInfo">;
3
- export declare class McpAppBridge {
4
+ export type McpToolState = {
5
+ toolInput: NonNullable<McpUiToolInputNotification["params"]["arguments"]> | null;
6
+ toolResult: McpUiToolResultNotification["params"] | null;
7
+ toolCancelled: McpUiToolCancelledNotification["params"] | null;
8
+ };
9
+ export type McpAppBridgeContext = McpUiHostContext & McpToolState;
10
+ export type McpAppBridgeKey = keyof McpAppBridgeContext;
11
+ export declare class McpAppBridge implements Bridge<McpUiHostContext> {
4
12
  private static instance;
5
- context: McpUiHostContext | null;
13
+ context: McpAppBridgeContext;
6
14
  private listeners;
7
15
  private pendingRequests;
8
16
  private nextId;
@@ -11,8 +19,9 @@ export declare class McpAppBridge {
11
19
  private requestTimeout;
12
20
  constructor(options: McpAppInitializationOptions, requestTimeout?: number);
13
21
  static getInstance(options?: Partial<McpAppInitializationOptions>, requestTimeout?: number): McpAppBridge;
14
- subscribe: (key: keyof McpUiHostContext) => (onChange: () => void) => () => boolean | undefined;
15
- getSnapshot: <K extends keyof McpUiHostContext>(key: K) => McpUiHostContext[K] | undefined;
22
+ subscribe(key: McpAppBridgeKey): Subscribe;
23
+ subscribe(keys: readonly McpAppBridgeKey[]): Subscribe;
24
+ getSnapshot<K extends keyof McpAppBridgeContext>(key: K): McpAppBridgeContext[K];
16
25
  cleanup: () => void;
17
26
  static resetInstance(): void;
18
27
  request<R extends {
@@ -20,7 +29,7 @@ export declare class McpAppBridge {
20
29
  params?: unknown;
21
30
  }, T>({ method, params, }: R): Promise<T>;
22
31
  private emit;
23
- private setContext;
32
+ private updateContext;
24
33
  private init;
25
34
  private handleMessage;
26
35
  private connect;