skybridge 0.0.0-dev.df0cfdd → 0.0.0-dev.df1e961

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 (233) hide show
  1. package/README.md +7 -7
  2. package/dist/cli/build-helpers.d.ts +1 -1
  3. package/dist/cli/build-helpers.js +4 -4
  4. package/dist/cli/build-helpers.js.map +1 -1
  5. package/dist/cli/build-helpers.test.js +2 -2
  6. package/dist/cli/build-helpers.test.js.map +1 -1
  7. package/dist/cli/build-steps.js +1 -1
  8. package/dist/cli/build-steps.js.map +1 -1
  9. package/dist/cli/detect-port.js +0 -1
  10. package/dist/cli/detect-port.js.map +1 -1
  11. package/dist/cli/use-execute-steps.d.ts +1 -1
  12. package/dist/cli/use-nodemon.js +11 -3
  13. package/dist/cli/use-nodemon.js.map +1 -1
  14. package/dist/cli/use-typescript-check.js +1 -1
  15. package/dist/cli/use-typescript-check.js.map +1 -1
  16. package/dist/commands/dev.js +1 -1
  17. package/dist/commands/dev.js.map +1 -1
  18. package/dist/commands/start.js +2 -2
  19. package/dist/commands/start.js.map +1 -1
  20. package/dist/server/app.d.ts +194 -0
  21. package/dist/server/app.js +266 -0
  22. package/dist/server/app.js.map +1 -0
  23. package/dist/server/app.test.js +97 -0
  24. package/dist/server/app.test.js.map +1 -0
  25. package/dist/server/auth/discovery.d.ts +2 -1
  26. package/dist/server/auth/discovery.js +2 -2
  27. package/dist/server/auth/discovery.js.map +1 -1
  28. package/dist/server/auth/index.d.ts +21 -17
  29. package/dist/server/auth/index.js.map +1 -1
  30. package/dist/server/auth/providers/auth0.d.ts +2 -2
  31. package/dist/server/auth/providers/auth0.js +13 -8
  32. package/dist/server/auth/providers/auth0.js.map +1 -1
  33. package/dist/server/auth/providers/auth0.test.js +1 -1
  34. package/dist/server/auth/providers/auth0.test.js.map +1 -1
  35. package/dist/server/auth/providers/authplane.d.ts +2 -2
  36. package/dist/server/auth/providers/authplane.js.map +1 -1
  37. package/dist/server/auth/providers/authplane.test.js +10 -7
  38. package/dist/server/auth/providers/authplane.test.js.map +1 -1
  39. package/dist/server/auth/providers/clerk.d.ts +2 -2
  40. package/dist/server/auth/providers/clerk.js.map +1 -1
  41. package/dist/server/auth/providers/clerk.test.js +1 -1
  42. package/dist/server/auth/providers/clerk.test.js.map +1 -1
  43. package/dist/server/auth/providers/custom.d.ts +4 -4
  44. package/dist/server/auth/providers/custom.js +5 -2
  45. package/dist/server/auth/providers/custom.js.map +1 -1
  46. package/dist/server/auth/providers/custom.test.js +13 -10
  47. package/dist/server/auth/providers/custom.test.js.map +1 -1
  48. package/dist/server/auth/providers/descope.d.ts +2 -2
  49. package/dist/server/auth/providers/descope.js.map +1 -1
  50. package/dist/server/auth/providers/descope.test.js +3 -3
  51. package/dist/server/auth/providers/descope.test.js.map +1 -1
  52. package/dist/server/auth/providers/stytch.d.ts +2 -2
  53. package/dist/server/auth/providers/stytch.js.map +1 -1
  54. package/dist/server/auth/providers/workos.d.ts +2 -2
  55. package/dist/server/auth/providers/workos.js.map +1 -1
  56. package/dist/server/auth/setup.d.ts +1 -1
  57. package/dist/server/auth/setup.js +3 -4
  58. package/dist/server/auth/setup.js.map +1 -1
  59. package/dist/server/auth/setup.test.js +83 -77
  60. package/dist/server/auth/setup.test.js.map +1 -1
  61. package/dist/server/auth/verify.js +2 -2
  62. package/dist/server/auth/verify.js.map +1 -1
  63. package/dist/server/auth-extra.test-d.js +97 -49
  64. package/dist/server/auth-extra.test-d.js.map +1 -1
  65. package/dist/server/auth.d.ts +7 -8
  66. package/dist/server/auth.js +4 -5
  67. package/dist/server/auth.js.map +1 -1
  68. package/dist/server/build-manifest.test.js +7 -6
  69. package/dist/server/build-manifest.test.js.map +1 -1
  70. package/dist/server/content-helpers.d.ts +1 -1
  71. package/dist/server/content-helpers.js.map +1 -1
  72. package/dist/server/express.d.ts +23 -3
  73. package/dist/server/express.js +38 -32
  74. package/dist/server/express.js.map +1 -1
  75. package/dist/server/express.test.js +220 -103
  76. package/dist/server/express.test.js.map +1 -1
  77. package/dist/server/file-ref.d.ts +1 -1
  78. package/dist/server/file-ref.js +1 -1
  79. package/dist/server/file-ref.js.map +1 -1
  80. package/dist/server/index.d.ts +6 -3
  81. package/dist/server/index.js +3 -1
  82. package/dist/server/index.js.map +1 -1
  83. package/dist/server/mcp-errors.test.js +41 -0
  84. package/dist/server/mcp-errors.test.js.map +1 -0
  85. package/dist/server/middleware.d.ts +6 -6
  86. package/dist/server/middleware.js.map +1 -1
  87. package/dist/server/middleware.test-d.js +1 -1
  88. package/dist/server/middleware.test-d.js.map +1 -1
  89. package/dist/server/middleware.test.js +222 -150
  90. package/dist/server/middleware.test.js.map +1 -1
  91. package/dist/server/register-tool.test.d.ts +1 -0
  92. package/dist/server/register-tool.test.js +27 -0
  93. package/dist/server/register-tool.test.js.map +1 -0
  94. package/dist/server/server.d.ts +74 -122
  95. package/dist/server/server.js +101 -302
  96. package/dist/server/server.js.map +1 -1
  97. package/dist/server/skills-integration.test.js +19 -12
  98. package/dist/server/skills-integration.test.js.map +1 -1
  99. package/dist/server/skills.d.ts +3 -5
  100. package/dist/server/skills.js +17 -24
  101. package/dist/server/skills.js.map +1 -1
  102. package/dist/server/skills.test.js +8 -12
  103. package/dist/server/skills.test.js.map +1 -1
  104. package/dist/server/templateHelper.d.ts +0 -3
  105. package/dist/server/templateHelper.js.map +1 -1
  106. package/dist/server/templates.generated.js +4 -8
  107. package/dist/server/templates.generated.js.map +1 -1
  108. package/dist/server/tool-extra.test.d.ts +1 -0
  109. package/dist/server/tool-extra.test.js +88 -0
  110. package/dist/server/tool-extra.test.js.map +1 -0
  111. package/dist/server/view-resource-resolution.test.js +18 -13
  112. package/dist/server/view-resource-resolution.test.js.map +1 -1
  113. package/dist/test/utils.d.ts +9 -11
  114. package/dist/test/utils.js +220 -201
  115. package/dist/test/utils.js.map +1 -1
  116. package/dist/test/view.test.js +25 -37
  117. package/dist/test/view.test.js.map +1 -1
  118. package/dist/views/index.d.ts +10 -0
  119. package/dist/views/index.js +3 -0
  120. package/dist/views/index.js.map +1 -0
  121. package/dist/views/scan-views.d.ts +16 -0
  122. package/dist/views/scan-views.js +88 -0
  123. package/dist/views/scan-views.js.map +1 -0
  124. package/dist/views/scan-views.test.d.ts +1 -0
  125. package/dist/views/scan-views.test.js +99 -0
  126. package/dist/views/scan-views.test.js.map +1 -0
  127. package/dist/views/validate-view.d.ts +1 -0
  128. package/dist/views/validate-view.js +9 -0
  129. package/dist/views/validate-view.js.map +1 -0
  130. package/dist/views/validate-view.test.d.ts +1 -0
  131. package/dist/views/validate-view.test.js +24 -0
  132. package/dist/views/validate-view.test.js.map +1 -0
  133. package/dist/web/bridges/adaptor.test.js +1 -1
  134. package/dist/web/bridges/adaptor.test.js.map +1 -1
  135. package/dist/web/bridges/apps-sdk/use-apps-sdk-context.d.ts +1 -1
  136. package/dist/web/bridges/apps-sdk/use-apps-sdk-context.js +1 -1
  137. package/dist/web/bridges/apps-sdk/use-apps-sdk-context.js.map +1 -1
  138. package/dist/web/bridges/get-adaptor.test.js +2 -2
  139. package/dist/web/bridges/get-adaptor.test.js.map +1 -1
  140. package/dist/web/bridges/mcp-app/bridge.js +1 -1
  141. package/dist/web/bridges/mcp-app/bridge.js.map +1 -1
  142. package/dist/web/bridges/mcp-app/bridge.test.js +2 -2
  143. package/dist/web/bridges/mcp-app/bridge.test.js.map +1 -1
  144. package/dist/web/bridges/mcp-app/use-mcp-app-context.d.ts +1 -1
  145. package/dist/web/bridges/mcp-app/use-mcp-app-context.js +1 -1
  146. package/dist/web/bridges/mcp-app/use-mcp-app-context.js.map +1 -1
  147. package/dist/web/bridges/mcp-app/use-mcp-app-context.test.js +1 -1
  148. package/dist/web/bridges/mcp-app/use-mcp-app-context.test.js.map +1 -1
  149. package/dist/web/bridges/mcp-app/view-tools.test.js +1 -1
  150. package/dist/web/bridges/mcp-app/view-tools.test.js.map +1 -1
  151. package/dist/web/bridges/types.d.ts +17 -12
  152. package/dist/web/bridges/types.js.map +1 -1
  153. package/dist/web/create-store.test.js +2 -2
  154. package/dist/web/create-store.test.js.map +1 -1
  155. package/dist/web/data-llm.test.js +2 -2
  156. package/dist/web/data-llm.test.js.map +1 -1
  157. package/dist/web/generate-helpers.d.ts +22 -18
  158. package/dist/web/generate-helpers.js +19 -15
  159. package/dist/web/generate-helpers.js.map +1 -1
  160. package/dist/web/generate-helpers.test-d.js +3 -3
  161. package/dist/web/generate-helpers.test-d.js.map +1 -1
  162. package/dist/web/generate-helpers.test.js +2 -2
  163. package/dist/web/generate-helpers.test.js.map +1 -1
  164. package/dist/web/hooks/index.d.ts +2 -2
  165. package/dist/web/hooks/index.js +2 -2
  166. package/dist/web/hooks/index.js.map +1 -1
  167. package/dist/web/hooks/use-call-tool.test.js +2 -2
  168. package/dist/web/hooks/use-call-tool.test.js.map +1 -1
  169. package/dist/web/hooks/use-display-mode.d.ts +1 -1
  170. package/dist/web/hooks/use-display-mode.js +1 -1
  171. package/dist/web/hooks/use-display-mode.js.map +1 -1
  172. package/dist/web/hooks/use-display-mode.test.js +1 -1
  173. package/dist/web/hooks/use-display-mode.test.js.map +1 -1
  174. package/dist/web/hooks/use-download.d.ts +1 -3
  175. package/dist/web/hooks/use-download.js +1 -2
  176. package/dist/web/hooks/use-download.js.map +1 -1
  177. package/dist/web/hooks/use-download.test.js +7 -7
  178. package/dist/web/hooks/use-download.test.js.map +1 -1
  179. package/dist/web/hooks/use-files.test.js +1 -1
  180. package/dist/web/hooks/use-files.test.js.map +1 -1
  181. package/dist/web/hooks/{use-host-info.d.ts → use-host.d.ts} +2 -2
  182. package/dist/web/hooks/{use-host-info.js → use-host.js} +3 -3
  183. package/dist/web/hooks/use-host.js.map +1 -0
  184. package/dist/web/hooks/use-host.test.d.ts +1 -0
  185. package/dist/web/hooks/{use-host-info.test.js → use-host.test.js} +7 -7
  186. package/dist/web/hooks/use-host.test.js.map +1 -0
  187. package/dist/web/hooks/use-open-external.test.js +2 -2
  188. package/dist/web/hooks/use-open-external.test.js.map +1 -1
  189. package/dist/web/hooks/use-register-view-tool.d.ts +2 -3
  190. package/dist/web/hooks/use-register-view-tool.js.map +1 -1
  191. package/dist/web/hooks/use-request-close.test.js +1 -1
  192. package/dist/web/hooks/use-request-close.test.js.map +1 -1
  193. package/dist/web/hooks/use-request-modal.test.js +1 -1
  194. package/dist/web/hooks/use-request-modal.test.js.map +1 -1
  195. package/dist/web/hooks/use-request-size.d.ts +1 -1
  196. package/dist/web/hooks/use-request-size.js +1 -1
  197. package/dist/web/hooks/use-request-size.js.map +1 -1
  198. package/dist/web/hooks/use-request-size.test.js +1 -1
  199. package/dist/web/hooks/use-request-size.test.js.map +1 -1
  200. package/dist/web/hooks/use-set-open-in-app-url.test.js +2 -8
  201. package/dist/web/hooks/use-set-open-in-app-url.test.js.map +1 -1
  202. package/dist/web/hooks/use-tool-info.d.ts +1 -20
  203. package/dist/web/hooks/use-tool-info.js +0 -1
  204. package/dist/web/hooks/use-tool-info.js.map +1 -1
  205. package/dist/web/hooks/use-tool-info.test-d.js +0 -5
  206. package/dist/web/hooks/use-tool-info.test-d.js.map +1 -1
  207. package/dist/web/hooks/use-tool-info.test.js +2 -7
  208. package/dist/web/hooks/use-tool-info.test.js.map +1 -1
  209. package/dist/web/hooks/use-user.d.ts +3 -2
  210. package/dist/web/hooks/use-user.js +4 -3
  211. package/dist/web/hooks/use-user.js.map +1 -1
  212. package/dist/web/hooks/use-user.test.js +5 -3
  213. package/dist/web/hooks/use-user.test.js.map +1 -1
  214. package/dist/web/hooks/use-view-state.test.js +2 -2
  215. package/dist/web/hooks/use-view-state.test.js.map +1 -1
  216. package/dist/web/hooks/use-viewport.d.ts +20 -0
  217. package/dist/web/hooks/use-viewport.js +21 -0
  218. package/dist/web/hooks/use-viewport.js.map +1 -0
  219. package/dist/web/hooks/use-viewport.test.d.ts +1 -0
  220. package/dist/web/hooks/{use-layout.test.js → use-viewport.test.js} +12 -32
  221. package/dist/web/hooks/use-viewport.test.js.map +1 -0
  222. package/dist/web/mount-view.d.ts +3 -2
  223. package/dist/web/mount-view.js +5 -8
  224. package/dist/web/mount-view.js.map +1 -1
  225. package/package.json +15 -8
  226. package/dist/web/hooks/use-host-info.js.map +0 -1
  227. package/dist/web/hooks/use-host-info.test.js.map +0 -1
  228. package/dist/web/hooks/use-layout.d.ts +0 -24
  229. package/dist/web/hooks/use-layout.js +0 -25
  230. package/dist/web/hooks/use-layout.js.map +0 -1
  231. package/dist/web/hooks/use-layout.test.js.map +0 -1
  232. /package/dist/{web/hooks/use-host-info.test.d.ts → server/app.test.d.ts} +0 -0
  233. /package/dist/{web/hooks/use-layout.test.d.ts → server/mcp-errors.test.d.ts} +0 -0
