@apollo/client-ai-apps 0.3.2 → 0.4.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 (140) hide show
  1. package/.github/workflows/pr.yaml +52 -3
  2. package/.github/workflows/prep-release.yml +38 -0
  3. package/.github/workflows/release.yaml +8 -4
  4. package/.github/workflows/verify-changeset.yml +58 -0
  5. package/CHANGELOG.md +88 -0
  6. package/dist/core/ApolloClient.d.ts +3 -2
  7. package/dist/core/ApolloClient.d.ts.map +1 -0
  8. package/dist/core/ApolloClient.js +65 -0
  9. package/dist/core/ApolloClient.js.map +1 -0
  10. package/dist/index.d.ts +18 -18
  11. package/dist/index.d.ts.map +1 -0
  12. package/dist/index.js +16 -279
  13. package/dist/index.js.map +1 -0
  14. package/dist/link/ToolCallLink.d.ts +1 -0
  15. package/dist/link/ToolCallLink.d.ts.map +1 -0
  16. package/dist/link/ToolCallLink.js +39 -0
  17. package/dist/link/ToolCallLink.js.map +1 -0
  18. package/dist/react/ApolloProvider.d.ts +4 -3
  19. package/dist/react/ApolloProvider.d.ts.map +1 -0
  20. package/dist/react/ApolloProvider.js +30 -0
  21. package/dist/react/ApolloProvider.js.map +1 -0
  22. package/dist/react/context/ToolUseContext.d.ts +4 -3
  23. package/dist/react/context/ToolUseContext.d.ts.map +1 -0
  24. package/dist/react/context/ToolUseContext.js +11 -0
  25. package/dist/react/context/ToolUseContext.js.map +1 -0
  26. package/dist/react/hooks/useCallTool.d.ts +4 -0
  27. package/dist/react/hooks/useCallTool.d.ts.map +1 -0
  28. package/dist/react/hooks/useCallTool.js +5 -0
  29. package/dist/react/hooks/useCallTool.js.map +1 -0
  30. package/dist/react/hooks/useOpenAiGlobal.d.ts +2 -1
  31. package/dist/react/hooks/useOpenAiGlobal.d.ts.map +1 -0
  32. package/dist/react/hooks/useOpenAiGlobal.js +20 -0
  33. package/dist/react/hooks/useOpenAiGlobal.js.map +1 -0
  34. package/dist/react/hooks/useOpenExternal.d.ts +1 -0
  35. package/dist/react/hooks/useOpenExternal.d.ts.map +1 -0
  36. package/dist/react/hooks/useOpenExternal.js +5 -0
  37. package/dist/react/hooks/useOpenExternal.js.map +1 -0
  38. package/dist/react/hooks/useRequestDisplayMode.d.ts +2 -1
  39. package/dist/react/hooks/useRequestDisplayMode.d.ts.map +1 -0
  40. package/dist/react/hooks/useRequestDisplayMode.js +6 -0
  41. package/dist/react/hooks/useRequestDisplayMode.js.map +1 -0
  42. package/dist/react/hooks/useSendFollowUpMessage.d.ts +1 -0
  43. package/dist/react/hooks/useSendFollowUpMessage.d.ts.map +1 -0
  44. package/dist/react/hooks/useSendFollowUpMessage.js +8 -0
  45. package/dist/react/hooks/useSendFollowUpMessage.js.map +1 -0
  46. package/dist/react/hooks/useToolEffect.d.ts +1 -0
  47. package/dist/react/hooks/useToolEffect.d.ts.map +1 -0
  48. package/dist/react/hooks/useToolEffect.js +28 -0
  49. package/dist/react/hooks/useToolEffect.js.map +1 -0
  50. package/dist/react/hooks/useToolInput.d.ts +1 -0
  51. package/dist/react/hooks/useToolInput.d.ts.map +1 -0
  52. package/dist/react/hooks/useToolInput.js +6 -0
  53. package/dist/react/hooks/useToolInput.js.map +1 -0
  54. package/dist/react/hooks/useToolName.d.ts +1 -0
  55. package/dist/react/hooks/useToolName.d.ts.map +1 -0
  56. package/dist/react/hooks/useToolName.js +6 -0
  57. package/dist/react/hooks/useToolName.js.map +1 -0
  58. package/dist/react/hooks/useToolOutput.d.ts +2 -1
  59. package/dist/react/hooks/useToolOutput.d.ts.map +1 -0
  60. package/dist/react/hooks/useToolOutput.js +5 -0
  61. package/dist/react/hooks/useToolOutput.js.map +1 -0
  62. package/dist/react/hooks/useToolResponseMetadata.d.ts +2 -1
  63. package/dist/react/hooks/useToolResponseMetadata.d.ts.map +1 -0
  64. package/dist/react/hooks/useToolResponseMetadata.js +5 -0
  65. package/dist/react/hooks/useToolResponseMetadata.js.map +1 -0
  66. package/dist/react/hooks/useWidgetState.d.ts +3 -2
  67. package/dist/react/hooks/useWidgetState.d.ts.map +1 -0
  68. package/dist/react/hooks/useWidgetState.js +27 -0
  69. package/dist/react/hooks/useWidgetState.js.map +1 -0
  70. package/dist/types/application-manifest.d.ts +15 -0
  71. package/dist/types/application-manifest.d.ts.map +1 -0
  72. package/dist/types/application-manifest.js +2 -0
  73. package/dist/types/application-manifest.js.map +1 -0
  74. package/dist/types/openai.d.ts +1 -0
  75. package/dist/types/openai.d.ts.map +1 -0
  76. package/dist/types/openai.js +6 -0
  77. package/dist/types/openai.js.map +1 -0
  78. package/dist/vite/absolute_asset_imports_plugin.d.ts +1 -0
  79. package/dist/vite/absolute_asset_imports_plugin.d.ts.map +1 -0
  80. package/dist/vite/absolute_asset_imports_plugin.js +17 -0
  81. package/dist/vite/absolute_asset_imports_plugin.js.map +1 -0
  82. package/dist/vite/application_manifest_plugin.d.ts +2 -1
  83. package/dist/vite/application_manifest_plugin.d.ts.map +1 -0
  84. package/dist/vite/application_manifest_plugin.js +317 -0
  85. package/dist/vite/application_manifest_plugin.js.map +1 -0
  86. package/dist/vite/index.d.ts +3 -2
  87. package/dist/vite/index.d.ts.map +1 -0
  88. package/dist/vite/index.js +3 -307
  89. package/dist/vite/index.js.map +1 -0
  90. package/knope.toml +63 -0
  91. package/package.json +19 -11
  92. package/src/core/ApolloClient.ts +10 -5
  93. package/src/core/__tests__/ApolloClient.test.ts +33 -10
  94. package/src/index.ts +19 -18
  95. package/src/react/ApolloProvider.tsx +4 -3
  96. package/src/react/__tests__/ApolloProvider.test.tsx +3 -3
  97. package/src/react/context/ToolUseContext.tsx +2 -1
  98. package/src/react/hooks/__tests__/useCallTool.test.ts +1 -1
  99. package/src/react/hooks/__tests__/useOpenAiGlobal.test.ts +6 -6
  100. package/src/react/hooks/__tests__/useOpenExternal.test.tsx +2 -2
  101. package/src/react/hooks/__tests__/useRequestDisplayMode.test.ts +2 -2
  102. package/src/react/hooks/__tests__/useSendFollowUpMessage.test.ts +1 -1
  103. package/src/react/hooks/__tests__/useToolEffect.test.tsx +2 -2
  104. package/src/react/hooks/__tests__/useToolInput.test.ts +1 -1
  105. package/src/react/hooks/__tests__/useToolName.test.ts +1 -1
  106. package/src/react/hooks/__tests__/useToolOutput.test.tsx +2 -2
  107. package/src/react/hooks/__tests__/useToolResponseMetadata.test.tsx +2 -2
  108. package/src/react/hooks/__tests__/useWidgetState.test.tsx +2 -2
  109. package/src/react/hooks/useOpenAiGlobal.ts +2 -5
  110. package/src/react/hooks/useOpenExternal.ts +1 -1
  111. package/src/react/hooks/useRequestDisplayMode.ts +1 -1
  112. package/src/react/hooks/useToolEffect.tsx +3 -3
  113. package/src/react/hooks/useToolInput.ts +1 -1
  114. package/src/react/hooks/useToolName.ts +1 -1
  115. package/src/react/hooks/useToolOutput.ts +1 -1
  116. package/src/react/hooks/useToolResponseMetadata.ts +1 -1
  117. package/src/react/hooks/useWidgetState.ts +4 -3
  118. package/src/testing/internal/index.ts +2 -2
  119. package/src/testing/internal/matchers/index.ts +1 -1
  120. package/src/testing/internal/matchers/toRerender.ts +2 -2
  121. package/src/testing/internal/matchers/{index.d.ts → types.ts} +1 -1
  122. package/src/testing/internal/openai/dispatchStateChange.ts +1 -1
  123. package/src/testing/internal/openai/stubOpenAiGlobals.ts +6 -2
  124. package/src/types/application-manifest.ts +16 -0
  125. package/src/vite/__tests__/absolute_asset_imports_plugin.test.ts +2 -2
  126. package/src/vite/__tests__/application_manifest_plugin.test.ts +460 -240
  127. package/src/vite/application_manifest_plugin.ts +253 -93
  128. package/src/vite/index.ts +2 -2
  129. package/tsconfig.base.build.json +13 -0
  130. package/tsconfig.base.json +21 -0
  131. package/tsconfig.config.json +9 -0
  132. package/tsconfig.json +10 -0
  133. package/tsconfig.src.build.json +14 -0
  134. package/tsconfig.src.json +17 -0
  135. package/tsconfig.test.json +20 -0
  136. package/tsconfig.vite.build.json +6 -0
  137. package/tsconfig.vite.json +16 -0
  138. package/scripts/build-vite.mjs +0 -18
  139. package/scripts/build.mjs +0 -7
  140. package/scripts/shared.mjs +0 -9
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useToolInput.d.ts","sourceRoot":"","sources":["../../../src/react/hooks/useToolInput.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,YAAY,QAAO,GAI/B,CAAC"}
@@ -0,0 +1,6 @@
1
+ import { useOpenAiGlobal } from "./useOpenAiGlobal.js";
2
+ export const useToolInput = () => {
3
+ const toolInput = useOpenAiGlobal("toolInput");
4
+ return toolInput;
5
+ };
6
+ //# sourceMappingURL=useToolInput.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useToolInput.js","sourceRoot":"","sources":["../../../src/react/hooks/useToolInput.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAEvD,MAAM,CAAC,MAAM,YAAY,GAAG,GAAQ,EAAE;IACpC,MAAM,SAAS,GAAG,eAAe,CAAC,WAAW,CAAC,CAAC;IAE/C,OAAO,SAAS,CAAC;AACnB,CAAC,CAAC","sourcesContent":["import { useOpenAiGlobal } from \"./useOpenAiGlobal.js\";\n\nexport const useToolInput = (): any => {\n const toolInput = useOpenAiGlobal(\"toolInput\");\n\n return toolInput;\n};\n"]}
@@ -1 +1,2 @@
1
1
  export declare const useToolName: () => string | undefined;
