@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.
- package/.github/workflows/pr.yaml +52 -3
- package/.github/workflows/prep-release.yml +38 -0
- package/.github/workflows/release.yaml +8 -4
- package/.github/workflows/verify-changeset.yml +58 -0
- package/CHANGELOG.md +88 -0
- package/dist/core/ApolloClient.d.ts +3 -2
- package/dist/core/ApolloClient.d.ts.map +1 -0
- package/dist/core/ApolloClient.js +65 -0
- package/dist/core/ApolloClient.js.map +1 -0
- package/dist/index.d.ts +18 -18
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +16 -279
- package/dist/index.js.map +1 -0
- package/dist/link/ToolCallLink.d.ts +1 -0
- package/dist/link/ToolCallLink.d.ts.map +1 -0
- package/dist/link/ToolCallLink.js +39 -0
- package/dist/link/ToolCallLink.js.map +1 -0
- package/dist/react/ApolloProvider.d.ts +4 -3
- package/dist/react/ApolloProvider.d.ts.map +1 -0
- package/dist/react/ApolloProvider.js +30 -0
- package/dist/react/ApolloProvider.js.map +1 -0
- package/dist/react/context/ToolUseContext.d.ts +4 -3
- package/dist/react/context/ToolUseContext.d.ts.map +1 -0
- package/dist/react/context/ToolUseContext.js +11 -0
- package/dist/react/context/ToolUseContext.js.map +1 -0
- package/dist/react/hooks/useCallTool.d.ts +4 -0
- package/dist/react/hooks/useCallTool.d.ts.map +1 -0
- package/dist/react/hooks/useCallTool.js +5 -0
- package/dist/react/hooks/useCallTool.js.map +1 -0
- package/dist/react/hooks/useOpenAiGlobal.d.ts +2 -1
- package/dist/react/hooks/useOpenAiGlobal.d.ts.map +1 -0
- package/dist/react/hooks/useOpenAiGlobal.js +20 -0
- package/dist/react/hooks/useOpenAiGlobal.js.map +1 -0
- package/dist/react/hooks/useOpenExternal.d.ts +1 -0
- package/dist/react/hooks/useOpenExternal.d.ts.map +1 -0
- package/dist/react/hooks/useOpenExternal.js +5 -0
- package/dist/react/hooks/useOpenExternal.js.map +1 -0
- package/dist/react/hooks/useRequestDisplayMode.d.ts +2 -1
- package/dist/react/hooks/useRequestDisplayMode.d.ts.map +1 -0
- package/dist/react/hooks/useRequestDisplayMode.js +6 -0
- package/dist/react/hooks/useRequestDisplayMode.js.map +1 -0
- package/dist/react/hooks/useSendFollowUpMessage.d.ts +1 -0
- package/dist/react/hooks/useSendFollowUpMessage.d.ts.map +1 -0
- package/dist/react/hooks/useSendFollowUpMessage.js +8 -0
- package/dist/react/hooks/useSendFollowUpMessage.js.map +1 -0
- package/dist/react/hooks/useToolEffect.d.ts +1 -0
- package/dist/react/hooks/useToolEffect.d.ts.map +1 -0
- package/dist/react/hooks/useToolEffect.js +28 -0
- package/dist/react/hooks/useToolEffect.js.map +1 -0
- package/dist/react/hooks/useToolInput.d.ts +1 -0
- package/dist/react/hooks/useToolInput.d.ts.map +1 -0
- package/dist/react/hooks/useToolInput.js +6 -0
- package/dist/react/hooks/useToolInput.js.map +1 -0
- package/dist/react/hooks/useToolName.d.ts +1 -0
- package/dist/react/hooks/useToolName.d.ts.map +1 -0
- package/dist/react/hooks/useToolName.js +6 -0
- package/dist/react/hooks/useToolName.js.map +1 -0
- package/dist/react/hooks/useToolOutput.d.ts +2 -1
- package/dist/react/hooks/useToolOutput.d.ts.map +1 -0
- package/dist/react/hooks/useToolOutput.js +5 -0
- package/dist/react/hooks/useToolOutput.js.map +1 -0
- package/dist/react/hooks/useToolResponseMetadata.d.ts +2 -1
- package/dist/react/hooks/useToolResponseMetadata.d.ts.map +1 -0
- package/dist/react/hooks/useToolResponseMetadata.js +5 -0
- package/dist/react/hooks/useToolResponseMetadata.js.map +1 -0
- package/dist/react/hooks/useWidgetState.d.ts +3 -2
- package/dist/react/hooks/useWidgetState.d.ts.map +1 -0
- package/dist/react/hooks/useWidgetState.js +27 -0
- package/dist/react/hooks/useWidgetState.js.map +1 -0
- package/dist/types/application-manifest.d.ts +15 -0
- package/dist/types/application-manifest.d.ts.map +1 -0
- package/dist/types/application-manifest.js +2 -0
- package/dist/types/application-manifest.js.map +1 -0
- package/dist/types/openai.d.ts +1 -0
- package/dist/types/openai.d.ts.map +1 -0
- package/dist/types/openai.js +6 -0
- package/dist/types/openai.js.map +1 -0
- package/dist/vite/absolute_asset_imports_plugin.d.ts +1 -0
- package/dist/vite/absolute_asset_imports_plugin.d.ts.map +1 -0
- package/dist/vite/absolute_asset_imports_plugin.js +17 -0
- package/dist/vite/absolute_asset_imports_plugin.js.map +1 -0
- package/dist/vite/application_manifest_plugin.d.ts +2 -1
- package/dist/vite/application_manifest_plugin.d.ts.map +1 -0
- package/dist/vite/application_manifest_plugin.js +317 -0
- package/dist/vite/application_manifest_plugin.js.map +1 -0
- package/dist/vite/index.d.ts +3 -2
- package/dist/vite/index.d.ts.map +1 -0
- package/dist/vite/index.js +3 -307
- package/dist/vite/index.js.map +1 -0
- package/knope.toml +63 -0
- package/package.json +19 -11
- package/src/core/ApolloClient.ts +10 -5
- package/src/core/__tests__/ApolloClient.test.ts +33 -10
- package/src/index.ts +19 -18
- package/src/react/ApolloProvider.tsx +4 -3
- package/src/react/__tests__/ApolloProvider.test.tsx +3 -3
- package/src/react/context/ToolUseContext.tsx +2 -1
- package/src/react/hooks/__tests__/useCallTool.test.ts +1 -1
- package/src/react/hooks/__tests__/useOpenAiGlobal.test.ts +6 -6
- package/src/react/hooks/__tests__/useOpenExternal.test.tsx +2 -2
- package/src/react/hooks/__tests__/useRequestDisplayMode.test.ts +2 -2
- package/src/react/hooks/__tests__/useSendFollowUpMessage.test.ts +1 -1
- package/src/react/hooks/__tests__/useToolEffect.test.tsx +2 -2
- package/src/react/hooks/__tests__/useToolInput.test.ts +1 -1
- package/src/react/hooks/__tests__/useToolName.test.ts +1 -1
- package/src/react/hooks/__tests__/useToolOutput.test.tsx +2 -2
- package/src/react/hooks/__tests__/useToolResponseMetadata.test.tsx +2 -2
- package/src/react/hooks/__tests__/useWidgetState.test.tsx +2 -2
- package/src/react/hooks/useOpenAiGlobal.ts +2 -5
- package/src/react/hooks/useOpenExternal.ts +1 -1
- package/src/react/hooks/useRequestDisplayMode.ts +1 -1
- package/src/react/hooks/useToolEffect.tsx +3 -3
- package/src/react/hooks/useToolInput.ts +1 -1
- package/src/react/hooks/useToolName.ts +1 -1
- package/src/react/hooks/useToolOutput.ts +1 -1
- package/src/react/hooks/useToolResponseMetadata.ts +1 -1
- package/src/react/hooks/useWidgetState.ts +4 -3
- package/src/testing/internal/index.ts +2 -2
- package/src/testing/internal/matchers/index.ts +1 -1
- package/src/testing/internal/matchers/toRerender.ts +2 -2
- package/src/testing/internal/matchers/{index.d.ts → types.ts} +1 -1
- package/src/testing/internal/openai/dispatchStateChange.ts +1 -1
- package/src/testing/internal/openai/stubOpenAiGlobals.ts +6 -2
- package/src/types/application-manifest.ts +16 -0
- package/src/vite/__tests__/absolute_asset_imports_plugin.test.ts +2 -2
- package/src/vite/__tests__/application_manifest_plugin.test.ts +460 -240
- package/src/vite/application_manifest_plugin.ts +253 -93
- package/src/vite/index.ts +2 -2
- package/tsconfig.base.build.json +13 -0
- package/tsconfig.base.json +21 -0
- package/tsconfig.config.json +9 -0
- package/tsconfig.json +10 -0
- package/tsconfig.src.build.json +14 -0
- package/tsconfig.src.json +17 -0
- package/tsconfig.test.json +20 -0
- package/tsconfig.vite.build.json +6 -0
- package/tsconfig.vite.json +16 -0
- package/scripts/build-vite.mjs +0 -18
- package/scripts/build.mjs +0 -7
- 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 @@
|
|
|
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"]}
|
|
@@ -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 @@
|
|
|
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("
|
|
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 @@
|
|
|
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("
|
|
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 @@
|
|
|
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 @@
|
|
|
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"]}
|
package/dist/types/openai.d.ts
CHANGED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"openai.d.ts","sourceRoot":"","sources":["../../src/types/openai.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,aAAa,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;AAEpD,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,MAAM;QACd,MAAM,EAAE,GAAG,CAAC,GAAG,CAAC,GAAG,aAAa,CAAC;KAClC;IAED,UAAU,cAAc;QACtB,CAAC,sBAAsB,CAAC,EAAE,eAAe,CAAC;KAC3C;CACF;AAED,MAAM,MAAM,aAAa,CACvB,SAAS,SAAS,aAAa,GAAG,aAAa,EAC/C,UAAU,SAAS,aAAa,GAAG,aAAa,EAChD,oBAAoB,SAAS,aAAa,GAAG,aAAa,EAC1D,WAAW,SAAS,aAAa,GAAG,aAAa,IAC/C;IACF,KAAK,EAAE,KAAK,CAAC;IACb,SAAS,EAAE,SAAS,CAAC;IACrB,MAAM,EAAE,MAAM,CAAC;IAGf,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,WAAW,CAAC;IACzB,QAAQ,EAAE,QAAQ,CAAC;IAGnB,SAAS,EAAE,SAAS,CAAC;IACrB,UAAU,EAAE,UAAU,GAAG,IAAI,CAAC;IAC9B,oBAAoB,EAAE,oBAAoB,GAAG,IAAI,CAAC;IAClD,WAAW,EAAE,WAAW,GAAG,IAAI,CAAC;CACjC,CAAC;AAEF,MAAM,MAAM,GAAG,CAAC,WAAW,SAAS,aAAa,IAAI;IACnD,2DAA2D;IAC3D,QAAQ,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,OAAO,CAAC,GAAG,CAAC,CAAC;IAExE,2DAA2D;IAC3D,mBAAmB,EAAE,CAAC,IAAI,EAAE;QAAE,MAAM,EAAE,MAAM,CAAA;KAAE,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAEjE,+DAA+D;IAC/D,YAAY,CAAC,OAAO,EAAE;QAAE,IAAI,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC;IAE9C,gEAAgE;IAChE,kBAAkB,EAAE,CAAC,IAAI,EAAE;QAAE,IAAI,EAAE,WAAW,CAAA;KAAE,KAAK,OAAO,CAAC;QAC3D;;;WAGG;QACH,IAAI,EAAE,WAAW,CAAC;KACnB,CAAC,CAAC;IAEH,cAAc,EAAE,CAAC,KAAK,EAAE,WAAW,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CACvD,CAAC;AAGF,eAAO,MAAM,sBAAsB,uBAAuB,CAAC;AAC3D,qBAAa,eAAgB,SAAQ,WAAW,CAAC;IAC/C,OAAO,EAAE,OAAO,CAAC,aAAa,CAAC,CAAC;CACjC,CAAC;IACA,QAAQ,CAAC,IAAI,wBAA0B;CACxC;AAED,MAAM,MAAM,QAAQ,GAAG,CACrB,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAC1B,OAAO,CAAC,GAAG,CAAC,CAAC;AAElB,MAAM,MAAM,WAAW,GAAG,KAAK,GAAG,QAAQ,GAAG,YAAY,CAAC;AAE1D,MAAM,MAAM,KAAK,GAAG,OAAO,GAAG,MAAM,CAAC;AAErC,MAAM,MAAM,cAAc,GAAG;IAC3B,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;CACf,CAAC;AAEF,MAAM,MAAM,QAAQ,GAAG;IACrB,MAAM,EAAE,cAAc,CAAC;CACxB,CAAC;AAEF,MAAM,MAAM,UAAU,GAAG,QAAQ,GAAG,QAAQ,GAAG,SAAS,GAAG,SAAS,CAAC;AAErE,MAAM,MAAM,SAAS,GAAG;IACtB,MAAM,EAAE;QAAE,IAAI,EAAE,UAAU,CAAA;KAAE,CAAC;IAC7B,YAAY,EAAE;QACZ,KAAK,EAAE,OAAO,CAAC;QACf,KAAK,EAAE,OAAO,CAAC;KAChB,CAAC;CACH,CAAC"}
|
|
@@ -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"]}
|
|
@@ -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 {
|
|
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
|