@apollo/client-ai-apps 0.4.0 → 0.5.0

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 (404) hide show
  1. package/.github/CODEOWNERS +1 -0
  2. package/.github/workflows/pr.yaml +23 -1
  3. package/.github/workflows/release.yaml +1 -5
  4. package/.github/workflows/verify-changeset.yml +112 -21
  5. package/CHANGELOG.md +353 -0
  6. package/__mocks__/fs/promises.cjs +3 -0
  7. package/__mocks__/fs.cjs +3 -0
  8. package/dist/config/defineConfig.d.ts +26 -0
  9. package/dist/config/defineConfig.d.ts.map +1 -0
  10. package/dist/config/defineConfig.js +7 -0
  11. package/dist/config/defineConfig.js.map +1 -0
  12. package/dist/config/index.d.ts +3 -0
  13. package/dist/config/index.d.ts.map +1 -0
  14. package/dist/config/index.js +2 -0
  15. package/dist/config/index.js.map +1 -0
  16. package/dist/config/schema.d.ts +29 -0
  17. package/dist/config/schema.d.ts.map +1 -0
  18. package/dist/config/schema.js +51 -0
  19. package/dist/config/schema.js.map +1 -0
  20. package/dist/config/types.d.ts +7 -0
  21. package/dist/config/types.d.ts.map +1 -0
  22. package/dist/config/types.js +2 -0
  23. package/dist/config/types.js.map +1 -0
  24. package/dist/core/ApolloClient.d.ts +4 -3
  25. package/dist/core/ApolloClient.d.ts.map +1 -1
  26. package/dist/core/ApolloClient.js +6 -59
  27. package/dist/core/ApolloClient.js.map +1 -1
  28. package/dist/core/Platform.d.ts +8 -0
  29. package/dist/core/Platform.d.ts.map +1 -0
  30. package/dist/core/Platform.js +20 -0
  31. package/dist/core/Platform.js.map +1 -0
  32. package/dist/core/types.d.ts +13 -0
  33. package/dist/core/types.d.ts.map +1 -0
  34. package/dist/core/types.js +2 -0
  35. package/dist/core/types.js.map +1 -0
  36. package/dist/index.d.ts +1 -14
  37. package/dist/index.d.ts.map +1 -1
  38. package/dist/index.js +1 -13
  39. package/dist/index.js.map +1 -1
  40. package/dist/index.mcp.d.ts +5 -0
  41. package/dist/index.mcp.d.ts.map +1 -0
  42. package/dist/index.mcp.js +5 -0
  43. package/dist/index.mcp.js.map +1 -0
  44. package/dist/index.openai.d.ts +5 -0
  45. package/dist/index.openai.d.ts.map +1 -0
  46. package/dist/index.openai.js +5 -0
  47. package/dist/index.openai.js.map +1 -0
  48. package/dist/link/ToolCallLink.d.ts +3 -3
  49. package/dist/link/ToolCallLink.d.ts.map +1 -1
  50. package/dist/link/ToolCallLink.js +5 -14
  51. package/dist/link/ToolCallLink.js.map +1 -1
  52. package/dist/mcp/core/ApolloClient.d.ts +21 -0
  53. package/dist/mcp/core/ApolloClient.d.ts.map +1 -0
  54. package/dist/mcp/core/ApolloClient.js +65 -0
  55. package/dist/mcp/core/ApolloClient.js.map +1 -0
  56. package/dist/mcp/core/McpAppManager.d.ts +34 -0
  57. package/dist/mcp/core/McpAppManager.d.ts.map +1 -0
  58. package/dist/mcp/core/McpAppManager.js +63 -0
  59. package/dist/mcp/core/McpAppManager.js.map +1 -0
  60. package/dist/mcp/core/Platform.d.ts +8 -0
  61. package/dist/mcp/core/Platform.d.ts.map +1 -0
  62. package/dist/mcp/core/Platform.js +8 -0
  63. package/dist/mcp/core/Platform.js.map +1 -0
  64. package/dist/mcp/index.d.ts +3 -0
  65. package/dist/mcp/index.d.ts.map +1 -0
  66. package/dist/mcp/index.js +3 -0
  67. package/dist/mcp/index.js.map +1 -0
  68. package/dist/mcp/link/ToolCallLink.d.ts +28 -0
  69. package/dist/mcp/link/ToolCallLink.d.ts.map +1 -0
  70. package/dist/mcp/link/ToolCallLink.js +35 -0
  71. package/dist/mcp/link/ToolCallLink.js.map +1 -0
  72. package/dist/mcp/react/hooks/useApolloClient.d.ts +3 -0
  73. package/dist/mcp/react/hooks/useApolloClient.d.ts.map +1 -0
  74. package/dist/mcp/react/hooks/useApolloClient.js +9 -0
  75. package/dist/mcp/react/hooks/useApolloClient.js.map +1 -0
  76. package/dist/mcp/react/hooks/useApp.d.ts +2 -0
  77. package/dist/mcp/react/hooks/useApp.d.ts.map +1 -0
  78. package/dist/mcp/react/hooks/useApp.js +5 -0
  79. package/dist/mcp/react/hooks/useApp.js.map +1 -0
  80. package/dist/mcp/react/hooks/useToolInput.d.ts +2 -0
  81. package/dist/mcp/react/hooks/useToolInput.d.ts.map +1 -0
  82. package/dist/mcp/react/hooks/useToolInput.js +5 -0
  83. package/dist/mcp/react/hooks/useToolInput.js.map +1 -0
  84. package/dist/mcp/react/hooks/useToolMetadata.d.ts +8 -0
  85. package/dist/mcp/react/hooks/useToolMetadata.d.ts.map +1 -0
  86. package/dist/mcp/react/hooks/useToolMetadata.js +5 -0
  87. package/dist/mcp/react/hooks/useToolMetadata.js.map +1 -0
  88. package/dist/mcp/react/hooks/useToolName.d.ts +2 -0
  89. package/dist/mcp/react/hooks/useToolName.d.ts.map +1 -0
  90. package/dist/mcp/react/hooks/useToolName.js +5 -0
  91. package/dist/mcp/react/hooks/useToolName.js.map +1 -0
  92. package/dist/mcp/react/index.d.ts +5 -0
  93. package/dist/mcp/react/index.d.ts.map +1 -0
  94. package/dist/mcp/react/index.js +5 -0
  95. package/dist/mcp/react/index.js.map +1 -0
  96. package/dist/openai/core/ApolloClient.d.ts +21 -0
  97. package/dist/openai/core/ApolloClient.d.ts.map +1 -0
  98. package/dist/openai/core/ApolloClient.js +66 -0
  99. package/dist/openai/core/ApolloClient.js.map +1 -0
  100. package/dist/openai/core/McpAppManager.d.ts +28 -0
  101. package/dist/openai/core/McpAppManager.d.ts.map +1 -0
  102. package/dist/openai/core/McpAppManager.js +73 -0
  103. package/dist/openai/core/McpAppManager.js.map +1 -0
  104. package/dist/openai/core/Platform.d.ts +8 -0
  105. package/dist/openai/core/Platform.d.ts.map +1 -0
  106. package/dist/openai/core/Platform.js +8 -0
  107. package/dist/openai/core/Platform.js.map +1 -0
  108. package/dist/openai/globals.d.ts +12 -0
  109. package/dist/openai/globals.d.ts.map +1 -0
  110. package/dist/openai/globals.js +2 -0
  111. package/dist/openai/globals.js.map +1 -0
  112. package/dist/openai/index.d.ts +3 -0
  113. package/dist/openai/index.d.ts.map +1 -0
  114. package/dist/openai/index.js +3 -0
  115. package/dist/openai/index.js.map +1 -0
  116. package/dist/openai/link/ToolCallLink.d.ts +28 -0
  117. package/dist/openai/link/ToolCallLink.d.ts.map +1 -0
  118. package/dist/openai/link/ToolCallLink.js +35 -0
  119. package/dist/openai/link/ToolCallLink.js.map +1 -0
  120. package/dist/openai/react/hooks/useApolloClient.d.ts +3 -0
  121. package/dist/openai/react/hooks/useApolloClient.d.ts.map +1 -0
  122. package/dist/openai/react/hooks/useApolloClient.js +9 -0
  123. package/dist/openai/react/hooks/useApolloClient.js.map +1 -0
  124. package/dist/openai/react/hooks/useApp.d.ts +2 -0
  125. package/dist/openai/react/hooks/useApp.d.ts.map +1 -0
  126. package/dist/openai/react/hooks/useApp.js +5 -0
  127. package/dist/openai/react/hooks/useApp.js.map +1 -0
  128. package/dist/openai/react/hooks/useOpenAiGlobal.d.ts +3 -0
  129. package/dist/openai/react/hooks/useOpenAiGlobal.d.ts.map +1 -0
  130. package/dist/{react → openai/react}/hooks/useOpenAiGlobal.js +1 -1
  131. package/dist/openai/react/hooks/useOpenAiGlobal.js.map +1 -0
  132. package/dist/openai/react/hooks/useToolInput.d.ts +2 -0
  133. package/dist/openai/react/hooks/useToolInput.d.ts.map +1 -0
  134. package/dist/openai/react/hooks/useToolInput.js +5 -0
  135. package/dist/openai/react/hooks/useToolInput.js.map +1 -0
  136. package/dist/openai/react/hooks/useToolMetadata.d.ts +2 -0
  137. package/dist/openai/react/hooks/useToolMetadata.d.ts.map +1 -0
  138. package/dist/openai/react/hooks/useToolMetadata.js +5 -0
  139. package/dist/openai/react/hooks/useToolMetadata.js.map +1 -0
  140. package/dist/openai/react/hooks/useToolName.d.ts.map +1 -0
  141. package/dist/openai/react/hooks/useToolName.js +5 -0
  142. package/dist/openai/react/hooks/useToolName.js.map +1 -0
  143. package/dist/{react → openai/react}/hooks/useWidgetState.d.ts +1 -1
  144. package/dist/openai/react/hooks/useWidgetState.d.ts.map +1 -0
  145. package/dist/openai/react/hooks/useWidgetState.js.map +1 -0
  146. package/dist/openai/react/index.d.ts +6 -0
  147. package/dist/openai/react/index.d.ts.map +1 -0
  148. package/dist/openai/react/index.js +6 -0
  149. package/dist/openai/react/index.js.map +1 -0
  150. package/dist/{types/openai.d.ts → openai/types.d.ts} +7 -11
  151. package/dist/openai/types.d.ts.map +1 -0
  152. package/dist/{types/openai.js → openai/types.js} +1 -1
  153. package/dist/openai/types.js.map +1 -0
  154. package/dist/react/ApolloProvider.d.ts +6 -2
  155. package/dist/react/ApolloProvider.d.ts.map +1 -1
  156. package/dist/react/ApolloProvider.js +12 -27
  157. package/dist/react/ApolloProvider.js.map +1 -1
  158. package/dist/react/index.d.ts +6 -0
  159. package/dist/react/index.d.ts.map +1 -0
  160. package/dist/react/index.js +9 -0
  161. package/dist/react/index.js.map +1 -0
  162. package/dist/react/index.mcp.d.ts +3 -0
  163. package/dist/react/index.mcp.d.ts.map +1 -0
  164. package/dist/react/index.mcp.js +3 -0
  165. package/dist/react/index.mcp.js.map +1 -0
  166. package/dist/react/index.openai.d.ts +3 -0
  167. package/dist/react/index.openai.d.ts.map +1 -0
  168. package/dist/react/index.openai.js +3 -0
  169. package/dist/react/index.openai.js.map +1 -0
  170. package/dist/react/missingHook.d.ts +2 -0
  171. package/dist/react/missingHook.d.ts.map +1 -0
  172. package/dist/react/missingHook.js +6 -0
  173. package/dist/react/missingHook.js.map +1 -0
  174. package/dist/tsconfig/core/tsconfig.json +5 -0
  175. package/dist/tsconfig/mcp/tsconfig.json +6 -0
  176. package/dist/tsconfig/openai/tsconfig.json +7 -0
  177. package/dist/types/application-manifest.d.ts +5 -1
  178. package/dist/types/application-manifest.d.ts.map +1 -1
  179. package/dist/types/application-manifest.js.map +1 -1
  180. package/dist/utilities/cacheAsync.d.ts +4 -0
  181. package/dist/utilities/cacheAsync.d.ts.map +1 -0
  182. package/dist/utilities/cacheAsync.js +19 -0
  183. package/dist/utilities/cacheAsync.js.map +1 -0
  184. package/dist/utilities/constants.d.ts +6 -0
  185. package/dist/utilities/constants.d.ts.map +1 -0
  186. package/dist/utilities/constants.js +6 -0
  187. package/dist/utilities/constants.js.map +1 -0
  188. package/dist/utilities/emptyModule.d.ts +2 -0
  189. package/dist/utilities/emptyModule.d.ts.map +1 -0
  190. package/dist/utilities/emptyModule.js +2 -0
  191. package/dist/utilities/emptyModule.js.map +1 -0
  192. package/dist/utilities/getVariablesForOperationFromToolInput.d.ts +5 -0
  193. package/dist/utilities/getVariablesForOperationFromToolInput.d.ts.map +1 -0
  194. package/dist/utilities/getVariablesForOperationFromToolInput.js +18 -0
  195. package/dist/utilities/getVariablesForOperationFromToolInput.js.map +1 -0
  196. package/dist/utilities/index.d.ts +6 -0
  197. package/dist/utilities/index.d.ts.map +1 -0
  198. package/dist/utilities/index.js +6 -0
  199. package/dist/utilities/index.js.map +1 -0
  200. package/dist/utilities/invariant.d.ts +2 -0
  201. package/dist/utilities/invariant.d.ts.map +1 -0
  202. package/dist/utilities/invariant.js +6 -0
  203. package/dist/utilities/invariant.js.map +1 -0
  204. package/dist/utilities/promiseWithResolvers.d.ts +7 -0
  205. package/dist/utilities/promiseWithResolvers.d.ts.map +1 -0
  206. package/dist/utilities/promiseWithResolvers.js +16 -0
  207. package/dist/utilities/promiseWithResolvers.js.map +1 -0
  208. package/dist/vite/__tests__/utilities/build.d.ts +41 -0
  209. package/dist/vite/__tests__/utilities/build.d.ts.map +1 -0
  210. package/dist/vite/__tests__/utilities/build.js +63 -0
  211. package/dist/vite/__tests__/utilities/build.js.map +1 -0
  212. package/dist/vite/apolloClientAiApps.d.ts +14 -0
  213. package/dist/vite/apolloClientAiApps.d.ts.map +1 -0
  214. package/dist/vite/apolloClientAiApps.js +350 -0
  215. package/dist/vite/apolloClientAiApps.js.map +1 -0
  216. package/dist/vite/index.d.ts +1 -2
  217. package/dist/vite/index.d.ts.map +1 -1
  218. package/dist/vite/index.js +1 -2
  219. package/dist/vite/index.js.map +1 -1
  220. package/dist/vite/utilities/config.d.ts +2 -0
  221. package/dist/vite/utilities/config.d.ts.map +1 -0
  222. package/dist/vite/utilities/config.js +11 -0
  223. package/dist/vite/utilities/config.js.map +1 -0
  224. package/dist/vite/utilities/graphql.d.ts +20 -0
  225. package/dist/vite/utilities/graphql.d.ts.map +1 -0
  226. package/dist/vite/utilities/graphql.js +42 -0
  227. package/dist/vite/utilities/graphql.js.map +1 -0
  228. package/knope.toml +1 -1
  229. package/package.json +105 -9
  230. package/src/config/defineConfig.ts +8 -0
  231. package/src/config/index.ts +2 -0
  232. package/src/config/schema.ts +73 -0
  233. package/src/config/types.ts +7 -0
  234. package/src/core/ApolloClient.ts +7 -95
  235. package/src/core/Platform.ts +27 -0
  236. package/src/core/types.ts +14 -0
  237. package/src/index.mcp.ts +5 -0
  238. package/src/index.openai.ts +5 -0
  239. package/src/index.ts +2 -27
  240. package/src/link/ToolCallLink.ts +6 -22
  241. package/src/mcp/core/ApolloClient.ts +102 -0
  242. package/src/mcp/core/McpAppManager.ts +98 -0
  243. package/src/mcp/core/Platform.ts +11 -0
  244. package/src/mcp/core/__tests__/ApolloClient.test.ts +464 -0
  245. package/src/mcp/index.ts +2 -0
  246. package/src/mcp/link/ToolCallLink.ts +40 -0
  247. package/src/mcp/link/__tests__/ToolCallLink.test.ts +53 -0
  248. package/src/mcp/react/hooks/__tests__/useApp.test.tsx +46 -0
  249. package/src/mcp/react/hooks/__tests__/useToolInput.test.tsx +50 -0
  250. package/src/mcp/react/hooks/__tests__/useToolMetadata.test.tsx +53 -0
  251. package/src/mcp/react/hooks/__tests__/useToolName.test.tsx +50 -0
  252. package/src/mcp/react/hooks/useApolloClient.ts +14 -0
  253. package/src/mcp/react/hooks/useApp.ts +5 -0
  254. package/src/mcp/react/hooks/useToolInput.ts +5 -0
  255. package/src/mcp/react/hooks/useToolMetadata.ts +5 -0
  256. package/src/mcp/react/hooks/useToolName.ts +5 -0
  257. package/src/mcp/react/index.ts +4 -0
  258. package/src/openai/core/ApolloClient.ts +100 -0
  259. package/src/openai/core/McpAppManager.ts +110 -0
  260. package/src/openai/core/Platform.ts +11 -0
  261. package/src/openai/core/__tests__/ApolloClient.test.ts +537 -0
  262. package/src/openai/globals.ts +14 -0
  263. package/src/openai/index.ts +2 -0
  264. package/src/openai/link/ToolCallLink.ts +40 -0
  265. package/src/{react → openai/react}/hooks/__tests__/useOpenAiGlobal.test.ts +1 -1
  266. package/src/openai/react/hooks/__tests__/useToolInput.test.tsx +85 -0
  267. package/src/openai/react/hooks/__tests__/useToolMetadata.test.tsx +86 -0
  268. package/src/openai/react/hooks/__tests__/useToolName.test.tsx +50 -0
  269. package/src/{react → openai/react}/hooks/__tests__/useWidgetState.test.tsx +1 -1
  270. package/src/openai/react/hooks/useApolloClient.ts +14 -0
  271. package/src/openai/react/hooks/useApp.ts +5 -0
  272. package/src/{react → openai/react}/hooks/useOpenAiGlobal.ts +2 -2
  273. package/src/openai/react/hooks/useToolInput.ts +5 -0
  274. package/src/openai/react/hooks/useToolMetadata.ts +5 -0
  275. package/src/openai/react/hooks/useToolName.ts +5 -0
  276. package/src/{react → openai/react}/hooks/useWidgetState.ts +1 -1
  277. package/src/openai/react/index.ts +5 -0
  278. package/src/{types/openai.ts → openai/types.ts} +9 -13
  279. package/src/react/ApolloProvider.tsx +23 -31
  280. package/src/react/__tests__/ApolloProvider/mcp.test.tsx +74 -0
  281. package/src/react/__tests__/ApolloProvider/openai.test.tsx +146 -0
  282. package/src/react/index.mcp.ts +7 -0
  283. package/src/react/index.openai.ts +7 -0
  284. package/src/react/index.ts +19 -0
  285. package/src/react/missingHook.ts +9 -0
  286. package/src/testing/internal/index.ts +8 -0
  287. package/src/testing/internal/matchers/index.ts +2 -0
  288. package/src/testing/internal/matchers/toComplete.ts +46 -0
  289. package/src/testing/internal/matchers/toEmitValue.ts +71 -0
  290. package/src/testing/internal/matchers/types.ts +3 -0
  291. package/src/testing/internal/mcp/graphqlToolResult.ts +31 -0
  292. package/src/testing/internal/mcp/minimalHostContextWithToolName.ts +9 -0
  293. package/src/testing/internal/mcp/mockMcpHost.ts +188 -0
  294. package/src/testing/internal/openai/dispatchStateChange.ts +1 -1
  295. package/src/testing/internal/openai/stubOpenAiGlobals.ts +22 -9
  296. package/src/testing/internal/react/renderAsync.ts +7 -0
  297. package/src/testing/internal/utilities/ObservableStream.ts +172 -0
  298. package/src/testing/internal/utilities/getSerializableProperties.ts +55 -0
  299. package/src/testing/internal/utilities/mockApplicationManifest.ts +39 -0
  300. package/src/testing/internal/utilities/spyOnConsole.ts +29 -0
  301. package/src/testing/internal/utilities/wait.ts +3 -0
  302. package/src/tsconfig/core/tsconfig.json +5 -0
  303. package/src/tsconfig/mcp/tsconfig.json +6 -0
  304. package/src/tsconfig/openai/tsconfig.json +7 -0
  305. package/src/types/application-manifest.ts +7 -1
  306. package/src/utilities/__tests__/cacheAsync.test.ts +64 -0
  307. package/src/utilities/cacheAsync.ts +25 -0
  308. package/src/utilities/constants.ts +5 -0
  309. package/src/utilities/emptyModule.ts +1 -0
  310. package/src/utilities/getVariablesForOperationFromToolInput.ts +27 -0
  311. package/src/utilities/index.ts +5 -0
  312. package/src/utilities/invariant.ts +5 -0
  313. package/src/utilities/promiseWithResolvers.ts +18 -0
  314. package/src/vite/__tests__/apolloClientAiApps.test.ts +1521 -0
  315. package/src/vite/__tests__/utilities/build.ts +72 -0
  316. package/src/vite/apolloClientAiApps.ts +515 -0
  317. package/src/vite/index.ts +1 -2
  318. package/src/vite/utilities/config.ts +13 -0
  319. package/src/vite/utilities/graphql.ts +123 -0
  320. package/tsconfig.base.json +2 -2
  321. package/tsconfig.vite.build.json +4 -1
  322. package/tsconfig.vite.json +8 -2
  323. package/vitest-setup.ts +28 -0
  324. package/dist/react/context/ToolUseContext.d.ts +0 -16
  325. package/dist/react/context/ToolUseContext.d.ts.map +0 -1
  326. package/dist/react/context/ToolUseContext.js +0 -11
  327. package/dist/react/context/ToolUseContext.js.map +0 -1
  328. package/dist/react/hooks/useCallTool.d.ts +0 -4
  329. package/dist/react/hooks/useCallTool.d.ts.map +0 -1
  330. package/dist/react/hooks/useCallTool.js +0 -5
  331. package/dist/react/hooks/useCallTool.js.map +0 -1
  332. package/dist/react/hooks/useOpenAiGlobal.d.ts +0 -3
  333. package/dist/react/hooks/useOpenAiGlobal.d.ts.map +0 -1
  334. package/dist/react/hooks/useOpenAiGlobal.js.map +0 -1
  335. package/dist/react/hooks/useOpenExternal.d.ts +0 -4
  336. package/dist/react/hooks/useOpenExternal.d.ts.map +0 -1
  337. package/dist/react/hooks/useOpenExternal.js +0 -5
  338. package/dist/react/hooks/useOpenExternal.js.map +0 -1
  339. package/dist/react/hooks/useRequestDisplayMode.d.ts +0 -7
  340. package/dist/react/hooks/useRequestDisplayMode.d.ts.map +0 -1
  341. package/dist/react/hooks/useRequestDisplayMode.js +0 -6
  342. package/dist/react/hooks/useRequestDisplayMode.js.map +0 -1
  343. package/dist/react/hooks/useSendFollowUpMessage.d.ts +0 -2
  344. package/dist/react/hooks/useSendFollowUpMessage.d.ts.map +0 -1
  345. package/dist/react/hooks/useSendFollowUpMessage.js +0 -8
  346. package/dist/react/hooks/useSendFollowUpMessage.js.map +0 -1
  347. package/dist/react/hooks/useToolEffect.d.ts +0 -3
  348. package/dist/react/hooks/useToolEffect.d.ts.map +0 -1
  349. package/dist/react/hooks/useToolEffect.js +0 -28
  350. package/dist/react/hooks/useToolEffect.js.map +0 -1
  351. package/dist/react/hooks/useToolInput.d.ts +0 -2
  352. package/dist/react/hooks/useToolInput.d.ts.map +0 -1
  353. package/dist/react/hooks/useToolInput.js +0 -6
  354. package/dist/react/hooks/useToolInput.js.map +0 -1
  355. package/dist/react/hooks/useToolName.d.ts.map +0 -1
  356. package/dist/react/hooks/useToolName.js +0 -6
  357. package/dist/react/hooks/useToolName.js.map +0 -1
  358. package/dist/react/hooks/useToolOutput.d.ts +0 -2
  359. package/dist/react/hooks/useToolOutput.d.ts.map +0 -1
  360. package/dist/react/hooks/useToolOutput.js +0 -5
  361. package/dist/react/hooks/useToolOutput.js.map +0 -1
  362. package/dist/react/hooks/useToolResponseMetadata.d.ts +0 -2
  363. package/dist/react/hooks/useToolResponseMetadata.d.ts.map +0 -1
  364. package/dist/react/hooks/useToolResponseMetadata.js +0 -5
  365. package/dist/react/hooks/useToolResponseMetadata.js.map +0 -1
  366. package/dist/react/hooks/useWidgetState.d.ts.map +0 -1
  367. package/dist/react/hooks/useWidgetState.js.map +0 -1
  368. package/dist/types/openai.d.ts.map +0 -1
  369. package/dist/types/openai.js.map +0 -1
  370. package/dist/vite/absolute_asset_imports_plugin.d.ts +0 -5
  371. package/dist/vite/absolute_asset_imports_plugin.d.ts.map +0 -1
  372. package/dist/vite/absolute_asset_imports_plugin.js +0 -17
  373. package/dist/vite/absolute_asset_imports_plugin.js.map +0 -1
  374. package/dist/vite/application_manifest_plugin.d.ts +0 -10
  375. package/dist/vite/application_manifest_plugin.d.ts.map +0 -1
  376. package/dist/vite/application_manifest_plugin.js +0 -317
  377. package/dist/vite/application_manifest_plugin.js.map +0 -1
  378. package/src/core/__tests__/ApolloClient.test.ts +0 -646
  379. package/src/react/__tests__/ApolloProvider.test.tsx +0 -41
  380. package/src/react/context/ToolUseContext.tsx +0 -31
  381. package/src/react/hooks/__tests__/useCallTool.test.ts +0 -46
  382. package/src/react/hooks/__tests__/useOpenExternal.test.tsx +0 -24
  383. package/src/react/hooks/__tests__/useRequestDisplayMode.test.ts +0 -17
  384. package/src/react/hooks/__tests__/useSendFollowUpMessage.test.ts +0 -15
  385. package/src/react/hooks/__tests__/useToolEffect.test.tsx +0 -67
  386. package/src/react/hooks/__tests__/useToolInput.test.ts +0 -13
  387. package/src/react/hooks/__tests__/useToolName.test.ts +0 -13
  388. package/src/react/hooks/__tests__/useToolOutput.test.tsx +0 -49
  389. package/src/react/hooks/__tests__/useToolResponseMetadata.test.tsx +0 -49
  390. package/src/react/hooks/useCallTool.ts +0 -13
  391. package/src/react/hooks/useOpenExternal.ts +0 -11
  392. package/src/react/hooks/useRequestDisplayMode.ts +0 -7
  393. package/src/react/hooks/useSendFollowUpMessage.ts +0 -7
  394. package/src/react/hooks/useToolEffect.tsx +0 -37
  395. package/src/react/hooks/useToolInput.ts +0 -7
  396. package/src/react/hooks/useToolName.ts +0 -7
  397. package/src/react/hooks/useToolOutput.ts +0 -5
  398. package/src/react/hooks/useToolResponseMetadata.ts +0 -5
  399. package/src/vite/__tests__/absolute_asset_imports_plugin.test.ts +0 -102
  400. package/src/vite/__tests__/application_manifest_plugin.test.ts +0 -1199
  401. package/src/vite/absolute_asset_imports_plugin.ts +0 -22
  402. package/src/vite/application_manifest_plugin.ts +0 -539
  403. /package/dist/{react → openai/react}/hooks/useToolName.d.ts +0 -0
  404. /package/dist/{react → openai/react}/hooks/useWidgetState.js +0 -0