2
+ //# sourceMappingURL=useToolName.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useToolName.d.ts","sourceRoot":"","sources":["../../../src/react/hooks/useToolName.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,WAAW,QAAO,MAAM,GAAG,SAIvC,CAAC"}
@@ -0,0 +1,6 @@
1
+ import { useOpenAiGlobal } from "./useOpenAiGlobal.js";
2
+ export const useToolName = () => {
3
+ const toolResponseMetadata = useOpenAiGlobal("toolResponseMetadata");
4
+ return toolResponseMetadata?.toolName;
5
+ };
6
+ //# sourceMappingURL=useToolName.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useToolName.js","sourceRoot":"","sources":["../../../src/react/hooks/useToolName.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAEvD,MAAM,CAAC,MAAM,WAAW,GAAG,GAAuB,EAAE;IAClD,MAAM,oBAAoB,GAAG,eAAe,CAAC,sBAAsB,CAAC,CAAC;IAErE,OAAO,oBAAoB,EAAE,QAAkB,CAAC;AAClD,CAAC,CAAC","sourcesContent":["import { useOpenAiGlobal } from \"./useOpenAiGlobal.js\";\n\nexport const useToolName = (): string | undefined => {\n const toolResponseMetadata = useOpenAiGlobal(\"toolResponseMetadata\");\n\n return toolResponseMetadata?.toolName as string;\n};\n"]}
@@ -1 +1,2 @@
1
- export declare function useToolOutput(): import("../..").UnknownObject;
1
+ export declare function useToolOutput(): import("../../index.js").UnknownObject | null;
2
+ //# sourceMappingURL=useToolOutput.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useToolOutput.d.ts","sourceRoot":"","sources":["../../../src/react/hooks/useToolOutput.ts"],"names":[],"mappings":"AAEA,wBAAgB,aAAa,kDAE5B"}
@@ -0,0 +1,5 @@
1
+ import { useOpenAiGlobal } from "./useOpenAiGlobal.js";
2
+ export function useToolOutput() {
3
+ return useOpenAiGlobal("toolOutput") ?? null;
4
+ }
5
+ //# sourceMappingURL=useToolOutput.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useToolOutput.js","sourceRoot":"","sources":["../../../src/react/hooks/useToolOutput.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAEvD,MAAM,UAAU,aAAa;IAC3B,OAAO,eAAe,CAAC,YAAY,CAAC,IAAI,IAAI,CAAC;AAC/C,CAAC","sourcesContent":["import { useOpenAiGlobal } from \"./useOpenAiGlobal.js\";\n\nexport function useToolOutput() {\n return useOpenAiGlobal(\"toolOutput\") ?? null;\n}\n"]}
@@ -1 +1,2 @@
1
- export declare function useToolResponseMetadata(): import("../..").UnknownObject;
1
+ export declare function useToolResponseMetadata(): import("../../index.js").UnknownObject | null;
2
+ //# sourceMappingURL=useToolResponseMetadata.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useToolResponseMetadata.d.ts","sourceRoot":"","sources":["../../../src/react/hooks/useToolResponseMetadata.ts"],"names":[],"mappings":"AAEA,wBAAgB,uBAAuB,kDAEtC"}
@@ -0,0 +1,5 @@
1
+ import { useOpenAiGlobal } from "./useOpenAiGlobal.js";
2
+ export function useToolResponseMetadata() {
3
+ return useOpenAiGlobal("toolResponseMetadata") ?? null;
4
+ }
5
+ //# sourceMappingURL=useToolResponseMetadata.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useToolResponseMetadata.js","sourceRoot":"","sources":["../../../src/react/hooks/useToolResponseMetadata.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAEvD,MAAM,UAAU,uBAAuB;IACrC,OAAO,eAAe,CAAC,sBAAsB,CAAC,IAAI,IAAI,CAAC;AACzD,CAAC","sourcesContent":["import { useOpenAiGlobal } from \"./useOpenAiGlobal.js\";\n\nexport function useToolResponseMetadata() {\n return useOpenAiGlobal(\"toolResponseMetadata\") ?? null;\n}\n"]}
@@ -1,4 +1,5 @@
1
- import { SetStateAction } from "react";
2
- import { UnknownObject } from "../../types/openai";
1
+ import type { SetStateAction } from "react";
2
+ import type { UnknownObject } from "../../types/openai.js";
3
3
  export declare function useWidgetState<T extends UnknownObject>(defaultState: T | (() => T)): readonly [T, (state: SetStateAction<T>) => void];
