skybridge 0.0.0-dev.a7b36b1 → 0.0.0-dev.a80dfb9

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 (185) hide show
  1. package/README.md +144 -0
  2. package/bin/run.js +0 -4
  3. package/dist/cli/telemetry.d.ts +7 -0
  4. package/dist/cli/telemetry.js +123 -0
  5. package/dist/cli/telemetry.js.map +1 -0
  6. package/dist/cli/use-execute-steps.d.ts +3 -2
  7. package/dist/cli/use-execute-steps.js +6 -1
  8. package/dist/cli/use-execute-steps.js.map +1 -1
  9. package/dist/cli/use-nodemon.d.ts +6 -0
  10. package/dist/cli/use-nodemon.js +61 -0
  11. package/dist/cli/use-nodemon.js.map +1 -0
  12. package/dist/cli/use-typescript-check.d.ts +8 -0
  13. package/dist/cli/use-typescript-check.js +59 -0
  14. package/dist/cli/use-typescript-check.js.map +1 -0
  15. package/dist/commands/build.js +4 -2
  16. package/dist/commands/build.js.map +1 -1
  17. package/dist/commands/dev.d.ts +3 -1
  18. package/dist/commands/dev.js +20 -9
  19. package/dist/commands/dev.js.map +1 -1
  20. package/dist/commands/telemetry/disable.d.ts +5 -0
  21. package/dist/commands/telemetry/disable.js +14 -0
  22. package/dist/commands/telemetry/disable.js.map +1 -0
  23. package/dist/commands/telemetry/enable.d.ts +5 -0
  24. package/dist/commands/telemetry/enable.js +14 -0
  25. package/dist/commands/telemetry/enable.js.map +1 -0
  26. package/dist/commands/telemetry/status.d.ts +5 -0
  27. package/dist/commands/telemetry/status.js +14 -0
  28. package/dist/commands/telemetry/status.js.map +1 -0
  29. package/dist/server/asset-base-url-transform-plugin.d.ts +11 -0
  30. package/dist/server/asset-base-url-transform-plugin.js +34 -0
  31. package/dist/server/asset-base-url-transform-plugin.js.map +1 -0
  32. package/dist/server/asset-base-url-transform-plugin.test.js +56 -0
  33. package/dist/server/asset-base-url-transform-plugin.test.js.map +1 -0
  34. package/dist/server/server.d.ts +2 -4
  35. package/dist/server/server.js +77 -56
  36. package/dist/server/server.js.map +1 -1
  37. package/dist/server/templateHelper.d.ts +1 -0
  38. package/dist/server/templateHelper.js.map +1 -1
  39. package/dist/server/templates/development.hbs +3 -2
  40. package/dist/server/templates/production.hbs +1 -2
  41. package/dist/server/widgetsDevServer.js +11 -1
  42. package/dist/server/widgetsDevServer.js.map +1 -1
  43. package/dist/test/widget.test.js +23 -2
  44. package/dist/test/widget.test.js.map +1 -1
  45. package/dist/web/bridges/apps-sdk/adaptor.d.ts +22 -0
  46. package/dist/web/bridges/apps-sdk/adaptor.js +64 -0
  47. package/dist/web/bridges/apps-sdk/adaptor.js.map +1 -0
  48. package/dist/web/bridges/apps-sdk/bridge.d.ts +10 -0
  49. package/dist/web/bridges/{apps-sdk-bridge.js → apps-sdk/bridge.js} +2 -2
  50. package/dist/web/bridges/apps-sdk/bridge.js.map +1 -0
  51. package/dist/web/bridges/apps-sdk/index.d.ts +5 -0
  52. package/dist/web/bridges/apps-sdk/index.js +5 -0
  53. package/dist/web/bridges/apps-sdk/index.js.map +1 -0
  54. package/dist/web/bridges/apps-sdk/types.d.ts +115 -0
  55. package/dist/web/bridges/apps-sdk/types.js +10 -0
  56. package/dist/web/bridges/apps-sdk/types.js.map +1 -0
  57. package/dist/web/bridges/apps-sdk/use-apps-sdk-context.d.ts +2 -0
  58. package/dist/web/bridges/{hooks/use-apps-sdk-bridge.js → apps-sdk/use-apps-sdk-context.js} +3 -3
  59. package/dist/web/bridges/apps-sdk/use-apps-sdk-context.js.map +1 -0
  60. package/dist/web/bridges/get-adaptor.d.ts +2 -0
  61. package/dist/web/bridges/get-adaptor.js +8 -0
  62. package/dist/web/bridges/get-adaptor.js.map +1 -0
  63. package/dist/web/bridges/index.d.ts +5 -4
  64. package/dist/web/bridges/index.js +5 -4
  65. package/dist/web/bridges/index.js.map +1 -1
  66. package/dist/web/bridges/mcp-app/adaptor.d.ts +36 -0
  67. package/dist/web/bridges/mcp-app/adaptor.js +185 -0
  68. package/dist/web/bridges/mcp-app/adaptor.js.map +1 -0
  69. package/dist/web/bridges/{mcp-app-bridge.d.ts → mcp-app/bridge.d.ts} +7 -13
  70. package/dist/web/bridges/{mcp-app-bridge.js → mcp-app/bridge.js} +18 -19
  71. package/dist/web/bridges/mcp-app/bridge.js.map +1 -0
  72. package/dist/web/bridges/mcp-app/index.d.ts +4 -0
  73. package/dist/web/bridges/mcp-app/index.js +4 -0
  74. package/dist/web/bridges/mcp-app/index.js.map +1 -0
  75. package/dist/web/bridges/mcp-app/types.d.ts +8 -0
  76. package/dist/web/bridges/mcp-app/types.js +2 -0
  77. package/dist/web/bridges/mcp-app/types.js.map +1 -0
  78. package/dist/web/bridges/mcp-app/use-mcp-app-context.d.ts +5 -0
  79. package/dist/web/bridges/{hooks/use-mcp-app-bridge.js → mcp-app/use-mcp-app-context.js} +3 -3
  80. package/dist/web/bridges/mcp-app/use-mcp-app-context.js.map +1 -0
  81. package/dist/web/bridges/mcp-app/use-mcp-app-context.test.d.ts +1 -0
  82. package/dist/web/bridges/{hooks/use-mcp-app-bridge.test.js → mcp-app/use-mcp-app-context.test.js} +17 -13
  83. package/dist/web/bridges/mcp-app/use-mcp-app-context.test.js.map +1 -0
  84. package/dist/web/bridges/types.d.ts +65 -24
  85. package/dist/web/bridges/use-host-context.d.ts +2 -0
  86. package/dist/web/bridges/use-host-context.js +8 -0
  87. package/dist/web/bridges/use-host-context.js.map +1 -0
  88. package/dist/web/components/modal-provider.d.ts +4 -0
  89. package/dist/web/components/modal-provider.js +47 -0
  90. package/dist/web/components/modal-provider.js.map +1 -0
  91. package/dist/web/create-store.js +6 -7
  92. package/dist/web/create-store.js.map +1 -1
  93. package/dist/web/create-store.test.js +108 -52
  94. package/dist/web/create-store.test.js.map +1 -1
  95. package/dist/web/data-llm.js +5 -3
  96. package/dist/web/data-llm.js.map +1 -1
  97. package/dist/web/data-llm.test.js +128 -65
  98. package/dist/web/data-llm.test.js.map +1 -1
  99. package/dist/web/generate-helpers.d.ts +3 -2
  100. package/dist/web/generate-helpers.js +1 -1
  101. package/dist/web/generate-helpers.js.map +1 -1
  102. package/dist/web/helpers/state.js +13 -8
  103. package/dist/web/helpers/state.js.map +1 -1
  104. package/dist/web/hooks/index.d.ts +1 -1
  105. package/dist/web/hooks/index.js +1 -1
  106. package/dist/web/hooks/index.js.map +1 -1
  107. package/dist/web/hooks/test/utils.d.ts +8 -2
  108. package/dist/web/hooks/test/utils.js +33 -13
  109. package/dist/web/hooks/test/utils.js.map +1 -1
  110. package/dist/web/hooks/use-call-tool.d.ts +3 -2
  111. package/dist/web/hooks/use-call-tool.js +2 -2
  112. package/dist/web/hooks/use-call-tool.js.map +1 -1
  113. package/dist/web/hooks/use-call-tool.test-d.js +1 -1
  114. package/dist/web/hooks/use-call-tool.test-d.js.map +1 -1
  115. package/dist/web/hooks/use-call-tool.test.js +3 -3
  116. package/dist/web/hooks/use-call-tool.test.js.map +1 -1
  117. package/dist/web/hooks/use-display-mode.js +3 -4
  118. package/dist/web/hooks/use-display-mode.js.map +1 -1
  119. package/dist/web/hooks/use-files.d.ts +2 -6
  120. package/dist/web/hooks/use-files.js +4 -2
  121. package/dist/web/hooks/use-files.js.map +1 -1
  122. package/dist/web/hooks/use-files.test.js +1 -0
  123. package/dist/web/hooks/use-files.test.js.map +1 -1
  124. package/dist/web/hooks/use-layout.d.ts +2 -2
  125. package/dist/web/hooks/use-layout.js +4 -4
  126. package/dist/web/hooks/use-layout.js.map +1 -1
  127. package/dist/web/hooks/use-layout.test.js +4 -3
  128. package/dist/web/hooks/use-layout.test.js.map +1 -1
  129. package/dist/web/hooks/use-open-external.js +2 -2
  130. package/dist/web/hooks/use-open-external.test.js +1 -1
  131. package/dist/web/hooks/use-request-modal.d.ts +2 -2
  132. package/dist/web/hooks/use-request-modal.js +9 -7
  133. package/dist/web/hooks/use-request-modal.js.map +1 -1
  134. package/dist/web/hooks/use-send-follow-up-message.js +2 -2
  135. package/dist/web/hooks/use-set-open-in-app-url.d.ts +1 -0
  136. package/dist/web/hooks/use-set-open-in-app-url.js +8 -0
  137. package/dist/web/hooks/use-set-open-in-app-url.js.map +1 -0
  138. package/dist/web/hooks/use-set-open-in-app-url.test.d.ts +1 -0
  139. package/dist/web/hooks/use-set-open-in-app-url.test.js +49 -0
  140. package/dist/web/hooks/use-set-open-in-app-url.test.js.map +1 -0
  141. package/dist/web/hooks/use-tool-info.js +4 -4
  142. package/dist/web/hooks/use-tool-info.js.map +1 -1
  143. package/dist/web/hooks/use-tool-info.test.js +4 -4
  144. package/dist/web/hooks/use-tool-info.test.js.map +1 -1
  145. package/dist/web/hooks/use-user.d.ts +1 -1
  146. package/dist/web/hooks/use-user.js +3 -3
  147. package/dist/web/hooks/use-user.js.map +1 -1
  148. package/dist/web/hooks/use-user.test.js +4 -3
  149. package/dist/web/hooks/use-user.test.js.map +1 -1
  150. package/dist/web/hooks/use-widget-state.js +10 -10
  151. package/dist/web/hooks/use-widget-state.js.map +1 -1
  152. package/dist/web/mount-widget.js +9 -1
  153. package/dist/web/mount-widget.js.map +1 -1
  154. package/dist/web/plugin/plugin.js +7 -0
  155. package/dist/web/plugin/plugin.js.map +1 -1
  156. package/dist/web/proxy.js +0 -1
  157. package/dist/web/proxy.js.map +1 -1
  158. package/dist/web/types.d.ts +0 -133
  159. package/dist/web/types.js +0 -9
  160. package/dist/web/types.js.map +1 -1
  161. package/package.json +24 -17
  162. package/dist/web/bridges/adaptors/apps-sdk-adaptor.d.ts +0 -13
  163. package/dist/web/bridges/adaptors/apps-sdk-adaptor.js +0 -33
  164. package/dist/web/bridges/adaptors/apps-sdk-adaptor.js.map +0 -1
  165. package/dist/web/bridges/adaptors/mcp-app-adaptor.d.ts +0 -16
  166. package/dist/web/bridges/adaptors/mcp-app-adaptor.js +0 -120
  167. package/dist/web/bridges/adaptors/mcp-app-adaptor.js.map +0 -1
  168. package/dist/web/bridges/apps-sdk-bridge.d.ts +0 -10
  169. package/dist/web/bridges/apps-sdk-bridge.js.map +0 -1
  170. package/dist/web/bridges/hooks/use-adaptor.d.ts +0 -2
  171. package/dist/web/bridges/hooks/use-adaptor.js +0 -8
  172. package/dist/web/bridges/hooks/use-adaptor.js.map +0 -1
  173. package/dist/web/bridges/hooks/use-apps-sdk-bridge.d.ts +0 -2
  174. package/dist/web/bridges/hooks/use-apps-sdk-bridge.js.map +0 -1
  175. package/dist/web/bridges/hooks/use-bridge.d.ts +0 -2
  176. package/dist/web/bridges/hooks/use-bridge.js +0 -8
  177. package/dist/web/bridges/hooks/use-bridge.js.map +0 -1
  178. package/dist/web/bridges/hooks/use-mcp-app-bridge.d.ts +0 -5
  179. package/dist/web/bridges/hooks/use-mcp-app-bridge.js.map +0 -1
  180. package/dist/web/bridges/hooks/use-mcp-app-bridge.test.js.map +0 -1
  181. package/dist/web/bridges/mcp-app-bridge.js.map +0 -1
  182. package/dist/web/hooks/use-openai-global.d.ts +0 -3
  183. package/dist/web/hooks/use-openai-global.js +0 -6
  184. package/dist/web/hooks/use-openai-global.js.map +0 -1
  185. /package/dist/{web/bridges/hooks/use-mcp-app-bridge.test.d.ts → server/asset-base-url-transform-plugin.test.d.ts} +0 -0
