@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 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";
@@ -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,GACZ,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,cAAc,gBAAgB,CAAC;AAC/B,OAAO,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AACtD,OAAO,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAC3D,OAAO,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC"}
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;AAU5E,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,cAAc,gBAAgB,CAAC;AAC/B,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} 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 * from \"@apollo/client\";\nexport { ApolloClient } from \"./core/ApolloClient.js\";\nexport { ApolloProvider } from \"./react/ApolloProvider.js\";\nexport { ToolCallLink } from \"./link/ToolCallLink.js\";\n"]}
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;CACzC,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;CACpC,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,eAAe,EAAE,MAAM,EAAE,CAAC;CAC3B,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;AA0GjB,eAAO,MAAM,yBAAyB;;mCA+NG,GAAG;;4BAuBhB,GAAG;;CAgB9B,CAAC;AAIF,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,YAAY,GAAG,YAAY,CA2CzE"}
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
- Object.keys(packageJson.widgetSettings).length > 0) {
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":"AAAA,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,IAAI,CAAC;AAC5D,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAC5B,OAAO,EAAE,0BAA0B,EAAE,MAAM,kCAAkC,CAAC;AAC9E,OAAO,EAAE,UAAU,EAAE,MAAM,QAAQ,CAAC;AAYpC,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AAC7C,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AACzE,OAAO,EAAE,4BAA4B,EAAE,MAAM,mCAAmC,CAAC;AACjF,OAAO,EAAE,EAAE,EAAE,MAAM,MAAM,CAAC;AAC1B,OAAO,IAAI,MAAM,MAAM,CAAC;AAQxB,MAAM,IAAI,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC;AAE3B,SAAS,WAAW,CAAC,IAAe;IAClC,QAAQ,IAAI,CAAC,IAAI,EAAE,CAAC;QAClB,KAAK,IAAI,CAAC,MAAM,CAAC;QACjB,KAAK,IAAI,CAAC,OAAO;YACf,OAAO,IAAI,CAAC,KAAK,CAAC;QACpB,KAAK,IAAI,CAAC,IAAI;YACZ,OAAO,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;QACtC,KAAK,IAAI,CAAC,MAAM;YACd,OAAO,IAAI,CAAC,MAAM,CAAC,MAAM,CAAsB,CAAC,GAAG,EAAE,KAAK,EAAE,EAAE;gBAC5D,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,WAAW,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;gBACjD,OAAO,GAAG,CAAC;YACb,CAAC,EAAE,EAAE,CAAC,CAAC;QACT;YACE,MAAM,IAAI,KAAK,CACb,yDAAyD,IAAI,CAAC,IAAI,GAAG,CACtE,CAAC;IACN,CAAC;AACH,CAAC;AAsBD,SAAS,gBAAgB,CAAC,QAAsB,EAAE,YAAkB;IAClE,MAAM,YAAY,GAAG,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC;IAEzC,SAAS,CACP,YAAY,KAAK,YAAY,EAC7B,sBAAsB,QAAQ,CAAC,IAAI,CAAC,KAAK,oBAAoB,YAAY,gBAAgB,YAAY,YAAY,CAClH,CAAC;IAEF,OAAO,WAAW,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;AACrC,CAAC;AAkBD,SAAS,oBAAoB,CAC3B,YAAoB,EACpB,SAAwB,EACxB,EAAE,QAAQ,GAAG,KAAK,KAA6B,EAAE;IAEjD,MAAM,QAAQ,GAAG,SAAS,CAAC,SAAS,EAAE,IAAI,CACxC,CAAC,iBAAiB,EAAE,EAAE,CAAC,iBAAiB,CAAC,IAAI,CAAC,KAAK,KAAK,YAAY,CACrE,CAAC;IAEF,SAAS,CACP,QAAQ,IAAI,CAAC,QAAQ,EACrB,IAAI,YAAY,uCAAuC,CACxD,CAAC;IAEF,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED,SAAS,WAAW,CAAC,IAAc;IACjC,IAAI,CAAC,GAAG,IAAI,CAAC;IACb,OAAO,CAAC,CAAC,IAAI,KAAK,aAAa,IAAI,CAAC,CAAC,IAAI,KAAK,UAAU,EAAE,CAAC;QACzD,CAAC,GAAI,CAAoC,CAAC,IAAI,CAAC;IACjD,CAAC;IACD,OAAQ,CAAmB,CAAC,IAAI,CAAC,KAAK,CAAC;AACzC,CAAC;AAED,MAAM,CAAC,MAAM,yBAAyB,GAAG,GAAG,EAAE;IAC5C,MAAM,KAAK,GAAG,IAAI,GAAG,EAAE,CAAC;IACxB,IAAI,WAAW,GAAQ,IAAI,CAAC;IAC5B,IAAI,MAAM,GAAQ,IAAI,CAAC;IAEvB,MAAM,WAAW,GAAG,IAAI,aAAa,EAAE,CAAC;IACxC,MAAM,MAAM,GAAG,IAAI,YAAY,CAAC;QAC9B,KAAK,EAAE,WAAW;QAClB,IAAI,EAAE,IAAI,UAAU,CAAC,CAAC,SAAS,EAAE,EAAE;YACjC,MAAM,IAAI,GAAG,KAAK,CAChB,qBAAqB,CAAC,uBAAuB,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,CAChE,CAAC;YACF,MAAM,IAAI,GAAG,SAAS,CAAC,aAAa,CAAC;YACrC,MAAM,UAAU,GAAG,SAAS,CAAC,KAAK,CAAC,WAAW,CAAC,IAAI,CACjD,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,qBAAqB,CACxC,CAAC;YAEF,wEAAwE;YACxE,+BAA+B;YAC/B,SAAS,CACP,UAAU,EACV,4CAA4C,KAAK,CAAC,SAAS,CAAC,KAAK,CAAC,EAAE,CACrE,CAAC;YAEF,MAAM,EAAE,UAAU,EAAE,SAAS,EAAE,IAAI,EAAE,GAAG,UAAU,CAAC;YAEnD,MAAM,SAAS,GAAG,UAAU,CAAC,mBAAmB,EAAE,MAAM,CACtD,CAAC,GAAG,EAAE,MAAM,EAAE,EAAE,CAAC,CAAC;gBAChB,GAAG,GAAG;gBACN,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,WAAW,CAAC,MAAM,CAAC,IAAI,CAAC;aACvD,CAAC,EACF,EAAE,CACH,CAAC;YAEF,MAAM,QAAQ,GAAG,UAAU,EAAE,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,KAAK,UAAU,CAAC,CAAC;YACtE,MAAM,EAAE,GAAG,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;YAC3D,kMAAkM;YAClM,MAAM,UAAU,GAAG,QAAQ,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,SAAS,CAAC;YAExD,MAAM,KAAK,GAAG,UAAU;gBACtB,EAAE,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,KAAK,MAAM,CAAC;iBACvC,GAAG,CAAC,CAAC,SAAS,EAAE,EAAE;gBACjB,MAAM,IAAI,GAAG,gBAAgB,CAC3B,oBAAoB,CAAC,MAAM,EAAE,SAAS,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,EAC3D,IAAI,CAAC,MAAM,CACZ,CAAC;gBAEF,SAAS,CACP,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,EACxB,mBAAmB,IAAI,yCAAyC,CACjE,CAAC;gBAEF,MAAM,WAAW,GAAG,gBAAgB,CAClC,oBAAoB,CAAC,aAAa,EAAE,SAAS,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,EAClE,IAAI,CAAC,MAAM,CACZ,CAAC;gBAEF,MAAM,eAAe,GAAG,oBAAoB,CAC1C,aAAa,EACb,SAAS,CACV,CAAC;gBAEF,MAAM,WAAW,GAAiB;oBAChC,IAAI;oBACJ,WAAW;iBACZ,CAAC;gBAEF,IAAI,eAAe,EAAE,CAAC;oBACpB,WAAW,CAAC,WAAW,GAAG,gBAAgB,CACxC,eAAe,EACf,IAAI,CAAC,IAAI,CACc,CAAC;gBAC5B,CAAC;gBAED,OAAO,WAAW,CAAC;YACrB,CAAC,CAAC,CAAC;YAEL,yEAAyE;YACzE,qEAAqE;YACrE,OAAO,EAAE,CAAC;gBACR,IAAI,EAAE,EAAE,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,SAAS,EAAE,QAAQ,EAAE,UAAU,EAAE,KAAK,EAAE;aACvE,CAAC,CAAC;QACL,CAAC,CAAC;KACH,CAAC,CAAC;IAEH,MAAM,WAAW,GAAG,KAAK,EAAE,IAAY,EAAE,EAAE;QACzC,MAAM,IAAI,GAAG,YAAY,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;QAEzC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC;YAAE,OAAO;QAElC,MAAM,QAAQ,GAAG,UAAU,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QAC9D,IAAI,KAAK,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,IAAI,KAAK,QAAQ;YAAE,OAAO;QACjD,MAAM,OAAO,GAAG,0BAA0B,CAAC,IAAI,EAAE,IAAI,EAAE;YACrD,OAAO,EAAE;gBACP,EAAE,IAAI,EAAE,aAAa,EAAE,UAAU,EAAE,KAAK,EAAE;gBAC1C,EAAE,IAAI,EAAE,gBAAgB,EAAE,UAAU,EAAE,KAAK,EAAE;aAC9C;SACF,CAAC,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;YAClB,IAAI,EAAE,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC;YACxB,IAAI;YACJ,QAAQ,EAAE,MAAM,CAAC,cAAc;SAChC,CAAC,CAAC,CAAC;QAEJ,MAAM,UAAU,GAAG,EAAE,CAAC;QACtB,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;YAC7B,MAAM,IAAI,GACR,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,IAAI,CAC1B,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,qBAAqB,CAE1C,CAAC,SAAS,CAAC;YAEZ,IAAI,MAAM,CAAC;YACX,IAAI,IAAI,KAAK,OAAO,EAAE,CAAC;gBACrB,MAAM,GAAG,MAAM,MAAM,CAAC,KAAK,CAAC;oBAC1B,KAAK,EAAE,MAAM,CAAC,IAAI;oBAClB,WAAW,EAAE,UAAU;iBACxB,CAAC,CAAC;YACL,CAAC;iBAAM,IAAI,IAAI,KAAK,UAAU,EAAE,CAAC;gBAC/B,MAAM,GAAG,MAAM,MAAM,CAAC,MAAM,CAAC;oBAC3B,QAAQ,EAAE,MAAM,CAAC,IAAI;oBACrB,WAAW,EAAE,UAAU;iBACxB,CAAC,CAAC;YACL,CAAC;iBAAM,CAAC;gBACN,MAAM,IAAI,KAAK,CACb,6EAA6E,CAC9E,CAAC;YACJ,CAAC;YACD,UAAU,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;QAC/B,CAAC;QAED,KAAK,CAAC,GAAG,CAAC,IAAI,EAAE;YACd,IAAI,EAAE,IAAI;YACV,IAAI,EAAE,QAAQ;YACd,UAAU;SACX,CAAC,CAAC;IACL,CAAC,CAAC;IAEF,MAAM,gBAAgB,GAAG,KAAK,IAAI,EAAE;QAClC,MAAM,UAAU,GAAG,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC,CAAC,OAAO,CACnD,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,UAAU,CAC5B,CAAC;QAEF,SAAS,CACP,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,MAAM,IAAI,CAAC,EAChD,kGAAkG,CACnG,CAAC;QAEF,IAAI,QAAQ,GAAG,EAAE,CAAC;QAClB,IAAI,MAAM,CAAC,OAAO,KAAK,OAAO,EAAE,CAAC;YAC/B,QAAQ;gBACN,WAAW,CAAC,KAAK,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC;oBAChC,OAAO,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,MAAM,MAAM,CAAC,MAAM,CAAC,IAAI,IAAI,WAAW,IAAI,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC;QACzG,CAAC;aAAM,CAAC;YACN,IAAI,UAAU,GAAG,WAAW,CAAC,KAAK,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;YAClD,IAAI,UAAU,EAAE,CAAC;gBACf,QAAQ,GAAG,UAAU,CAAC;YACxB,CAAC;iBAAM,IAAI,MAAM,CAAC,IAAI,KAAK,YAAY,EAAE,CAAC;gBACxC,QAAQ,GAAG,YAAY,CAAC;YAC1B,CAAC;iBAAM,CAAC;gBACN,MAAM,IAAI,KAAK,CACb,kCAAkC,MAAM,CAAC,IAAI,iGAAiG,CAC/I,CAAC;YACJ,CAAC;QACH,CAAC;QAED,MAAM,QAAQ,GAAwB;YACpC,MAAM,EAAE,wBAAwB;YAChC,OAAO,EAAE,GAAG;YACZ,IAAI,EAAE,WAAW,CAAC,IAAI;YACtB,WAAW,EAAE,WAAW,CAAC,WAAW;YACpC,IAAI,EAAE,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC;YACtE,UAAU,EAAE,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC,CAAC,OAAO,CAC5C,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,UAAU,CAC5B;YACD,QAAQ;YACR,GAAG,EAAE;gBACH,cAAc,EAAE,WAAW,CAAC,GAAG,EAAE,cAAc,IAAI,EAAE;gBACrD,eAAe,EAAE,WAAW,CAAC,GAAG,EAAE,eAAe,IAAI,EAAE;aACxD;SACF,CAAC;QAEF,IACE,WAAW,CAAC,cAAc;YAC1B,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,cAAc,CAAC,CAAC,MAAM,GAAG,CAAC,EAClD,CAAC;YACD,SAAS,qBAAqB,CAC5B,GAAiC,EACjC,IAA0B;gBAE1B,IAAI,GAAG,IAAI,cAAc,EAAE,CAAC;oBAC1B,SAAS,CACP,OAAO,cAAc,CAAC,GAAG,CAAC,KAAK,IAAI,EACnC,4BAA4B,GAAG,oBAAoB,IAAI,gBAAgB,OAAO,cAAc,CAAC,GAAG,CAAC,YAAY,CAC9G,CAAC;gBACJ,CAAC;YACH,CAAC;YAED,MAAM,cAAc,GAClB,WAAW,CAAC,cAAwC,CAAC;YAEvD,qBAAqB,CAAC,eAAe,EAAE,SAAS,CAAC,CAAC;YAClD,qBAAqB,CAAC,aAAa,EAAE,QAAQ,CAAC,CAAC;YAC/C,qBAAqB,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;YAE1C,QAAQ,CAAC,cAAc,GAAG,WAAW,CAAC,cAAc,CAAC;QACvD,CAAC;QAED,gEAAgE;QAChE,MAAM,IAAI,GAAG,IAAI,CAAC,OAAO,CACvB,IAAI,EACJ,MAAM,CAAC,KAAK,CAAC,MAAM,EACnB,4BAA4B,CAC7B,CAAC;QACF,SAAS,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QACnD,aAAa,CAAC,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC,CAAC;QAE9C,mFAAmF;QACnF,aAAa,CAAC,4BAA4B,EAAE,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC,CAAC;IACxE,CAAC,CAAC;IAEF,OAAO;QACL,IAAI,EAAE,mBAAmB;QAEzB,KAAK,CAAC,cAAc,CAAC,cAAmB;YACtC,MAAM,GAAG,cAAc,CAAC;QAC1B,CAAC;QAED,KAAK,CAAC,UAAU;YACd,6BAA6B;YAC7B,WAAW,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,cAAc,EAAE,OAAO,CAAC,CAAC,CAAC;YAEhE,4BAA4B;YAC5B,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,0BAA0B,CAAC,CAAC;YAErD,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;gBACzB,MAAM,QAAQ,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;gBAC1C,MAAM,WAAW,CAAC,QAAQ,CAAC,CAAC;YAC9B,CAAC;YAED,wHAAwH;YACxH,IAAI,MAAM,CAAC,OAAO,KAAK,OAAO,EAAE,CAAC;gBAC/B,MAAM,gBAAgB,EAAE,CAAC;YAC3B,CAAC;QACH,CAAC;QAED,8DAA8D;QAC9D,eAAe,CAAC,MAAW;YACzB,MAAM,CAAC,OAAO,CAAC,EAAE,CAAC,QAAQ,EAAE,KAAK,EAAE,IAAY,EAAE,EAAE;gBACjD,IAAI,IAAI,CAAC,QAAQ,CAAC,cAAc,CAAC,EAAE,CAAC;oBAClC,WAAW,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,cAAc,EAAE,OAAO,CAAC,CAAC,CAAC;oBAChE,MAAM,gBAAgB,EAAE,CAAC;gBAC3B,CAAC;qBAAM,IAAI,IAAI,CAAC,KAAK,CAAC,gBAAgB,CAAC,EAAE,CAAC;oBACxC,MAAM,WAAW,CAAC,IAAI,CAAC,CAAC;oBACxB,MAAM,gBAAgB,EAAE,CAAC;gBAC3B,CAAC;YACH,CAAC,CAAC,CAAC;QACL,CAAC;QAED,KAAK,CAAC,WAAW;YACf,MAAM,gBAAgB,EAAE,CAAC;QAC3B,CAAC;KACF,CAAC;AACJ,CAAC,CAAC;AAEF,kFAAkF;AAClF,yDAAyD;AACzD,MAAM,UAAU,uBAAuB,CAAC,KAAmB;IACzD,MAAM,WAAW,GAAG,CAAC,GAAG,KAAK,CAAC,WAAW,CAAC,CAAC;IAC3C,uEAAuE;IACvE,uCAAuC;IACvC,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE;QACxB,2FAA2F;QAC3F,IAAI,CAAC,CAAC,IAAI,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC;YACpB,OAAO,CAAC,CAAC,CAAC;QACZ,CAAC;QACD,IAAI,CAAC,CAAC,IAAI,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC;YACpB,OAAO,CAAC,CAAC;QACX,CAAC;QAED,yEAAyE;QACzE,uEAAuE;QACvE,gEAAgE;QAChE,gBAAgB;QAChB,MAAM,KAAK,GACT,CAAC,CAAC,IAAI,KAAK,qBAAqB,IAAI,CAAC,CAAC,IAAI,KAAK,oBAAoB,CAAC,CAAC;YACnE,CAAC,CAAC,CAAC,IAAI,EAAE,KAAK,IAAI,EAAE,CAAC;YACvB,CAAC,CAAC,EAAE,CAAC;QACP,MAAM,KAAK,GACT,CAAC,CAAC,IAAI,KAAK,qBAAqB,IAAI,CAAC,CAAC,IAAI,KAAK,oBAAoB,CAAC,CAAC;YACnE,CAAC,CAAC,CAAC,IAAI,EAAE,KAAK,IAAI,EAAE,CAAC;YACvB,CAAC,CAAC,EAAE,CAAC;QAEP,0BAA0B;QAC1B,IAAI,KAAK,GAAG,KAAK,EAAE,CAAC;YAClB,OAAO,CAAC,CAAC,CAAC;QACZ,CAAC;QACD,IAAI,KAAK,GAAG,KAAK,EAAE,CAAC;YAClB,OAAO,CAAC,CAAC;QACX,CAAC;QAED,kFAAkF;QAClF,oFAAoF;QACpF,QAAQ;QACR,OAAO,CAAC,CAAC;IACX,CAAC,CAAC,CAAC;IACH,OAAO;QACL,GAAG,KAAK;QACR,WAAW;KACZ,CAAC;AACJ,CAAC;AAED,SAAS,qBAAqB,CAAC,GAAiB;IAC9C,OAAO,4BAA4B,CACjC,CAAC,EAAE,IAAI,EAAE,UAAU,EAAE,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,EACxC,GAAG,CACH,CAAC;AACL,CAAC;AAED,SAAS,SAAS,CAAC,SAAc,EAAE,OAAe;IAChD,IAAI,CAAC,SAAS,EAAE,CAAC;QACf,MAAM,IAAI,KAAK,CAAC,OAAO,CAAC,CAAC;IAC3B,CAAC;AACH,CAAC","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.3",
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
- "react": "^19.2.0",
60
- "react-dom": "^19.2.0"
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: { connectDomains: [], resourceDomains: [] },
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: { connectDomains: [], resourceDomains: [] },
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: { connectDomains: [], resourceDomains: [] },
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: { resourceDomains: [], connectDomains: [] },
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(name: "hello-world", description: "This is an awesome tool!", extraInputs: [{
54
- name: "doStuff",
55
- type: "boolean",
56
- description: "Should we do stuff?"
57
- }]) { helloWorld(name: $name) }\`;
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
- Object.keys(packageJson.widgetSettings).length > 0
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
+ }