4
4
  export declare function useWidgetState<T extends UnknownObject>(defaultState?: T | (() => T | null) | null): readonly [T | null, (state: SetStateAction<T | null>) => void];
5
+ //# sourceMappingURL=useWidgetState.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useWidgetState.d.ts","sourceRoot":"","sources":["../../../src/react/hooks/useWidgetState.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,OAAO,CAAC;AAE5C,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAG3D,wBAAgB,cAAc,CAAC,CAAC,SAAS,aAAa,EACpD,YAAY,EAAE,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,GAC1B,SAAS,CAAC,CAAC,EAAE,CAAC,KAAK,EAAE,cAAc,CAAC,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC;AAEpD,wBAAgB,cAAc,CAAC,CAAC,SAAS,aAAa,EACpD,YAAY,CAAC,EAAE,CAAC,GAAG,CAAC,MAAM,CAAC,GAAG,IAAI,CAAC,GAAG,IAAI,GACzC,SAAS,CAAC,CAAC,GAAG,IAAI,EAAE,CAAC,KAAK,EAAE,cAAc,CAAC,CAAC,GAAG,IAAI,CAAC,KAAK,IAAI,CAAC,CAAC"}
@@ -0,0 +1,27 @@
1
+ import { useCallback, useState } from "react";
2
+ import { useOpenAiGlobal } from "./useOpenAiGlobal.js";
3
+ export function useWidgetState(defaultState) {
4
+ const widgetStateFromWindow = useOpenAiGlobal("widgetState");
5
+ const [previousWidgetStateFromWindow, setPreviousWidgetStateFromWindow] = useState(widgetStateFromWindow);
6
+ let [widgetState, _setWidgetState] = useState(() => {
7
+ if (widgetStateFromWindow != null) {
8
+ return widgetStateFromWindow;
9
+ }
10
+ return typeof defaultState === "function" ? defaultState() : ((defaultState ?? null));
11
+ });
12
+ if (previousWidgetStateFromWindow !== widgetStateFromWindow) {
13
+ _setWidgetState((widgetState = widgetStateFromWindow));
14
+ setPreviousWidgetStateFromWindow(widgetStateFromWindow);
15
+ }
16
+ const setWidgetState = useCallback((state) => {
17
+ _setWidgetState((prevState) => {
18
+ const newState = typeof state === "function" ? state(prevState) : state;
19
+ if (newState != null && typeof window !== "undefined") {
20
+ void window.openai?.setWidgetState?.(newState);
21
+ }
22
+ return newState;
23
+ });
24
+ }, []);
25
+ return [widgetState, setWidgetState];
26
+ }
27
+ //# sourceMappingURL=useWidgetState.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useWidgetState.js","sourceRoot":"","sources":["../../../src/react/hooks/useWidgetState.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AAE9C,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAUvD,MAAM,UAAU,cAAc,CAC5B,YAA0C;IAE1C,MAAM,qBAAqB,GAAG,eAAe,CAAC,aAAa,CAAM,CAAC;IAClE,MAAM,CAAC,6BAA6B,EAAE,gCAAgC,CAAC,GACrE,QAAQ,CAAC,qBAAqB,CAAC,CAAC;IAElC,IAAI,CAAC,WAAW,EAAE,eAAe,CAAC,GAAG,QAAQ,CAAW,GAAG,EAAE;QAC3D,IAAI,qBAAqB,IAAI,IAAI,EAAE,CAAC;YAClC,OAAO,qBAAqB,CAAC;QAC/B,CAAC;QAED,OAAO,OAAO,YAAY,KAAK,UAAU,CAAC,CAAC,CAAC,YAAY,EAAE,CAAC,CAAC,CAAC,CACzD,CAAC,YAAY,IAAI,IAAI,CAAC,CACvB,CAAC;IACN,CAAC,CAAC,CAAC;IAEH,IAAI,6BAA6B,KAAK,qBAAqB,EAAE,CAAC;QAC5D,eAAe,CAAC,CAAC,WAAW,GAAG,qBAAqB,CAAC,CAAC,CAAC;QACvD,gCAAgC,CAAC,qBAAqB,CAAC,CAAC;IAC1D,CAAC;IAED,MAAM,cAAc,GAAG,WAAW,CAAC,CAAC,KAA+B,EAAE,EAAE;QACrE,eAAe,CAAC,CAAC,SAAS,EAAE,EAAE;YAC5B,MAAM,QAAQ,GAAG,OAAO,KAAK,KAAK,UAAU,CAAC,CAAC,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC;YAExE,IAAI,QAAQ,IAAI,IAAI,IAAI,OAAO,MAAM,KAAK,WAAW,EAAE,CAAC;gBACtD,KAAK,MAAM,CAAC,MAAM,EAAE,cAAc,EAAE,CAAC,QAAQ,CAAC,CAAC;YACjD,CAAC;YAED,OAAO,QAAQ,CAAC;QAClB,CAAC,CAAC,CAAC;IACL,CAAC,EAAE,EAAE,CAAC,CAAC;IAEP,OAAO,CAAC,WAAW,EAAE,cAAc,CAAC,CAAC;AACvC,CAAC","sourcesContent":["import type { SetStateAction } from \"react\";\nimport { useCallback, useState } from \"react\";\nimport type { UnknownObject } from \"../../types/openai.js\";\nimport { useOpenAiGlobal } from \"./useOpenAiGlobal.js\";\n\nexport function useWidgetState<T extends UnknownObject>(\n defaultState: T | (() => T)\n): readonly [T, (state: SetStateAction<T>) => void];\n\nexport function useWidgetState<T extends UnknownObject>(\n defaultState?: T | (() => T | null) | null\n): readonly [T | null, (state: SetStateAction<T | null>) => void];\n\nexport function useWidgetState<T extends UnknownObject>(\n defaultState?: T | (() => T | null) | null\n): readonly [T | null, (state: SetStateAction<T | null>) => void] {\n const widgetStateFromWindow = useOpenAiGlobal(\"widgetState\") as T;\n const [previousWidgetStateFromWindow, setPreviousWidgetStateFromWindow] =\n useState(widgetStateFromWindow);\n\n let [widgetState, _setWidgetState] = useState<T | null>(() => {\n if (widgetStateFromWindow != null) {\n return widgetStateFromWindow;\n }\n\n return typeof defaultState === \"function\" ? defaultState() : (\n (defaultState ?? null)\n );\n });\n\n if (previousWidgetStateFromWindow !== widgetStateFromWindow) {\n _setWidgetState((widgetState = widgetStateFromWindow));\n setPreviousWidgetStateFromWindow(widgetStateFromWindow);\n }\n\n const setWidgetState = useCallback((state: SetStateAction<T | null>) => {\n _setWidgetState((prevState) => {\n const newState = typeof state === \"function\" ? state(prevState) : state;\n\n if (newState != null && typeof window !== \"undefined\") {\n void window.openai?.setWidgetState?.(newState);\n }\n\n return newState;\n });\n }, []);\n\n return [widgetState, setWidgetState];\n}\n"]}
@@ -7,6 +7,8 @@ export type ApplicationManifest = {
7
7
  resource: string;
8
8
  operations: ManifestOperation[];
9
9
  csp: ManifestCsp;
10
+ widgetSettings?: ManifestWidgetSettings;
11
+ labels?: ManifestLabels;
10
12
  };
