@apollo/client-ai-apps 0.3.3 → 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/CHANGELOG.md +63 -0
- package/dist/index.d.ts +1 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +0 -1
- package/dist/index.js.map +1 -1
- package/dist/types/application-manifest.d.ts +8 -0
- package/dist/types/application-manifest.d.ts.map +1 -1
- package/dist/types/application-manifest.js.map +1 -1
- package/dist/vite/application_manifest_plugin.d.ts.map +1 -1
- package/dist/vite/application_manifest_plugin.js +44 -1
- package/dist/vite/application_manifest_plugin.js.map +1 -1
- package/package.json +5 -4
- package/src/core/__tests__/ApolloClient.test.ts +24 -4
- package/src/index.ts +2 -1
- package/src/types/application-manifest.ts +9 -0
- package/src/vite/__tests__/application_manifest_plugin.test.ts +166 -5
- package/src/vite/application_manifest_plugin.ts +97 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,66 @@
|
|
|
1
|
+
## 0.4.0 (2026-01-15)
|
|
2
|
+
|
|
3
|
+
### Breaking Changes
|
|
4
|
+
|
|
5
|
+
#### Make `@apollo/client` a peer dependency
|
|
6
|
+
|
|
7
|
+
`@apollo/client` is now a peer dependency and must be installed along with this package.
|
|
8
|
+
|
|
9
|
+
`@apollo/client` exports have also been removed from this package and should be imported from `@apollo/client` instead.
|
|
10
|
+
|
|
11
|
+
```diff
|
|
12
|
+
- import { useQuery } from "@apollo/client-ai-apps";
|
|
13
|
+
+ import { useQuery } from "@apollo/client";
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
### Features
|
|
17
|
+
|
|
18
|
+
#### Support additional CSP settings
|
|
19
|
+
|
|
20
|
+
Add support for `frameDomains` and `redirectDomains` in CSP settings.
|
|
21
|
+
|
|
22
|
+
#### Support `toolInvocation` labels
|
|
23
|
+
|
|
24
|
+
Add support for `labels` config for both `package.json` and `@tool` directives.
|
|
25
|
+
|
|
26
|
+
```ts
|
|
27
|
+
// package.json
|
|
28
|
+
{
|
|
29
|
+
"labels": {
|
|
30
|
+
"toolInvocation": {
|
|
31
|
+
"invoking": "Invoking...",
|
|
32
|
+
"invoked": "Invoked!"
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
```gql
|
|
39
|
+
query {
|
|
40
|
+
MyQuery
|
|
41
|
+
@tool(
|
|
42
|
+
name: "MyQuery"
|
|
43
|
+
description: "..."
|
|
44
|
+
labels: {
|
|
45
|
+
toolInvocation: { invoking: "Invoking...", invoked: "Invoked!" }
|
|
46
|
+
}
|
|
47
|
+
) {
|
|
48
|
+
myField
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
These labels map to the following MCP server config:
|
|
54
|
+
|
|
55
|
+
- `toolInvocation.invoking` -> `toolInvocation/invoking`
|
|
56
|
+
- `toolInvocation.invoked` -> `toolInvocation/invoked`
|
|
57
|
+
|
|
58
|
+
### Fixes
|
|
59
|
+
|
|
60
|
+
#### Updated `react` and `react-dom` peer dependency versions
|
|
61
|
+
|
|
62
|
+
The `react` and `react-dom` peer dependency versions have been loosened to `^19.0.0`.
|
|
63
|
+
|
|
1
64
|
## 0.3.3 (2026-01-13)
|
|
2
65
|
|
|
3
66
|
### Features
|
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
export type { API, CallTool, DeviceType, DisplayMode, OpenAiGlobals, SafeArea, SafeAreaInsets, Theme, UserAgent, UnknownObject, } from "./types/openai.js";
|
|
2
2
|
export { SET_GLOBALS_EVENT_TYPE, SetGlobalsEvent } from "./types/openai.js";
|
|
3
|
-
export type { ApplicationManifest, ManifestOperation, ManifestTool, ManifestExtraInput, ManifestCsp, } from "./types/application-manifest.js";
|
|
3
|
+
export type { ApplicationManifest, ManifestOperation, ManifestTool, ManifestExtraInput, ManifestCsp, ManifestLabels, ManifestWidgetSettings, } from "./types/application-manifest.js";
|
|
4
4
|
export { ToolUseProvider } from "./react/context/ToolUseContext.js";
|
|
5
5
|
export { useOpenAiGlobal } from "./react/hooks/useOpenAiGlobal.js";
|
|
6
6
|
export { useToolName } from "./react/hooks/useToolName.js";
|
|
@@ -12,7 +12,6 @@ export { useOpenExternal } from "./react/hooks/useOpenExternal.js";
|
|
|
12
12
|
export { useToolOutput } from "./react/hooks/useToolOutput.js";
|
|
13
13
|
export { useToolResponseMetadata } from "./react/hooks/useToolResponseMetadata.js";
|
|
14
14
|
export { useWidgetState } from "./react/hooks/useWidgetState.js";
|
|
15
|
-
export * from "@apollo/client";
|
|
16
15
|
export { ApolloClient } from "./core/ApolloClient.js";
|
|
17
16
|
export { ApolloProvider } from "./react/ApolloProvider.js";
|
|
18
17
|
export { ToolCallLink } from "./link/ToolCallLink.js";
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,YAAY,EACV,GAAG,EACH,QAAQ,EACR,UAAU,EACV,WAAW,EACX,aAAa,EACb,QAAQ,EACR,cAAc,EACd,KAAK,EACL,SAAS,EACT,aAAa,GACd,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAE,sBAAsB,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAE5E,YAAY,EACV,mBAAmB,EACnB,iBAAiB,EACjB,YAAY,EACZ,kBAAkB,EAClB,WAAW,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,YAAY,EACV,GAAG,EACH,QAAQ,EACR,UAAU,EACV,WAAW,EACX,aAAa,EACb,QAAQ,EACR,cAAc,EACd,KAAK,EACL,SAAS,EACT,aAAa,GACd,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAE,sBAAsB,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAE5E,YAAY,EACV,mBAAmB,EACnB,iBAAiB,EACjB,YAAY,EACZ,kBAAkB,EAClB,WAAW,EACX,cAAc,EACd,sBAAsB,GACvB,MAAM,iCAAiC,CAAC;AAEzC,OAAO,EAAE,eAAe,EAAE,MAAM,mCAAmC,CAAC;AACpE,OAAO,EAAE,eAAe,EAAE,MAAM,kCAAkC,CAAC;AACnE,OAAO,EAAE,WAAW,EAAE,MAAM,8BAA8B,CAAC;AAC3D,OAAO,EAAE,YAAY,EAAE,MAAM,+BAA+B,CAAC;AAC7D,OAAO,EAAE,sBAAsB,EAAE,MAAM,yCAAyC,CAAC;AACjF,OAAO,EAAE,qBAAqB,EAAE,MAAM,wCAAwC,CAAC;AAC/E,OAAO,EAAE,aAAa,EAAE,MAAM,gCAAgC,CAAC;AAC/D,OAAO,EAAE,eAAe,EAAE,MAAM,kCAAkC,CAAC;AACnE,OAAO,EAAE,aAAa,EAAE,MAAM,gCAAgC,CAAC;AAC/D,OAAO,EAAE,uBAAuB,EAAE,MAAM,0CAA0C,CAAC;AACnF,OAAO,EAAE,cAAc,EAAE,MAAM,iCAAiC,CAAC;AAEjE,OAAO,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AACtD,OAAO,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAC3D,OAAO,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -10,7 +10,6 @@ export { useOpenExternal } from "./react/hooks/useOpenExternal.js";
|
|
|
10
10
|
export { useToolOutput } from "./react/hooks/useToolOutput.js";
|
|
11
11
|
export { useToolResponseMetadata } from "./react/hooks/useToolResponseMetadata.js";
|
|
12
12
|
export { useWidgetState } from "./react/hooks/useWidgetState.js";
|
|
13
|
-
export * from "@apollo/client";
|
|
14
13
|
export { ApolloClient } from "./core/ApolloClient.js";
|
|
15
14
|
export { ApolloProvider } from "./react/ApolloProvider.js";
|
|
16
15
|
export { ToolCallLink } from "./link/ToolCallLink.js";
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAYA,OAAO,EAAE,sBAAsB,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAYA,OAAO,EAAE,sBAAsB,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAY5E,OAAO,EAAE,eAAe,EAAE,MAAM,mCAAmC,CAAC;AACpE,OAAO,EAAE,eAAe,EAAE,MAAM,kCAAkC,CAAC;AACnE,OAAO,EAAE,WAAW,EAAE,MAAM,8BAA8B,CAAC;AAC3D,OAAO,EAAE,YAAY,EAAE,MAAM,+BAA+B,CAAC;AAC7D,OAAO,EAAE,sBAAsB,EAAE,MAAM,yCAAyC,CAAC;AACjF,OAAO,EAAE,qBAAqB,EAAE,MAAM,wCAAwC,CAAC;AAC/E,OAAO,EAAE,aAAa,EAAE,MAAM,gCAAgC,CAAC;AAC/D,OAAO,EAAE,eAAe,EAAE,MAAM,kCAAkC,CAAC;AACnE,OAAO,EAAE,aAAa,EAAE,MAAM,gCAAgC,CAAC;AAC/D,OAAO,EAAE,uBAAuB,EAAE,MAAM,0CAA0C,CAAC;AACnF,OAAO,EAAE,cAAc,EAAE,MAAM,iCAAiC,CAAC;AAEjE,OAAO,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AACtD,OAAO,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAC3D,OAAO,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC","sourcesContent":["export type {\n API,\n CallTool,\n DeviceType,\n DisplayMode,\n OpenAiGlobals,\n SafeArea,\n SafeAreaInsets,\n Theme,\n UserAgent,\n UnknownObject,\n} from \"./types/openai.js\";\nexport { SET_GLOBALS_EVENT_TYPE, SetGlobalsEvent } from \"./types/openai.js\";\n\nexport type {\n ApplicationManifest,\n ManifestOperation,\n ManifestTool,\n ManifestExtraInput,\n ManifestCsp,\n ManifestLabels,\n ManifestWidgetSettings,\n} from \"./types/application-manifest.js\";\n\nexport { ToolUseProvider } from \"./react/context/ToolUseContext.js\";\nexport { useOpenAiGlobal } from \"./react/hooks/useOpenAiGlobal.js\";\nexport { useToolName } from \"./react/hooks/useToolName.js\";\nexport { useToolInput } from \"./react/hooks/useToolInput.js\";\nexport { useSendFollowUpMessage } from \"./react/hooks/useSendFollowUpMessage.js\";\nexport { useRequestDisplayMode } from \"./react/hooks/useRequestDisplayMode.js\";\nexport { useToolEffect } from \"./react/hooks/useToolEffect.js\";\nexport { useOpenExternal } from \"./react/hooks/useOpenExternal.js\";\nexport { useToolOutput } from \"./react/hooks/useToolOutput.js\";\nexport { useToolResponseMetadata } from \"./react/hooks/useToolResponseMetadata.js\";\nexport { useWidgetState } from \"./react/hooks/useWidgetState.js\";\n\nexport { ApolloClient } from \"./core/ApolloClient.js\";\nexport { ApolloProvider } from \"./react/ApolloProvider.js\";\nexport { ToolCallLink } from \"./link/ToolCallLink.js\";\n"]}
|
|
@@ -8,6 +8,7 @@ export type ApplicationManifest = {
|
|
|
8
8
|
operations: ManifestOperation[];
|
|
9
9
|
csp: ManifestCsp;
|
|
10
10
|
widgetSettings?: ManifestWidgetSettings;
|
|
11
|
+
labels?: ManifestLabels;
|
|
11
12
|
};
|
|
12
13
|
export type ManifestOperation = {
|
|
13
14
|
id: string;
|
|
@@ -23,6 +24,7 @@ export type ManifestTool = {
|
|
|
23
24
|
name: string;
|
|
24
25
|
description: string;
|
|
25
26
|
extraInputs?: ManifestExtraInput[];
|
|
27
|
+
labels?: ManifestLabels;
|
|
26
28
|
};
|
|
27
29
|
export type ManifestWidgetSettings = {
|
|
28
30
|
description?: string;
|
|
@@ -36,6 +38,12 @@ export type ManifestExtraInput = {
|
|
|
36
38
|
};
|
|
37
39
|
export type ManifestCsp = {
|
|
38
40
|
connectDomains: string[];
|
|
41
|
+
frameDomains: string[];
|
|
42
|
+
redirectDomains: string[];
|
|
39
43
|
resourceDomains: string[];
|
|
40
44
|
};
|
|
45
|
+
export type ManifestLabels = {
|
|
46
|
+
"toolInvocation/invoking"?: string;
|
|
47
|
+
"toolInvocation/invoked"?: string;
|
|
48
|
+
};
|
|
41
49
|
//# sourceMappingURL=application-manifest.d.ts.map
|
|
@@ -1 +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;
|
|
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"}
|
|
@@ -1 +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};\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};\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 resourceDomains: string[];\n};\n"]}
|
|
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"]}
|
|
@@ -1 +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;
|
|
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"}
|
|
@@ -71,6 +71,7 @@ export const ApplicationManifestPlugin = () => {
|
|
|
71
71
|
invariant(name.indexOf(" ") === -1, `Tool with name "${name}" contains spaces which is not allowed.`);
|
|
72
72
|
const description = getArgumentValue(getDirectiveArgument("description", directive, { required: true }), Kind.STRING);
|
|
73
73
|
const extraInputsNode = getDirectiveArgument("extraInputs", directive);
|
|
74
|
+
const labelsNode = getDirectiveArgument("labels", directive);
|
|
74
75
|
const toolOptions = {
|
|
75
76
|
name,
|
|
76
77
|
description,
|
|
@@ -78,6 +79,12 @@ export const ApplicationManifestPlugin = () => {
|
|
|
78
79
|
if (extraInputsNode) {
|
|
79
80
|
toolOptions.extraInputs = getArgumentValue(extraInputsNode, Kind.LIST);
|
|
80
81
|
}
|
|
82
|
+
if (labelsNode) {
|
|
83
|
+
const labels = getLabelsFromConfig(getArgumentValue(labelsNode, Kind.OBJECT));
|
|
84
|
+
if (labels) {
|
|
85
|
+
toolOptions.labels = labels;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
81
88
|
return toolOptions;
|
|
82
89
|
});
|
|
83
90
|
// TODO: Make this object satisfy the `ManifestOperation` type. Currently
|
|
@@ -162,11 +169,13 @@ export const ApplicationManifestPlugin = () => {
|
|
|
162
169
|
resource,
|
|
163
170
|
csp: {
|
|
164
171
|
connectDomains: packageJson.csp?.connectDomains ?? [],
|
|
172
|
+
frameDomains: packageJson.csp?.frameDomains ?? [],
|
|
173
|
+
redirectDomains: packageJson.csp?.redirectDomains ?? [],
|
|
165
174
|
resourceDomains: packageJson.csp?.resourceDomains ?? [],
|
|
166
175
|
},
|
|
167
176
|
};
|
|
168
177
|
if (packageJson.widgetSettings &&
|
|
169
|
-
|
|
178
|
+
isNonEmptyObject(packageJson.widgetSettings)) {
|
|
170
179
|
function validateWidgetSetting(key, type) {
|
|
171
180
|
if (key in widgetSettings) {
|
|
172
181
|
invariant(typeof widgetSettings[key] === type, `Expected 'widgetSettings.${key}' to be of type '${type}' but found '${typeof widgetSettings[key]}' instead.`);
|
|
@@ -178,6 +187,12 @@ export const ApplicationManifestPlugin = () => {
|
|
|
178
187
|
validateWidgetSetting("domain", "string");
|
|
179
188
|
manifest.widgetSettings = packageJson.widgetSettings;
|
|
180
189
|
}
|
|
190
|
+
if (packageJson.labels) {
|
|
191
|
+
const labels = getLabelsFromConfig(packageJson.labels);
|
|
192
|
+
if (labels) {
|
|
193
|
+
manifest.labels = labels;
|
|
194
|
+
}
|
|
195
|
+
}
|
|
181
196
|
// Always write to build directory so the MCP server picks it up
|
|
182
197
|
const dest = path.resolve(root, config.build.outDir, ".application-manifest.json");
|
|
183
198
|
mkdirSync(path.dirname(dest), { recursive: true });
|
|
@@ -263,6 +278,28 @@ export function sortTopLevelDefinitions(query) {
|
|
|
263
278
|
definitions,
|
|
264
279
|
};
|
|
265
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
|
+
}
|
|
266
303
|
function removeClientDirective(doc) {
|
|
267
304
|
return removeDirectivesFromDocument([{ name: "prefetch" }, { name: "tool" }], doc);
|
|
268
305
|
}
|
|
@@ -271,4 +308,10 @@ function invariant(condition, message) {
|
|
|
271
308
|
throw new Error(message);
|
|
272
309
|
}
|
|
273
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
|
+
}
|
|
274
317
|
//# sourceMappingURL=application_manifest_plugin.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"application_manifest_plugin.js","sourceRoot":"","sources":["../../src/vite/application_manifest_plugin.ts"],"names":[],"mappings":"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","sourcesContent":["import { readFileSync, writeFileSync, mkdirSync } from \"fs\";\nimport { glob } from \"glob\";\nimport { gqlPluckFromCodeStringSync } from \"@graphql-tools/graphql-tag-pluck\";\nimport { createHash } from \"crypto\";\nimport type {\n ArgumentNode,\n ListTypeNode,\n NamedTypeNode,\n NonNullTypeNode,\n TypeNode,\n ValueNode,\n DocumentNode,\n OperationDefinitionNode,\n DirectiveNode,\n} from \"graphql\";\nimport { Kind, parse, print } from \"graphql\";\nimport { ApolloClient, ApolloLink, InMemoryCache } from \"@apollo/client\";\nimport { removeDirectivesFromDocument } from \"@apollo/client/utilities/internal\";\nimport { of } from \"rxjs\";\nimport path from \"path\";\nimport type {\n ApplicationManifest,\n ManifestExtraInput,\n ManifestTool,\n ManifestWidgetSettings,\n} from \"../types/application-manifest.js\";\n\nconst root = process.cwd();\n\nfunction getRawValue(node: ValueNode): unknown {\n switch (node.kind) {\n case Kind.STRING:\n case Kind.BOOLEAN:\n return node.value;\n case Kind.LIST:\n return node.values.map(getRawValue);\n case Kind.OBJECT:\n return node.fields.reduce<Record<string, any>>((acc, field) => {\n acc[field.name.value] = getRawValue(field.value);\n return acc;\n }, {});\n default:\n throw new Error(\n `Error when parsing directive values: unexpected type '${node.kind}'`\n );\n }\n}\n\nfunction getArgumentValue(\n argument: ArgumentNode,\n expectedType: Kind.STRING\n): string;\n\nfunction getArgumentValue(\n argument: ArgumentNode,\n expectedType: Kind.BOOLEAN\n): boolean;\n\nfunction getArgumentValue(\n argument: ArgumentNode,\n expectedType: Kind.LIST\n): unknown[];\n\nfunction getArgumentValue(\n argument: ArgumentNode,\n expectedType: Kind.OBJECT\n): Record<string, unknown>;\n\nfunction getArgumentValue(argument: ArgumentNode, expectedType: Kind) {\n const argumentType = argument.value.kind;\n\n invariant(\n argumentType === expectedType,\n `Expected argument '${argument.name.value}' to be of type '${expectedType}' but found '${argumentType}' instead.`\n );\n\n return getRawValue(argument.value);\n}\n\ninterface GetArgumentNodeOptions {\n required?: boolean;\n}\n\nfunction getDirectiveArgument(\n argumentName: string,\n directive: DirectiveNode,\n opts: GetArgumentNodeOptions & { required: true }\n): ArgumentNode;\n\nfunction getDirectiveArgument(\n argumentName: string,\n directive: DirectiveNode,\n opts?: GetArgumentNodeOptions\n): ArgumentNode | undefined;\n\nfunction getDirectiveArgument(\n argumentName: string,\n directive: DirectiveNode,\n { required = false }: { required?: boolean } = {}\n) {\n const argument = directive.arguments?.find(\n (directiveArgument) => directiveArgument.name.value === argumentName\n );\n\n invariant(\n argument || !required,\n `'${argumentName}' argument must be supplied for @tool`\n );\n\n return argument;\n}\n\nfunction getTypeName(type: TypeNode): string {\n let t = type;\n while (t.kind === \"NonNullType\" || t.kind === \"ListType\") {\n t = (t as NonNullTypeNode | ListTypeNode).type;\n }\n return (t as NamedTypeNode).name.value;\n}\n\nexport const ApplicationManifestPlugin = () => {\n const cache = new Map();\n let packageJson: any = null;\n let config: any = null;\n\n const clientCache = new InMemoryCache();\n const client = new ApolloClient({\n cache: clientCache,\n link: new ApolloLink((operation) => {\n const body = print(\n removeClientDirective(sortTopLevelDefinitions(operation.query))\n );\n const name = operation.operationName;\n const definition = operation.query.definitions.find(\n (d) => d.kind === \"OperationDefinition\"\n );\n\n // Use `operation.query` so that the error reflects the end-user defined\n // document, not our sorted one\n invariant(\n definition,\n `Document does not contain an operation:\\n${print(operation.query)}`\n );\n\n const { directives, operation: type } = definition;\n\n const variables = definition.variableDefinitions?.reduce(\n (obj, varDef) => ({\n ...obj,\n [varDef.variable.name.value]: getTypeName(varDef.type),\n }),\n {}\n );\n\n const prefetch = directives?.some((d) => d.name.value === \"prefetch\");\n const id = createHash(\"sha256\").update(body).digest(\"hex\");\n // 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\n const prefetchID = prefetch ? \"__anonymous\" : undefined;\n\n const tools = directives\n ?.filter((d) => d.name.value === \"tool\")\n .map((directive) => {\n const name = getArgumentValue(\n getDirectiveArgument(\"name\", directive, { required: true }),\n Kind.STRING\n );\n\n invariant(\n name.indexOf(\" \") === -1,\n `Tool with name \"${name}\" contains spaces which is not allowed.`\n );\n\n const description = getArgumentValue(\n getDirectiveArgument(\"description\", directive, { required: true }),\n Kind.STRING\n );\n\n const extraInputsNode = getDirectiveArgument(\n \"extraInputs\",\n directive\n );\n\n const toolOptions: ManifestTool = {\n name,\n description,\n };\n\n if (extraInputsNode) {\n toolOptions.extraInputs = getArgumentValue(\n extraInputsNode,\n Kind.LIST\n ) as ManifestExtraInput[];\n }\n\n return toolOptions;\n });\n\n // TODO: Make this object satisfy the `ManifestOperation` type. Currently\n // it errors because we need more validation on a few of these fields\n return of({\n data: { id, name, type, body, variables, prefetch, prefetchID, tools },\n });\n }),\n });\n\n const processFile = async (file: string) => {\n const code = readFileSync(file, \"utf-8\");\n\n if (!code.includes(\"gql\")) return;\n\n const fileHash = createHash(\"md5\").update(code).digest(\"hex\");\n if (cache.get(\"file\")?.hash === fileHash) return;\n const sources = gqlPluckFromCodeStringSync(file, code, {\n modules: [\n { name: \"graphql-tag\", identifier: \"gql\" },\n { name: \"@apollo/client\", identifier: \"gql\" },\n ],\n }).map((source) => ({\n node: parse(source.body),\n file,\n location: source.locationOffset,\n }));\n\n const operations = [];\n for (const source of sources) {\n const type = (\n source.node.definitions.find(\n (d) => d.kind === \"OperationDefinition\"\n ) as OperationDefinitionNode\n ).operation;\n\n let result;\n if (type === \"query\") {\n result = await client.query({\n query: source.node,\n fetchPolicy: \"no-cache\",\n });\n } else if (type === \"mutation\") {\n result = await client.mutate({\n mutation: source.node,\n fetchPolicy: \"no-cache\",\n });\n } else {\n throw new Error(\n \"Found an unsupported operation type. Only Query and Mutation are supported.\"\n );\n }\n operations.push(result.data);\n }\n\n cache.set(file, {\n file: file,\n hash: fileHash,\n operations,\n });\n };\n\n const generateManifest = async () => {\n const operations = Array.from(cache.values()).flatMap(\n (entry) => entry.operations\n );\n\n invariant(\n operations.filter((o) => o.prefetch).length <= 1,\n \"Found multiple operations marked as `@prefetch`. You can only mark 1 operation with `@prefetch`.\"\n );\n\n let resource = \"\";\n if (config.command === \"serve\") {\n resource =\n packageJson.entry?.[config.mode] ??\n `http${config.server.https ? \"s\" : \"\"}://${config.server.host ?? \"localhost\"}:${config.server.port}`;\n } else {\n let entryPoint = packageJson.entry?.[config.mode];\n if (entryPoint) {\n resource = entryPoint;\n } else if (config.mode === \"production\") {\n resource = \"index.html\";\n } else {\n throw new Error(\n `No entry point found for mode \"${config.mode}\". Entry points other than \"development\" and \"production\" must be defined in package.json file.`\n );\n }\n }\n\n const manifest: ApplicationManifest = {\n format: \"apollo-ai-app-manifest\",\n version: \"1\",\n name: packageJson.name,\n description: packageJson.description,\n hash: createHash(\"sha256\").update(Date.now().toString()).digest(\"hex\"),\n operations: Array.from(cache.values()).flatMap(\n (entry) => entry.operations\n ),\n resource,\n csp: {\n connectDomains: packageJson.csp?.connectDomains ?? [],\n resourceDomains: packageJson.csp?.resourceDomains ?? [],\n },\n };\n\n if (\n packageJson.widgetSettings &&\n Object.keys(packageJson.widgetSettings).length > 0\n ) {\n function validateWidgetSetting(\n key: keyof ManifestWidgetSettings,\n type: \"string\" | \"boolean\"\n ) {\n if (key in widgetSettings) {\n invariant(\n typeof widgetSettings[key] === type,\n `Expected 'widgetSettings.${key}' to be of type '${type}' but found '${typeof widgetSettings[key]}' instead.`\n );\n }\n }\n\n const widgetSettings =\n packageJson.widgetSettings as ManifestWidgetSettings;\n\n validateWidgetSetting(\"prefersBorder\", \"boolean\");\n validateWidgetSetting(\"description\", \"string\");\n validateWidgetSetting(\"domain\", \"string\");\n\n manifest.widgetSettings = packageJson.widgetSettings;\n }\n\n // Always write to build directory so the MCP server picks it up\n const dest = path.resolve(\n root,\n config.build.outDir,\n \".application-manifest.json\"\n );\n mkdirSync(path.dirname(dest), { recursive: true });\n writeFileSync(dest, JSON.stringify(manifest));\n\n // Always write to the dev location so that the app can bundle the manifest content\n writeFileSync(\".application-manifest.json\", JSON.stringify(manifest));\n };\n\n return {\n name: \"OperationManifest\",\n\n async configResolved(resolvedConfig: any) {\n config = resolvedConfig;\n },\n\n async buildStart() {\n // Read package.json on start\n packageJson = JSON.parse(readFileSync(\"package.json\", \"utf-8\"));\n\n // Scan all files on startup\n const files = await glob(\"src/**/*.{ts,tsx,js,jsx}\");\n\n for (const file of files) {\n const fullPath = path.resolve(root, file);\n await processFile(fullPath);\n }\n\n // We don't want to do this here on builds cause it just gets overwritten anyways. We'll call it on writeBundle instead.\n if (config.command === \"serve\") {\n await generateManifest();\n }\n },\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n configureServer(server: any) {\n server.watcher.on(\"change\", async (file: string) => {\n if (file.endsWith(\"package.json\")) {\n packageJson = JSON.parse(readFileSync(\"package.json\", \"utf-8\"));\n await generateManifest();\n } else if (file.match(/\\.(jsx?|tsx?)$/)) {\n await processFile(file);\n await generateManifest();\n }\n });\n },\n\n async writeBundle() {\n await generateManifest();\n },\n };\n};\n\n// Sort the definitions in this document so that operations come before fragments,\n// and so that each kind of definition is sorted by name.\nexport function sortTopLevelDefinitions(query: DocumentNode): DocumentNode {\n const definitions = [...query.definitions];\n // We want to avoid unnecessary dependencies, so write out a comparison\n // function instead of using _.orderBy.\n definitions.sort((a, b) => {\n // This is a reverse sort by kind, so that OperationDefinition precedes FragmentDefinition.\n if (a.kind > b.kind) {\n return -1;\n }\n if (a.kind < b.kind) {\n return 1;\n }\n\n // Extract the name from each definition. Jump through some hoops because\n // non-executable definitions don't have to have names (even though any\n // DocumentNode actually passed here should only have executable\n // definitions).\n const aName =\n a.kind === \"OperationDefinition\" || a.kind === \"FragmentDefinition\" ?\n (a.name?.value ?? \"\")\n : \"\";\n const bName =\n b.kind === \"OperationDefinition\" || b.kind === \"FragmentDefinition\" ?\n (b.name?.value ?? \"\")\n : \"\";\n\n // Sort by name ascending.\n if (aName < bName) {\n return -1;\n }\n if (aName > bName) {\n return 1;\n }\n\n // Assuming that the document is \"valid\", no operation or fragment name can appear\n // more than once, so we don't need to differentiate further to have a deterministic\n // sort.\n return 0;\n });\n return {\n ...query,\n definitions,\n };\n}\n\nfunction removeClientDirective(doc: DocumentNode) {\n return removeDirectivesFromDocument(\n [{ name: \"prefetch\" }, { name: \"tool\" }],\n doc\n )!;\n}\n\nfunction invariant(condition: any, message: string): asserts condition {\n if (!condition) {\n throw new Error(message);\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"application_manifest_plugin.js","sourceRoot":"","sources":["../../src/vite/application_manifest_plugin.ts"],"names":[],"mappings":"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","sourcesContent":["import { readFileSync, writeFileSync, mkdirSync } from \"fs\";\nimport { glob } from \"glob\";\nimport { gqlPluckFromCodeStringSync } from \"@graphql-tools/graphql-tag-pluck\";\nimport { createHash } from \"crypto\";\nimport type {\n ArgumentNode,\n ListTypeNode,\n NamedTypeNode,\n NonNullTypeNode,\n TypeNode,\n ValueNode,\n DocumentNode,\n OperationDefinitionNode,\n DirectiveNode,\n} from \"graphql\";\nimport { Kind, parse, print } from \"graphql\";\nimport { ApolloClient, ApolloLink, InMemoryCache } from \"@apollo/client\";\nimport { removeDirectivesFromDocument } from \"@apollo/client/utilities/internal\";\nimport { of } from \"rxjs\";\nimport path from \"path\";\nimport type {\n ApplicationManifest,\n ManifestExtraInput,\n ManifestLabels,\n ManifestTool,\n ManifestWidgetSettings,\n} from \"../types/application-manifest.js\";\n\nconst root = process.cwd();\n\nfunction getRawValue(node: ValueNode): unknown {\n switch (node.kind) {\n case Kind.STRING:\n case Kind.BOOLEAN:\n return node.value;\n case Kind.LIST:\n return node.values.map(getRawValue);\n case Kind.OBJECT:\n return node.fields.reduce<Record<string, any>>((acc, field) => {\n acc[field.name.value] = getRawValue(field.value);\n return acc;\n }, {});\n default:\n throw new Error(\n `Error when parsing directive values: unexpected type '${node.kind}'`\n );\n }\n}\n\nfunction getArgumentValue(\n argument: ArgumentNode,\n expectedType: Kind.STRING\n): string;\n\nfunction getArgumentValue(\n argument: ArgumentNode,\n expectedType: Kind.BOOLEAN\n): boolean;\n\nfunction getArgumentValue(\n argument: ArgumentNode,\n expectedType: Kind.LIST\n): unknown[];\n\nfunction getArgumentValue(\n argument: ArgumentNode,\n expectedType: Kind.OBJECT\n): Record<string, unknown>;\n\nfunction getArgumentValue(argument: ArgumentNode, expectedType: Kind) {\n const argumentType = argument.value.kind;\n\n invariant(\n argumentType === expectedType,\n `Expected argument '${argument.name.value}' to be of type '${expectedType}' but found '${argumentType}' instead.`\n );\n\n return getRawValue(argument.value);\n}\n\ninterface GetArgumentNodeOptions {\n required?: boolean;\n}\n\nfunction getDirectiveArgument(\n argumentName: string,\n directive: DirectiveNode,\n opts: GetArgumentNodeOptions & { required: true }\n): ArgumentNode;\n\nfunction getDirectiveArgument(\n argumentName: string,\n directive: DirectiveNode,\n opts?: GetArgumentNodeOptions\n): ArgumentNode | undefined;\n\nfunction getDirectiveArgument(\n argumentName: string,\n directive: DirectiveNode,\n { required = false }: { required?: boolean } = {}\n) {\n const argument = directive.arguments?.find(\n (directiveArgument) => directiveArgument.name.value === argumentName\n );\n\n invariant(\n argument || !required,\n `'${argumentName}' argument must be supplied for @tool`\n );\n\n return argument;\n}\n\nfunction getTypeName(type: TypeNode): string {\n let t = type;\n while (t.kind === \"NonNullType\" || t.kind === \"ListType\") {\n t = (t as NonNullTypeNode | ListTypeNode).type;\n }\n return (t as NamedTypeNode).name.value;\n}\n\nexport const ApplicationManifestPlugin = () => {\n const cache = new Map();\n let packageJson: any = null;\n let config: any = null;\n\n const clientCache = new InMemoryCache();\n const client = new ApolloClient({\n cache: clientCache,\n link: new ApolloLink((operation) => {\n const body = print(\n removeClientDirective(sortTopLevelDefinitions(operation.query))\n );\n const name = operation.operationName;\n const definition = operation.query.definitions.find(\n (d) => d.kind === \"OperationDefinition\"\n );\n\n // Use `operation.query` so that the error reflects the end-user defined\n // document, not our sorted one\n invariant(\n definition,\n `Document does not contain an operation:\\n${print(operation.query)}`\n );\n\n const { directives, operation: type } = definition;\n\n const variables = definition.variableDefinitions?.reduce(\n (obj, varDef) => ({\n ...obj,\n [varDef.variable.name.value]: getTypeName(varDef.type),\n }),\n {}\n );\n\n const prefetch = directives?.some((d) => d.name.value === \"prefetch\");\n const id = createHash(\"sha256\").update(body).digest(\"hex\");\n // 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\n const prefetchID = prefetch ? \"__anonymous\" : undefined;\n\n const tools = directives\n ?.filter((d) => d.name.value === \"tool\")\n .map((directive) => {\n const name = getArgumentValue(\n getDirectiveArgument(\"name\", directive, { required: true }),\n Kind.STRING\n );\n\n invariant(\n name.indexOf(\" \") === -1,\n `Tool with name \"${name}\" contains spaces which is not allowed.`\n );\n\n const description = getArgumentValue(\n getDirectiveArgument(\"description\", directive, { required: true }),\n Kind.STRING\n );\n\n const extraInputsNode = getDirectiveArgument(\n \"extraInputs\",\n directive\n );\n\n const labelsNode = getDirectiveArgument(\"labels\", directive);\n\n const toolOptions: ManifestTool = {\n name,\n description,\n };\n\n if (extraInputsNode) {\n toolOptions.extraInputs = getArgumentValue(\n extraInputsNode,\n Kind.LIST\n ) as ManifestExtraInput[];\n }\n\n if (labelsNode) {\n const labels = getLabelsFromConfig(\n getArgumentValue(labelsNode, Kind.OBJECT)\n );\n\n if (labels) {\n toolOptions.labels = labels;\n }\n }\n\n return toolOptions;\n });\n\n // TODO: Make this object satisfy the `ManifestOperation` type. Currently\n // it errors because we need more validation on a few of these fields\n return of({\n data: { id, name, type, body, variables, prefetch, prefetchID, tools },\n });\n }),\n });\n\n const processFile = async (file: string) => {\n const code = readFileSync(file, \"utf-8\");\n\n if (!code.includes(\"gql\")) return;\n\n const fileHash = createHash(\"md5\").update(code).digest(\"hex\");\n if (cache.get(\"file\")?.hash === fileHash) return;\n const sources = gqlPluckFromCodeStringSync(file, code, {\n modules: [\n { name: \"graphql-tag\", identifier: \"gql\" },\n { name: \"@apollo/client\", identifier: \"gql\" },\n ],\n }).map((source) => ({\n node: parse(source.body),\n file,\n location: source.locationOffset,\n }));\n\n const operations = [];\n for (const source of sources) {\n const type = (\n source.node.definitions.find(\n (d) => d.kind === \"OperationDefinition\"\n ) as OperationDefinitionNode\n ).operation;\n\n let result;\n if (type === \"query\") {\n result = await client.query({\n query: source.node,\n fetchPolicy: \"no-cache\",\n });\n } else if (type === \"mutation\") {\n result = await client.mutate({\n mutation: source.node,\n fetchPolicy: \"no-cache\",\n });\n } else {\n throw new Error(\n \"Found an unsupported operation type. Only Query and Mutation are supported.\"\n );\n }\n operations.push(result.data);\n }\n\n cache.set(file, {\n file: file,\n hash: fileHash,\n operations,\n });\n };\n\n const generateManifest = async () => {\n const operations = Array.from(cache.values()).flatMap(\n (entry) => entry.operations\n );\n\n invariant(\n operations.filter((o) => o.prefetch).length <= 1,\n \"Found multiple operations marked as `@prefetch`. You can only mark 1 operation with `@prefetch`.\"\n );\n\n let resource = \"\";\n if (config.command === \"serve\") {\n resource =\n packageJson.entry?.[config.mode] ??\n `http${config.server.https ? \"s\" : \"\"}://${config.server.host ?? \"localhost\"}:${config.server.port}`;\n } else {\n let entryPoint = packageJson.entry?.[config.mode];\n if (entryPoint) {\n resource = entryPoint;\n } else if (config.mode === \"production\") {\n resource = \"index.html\";\n } else {\n throw new Error(\n `No entry point found for mode \"${config.mode}\". Entry points other than \"development\" and \"production\" must be defined in package.json file.`\n );\n }\n }\n\n const manifest: ApplicationManifest = {\n format: \"apollo-ai-app-manifest\",\n version: \"1\",\n name: packageJson.name,\n description: packageJson.description,\n hash: createHash(\"sha256\").update(Date.now().toString()).digest(\"hex\"),\n operations: Array.from(cache.values()).flatMap(\n (entry) => entry.operations\n ),\n resource,\n csp: {\n connectDomains: packageJson.csp?.connectDomains ?? [],\n frameDomains: packageJson.csp?.frameDomains ?? [],\n redirectDomains: packageJson.csp?.redirectDomains ?? [],\n resourceDomains: packageJson.csp?.resourceDomains ?? [],\n },\n };\n\n if (\n packageJson.widgetSettings &&\n isNonEmptyObject(packageJson.widgetSettings)\n ) {\n function validateWidgetSetting(\n key: keyof ManifestWidgetSettings,\n type: \"string\" | \"boolean\"\n ) {\n if (key in widgetSettings) {\n invariant(\n typeof widgetSettings[key] === type,\n `Expected 'widgetSettings.${key}' to be of type '${type}' but found '${typeof widgetSettings[key]}' instead.`\n );\n }\n }\n\n const widgetSettings =\n packageJson.widgetSettings as ManifestWidgetSettings;\n\n validateWidgetSetting(\"prefersBorder\", \"boolean\");\n validateWidgetSetting(\"description\", \"string\");\n validateWidgetSetting(\"domain\", \"string\");\n\n manifest.widgetSettings = packageJson.widgetSettings;\n }\n\n if (packageJson.labels) {\n const labels = getLabelsFromConfig(packageJson.labels);\n\n if (labels) {\n manifest.labels = labels;\n }\n }\n\n // Always write to build directory so the MCP server picks it up\n const dest = path.resolve(\n root,\n config.build.outDir,\n \".application-manifest.json\"\n );\n mkdirSync(path.dirname(dest), { recursive: true });\n writeFileSync(dest, JSON.stringify(manifest));\n\n // Always write to the dev location so that the app can bundle the manifest content\n writeFileSync(\".application-manifest.json\", JSON.stringify(manifest));\n };\n\n return {\n name: \"OperationManifest\",\n\n async configResolved(resolvedConfig: any) {\n config = resolvedConfig;\n },\n\n async buildStart() {\n // Read package.json on start\n packageJson = JSON.parse(readFileSync(\"package.json\", \"utf-8\"));\n\n // Scan all files on startup\n const files = await glob(\"src/**/*.{ts,tsx,js,jsx}\");\n\n for (const file of files) {\n const fullPath = path.resolve(root, file);\n await processFile(fullPath);\n }\n\n // We don't want to do this here on builds cause it just gets overwritten anyways. We'll call it on writeBundle instead.\n if (config.command === \"serve\") {\n await generateManifest();\n }\n },\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n configureServer(server: any) {\n server.watcher.on(\"change\", async (file: string) => {\n if (file.endsWith(\"package.json\")) {\n packageJson = JSON.parse(readFileSync(\"package.json\", \"utf-8\"));\n await generateManifest();\n } else if (file.match(/\\.(jsx?|tsx?)$/)) {\n await processFile(file);\n await generateManifest();\n }\n });\n },\n\n async writeBundle() {\n await generateManifest();\n },\n };\n};\n\n// Sort the definitions in this document so that operations come before fragments,\n// and so that each kind of definition is sorted by name.\nexport function sortTopLevelDefinitions(query: DocumentNode): DocumentNode {\n const definitions = [...query.definitions];\n // We want to avoid unnecessary dependencies, so write out a comparison\n // function instead of using _.orderBy.\n definitions.sort((a, b) => {\n // This is a reverse sort by kind, so that OperationDefinition precedes FragmentDefinition.\n if (a.kind > b.kind) {\n return -1;\n }\n if (a.kind < b.kind) {\n return 1;\n }\n\n // Extract the name from each definition. Jump through some hoops because\n // non-executable definitions don't have to have names (even though any\n // DocumentNode actually passed here should only have executable\n // definitions).\n const aName =\n a.kind === \"OperationDefinition\" || a.kind === \"FragmentDefinition\" ?\n (a.name?.value ?? \"\")\n : \"\";\n const bName =\n b.kind === \"OperationDefinition\" || b.kind === \"FragmentDefinition\" ?\n (b.name?.value ?? \"\")\n : \"\";\n\n // Sort by name ascending.\n if (aName < bName) {\n return -1;\n }\n if (aName > bName) {\n return 1;\n }\n\n // Assuming that the document is \"valid\", no operation or fragment name can appear\n // more than once, so we don't need to differentiate further to have a deterministic\n // sort.\n return 0;\n });\n return {\n ...query,\n definitions,\n };\n}\n\ninterface LabelConfig {\n toolInvocation?: {\n invoking?: string;\n invoked?: string;\n };\n}\n\nfunction getLabelsFromConfig(config: LabelConfig): ManifestLabels | undefined {\n if (!(\"toolInvocation\" in config)) {\n return;\n }\n\n const { toolInvocation } = config;\n const labels: ManifestLabels = {};\n\n if (Object.hasOwn(toolInvocation, \"invoking\")) {\n validateType(toolInvocation.invoking, \"string\", {\n propertyName: \"labels.toolInvocation.invoking\",\n });\n\n labels[\"toolInvocation/invoking\"] = toolInvocation.invoking;\n }\n\n if (Object.hasOwn(toolInvocation, \"invoked\")) {\n validateType(toolInvocation.invoked, \"string\", {\n propertyName: \"labels.toolInvocation.invoked\",\n });\n\n labels[\"toolInvocation/invoked\"] = toolInvocation.invoked;\n }\n\n if (isNonEmptyObject(labels)) {\n return labels;\n }\n}\n\nfunction removeClientDirective(doc: DocumentNode) {\n return removeDirectivesFromDocument(\n [{ name: \"prefetch\" }, { name: \"tool\" }],\n doc\n )!;\n}\n\nfunction invariant(condition: any, message: string): asserts condition {\n if (!condition) {\n throw new Error(message);\n }\n}\n\n// possible values of `typeof`\ntype TypeofResult =\n | \"string\"\n | \"number\"\n | \"bigint\"\n | \"boolean\"\n | \"symbol\"\n | \"undefined\"\n | \"object\"\n | \"function\";\n\ntype TypeofResultToConcreteType<T extends TypeofResult> =\n T extends \"string\" ? string\n : T extends \"number\" ? number\n : T extends \"bigint\" ? bigint\n : T extends \"boolean\" ? boolean\n : T extends \"symbol\" ? symbol\n : T extends \"undefined\" ? undefined\n : T extends \"object\" ? object\n : T extends \"function\" ? Function\n : never;\n\nfunction validateType<Typeof extends TypeofResult>(\n value: unknown,\n expectedType: Typeof,\n options: { propertyName: string }\n): asserts value is TypeofResultToConcreteType<Typeof> {\n invariant(\n typeof value === expectedType,\n `Expected '${options.propertyName}' to be of type '${expectedType}' but found '${typeof value}' instead.`\n );\n}\n\nfunction isNonEmptyObject(obj: object) {\n return Object.keys(obj).length > 0;\n}\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@apollo/client-ai-apps",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.0",
|
|
4
4
|
"publishConfig": {
|
|
5
5
|
"access": "public"
|
|
6
6
|
},
|
|
@@ -39,6 +39,7 @@
|
|
|
39
39
|
"license": "ISC",
|
|
40
40
|
"description": "",
|
|
41
41
|
"devDependencies": {
|
|
42
|
+
"@apollo/client": "^4.0.12",
|
|
42
43
|
"@testing-library/jest-dom": "^6.9.1",
|
|
43
44
|
"@testing-library/react": "^16.3.0",
|
|
44
45
|
"@testing-library/react-render-stream": "^2.0.2",
|
|
@@ -56,11 +57,11 @@
|
|
|
56
57
|
"vitest": "^4.0.13"
|
|
57
58
|
},
|
|
58
59
|
"peerDependencies": {
|
|
59
|
-
"
|
|
60
|
-
"react
|
|
60
|
+
"@apollo/client": "^4.0.0",
|
|
61
|
+
"react": "^19.0.0",
|
|
62
|
+
"react-dom": "^19.0.0"
|
|
61
63
|
},
|
|
62
64
|
"dependencies": {
|
|
63
|
-
"@apollo/client": "^4.0.9",
|
|
64
65
|
"@graphql-tools/graphql-tag-pluck": "^8.3.23",
|
|
65
66
|
"crypto-hash": "^4.0.0",
|
|
66
67
|
"glob": "^11.0.3",
|
|
@@ -56,7 +56,12 @@ describe("Client Basics", () => {
|
|
|
56
56
|
},
|
|
57
57
|
],
|
|
58
58
|
resource: "index.html",
|
|
59
|
-
csp: {
|
|
59
|
+
csp: {
|
|
60
|
+
connectDomains: [],
|
|
61
|
+
resourceDomains: [],
|
|
62
|
+
frameDomains: [],
|
|
63
|
+
redirectDomains: [],
|
|
64
|
+
},
|
|
60
65
|
} satisfies ApplicationManifest;
|
|
61
66
|
|
|
62
67
|
const client = new ApolloClient({
|
|
@@ -146,7 +151,12 @@ describe("prefetchData", () => {
|
|
|
146
151
|
},
|
|
147
152
|
],
|
|
148
153
|
resource: "index.html",
|
|
149
|
-
csp: {
|
|
154
|
+
csp: {
|
|
155
|
+
connectDomains: [],
|
|
156
|
+
resourceDomains: [],
|
|
157
|
+
frameDomains: [],
|
|
158
|
+
redirectDomains: [],
|
|
159
|
+
},
|
|
150
160
|
} satisfies ApplicationManifest;
|
|
151
161
|
|
|
152
162
|
const client = new ApolloClient({
|
|
@@ -430,7 +440,12 @@ describe("prefetchData", () => {
|
|
|
430
440
|
},
|
|
431
441
|
],
|
|
432
442
|
resource: "index.html",
|
|
433
|
-
csp: {
|
|
443
|
+
csp: {
|
|
444
|
+
connectDomains: [],
|
|
445
|
+
resourceDomains: [],
|
|
446
|
+
frameDomains: [],
|
|
447
|
+
redirectDomains: [],
|
|
448
|
+
},
|
|
434
449
|
} satisfies ApplicationManifest;
|
|
435
450
|
|
|
436
451
|
const client = new ApolloClient({
|
|
@@ -620,7 +635,12 @@ function createManifest(
|
|
|
620
635
|
},
|
|
621
636
|
],
|
|
622
637
|
resource: "index.html",
|
|
623
|
-
csp: {
|
|
638
|
+
csp: {
|
|
639
|
+
resourceDomains: [],
|
|
640
|
+
connectDomains: [],
|
|
641
|
+
frameDomains: [],
|
|
642
|
+
redirectDomains: [],
|
|
643
|
+
},
|
|
624
644
|
...overrides,
|
|
625
645
|
};
|
|
626
646
|
}
|
package/src/index.ts
CHANGED
|
@@ -18,6 +18,8 @@ export type {
|
|
|
18
18
|
ManifestTool,
|
|
19
19
|
ManifestExtraInput,
|
|
20
20
|
ManifestCsp,
|
|
21
|
+
ManifestLabels,
|
|
22
|
+
ManifestWidgetSettings,
|
|
21
23
|
} from "./types/application-manifest.js";
|
|
22
24
|
|
|
23
25
|
export { ToolUseProvider } from "./react/context/ToolUseContext.js";
|
|
@@ -32,7 +34,6 @@ export { useToolOutput } from "./react/hooks/useToolOutput.js";
|
|
|
32
34
|
export { useToolResponseMetadata } from "./react/hooks/useToolResponseMetadata.js";
|
|
33
35
|
export { useWidgetState } from "./react/hooks/useWidgetState.js";
|
|
34
36
|
|
|
35
|
-
export * from "@apollo/client";
|
|
36
37
|
export { ApolloClient } from "./core/ApolloClient.js";
|
|
37
38
|
export { ApolloProvider } from "./react/ApolloProvider.js";
|
|
38
39
|
export { ToolCallLink } from "./link/ToolCallLink.js";
|
|
@@ -8,6 +8,7 @@ export type ApplicationManifest = {
|
|
|
8
8
|
operations: ManifestOperation[];
|
|
9
9
|
csp: ManifestCsp;
|
|
10
10
|
widgetSettings?: ManifestWidgetSettings;
|
|
11
|
+
labels?: ManifestLabels;
|
|
11
12
|
};
|
|
12
13
|
|
|
13
14
|
export type ManifestOperation = {
|
|
@@ -25,6 +26,7 @@ export type ManifestTool = {
|
|
|
25
26
|
name: string;
|
|
26
27
|
description: string;
|
|
27
28
|
extraInputs?: ManifestExtraInput[];
|
|
29
|
+
labels?: ManifestLabels;
|
|
28
30
|
};
|
|
29
31
|
|
|
30
32
|
export type ManifestWidgetSettings = {
|
|
@@ -41,5 +43,12 @@ export type ManifestExtraInput = {
|
|
|
41
43
|
|
|
42
44
|
export type ManifestCsp = {
|
|
43
45
|
connectDomains: string[];
|
|
46
|
+
frameDomains: string[];
|
|
47
|
+
redirectDomains: string[];
|
|
44
48
|
resourceDomains: string[];
|
|
45
49
|
};
|
|
50
|
+
|
|
51
|
+
export type ManifestLabels = {
|
|
52
|
+
"toolInvocation/invoking"?: string;
|
|
53
|
+
"toolInvocation/invoked"?: string;
|
|
54
|
+
};
|
|
@@ -43,6 +43,12 @@ describe("buildStart", () => {
|
|
|
43
43
|
test("Should write to dev application manifest file when using a serve command", async () => {
|
|
44
44
|
mockReadFile({
|
|
45
45
|
"package.json": JSON.stringify({
|
|
46
|
+
labels: {
|
|
47
|
+
toolInvocation: {
|
|
48
|
+
invoking: "Testing global...",
|
|
49
|
+
invoked: "Tested global!",
|
|
50
|
+
},
|
|
51
|
+
},
|
|
46
52
|
widgetSettings: {
|
|
47
53
|
description: "Test",
|
|
48
54
|
domain: "https://example.com",
|
|
@@ -50,11 +56,21 @@ describe("buildStart", () => {
|
|
|
50
56
|
} satisfies ManifestWidgetSettings,
|
|
51
57
|
}),
|
|
52
58
|
[`${root}/my-component.tsx`]: `
|
|
53
|
-
const MY_QUERY = gql\`query HelloWorldQuery($name: string!) @tool(
|
|
54
|
-
name: "
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
59
|
+
const MY_QUERY = gql\`query HelloWorldQuery($name: string!) @tool(
|
|
60
|
+
name: "hello-world",
|
|
61
|
+
description: "This is an awesome tool!",
|
|
62
|
+
extraInputs: [{
|
|
63
|
+
name: "doStuff",
|
|
64
|
+
type: "boolean",
|
|
65
|
+
description: "Should we do stuff?"
|
|
66
|
+
}],
|
|
67
|
+
labels: {
|
|
68
|
+
toolInvocation: {
|
|
69
|
+
invoking: "Testing tool...",
|
|
70
|
+
invoked: "Tested tool!"
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
) { helloWorld(name: $name) }\`;
|
|
58
74
|
`,
|
|
59
75
|
});
|
|
60
76
|
|
|
@@ -82,10 +98,16 @@ const MY_QUERY = gql\`query HelloWorldQuery($name: string!) @tool(name: "hello-w
|
|
|
82
98
|
{
|
|
83
99
|
"csp": {
|
|
84
100
|
"connectDomains": [],
|
|
101
|
+
"frameDomains": [],
|
|
102
|
+
"redirectDomains": [],
|
|
85
103
|
"resourceDomains": [],
|
|
86
104
|
},
|
|
87
105
|
"format": "apollo-ai-app-manifest",
|
|
88
106
|
"hash": "abc",
|
|
107
|
+
"labels": {
|
|
108
|
+
"toolInvocation/invoked": "Tested global!",
|
|
109
|
+
"toolInvocation/invoking": "Testing global...",
|
|
110
|
+
},
|
|
89
111
|
"operations": [
|
|
90
112
|
{
|
|
91
113
|
"body": "query HelloWorldQuery($name: string!) {
|
|
@@ -104,6 +126,10 @@ const MY_QUERY = gql\`query HelloWorldQuery($name: string!) @tool(name: "hello-w
|
|
|
104
126
|
"type": "boolean",
|
|
105
127
|
},
|
|
106
128
|
],
|
|
129
|
+
"labels": {
|
|
130
|
+
"toolInvocation/invoked": "Tested tool!",
|
|
131
|
+
"toolInvocation/invoking": "Testing tool...",
|
|
132
|
+
},
|
|
107
133
|
"name": "hello-world",
|
|
108
134
|
},
|
|
109
135
|
],
|
|
@@ -175,6 +201,8 @@ const MY_QUERY = gql\`query HelloWorldQuery($name: string!) @tool(name: "hello-w
|
|
|
175
201
|
{
|
|
176
202
|
"csp": {
|
|
177
203
|
"connectDomains": [],
|
|
204
|
+
"frameDomains": [],
|
|
205
|
+
"redirectDomains": [],
|
|
178
206
|
"resourceDomains": [],
|
|
179
207
|
},
|
|
180
208
|
"format": "apollo-ai-app-manifest",
|
|
@@ -217,6 +245,8 @@ const MY_QUERY = gql\`query HelloWorldQuery($name: string!) @tool(name: "hello-w
|
|
|
217
245
|
{
|
|
218
246
|
"csp": {
|
|
219
247
|
"connectDomains": [],
|
|
248
|
+
"frameDomains": [],
|
|
249
|
+
"redirectDomains": [],
|
|
220
250
|
"resourceDomains": [],
|
|
221
251
|
},
|
|
222
252
|
"format": "apollo-ai-app-manifest",
|
|
@@ -271,6 +301,8 @@ const MY_QUERY = gql\`query HelloWorldQuery($name: string!) @tool(name: "hello-w
|
|
|
271
301
|
{
|
|
272
302
|
"csp": {
|
|
273
303
|
"connectDomains": [],
|
|
304
|
+
"frameDomains": [],
|
|
305
|
+
"redirectDomains": [],
|
|
274
306
|
"resourceDomains": [],
|
|
275
307
|
},
|
|
276
308
|
"format": "apollo-ai-app-manifest",
|
|
@@ -349,6 +381,8 @@ const MY_QUERY = gql\`query HelloWorldQuery($name: string!) @tool(name: "hello-w
|
|
|
349
381
|
{
|
|
350
382
|
"csp": {
|
|
351
383
|
"connectDomains": [],
|
|
384
|
+
"frameDomains": [],
|
|
385
|
+
"redirectDomains": [],
|
|
352
386
|
"resourceDomains": [],
|
|
353
387
|
},
|
|
354
388
|
"format": "apollo-ai-app-manifest",
|
|
@@ -726,6 +760,131 @@ const MY_QUERY = gql\`query HelloWorldQuery($name: string!) @tool(name: "hello-w
|
|
|
726
760
|
await expect(plugin.buildStart()).resolves.toBeUndefined();
|
|
727
761
|
});
|
|
728
762
|
|
|
763
|
+
test("Should error when labels.toolInvocation.invoking in package.json is not a string", async () => {
|
|
764
|
+
mockReadFile({
|
|
765
|
+
"package.json": JSON.stringify({
|
|
766
|
+
labels: {
|
|
767
|
+
toolInvocation: {
|
|
768
|
+
invoking: true,
|
|
769
|
+
},
|
|
770
|
+
},
|
|
771
|
+
}),
|
|
772
|
+
"my-component.tsx": `
|
|
773
|
+
const MY_QUERY = gql\`query HelloWorldQuery @tool(name: "test", description: "Test") { helloWorld }\`;
|
|
774
|
+
`,
|
|
775
|
+
});
|
|
776
|
+
vi.spyOn(glob, "glob").mockImplementation(() =>
|
|
777
|
+
Promise.resolve(["my-component.tsx"])
|
|
778
|
+
);
|
|
779
|
+
vi.spyOn(path, "resolve").mockImplementation((_, file) => file);
|
|
780
|
+
vi.spyOn(fs, "writeFileSync");
|
|
781
|
+
|
|
782
|
+
const plugin = ApplicationManifestPlugin();
|
|
783
|
+
plugin.configResolved({ command: "serve", server: {} });
|
|
784
|
+
|
|
785
|
+
await expect(
|
|
786
|
+
async () => await plugin.buildStart()
|
|
787
|
+
).rejects.toThrowErrorMatchingInlineSnapshot(
|
|
788
|
+
`[Error: Expected 'labels.toolInvocation.invoking' to be of type 'string' but found 'boolean' instead.]`
|
|
789
|
+
);
|
|
790
|
+
});
|
|
791
|
+
|
|
792
|
+
test("Should error when labels.toolInvocation.invoking in @tool is not a string", async () => {
|
|
793
|
+
mockReadFile({
|
|
794
|
+
"package.json": JSON.stringify({}),
|
|
795
|
+
"my-component.tsx": `
|
|
796
|
+
const MY_QUERY = gql\`query HelloWorldQuery @tool(name: "test", description: "Test", labels: { toolInvocation: { invoking: true } }) { helloWorld }\`;
|
|
797
|
+
`,
|
|
798
|
+
});
|
|
799
|
+
vi.spyOn(glob, "glob").mockImplementation(() =>
|
|
800
|
+
Promise.resolve(["my-component.tsx"])
|
|
801
|
+
);
|
|
802
|
+
vi.spyOn(path, "resolve").mockImplementation((_, file) => file);
|
|
803
|
+
vi.spyOn(fs, "writeFileSync");
|
|
804
|
+
|
|
805
|
+
const plugin = ApplicationManifestPlugin();
|
|
806
|
+
plugin.configResolved({ command: "serve", server: {} });
|
|
807
|
+
|
|
808
|
+
await expect(
|
|
809
|
+
async () => await plugin.buildStart()
|
|
810
|
+
).rejects.toThrowErrorMatchingInlineSnapshot(
|
|
811
|
+
`[Error: Expected 'labels.toolInvocation.invoking' to be of type 'string' but found 'boolean' instead.]`
|
|
812
|
+
);
|
|
813
|
+
});
|
|
814
|
+
|
|
815
|
+
test("Should error when labels.toolInvocation.invoked in package.json is not a string", async () => {
|
|
816
|
+
mockReadFile({
|
|
817
|
+
"package.json": JSON.stringify({
|
|
818
|
+
labels: {
|
|
819
|
+
toolInvocation: {
|
|
820
|
+
invoked: true,
|
|
821
|
+
},
|
|
822
|
+
},
|
|
823
|
+
}),
|
|
824
|
+
"my-component.tsx": `
|
|
825
|
+
const MY_QUERY = gql\`query HelloWorldQuery @tool(name: "test", description: "Test") { helloWorld }\`;
|
|
826
|
+
`,
|
|
827
|
+
});
|
|
828
|
+
vi.spyOn(glob, "glob").mockImplementation(() =>
|
|
829
|
+
Promise.resolve(["my-component.tsx"])
|
|
830
|
+
);
|
|
831
|
+
vi.spyOn(path, "resolve").mockImplementation((_, file) => file);
|
|
832
|
+
vi.spyOn(fs, "writeFileSync");
|
|
833
|
+
|
|
834
|
+
const plugin = ApplicationManifestPlugin();
|
|
835
|
+
plugin.configResolved({ command: "serve", server: {} });
|
|
836
|
+
|
|
837
|
+
await expect(
|
|
838
|
+
async () => await plugin.buildStart()
|
|
839
|
+
).rejects.toThrowErrorMatchingInlineSnapshot(
|
|
840
|
+
`[Error: Expected 'labels.toolInvocation.invoked' to be of type 'string' but found 'boolean' instead.]`
|
|
841
|
+
);
|
|
842
|
+
});
|
|
843
|
+
|
|
844
|
+
test("Should error when labels.toolInvocation.invoked in @tool is not a string", async () => {
|
|
845
|
+
mockReadFile({
|
|
846
|
+
"package.json": JSON.stringify({}),
|
|
847
|
+
"my-component.tsx": `
|
|
848
|
+
const MY_QUERY = gql\`query HelloWorldQuery @tool(name: "test", description: "Test", labels: { toolInvocation: { invoked: true } }) { helloWorld }\`;
|
|
849
|
+
`,
|
|
850
|
+
});
|
|
851
|
+
vi.spyOn(glob, "glob").mockImplementation(() =>
|
|
852
|
+
Promise.resolve(["my-component.tsx"])
|
|
853
|
+
);
|
|
854
|
+
vi.spyOn(path, "resolve").mockImplementation((_, file) => file);
|
|
855
|
+
vi.spyOn(fs, "writeFileSync");
|
|
856
|
+
|
|
857
|
+
const plugin = ApplicationManifestPlugin();
|
|
858
|
+
plugin.configResolved({ command: "serve", server: {} });
|
|
859
|
+
|
|
860
|
+
await expect(
|
|
861
|
+
async () => await plugin.buildStart()
|
|
862
|
+
).rejects.toThrowErrorMatchingInlineSnapshot(
|
|
863
|
+
`[Error: Expected 'labels.toolInvocation.invoked' to be of type 'string' but found 'boolean' instead.]`
|
|
864
|
+
);
|
|
865
|
+
});
|
|
866
|
+
|
|
867
|
+
test("Should allow empty labels value", async () => {
|
|
868
|
+
mockReadFile({
|
|
869
|
+
"package.json": JSON.stringify({
|
|
870
|
+
labels: {},
|
|
871
|
+
}),
|
|
872
|
+
"my-component.tsx": `
|
|
873
|
+
const MY_QUERY = gql\`query HelloWorldQuery @tool(name: "test", description: "Test", labels: {}) { helloWorld }\`;
|
|
874
|
+
`,
|
|
875
|
+
});
|
|
876
|
+
vi.spyOn(glob, "glob").mockImplementation(() =>
|
|
877
|
+
Promise.resolve(["my-component.tsx"])
|
|
878
|
+
);
|
|
879
|
+
vi.spyOn(path, "resolve").mockImplementation((_, file) => file);
|
|
880
|
+
vi.spyOn(fs, "writeFileSync");
|
|
881
|
+
|
|
882
|
+
const plugin = ApplicationManifestPlugin();
|
|
883
|
+
plugin.configResolved({ command: "serve", server: {}, build: {} });
|
|
884
|
+
|
|
885
|
+
await expect(plugin.buildStart()).resolves.toBeUndefined();
|
|
886
|
+
});
|
|
887
|
+
|
|
729
888
|
test("Should error when an unknown type is discovered", async () => {
|
|
730
889
|
mockReadFile({
|
|
731
890
|
"package.json": JSON.stringify({}),
|
|
@@ -793,6 +952,8 @@ const MY_QUERY = gql\`query HelloWorldQuery($name: string!) @tool(name: "hello-w
|
|
|
793
952
|
{
|
|
794
953
|
"csp": {
|
|
795
954
|
"connectDomains": [],
|
|
955
|
+
"frameDomains": [],
|
|
956
|
+
"redirectDomains": [],
|
|
796
957
|
"resourceDomains": [],
|
|
797
958
|
},
|
|
798
959
|
"format": "apollo-ai-app-manifest",
|
|
@@ -21,6 +21,7 @@ import path from "path";
|
|
|
21
21
|
import type {
|
|
22
22
|
ApplicationManifest,
|
|
23
23
|
ManifestExtraInput,
|
|
24
|
+
ManifestLabels,
|
|
24
25
|
ManifestTool,
|
|
25
26
|
ManifestWidgetSettings,
|
|
26
27
|
} from "../types/application-manifest.js";
|
|
@@ -180,6 +181,8 @@ export const ApplicationManifestPlugin = () => {
|
|
|
180
181
|
directive
|
|
181
182
|
);
|
|
182
183
|
|
|
184
|
+
const labelsNode = getDirectiveArgument("labels", directive);
|
|
185
|
+
|
|
183
186
|
const toolOptions: ManifestTool = {
|
|
184
187
|
name,
|
|
185
188
|
description,
|
|
@@ -192,6 +195,16 @@ export const ApplicationManifestPlugin = () => {
|
|
|
192
195
|
) as ManifestExtraInput[];
|
|
193
196
|
}
|
|
194
197
|
|
|
198
|
+
if (labelsNode) {
|
|
199
|
+
const labels = getLabelsFromConfig(
|
|
200
|
+
getArgumentValue(labelsNode, Kind.OBJECT)
|
|
201
|
+
);
|
|
202
|
+
|
|
203
|
+
if (labels) {
|
|
204
|
+
toolOptions.labels = labels;
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
|
|
195
208
|
return toolOptions;
|
|
196
209
|
});
|
|
197
210
|
|
|
@@ -295,13 +308,15 @@ export const ApplicationManifestPlugin = () => {
|
|
|
295
308
|
resource,
|
|
296
309
|
csp: {
|
|
297
310
|
connectDomains: packageJson.csp?.connectDomains ?? [],
|
|
311
|
+
frameDomains: packageJson.csp?.frameDomains ?? [],
|
|
312
|
+
redirectDomains: packageJson.csp?.redirectDomains ?? [],
|
|
298
313
|
resourceDomains: packageJson.csp?.resourceDomains ?? [],
|
|
299
314
|
},
|
|
300
315
|
};
|
|
301
316
|
|
|
302
317
|
if (
|
|
303
318
|
packageJson.widgetSettings &&
|
|
304
|
-
|
|
319
|
+
isNonEmptyObject(packageJson.widgetSettings)
|
|
305
320
|
) {
|
|
306
321
|
function validateWidgetSetting(
|
|
307
322
|
key: keyof ManifestWidgetSettings,
|
|
@@ -325,6 +340,14 @@ export const ApplicationManifestPlugin = () => {
|
|
|
325
340
|
manifest.widgetSettings = packageJson.widgetSettings;
|
|
326
341
|
}
|
|
327
342
|
|
|
343
|
+
if (packageJson.labels) {
|
|
344
|
+
const labels = getLabelsFromConfig(packageJson.labels);
|
|
345
|
+
|
|
346
|
+
if (labels) {
|
|
347
|
+
manifest.labels = labels;
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
|
|
328
351
|
// Always write to build directory so the MCP server picks it up
|
|
329
352
|
const dest = path.resolve(
|
|
330
353
|
root,
|
|
@@ -429,6 +452,42 @@ export function sortTopLevelDefinitions(query: DocumentNode): DocumentNode {
|
|
|
429
452
|
};
|
|
430
453
|
}
|
|
431
454
|
|
|
455
|
+
interface LabelConfig {
|
|
456
|
+
toolInvocation?: {
|
|
457
|
+
invoking?: string;
|
|
458
|
+
invoked?: string;
|
|
459
|
+
};
|
|
460
|
+
}
|
|
461
|
+
|
|
462
|
+
function getLabelsFromConfig(config: LabelConfig): ManifestLabels | undefined {
|
|
463
|
+
if (!("toolInvocation" in config)) {
|
|
464
|
+
return;
|
|
465
|
+
}
|
|
466
|
+
|
|
467
|
+
const { toolInvocation } = config;
|
|
468
|
+
const labels: ManifestLabels = {};
|
|
469
|
+
|
|
470
|
+
if (Object.hasOwn(toolInvocation, "invoking")) {
|
|
471
|
+
validateType(toolInvocation.invoking, "string", {
|
|
472
|
+
propertyName: "labels.toolInvocation.invoking",
|
|
473
|
+
});
|
|
474
|
+
|
|
475
|
+
labels["toolInvocation/invoking"] = toolInvocation.invoking;
|
|
476
|
+
}
|
|
477
|
+
|
|
478
|
+
if (Object.hasOwn(toolInvocation, "invoked")) {
|
|
479
|
+
validateType(toolInvocation.invoked, "string", {
|
|
480
|
+
propertyName: "labels.toolInvocation.invoked",
|
|
481
|
+
});
|
|
482
|
+
|
|
483
|
+
labels["toolInvocation/invoked"] = toolInvocation.invoked;
|
|
484
|
+
}
|
|
485
|
+
|
|
486
|
+
if (isNonEmptyObject(labels)) {
|
|
487
|
+
return labels;
|
|
488
|
+
}
|
|
489
|
+
}
|
|
490
|
+
|
|
432
491
|
function removeClientDirective(doc: DocumentNode) {
|
|
433
492
|
return removeDirectivesFromDocument(
|
|
434
493
|
[{ name: "prefetch" }, { name: "tool" }],
|
|
@@ -441,3 +500,40 @@ function invariant(condition: any, message: string): asserts condition {
|
|
|
441
500
|
throw new Error(message);
|
|
442
501
|
}
|
|
443
502
|
}
|
|
503
|
+
|
|
504
|
+
// possible values of `typeof`
|
|
505
|
+
type TypeofResult =
|
|
506
|
+
| "string"
|
|
507
|
+
| "number"
|
|
508
|
+
| "bigint"
|
|
509
|
+
| "boolean"
|
|
510
|
+
| "symbol"
|
|
511
|
+
| "undefined"
|
|
512
|
+
| "object"
|
|
513
|
+
| "function";
|
|
514
|
+
|
|
515
|
+
type TypeofResultToConcreteType<T extends TypeofResult> =
|
|
516
|
+
T extends "string" ? string
|
|
517
|
+
: T extends "number" ? number
|
|
518
|
+
: T extends "bigint" ? bigint
|
|
519
|
+
: T extends "boolean" ? boolean
|
|
520
|
+
: T extends "symbol" ? symbol
|
|
521
|
+
: T extends "undefined" ? undefined
|
|
522
|
+
: T extends "object" ? object
|
|
523
|
+
: T extends "function" ? Function
|
|
524
|
+
: never;
|
|
525
|
+
|
|
526
|
+
function validateType<Typeof extends TypeofResult>(
|
|
527
|
+
value: unknown,
|
|
528
|
+
expectedType: Typeof,
|
|
529
|
+
options: { propertyName: string }
|
|
530
|
+
): asserts value is TypeofResultToConcreteType<Typeof> {
|
|
531
|
+
invariant(
|
|
532
|
+
typeof value === expectedType,
|
|
533
|
+
`Expected '${options.propertyName}' to be of type '${expectedType}' but found '${typeof value}' instead.`
|
|
534
|
+
);
|
|
535
|
+
}
|
|
536
|
+
|
|
537
|
+
function isNonEmptyObject(obj: object) {
|
|
538
|
+
return Object.keys(obj).length > 0;
|
|
539
|
+
}
|