@@ -0,0 +1,98 @@
1
+ import { App, PostMessageTransport } from "@modelcontextprotocol/ext-apps";
2
+ import type { CallToolResult } from "@modelcontextprotocol/sdk/types.js";
3
+ import type { ApplicationManifest } from "../../types/application-manifest";
4
+ import type { FormattedExecutionResult } from "graphql";
5
+ import type { DocumentNode, OperationVariables } from "@apollo/client";
6
+ import { print } from "@apollo/client/utilities";
7
+ import { cacheAsync, promiseWithResolvers } from "../../utilities";
8
+ import type { ApolloMcpServerApps } from "../../core/types";
9
+
10
+ type ExecuteQueryCallToolResult = Omit<CallToolResult, "structuredContent"> & {
11
+ structuredContent: FormattedExecutionResult;
12
+ };
13
+
14
+ /** @internal */
15
+ export class McpAppManager {
16
+ readonly app: App;
17
+
18
+ #toolName: string | undefined;
19
+ #toolMetadata: ApolloMcpServerApps.CallToolResult["_meta"];
20
+ #toolInput: Record<string, unknown> | undefined;
21
+
22
+ constructor(manifest: ApplicationManifest) {
23
+ this.app = new App({ name: manifest.name, version: manifest.appVersion });
24
+ }
25
+
26
+ get toolName() {
27
+ return this.#toolName;
28
+ }
29
+
30
+ get toolMetadata() {
31
+ return this.#toolMetadata;
32
+ }
33
+
34
+ get toolInput() {
35
+ return this.#toolInput;
36
+ }
37
+
38
+ waitForInitialization = cacheAsync(async () => {
39
+ let toolResult = promiseWithResolvers<ApolloMcpServerApps.CallToolResult>();
40
+ let toolInput = promiseWithResolvers<Parameters<App["ontoolinput"]>[0]>();
41
+
42
+ this.app.ontoolresult = (params) => {
43
+ toolResult.resolve(
44
+ params as unknown as ApolloMcpServerApps.CallToolResult
45
+ );
46
+ };
47
+
48
+ this.app.ontoolinput = (params) => {
49
+ toolInput.resolve(params);
50
+ };
51
+
52
+ await this.connect();
53
+
54
+ const { structuredContent, _meta } = await toolResult.promise;
55
+ const { arguments: args } = await toolInput.promise;
56
+
57
+ this.#toolName = this.app.getHostContext()?.toolInfo?.tool.name;
58
+ this.#toolMetadata = _meta;
59
+ this.#toolInput = args;
60
+
61
+ return {
62
+ ...structuredContent,
63
+ toolName: this.toolName,
64
+ args,
65
+ };
66
+ });
67
+
68
+ close() {
69
+ return this.app.close();
70
+ }
71
+
72
+ async executeQuery({
73
+ query,
74
+ variables,
75
+ }: {
76
+ query: DocumentNode;
77
+ variables: OperationVariables | undefined;
78
+ }) {
79
+ const result = (await this.app.callServerTool({
80
+ name: "execute",
81
+ arguments: { query: print(query), variables },
82
+ })) as ExecuteQueryCallToolResult;
83
+
84
+ return result.structuredContent;
85
+ }
86
+
87
+ private async connect() {
88
+ try {
89
+ return await this.app.connect(
90
+ new PostMessageTransport(window.parent, window.parent)
91
+ );
92
+ } catch (e) {
93
+ const error = e instanceof Error ? e : new Error("Failed to connect");
94
+
95
+ throw error;
96
+ }
97
+ }
98
+ }
@@ -0,0 +1,11 @@
1
+ export const Platform = Object.freeze({
2
+ target: "mcp",
3
+ select<
4
+ T = unknown,
5
+ TReturn = T extends (...args: any[]) => infer TReturn ? TReturn : T,
6
+ >(config: { mcp?: T; openai?: T }): TReturn | undefined {
7
+ const value = config.mcp;
8
+
9
+ return typeof value === "function" ? value() : (value as TReturn);
10
+ },
11
+ });
@@ -0,0 +1,464 @@
1
+ import { expect, test, vi } from "vitest";
2
+ import { ApolloClient } from "../ApolloClient.js";
3
+ import { ApolloLink, HttpLink, InMemoryCache, gql } from "@apollo/client";
4
+ import { print } from "@apollo/client/utilities";
5
+ import { ToolCallLink } from "../../link/ToolCallLink.js";
6
+ import {
7
+ minimalHostContextWithToolName,
8
+ mockApplicationManifest,
9
+ mockMcpHost,
10
+ spyOnConsole,
11
+ } from "../../../testing/internal/index.js";
12
+
13
+ test("writes tool result data to cache", async () => {
14
+ using _ = spyOnConsole("debug");
15
+
16
+ const query = gql`
17
+ query Product($id: ID!) {
18
+ product(id: $id) {
19
+ id
20
+ title
21
+ __typename
22
+ }
23
+ }
24
+ `;
25
+
26
+ const client = new ApolloClient({
27
+ cache: new InMemoryCache(),
28
+ manifest: mockApplicationManifest({
29
+ operations: [
30
+ {
31
+ id: "1",
32
+ name: "Product",
33
+ body: print(query),
34
+ type: "query",
35
+ prefetch: false,
36
+ variables: { id: "ID" },
37
+ tools: [{ name: "GetProduct", description: "Get a product" }],
38
+ },
39
+ ],
40
+ }),
41
+ });
42
+
43
+ using host = await mockMcpHost({
44
+ hostContext: minimalHostContextWithToolName("GetProduct"),
45
+ });
46
+ host.onCleanup(() => client.stop());
47
+
48
+ host.sendToolResult({
49
+ content: [],
50
+ structuredContent: {
51
+ result: {
52
+ data: {
53
+ product: { id: "1", title: "Pen", __typename: "Product" },
54
+ },
55
+ },
56
+ },
57
+ });
58
+ host.sendToolInput({ arguments: { id: "1" } });
59
+
60
+ await client.waitForInitialization();
61
+
62
+ expect(client.extract()).toEqual({
63
+ "Product:1": {
64
+ __typename: "Product",
65
+ id: "1",
66
+ title: "Pen",
67
+ },
68
+ ROOT_QUERY: {
69
+ __typename: "Query",
70
+ 'product({"id":"1"})': {
71
+ __ref: "Product:1",
72
+ },
73
+ },
74
+ });
75
+ });
76
+
77
+ test("writes prefetch data to cache", async () => {
78
+ using _ = spyOnConsole("debug");
79
+
80
+ const query = gql`
81
+ query TopProducts {
82
+ topProducts {
83
+ id
84
+ title
85
+ __typename
86
+ }
87
+ }
88
+ `;
89
+
90
+ const client = new ApolloClient({
91
+ cache: new InMemoryCache(),
92
+ manifest: mockApplicationManifest({
93
+ operations: [
94
+ {
95
+ id: "1",
96
+ name: "TopProducts",
97
+ body: print(query),
98
+ type: "query",
99
+ prefetch: true,
100
+ prefetchID: "__anonymous",
101
+ variables: {},
102
+ tools: [{ name: "TopProducts", description: "Shows top products" }],
103
+ },
104
+ ],
105
+ }),
106
+ });
107
+
108
+ using host = await mockMcpHost({
109
+ hostContext: minimalHostContextWithToolName("OtherTool"),
110
+ });
111
+ host.onCleanup(() => client.stop());
112
+
113
+ host.sendToolResult({
114
+ content: [],
115
+ structuredContent: {
116
+ prefetch: {
117
+ __anonymous: {
118
+ data: {
119
+ topProducts: [{ id: "1", title: "iPhone", __typename: "Product" }],
120
+ },
121
+ },
122
+ },
123
+ },
124
+ });
125
+ host.sendToolInput({ arguments: {} });
126
+
127
+ await client.waitForInitialization();
128
+
129
+ expect(client.extract()).toEqual({
130
+ "Product:1": {
131
+ __typename: "Product",
132
+ id: "1",
133
+ title: "iPhone",
134
+ },
135
+ ROOT_QUERY: {
136
+ __typename: "Query",
137
+ topProducts: [{ __ref: "Product:1" }],
138
+ },
139
+ });
140
+ });
141
+
142
+ test("writes prefetch and tool response data to cache when both are provided", async () => {
143
+ using _ = spyOnConsole("debug");
144
+
145
+ const prefetchQuery = gql`
146
+ query TopProducts {
147
+ topProducts {
148
+ id
149
+ title
150
+ __typename
151
+ }
152
+ }
153
+ `;
154
+
155
+ const query = gql`
156
+ query Product($id: ID!) {
157
+ product(id: $id) {
158
+ id
159
+ title
160
+ __typename
161
+ }
162
+ }
163
+ `;
164
+
165
+ const client = new ApolloClient({
166
+ cache: new InMemoryCache(),
167
+ manifest: mockApplicationManifest({
168
+ operations: [
169
+ {
170
+ id: "1",
171
+ name: "TopProducts",
172
+ body: print(prefetchQuery),
173
+ type: "query",
174
+ prefetch: true,
175
+ prefetchID: "__anonymous",
176
+ variables: {},
177
+ tools: [{ name: "TopProducts", description: "Shows top products" }],
178
+ },
179
+ {
180
+ id: "2",
181
+ name: "Product",
182
+ body: print(query),
183
+ type: "query",
184
+ prefetch: false,
185
+ variables: { id: "ID" },
186
+ tools: [{ name: "Product", description: "Get a product by id" }],
187
+ },
188
+ ],
189
+ }),
190
+ });
191
+
192
+ using host = await mockMcpHost({
193
+ hostContext: minimalHostContextWithToolName("Product"),
194
+ });
195
+ host.onCleanup(() => client.stop());
196
+
197
+ host.sendToolResult({
198
+ content: [],
199
+ structuredContent: {
200
+ prefetch: {
201
+ __anonymous: {
202
+ data: {
203
+ topProducts: [{ id: "1", title: "iPhone", __typename: "Product" }],
204
+ },
205
+ },
206
+ },
207
+ result: {
208
+ data: {
209
+ product: { __typename: "Product", id: "2", title: "iPad" },
210
+ },
211
+ },
212
+ },
213
+ });
214
+ host.sendToolInput({ arguments: { id: "2" } });
215
+
216
+ await client.waitForInitialization();
217
+
218
+ expect(client.extract()).toEqual({
219
+ "Product:1": {
220
+ __typename: "Product",
221
+ id: "1",
222
+ title: "iPhone",
223
+ },
224
+ "Product:2": {
225
+ __typename: "Product",
226
+ id: "2",
227
+ title: "iPad",
228
+ },
229
+ ROOT_QUERY: {
230
+ __typename: "Query",
231
+ topProducts: [{ __ref: "Product:1" }],
232
+ 'product({"id":"2"})': { __ref: "Product:2" },
233
+ },
234
+ });
235
+ });
236
+
237
+ test("excludes extra tool input variables not defined in the operation", async () => {
238
+ using _ = spyOnConsole("debug");
239
+
240
+ const query = gql`
241
+ query Product($id: ID!) {
242
+ product(id: $id) {
243
+ id
244
+ title
245
+ __typename
246
+ }
247
+ }
248
+ `;
249
+
250
+ const client = new ApolloClient({
251
+ cache: new InMemoryCache(),
252
+ manifest: mockApplicationManifest({
253
+ operations: [
254
+ {
255
+ id: "1",
256
+ name: "Product",
257
+ body: print(query),
258
+ type: "query",
259
+ prefetch: false,
260
+ variables: { id: "ID" },
261
+ tools: [{ name: "GetProduct", description: "Get a product" }],
262
+ },
263
+ ],
264
+ }),
265
+ });
266
+
267
+ using host = await mockMcpHost({
268
+ hostContext: minimalHostContextWithToolName("GetProduct"),
269
+ });
270
+ host.onCleanup(() => client.stop());
271
+
272
+ host.sendToolResult({
273
+ content: [],
274
+ structuredContent: {
275
+ result: {
276
+ data: {
277
+ product: { id: "1", title: "Pen", __typename: "Product" },
278
+ },
279
+ },
280
+ },
281
+ });
282
+ host.sendToolInput({ arguments: { id: "1", extraParam: "ignored" } });
283
+
284
+ await client.waitForInitialization();
285
+
286
+ expect(client.extract()).toEqual({
287
+ "Product:1": {
288
+ __typename: "Product",
289
+ id: "1",
290
+ title: "Pen",
291
+ },
292
+ ROOT_QUERY: {
293
+ __typename: "Query",
294
+ 'product({"id":"1"})': {
295
+ __ref: "Product:1",
296
+ },
297
+ },
298
+ });
299
+ });
300
+
301
+ test("allows for custom links provided to the constructor", async () => {
302
+ using _ = spyOnConsole("debug");
303
+ const manifest = mockApplicationManifest();
304
+ const linkHandler = vi.fn<ApolloLink.RequestHandler>((operation, forward) =>
305
+ forward(operation)
306
+ );
307
+
308
+ const client = new ApolloClient({
309
+ manifest,
310
+ cache: new InMemoryCache(),
311
+ link: ApolloLink.from([new ApolloLink(linkHandler), new ToolCallLink()]),
312
+ });
313
+
314
+ using host = await mockMcpHost({
315
+ hostContext: minimalHostContextWithToolName("GetProduct"),
316
+ });
317
+ host.onCleanup(() => client.stop());
318
+
319
+ host.sendToolResult({
320
+ content: [],
321
+ structuredContent: {
322
+ result: {
323
+ data: {
324
+ product: { id: "1", title: "Pen", __typename: "Product" },
325
+ },
326
+ },
327
+ },
328
+ });
329
+ host.sendToolInput({ arguments: {} });
330
+
331
+ host.mockToolCall("execute", () => ({
332
+ content: [],
333
+ structuredContent: {
334
+ data: {
335
+ product: {
336
+ id: "1",
337
+ title: "Pen",
338
+ rating: 5,
339
+ price: 1.0,
340
+ description: "Awesome pen",
341
+ images: [],
342
+ __typename: "Product",
343
+ },
344
+ },
345
+ },
346
+ }));
347
+
348
+ await client.waitForInitialization();
349
+
350
+ const variables = { id: "1" };
351
+ const query = gql(manifest.operations[0].body);
352
+
353
+ await expect(client.query({ query, variables })).resolves.toStrictEqual({
354
+ data: {
355
+ product: {
356
+ id: "1",
357
+ title: "Pen",
358
+ rating: 5,
359
+ price: 1.0,
360
+ description: "Awesome pen",
361
+ images: [],
362
+ __typename: "Product",
363
+ },
364
+ },
365
+ });
366
+
367
+ expect(linkHandler).toHaveBeenCalledOnce();
368
+ expect(linkHandler).toHaveBeenCalledWith(
369
+ expect.objectContaining({ query, variables, operationType: "query" }),
370
+ expect.any(Function)
371
+ );
372
+ });
373
+
374
+ test("enforces ToolCallLink as terminating link", () => {
375
+ const manifest = mockApplicationManifest();
376
+ const expectedError = new Error(
377
+ "The terminating link must be a `ToolCallLink`. If you are using a `split` link, ensure the `right` branch uses a `ToolCallLink` as the terminating link."
378
+ );
379
+
380
+ expect(() => {
381
+ new ApolloClient({
382
+ manifest,
383
+ cache: new InMemoryCache(),
384
+ link: new HttpLink(),
385
+ });
386
+ }).toThrow(expectedError);
387
+
388
+ expect(() => {
389
+ new ApolloClient({
390
+ manifest,
391
+ cache: new InMemoryCache(),
392
+ link: new ApolloLink(),
393
+ });
394
+ }).toThrow(expectedError);
395
+
396
+ expect(() => {
397
+ new ApolloClient({
398
+ manifest,
399
+ cache: new InMemoryCache(),
400
+ link: ApolloLink.from([new ApolloLink(), new HttpLink()]),
401
+ });
402
+ }).toThrow(expectedError);
403
+
404
+ expect(() => {
405
+ new ApolloClient({
406
+ manifest,
407
+ cache: new InMemoryCache(),
408
+ link: ApolloLink.split(() => true, new ToolCallLink(), new HttpLink()),
409
+ });
410
+ }).toThrow(expectedError);
411
+
412
+ // Allow you to use a custom terminating link for `split` links if the
413
+ // custom link is the `left` branch link.
414
+ expect(() => {
415
+ new ApolloClient({
416
+ manifest,
417
+ cache: new InMemoryCache(),
418
+ link: ApolloLink.split(() => true, new HttpLink(), new ToolCallLink()),
419
+ });
420
+ }).not.toThrow(expectedError);
421
+
422
+ expect(() => {
423
+ new ApolloClient({
424
+ manifest,
425
+ cache: new InMemoryCache(),
426
+ link: ApolloLink.split(
427
+ () => true,
428
+ new ToolCallLink(),
429
+ new ToolCallLink()
430
+ ),
431
+ });
432
+ }).not.toThrow();
433
+ });
434
+
435
+ test("allows ToolCallLink as terminating link", () => {
436
+ const manifest = mockApplicationManifest();
437
+
438
+ expect(() => {
439
+ new ApolloClient({
440
+ manifest,
441
+ cache: new InMemoryCache(),
442
+ link: ApolloLink.from([new ApolloLink(), new ToolCallLink()]),
443
+ });
444
+ }).not.toThrow();
445
+
446
+ expect(() => {
447
+ new ApolloClient({
448
+ manifest,
449
+ cache: new InMemoryCache(),
450
+ link: ApolloLink.split(() => true, new HttpLink(), new ToolCallLink()),
451
+ });
452
+ }).not.toThrow();
453
+ });
454
+
455
+ test("creates a default ToolCallLink when no link is provided", () => {
456
+ const manifest = mockApplicationManifest();
457
+
458
+ expect(() => {
459
+ new ApolloClient({
460
+ manifest,
461
+ cache: new InMemoryCache(),
462
+ });
463
+ }).not.toThrow();
464
+ });
@@ -0,0 +1,2 @@
1
+ export { ApolloClient } from "./core/ApolloClient.js";
2
+ export { ToolCallLink } from "./link/ToolCallLink.js";
@@ -0,0 +1,40 @@
1
+ import { ApolloLink, Observable } from "@apollo/client";
2
+ import { from } from "rxjs";
3
+ import type { ApolloClient as McpApolloClient } from "../core/ApolloClient";
4
+
5
+ /**
6
+ * A terminating link that sends a GraphQL request through an agent tool call.
7
+ * When providing a custom link chain to `ApolloClient`, `ApolloClient` will
8
+ * validate that the terminating link is an instance of this link.
9
+ *
10
+ * @example Providing a custom link chain
11
+ *
12
+ * ```ts
13
+ * import { ApolloLink } from "@apollo/client";
14
+ * import { ApolloClient, ToolCallLink } from "@apollo/client-ai-apps";
15
+ *
16
+ * const link = ApolloLink.from([
17
+ * ...otherLinks,
18
+ * new ToolCallLink()
19
+ * ]);
20
+ *
21
+ * const client = new ApolloClient({
22
+ * link,
23
+ * // ...
24
+ * });
25
+ * ```
26
+ */
27
+ export class ToolCallLink extends ApolloLink {
28
+ readonly name = "ToolCallLink";
29
+
30
+ request(operation: ApolloLink.Operation): Observable<ApolloLink.Result> {
31
+ const client = operation.client as McpApolloClient;
32
+
33
+ return from(
34
+ client["appManager"].executeQuery({
35
+ query: operation.query,
36
+ variables: operation.variables,
37
+ })
38
+ );
39
+ }
40
+ }
@@ -0,0 +1,53 @@
1
+ import { expect, test } from "vitest";
2
+ import { gql, InMemoryCache } from "@apollo/client";
3
+ import { execute } from "@apollo/client/link";
4
+ import { ApolloClient } from "../../core/ApolloClient.js";
5
+ import {
6
+ mockApplicationManifest,
7
+ mockMcpHost,
8
+ ObservableStream,
9
+ spyOnConsole,
10
+ } from "../../../testing/internal/index.js";
11
+ import { ToolCallLink } from "../ToolCallLink.js";
12
+
13
+ test("delegates query execution to MCP host", async () => {
14
+ using _ = spyOnConsole("debug");
15
+ const query = gql`
16
+ query GreetingQuery {
17
+ greeting
18
+ }
19
+ `;
20
+
21
+ const client = new ApolloClient({
22
+ cache: new InMemoryCache(),
23
+ manifest: mockApplicationManifest(),
24
+ });
25
+
26
+ using host = await mockMcpHost();
27
+ host.onCleanup(() => client.stop());
28
+
29
+ host.sendToolResult({
30
+ _meta: { toolName: "GetProduct" },
31
+ content: [],
32
+ structuredContent: {},
33
+ });
34
+ host.sendToolInput({ arguments: {} });
35
+
36
+ host.mockToolCall("execute", () => ({
37
+ content: [],
38
+ structuredContent: {
39
+ data: { greeting: "Hello, world" },
40
+ },
41
+ }));
42
+
43
+ await client.waitForInitialization();
44
+
45
+ const observable = execute(new ToolCallLink(), { query }, { client });
46
+ const stream = new ObservableStream(observable);
47
+
48
+ await expect(stream).toEmitValue({
49
+ data: { greeting: "Hello, world" },
50
+ });
51
+
52
+ await expect(stream).toComplete();
53
+ });
@@ -0,0 +1,46 @@
1
+ import { test, expect } from "vitest";
2
+ import {
3
+ disableActEnvironment,
4
+ renderHookToSnapshotStream,
5
+ } from "@testing-library/react-render-stream";
6
+ import { Suspense } from "react";
7
+ import { InMemoryCache } from "@apollo/client";
8
+ import { App } from "@modelcontextprotocol/ext-apps";
9
+
10
+ import { useApp } from "../useApp.js";
11
+ import { ApolloClient } from "../../../core/ApolloClient.js";
12
+ import {
13
+ mockApplicationManifest,
14
+ mockMcpHost,
15
+ spyOnConsole,
16
+ } from "../../../../testing/internal/index.js";
17
+ import { ApolloProvider } from "../../../../react/ApolloProvider.js";
18
+
19
+ test("returns app instance created by ApolloClient", async () => {
20
+ using _ = spyOnConsole("debug");
21
+ const client = new ApolloClient({
22
+ cache: new InMemoryCache(),
23
+ manifest: mockApplicationManifest(),
24
+ });
25
+
26
+ using host = await mockMcpHost();
27
+ host.onCleanup(() => client.stop());
28
+
29
+ host.sendToolInput({ arguments: {} });
30
+ host.sendToolResult({
31
+ _meta: { toolName: "Test" },
32
+ content: [],
33
+ structuredContent: {},
34
+ });
35
+
36
+ using _disabledAct = disableActEnvironment();
37
+ const { takeSnapshot } = await renderHookToSnapshotStream(() => useApp(), {
38
+ wrapper: ({ children }) => (
39
+ <Suspense>
40
+ <ApolloProvider client={client}>{children}</ApolloProvider>
41
+ </Suspense>
42
+ ),
43
+ });
44
+
45
+ await expect(takeSnapshot()).resolves.toBeInstanceOf(App);
46
+ });