@@ -29,6 +29,7 @@ export class McpAppBridge {
29
29
  appCapabilities: {},
30
30
  protocolVersion: LATEST_PROTOCOL_VERSION,
31
31
  };
32
+ this.init();
32
33
  }
33
34
  static getInstance(options, requestTimeout) {
34
35
  if (window.skybridge.hostType !== "mcp-app") {
@@ -51,7 +52,6 @@ export class McpAppBridge {
51
52
  for (const key of keys) {
52
53
  this.listeners.set(key, new Set([...(this.listeners.get(key) || []), onChange]));
53
54
  }
54
- this.init();
55
55
  return () => {
56
56
  for (const key of keys) {
57
57
  this.listeners.get(key)?.delete(onChange);
@@ -220,23 +220,22 @@ export class McpAppBridge {
220
220
  scheduled = true;
221
221
  requestAnimationFrame(() => {
222
222
  scheduled = false;
223
- const html = document.documentElement;
224
- // Measure actual content size by temporarily setting html to fit-content.
225
- // This shrinks html to fit body (including body margins), giving us the
226
- // true minimum size needed by the content.
227
- const originalWidth = html.style.width;
228
- const originalHeight = html.style.height;
229
- html.style.width = "fit-content";
230
- html.style.height = "fit-content";
231
- const rect = html.getBoundingClientRect();
232
- html.style.width = originalWidth;
233
- html.style.height = originalHeight;
234
- // Compensate for scrollbar width on Linux/Windows where scrollbars
235
- // consume space. On systems with overlay scrollbars (macOS), this
236
- // will be 0.
237
- const scrollbarWidth = window.innerWidth - html.clientWidth;
238
- const width = Math.ceil(rect.width + scrollbarWidth);
239
- const height = Math.ceil(rect.height);
223
+ let width;
224
+ let height;
225
+ // In fullscreen mode, use viewport size since the widget should fill
226
+ // the entire available space provided by the host.
227
+ if (this.context.displayMode === "fullscreen") {
228
+ width = window.innerWidth;
229
+ height = window.innerHeight;
230
+ }
231
+ else {
232
+ // Use scrollWidth/scrollHeight to measure actual rendered content size.
233
+ // This works better than fit-content for viewport-based layouts (vw/vh)
234
+ // and fluid elements like maps that want to fill available space.
235
+ const body = document.body;
236
+ width = Math.ceil(body.scrollWidth);
237
+ height = Math.ceil(body.scrollHeight);
238
+ }
240
239
  // Only send if size actually changed (prevents feedback loops from
241
240
  // style changes)
242
241
  if (width !== lastWidth || height !== lastHeight) {
@@ -253,4 +252,4 @@ export class McpAppBridge {
253
252
  return () => resizeObserver.disconnect();
254
253
  }
255
254
  }
256
- //# sourceMappingURL=mcp-app-bridge.js.map
255
+ //# sourceMappingURL=bridge.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bridge.js","sourceRoot":"","sources":["../../../../src/web/bridges/mcp-app/bridge.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ export { McpAppAdaptor } from "./adaptor.js";
2
+ export { McpAppBridge } from "./bridge.js";
3
+ export type { McpAppContext, McpAppContextKey, McpToolState, } from "./types.js";
4
+ export { useMcpAppContext } from "./use-mcp-app-context.js";
@@ -0,0 +1,4 @@
1
+ export { McpAppAdaptor } from "./adaptor.js";
2
+ export { McpAppBridge } from "./bridge.js";
3
+ export { useMcpAppContext } from "./use-mcp-app-context.js";
4
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/web/bridges/mcp-app/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAC7C,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAM3C,OAAO,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC"}
@@ -0,0 +1,8 @@
1
+ import type { McpUiHostContext, McpUiToolCancelledNotification, McpUiToolInputNotification, McpUiToolResultNotification } from "@modelcontextprotocol/ext-apps";
2
+ export type McpToolState = {
3
+ toolInput: NonNullable<McpUiToolInputNotification["params"]["arguments"]> | null;
4
+ toolResult: McpUiToolResultNotification["params"] | null;
5
+ toolCancelled: McpUiToolCancelledNotification["params"] | null;
6
+ };
7
+ export type McpAppContext = McpUiHostContext & McpToolState;
8
+ export type McpAppContextKey = keyof McpAppContext;
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../../../src/web/bridges/mcp-app/types.ts"],"names":[],"mappings":""}
@@ -0,0 +1,5 @@
1
+ import type { McpUiInitializeRequest } from "@modelcontextprotocol/ext-apps";
2
+ import type { McpAppContext } from "./types.js";
3
+ type McpAppInitializationOptions = Pick<McpUiInitializeRequest["params"], "appInfo">;
4
+ export declare function useMcpAppContext<K extends keyof McpAppContext>(key: K, options?: Partial<McpAppInitializationOptions>, requestTimeout?: number): McpAppContext[K];
5
+ export {};
@@ -1,7 +1,7 @@
1
1
  import { useSyncExternalStore } from "react";
2
- import { McpAppBridge } from "../mcp-app-bridge.js";
3
- export function useMcpAppBridge(key, options, requestTimeout) {
2
+ import { McpAppBridge } from "./bridge.js";
3
+ export function useMcpAppContext(key, options, requestTimeout) {
4
4
  const bridge = McpAppBridge.getInstance(options, requestTimeout);
5
5
  return useSyncExternalStore(bridge.subscribe(key), () => bridge.getSnapshot(key));
6
6
  }
7
- //# sourceMappingURL=use-mcp-app-bridge.js.map
7
+ //# sourceMappingURL=use-mcp-app-context.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use-mcp-app-context.js","sourceRoot":"","sources":["../../../../src/web/bridges/mcp-app/use-mcp-app-context.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,oBAAoB,EAAE,MAAM,OAAO,CAAC;AAC7C,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAQ3C,MAAM,UAAU,gBAAgB,CAC9B,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,14 +1,9 @@
1
1
  import { act, renderHook, waitFor } from "@testing-library/react";
2
2
  import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
3
- import { getMcpAppHostPostMessageMock } from "../../hooks/test/utils.js";
4
- import { McpAppBridge } from "../mcp-app-bridge.js";
5
- import { useMcpAppBridge } from "./use-mcp-app-bridge.js";
6
- class MockResizeObserver {
7
- observe = vi.fn();
8
- unobserve = vi.fn();
9
- disconnect = vi.fn();
10
- }
11
- describe("useMcpAppBridge", () => {
3
+ import { getMcpAppHostPostMessageMock, MockResizeObserver, } from "../../hooks/test/utils.js";
4
+ import { McpAppBridge } from "./bridge.js";
5
+ import { useMcpAppContext } from "./use-mcp-app-context.js";
6
+ describe("useMcpAppContext", () => {
12
7
  beforeEach(async () => {
13
8
  vi.stubGlobal("skybridge", { hostType: "mcp-app" });
14
9
  vi.stubGlobal("ResizeObserver", MockResizeObserver);
@@ -22,7 +17,7 @@ describe("useMcpAppBridge", () => {
22
17
  vi.stubGlobal("parent", {
23
18
  postMessage: getMcpAppHostPostMessageMock({ theme: "light" }),
24
19
  });
25
- const { result } = renderHook(() => useMcpAppBridge("theme"));
20
+ const { result } = renderHook(() => useMcpAppContext("theme"));
26
21
  await waitFor(() => {
27
22
  expect(result.current).toBe("light");
28
23
  });
@@ -34,7 +29,7 @@ describe("useMcpAppBridge", () => {
34
29
  .mockImplementation(() => { });
35
30
  const nonRespondingMock = vi.fn();
36
31
  vi.stubGlobal("parent", { postMessage: nonRespondingMock });
37
- renderHook(() => useMcpAppBridge("theme", undefined, 100));
32
+ renderHook(() => useMcpAppContext("theme", undefined, 100));
38
33
  expect(nonRespondingMock).toHaveBeenCalledWith(expect.objectContaining({ method: "ui/initialize" }), "*");
39
34
  await act(async () => {
40
35
  await vi.advanceTimersByTimeAsync(100);
@@ -44,9 +39,18 @@ describe("useMcpAppBridge", () => {
44
39
  vi.useRealTimers();
45
40
  });
46
41
  it("should send size-changed notification after successful initialization", async () => {
42
+ // Mock body dimensions to non-zero (size-changed only sends when dimensions change)
43
+ Object.defineProperty(document.body, "scrollWidth", {
44
+ value: 800,
45
+ configurable: true,
46
+ });
47
+ Object.defineProperty(document.body, "scrollHeight", {
48
+ value: 600,
49
+ configurable: true,
50
+ });
47
51
  const postMessageMock = getMcpAppHostPostMessageMock({ theme: "light" });
48
52
  vi.stubGlobal("parent", { postMessage: postMessageMock });
49
- renderHook(() => useMcpAppBridge("theme"));
53
+ renderHook(() => useMcpAppContext("theme"));
50
54
  await waitFor(() => {
51
55
  expect(postMessageMock).toHaveBeenCalledWith(expect.objectContaining({
52
56
  jsonrpc: "2.0",
@@ -59,4 +63,4 @@ describe("useMcpAppBridge", () => {
59
63
  });
60
64
  });
61
65
  });
62
- //# sourceMappingURL=use-mcp-app-bridge.test.js.map
66
+ //# sourceMappingURL=use-mcp-app-context.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use-mcp-app-context.test.js","sourceRoot":"","sources":["../../../../src/web/bridges/mcp-app/use-mcp-app-context.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,4BAA4B,EAC5B,kBAAkB,GACnB,MAAM,2BAA2B,CAAC;AACnC,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AAE5D,QAAQ,CAAC,kBAAkB,EAAE,GAAG,EAAE;IAChC,UAAU,CAAC,KAAK,IAAI,EAAE;QACpB,EAAE,CAAC,UAAU,CAAC,WAAW,EAAE,EAAE,QAAQ,EAAE,SAAS,EAAE,CAAC,CAAC;QACpD,EAAE,CAAC,UAAU,CAAC,gBAAgB,EAAE,kBAAkB,CAAC,CAAC;QACpD,YAAY,CAAC,aAAa,EAAE,CAAC;IAC/B,CAAC,CAAC,CAAC;IAEH,SAAS,CAAC,GAAG,EAAE;QACb,EAAE,CAAC,gBAAgB,EAAE,CAAC;QACtB,EAAE,CAAC,aAAa,EAAE,CAAC;IACrB,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,4EAA4E,EAAE,KAAK,IAAI,EAAE;QAC1F,EAAE,CAAC,UAAU,CAAC,QAAQ,EAAE;YACtB,WAAW,EAAE,4BAA4B,CAAC,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC;SAC9D,CAAC,CAAC;QACH,MAAM,EAAE,MAAM,EAAE,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC,gBAAgB,CAAC,OAAO,CAAC,CAAC,CAAC;QAE/D,MAAM,OAAO,CAAC,GAAG,EAAE;YACjB,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QACvC,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,gBAAgB,CAAC,OAAO,EAAE,SAAS,EAAE,GAAG,CAAC,CAAC,CAAC;QAE5D,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;IAEH,EAAE,CAAC,uEAAuE,EAAE,KAAK,IAAI,EAAE;QACrF,oFAAoF;QACpF,MAAM,CAAC,cAAc,CAAC,QAAQ,CAAC,IAAI,EAAE,aAAa,EAAE;YAClD,KAAK,EAAE,GAAG;YACV,YAAY,EAAE,IAAI;SACnB,CAAC,CAAC;QACH,MAAM,CAAC,cAAc,CAAC,QAAQ,CAAC,IAAI,EAAE,cAAc,EAAE;YACnD,KAAK,EAAE,GAAG;YACV,YAAY,EAAE,IAAI;SACnB,CAAC,CAAC;QAEH,MAAM,eAAe,GAAG,4BAA4B,CAAC,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC,CAAC;QACzE,EAAE,CAAC,UAAU,CAAC,QAAQ,EAAE,EAAE,WAAW,EAAE,eAAe,EAAE,CAAC,CAAC;QAE1D,UAAU,CAAC,GAAG,EAAE,CAAC,gBAAgB,CAAC,OAAO,CAAC,CAAC,CAAC;QAE5C,MAAM,OAAO,CAAC,GAAG,EAAE;YACjB,MAAM,CAAC,eAAe,CAAC,CAAC,oBAAoB,CAC1C,MAAM,CAAC,gBAAgB,CAAC;gBACtB,OAAO,EAAE,KAAK;gBACd,MAAM,EAAE,+BAA+B;gBACvC,MAAM,EAAE,MAAM,CAAC,gBAAgB,CAAC;oBAC9B,KAAK,EAAE,MAAM,CAAC,GAAG,CAAC,MAAM,CAAC;oBACzB,MAAM,EAAE,MAAM,CAAC,GAAG,CAAC,MAAM,CAAC;iBAC3B,CAAC;aACH,CAAC,EACF,GAAG,CACJ,CAAC;QACJ,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
@@ -1,40 +1,59 @@
1
1
  import type { CallToolResult } from "@modelcontextprotocol/sdk/types.js";
2
2
  import type { useSyncExternalStore } from "react";
3
+ import type { WidgetHostType } from "../../server/index.js";
4
+ export type SkybridgeProperties = {
5
+ hostType: WidgetHostType;
6
+ serverUrl: string;
7
+ };
8
+ declare global {
9
+ interface Window {
10
+ skybridge: SkybridgeProperties;
11
+ }
12
+ }
3
13
  export type CallToolArgs = Record<string, unknown> | null;
4
14
  export type CallToolResponse = {
5
15
  content: CallToolResult["content"];
6
16
  structuredContent: NonNullable<CallToolResult["structuredContent"]>;
7
17
  isError: NonNullable<CallToolResult["isError"]>;
8
18
  result: string;
9
- _meta?: CallToolResult["_meta"];
19
+ meta?: CallToolResult["_meta"];
10
20
  };
11
21
  export type DisplayMode = "pip" | "inline" | "fullscreen" | "modal";
22
+ export type Theme = "light" | "dark";
12
23
  export type DeviceType = "mobile" | "tablet" | "desktop" | "unknown";
13
- export interface BridgeInterface {
14
- theme: "light" | "dark";
15
- locale: string;
16
- displayMode: DisplayMode;
17
- safeArea: {
18
- insets: {
19
- top: number;
20
- right: number;
21
- bottom: number;
22
- left: number;
23
- };
24
+ export type SafeAreaInsets = {
25
+ top: number;
26
+ right: number;
27
+ bottom: number;
28
+ left: number;
29
+ };
30
+ export type SafeArea = {
31
+ insets: SafeAreaInsets;
32
+ };
33
+ export type UserAgent = {
34
+ device: {
35
+ type: DeviceType;
24
36
  };
25
- maxHeight: number;
26
- userAgent: {
27
- device: {
28
- type: DeviceType;
29
- };
30
- capabilities: {
31
- hover: boolean;
32
- touch: boolean;
33
- };
37
+ capabilities: {
38
+ hover: boolean;
39
+ touch: boolean;
34
40
  };
41
+ };
42
+ export interface HostContext {
43
+ theme: Theme;
44
+ locale: string;
45
+ displayMode: DisplayMode;
46
+ safeArea: SafeArea;
47
+ maxHeight: number | undefined;
48
+ userAgent: UserAgent;
35
49
  toolInput: Record<string, unknown> | null;
36
50
  toolOutput: Record<string, unknown> | null;
37
51
  toolResponseMetadata: Record<string, unknown> | null;
52
+ view: {
53
+ mode: DisplayMode;
54
+ params?: Record<string, unknown>;
55
+ };
56
+ widgetState: Record<string, unknown> | null;
38
57
  }
39
58
  export type Subscribe = Parameters<typeof useSyncExternalStore>[0];
40
59
  export interface Bridge<Context> {
@@ -42,16 +61,38 @@ export interface Bridge<Context> {
42
61
  subscribe(keys: readonly (keyof Context)[]): Subscribe;
43
62
  getSnapshot<K extends keyof Context>(key: K): Context[K] | undefined;
44
63
  }
45
- export type ExternalStore<K extends keyof BridgeInterface> = {
64
+ export type HostContextStore<K extends keyof HostContext> = {
46
65
  subscribe: Subscribe;
47
- getSnapshot: () => BridgeInterface[K];
66
+ getSnapshot: () => HostContext[K];
67
+ };
68
+ export type WidgetState = Record<string, unknown>;
69
+ export type SetWidgetStateAction = WidgetState | ((prevState: WidgetState | null) => WidgetState);
70
+ export type FileMetadata = {
71
+ fileId: string;
72
+ };
73
+ export type RequestModalOptions = {
74
+ title?: string;
75
+ params?: Record<string, unknown>;
76
+ anchor?: {
77
+ top?: number;
78
+ left?: number;
79
+ width?: number;
80
+ height?: number;
81
+ };
48
82
  };
49
83
  export interface Adaptor {
50
- getExternalStore<K extends keyof BridgeInterface>(key: K): ExternalStore<K>;
84
+ getHostContextStore<K extends keyof HostContext>(key: K): HostContextStore<K>;
51
85
  callTool<ToolArgs extends CallToolArgs = null, ToolResponse extends CallToolResponse = CallToolResponse>(name: string, args: ToolArgs): Promise<ToolResponse>;
52
86
  requestDisplayMode(mode: DisplayMode): Promise<{
53
87
  mode: DisplayMode;
54
88
  }>;
55
89
  sendFollowUpMessage(prompt: string): Promise<void>;
56
90
  openExternal(href: string): void;
91
+ setWidgetState(stateOrUpdater: SetWidgetStateAction): Promise<void>;
92
+ uploadFile(file: File): Promise<FileMetadata>;
93
+ getFileDownloadUrl(file: FileMetadata): Promise<{
94
+ downloadUrl: string;
95
+ }>;
96
+ openModal(options: RequestModalOptions): void;
97
+ setOpenInAppUrl(href: string): Promise<void>;
57
98
  }
@@ -0,0 +1,2 @@
1
+ import type { HostContext } from "./types.js";
2
+ export declare const useHostContext: <K extends keyof HostContext>(key: K) => HostContext[K];
@@ -0,0 +1,8 @@
1
+ import { useSyncExternalStore } from "react";
2
+ import { getAdaptor } from "./get-adaptor.js";
3
+ export const useHostContext = (key) => {
4
+ const adaptor = getAdaptor();
5
+ const store = adaptor.getHostContextStore(key);
6
+ return useSyncExternalStore(store.subscribe, store.getSnapshot);
7
+ };
8
+ //# sourceMappingURL=use-host-context.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use-host-context.js","sourceRoot":"","sources":["../../../src/web/bridges/use-host-context.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,MAAM,OAAO,CAAC;AAC7C,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAG9C,MAAM,CAAC,MAAM,cAAc,GAAG,CAC5B,GAAM,EACU,EAAE;IAClB,MAAM,OAAO,GAAG,UAAU,EAAE,CAAC;IAC7B,MAAM,KAAK,GAAG,OAAO,CAAC,mBAAmB,CAAC,GAAG,CAAC,CAAC;IAE/C,OAAO,oBAAoB,CAAC,KAAK,CAAC,SAAS,EAAE,KAAK,CAAC,WAAW,CAAC,CAAC;AAClE,CAAC,CAAC"}
@@ -0,0 +1,4 @@
1
+ import { type ReactNode } from "react";
2
+ export declare function ModalProvider({ children }: {
3
+ children: ReactNode;
4
+ }): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,47 @@
1
+ import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useEffect, useSyncExternalStore } from "react";
3
+ import { McpAppAdaptor } from "../bridges";
4
+ const modalStyles = `
5
+ .sb-modal-backdrop {
6
+ position: fixed;
7
+ inset: 0;
8
+ background: rgba(0, 0, 0, 0.5);
9
+ z-index: 9998;
10
+ }
11
+ .sb-modal-container {
12
+ border-radius: 12px;
13
+ position: fixed;
14
+ inset: 0;
15
+ margin: auto;
16
+ width: fit-content;
17
+ height: fit-content;
18
+ background: white;
19
+ z-index: 9999;
20
+ }
21
+ `;
22
+ export function ModalProvider({ children }) {
23
+ const adaptor = McpAppAdaptor.getInstance();
24
+ const { mode } = useSyncExternalStore(adaptor.getHostContextStore("view").subscribe, adaptor.getHostContextStore("view").getSnapshot);
25
+ const isOpen = mode === "modal";
26
+ const handleBackdropClick = (e) => {
27
+ if (e.target === e.currentTarget) {
28
+ adaptor.closeModal();
29
+ }
30
+ };
31
+ useEffect(() => {
32
+ if (!isOpen) {
33
+ return;
34
+ }
35
+ const handler = (e) => {
36
+ if (e.key === "Escape") {
37
+ adaptor.closeModal();
38
+ }
39
+ };
40
+ document.addEventListener("keydown", handler);
41
+ return () => document.removeEventListener("keydown", handler);
42
+ }, [isOpen, adaptor]);
43
+ return (_jsxs(_Fragment, { children: [_jsx("style", { children: modalStyles }), isOpen && (
44
+ // biome-ignore lint/a11y/useKeyWithClickEvents: backdrop isn't focusable
45
+ _jsx("div", { role: "dialog", className: "sb-modal-backdrop", onClick: handleBackdropClick })), _jsx("div", { className: isOpen ? "sb-modal-container" : undefined, children: children })] }));
46
+ }
47
+ //# sourceMappingURL=modal-provider.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"modal-provider.js","sourceRoot":"","sources":["../../../src/web/components/modal-provider.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAkB,SAAS,EAAE,oBAAoB,EAAE,MAAM,OAAO,CAAC;AACxE,OAAO,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAE3C,MAAM,WAAW,GAAG;;;;;;;;;;;;;;;;;CAiBnB,CAAC;AAEF,MAAM,UAAU,aAAa,CAAC,EAAE,QAAQ,EAA2B;IACjE,MAAM,OAAO,GAAG,aAAa,CAAC,WAAW,EAAE,CAAC;IAE5C,MAAM,EAAE,IAAI,EAAE,GAAG,oBAAoB,CACnC,OAAO,CAAC,mBAAmB,CAAC,MAAM,CAAC,CAAC,SAAS,EAC7C,OAAO,CAAC,mBAAmB,CAAC,MAAM,CAAC,CAAC,WAAW,CAChD,CAAC;IACF,MAAM,MAAM,GAAG,IAAI,KAAK,OAAO,CAAC;IAEhC,MAAM,mBAAmB,GAAG,CAAC,CAAmB,EAAE,EAAE;QAClD,IAAI,CAAC,CAAC,MAAM,KAAK,CAAC,CAAC,aAAa,EAAE,CAAC;YACjC,OAAO,CAAC,UAAU,EAAE,CAAC;QACvB,CAAC;IACH,CAAC,CAAC;IAEF,SAAS,CAAC,GAAG,EAAE;QACb,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,OAAO;QACT,CAAC;QACD,MAAM,OAAO,GAAG,CAAC,CAAgB,EAAE,EAAE;YACnC,IAAI,CAAC,CAAC,GAAG,KAAK,QAAQ,EAAE,CAAC;gBACvB,OAAO,CAAC,UAAU,EAAE,CAAC;YACvB,CAAC;QACH,CAAC,CAAC;QACF,QAAQ,CAAC,gBAAgB,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC;QAC9C,OAAO,GAAG,EAAE,CAAC,QAAQ,CAAC,mBAAmB,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC;IAChE,CAAC,EAAE,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;IAEtB,OAAO,CACL,8BACE,0BAAQ,WAAW,GAAS,EAC3B,MAAM,IAAI;YACT,yEAAyE;YACzE,cACE,IAAI,EAAC,QAAQ,EACb,SAAS,EAAC,mBAAmB,EAC7B,OAAO,EAAE,mBAAmB,GAC5B,CACH,EACD,cAAK,SAAS,EAAE,MAAM,CAAC,CAAC,CAAC,oBAAoB,CAAC,CAAC,CAAC,SAAS,YACtD,QAAQ,GACL,IACL,CACJ,CAAC;AACJ,CAAC"}
@@ -1,4 +1,5 @@
1
1
  import { create } from "zustand";
2
+ import { getAdaptor } from "./bridges/index.js";
2
3
  import { getInitialState, injectWidgetContext, serializeState, } from "./helpers/state.js";
3
4
  export function createStore(storeCreator, defaultState) {
4
5
  const initialState = getInitialState(defaultState);
@@ -10,13 +11,11 @@ export function createStore(storeCreator, defaultState) {
10
11
  return baseStore;
11
12
  });
12
13
  store.subscribe((state) => {
13
- if (window.openai) {
14
- const serializedState = serializeState(state);
15
- if (serializedState !== null && serializedState !== undefined) {
16
- const stateToPersist = injectWidgetContext(serializedState);
17
- if (stateToPersist !== null) {
18
- window.openai.setWidgetState(stateToPersist);
19
- }
14
+ const serializedState = serializeState(state);
15
+ if (serializedState !== null && serializedState !== undefined) {
16
+ const stateToPersist = injectWidgetContext(serializedState);
17
+ if (stateToPersist !== null) {
18
+ getAdaptor().setWidgetState(stateToPersist);
20
19
  }
21
20
  }
22
21
  });
@@ -1 +1 @@
1
- {"version":3,"file":"create-store.js","sourceRoot":"","sources":["../../src/web/create-store.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAqB,MAAM,SAAS,CAAC;AACpD,OAAO,EACL,eAAe,EACf,mBAAmB,EACnB,cAAc,GACf,MAAM,oBAAoB,CAAC;AAG5B,MAAM,UAAU,WAAW,CACzB,YAAgD,EAChD,YAAoC;IAEpC,MAAM,YAAY,GAAG,eAAe,CAAC,YAAY,CAAC,CAAC;IAEnD,MAAM,KAAK,GAAG,MAAM,EAAS,CAC3B,CAAC,GAAG,IAAoD,EAAE,EAAE;QAC1D,MAAM,SAAS,GAAG,YAAY,CAAC,GAAG,IAAI,CAAC,CAAC;QAExC,IAAI,YAAY,KAAK,IAAI,EAAE,CAAC;YAC1B,OAAO,EAAE,GAAG,SAAS,EAAE,GAAG,YAAY,EAAE,CAAC;QAC3C,CAAC;QAED,OAAO,SAAS,CAAC;IACnB,CAAC,CACF,CAAC;IAEF,KAAK,CAAC,SAAS,CAAC,CAAC,KAAY,EAAE,EAAE;QAC/B,IAAI,MAAM,CAAC,MAAM,EAAE,CAAC;YAClB,MAAM,eAAe,GAAG,cAAc,CAAC,KAAK,CAAC,CAAC;YAC9C,IAAI,eAAe,KAAK,IAAI,IAAI,eAAe,KAAK,SAAS,EAAE,CAAC;gBAC9D,MAAM,cAAc,GAAG,mBAAmB,CAAC,eAAwB,CAAC,CAAC;gBACrE,IAAI,cAAc,KAAK,IAAI,EAAE,CAAC;oBAC5B,MAAM,CAAC,MAAM,CAAC,cAAc,CAAC,cAAc,CAAC,CAAC;gBAC/C,CAAC;YACH,CAAC;QACH,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,OAAO,KAAK,CAAC;AACf,CAAC"}
1
+ {"version":3,"file":"create-store.js","sourceRoot":"","sources":["../../src/web/create-store.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAqB,MAAM,SAAS,CAAC;AACpD,OAAO,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAChD,OAAO,EACL,eAAe,EACf,mBAAmB,EACnB,cAAc,GACf,MAAM,oBAAoB,CAAC;AAG5B,MAAM,UAAU,WAAW,CACzB,YAAgD,EAChD,YAAoC;IAEpC,MAAM,YAAY,GAAG,eAAe,CAAC,YAAY,CAAC,CAAC;IAEnD,MAAM,KAAK,GAAG,MAAM,EAAS,CAC3B,CAAC,GAAG,IAAoD,EAAE,EAAE;QAC1D,MAAM,SAAS,GAAG,YAAY,CAAC,GAAG,IAAI,CAAC,CAAC;QAExC,IAAI,YAAY,KAAK,IAAI,EAAE,CAAC;YAC1B,OAAO,EAAE,GAAG,SAAS,EAAE,GAAG,YAAY,EAAE,CAAC;QAC3C,CAAC;QAED,OAAO,SAAS,CAAC;IACnB,CAAC,CACF,CAAC;IAEF,KAAK,CAAC,SAAS,CAAC,CAAC,KAAY,EAAE,EAAE;QAC/B,MAAM,eAAe,GAAG,cAAc,CAAC,KAAK,CAAC,CAAC;QAC9C,IAAI,eAAe,KAAK,IAAI,IAAI,eAAe,KAAK,SAAS,EAAE,CAAC;YAC9D,MAAM,cAAc,GAAG,mBAAmB,CAAC,eAAwB,CAAC,CAAC;YACrE,IAAI,cAAc,KAAK,IAAI,EAAE,CAAC;gBAC5B,UAAU,EAAE,CAAC,cAAc,CAAC,cAAc,CAAC,CAAC;YAC9C,CAAC;QACH,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,OAAO,KAAK,CAAC;AACf,CAAC"}
@@ -1,70 +1,126 @@
1
1
  import { afterEach, beforeEach, describe, expect, it, vi, } from "vitest";
2
+ import { McpAppAdaptor } from "./bridges/mcp-app/adaptor.js";
3
+ import { McpAppBridge } from "./bridges/mcp-app/bridge.js";
2
4
  import { createStore } from "./create-store.js";
3
5
  import { WIDGET_CONTEXT_KEY } from "./data-llm.js";
6
+ import { getMcpAppHostPostMessageMock, MockResizeObserver, } from "./hooks/test/utils.js";
4
7
  describe("createStore", () => {
5
- let OpenaiMock;
6
- beforeEach(() => {
7
- OpenaiMock = {
8
- widgetState: null,
9
- setWidgetState: vi.fn().mockResolvedValue(undefined),
10
- };
11
- vi.stubGlobal("openai", OpenaiMock);
12
- });
13
8
  afterEach(() => {
14
9
  vi.unstubAllGlobals();
15
10
  vi.resetAllMocks();
16
11
  });
17
- it("should create a store without default state", () => {
18
- const storeCreator = () => ({
19
- count: 0,
12
+ describe("apps-sdk mode", () => {
13
+ let OpenaiMock;
14
+ beforeEach(() => {
15
+ OpenaiMock = {
16
+ widgetState: null,
17
+ setWidgetState: vi.fn().mockResolvedValue(undefined),
18
+ };
19
+ vi.stubGlobal("openai", OpenaiMock);
20
+ vi.stubGlobal("skybridge", { hostType: "apps-sdk" });
20
21
  });
21
- const store = createStore(storeCreator);
22
- expect(store.getState()).toEqual({ count: 0 });
23
- });
24
- it("should create a store with default state", () => {
25
- const storeCreator = () => ({
26
- count: 0,
27
- name: "initial",
22
+ it("should create a store without default state", () => {
23
+ const storeCreator = () => ({
24
+ count: 0,
25
+ });
26
+ const store = createStore(storeCreator);
27
+ expect(store.getState()).toEqual({ count: 0 });
28
28
  });
29
- const defaultState = { count: 5, name: "default" };
30
- const store = createStore(storeCreator, defaultState);
31
- expect(store.getState()).toEqual({ count: 5, name: "default" });
32
- });
33
- it("should initialize from window.openai.widgetState when available", () => {
34
- const storeCreator = () => ({
35
- count: 0,
36
- name: "initial",
29
+ it("should create a store with default state", () => {
30
+ const storeCreator = () => ({
31
+ count: 0,
32
+ name: "initial",
33
+ });
34
+ const defaultState = { count: 5, name: "default" };
35
+ const store = createStore(storeCreator, defaultState);
36
+ expect(store.getState()).toEqual({ count: 5, name: "default" });
37
37
  });
38
- const windowState = { count: 20, name: "window" };
39
- OpenaiMock.widgetState = windowState;
40
- const store = createStore(storeCreator);
41
- expect(store.getState()).toEqual({ count: 20, name: "window" });
42
- });
43
- it("should persist state changes to window.openai.setWidgetState", async () => {
44
- const storeCreator = (set) => ({
45
- count: 0,
46
- increment: () => set((state) => ({ count: state.count + 1 })),
38
+ it("should initialize from window.openai.widgetState when available", () => {
39
+ const storeCreator = () => ({
40
+ count: 0,
41
+ name: "initial",
42
+ });
43
+ const windowState = { count: 20, name: "window" };
44
+ OpenaiMock.widgetState = windowState;
45
+ const store = createStore(storeCreator);
46
+ expect(store.getState()).toEqual({ count: 20, name: "window" });
47
+ });
48
+ it("should persist state changes to window.openai.setWidgetState", async () => {
49
+ const storeCreator = (set) => ({
50
+ count: 0,
51
+ increment: () => set((state) => ({ count: state.count + 1 })),
52
+ });
53
+ const store = createStore(storeCreator);
54
+ store.getState().increment();
55
+ await vi.waitFor(() => {
56
+ expect(OpenaiMock.setWidgetState).toHaveBeenCalled();
57
+ });
58
+ const callArgs = OpenaiMock.setWidgetState.mock.calls[0]?.[0];
59
+ expect(callArgs).toEqual({ count: 1 });
47
60
  });
48
- const store = createStore(storeCreator);
49
- store.getState().increment();
50
- await vi.waitFor(() => {
51
- expect(OpenaiMock.setWidgetState).toHaveBeenCalled();
61
+ it("should filter widget context from initial state", () => {
62
+ const storeCreator = () => ({
63
+ count: 0,
64
+ });
65
+ const windowState = {
66
+ count: 5,
67
+ [WIDGET_CONTEXT_KEY]: "context-value",
68
+ };
69
+ OpenaiMock.widgetState = windowState;
70
+ const store = createStore(storeCreator);
71
+ expect(store.getState()).toEqual({ count: 5 });
72
+ expect(store.getState()[WIDGET_CONTEXT_KEY]).toBeUndefined();
52
73
  });
53
- const callArgs = OpenaiMock.setWidgetState.mock.calls[0]?.[0];
54
- expect(callArgs).toEqual({ count: 1 });
55
74
  });
56
- it("should filter widget context from initial state", () => {
57
- const storeCreator = () => ({
58
- count: 0,
75
+ describe("mcp-app mode", () => {
76
+ beforeEach(() => {
77
+ vi.stubGlobal("skybridge", { hostType: "mcp-app" });
78
+ vi.stubGlobal("ResizeObserver", MockResizeObserver);
79
+ });
80
+ afterEach(() => {
81
+ McpAppBridge.resetInstance();
82
+ McpAppAdaptor.resetInstance();
83
+ });
84
+ it("should initialize with null widgetState", () => {
85
+ const adaptor = McpAppAdaptor.getInstance();
86
+ const widgetState = adaptor
87
+ .getHostContextStore("widgetState")
88
+ .getSnapshot();
89
+ expect(widgetState).toBeNull();
90
+ });
91
+ it("should create a store with default state when no persisted state exists", () => {
92
+ const storeCreator = () => ({
93
+ count: 0,
94
+ });
95
+ const store = createStore(storeCreator);
96
+ expect(store.getState()).toEqual({ count: 0 });
97
+ });
98
+ it("should update in-memory state via setWidgetState", async () => {
99
+ const adaptor = McpAppAdaptor.getInstance();
100
+ vi.spyOn(adaptor, "setWidgetState").mockResolvedValue(undefined);
101
+ const storeCreator = (set) => ({
102
+ count: 0,
103
+ increment: () => set((state) => ({ count: state.count + 1 })),
104
+ });
105
+ const store = createStore(storeCreator);
106
+ store.getState().increment();
107
+ await vi.waitFor(() => {
108
+ expect(adaptor.setWidgetState).toHaveBeenCalledWith({ count: 1 });
109
+ });
110
+ });
111
+ it("should notify listeners when widget state changes", async () => {
112
+ const postMessageMock = getMcpAppHostPostMessageMock();
113
+ vi.stubGlobal("parent", { postMessage: postMessageMock });
114
+ const adaptor = McpAppAdaptor.getInstance();
115
+ const listener = vi.fn();
116
+ adaptor.getHostContextStore("widgetState").subscribe(listener);
117
+ await adaptor.setWidgetState({ count: 42 });
118
+ expect(postMessageMock).toHaveBeenCalledWith(expect.objectContaining({ method: "ui/update-model-context" }), "*");
119
+ expect(listener).toHaveBeenCalled();
120
+ expect(adaptor.getHostContextStore("widgetState").getSnapshot()).toEqual({
121
+ count: 42,
122
+ });
59
123
  });
60
- const windowState = {
61
- count: 5,
62
- [WIDGET_CONTEXT_KEY]: "context-value",
63
- };
64
- OpenaiMock.widgetState = windowState;
65
- const store = createStore(storeCreator);
66
- expect(store.getState()).toEqual({ count: 5 });
67
- expect(store.getState()[WIDGET_CONTEXT_KEY]).toBeUndefined();
68
124
  });
69
125
  });
70
126
  //# sourceMappingURL=create-store.test.js.map