@@ -3,18 +3,18 @@ import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
3
3
  import { HostAdaptor } from "../bridges/adaptor.js";
4
4
  import { McpAppBridge } from "../bridges/mcp-app/bridge.js";
5
5
  import { getMcpAppHostPostMessageMock, MockResizeObserver, } from "./test/utils.js";
6
- import { useHostInfo } from "./use-host-info.js";
6
+ import { useHost } from "./use-host.js";
7
7
  const stubHost = (hostInfo) => {
8
8
  vi.stubGlobal("parent", {
9
9
  postMessage: getMcpAppHostPostMessageMock({}, { hostInfo }),
10
10
  });
11
11
  };
12
- describe("useHostInfo", () => {
12
+ describe("useHost", () => {
13
13
  beforeEach(() => {
14
14
  HostAdaptor.resetInstance();
15
15
  McpAppBridge.resetInstance();
16
16
  vi.stubGlobal("openai", undefined);
17
- vi.stubGlobal("skybridge", { hostType: "mcp-app" });
17
+ vi.stubGlobal("skybridge", {});
18
18
  vi.stubGlobal("ResizeObserver", MockResizeObserver);
19
19
  });
20
20
  afterEach(() => {
@@ -25,7 +25,7 @@ describe("useHostInfo", () => {
25
25
  });
26
26
  it("is undefined before the handshake resolves, then populated after", async () => {
27
27
  stubHost({ name: "Claude", version: "1.2.3" });
28
- const { result } = renderHook(() => useHostInfo());
28
+ const { result } = renderHook(() => useHost());
29
29
  expect(result.current.name).toBeUndefined();
30
30
  expect(result.current.version).toBeUndefined();
31
31
  await waitFor(() => {
@@ -42,18 +42,18 @@ describe("useHostInfo", () => {
42
42
  ["alpic-playground", "alpic"],
43
43
  ])("normalizes reported name %j to slug %j", async (reported, slug) => {
44
44
  stubHost({ name: reported, version: "1.0.0" });
45
- const { result } = renderHook(() => useHostInfo());
45
+ const { result } = renderHook(() => useHost());
46
46
  await waitFor(() => {
47
47
  expect(result.current.name).toBe(slug);
48
48
  });
49
49
  });
50
50
  it("preserves an unrecognized reported name as-is", async () => {
51
51
  stubHost({ name: "Some Future Host", version: "9.9.9" });
52
- const { result } = renderHook(() => useHostInfo());
52
+ const { result } = renderHook(() => useHost());
53
53
  await waitFor(() => {
54
54
  expect(result.current.name).toBe("Some Future Host");
55
55
  expect(result.current.version).toBe("9.9.9");
56
56
  });
57
57
  });
58
58
  });
59
- //# sourceMappingURL=use-host-info.test.js.map
59
+ //# sourceMappingURL=use-host.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use-host.test.js","sourceRoot":"","sources":["../../../src/web/hooks/use-host.test.ts"],"names":[],"mappings":"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","sourcesContent":["import { renderHook, waitFor } from \"@testing-library/react\";\nimport { afterEach, beforeEach, describe, expect, it, vi } from \"vitest\";\nimport { HostAdaptor } from \"../bridges/adaptor.js\";\nimport { McpAppBridge } from \"../bridges/mcp-app/bridge.js\";\nimport {\n getMcpAppHostPostMessageMock,\n MockResizeObserver,\n} from \"./test/utils.js\";\nimport { type Host, useHost } from \"./use-host.js\";\n\nconst stubHost = (hostInfo?: { name: string; version: string }) => {\n vi.stubGlobal(\"parent\", {\n postMessage: getMcpAppHostPostMessageMock({}, { hostInfo }),\n });\n};\n\ndescribe(\"useHost\", () => {\n beforeEach(() => {\n HostAdaptor.resetInstance();\n McpAppBridge.resetInstance();\n vi.stubGlobal(\"openai\", undefined);\n vi.stubGlobal(\"skybridge\", {});\n vi.stubGlobal(\"ResizeObserver\", MockResizeObserver);\n });\n\n afterEach(() => {\n vi.unstubAllGlobals();\n vi.resetAllMocks();\n McpAppBridge.resetInstance();\n HostAdaptor.resetInstance();\n });\n\n it(\"is undefined before the handshake resolves, then populated after\", async () => {\n stubHost({ name: \"Claude\", version: \"1.2.3\" });\n const { result } = renderHook(() => useHost());\n\n expect(result.current.name).toBeUndefined();\n expect(result.current.version).toBeUndefined();\n\n await waitFor(() => {\n expect(result.current.name).toBe(\"claude\");\n expect(result.current.version).toBe(\"1.2.3\");\n });\n });\n\n it.each<[string, Host]>([\n [\"chatgpt\", \"chatgpt\"],\n [\"Claude\", \"claude\"],\n [\"Cursor\", \"cursor\"],\n [\"MCP-UI Host\", \"goose\"],\n [\"Le Chat\", \"mistral-vibe\"],\n [\"alpic-playground\", \"alpic\"],\n ])(\"normalizes reported name %j to slug %j\", async (reported, slug) => {\n stubHost({ name: reported, version: \"1.0.0\" });\n const { result } = renderHook(() => useHost());\n\n await waitFor(() => {\n expect(result.current.name).toBe(slug);\n });\n });\n\n it(\"preserves an unrecognized reported name as-is\", async () => {\n stubHost({ name: \"Some Future Host\", version: \"9.9.9\" });\n const { result } = renderHook(() => useHost());\n\n await waitFor(() => {\n expect(result.current.name).toBe(\"Some Future Host\");\n expect(result.current.version).toBe(\"9.9.9\");\n });\n });\n});\n"]}
@@ -13,7 +13,7 @@ describe("useOpenExternal", () => {
13
13
  vi.stubGlobal("openai", {
14
14
  openExternal: openExternalMock,
15
15
  });
16
- vi.stubGlobal("skybridge", { hostType: "apps-sdk" });
16
+ vi.stubGlobal("skybridge", {});
17
17
  vi.stubGlobal("ResizeObserver", MockResizeObserver);
18
18
  postMessageMock = getMcpAppHostPostMessageMock();
19
19
  vi.stubGlobal("parent", { postMessage: postMessageMock });
@@ -47,7 +47,7 @@ describe("useOpenExternal", () => {
47
47
  let postMessageMock;
48
48
  beforeEach(() => {
49
49
  vi.stubGlobal("openai", undefined);
50
- vi.stubGlobal("skybridge", { hostType: "mcp-app" });
50
+ vi.stubGlobal("skybridge", {});
51
51
  vi.stubGlobal("ResizeObserver", MockResizeObserver);
52
52
  postMessageMock = getMcpAppHostPostMessageMock();
53
53
  vi.stubGlobal("parent", { postMessage: postMessageMock });
@@ -1 +1 @@
1
- {"version":3,"file":"use-open-external.test.js","sourceRoot":"","sources":["../../../src/web/hooks/use-open-external.test.ts"],"names":[],"mappings":"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","sourcesContent":["import { renderHook, waitFor } from \"@testing-library/react\";\nimport { afterEach, beforeEach, describe, expect, it, vi } from \"vitest\";\nimport { HostAdaptor } from \"../bridges/adaptor.js\";\nimport { McpAppBridge } from \"../bridges/mcp-app/bridge.js\";\nimport {\n getMcpAppHostPostMessageMock,\n MockResizeObserver,\n} from \"./test/utils.js\";\nimport { useOpenExternal } from \"./use-open-external.js\";\n\ndescribe(\"useOpenExternal\", () => {\n describe(\"apps-sdk host\", () => {\n let openExternalMock: ReturnType<typeof vi.fn>;\n let postMessageMock: ReturnType<typeof getMcpAppHostPostMessageMock>;\n\n beforeEach(() => {\n openExternalMock = vi.fn();\n vi.stubGlobal(\"openai\", {\n openExternal: openExternalMock,\n });\n vi.stubGlobal(\"skybridge\", { hostType: \"apps-sdk\" });\n vi.stubGlobal(\"ResizeObserver\", MockResizeObserver);\n postMessageMock = getMcpAppHostPostMessageMock();\n vi.stubGlobal(\"parent\", { postMessage: postMessageMock });\n });\n\n afterEach(() => {\n HostAdaptor.resetInstance();\n McpAppBridge.resetInstance();\n vi.unstubAllGlobals();\n vi.resetAllMocks();\n });\n\n it(\"should call window.openai.openExternal even without a redirectUrl option\", () => {\n const { result } = renderHook(() => useOpenExternal());\n\n const href = \"https://example.com\";\n result.current(href);\n\n expect(openExternalMock).toHaveBeenCalledTimes(1);\n expect(openExternalMock).toHaveBeenCalledWith({ href });\n expect(postMessageMock).not.toHaveBeenCalledWith(\n expect.objectContaining({ method: \"ui/open-link\" }),\n \"*\",\n );\n });\n\n it(\"should call window.openai.openExternal when redirectUrl is false\", () => {\n const { result } = renderHook(() => useOpenExternal());\n\n const href = \"https://example.com\";\n result.current(href, { redirectUrl: false });\n\n expect(openExternalMock).toHaveBeenCalledTimes(1);\n expect(openExternalMock).toHaveBeenCalledWith({\n href,\n redirectUrl: false,\n });\n });\n });\n\n describe(\"mcp-app host\", () => {\n let postMessageMock: ReturnType<typeof getMcpAppHostPostMessageMock>;\n\n beforeEach(() => {\n vi.stubGlobal(\"openai\", undefined);\n vi.stubGlobal(\"skybridge\", { hostType: \"mcp-app\" });\n vi.stubGlobal(\"ResizeObserver\", MockResizeObserver);\n postMessageMock = getMcpAppHostPostMessageMock();\n vi.stubGlobal(\"parent\", { postMessage: postMessageMock });\n });\n\n afterEach(async () => {\n HostAdaptor.resetInstance();\n McpAppBridge.resetInstance();\n vi.unstubAllGlobals();\n vi.resetAllMocks();\n });\n\n it(\"should return a function that sends ui/open-link request to the MCP host\", async () => {\n const { result } = renderHook(() => useOpenExternal());\n\n const href = \"https://example.com\";\n result.current(href, { redirectUrl: false });\n\n await waitFor(() => {\n expect(postMessageMock).toHaveBeenCalledWith(\n expect.objectContaining({\n jsonrpc: \"2.0\",\n method: \"ui/open-link\",\n params: { url: href },\n }),\n \"*\",\n );\n });\n });\n });\n});\n"]}
1
+ {"version":3,"file":"use-open-external.test.js","sourceRoot":"","sources":["../../../src/web/hooks/use-open-external.test.ts"],"names":[],"mappings":"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","sourcesContent":["import { renderHook, waitFor } from \"@testing-library/react\";\nimport { afterEach, beforeEach, describe, expect, it, vi } from \"vitest\";\nimport { HostAdaptor } from \"../bridges/adaptor.js\";\nimport { McpAppBridge } from \"../bridges/mcp-app/bridge.js\";\nimport {\n getMcpAppHostPostMessageMock,\n MockResizeObserver,\n} from \"./test/utils.js\";\nimport { useOpenExternal } from \"./use-open-external.js\";\n\ndescribe(\"useOpenExternal\", () => {\n describe(\"apps-sdk host\", () => {\n let openExternalMock: ReturnType<typeof vi.fn>;\n let postMessageMock: ReturnType<typeof getMcpAppHostPostMessageMock>;\n\n beforeEach(() => {\n openExternalMock = vi.fn();\n vi.stubGlobal(\"openai\", {\n openExternal: openExternalMock,\n });\n vi.stubGlobal(\"skybridge\", {});\n vi.stubGlobal(\"ResizeObserver\", MockResizeObserver);\n postMessageMock = getMcpAppHostPostMessageMock();\n vi.stubGlobal(\"parent\", { postMessage: postMessageMock });\n });\n\n afterEach(() => {\n HostAdaptor.resetInstance();\n McpAppBridge.resetInstance();\n vi.unstubAllGlobals();\n vi.resetAllMocks();\n });\n\n it(\"should call window.openai.openExternal even without a redirectUrl option\", () => {\n const { result } = renderHook(() => useOpenExternal());\n\n const href = \"https://example.com\";\n result.current(href);\n\n expect(openExternalMock).toHaveBeenCalledTimes(1);\n expect(openExternalMock).toHaveBeenCalledWith({ href });\n expect(postMessageMock).not.toHaveBeenCalledWith(\n expect.objectContaining({ method: \"ui/open-link\" }),\n \"*\",\n );\n });\n\n it(\"should call window.openai.openExternal when redirectUrl is false\", () => {\n const { result } = renderHook(() => useOpenExternal());\n\n const href = \"https://example.com\";\n result.current(href, { redirectUrl: false });\n\n expect(openExternalMock).toHaveBeenCalledTimes(1);\n expect(openExternalMock).toHaveBeenCalledWith({\n href,\n redirectUrl: false,\n });\n });\n });\n\n describe(\"mcp-app host\", () => {\n let postMessageMock: ReturnType<typeof getMcpAppHostPostMessageMock>;\n\n beforeEach(() => {\n vi.stubGlobal(\"openai\", undefined);\n vi.stubGlobal(\"skybridge\", {});\n vi.stubGlobal(\"ResizeObserver\", MockResizeObserver);\n postMessageMock = getMcpAppHostPostMessageMock();\n vi.stubGlobal(\"parent\", { postMessage: postMessageMock });\n });\n\n afterEach(async () => {\n HostAdaptor.resetInstance();\n McpAppBridge.resetInstance();\n vi.unstubAllGlobals();\n vi.resetAllMocks();\n });\n\n it(\"should return a function that sends ui/open-link request to the MCP host\", async () => {\n const { result } = renderHook(() => useOpenExternal());\n\n const href = \"https://example.com\";\n result.current(href, { redirectUrl: false });\n\n await waitFor(() => {\n expect(postMessageMock).toHaveBeenCalledWith(\n expect.objectContaining({\n jsonrpc: \"2.0\",\n method: \"ui/open-link\",\n params: { url: href },\n }),\n \"*\",\n );\n });\n });\n });\n});\n"]}
@@ -1,5 +1,4 @@
1
- import type { ZodRawShapeCompat } from "@modelcontextprotocol/sdk/server/zod-compat.js";
2
- import type { ViewToolConfig, ViewToolHandler } from "../bridges/types.js";
1
+ import type { ViewToolConfig, ViewToolHandler, ViewToolInputShape } from "../bridges/types.js";
3
2
  /**
4
3
  * Register a tool the view exposes to the host and model — the MCP Apps
5
4
  * "app-provided tools" feature. A view tool runs *inside the view*: the host
@@ -35,4 +34,4 @@ import type { ViewToolConfig, ViewToolHandler } from "../bridges/types.js";
35
34
  *
36
35
  * @see https://docs.skybridge.tech/api-reference/use-register-view-tool
37
36
  */
38
- export declare const useRegisterViewTool: <TInput extends ZodRawShapeCompat = ZodRawShapeCompat>(config: ViewToolConfig<TInput>, handler: ViewToolHandler<TInput>) => void;
37
+ export declare const useRegisterViewTool: <TInput extends ViewToolInputShape = ViewToolInputShape>(config: ViewToolConfig<TInput>, handler: ViewToolHandler<TInput>) => void;
@@ -1 +1 @@
1
- {"version":3,"file":"use-register-view-tool.js","sourceRoot":"","sources":["../../../src/web/hooks/use-register-view-tool.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,OAAO,CAAC;AAC1C,OAAO,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAOjD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AACH,MAAM,CAAC,MAAM,mBAAmB,GAAG,CAGjC,MAA8B,EAC9B,OAAgC,EAChC,EAAE;IACF,MAAM,EAAE,IAAI,EAAE,GAAG,MAAM,CAAC;IACxB,MAAM,SAAS,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC;IACjC,SAAS,CAAC,OAAO,GAAG,MAAM,CAAC;IAC3B,MAAM,UAAU,GAAG,MAAM,CAAC,OAAO,CAAC,CAAC;IACnC,UAAU,CAAC,OAAO,GAAG,OAAO,CAAC;IAE7B,SAAS,CAAC,GAAG,EAAE;QACb,MAAM,OAAO,GAAG,UAAU,EAAE,CAAC;QAC7B,MAAM,cAAc,GAAuB,CAAC,IAAI,EAAE,EAAE,CAClD,UAAU,CAAC,OAAO,CAAC,IAA8C,CAAC,CAAC;QAErE,OAAO,OAAO,CAAC,gBAAgB,CAC7B,EAAE,GAAG,SAAS,CAAC,OAAO,EAAE,IAAI,EAAE,EAC9B,cAAc,CACf,CAAC;IACJ,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC;AACb,CAAC,CAAC","sourcesContent":["import type { ZodRawShapeCompat } from \"@modelcontextprotocol/sdk/server/zod-compat.js\";\nimport { useEffect, useRef } from \"react\";\nimport { getAdaptor } from \"../bridges/index.js\";\nimport type {\n AnyViewToolHandler,\n ViewToolConfig,\n ViewToolHandler,\n} from \"../bridges/types.js\";\n\n/**\n * Register a tool the view exposes to the host and model — the MCP Apps\n * \"app-provided tools\" feature. A view tool runs *inside the view*: the host\n * discovers it via `tools/list` and invokes it via `tools/call`, and the\n * handler executes against the view's live state. It is the inverse of\n * {@link useCallTool} (which calls a server tool). Registered on mount, removed\n * on unmount; re-registered when `config.name` changes.\n *\n * MCP Apps only — on the Apps SDK (`window.openai`) runtime it is a no-op.\n *\n * @example\n * ```tsx\n * import * as z from \"zod\";\n * import { useRegisterViewTool } from \"skybridge/web\";\n *\n * useRegisterViewTool(\n * {\n * name: \"chess_make_move\",\n * description: \"Play a move in algebraic notation, e.g. 'e4' or 'Nf3'.\",\n * inputSchema: { san: z.string() },\n * annotations: { readOnlyHint: false },\n * },\n * ({ san }) => {\n * const move = game.move(san);\n * return {\n * content: [{ type: \"text\", text: move ? `Played ${move.san}` : \"Illegal move\" }],\n * structuredContent: { fen: game.fen() },\n * isError: !move,\n * };\n * },\n * );\n * ```\n *\n * @see https://docs.skybridge.tech/api-reference/use-register-view-tool\n */\nexport const useRegisterViewTool = <\n TInput extends ZodRawShapeCompat = ZodRawShapeCompat,\n>(\n config: ViewToolConfig<TInput>,\n handler: ViewToolHandler<TInput>,\n) => {\n const { name } = config;\n const configRef = useRef(config);\n configRef.current = config;\n const handlerRef = useRef(handler);\n handlerRef.current = handler;\n\n useEffect(() => {\n const adaptor = getAdaptor();\n const wrappedHandler: AnyViewToolHandler = (args) =>\n handlerRef.current(args as Parameters<ViewToolHandler<TInput>>[0]);\n\n return adaptor.registerViewTool(\n { ...configRef.current, name },\n wrappedHandler,\n );\n }, [name]);\n};\n"]}
1
+ {"version":3,"file":"use-register-view-tool.js","sourceRoot":"","sources":["../../../src/web/hooks/use-register-view-tool.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,OAAO,CAAC;AAC1C,OAAO,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAQjD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AACH,MAAM,CAAC,MAAM,mBAAmB,GAAG,CAGjC,MAA8B,EAC9B,OAAgC,EAChC,EAAE;IACF,MAAM,EAAE,IAAI,EAAE,GAAG,MAAM,CAAC;IACxB,MAAM,SAAS,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC;IACjC,SAAS,CAAC,OAAO,GAAG,MAAM,CAAC;IAC3B,MAAM,UAAU,GAAG,MAAM,CAAC,OAAO,CAAC,CAAC;IACnC,UAAU,CAAC,OAAO,GAAG,OAAO,CAAC;IAE7B,SAAS,CAAC,GAAG,EAAE;QACb,MAAM,OAAO,GAAG,UAAU,EAAE,CAAC;QAC7B,MAAM,cAAc,GAAuB,CAAC,IAAI,EAAE,EAAE,CAClD,UAAU,CAAC,OAAO,CAAC,IAA8C,CAAC,CAAC;QAErE,OAAO,OAAO,CAAC,gBAAgB,CAC7B,EAAE,GAAG,SAAS,CAAC,OAAO,EAAE,IAAI,EAAE,EAC9B,cAAc,CACf,CAAC;IACJ,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC;AACb,CAAC,CAAC","sourcesContent":["import { useEffect, useRef } from \"react\";\nimport { getAdaptor } from \"../bridges/index.js\";\nimport type {\n AnyViewToolHandler,\n ViewToolConfig,\n ViewToolHandler,\n ViewToolInputShape,\n} from \"../bridges/types.js\";\n\n/**\n * Register a tool the view exposes to the host and model — the MCP Apps\n * \"app-provided tools\" feature. A view tool runs *inside the view*: the host\n * discovers it via `tools/list` and invokes it via `tools/call`, and the\n * handler executes against the view's live state. It is the inverse of\n * {@link useCallTool} (which calls a server tool). Registered on mount, removed\n * on unmount; re-registered when `config.name` changes.\n *\n * MCP Apps only — on the Apps SDK (`window.openai`) runtime it is a no-op.\n *\n * @example\n * ```tsx\n * import * as z from \"zod\";\n * import { useRegisterViewTool } from \"skybridge/web\";\n *\n * useRegisterViewTool(\n * {\n * name: \"chess_make_move\",\n * description: \"Play a move in algebraic notation, e.g. 'e4' or 'Nf3'.\",\n * inputSchema: { san: z.string() },\n * annotations: { readOnlyHint: false },\n * },\n * ({ san }) => {\n * const move = game.move(san);\n * return {\n * content: [{ type: \"text\", text: move ? `Played ${move.san}` : \"Illegal move\" }],\n * structuredContent: { fen: game.fen() },\n * isError: !move,\n * };\n * },\n * );\n * ```\n *\n * @see https://docs.skybridge.tech/api-reference/use-register-view-tool\n */\nexport const useRegisterViewTool = <\n TInput extends ViewToolInputShape = ViewToolInputShape,\n>(\n config: ViewToolConfig<TInput>,\n handler: ViewToolHandler<TInput>,\n) => {\n const { name } = config;\n const configRef = useRef(config);\n configRef.current = config;\n const handlerRef = useRef(handler);\n handlerRef.current = handler;\n\n useEffect(() => {\n const adaptor = getAdaptor();\n const wrappedHandler: AnyViewToolHandler = (args) =>\n handlerRef.current(args as Parameters<ViewToolHandler<TInput>>[0]);\n\n return adaptor.registerViewTool(\n { ...configRef.current, name },\n wrappedHandler,\n );\n }, [name]);\n};\n"]}
@@ -8,7 +8,7 @@ describe("useRequestClose", () => {
8
8
  beforeEach(() => {
9
9
  HostAdaptor.resetInstance();
10
10
  McpAppBridge.resetInstance();
11
- vi.stubGlobal("skybridge", { hostType: "mcp-app" });
11
+ vi.stubGlobal("skybridge", {});
12
12
  vi.stubGlobal("openai", undefined);
13
13
  vi.stubGlobal("parent", { postMessage: vi.fn() });
14
14
  });
@@ -1 +1 @@
1
- {"version":3,"file":"use-request-close.test.js","sourceRoot":"","sources":["../../../src/web/hooks/use-request-close.test.ts"],"names":[],"mappings":"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","sourcesContent":["import { act, renderHook } from \"@testing-library/react\";\nimport { afterEach, beforeEach, describe, expect, it, vi } from \"vitest\";\nimport { HostAdaptor } from \"../bridges/adaptor.js\";\nimport { getAdaptor } from \"../bridges/get-adaptor.js\";\nimport { McpAppBridge } from \"../bridges/mcp-app/bridge.js\";\nimport { useRequestClose } from \"./use-request-close.js\";\n\ndescribe(\"useRequestClose\", () => {\n beforeEach(() => {\n HostAdaptor.resetInstance();\n McpAppBridge.resetInstance();\n vi.stubGlobal(\"skybridge\", { hostType: \"mcp-app\" });\n vi.stubGlobal(\"openai\", undefined);\n vi.stubGlobal(\"parent\", { postMessage: vi.fn() });\n });\n\n afterEach(() => {\n vi.unstubAllGlobals();\n vi.resetAllMocks();\n HostAdaptor.resetInstance();\n McpAppBridge.resetInstance();\n });\n\n it(\"calls app.requestTeardown via the MCP path\", async () => {\n const requestTeardown = vi.fn().mockResolvedValue(undefined);\n // biome-ignore lint/suspicious/noExplicitAny: test seam\n const adaptor = getAdaptor() as any;\n adaptor.mcp.getApp = vi.fn().mockResolvedValue({ requestTeardown });\n\n const { result } = renderHook(() => useRequestClose());\n await act(async () => {\n await result.current();\n });\n\n expect(requestTeardown).toHaveBeenCalledTimes(1);\n });\n\n it(\"calls app.requestTeardown even when window.openai is present\", async () => {\n vi.stubGlobal(\"openai\", { requestClose: vi.fn() });\n HostAdaptor.resetInstance();\n McpAppBridge.resetInstance();\n\n const requestTeardown = vi.fn().mockResolvedValue(undefined);\n // biome-ignore lint/suspicious/noExplicitAny: test seam\n const adaptor = getAdaptor() as any;\n adaptor.mcp.getApp = vi.fn().mockResolvedValue({ requestTeardown });\n\n const { result } = renderHook(() => useRequestClose());\n await act(async () => {\n await result.current();\n });\n\n expect(requestTeardown).toHaveBeenCalledTimes(1);\n });\n});\n"]}
1
+ {"version":3,"file":"use-request-close.test.js","sourceRoot":"","sources":["../../../src/web/hooks/use-request-close.test.ts"],"names":[],"mappings":"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","sourcesContent":["import { act, renderHook } from \"@testing-library/react\";\nimport { afterEach, beforeEach, describe, expect, it, vi } from \"vitest\";\nimport { HostAdaptor } from \"../bridges/adaptor.js\";\nimport { getAdaptor } from \"../bridges/get-adaptor.js\";\nimport { McpAppBridge } from \"../bridges/mcp-app/bridge.js\";\nimport { useRequestClose } from \"./use-request-close.js\";\n\ndescribe(\"useRequestClose\", () => {\n beforeEach(() => {\n HostAdaptor.resetInstance();\n McpAppBridge.resetInstance();\n vi.stubGlobal(\"skybridge\", {});\n vi.stubGlobal(\"openai\", undefined);\n vi.stubGlobal(\"parent\", { postMessage: vi.fn() });\n });\n\n afterEach(() => {\n vi.unstubAllGlobals();\n vi.resetAllMocks();\n HostAdaptor.resetInstance();\n McpAppBridge.resetInstance();\n });\n\n it(\"calls app.requestTeardown via the MCP path\", async () => {\n const requestTeardown = vi.fn().mockResolvedValue(undefined);\n // biome-ignore lint/suspicious/noExplicitAny: test seam\n const adaptor = getAdaptor() as any;\n adaptor.mcp.getApp = vi.fn().mockResolvedValue({ requestTeardown });\n\n const { result } = renderHook(() => useRequestClose());\n await act(async () => {\n await result.current();\n });\n\n expect(requestTeardown).toHaveBeenCalledTimes(1);\n });\n\n it(\"calls app.requestTeardown even when window.openai is present\", async () => {\n vi.stubGlobal(\"openai\", { requestClose: vi.fn() });\n HostAdaptor.resetInstance();\n McpAppBridge.resetInstance();\n\n const requestTeardown = vi.fn().mockResolvedValue(undefined);\n // biome-ignore lint/suspicious/noExplicitAny: test seam\n const adaptor = getAdaptor() as any;\n adaptor.mcp.getApp = vi.fn().mockResolvedValue({ requestTeardown });\n\n const { result } = renderHook(() => useRequestClose());\n await act(async () => {\n await result.current();\n });\n\n expect(requestTeardown).toHaveBeenCalledTimes(1);\n });\n});\n"]}
@@ -11,7 +11,7 @@ describe("useRequestModal", () => {
11
11
  McpAppBridge.resetInstance();
12
12
  AppsSdkBridge.resetInstance();
13
13
  requestModalMock = vi.fn();
14
- vi.stubGlobal("skybridge", { hostType: "apps-sdk" });
14
+ vi.stubGlobal("skybridge", {});
15
15
  vi.stubGlobal("parent", { postMessage: vi.fn() });
16
16
  vi.stubGlobal("openai", {
17
17
  requestModal: requestModalMock,
@@ -1 +1 @@
1
- {"version":3,"file":"use-request-modal.test.js","sourceRoot":"","sources":["../../../src/web/hooks/use-request-modal.test.ts"],"names":[],"mappings":"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","sourcesContent":["import { renderHook } from \"@testing-library/react\";\nimport { afterEach, beforeEach, describe, expect, it, vi } from \"vitest\";\nimport { HostAdaptor } from \"../bridges/adaptor.js\";\nimport { AppsSdkBridge } from \"../bridges/apps-sdk/bridge.js\";\nimport { McpAppBridge } from \"../bridges/mcp-app/bridge.js\";\nimport { useRequestModal } from \"./use-request-modal.js\";\n\ndescribe(\"useRequestModal\", () => {\n let requestModalMock: ReturnType<typeof vi.fn>;\n\n beforeEach(() => {\n HostAdaptor.resetInstance();\n McpAppBridge.resetInstance();\n AppsSdkBridge.resetInstance();\n requestModalMock = vi.fn();\n vi.stubGlobal(\"skybridge\", { hostType: \"apps-sdk\" });\n vi.stubGlobal(\"parent\", { postMessage: vi.fn() });\n vi.stubGlobal(\"openai\", {\n requestModal: requestModalMock,\n view: { mode: \"inline\" },\n });\n });\n\n afterEach(() => {\n vi.unstubAllGlobals();\n vi.resetAllMocks();\n HostAdaptor.resetInstance();\n McpAppBridge.resetInstance();\n AppsSdkBridge.resetInstance();\n });\n\n it(\"should return an object with open, isOpen, and params properties where isOpen is false when mode is not modal\", () => {\n const { result } = renderHook(() => useRequestModal());\n\n expect(typeof result.current).toBe(\"object\");\n expect(result.current).toHaveProperty(\"open\");\n expect(result.current).toHaveProperty(\"isOpen\");\n expect(result.current).toHaveProperty(\"params\");\n\n const { open, isOpen, params } = result.current;\n expect(typeof open).toBe(\"function\");\n expect(isOpen).toBe(false);\n expect(params).toBeUndefined();\n });\n\n it(\"should return isOpen as true when mode is modal\", () => {\n vi.stubGlobal(\"openai\", {\n requestModal: requestModalMock,\n view: { mode: \"modal\" },\n });\n\n const { result } = renderHook(() => useRequestModal());\n const { isOpen } = result.current;\n\n expect(isOpen).toBe(true);\n });\n\n it(\"should return params from view when available\", () => {\n const testParams = { foo: \"bar\", baz: 42 };\n vi.stubGlobal(\"openai\", {\n requestModal: requestModalMock,\n view: { mode: \"modal\", params: testParams },\n });\n\n const { result } = renderHook(() => useRequestModal());\n const { params } = result.current;\n\n expect(params).toEqual(testParams);\n });\n\n it(\"should call window.openai.requestModal with the options when open is called\", () => {\n const { result } = renderHook(() => useRequestModal());\n const { open } = result.current;\n\n const options = {\n title: \"Test Modal\",\n params: { foo: \"bar\" },\n template: \"ui://view/modal-template.html\",\n };\n open(options);\n\n expect(requestModalMock).toHaveBeenCalledTimes(1);\n expect(requestModalMock).toHaveBeenCalledWith(options);\n });\n});\n"]}
1
+ {"version":3,"file":"use-request-modal.test.js","sourceRoot":"","sources":["../../../src/web/hooks/use-request-modal.test.ts"],"names":[],"mappings":"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","sourcesContent":["import { renderHook } from \"@testing-library/react\";\nimport { afterEach, beforeEach, describe, expect, it, vi } from \"vitest\";\nimport { HostAdaptor } from \"../bridges/adaptor.js\";\nimport { AppsSdkBridge } from \"../bridges/apps-sdk/bridge.js\";\nimport { McpAppBridge } from \"../bridges/mcp-app/bridge.js\";\nimport { useRequestModal } from \"./use-request-modal.js\";\n\ndescribe(\"useRequestModal\", () => {\n let requestModalMock: ReturnType<typeof vi.fn>;\n\n beforeEach(() => {\n HostAdaptor.resetInstance();\n McpAppBridge.resetInstance();\n AppsSdkBridge.resetInstance();\n requestModalMock = vi.fn();\n vi.stubGlobal(\"skybridge\", {});\n vi.stubGlobal(\"parent\", { postMessage: vi.fn() });\n vi.stubGlobal(\"openai\", {\n requestModal: requestModalMock,\n view: { mode: \"inline\" },\n });\n });\n\n afterEach(() => {\n vi.unstubAllGlobals();\n vi.resetAllMocks();\n HostAdaptor.resetInstance();\n McpAppBridge.resetInstance();\n AppsSdkBridge.resetInstance();\n });\n\n it(\"should return an object with open, isOpen, and params properties where isOpen is false when mode is not modal\", () => {\n const { result } = renderHook(() => useRequestModal());\n\n expect(typeof result.current).toBe(\"object\");\n expect(result.current).toHaveProperty(\"open\");\n expect(result.current).toHaveProperty(\"isOpen\");\n expect(result.current).toHaveProperty(\"params\");\n\n const { open, isOpen, params } = result.current;\n expect(typeof open).toBe(\"function\");\n expect(isOpen).toBe(false);\n expect(params).toBeUndefined();\n });\n\n it(\"should return isOpen as true when mode is modal\", () => {\n vi.stubGlobal(\"openai\", {\n requestModal: requestModalMock,\n view: { mode: \"modal\" },\n });\n\n const { result } = renderHook(() => useRequestModal());\n const { isOpen } = result.current;\n\n expect(isOpen).toBe(true);\n });\n\n it(\"should return params from view when available\", () => {\n const testParams = { foo: \"bar\", baz: 42 };\n vi.stubGlobal(\"openai\", {\n requestModal: requestModalMock,\n view: { mode: \"modal\", params: testParams },\n });\n\n const { result } = renderHook(() => useRequestModal());\n const { params } = result.current;\n\n expect(params).toEqual(testParams);\n });\n\n it(\"should call window.openai.requestModal with the options when open is called\", () => {\n const { result } = renderHook(() => useRequestModal());\n const { open } = result.current;\n\n const options = {\n title: \"Test Modal\",\n params: { foo: \"bar\" },\n template: \"ui://view/modal-template.html\",\n };\n open(options);\n\n expect(requestModalMock).toHaveBeenCalledTimes(1);\n expect(requestModalMock).toHaveBeenCalledWith(options);\n });\n});\n"]}
@@ -3,7 +3,7 @@ import type { RequestSizeOptions } from "../bridges/types.js";
3
3
  export type RequestSizeFn = (size: RequestSizeOptions) => Promise<void>;
4
4
  /**
5
5
  * Ask the host to resize the view iframe. The applied size is host-driven —
6
- * the host decides whether and how to honor the request, and {@link useLayout}
6
+ * the host decides whether and how to honor the request, and {@link useViewport}
7
7
  * still reports the final `maxHeight` it allows.
8
8
  *
9
9
  * Pair with a `ResizeObserver` on your root element to react to content size
@@ -2,7 +2,7 @@ import { useCallback } from "react";
2
2
  import { getAdaptor } from "../bridges/index.js";
3
3
  /**
4
4
  * Ask the host to resize the view iframe. The applied size is host-driven —
5
- * the host decides whether and how to honor the request, and {@link useLayout}
5
+ * the host decides whether and how to honor the request, and {@link useViewport}
6
6
  * still reports the final `maxHeight` it allows.
7
7
  *
8
8
  * Pair with a `ResizeObserver` on your root element to react to content size
@@ -1 +1 @@
1
- {"version":3,"file":"use-request-size.js","sourceRoot":"","sources":["../../../src/web/hooks/use-request-size.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,OAAO,CAAC;AACpC,OAAO,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAMjD;;;;;;;;;;;;;;;GAeG;AACH,MAAM,UAAU,cAAc;IAC5B,MAAM,OAAO,GAAG,UAAU,EAAE,CAAC;IAC7B,MAAM,WAAW,GAAG,WAAW,CAC7B,CAAC,IAAwB,EAAE,EAAE,CAAC,OAAO,CAAC,WAAW,CAAC,IAAI,CAAC,EACvD,CAAC,OAAO,CAAC,CACV,CAAC;IAEF,OAAO,WAAW,CAAC;AACrB,CAAC","sourcesContent":["import { useCallback } from \"react\";\nimport { getAdaptor } from \"../bridges/index.js\";\nimport type { RequestSizeOptions } from \"../bridges/types.js\";\n\n/** Function that asks the host to resize the view, returned by {@link useRequestSize}. */\nexport type RequestSizeFn = (size: RequestSizeOptions) => Promise<void>;\n\n/**\n * Ask the host to resize the view iframe. The applied size is host-driven —\n * the host decides whether and how to honor the request, and {@link useLayout}\n * still reports the final `maxHeight` it allows.\n *\n * Pair with a `ResizeObserver` on your root element to react to content size\n * changes without hard-coded values.\n *\n * @example\n * ```tsx\n * const requestSize = useRequestSize();\n * useEffect(() => { requestSize({ height: rootRef.current!.scrollHeight }); }, [content]);\n * ```\n *\n * @see https://docs.skybridge.tech/api-reference/use-request-size\n */\nexport function useRequestSize(): RequestSizeFn {\n const adaptor = getAdaptor();\n const requestSize = useCallback(\n (size: RequestSizeOptions) => adaptor.requestSize(size),\n [adaptor],\n );\n\n return requestSize;\n}\n"]}
1
+ {"version":3,"file":"use-request-size.js","sourceRoot":"","sources":["../../../src/web/hooks/use-request-size.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,OAAO,CAAC;AACpC,OAAO,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAMjD;;;;;;;;;;;;;;;GAeG;AACH,MAAM,UAAU,cAAc;IAC5B,MAAM,OAAO,GAAG,UAAU,EAAE,CAAC;IAC7B,MAAM,WAAW,GAAG,WAAW,CAC7B,CAAC,IAAwB,EAAE,EAAE,CAAC,OAAO,CAAC,WAAW,CAAC,IAAI,CAAC,EACvD,CAAC,OAAO,CAAC,CACV,CAAC;IAEF,OAAO,WAAW,CAAC;AACrB,CAAC","sourcesContent":["import { useCallback } from \"react\";\nimport { getAdaptor } from \"../bridges/index.js\";\nimport type { RequestSizeOptions } from \"../bridges/types.js\";\n\n/** Function that asks the host to resize the view, returned by {@link useRequestSize}. */\nexport type RequestSizeFn = (size: RequestSizeOptions) => Promise<void>;\n\n/**\n * Ask the host to resize the view iframe. The applied size is host-driven —\n * the host decides whether and how to honor the request, and {@link useViewport}\n * still reports the final `maxHeight` it allows.\n *\n * Pair with a `ResizeObserver` on your root element to react to content size\n * changes without hard-coded values.\n *\n * @example\n * ```tsx\n * const requestSize = useRequestSize();\n * useEffect(() => { requestSize({ height: rootRef.current!.scrollHeight }); }, [content]);\n * ```\n *\n * @see https://docs.skybridge.tech/api-reference/use-request-size\n */\nexport function useRequestSize(): RequestSizeFn {\n const adaptor = getAdaptor();\n const requestSize = useCallback(\n (size: RequestSizeOptions) => adaptor.requestSize(size),\n [adaptor],\n );\n\n return requestSize;\n}\n"]}
@@ -9,7 +9,7 @@ describe("useRequestSize", () => {
9
9
  beforeEach(() => {
10
10
  HostAdaptor.resetInstance();
11
11
  McpAppBridge.resetInstance();
12
- vi.stubGlobal("skybridge", { hostType: "mcp-app" });
12
+ vi.stubGlobal("skybridge", {});
13
13
  vi.stubGlobal("openai", undefined);
14
14
  vi.stubGlobal("ResizeObserver", MockResizeObserver);
15
15
  postMessageMock = getMcpAppHostPostMessageMock();
@@ -1 +1 @@
1
- {"version":3,"file":"use-request-size.test.js","sourceRoot":"","sources":["../../../src/web/hooks/use-request-size.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,OAAO,EAAE,MAAM,wBAAwB,CAAC;AAC7D,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AACzE,OAAO,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AACpD,OAAO,EAAE,YAAY,EAAE,MAAM,8BAA8B,CAAC;AAC5D,OAAO,EACL,4BAA4B,EAC5B,kBAAkB,GACnB,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAEvD,QAAQ,CAAC,gBAAgB,EAAE,GAAG,EAAE;IAC9B,IAAI,eAAgE,CAAC;IAErE,UAAU,CAAC,GAAG,EAAE;QACd,WAAW,CAAC,aAAa,EAAE,CAAC;QAC5B,YAAY,CAAC,aAAa,EAAE,CAAC;QAC7B,EAAE,CAAC,UAAU,CAAC,WAAW,EAAE,EAAE,QAAQ,EAAE,SAAS,EAAE,CAAC,CAAC;QACpD,EAAE,CAAC,UAAU,CAAC,QAAQ,EAAE,SAAS,CAAC,CAAC;QACnC,EAAE,CAAC,UAAU,CAAC,gBAAgB,EAAE,kBAAkB,CAAC,CAAC;QACpD,eAAe,GAAG,4BAA4B,EAAE,CAAC;QACjD,EAAE,CAAC,UAAU,CAAC,QAAQ,EAAE,EAAE,WAAW,EAAE,eAAe,EAAE,CAAC,CAAC;IAC5D,CAAC,CAAC,CAAC;IAEH,SAAS,CAAC,GAAG,EAAE;QACb,EAAE,CAAC,gBAAgB,EAAE,CAAC;QACtB,EAAE,CAAC,aAAa,EAAE,CAAC;QACnB,WAAW,CAAC,aAAa,EAAE,CAAC;QAC5B,YAAY,CAAC,aAAa,EAAE,CAAC;IAC/B,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,0EAA0E,EAAE,KAAK,IAAI,EAAE;QACxF,MAAM,EAAE,MAAM,EAAE,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC,cAAc,EAAE,CAAC,CAAC;QAEtD,MAAM,MAAM,CAAC,OAAO,CAAC,EAAE,KAAK,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,CAAC;QAElD,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,EAAE,KAAK,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE;aACpC,CAAC,EACF,GAAG,CACJ,CAAC;QACJ,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,qCAAqC,EAAE,KAAK,IAAI,EAAE;QACnD,MAAM,EAAE,MAAM,EAAE,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC,cAAc,EAAE,CAAC,CAAC;QAEtD,MAAM,MAAM,CAAC,OAAO,CAAC,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,CAAC;QAEtC,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,EAAE,MAAM,EAAE,GAAG,EAAE;aACxB,CAAC,EACF,GAAG,CACJ,CAAC;QACJ,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC","sourcesContent":["import { renderHook, waitFor } from \"@testing-library/react\";\nimport { afterEach, beforeEach, describe, expect, it, vi } from \"vitest\";\nimport { HostAdaptor } from \"../bridges/adaptor.js\";\nimport { McpAppBridge } from \"../bridges/mcp-app/bridge.js\";\nimport {\n getMcpAppHostPostMessageMock,\n MockResizeObserver,\n} from \"./test/utils.js\";\nimport { useRequestSize } from \"./use-request-size.js\";\n\ndescribe(\"useRequestSize\", () => {\n let postMessageMock: ReturnType<typeof getMcpAppHostPostMessageMock>;\n\n beforeEach(() => {\n HostAdaptor.resetInstance();\n McpAppBridge.resetInstance();\n vi.stubGlobal(\"skybridge\", { hostType: \"mcp-app\" });\n vi.stubGlobal(\"openai\", undefined);\n vi.stubGlobal(\"ResizeObserver\", MockResizeObserver);\n postMessageMock = getMcpAppHostPostMessageMock();\n vi.stubGlobal(\"parent\", { postMessage: postMessageMock });\n });\n\n afterEach(() => {\n vi.unstubAllGlobals();\n vi.resetAllMocks();\n HostAdaptor.resetInstance();\n McpAppBridge.resetInstance();\n });\n\n it(\"sends a ui/notifications/size-changed notification with width and height\", async () => {\n const { result } = renderHook(() => useRequestSize());\n\n await result.current({ width: 800, height: 400 });\n\n await waitFor(() => {\n expect(postMessageMock).toHaveBeenCalledWith(\n expect.objectContaining({\n jsonrpc: \"2.0\",\n method: \"ui/notifications/size-changed\",\n params: { width: 800, height: 400 },\n }),\n \"*\",\n );\n });\n });\n\n it(\"forwards height-only payloads as-is\", async () => {\n const { result } = renderHook(() => useRequestSize());\n\n await result.current({ height: 400 });\n\n await waitFor(() => {\n expect(postMessageMock).toHaveBeenCalledWith(\n expect.objectContaining({\n jsonrpc: \"2.0\",\n method: \"ui/notifications/size-changed\",\n params: { height: 400 },\n }),\n \"*\",\n );\n });\n });\n});\n"]}
1
+ {"version":3,"file":"use-request-size.test.js","sourceRoot":"","sources":["../../../src/web/hooks/use-request-size.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,OAAO,EAAE,MAAM,wBAAwB,CAAC;AAC7D,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AACzE,OAAO,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AACpD,OAAO,EAAE,YAAY,EAAE,MAAM,8BAA8B,CAAC;AAC5D,OAAO,EACL,4BAA4B,EAC5B,kBAAkB,GACnB,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAEvD,QAAQ,CAAC,gBAAgB,EAAE,GAAG,EAAE;IAC9B,IAAI,eAAgE,CAAC;IAErE,UAAU,CAAC,GAAG,EAAE;QACd,WAAW,CAAC,aAAa,EAAE,CAAC;QAC5B,YAAY,CAAC,aAAa,EAAE,CAAC;QAC7B,EAAE,CAAC,UAAU,CAAC,WAAW,EAAE,EAAE,CAAC,CAAC;QAC/B,EAAE,CAAC,UAAU,CAAC,QAAQ,EAAE,SAAS,CAAC,CAAC;QACnC,EAAE,CAAC,UAAU,CAAC,gBAAgB,EAAE,kBAAkB,CAAC,CAAC;QACpD,eAAe,GAAG,4BAA4B,EAAE,CAAC;QACjD,EAAE,CAAC,UAAU,CAAC,QAAQ,EAAE,EAAE,WAAW,EAAE,eAAe,EAAE,CAAC,CAAC;IAC5D,CAAC,CAAC,CAAC;IAEH,SAAS,CAAC,GAAG,EAAE;QACb,EAAE,CAAC,gBAAgB,EAAE,CAAC;QACtB,EAAE,CAAC,aAAa,EAAE,CAAC;QACnB,WAAW,CAAC,aAAa,EAAE,CAAC;QAC5B,YAAY,CAAC,aAAa,EAAE,CAAC;IAC/B,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,0EAA0E,EAAE,KAAK,IAAI,EAAE;QACxF,MAAM,EAAE,MAAM,EAAE,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC,cAAc,EAAE,CAAC,CAAC;QAEtD,MAAM,MAAM,CAAC,OAAO,CAAC,EAAE,KAAK,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,CAAC;QAElD,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,EAAE,KAAK,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE;aACpC,CAAC,EACF,GAAG,CACJ,CAAC;QACJ,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,qCAAqC,EAAE,KAAK,IAAI,EAAE;QACnD,MAAM,EAAE,MAAM,EAAE,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC,cAAc,EAAE,CAAC,CAAC;QAEtD,MAAM,MAAM,CAAC,OAAO,CAAC,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,CAAC;QAEtC,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,EAAE,MAAM,EAAE,GAAG,EAAE;aACxB,CAAC,EACF,GAAG,CACJ,CAAC;QACJ,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC","sourcesContent":["import { renderHook, waitFor } from \"@testing-library/react\";\nimport { afterEach, beforeEach, describe, expect, it, vi } from \"vitest\";\nimport { HostAdaptor } from \"../bridges/adaptor.js\";\nimport { McpAppBridge } from \"../bridges/mcp-app/bridge.js\";\nimport {\n getMcpAppHostPostMessageMock,\n MockResizeObserver,\n} from \"./test/utils.js\";\nimport { useRequestSize } from \"./use-request-size.js\";\n\ndescribe(\"useRequestSize\", () => {\n let postMessageMock: ReturnType<typeof getMcpAppHostPostMessageMock>;\n\n beforeEach(() => {\n HostAdaptor.resetInstance();\n McpAppBridge.resetInstance();\n vi.stubGlobal(\"skybridge\", {});\n vi.stubGlobal(\"openai\", undefined);\n vi.stubGlobal(\"ResizeObserver\", MockResizeObserver);\n postMessageMock = getMcpAppHostPostMessageMock();\n vi.stubGlobal(\"parent\", { postMessage: postMessageMock });\n });\n\n afterEach(() => {\n vi.unstubAllGlobals();\n vi.resetAllMocks();\n HostAdaptor.resetInstance();\n McpAppBridge.resetInstance();\n });\n\n it(\"sends a ui/notifications/size-changed notification with width and height\", async () => {\n const { result } = renderHook(() => useRequestSize());\n\n await result.current({ width: 800, height: 400 });\n\n await waitFor(() => {\n expect(postMessageMock).toHaveBeenCalledWith(\n expect.objectContaining({\n jsonrpc: \"2.0\",\n method: \"ui/notifications/size-changed\",\n params: { width: 800, height: 400 },\n }),\n \"*\",\n );\n });\n });\n\n it(\"forwards height-only payloads as-is\", async () => {\n const { result } = renderHook(() => useRequestSize());\n\n await result.current({ height: 400 });\n\n await waitFor(() => {\n expect(postMessageMock).toHaveBeenCalledWith(\n expect.objectContaining({\n jsonrpc: \"2.0\",\n method: \"ui/notifications/size-changed\",\n params: { height: 400 },\n }),\n \"*\",\n );\n });\n });\n});\n"]}
@@ -20,10 +20,7 @@ describe("useSetOpenInAppUrl", () => {
20
20
  vi.stubGlobal("openai", {
21
21
  setOpenInAppUrl: setOpenInAppUrlMock,
22
22
  });
23
- vi.stubGlobal("skybridge", {
24
- hostType: "apps-sdk",
25
- serverUrl: "https://example.com",
26
- });
23
+ vi.stubGlobal("skybridge", { serverUrl: "https://example.com" });
27
24
  vi.stubGlobal("parent", { postMessage: vi.fn() });
28
25
  });
29
26
  it("should return a function that calls window.openai.setOpenInAppUrl with the href", async () => {
@@ -48,10 +45,7 @@ describe("useSetOpenInAppUrl", () => {
48
45
  describe("mcp-app host", () => {
49
46
  beforeEach(() => {
50
47
  vi.stubGlobal("openai", undefined);
51
- vi.stubGlobal("skybridge", {
52
- hostType: "mcp-app",
53
- serverUrl: "https://example.com",
54
- });
48
+ vi.stubGlobal("skybridge", { serverUrl: "https://example.com" });
55
49
  vi.stubGlobal("parent", { postMessage: vi.fn() });
56
50
  });
57
51
  it("should throw NotSupportedError when called from an MCP App runtime", async () => {
@@ -1 +1 @@
1
- {"version":3,"file":"use-set-open-in-app-url.test.js","sourceRoot":"","sources":["../../../src/web/hooks/use-set-open-in-app-url.test.ts"],"names":[],"mappings":"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","sourcesContent":["import { renderHook } from \"@testing-library/react\";\nimport { afterEach, beforeEach, describe, expect, it, vi } from \"vitest\";\nimport { HostAdaptor } from \"../bridges/adaptor.js\";\nimport { AppsSdkBridge } from \"../bridges/apps-sdk/bridge.js\";\nimport { McpAppBridge } from \"../bridges/mcp-app/bridge.js\";\nimport { NotSupportedError } from \"../bridges/types.js\";\nimport { useSetOpenInAppUrl } from \"./use-set-open-in-app-url.js\";\n\ndescribe(\"useSetOpenInAppUrl\", () => {\n afterEach(() => {\n vi.unstubAllGlobals();\n vi.resetAllMocks();\n HostAdaptor.resetInstance();\n AppsSdkBridge.resetInstance();\n McpAppBridge.resetInstance();\n });\n\n describe(\"apps-sdk host\", () => {\n let setOpenInAppUrlMock: ReturnType<typeof vi.fn>;\n\n beforeEach(() => {\n setOpenInAppUrlMock = vi.fn().mockResolvedValue(undefined);\n vi.stubGlobal(\"openai\", {\n setOpenInAppUrl: setOpenInAppUrlMock,\n });\n vi.stubGlobal(\"skybridge\", {\n hostType: \"apps-sdk\",\n serverUrl: \"https://example.com\",\n });\n vi.stubGlobal(\"parent\", { postMessage: vi.fn() });\n });\n\n it(\"should return a function that calls window.openai.setOpenInAppUrl with the href\", async () => {\n const { result } = renderHook(() => useSetOpenInAppUrl());\n\n const href = \"https://example.com/path\";\n await result.current(href);\n\n expect(setOpenInAppUrlMock).toHaveBeenCalledTimes(1);\n expect(setOpenInAppUrlMock).toHaveBeenCalledWith({ href });\n });\n\n it(\"should reject when href is empty\", async () => {\n const { result } = renderHook(() => useSetOpenInAppUrl());\n\n await expect(result.current(\"\")).rejects.toThrow(\n \"The href parameter is required.\",\n );\n });\n\n it(\"should call setOpenInAppUrl when href origin differs from serverUrl origin\", async () => {\n const { result } = renderHook(() => useSetOpenInAppUrl());\n\n const href = \"https://different-domain.com/path\";\n await result.current(href);\n\n expect(setOpenInAppUrlMock).toHaveBeenCalledTimes(1);\n expect(setOpenInAppUrlMock).toHaveBeenCalledWith({ href });\n });\n });\n\n describe(\"mcp-app host\", () => {\n beforeEach(() => {\n vi.stubGlobal(\"openai\", undefined);\n vi.stubGlobal(\"skybridge\", {\n hostType: \"mcp-app\",\n serverUrl: \"https://example.com\",\n });\n vi.stubGlobal(\"parent\", { postMessage: vi.fn() });\n });\n\n it(\"should throw NotSupportedError when called from an MCP App runtime\", async () => {\n const { result } = renderHook(() => useSetOpenInAppUrl());\n\n await expect(\n result.current(\"https://example.com/path\"),\n ).rejects.toBeInstanceOf(NotSupportedError);\n });\n });\n});\n"]}
1
+ {"version":3,"file":"use-set-open-in-app-url.test.js","sourceRoot":"","sources":["../../../src/web/hooks/use-set-open-in-app-url.test.ts"],"names":[],"mappings":"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","sourcesContent":["import { renderHook } from \"@testing-library/react\";\nimport { afterEach, beforeEach, describe, expect, it, vi } from \"vitest\";\nimport { HostAdaptor } from \"../bridges/adaptor.js\";\nimport { AppsSdkBridge } from \"../bridges/apps-sdk/bridge.js\";\nimport { McpAppBridge } from \"../bridges/mcp-app/bridge.js\";\nimport { NotSupportedError } from \"../bridges/types.js\";\nimport { useSetOpenInAppUrl } from \"./use-set-open-in-app-url.js\";\n\ndescribe(\"useSetOpenInAppUrl\", () => {\n afterEach(() => {\n vi.unstubAllGlobals();\n vi.resetAllMocks();\n HostAdaptor.resetInstance();\n AppsSdkBridge.resetInstance();\n McpAppBridge.resetInstance();\n });\n\n describe(\"apps-sdk host\", () => {\n let setOpenInAppUrlMock: ReturnType<typeof vi.fn>;\n\n beforeEach(() => {\n setOpenInAppUrlMock = vi.fn().mockResolvedValue(undefined);\n vi.stubGlobal(\"openai\", {\n setOpenInAppUrl: setOpenInAppUrlMock,\n });\n vi.stubGlobal(\"skybridge\", { serverUrl: \"https://example.com\" });\n vi.stubGlobal(\"parent\", { postMessage: vi.fn() });\n });\n\n it(\"should return a function that calls window.openai.setOpenInAppUrl with the href\", async () => {\n const { result } = renderHook(() => useSetOpenInAppUrl());\n\n const href = \"https://example.com/path\";\n await result.current(href);\n\n expect(setOpenInAppUrlMock).toHaveBeenCalledTimes(1);\n expect(setOpenInAppUrlMock).toHaveBeenCalledWith({ href });\n });\n\n it(\"should reject when href is empty\", async () => {\n const { result } = renderHook(() => useSetOpenInAppUrl());\n\n await expect(result.current(\"\")).rejects.toThrow(\n \"The href parameter is required.\",\n );\n });\n\n it(\"should call setOpenInAppUrl when href origin differs from serverUrl origin\", async () => {\n const { result } = renderHook(() => useSetOpenInAppUrl());\n\n const href = \"https://different-domain.com/path\";\n await result.current(href);\n\n expect(setOpenInAppUrlMock).toHaveBeenCalledTimes(1);\n expect(setOpenInAppUrlMock).toHaveBeenCalledWith({ href });\n });\n });\n\n describe(\"mcp-app host\", () => {\n beforeEach(() => {\n vi.stubGlobal(\"openai\", undefined);\n vi.stubGlobal(\"skybridge\", { serverUrl: \"https://example.com\" });\n vi.stubGlobal(\"parent\", { postMessage: vi.fn() });\n });\n\n it(\"should throw NotSupportedError when called from an MCP App runtime\", async () => {\n const { result } = renderHook(() => useSetOpenInAppUrl());\n\n await expect(\n result.current(\"https://example.com/path\"),\n ).rejects.toBeInstanceOf(NotSupportedError);\n });\n });\n});\n"]}
@@ -1,21 +1,4 @@
1
1
  import type { UnknownObject } from "../types.js";
2
- /**
3
- * {@link useToolInfo} state before the tool has been invoked.
4
- *
5
- * @deprecated `useToolInfo` no longer returns the idle state — it starts in
6
- * `"pending"` and transitions to `"success"`, so `isIdle` is always `false` at
7
- * runtime. This type is retained in {@link ToolState} for backwards
8
- * compatibility and will be removed in the next major.
9
- */
10
- export type ToolIdleState = {
11
- status: "idle";
12
- isIdle: true;
13
- isPending: false;
14
- isSuccess: false;
15
- input: undefined;
16
- output: undefined;
17
- responseMetadata: undefined;
18
- };
19
2
  /**
20
3
  * {@link useToolInfo} state while the tool is executing — `output` is not yet
21
4
  * available.
@@ -25,7 +8,6 @@ export type ToolIdleState = {
25
8
  */
26
9
  export type ToolPendingState<ToolInput extends UnknownObject> = {
27
10
  status: "pending";
28
- isIdle: false;
29
11
  isPending: true;
30
12
  isSuccess: false;
31
13
  input: ToolInput | undefined;
@@ -40,7 +22,6 @@ export type ToolPendingState<ToolInput extends UnknownObject> = {
40
22
  */
41
23
  export type ToolSuccessState<ToolInput extends UnknownObject, ToolOutput extends UnknownObject, ToolResponseMetadata extends UnknownObject> = {
42
24
  status: "success";
43
- isIdle: false;
44
25
  isPending: false;
45
26
  isSuccess: true;
46
27
  input: ToolInput | undefined;
@@ -51,7 +32,7 @@ export type ToolSuccessState<ToolInput extends UnknownObject, ToolOutput extends
51
32
  * Discriminated union describing the tool invocation that triggered the
52
33
  * current view render. Use `isPending` / `isSuccess` to narrow.
53
34
  */
54
- export type ToolState<ToolInput extends UnknownObject, ToolOutput extends UnknownObject, ToolResponseMetadata extends UnknownObject> = ToolIdleState | ToolPendingState<ToolInput> | ToolSuccessState<ToolInput, ToolOutput, ToolResponseMetadata>;
35
+ export type ToolState<ToolInput extends UnknownObject, ToolOutput extends UnknownObject, ToolResponseMetadata extends UnknownObject> = ToolPendingState<ToolInput> | ToolSuccessState<ToolInput, ToolOutput, ToolResponseMetadata>;
55
36
  type ToolSignature = {
56
37
  input: UnknownObject;
57
38
  output: UnknownObject;
@@ -39,7 +39,6 @@ export function useToolInfo() {
39
39
  return {
40
40
  input: input ?? undefined,
41
41
  status,
42
- isIdle: false,
43
42
  isPending: status === "pending",
44
43
  isSuccess: status === "success",
45
44
  output,
@@ -1 +1 @@
1
- {"version":3,"file":"use-tool-info.js","sourceRoot":"","sources":["../../../src/web/hooks/use-tool-info.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AA6ErD,SAAS,YAAY,CACnB,MAAsC,EACtC,gBAAgD;IAEhD,IAAI,MAAM,KAAK,IAAI,IAAI,gBAAgB,KAAK,IAAI,EAAE,CAAC;QACjD,OAAO,SAAS,CAAC;IACnB,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,MAAM,UAAU,WAAW;IAGzB,MAAM,KAAK,GAAG,cAAc,CAAC,WAAW,CAAC,CAAC;IAC1C,MAAM,MAAM,GAAG,cAAc,CAAC,YAAY,CAAC,CAAC;IAC5C,MAAM,gBAAgB,GAAG,cAAc,CAAC,sBAAsB,CAAC,CAAC;IAEhE,MAAM,MAAM,GAAG,YAAY,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAAC;IAMtD,OAAO;QACL,KAAK,EAAE,KAAK,IAAI,SAAS;QACzB,MAAM;QACN,MAAM,EAAE,KAAK;QACb,SAAS,EAAE,MAAM,KAAK,SAAS;QAC/B,SAAS,EAAE,MAAM,KAAK,SAAS;QAC/B,MAAM;QACN,gBAAgB;KACqB,CAAC;AAC1C,CAAC","sourcesContent":["import { useHostContext } from \"../bridges/index.js\";\nimport type { UnknownObject } from \"../types.js\";\n\n/**\n * {@link useToolInfo} state before the tool has been invoked.\n *\n * @deprecated `useToolInfo` no longer returns the idle state — it starts in\n * `\"pending\"` and transitions to `\"success\"`, so `isIdle` is always `false` at\n * runtime. This type is retained in {@link ToolState} for backwards\n * compatibility and will be removed in the next major.\n */\nexport type ToolIdleState = {\n status: \"idle\";\n isIdle: true;\n isPending: false;\n isSuccess: false;\n input: undefined;\n output: undefined;\n responseMetadata: undefined;\n};\n\n/**\n * {@link useToolInfo} state while the tool is executing — `output` is not yet\n * available.\n *\n * `input` is optional: the host may render the view before delivering the\n * tool arguments.\n */\nexport type ToolPendingState<ToolInput extends UnknownObject> = {\n status: \"pending\";\n isIdle: false;\n isPending: true;\n isSuccess: false;\n input: ToolInput | undefined;\n output: undefined;\n responseMetadata: undefined;\n};\n\n/**\n * {@link useToolInfo} state once the tool returned — `output` is available.\n *\n * `input` is optional: the host may not have surfaced the tool arguments by\n * the time `output` arrives.\n */\nexport type ToolSuccessState<\n ToolInput extends UnknownObject,\n ToolOutput extends UnknownObject,\n ToolResponseMetadata extends UnknownObject,\n> = {\n status: \"success\";\n isIdle: false;\n isPending: false;\n isSuccess: true;\n input: ToolInput | undefined;\n output: ToolOutput;\n responseMetadata: ToolResponseMetadata;\n};\n\n/**\n * Discriminated union describing the tool invocation that triggered the\n * current view render. Use `isPending` / `isSuccess` to narrow.\n */\nexport type ToolState<\n ToolInput extends UnknownObject,\n ToolOutput extends UnknownObject,\n ToolResponseMetadata extends UnknownObject,\n> =\n | ToolIdleState\n | ToolPendingState<ToolInput>\n | ToolSuccessState<ToolInput, ToolOutput, ToolResponseMetadata>;\n\ntype ToolSignature = {\n input: UnknownObject;\n output: UnknownObject;\n responseMetadata: UnknownObject;\n};\n\nfunction deriveStatus(\n output: Record<string, unknown> | null,\n responseMetadata: Record<string, unknown> | null,\n): \"pending\" | \"success\" {\n if (output === null && responseMetadata === null) {\n return \"pending\";\n }\n return \"success\";\n}\n\n/**\n * Access the tool invocation that produced the current view: its `input`,\n * resulting `output`, and `responseMetadata`. The shape evolves as the tool\n * runs (pending → success), exposed through {@link ToolState}.\n *\n * For full input/output typing per tool name, prefer the typed `useToolInfo`\n * returned by {@link generateHelpers} over the generic form.\n *\n * @typeParam TS - Optional partial shape `{ input, output, responseMetadata }`\n * to refine each field's type. When omitted, each typed field resolves to\n * `never` — pass an explicit shape or use the typed helper from\n * {@link generateHelpers} to get usable types.\n *\n * @example\n * ```tsx\n * const { isSuccess, input, output } = useToolInfo<{\n * input: { query: string };\n * output: { results: Result[] };\n * }>();\n *\n * if (!isSuccess || !output) return <Skeleton />;\n * return <Results items={output.results} />;\n * ```\n *\n * @see https://docs.skybridge.tech/api-reference/use-tool-info\n */\nexport function useToolInfo<\n TS extends Partial<ToolSignature> = Record<string, never>,\n>() {\n const input = useHostContext(\"toolInput\");\n const output = useHostContext(\"toolOutput\");\n const responseMetadata = useHostContext(\"toolResponseMetadata\");\n\n const status = deriveStatus(output, responseMetadata);\n\n type Input = UnknownObject & TS[\"input\"];\n type Output = UnknownObject & TS[\"output\"];\n type Metadata = UnknownObject & TS[\"responseMetadata\"];\n\n return {\n input: input ?? undefined,\n status,\n isIdle: false,\n isPending: status === \"pending\",\n isSuccess: status === \"success\",\n output,\n responseMetadata,\n } as ToolState<Input, Output, Metadata>;\n}\n"]}
1
+ {"version":3,"file":"use-tool-info.js","sourceRoot":"","sources":["../../../src/web/hooks/use-tool-info.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAwDrD,SAAS,YAAY,CACnB,MAAsC,EACtC,gBAAgD;IAEhD,IAAI,MAAM,KAAK,IAAI,IAAI,gBAAgB,KAAK,IAAI,EAAE,CAAC;QACjD,OAAO,SAAS,CAAC;IACnB,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,MAAM,UAAU,WAAW;IAGzB,MAAM,KAAK,GAAG,cAAc,CAAC,WAAW,CAAC,CAAC;IAC1C,MAAM,MAAM,GAAG,cAAc,CAAC,YAAY,CAAC,CAAC;IAC5C,MAAM,gBAAgB,GAAG,cAAc,CAAC,sBAAsB,CAAC,CAAC;IAEhE,MAAM,MAAM,GAAG,YAAY,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAAC;IAMtD,OAAO;QACL,KAAK,EAAE,KAAK,IAAI,SAAS;QACzB,MAAM;QACN,SAAS,EAAE,MAAM,KAAK,SAAS;QAC/B,SAAS,EAAE,MAAM,KAAK,SAAS;QAC/B,MAAM;QACN,gBAAgB;KACqB,CAAC;AAC1C,CAAC","sourcesContent":["import { useHostContext } from \"../bridges/index.js\";\nimport type { UnknownObject } from \"../types.js\";\n\n/**\n * {@link useToolInfo} state while the tool is executing — `output` is not yet\n * available.\n *\n * `input` is optional: the host may render the view before delivering the\n * tool arguments.\n */\nexport type ToolPendingState<ToolInput extends UnknownObject> = {\n status: \"pending\";\n isPending: true;\n isSuccess: false;\n input: ToolInput | undefined;\n output: undefined;\n responseMetadata: undefined;\n};\n\n/**\n * {@link useToolInfo} state once the tool returned — `output` is available.\n *\n * `input` is optional: the host may not have surfaced the tool arguments by\n * the time `output` arrives.\n */\nexport type ToolSuccessState<\n ToolInput extends UnknownObject,\n ToolOutput extends UnknownObject,\n ToolResponseMetadata extends UnknownObject,\n> = {\n status: \"success\";\n isPending: false;\n isSuccess: true;\n input: ToolInput | undefined;\n output: ToolOutput;\n responseMetadata: ToolResponseMetadata;\n};\n\n/**\n * Discriminated union describing the tool invocation that triggered the\n * current view render. Use `isPending` / `isSuccess` to narrow.\n */\nexport type ToolState<\n ToolInput extends UnknownObject,\n ToolOutput extends UnknownObject,\n ToolResponseMetadata extends UnknownObject,\n> =\n | ToolPendingState<ToolInput>\n | ToolSuccessState<ToolInput, ToolOutput, ToolResponseMetadata>;\n\ntype ToolSignature = {\n input: UnknownObject;\n output: UnknownObject;\n responseMetadata: UnknownObject;\n};\n\nfunction deriveStatus(\n output: Record<string, unknown> | null,\n responseMetadata: Record<string, unknown> | null,\n): \"pending\" | \"success\" {\n if (output === null && responseMetadata === null) {\n return \"pending\";\n }\n return \"success\";\n}\n\n/**\n * Access the tool invocation that produced the current view: its `input`,\n * resulting `output`, and `responseMetadata`. The shape evolves as the tool\n * runs (pending → success), exposed through {@link ToolState}.\n *\n * For full input/output typing per tool name, prefer the typed `useToolInfo`\n * returned by {@link generateHelpers} over the generic form.\n *\n * @typeParam TS - Optional partial shape `{ input, output, responseMetadata }`\n * to refine each field's type. When omitted, each typed field resolves to\n * `never` — pass an explicit shape or use the typed helper from\n * {@link generateHelpers} to get usable types.\n *\n * @example\n * ```tsx\n * const { isSuccess, input, output } = useToolInfo<{\n * input: { query: string };\n * output: { results: Result[] };\n * }>();\n *\n * if (!isSuccess || !output) return <Skeleton />;\n * return <Results items={output.results} />;\n * ```\n *\n * @see https://docs.skybridge.tech/api-reference/use-tool-info\n */\nexport function useToolInfo<\n TS extends Partial<ToolSignature> = Record<string, never>,\n>() {\n const input = useHostContext(\"toolInput\");\n const output = useHostContext(\"toolOutput\");\n const responseMetadata = useHostContext(\"toolResponseMetadata\");\n\n const status = deriveStatus(output, responseMetadata);\n\n type Input = UnknownObject & TS[\"input\"];\n type Output = UnknownObject & TS[\"output\"];\n type Metadata = UnknownObject & TS[\"responseMetadata\"];\n\n return {\n input: input ?? undefined,\n status,\n isPending: status === \"pending\",\n isSuccess: status === \"success\",\n output,\n responseMetadata,\n } as ToolState<Input, Output, Metadata>;\n}\n"]}
@@ -6,7 +6,6 @@ test("useToolInfo - TypeScript typing", () => {
6
6
  expectTypeOf(result.status);
7
7
  expectTypeOf(result.isPending);
8
8
  expectTypeOf(result.isSuccess);
9
- expectTypeOf(result.isIdle);
10
9
  expectTypeOf(result.input);
11
10
  });
12
11
  test("should correctly type input, output, and responseMetadata with explicit ToolSignature", () => {
@@ -31,7 +30,6 @@ test("useToolInfo - TypeScript typing", () => {
31
30
  // Test type narrowing for pending
32
31
  if (result.isPending) {
33
32
  expectTypeOf(result.status);
34
- expectTypeOf(result.isIdle);
35
33
  expectTypeOf(result.isPending);
36
34
  expectTypeOf(result.isSuccess);
37
35
  expectTypeOf(result.input);
@@ -40,7 +38,6 @@ test("useToolInfo - TypeScript typing", () => {
40
38
  }
41
39
  if (result.isSuccess) {
42
40
  expectTypeOf(result.status);
43
- expectTypeOf(result.isIdle);
44
41
  expectTypeOf(result.isPending);
45
42
  expectTypeOf(result.isSuccess);
46
43
  expectTypeOf(result.input);
@@ -49,7 +46,6 @@ test("useToolInfo - TypeScript typing", () => {
49
46
  }
50
47
  if (result.status === "pending") {
51
48
  expectTypeOf(result.input);
52
- expectTypeOf(result.isIdle);
53
49
  expectTypeOf(result.isPending);
54
50
  expectTypeOf(result.isSuccess);
55
51
  expectTypeOf(result.output);
@@ -57,7 +53,6 @@ test("useToolInfo - TypeScript typing", () => {
57
53
  }
58
54
  if (result.status === "success") {
59
55
  expectTypeOf(result.input);
60
- expectTypeOf(result.isIdle);
61
56
  expectTypeOf(result.isPending);
62
57
  expectTypeOf(result.isSuccess);
63
58
  expectTypeOf(result.output);
@@ -1 +1 @@
1
- {"version":3,"file":"use-tool-info.test-d.js","sourceRoot":"","sources":["../../../src/web/hooks/use-tool-info.test-d.ts"],"names":[],"mappings":"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","sourcesContent":["import { expectTypeOf, test } from \"vitest\";\nimport { useToolInfo } from \"./use-tool-info.js\";\n\ntest(\"useToolInfo - TypeScript typing\", () => {\n test(\"should have correct types when no generic parameter is provided\", () => {\n const result = useToolInfo();\n\n expectTypeOf<\"idle\" | \"pending\" | \"success\">(result.status);\n expectTypeOf<boolean>(result.isPending);\n expectTypeOf<boolean>(result.isSuccess);\n expectTypeOf<boolean>(result.isIdle);\n expectTypeOf<Record<string, unknown> | undefined>(result.input);\n });\n\n test(\"should correctly type input, output, and responseMetadata with explicit ToolSignature\", () => {\n type TestInput = { name: string; args: { name: string } };\n type TestOutput = { name: string; color: string };\n type TestMetadata = { id: number };\n\n const result = useToolInfo<{\n input: TestInput;\n output: TestOutput;\n responseMetadata: TestMetadata;\n }>();\n\n // When pending, input may be undefined (host hasn't delivered args yet,\n // or the tool has no input schema)\n if (result.status === \"pending\") {\n expectTypeOf<TestInput | undefined>(result.input);\n expectTypeOf<undefined>(result.output);\n expectTypeOf<undefined>(result.responseMetadata);\n }\n\n // When success, output and responseMetadata are defined; input may still\n // be undefined if the host hasn't surfaced the tool arguments\n if (result.status === \"success\") {\n expectTypeOf<TestInput | undefined>(result.input);\n expectTypeOf<TestOutput>(result.output);\n expectTypeOf<TestMetadata>(result.responseMetadata);\n }\n });\n\n test(\"should correctly narrow types based on status discriminated union\", () => {\n type TestInput = { query: string };\n type TestOutput = { result: string };\n type TestMetadata = { timestamp: number };\n\n const result = useToolInfo<{\n input: TestInput;\n output: TestOutput;\n responseMetadata: TestMetadata;\n }>();\n\n // Test type narrowing for pending\n if (result.isPending) {\n expectTypeOf<\"pending\">(result.status);\n expectTypeOf<false>(result.isIdle);\n expectTypeOf<true>(result.isPending);\n expectTypeOf<false>(result.isSuccess);\n expectTypeOf<TestInput | undefined>(result.input);\n expectTypeOf<undefined>(result.output);\n expectTypeOf<undefined>(result.responseMetadata);\n }\n\n if (result.isSuccess) {\n expectTypeOf<\"success\">(result.status);\n expectTypeOf<false>(result.isIdle);\n expectTypeOf<false>(result.isPending);\n expectTypeOf<true>(result.isSuccess);\n expectTypeOf<TestInput | undefined>(result.input);\n expectTypeOf<TestOutput>(result.output);\n expectTypeOf<TestMetadata>(result.responseMetadata);\n }\n\n if (result.status === \"pending\") {\n expectTypeOf<TestInput | undefined>(result.input);\n expectTypeOf<false>(result.isIdle);\n expectTypeOf<true>(result.isPending);\n expectTypeOf<false>(result.isSuccess);\n expectTypeOf<undefined>(result.output);\n expectTypeOf<undefined>(result.responseMetadata);\n }\n\n if (result.status === \"success\") {\n expectTypeOf<TestInput | undefined>(result.input);\n expectTypeOf<false>(result.isIdle);\n expectTypeOf<false>(result.isPending);\n expectTypeOf<true>(result.isSuccess);\n expectTypeOf<TestOutput>(result.output);\n expectTypeOf<TestMetadata>(result.responseMetadata);\n }\n });\n\n test(\"should handle partial ToolSignature with only input specified\", () => {\n type TestInput = { id: number };\n\n const result = useToolInfo<{\n input: TestInput;\n }>();\n\n // Input is optional in both states — undefined while args haven't arrived\n // (pending) and for no-input tools (success).\n if (result.status === \"pending\") {\n expectTypeOf<TestInput | undefined>(result.input);\n }\n\n if (result.status === \"success\") {\n expectTypeOf<TestInput | undefined>(result.input);\n expectTypeOf<Record<string, unknown>>(result.output);\n expectTypeOf<Record<string, unknown>>(result.responseMetadata);\n }\n });\n\n test(\"should handle ToolSignature with only output specified\", () => {\n type TestOutput = { data: string[] };\n\n const result = useToolInfo<{\n output: TestOutput;\n }>();\n\n if (result.status === \"pending\") {\n expectTypeOf<Record<string, unknown> | undefined>(result.input);\n }\n\n if (result.status === \"success\") {\n expectTypeOf<Record<string, unknown> | undefined>(result.input);\n expectTypeOf<TestOutput>(result.output);\n }\n });\n});\n"]}
1
+ {"version":3,"file":"use-tool-info.test-d.js","sourceRoot":"","sources":["../../../src/web/hooks/use-tool-info.test-d.ts"],"names":[],"mappings":"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","sourcesContent":["import { expectTypeOf, test } from \"vitest\";\nimport { useToolInfo } from \"./use-tool-info.js\";\n\ntest(\"useToolInfo - TypeScript typing\", () => {\n test(\"should have correct types when no generic parameter is provided\", () => {\n const result = useToolInfo();\n\n expectTypeOf<\"pending\" | \"success\">(result.status);\n expectTypeOf<boolean>(result.isPending);\n expectTypeOf<boolean>(result.isSuccess);\n expectTypeOf<Record<string, unknown> | undefined>(result.input);\n });\n\n test(\"should correctly type input, output, and responseMetadata with explicit ToolSignature\", () => {\n type TestInput = { name: string; args: { name: string } };\n type TestOutput = { name: string; color: string };\n type TestMetadata = { id: number };\n\n const result = useToolInfo<{\n input: TestInput;\n output: TestOutput;\n responseMetadata: TestMetadata;\n }>();\n\n // When pending, input may be undefined (host hasn't delivered args yet,\n // or the tool has no input schema)\n if (result.status === \"pending\") {\n expectTypeOf<TestInput | undefined>(result.input);\n expectTypeOf<undefined>(result.output);\n expectTypeOf<undefined>(result.responseMetadata);\n }\n\n // When success, output and responseMetadata are defined; input may still\n // be undefined if the host hasn't surfaced the tool arguments\n if (result.status === \"success\") {\n expectTypeOf<TestInput | undefined>(result.input);\n expectTypeOf<TestOutput>(result.output);\n expectTypeOf<TestMetadata>(result.responseMetadata);\n }\n });\n\n test(\"should correctly narrow types based on status discriminated union\", () => {\n type TestInput = { query: string };\n type TestOutput = { result: string };\n type TestMetadata = { timestamp: number };\n\n const result = useToolInfo<{\n input: TestInput;\n output: TestOutput;\n responseMetadata: TestMetadata;\n }>();\n\n // Test type narrowing for pending\n if (result.isPending) {\n expectTypeOf<\"pending\">(result.status);\n expectTypeOf<true>(result.isPending);\n expectTypeOf<false>(result.isSuccess);\n expectTypeOf<TestInput | undefined>(result.input);\n expectTypeOf<undefined>(result.output);\n expectTypeOf<undefined>(result.responseMetadata);\n }\n\n if (result.isSuccess) {\n expectTypeOf<\"success\">(result.status);\n expectTypeOf<false>(result.isPending);\n expectTypeOf<true>(result.isSuccess);\n expectTypeOf<TestInput | undefined>(result.input);\n expectTypeOf<TestOutput>(result.output);\n expectTypeOf<TestMetadata>(result.responseMetadata);\n }\n\n if (result.status === \"pending\") {\n expectTypeOf<TestInput | undefined>(result.input);\n expectTypeOf<true>(result.isPending);\n expectTypeOf<false>(result.isSuccess);\n expectTypeOf<undefined>(result.output);\n expectTypeOf<undefined>(result.responseMetadata);\n }\n\n if (result.status === \"success\") {\n expectTypeOf<TestInput | undefined>(result.input);\n expectTypeOf<false>(result.isPending);\n expectTypeOf<true>(result.isSuccess);\n expectTypeOf<TestOutput>(result.output);\n expectTypeOf<TestMetadata>(result.responseMetadata);\n }\n });\n\n test(\"should handle partial ToolSignature with only input specified\", () => {\n type TestInput = { id: number };\n\n const result = useToolInfo<{\n input: TestInput;\n }>();\n\n // Input is optional in both states — undefined while args haven't arrived\n // (pending) and for no-input tools (success).\n if (result.status === \"pending\") {\n expectTypeOf<TestInput | undefined>(result.input);\n }\n\n if (result.status === \"success\") {\n expectTypeOf<TestInput | undefined>(result.input);\n expectTypeOf<Record<string, unknown>>(result.output);\n expectTypeOf<Record<string, unknown>>(result.responseMetadata);\n }\n });\n\n test(\"should handle ToolSignature with only output specified\", () => {\n type TestOutput = { data: string[] };\n\n const result = useToolInfo<{\n output: TestOutput;\n }>();\n\n if (result.status === \"pending\") {\n expectTypeOf<Record<string, unknown> | undefined>(result.input);\n }\n\n if (result.status === \"success\") {\n expectTypeOf<Record<string, unknown> | undefined>(result.input);\n expectTypeOf<TestOutput>(result.output);\n }\n });\n});\n"]}
@@ -13,7 +13,7 @@ describe("useToolInfo", () => {
13
13
  toolOutput: null,
14
14
  toolResponseMetadata: null,
15
15
  });
16
- vi.stubGlobal("skybridge", { hostType: "apps-sdk" });
16
+ vi.stubGlobal("skybridge", {});
17
17
  vi.stubGlobal("ResizeObserver", MockResizeObserver);
18
18
  });
19
19
  afterEach(() => {
@@ -34,7 +34,6 @@ describe("useToolInfo", () => {
34
34
  expect(result.current).toMatchObject({
35
35
  input: { name: "pokemon", args: { name: "pikachu" } },
36
36
  status: "pending",
37
- isIdle: false,
38
37
  isPending: true,
39
38
  isSuccess: false,
40
39
  });
@@ -62,7 +61,6 @@ describe("useToolInfo", () => {
62
61
  await waitFor(() => {
63
62
  expect(result.current).toMatchObject({
64
63
  status: "success",
65
- isIdle: false,
66
64
  isPending: false,
67
65
  isSuccess: true,
68
66
  output: toolOutput,
@@ -74,7 +72,7 @@ describe("useToolInfo", () => {
74
72
  describe("mcp-app host", () => {
75
73
  beforeEach(() => {
76
74
  vi.stubGlobal("parent", { postMessage: getMcpAppHostPostMessageMock() });
77
- vi.stubGlobal("skybridge", { hostType: "mcp-app" });
75
+ vi.stubGlobal("skybridge", {});
78
76
  vi.stubGlobal("openai", undefined);
79
77
  vi.stubGlobal("ResizeObserver", MockResizeObserver);
80
78
  });
@@ -89,7 +87,6 @@ describe("useToolInfo", () => {
89
87
  await waitFor(() => {
90
88
  expect(result.current).toMatchObject({
91
89
  status: "pending",
92
- isIdle: false,
93
90
  isPending: true,
94
91
  isSuccess: false,
95
92
  input: undefined,
@@ -106,7 +103,6 @@ describe("useToolInfo", () => {
106
103
  await waitFor(() => {
107
104
  expect(result.current).toMatchObject({
108
105
  status: "pending",
109
- isIdle: false,
110
106
  isPending: true,
111
107
  isSuccess: false,
112
108
  input: { name: "pokemon", query: "pikachu" },
@@ -126,7 +122,6 @@ describe("useToolInfo", () => {
126
122
  await waitFor(() => {
127
123
  expect(result.current).toMatchObject({
128
124
  status: "success",
129
- isIdle: false,
130
125
  isPending: false,
131
126
  isSuccess: true,
132
127
  input: { name: "pokemon", query: "pikachu" },