11
13
  export type ManifestOperation = {
12
14
  id: string;
@@ -22,6 +24,12 @@ export type ManifestTool = {
22
24
  name: string;
23
25
  description: string;
24
26
  extraInputs?: ManifestExtraInput[];
27
+ labels?: ManifestLabels;
28
+ };
29
+ export type ManifestWidgetSettings = {
30
+ description?: string;
31
+ domain?: string;
32
+ prefersBorder?: boolean;
25
33
  };
26
34
  export type ManifestExtraInput = {
27
35
  name: string;
@@ -30,5 +38,12 @@ export type ManifestExtraInput = {
30
38
  };
31
39
  export type ManifestCsp = {
32
40
  connectDomains: string[];
41
+ frameDomains: string[];
42
+ redirectDomains: string[];
33
43
  resourceDomains: string[];
34
44
  };
45
+ export type ManifestLabels = {
46
+ "toolInvocation/invoking"?: string;
47
+ "toolInvocation/invoked"?: string;
48
+ };
49
+ //# sourceMappingURL=application-manifest.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"application-manifest.d.ts","sourceRoot":"","sources":["../../src/types/application-manifest.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,mBAAmB,GAAG;IAChC,MAAM,EAAE,wBAAwB,CAAC;IACjC,OAAO,EAAE,GAAG,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,iBAAiB,EAAE,CAAC;IAChC,GAAG,EAAE,WAAW,CAAC;IACjB,cAAc,CAAC,EAAE,sBAAsB,CAAC;IACxC,MAAM,CAAC,EAAE,cAAc,CAAC;CACzB,CAAC;AAEF,MAAM,MAAM,iBAAiB,GAAG;IAC9B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,OAAO,GAAG,UAAU,CAAC;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAC;IAC/C,QAAQ,EAAE,OAAO,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,KAAK,EAAE,YAAY,EAAE,CAAC;CACvB,CAAC;AAEF,MAAM,MAAM,YAAY,GAAG;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,CAAC,EAAE,kBAAkB,EAAE,CAAC;IACnC,MAAM,CAAC,EAAE,cAAc,CAAC;CACzB,CAAC;AAEF,MAAM,MAAM,sBAAsB,GAAG;IACnC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,aAAa,CAAC,EAAE,OAAO,CAAC;CACzB,CAAC;AAEF,MAAM,MAAM,kBAAkB,GAAG;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,IAAI,EAAE,QAAQ,GAAG,SAAS,GAAG,QAAQ,CAAC;CACvC,CAAC;AAEF,MAAM,MAAM,WAAW,GAAG;IACxB,cAAc,EAAE,MAAM,EAAE,CAAC;IACzB,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,eAAe,EAAE,MAAM,EAAE,CAAC;IAC1B,eAAe,EAAE,MAAM,EAAE,CAAC;CAC3B,CAAC;AAEF,MAAM,MAAM,cAAc,GAAG;IAC3B,yBAAyB,CAAC,EAAE,MAAM,CAAC;IACnC,wBAAwB,CAAC,EAAE,MAAM,CAAC;CACnC,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=application-manifest.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"application-manifest.js","sourceRoot":"","sources":["../../src/types/application-manifest.ts"],"names":[],"mappings":"","sourcesContent":["export type ApplicationManifest = {\n format: \"apollo-ai-app-manifest\";\n version: \"1\";\n name: string;\n description: string;\n hash: string;\n resource: string;\n operations: ManifestOperation[];\n csp: ManifestCsp;\n widgetSettings?: ManifestWidgetSettings;\n labels?: ManifestLabels;\n};\n\nexport type ManifestOperation = {\n id: string;\n name: string;\n type: \"query\" | \"mutation\";\n body: string;\n variables?: Record<string, string | undefined>;\n prefetch: boolean;\n prefetchID?: string;\n tools: ManifestTool[];\n};\n\nexport type ManifestTool = {\n name: string;\n description: string;\n extraInputs?: ManifestExtraInput[];\n labels?: ManifestLabels;\n};\n\nexport type ManifestWidgetSettings = {\n description?: string;\n domain?: string;\n prefersBorder?: boolean;\n};\n\nexport type ManifestExtraInput = {\n name: string;\n description: string;\n type: \"string\" | \"boolean\" | \"number\";\n};\n\nexport type ManifestCsp = {\n connectDomains: string[];\n frameDomains: string[];\n redirectDomains: string[];\n resourceDomains: string[];\n};\n\nexport type ManifestLabels = {\n \"toolInvocation/invoking\"?: string;\n \"toolInvocation/invoked\"?: string;\n};\n"]}
@@ -70,3 +70,4 @@ export type UserAgent = {
70
70
  touch: boolean;
71
71
  };
72
72
  };
73
+ //# sourceMappingURL=openai.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"openai.d.ts","sourceRoot":"","sources":["../../src/types/openai.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ // Dispatched when any global changes in the host page
2
+ export const SET_GLOBALS_EVENT_TYPE = "openai:set_globals";
3
+ export class SetGlobalsEvent extends CustomEvent {
4
+ type = SET_GLOBALS_EVENT_TYPE;
5
+ }
6
+ //# sourceMappingURL=openai.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"openai.js","sourceRoot":"","sources":["../../src/types/openai.ts"],"names":[],"mappings":"AAwDA,sDAAsD;AACtD,MAAM,CAAC,MAAM,sBAAsB,GAAG,oBAAoB,CAAC;AAC3D,MAAM,OAAO,eAAgB,SAAQ,WAEnC;IACS,IAAI,GAAG,sBAAsB,CAAC;CACxC","sourcesContent":["export type UnknownObject = Record<string, unknown>;\n\ndeclare global {\n interface Window {\n openai: API<any> & OpenAiGlobals;\n }\n\n interface WindowEventMap {\n [SET_GLOBALS_EVENT_TYPE]: SetGlobalsEvent;\n }\n}\n\nexport type OpenAiGlobals<\n ToolInput extends UnknownObject = UnknownObject,\n ToolOutput extends UnknownObject = UnknownObject,\n ToolResponseMetadata extends UnknownObject = UnknownObject,\n WidgetState extends UnknownObject = UnknownObject,\n> = {\n theme: Theme;\n userAgent: UserAgent;\n locale: string;\n\n // layout\n maxHeight: number;\n displayMode: DisplayMode;\n safeArea: SafeArea;\n\n // state\n toolInput: ToolInput;\n toolOutput: ToolOutput | null;\n toolResponseMetadata: ToolResponseMetadata | null;\n widgetState: WidgetState | null;\n};\n\nexport type API<WidgetState extends UnknownObject> = {\n /** Calls a tool on your MCP. Returns the full response. */\n callTool: (name: string, args: Record<string, unknown>) => Promise<any>;\n\n /** Triggers a followup turn in the ChatGPT conversation */\n sendFollowUpMessage: (args: { prompt: string }) => Promise<void>;\n\n /** Opens an external link, redirects web page or mobile app */\n openExternal(payload: { href: string }): void;\n\n /** For transitioning an app from inline to fullscreen or pip */\n requestDisplayMode: (args: { mode: DisplayMode }) => Promise<{\n /**\n * The granted display mode. The host may reject the request.\n * For mobile, PiP is always coerced to fullscreen.\n */\n mode: DisplayMode;\n }>;\n\n setWidgetState: (state: WidgetState) => Promise<void>;\n};\n\n// Dispatched when any global changes in the host page\nexport const SET_GLOBALS_EVENT_TYPE = \"openai:set_globals\";\nexport class SetGlobalsEvent extends CustomEvent<{\n globals: Partial<OpenAiGlobals>;\n}> {\n readonly type = SET_GLOBALS_EVENT_TYPE;\n}\n\nexport type CallTool = (\n name: string,\n args: Record<string, unknown>\n) => Promise<any>;\n\nexport type DisplayMode = \"pip\" | \"inline\" | \"fullscreen\";\n\nexport type Theme = \"light\" | \"dark\";\n\nexport type SafeAreaInsets = {\n top: number;\n bottom: number;\n left: number;\n right: number;\n};\n\nexport type SafeArea = {\n insets: SafeAreaInsets;\n};\n\nexport type DeviceType = \"mobile\" | \"tablet\" | \"desktop\" | \"unknown\";\n\nexport type UserAgent = {\n device: { type: DeviceType };\n capabilities: {\n hover: boolean;\n touch: boolean;\n };\n};\n"]}
@@ -2,3 +2,4 @@ export declare const AbsoluteAssetImportsPlugin: () => {
2
2
  name: string;
3
3
  transformIndexHtml(html: string, ctx: any): string;
4
4
  };
5
+ //# sourceMappingURL=absolute_asset_imports_plugin.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"absolute_asset_imports_plugin.d.ts","sourceRoot":"","sources":["../../src/vite/absolute_asset_imports_plugin.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,0BAA0B;;6BAIV,MAAM,OAAO,GAAG;CAiB5C,CAAC"}
@@ -0,0 +1,17 @@
1
+ export const AbsoluteAssetImportsPlugin = () => {
2
+ return {
3
+ name: "absolute-asset-imports",
4
+ transformIndexHtml(html, ctx) {
5
+ if (!ctx.server)
6
+ return html;
7
+ let baseUrl = (ctx.server.config?.server?.origin ?? ctx.server.resolvedUrls?.local[0]).replace(/\/$/, "");
8
+ baseUrl = baseUrl.replace(/\/$/, "");
9
+ return (html
10
+ // import "/@vite/..." or "/@react-refresh"
11
+ .replace(/(from\s+["'])\/([^"']+)/g, `$1${baseUrl}/$2`)
12
+ // src="/src/..."
13
+ .replace(/(src=["'])\/([^"']+)/gi, `$1${baseUrl}/$2`));
14
+ },
15
+ };
16
+ };
17
+ //# sourceMappingURL=absolute_asset_imports_plugin.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"absolute_asset_imports_plugin.js","sourceRoot":"","sources":["../../src/vite/absolute_asset_imports_plugin.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,0BAA0B,GAAG,GAAG,EAAE;IAC7C,OAAO;QACL,IAAI,EAAE,wBAAwB;QAE9B,kBAAkB,CAAC,IAAY,EAAE,GAAQ;YACvC,IAAI,CAAC,GAAG,CAAC,MAAM;gBAAE,OAAO,IAAI,CAAC;YAE7B,IAAI,OAAO,GAAG,CACZ,GAAG,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,IAAI,GAAG,CAAC,MAAM,CAAC,YAAY,EAAE,KAAK,CAAC,CAAC,CAAC,CACvE,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;YACrB,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;YAErC,OAAO,CACL,IAAI;gBACF,2CAA2C;iBAC1C,OAAO,CAAC,0BAA0B,EAAE,KAAK,OAAO,KAAK,CAAC;gBACvD,iBAAiB;iBAChB,OAAO,CAAC,wBAAwB,EAAE,KAAK,OAAO,KAAK,CAAC,CACxD,CAAC;QACJ,CAAC;KACF,CAAC;AACJ,CAAC,CAAC","sourcesContent":["export const AbsoluteAssetImportsPlugin = () => {\n return {\n name: \"absolute-asset-imports\",\n\n transformIndexHtml(html: string, ctx: any) {\n if (!ctx.server) return html;\n\n let baseUrl = (\n ctx.server.config?.server?.origin ?? ctx.server.resolvedUrls?.local[0]\n ).replace(/\\/$/, \"\");\n baseUrl = baseUrl.replace(/\\/$/, \"\");\n\n return (\n html\n // import \"/@vite/...\" or \"/@react-refresh\"\n .replace(/(from\\s+[\"'])\\/([^\"']+)/g, `$1${baseUrl}/$2`)\n // src=\"/src/...\"\n .replace(/(src=[\"'])\\/([^\"']+)/gi, `$1${baseUrl}/$2`)\n );\n },\n };\n};\n"]}
@@ -1,4 +1,4 @@
1
- import { type DocumentNode } from "graphql";
1
+ import type { DocumentNode } from "graphql";
2
2
  export declare const ApplicationManifestPlugin: () => {
3
3
  name: string;
4
4
  configResolved(resolvedConfig: any): Promise<void>;
@@ -7,3 +7,4 @@ export declare const ApplicationManifestPlugin: () => {
7
7
  writeBundle(): Promise<void>;
8
8
  };
9
9
  export declare function sortTopLevelDefinitions(query: DocumentNode): DocumentNode;
10
+ //# sourceMappingURL=application_manifest_plugin.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"application_manifest_plugin.d.ts","sourceRoot":"","sources":["../../src/vite/application_manifest_plugin.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAOV,YAAY,EAGb,MAAM,SAAS,CAAC;AA2GjB,eAAO,MAAM,yBAAyB;;mCAqPG,GAAG;;4BAuBhB,GAAG;;CAgB9B,CAAC;AAIF,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,YAAY,GAAG,YAAY,CA2CzE"}
@@ -0,0 +1,317 @@
1
+ import { readFileSync, writeFileSync, mkdirSync } from "fs";
2
+ import { glob } from "glob";
3
+ import { gqlPluckFromCodeStringSync } from "@graphql-tools/graphql-tag-pluck";
4
+ import { createHash } from "crypto";
5
+ import { Kind, parse, print } from "graphql";
6
+ import { ApolloClient, ApolloLink, InMemoryCache } from "@apollo/client";
7
+ import { removeDirectivesFromDocument } from "@apollo/client/utilities/internal";
8
+ import { of } from "rxjs";
9
+ import path from "path";
10
+ const root = process.cwd();
11
+ function getRawValue(node) {
12
+ switch (node.kind) {
13
+ case Kind.STRING:
14
+ case Kind.BOOLEAN:
15
+ return node.value;
16
+ case Kind.LIST:
17
+ return node.values.map(getRawValue);
18
+ case Kind.OBJECT:
19
+ return node.fields.reduce((acc, field) => {
20
+ acc[field.name.value] = getRawValue(field.value);
21
+ return acc;
22
+ }, {});
23
+ default:
24
+ throw new Error(`Error when parsing directive values: unexpected type '${node.kind}'`);
25
+ }
26
+ }
27
+ function getArgumentValue(argument, expectedType) {
28
+ const argumentType = argument.value.kind;
29
+ invariant(argumentType === expectedType, `Expected argument '${argument.name.value}' to be of type '${expectedType}' but found '${argumentType}' instead.`);
30
+ return getRawValue(argument.value);
31
+ }
32
+ function getDirectiveArgument(argumentName, directive, { required = false } = {}) {
33
+ const argument = directive.arguments?.find((directiveArgument) => directiveArgument.name.value === argumentName);
34
+ invariant(argument || !required, `'${argumentName}' argument must be supplied for @tool`);
35
+ return argument;
36
+ }
37
+ function getTypeName(type) {
38
+ let t = type;
39
+ while (t.kind === "NonNullType" || t.kind === "ListType") {
40
+ t = t.type;
41
+ }
42
+ return t.name.value;
43
+ }
44
+ export const ApplicationManifestPlugin = () => {
45
+ const cache = new Map();
46
+ let packageJson = null;
47
+ let config = null;
48
+ const clientCache = new InMemoryCache();
49
+ const client = new ApolloClient({
50
+ cache: clientCache,
51
+ link: new ApolloLink((operation) => {
52
+ const body = print(removeClientDirective(sortTopLevelDefinitions(operation.query)));
53
+ const name = operation.operationName;
54
+ const definition = operation.query.definitions.find((d) => d.kind === "OperationDefinition");
55
+ // Use `operation.query` so that the error reflects the end-user defined
56
+ // document, not our sorted one
57
+ invariant(definition, `Document does not contain an operation:\n${print(operation.query)}`);
58
+ const { directives, operation: type } = definition;
59
+ const variables = definition.variableDefinitions?.reduce((obj, varDef) => ({
60
+ ...obj,
61
+ [varDef.variable.name.value]: getTypeName(varDef.type),
62
+ }), {});
63
+ const prefetch = directives?.some((d) => d.name.value === "prefetch");
64
+ const id = createHash("sha256").update(body).digest("hex");
65
+ // TODO: For now, you can only have 1 operation marked as prefetch. In the future, we'll likely support more than 1, and the "prefetchId" will be defined on the `@prefetch` itself as an argument
66
+ const prefetchID = prefetch ? "__anonymous" : undefined;
67
+ const tools = directives
68
+ ?.filter((d) => d.name.value === "tool")
69
+ .map((directive) => {
70
+ const name = getArgumentValue(getDirectiveArgument("name", directive, { required: true }), Kind.STRING);
71
+ invariant(name.indexOf(" ") === -1, `Tool with name "${name}" contains spaces which is not allowed.`);
72
+ const description = getArgumentValue(getDirectiveArgument("description", directive, { required: true }), Kind.STRING);
73
+ const extraInputsNode = getDirectiveArgument("extraInputs", directive);
74
+ const labelsNode = getDirectiveArgument("labels", directive);
75
+ const toolOptions = {
76
+ name,
77
+ description,
78
+ };
79
+ if (extraInputsNode) {
80
+ toolOptions.extraInputs = getArgumentValue(extraInputsNode, Kind.LIST);
81
+ }
82
+ if (labelsNode) {
83
+ const labels = getLabelsFromConfig(getArgumentValue(labelsNode, Kind.OBJECT));
84
+ if (labels) {
85
+ toolOptions.labels = labels;
86
+ }
87
+ }
88
+ return toolOptions;
89
+ });
90
+ // TODO: Make this object satisfy the `ManifestOperation` type. Currently
91
+ // it errors because we need more validation on a few of these fields
92
+ return of({
93
+ data: { id, name, type, body, variables, prefetch, prefetchID, tools },
94
+ });
95
+ }),
96
+ });
97
+ const processFile = async (file) => {
98
+ const code = readFileSync(file, "utf-8");
99
+ if (!code.includes("gql"))
100
+ return;
101
+ const fileHash = createHash("md5").update(code).digest("hex");
102
+ if (cache.get("file")?.hash === fileHash)
103
+ return;
104
+ const sources = gqlPluckFromCodeStringSync(file, code, {
105
+ modules: [
106
+ { name: "graphql-tag", identifier: "gql" },
107
+ { name: "@apollo/client", identifier: "gql" },
108
+ ],
109
+ }).map((source) => ({
110
+ node: parse(source.body),
111
+ file,
112
+ location: source.locationOffset,
113
+ }));
114
+ const operations = [];
115
+ for (const source of sources) {
116
+ const type = source.node.definitions.find((d) => d.kind === "OperationDefinition").operation;
117
+ let result;
118
+ if (type === "query") {
119
+ result = await client.query({
120
+ query: source.node,
121
+ fetchPolicy: "no-cache",
122
+ });
123
+ }
124
+ else if (type === "mutation") {
125
+ result = await client.mutate({
126
+ mutation: source.node,
127
+ fetchPolicy: "no-cache",
128
+ });
129
+ }
130
+ else {
131
+ throw new Error("Found an unsupported operation type. Only Query and Mutation are supported.");
132
+ }
133
+ operations.push(result.data);
134
+ }
135
+ cache.set(file, {
136
+ file: file,
137
+ hash: fileHash,
138
+ operations,
139
+ });
140
+ };
141
+ const generateManifest = async () => {
142
+ const operations = Array.from(cache.values()).flatMap((entry) => entry.operations);
143
+ invariant(operations.filter((o) => o.prefetch).length <= 1, "Found multiple operations marked as `@prefetch`. You can only mark 1 operation with `@prefetch`.");
144
+ let resource = "";
145
+ if (config.command === "serve") {
146
+ resource =
147
+ packageJson.entry?.[config.mode] ??
148
+ `http${config.server.https ? "s" : ""}://${config.server.host ?? "localhost"}:${config.server.port}`;
149
+ }
150
+ else {
151
+ let entryPoint = packageJson.entry?.[config.mode];
152
+ if (entryPoint) {
153
+ resource = entryPoint;
154
+ }
155
+ else if (config.mode === "production") {
156
+ resource = "index.html";
157
+ }
158
+ else {
159
+ throw new Error(`No entry point found for mode "${config.mode}". Entry points other than "development" and "production" must be defined in package.json file.`);
160
+ }
161
+ }
162
+ const manifest = {
163
+ format: "apollo-ai-app-manifest",
164
+ version: "1",
165
+ name: packageJson.name,
166
+ description: packageJson.description,
167
+ hash: createHash("sha256").update(Date.now().toString()).digest("hex"),
168
+ operations: Array.from(cache.values()).flatMap((entry) => entry.operations),
169
+ resource,
170
+ csp: {
171
+ connectDomains: packageJson.csp?.connectDomains ?? [],
172
+ frameDomains: packageJson.csp?.frameDomains ?? [],
173
+ redirectDomains: packageJson.csp?.redirectDomains ?? [],
174
+ resourceDomains: packageJson.csp?.resourceDomains ?? [],
175
+ },
176
+ };
177
+ if (packageJson.widgetSettings &&
178
+ isNonEmptyObject(packageJson.widgetSettings)) {
179
+ function validateWidgetSetting(key, type) {
180
+ if (key in widgetSettings) {
181
+ invariant(typeof widgetSettings[key] === type, `Expected 'widgetSettings.${key}' to be of type '${type}' but found '${typeof widgetSettings[key]}' instead.`);
182
+ }
183
+ }
184
+ const widgetSettings = packageJson.widgetSettings;
185
+ validateWidgetSetting("prefersBorder", "boolean");
186
+ validateWidgetSetting("description", "string");
187
+ validateWidgetSetting("domain", "string");
188
+ manifest.widgetSettings = packageJson.widgetSettings;
189
+ }
190
+ if (packageJson.labels) {
191
+ const labels = getLabelsFromConfig(packageJson.labels);
192
+ if (labels) {
193
+ manifest.labels = labels;
194
+ }
195
+ }
196
+ // Always write to build directory so the MCP server picks it up
197
+ const dest = path.resolve(root, config.build.outDir, ".application-manifest.json");
198
+ mkdirSync(path.dirname(dest), { recursive: true });
199
+ writeFileSync(dest, JSON.stringify(manifest));
200
+ // Always write to the dev location so that the app can bundle the manifest content
201
+ writeFileSync(".application-manifest.json", JSON.stringify(manifest));
202
+ };
203
+ return {
204
+ name: "OperationManifest",
205
+ async configResolved(resolvedConfig) {
206
+ config = resolvedConfig;
207
+ },
208
+ async buildStart() {
209
+ // Read package.json on start
210
+ packageJson = JSON.parse(readFileSync("package.json", "utf-8"));
211
+ // Scan all files on startup
212
+ const files = await glob("src/**/*.{ts,tsx,js,jsx}");
213
+ for (const file of files) {
214
+ const fullPath = path.resolve(root, file);
215
+ await processFile(fullPath);
216
+ }
217
+ // We don't want to do this here on builds cause it just gets overwritten anyways. We'll call it on writeBundle instead.
218
+ if (config.command === "serve") {
219
+ await generateManifest();
220
+ }
221
+ },
222
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
223
+ configureServer(server) {
224
+ server.watcher.on("change", async (file) => {
225
+ if (file.endsWith("package.json")) {
226
+ packageJson = JSON.parse(readFileSync("package.json", "utf-8"));
227
+ await generateManifest();
228
+ }
229
+ else if (file.match(/\.(jsx?|tsx?)$/)) {
230
+ await processFile(file);
231
+ await generateManifest();
232
+ }
233
+ });
234
+ },
235
+ async writeBundle() {
236
+ await generateManifest();
237
+ },
238
+ };
239
+ };
240
+ // Sort the definitions in this document so that operations come before fragments,
241
+ // and so that each kind of definition is sorted by name.
242
+ export function sortTopLevelDefinitions(query) {
243
+ const definitions = [...query.definitions];
244
+ // We want to avoid unnecessary dependencies, so write out a comparison
245
+ // function instead of using _.orderBy.
246
+ definitions.sort((a, b) => {
247
+ // This is a reverse sort by kind, so that OperationDefinition precedes FragmentDefinition.
248
+ if (a.kind > b.kind) {
249
+ return -1;
250
+ }
251
+ if (a.kind < b.kind) {
252
+ return 1;
253
+ }
254
+ // Extract the name from each definition. Jump through some hoops because
255
+ // non-executable definitions don't have to have names (even though any
256
+ // DocumentNode actually passed here should only have executable
257
+ // definitions).
258
+ const aName = a.kind === "OperationDefinition" || a.kind === "FragmentDefinition" ?
259
+ (a.name?.value ?? "")
260
+ : "";
261
+ const bName = b.kind === "OperationDefinition" || b.kind === "FragmentDefinition" ?
262
+ (b.name?.value ?? "")
263
+ : "";
264
+ // Sort by name ascending.
265
+ if (aName < bName) {
266
+ return -1;
267
+ }
268
+ if (aName > bName) {
269
+ return 1;
270
+ }
271
+ // Assuming that the document is "valid", no operation or fragment name can appear
272
+ // more than once, so we don't need to differentiate further to have a deterministic
273
+ // sort.
274
+ return 0;
275
+ });
276
+ return {
277
+ ...query,
278
+ definitions,
279
+ };
280
+ }
281
+ function getLabelsFromConfig(config) {
282
+ if (!("toolInvocation" in config)) {
283
+ return;
284
+ }
285
+ const { toolInvocation } = config;
286
+ const labels = {};
287
+ if (Object.hasOwn(toolInvocation, "invoking")) {
288
+ validateType(toolInvocation.invoking, "string", {
289
+ propertyName: "labels.toolInvocation.invoking",
290
+ });
291
+ labels["toolInvocation/invoking"] = toolInvocation.invoking;
292
+ }
293
+ if (Object.hasOwn(toolInvocation, "invoked")) {
294
+ validateType(toolInvocation.invoked, "string", {
295
+ propertyName: "labels.toolInvocation.invoked",
296
+ });
297
+ labels["toolInvocation/invoked"] = toolInvocation.invoked;
298
+ }
299
+ if (isNonEmptyObject(labels)) {
300
+ return labels;
301
+ }
302
+ }
303
+ function removeClientDirective(doc) {
304
+ return removeDirectivesFromDocument([{ name: "prefetch" }, { name: "tool" }], doc);
305
+ }
306
+ function invariant(condition, message) {
307
+ if (!condition) {
308
+ throw new Error(message);
309
+ }
310
+ }
311
+ function validateType(value, expectedType, options) {
312
+ invariant(typeof value === expectedType, `Expected '${options.propertyName}' to be of type '${expectedType}' but found '${typeof value}' instead.`);
313
+ }
314
+ function isNonEmptyObject(obj) {
315
+ return Object.keys(obj).length > 0;
316
+ }
317
+ //# sourceMappingURL=application_manifest_plugin.js.map