@apollo/client-ai-apps 0.3.2 → 0.3.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (140) hide show
  1. package/.github/workflows/pr.yaml +52 -3
  2. package/.github/workflows/prep-release.yml +38 -0
  3. package/.github/workflows/release.yaml +8 -4
  4. package/.github/workflows/verify-changeset.yml +58 -0
  5. package/CHANGELOG.md +25 -0
  6. package/dist/core/ApolloClient.d.ts +3 -2
  7. package/dist/core/ApolloClient.d.ts.map +1 -0
  8. package/dist/core/ApolloClient.js +65 -0
  9. package/dist/core/ApolloClient.js.map +1 -0
  10. package/dist/index.d.ts +18 -17
  11. package/dist/index.d.ts.map +1 -0
  12. package/dist/index.js +16 -278
  13. package/dist/index.js.map +1 -0
  14. package/dist/link/ToolCallLink.d.ts +1 -0
  15. package/dist/link/ToolCallLink.d.ts.map +1 -0
  16. package/dist/link/ToolCallLink.js +39 -0
  17. package/dist/link/ToolCallLink.js.map +1 -0
  18. package/dist/react/ApolloProvider.d.ts +4 -3
  19. package/dist/react/ApolloProvider.d.ts.map +1 -0
  20. package/dist/react/ApolloProvider.js +30 -0
  21. package/dist/react/ApolloProvider.js.map +1 -0
  22. package/dist/react/context/ToolUseContext.d.ts +4 -3
  23. package/dist/react/context/ToolUseContext.d.ts.map +1 -0
  24. package/dist/react/context/ToolUseContext.js +11 -0
  25. package/dist/react/context/ToolUseContext.js.map +1 -0
  26. package/dist/react/hooks/useCallTool.d.ts +4 -0
  27. package/dist/react/hooks/useCallTool.d.ts.map +1 -0
  28. package/dist/react/hooks/useCallTool.js +5 -0
  29. package/dist/react/hooks/useCallTool.js.map +1 -0
  30. package/dist/react/hooks/useOpenAiGlobal.d.ts +2 -1
  31. package/dist/react/hooks/useOpenAiGlobal.d.ts.map +1 -0
  32. package/dist/react/hooks/useOpenAiGlobal.js +20 -0
  33. package/dist/react/hooks/useOpenAiGlobal.js.map +1 -0
  34. package/dist/react/hooks/useOpenExternal.d.ts +1 -0
  35. package/dist/react/hooks/useOpenExternal.d.ts.map +1 -0
  36. package/dist/react/hooks/useOpenExternal.js +5 -0
  37. package/dist/react/hooks/useOpenExternal.js.map +1 -0
  38. package/dist/react/hooks/useRequestDisplayMode.d.ts +2 -1
  39. package/dist/react/hooks/useRequestDisplayMode.d.ts.map +1 -0
  40. package/dist/react/hooks/useRequestDisplayMode.js +6 -0
  41. package/dist/react/hooks/useRequestDisplayMode.js.map +1 -0
  42. package/dist/react/hooks/useSendFollowUpMessage.d.ts +1 -0
  43. package/dist/react/hooks/useSendFollowUpMessage.d.ts.map +1 -0
  44. package/dist/react/hooks/useSendFollowUpMessage.js +8 -0
  45. package/dist/react/hooks/useSendFollowUpMessage.js.map +1 -0
  46. package/dist/react/hooks/useToolEffect.d.ts +1 -0
  47. package/dist/react/hooks/useToolEffect.d.ts.map +1 -0
  48. package/dist/react/hooks/useToolEffect.js +28 -0
  49. package/dist/react/hooks/useToolEffect.js.map +1 -0
  50. package/dist/react/hooks/useToolInput.d.ts +1 -0
  51. package/dist/react/hooks/useToolInput.d.ts.map +1 -0
  52. package/dist/react/hooks/useToolInput.js +6 -0
  53. package/dist/react/hooks/useToolInput.js.map +1 -0
  54. package/dist/react/hooks/useToolName.d.ts +1 -0
  55. package/dist/react/hooks/useToolName.d.ts.map +1 -0
  56. package/dist/react/hooks/useToolName.js +6 -0
  57. package/dist/react/hooks/useToolName.js.map +1 -0
  58. package/dist/react/hooks/useToolOutput.d.ts +2 -1
  59. package/dist/react/hooks/useToolOutput.d.ts.map +1 -0
  60. package/dist/react/hooks/useToolOutput.js +5 -0
  61. package/dist/react/hooks/useToolOutput.js.map +1 -0
  62. package/dist/react/hooks/useToolResponseMetadata.d.ts +2 -1
  63. package/dist/react/hooks/useToolResponseMetadata.d.ts.map +1 -0
  64. package/dist/react/hooks/useToolResponseMetadata.js +5 -0
  65. package/dist/react/hooks/useToolResponseMetadata.js.map +1 -0
  66. package/dist/react/hooks/useWidgetState.d.ts +3 -2
  67. package/dist/react/hooks/useWidgetState.d.ts.map +1 -0
  68. package/dist/react/hooks/useWidgetState.js +27 -0
  69. package/dist/react/hooks/useWidgetState.js.map +1 -0
  70. package/dist/types/application-manifest.d.ts +7 -0
  71. package/dist/types/application-manifest.d.ts.map +1 -0
  72. package/dist/types/application-manifest.js +2 -0
  73. package/dist/types/application-manifest.js.map +1 -0
  74. package/dist/types/openai.d.ts +1 -0
  75. package/dist/types/openai.d.ts.map +1 -0
  76. package/dist/types/openai.js +6 -0
  77. package/dist/types/openai.js.map +1 -0
  78. package/dist/vite/absolute_asset_imports_plugin.d.ts +1 -0
  79. package/dist/vite/absolute_asset_imports_plugin.d.ts.map +1 -0
  80. package/dist/vite/absolute_asset_imports_plugin.js +17 -0
  81. package/dist/vite/absolute_asset_imports_plugin.js.map +1 -0
  82. package/dist/vite/application_manifest_plugin.d.ts +2 -1
  83. package/dist/vite/application_manifest_plugin.d.ts.map +1 -0
  84. package/dist/vite/application_manifest_plugin.js +274 -0
  85. package/dist/vite/application_manifest_plugin.js.map +1 -0
  86. package/dist/vite/index.d.ts +3 -2
  87. package/dist/vite/index.d.ts.map +1 -0
  88. package/dist/vite/index.js +3 -307
  89. package/dist/vite/index.js.map +1 -0
  90. package/knope.toml +63 -0
  91. package/package.json +15 -8
  92. package/src/core/ApolloClient.ts +10 -5
  93. package/src/core/__tests__/ApolloClient.test.ts +12 -9
  94. package/src/index.ts +17 -17
  95. package/src/react/ApolloProvider.tsx +4 -3
  96. package/src/react/__tests__/ApolloProvider.test.tsx +3 -3
  97. package/src/react/context/ToolUseContext.tsx +2 -1
  98. package/src/react/hooks/__tests__/useCallTool.test.ts +1 -1
  99. package/src/react/hooks/__tests__/useOpenAiGlobal.test.ts +6 -6
  100. package/src/react/hooks/__tests__/useOpenExternal.test.tsx +2 -2
  101. package/src/react/hooks/__tests__/useRequestDisplayMode.test.ts +2 -2
  102. package/src/react/hooks/__tests__/useSendFollowUpMessage.test.ts +1 -1
  103. package/src/react/hooks/__tests__/useToolEffect.test.tsx +2 -2
  104. package/src/react/hooks/__tests__/useToolInput.test.ts +1 -1
  105. package/src/react/hooks/__tests__/useToolName.test.ts +1 -1
  106. package/src/react/hooks/__tests__/useToolOutput.test.tsx +2 -2
  107. package/src/react/hooks/__tests__/useToolResponseMetadata.test.tsx +2 -2
  108. package/src/react/hooks/__tests__/useWidgetState.test.tsx +2 -2
  109. package/src/react/hooks/useOpenAiGlobal.ts +2 -5
  110. package/src/react/hooks/useOpenExternal.ts +1 -1
  111. package/src/react/hooks/useRequestDisplayMode.ts +1 -1
  112. package/src/react/hooks/useToolEffect.tsx +3 -3
  113. package/src/react/hooks/useToolInput.ts +1 -1
  114. package/src/react/hooks/useToolName.ts +1 -1
  115. package/src/react/hooks/useToolOutput.ts +1 -1
  116. package/src/react/hooks/useToolResponseMetadata.ts +1 -1
  117. package/src/react/hooks/useWidgetState.ts +4 -3
  118. package/src/testing/internal/index.ts +2 -2
  119. package/src/testing/internal/matchers/index.ts +1 -1
  120. package/src/testing/internal/matchers/toRerender.ts +2 -2
  121. package/src/testing/internal/matchers/{index.d.ts → types.ts} +1 -1
  122. package/src/testing/internal/openai/dispatchStateChange.ts +1 -1
  123. package/src/testing/internal/openai/stubOpenAiGlobals.ts +6 -2
  124. package/src/types/application-manifest.ts +7 -0
  125. package/src/vite/__tests__/absolute_asset_imports_plugin.test.ts +2 -2
  126. package/src/vite/__tests__/application_manifest_plugin.test.ts +299 -240
  127. package/src/vite/application_manifest_plugin.ts +160 -96
  128. package/src/vite/index.ts +2 -2
  129. package/tsconfig.base.build.json +13 -0
  130. package/tsconfig.base.json +21 -0
  131. package/tsconfig.config.json +9 -0
  132. package/tsconfig.json +10 -0
  133. package/tsconfig.src.build.json +14 -0
  134. package/tsconfig.src.json +17 -0
  135. package/tsconfig.test.json +20 -0
  136. package/tsconfig.vite.build.json +6 -0
  137. package/tsconfig.vite.json +16 -0
  138. package/scripts/build-vite.mjs +0 -18
  139. package/scripts/build.mjs +0 -7
  140. package/scripts/shared.mjs +0 -9
@@ -15,7 +15,7 @@ jobs:
15
15
  - name: Set up Node.js
16
16
  uses: actions/setup-node@v4
17
17
  with:
18
- node-version: 20.x
18
+ node-version: 24.x
19
19
 
20
20
  - name: Install dependencies
21
21
  run: npm ci
@@ -23,10 +23,59 @@ jobs:
23
23
  - name: Run build
24
24
  run: npm run build
25
25
 
26
- - name: Test
26
+ typecheck:
27
+ runs-on: ubuntu-latest
28
+
29
+ steps:
30
+ - name: Checkout code
31
+ uses: actions/checkout@v4
32
+
33
+ - name: Set up Node.js
34
+ uses: actions/setup-node@v4
35
+ with:
36
+ node-version: 24.x
37
+
38
+ - name: Install dependencies
39
+ run: npm ci
40
+
41
+ - name: Check types
27
42
  shell: bash
28
- run: npm run test
43
+ run: npm run typecheck
44
+
45
+ check-formatting:
46
+ runs-on: ubuntu-latest
47
+
48
+ steps:
49
+ - name: Checkout code
50
+ uses: actions/checkout@v4
51
+
52
+ - name: Set up Node.js
53
+ uses: actions/setup-node@v4
54
+ with:
55
+ node-version: 24.x
56
+
57
+ - name: Install dependencies
58
+ run: npm ci
29
59
 
30
60
  - name: Check formatting
31
61
  shell: bash
32
62
  run: npm run format:check
63
+
64
+ test:
65
+ runs-on: ubuntu-latest
66
+
67
+ steps:
68
+ - name: Checkout code
69
+ uses: actions/checkout@v4
70
+
71
+ - name: Set up Node.js
72
+ uses: actions/setup-node@v4
73
+ with:
74
+ node-version: 24.x
75
+
76
+ - name: Install dependencies
77
+ run: npm ci
78
+
79
+ - name: Check types
80
+ shell: bash
81
+ run: npm test
@@ -0,0 +1,38 @@
1
+ name: Prepare Release
2
+
3
+ on: workflow_dispatch
4
+
5
+ permissions:
6
+ contents: write
7
+ pull-requests: write
8
+ issues: write
9
+ id-token: write
10
+
11
+ jobs:
12
+ prepare-release:
13
+ runs-on: ubuntu-latest
14
+ steps:
15
+ - uses: actions/checkout@v6
16
+
17
+ # We need to setup node because knope runs `npm run format` so we need to install prettier via npm
18
+ - name: Set up Node.js
19
+ uses: actions/setup-node@v4
20
+ with:
21
+ node-version: 24.x
22
+
23
+ - name: Install dependencies
24
+ run: npm ci
25
+
26
+ - name: Configure Git
27
+ run: |
28
+ git config --global user.name GitHub Actions
29
+ git config user.email github-actions@github.com
30
+
31
+ - uses: knope-dev/action@v2.1.0
32
+ with:
33
+ version: 0.22.0
34
+
35
+ - run: knope prepare-release --verbose
36
+ env:
37
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
38
+ BASE_BRANCH: ${{ github.ref_name }}
@@ -1,7 +1,10 @@
1
1
  name: Release new Version
2
2
 
3
3
  on:
4
- workflow_dispatch:
4
+ pull_request:
5
+ types: [closed]
6
+ branches:
7
+ - main
5
8
 
6
9
  permissions:
7
10
  contents: write
@@ -10,10 +13,11 @@ permissions:
10
13
  jobs:
11
14
  release:
12
15
  name: Release
13
- if: github.repository == 'apollographql/apollo-ai-apps-client'
16
+ # Important: Only run this when we've merged a "release/*" PR into main... all other PRs should be skipped.
17
+ if: github.repository == 'apollographql/apollo-ai-apps-client' && (github.event.pull_request.merged == true && startsWith(github.event.pull_request.head.ref, 'release/'))
14
18
  runs-on: ubuntu-latest
15
19
  steps:
16
- - uses: actions/checkout@v4
20
+ - uses: actions/checkout@v6
17
21
 
18
22
  - name: Setup Node.js 20.x
19
23
  uses: actions/setup-node@v4
@@ -42,7 +46,7 @@ jobs:
42
46
 
43
47
  - uses: knope-dev/action@v2.1.0
44
48
  with:
45
- version: 0.21.5
49
+ version: 0.22.0
46
50
 
47
51
  - run: knope release
48
52
  env:
@@ -0,0 +1,58 @@
1
+ name: Verify Changeset
2
+ on:
3
+ pull_request:
4
+ types: [opened, reopened, synchronize, ready_for_review, labeled]
5
+ paths-ignore:
6
+ - ".github/**"
7
+ - ".vscode/**"
8
+ - "docs/**"
9
+ - "*.md"
10
+ workflow_dispatch:
11
+
12
+ jobs:
13
+ verify-changeset:
14
+ if: ${{ !contains(github.event.pull_request.labels.*.name, 'skip-changeset') && !startsWith(github.head_ref, 'release/') && !startsWith(github.head_ref, 'conflict/') && !github.event.pull_request.draft }}
15
+ name: Verify
16
+ runs-on: ubuntu-24.04
17
+ permissions:
18
+ pull-requests: write
19
+ contents: read
20
+ steps:
21
+ - name: Verify changeset included
22
+ uses: actions/github-script@v7
23
+ with:
24
+ script: |
25
+ const dir = '.changeset/';
26
+ const pr = context.payload.pull_request;
27
+ const files = await github.paginate(
28
+ github.rest.pulls.listFiles,
29
+ { owner: context.repo.owner, repo: context.repo.repo, pull_number: pr.number, per_page: 100 }
30
+ );
31
+ const ok = files.some(f =>
32
+ f.filename.startsWith(dir) &&
33
+ ['added','modified','renamed'].includes(f.status)
34
+ );
35
+ if (!ok) {
36
+ core.setFailed(`No changeset added to ${dir}.`);
37
+ } else {
38
+ core.info(`Changeset found under ${dir}.`);
39
+ }
40
+ core.setOutput('ok', ok ? 'true' : 'false');
41
+ - name: Add changeset missing comment on failure
42
+ uses: actions/github-script@v7
43
+ if: failure()
44
+ with:
45
+ script: |
46
+ const pr = context.payload.pull_request;
47
+ await github.rest.issues.createComment({
48
+ owner: context.repo.owner,
49
+ repo: context.repo.repo,
50
+ issue_number: pr.number,
51
+ body: [
52
+ "❌ **Changeset file missing for PR**",
53
+ "",
54
+ "All changes should include an associated changeset file.",
55
+ "If this change does not require a changeset, please tag this PR with the `skip-changeset` tag.",
56
+ "Please use `knope document-change` to create a changeset. (installation instructions: https://knope.tech/installation/)"
57
+ ].join("\n")
58
+ });
package/CHANGELOG.md ADDED
@@ -0,0 +1,25 @@
1
+ ## 0.3.3 (2026-01-13)
2
+
3
+ ### Features
4
+
5
+ #### Add support for `widgetSettings` in the manifest file
6
+
7
+ This includes `widgetSettngs.prefersBorder`, `widgetSettings.description`, and `widgetSettings.domain`.
8
+
9
+ ```json
10
+ // package.json
11
+ {
12
+ // ...
13
+ "widgetSettings": {
14
+ "prefersBorder": true,
15
+ "description": "Widget description",
16
+ "domain": "https://example.com"
17
+ }
18
+ }
19
+ ```
20
+
21
+ These map to the OpenAI meta fields:
22
+
23
+ - `widgetSettings.description` -> `openai/widgetDescription`
24
+ - `widgetSettings.domain` -> `openai/widgetDomain`
25
+ - `widgetSettings.prefersBorder` -> `openai/widgetPrefersBorder,`
@@ -1,6 +1,6 @@
1
1
  import { ApolloClient as BaseApolloClient } from "@apollo/client";
2
- import "../types/openai";
3
- import { ApplicationManifest } from "../types/application-manifest";
2
+ import "../types/openai.js";
3
+ import type { ApplicationManifest } from "../types/application-manifest.js";
4
4
  export declare namespace ApolloClient {
5
5
  interface Options extends Omit<BaseApolloClient.Options, "link"> {
6
6
  link?: BaseApolloClient.Options["link"];
@@ -12,3 +12,4 @@ export declare class ApolloClient extends BaseApolloClient {
12
12
  constructor(options: ApolloClient.Options);
13
13
  prefetchData(): Promise<void>;
14
14
  }
15
+ //# sourceMappingURL=ApolloClient.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ApolloClient.d.ts","sourceRoot":"","sources":["../../src/core/ApolloClient.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,IAAI,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAKlE,OAAO,oBAAoB,CAAC;AAC5B,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,kCAAkC,CAAC;AAY5E,MAAM,CAAC,OAAO,WAAW,YAAY,CAAC;IAEpC,UAAiB,OAAQ,SAAQ,IAAI,CAAC,gBAAgB,CAAC,OAAO,EAAE,MAAM,CAAC;QACrE,IAAI,CAAC,EAAE,gBAAgB,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;QACxC,QAAQ,EAAE,mBAAmB,CAAC;KAC/B;CACF;AAED,qBAAa,YAAa,SAAQ,gBAAgB;IAChD,QAAQ,EAAE,mBAAmB,CAAC;gBAElB,OAAO,EAAE,YAAY,CAAC,OAAO;IAsBnC,YAAY;CA8CnB"}
@@ -0,0 +1,65 @@
1
+ import { ApolloClient as BaseApolloClient } from "@apollo/client";
2
+ import { DocumentTransform } from "@apollo/client";
3
+ import { removeDirectivesFromDocument } from "@apollo/client/utilities/internal";
4
+ import { parse } from "graphql";
5
+ import { __DEV__ } from "@apollo/client/utilities/environment";
6
+ import "../types/openai.js";
7
+ import { ToolCallLink } from "../link/ToolCallLink.js";
8
+ export class ApolloClient extends BaseApolloClient {
9
+ manifest;
10
+ constructor(options) {
11
+ const link = options.link ?? new ToolCallLink();
12
+ if (__DEV__) {
13
+ validateTerminatingLink(link);
14
+ }
15
+ super({
16
+ ...options,
17
+ link,
18
+ // Strip out the prefetch/tool directives so they don't get sent with the operation to the server
19
+ documentTransform: new DocumentTransform((document) => {
20
+ return removeDirectivesFromDocument([{ name: "prefetch" }, { name: "tool" }], document);
21
+ }),
22
+ });
23
+ this.manifest = options.manifest;
24
+ }
25
+ async prefetchData() {
26
+ const toolOutput = window.openai.toolOutput;
27
+ // Write prefetched data to the cache
28
+ this.manifest.operations.forEach((operation) => {
29
+ if (operation.prefetch &&
30
+ operation.prefetchID &&
31
+ toolOutput?.prefetch?.[operation.prefetchID]) {
32
+ this.writeQuery({
33
+ query: parse(operation.body),
34
+ data: toolOutput.prefetch[operation.prefetchID].data,
35
+ });
36
+ }
37
+ // If this operation has the tool that matches up with the tool that was executed, write the tool result to the cache
38
+ if (operation.tools?.find((tool) => `${this.manifest.name}--${tool.name}` ===
39
+ window.openai.toolResponseMetadata?.toolName)) {
40
+ // We need to include the variables that were used as part of the tool call so that we get a proper cache entry
41
+ // However, we only want to include toolInput's that were graphql operation (ignore extraInputs)
42
+ const variables = Object.keys(window.openai.toolInput).reduce((obj, key) => operation.variables?.[key] ?
43
+ { ...obj, [key]: window.openai.toolInput[key] }
44
+ : obj, {});
45
+ if (window.openai.toolOutput) {
46
+ this.writeQuery({
47
+ query: parse(operation.body),
48
+ data: window.openai.toolOutput.result.data,
49
+ variables,
50
+ });
51
+ }
52
+ }
53
+ });
54
+ }
55
+ }
56
+ function validateTerminatingLink(link) {
57
+ let terminatingLink = link;
58
+ while (terminatingLink.right) {
59
+ terminatingLink = terminatingLink.right;
60
+ }
61
+ if (terminatingLink.constructor.name !== "ToolCallLink") {
62
+ throw new Error("The terminating link must be a `ToolCallLink`. If you are using a `split` link, ensure the `right` branch uses a `ToolCallLink` as the terminating link.");
63
+ }
64
+ }
65
+ //# sourceMappingURL=ApolloClient.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ApolloClient.js","sourceRoot":"","sources":["../../src/core/ApolloClient.ts"],"names":[],"mappings":"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","sourcesContent":["import type { ApolloLink } from \"@apollo/client\";\nimport { ApolloClient as BaseApolloClient } from \"@apollo/client\";\nimport { DocumentTransform } from \"@apollo/client\";\nimport { removeDirectivesFromDocument } from \"@apollo/client/utilities/internal\";\nimport { parse } from \"graphql\";\nimport { __DEV__ } from \"@apollo/client/utilities/environment\";\nimport \"../types/openai.js\";\nimport type { ApplicationManifest } from \"../types/application-manifest.js\";\nimport { ToolCallLink } from \"../link/ToolCallLink.js\";\nimport type { FetchResult } from \"@apollo/client\";\n\n// TODO: In the future if/when we support PQs again, do pqLink.concat(toolCallLink)\n// Commenting this out for now.\n// import { sha256 } from \"crypto-hash\";\n// import { PersistedQueryLink } from \"@apollo/client/link/persisted-queries\";\n// const pqLink = new PersistedQueryLink({\n// sha256: (queryString) => sha256(queryString),\n// });\n\nexport declare namespace ApolloClient {\n // This allows us to extend the options with the \"manifest\" option AND make link optional (it is normally required)\n export interface Options extends Omit<BaseApolloClient.Options, \"link\"> {\n link?: BaseApolloClient.Options[\"link\"];\n manifest: ApplicationManifest;\n }\n}\n\nexport class ApolloClient extends BaseApolloClient {\n manifest: ApplicationManifest;\n\n constructor(options: ApolloClient.Options) {\n const link = options.link ?? new ToolCallLink();\n\n if (__DEV__) {\n validateTerminatingLink(link);\n }\n\n super({\n ...options,\n link,\n // Strip out the prefetch/tool directives so they don't get sent with the operation to the server\n documentTransform: new DocumentTransform((document) => {\n return removeDirectivesFromDocument(\n [{ name: \"prefetch\" }, { name: \"tool\" }],\n document\n )!;\n }),\n });\n\n this.manifest = options.manifest;\n }\n\n async prefetchData() {\n const toolOutput = window.openai.toolOutput as {\n prefetch?: Record<string, FetchResult<any>>;\n } | null;\n\n // Write prefetched data to the cache\n this.manifest.operations.forEach((operation) => {\n if (\n operation.prefetch &&\n operation.prefetchID &&\n toolOutput?.prefetch?.[operation.prefetchID]\n ) {\n this.writeQuery({\n query: parse(operation.body),\n data: toolOutput.prefetch[operation.prefetchID].data,\n });\n }\n\n // If this operation has the tool that matches up with the tool that was executed, write the tool result to the cache\n if (\n operation.tools?.find(\n (tool) =>\n `${this.manifest.name}--${tool.name}` ===\n window.openai.toolResponseMetadata?.toolName\n )\n ) {\n // We need to include the variables that were used as part of the tool call so that we get a proper cache entry\n // However, we only want to include toolInput's that were graphql operation (ignore extraInputs)\n const variables = Object.keys(window.openai.toolInput).reduce(\n (obj, key) =>\n operation.variables?.[key] ?\n { ...obj, [key]: window.openai.toolInput[key] }\n : obj,\n {}\n );\n\n if (window.openai.toolOutput) {\n this.writeQuery({\n query: parse(operation.body),\n data: (window.openai.toolOutput.result as any).data,\n variables,\n });\n }\n }\n });\n }\n}\n\nfunction validateTerminatingLink(link: ApolloLink) {\n let terminatingLink = link;\n\n while (terminatingLink.right) {\n terminatingLink = terminatingLink.right;\n }\n\n if (terminatingLink.constructor.name !== \"ToolCallLink\") {\n throw new Error(\n \"The terminating link must be a `ToolCallLink`. If you are using a `split` link, ensure the `right` branch uses a `ToolCallLink` as the terminating link.\"\n );\n }\n}\n"]}
package/dist/index.d.ts CHANGED
@@ -1,18 +1,19 @@
1
- export type { API, CallTool, DeviceType, DisplayMode, OpenAiGlobals, SafeArea, SafeAreaInsets, Theme, UserAgent, UnknownObject, } from "./types/openai";
2
- export { SET_GLOBALS_EVENT_TYPE, SetGlobalsEvent } from "./types/openai";
3
- export type { ApplicationManifest, ManifestOperation, ManifestTool, ManifestExtraInput, ManifestCsp, } from "./types/application-manifest";
4
- export { ToolUseProvider } from "./react/context/ToolUseContext";
5
- export { useOpenAiGlobal } from "./react/hooks/useOpenAiGlobal";
6
- export { useToolName } from "./react/hooks/useToolName";
7
- export { useToolInput } from "./react/hooks/useToolInput";
8
- export { useSendFollowUpMessage } from "./react/hooks/useSendFollowUpMessage";
9
- export { useRequestDisplayMode } from "./react/hooks/useRequestDisplayMode";
10
- export { useToolEffect } from "./react/hooks/useToolEffect";
11
- export { useOpenExternal } from "./react/hooks/useOpenExternal";
12
- export { useToolOutput } from "./react/hooks/useToolOutput";
13
- export { useToolResponseMetadata } from "./react/hooks/useToolResponseMetadata";
14
- export { useWidgetState } from "./react/hooks/useWidgetState";
1
+ export type { API, CallTool, DeviceType, DisplayMode, OpenAiGlobals, SafeArea, SafeAreaInsets, Theme, UserAgent, UnknownObject, } from "./types/openai.js";
2
+ export { SET_GLOBALS_EVENT_TYPE, SetGlobalsEvent } from "./types/openai.js";
3
+ export type { ApplicationManifest, ManifestOperation, ManifestTool, ManifestExtraInput, ManifestCsp, } from "./types/application-manifest.js";
4
+ export { ToolUseProvider } from "./react/context/ToolUseContext.js";
5
+ export { useOpenAiGlobal } from "./react/hooks/useOpenAiGlobal.js";
6
+ export { useToolName } from "./react/hooks/useToolName.js";
7
+ export { useToolInput } from "./react/hooks/useToolInput.js";
8
+ export { useSendFollowUpMessage } from "./react/hooks/useSendFollowUpMessage.js";
9
+ export { useRequestDisplayMode } from "./react/hooks/useRequestDisplayMode.js";
10
+ export { useToolEffect } from "./react/hooks/useToolEffect.js";
11
+ export { useOpenExternal } from "./react/hooks/useOpenExternal.js";
12
+ export { useToolOutput } from "./react/hooks/useToolOutput.js";
13
+ export { useToolResponseMetadata } from "./react/hooks/useToolResponseMetadata.js";
14
+ export { useWidgetState } from "./react/hooks/useWidgetState.js";
15
15
  export * from "@apollo/client";
16
- export { ApolloClient } from "./core/ApolloClient";
17
- export { ApolloProvider } from "./react/ApolloProvider";
18
- export { ToolCallLink } from "./link/ToolCallLink";
16
+ export { ApolloClient } from "./core/ApolloClient.js";
17
+ export { ApolloProvider } from "./react/ApolloProvider.js";
18
+ export { ToolCallLink } from "./link/ToolCallLink.js";
19
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +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"}
package/dist/index.js CHANGED
@@ -1,279 +1,17 @@
1
- // src/types/openai.ts
2
- var SET_GLOBALS_EVENT_TYPE = "openai:set_globals";
3
- var SetGlobalsEvent = class extends CustomEvent {
4
- type = SET_GLOBALS_EVENT_TYPE;
5
- };
6
-
7
- // src/react/context/ToolUseContext.tsx
8
- import React, { createContext, useContext, useState } from "react";
9
- var ToolUseContext = createContext(null);
10
- function ToolUseProvider({ children, appName }) {
11
- const [hasNavigated, setHasNavigated] = useState(false);
12
- return /* @__PURE__ */ React.createElement(ToolUseContext.Provider, { value: { hasNavigated, setHasNavigated, appName } }, children);
13
- }
14
- function useToolUseState() {
15
- return useContext(ToolUseContext);
16
- }
17
-
18
- // src/react/hooks/useOpenAiGlobal.ts
19
- import { useSyncExternalStore, useCallback } from "react";
20
- function useOpenAiGlobal(key) {
21
- return useSyncExternalStore(
22
- useCallback((onChange) => {
23
- const handleSetGlobal = (event) => {
24
- const value = event.detail.globals[key];
25
- if (value === void 0) {
26
- return;
27
- }
28
- onChange();
29
- };
30
- window.addEventListener(SET_GLOBALS_EVENT_TYPE, handleSetGlobal, {
31
- passive: true
32
- });
33
- return () => {
34
- window.removeEventListener(SET_GLOBALS_EVENT_TYPE, handleSetGlobal);
35
- };
36
- }, []),
37
- () => window.openai[key]
38
- );
39
- }
40
-
41
- // src/react/hooks/useToolName.ts
42
- var useToolName = () => {
43
- const toolResponseMetadata = useOpenAiGlobal("toolResponseMetadata");
44
- return toolResponseMetadata?.toolName;
45
- };
46
-
47
- // src/react/hooks/useToolInput.ts
48
- var useToolInput = () => {
49
- const toolInput = useOpenAiGlobal("toolInput");
50
- return toolInput;
51
- };
52
-
53
- // src/react/hooks/useSendFollowUpMessage.ts
54
- var useSendFollowUpMessage = () => {
55
- return async (prompt) => {
56
- await window.openai?.sendFollowUpMessage({
57
- prompt
58
- });
59
- };
60
- };
61
-
62
- // src/react/hooks/useRequestDisplayMode.ts
63
- var useRequestDisplayMode = () => {
64
- return async (args) => {
65
- return await window.openai?.requestDisplayMode(args);
66
- };
67
- };
68
-
69
- // src/react/hooks/useToolEffect.tsx
70
- import { useEffect } from "react";
71
- var useToolEffect = (toolName, effect, deps = []) => {
72
- const ctx = useToolUseState();
73
- const fullToolName = useToolName();
74
- const toolInput = useToolInput();
75
- if (!ctx)
76
- throw new Error("useToolEffect must be used within ToolUseProvider");
77
- const toolNames = Array.isArray(toolName) ? toolName : [toolName];
78
- useEffect(() => {
79
- const matches = toolNames.some(
80
- (name) => fullToolName === `${ctx.appName}--${name}`
81
- );
82
- if (!ctx.hasNavigated && matches) {
83
- effect(toolInput);
84
- ctx.setHasNavigated(true);
85
- }
86
- }, [
87
- ctx.hasNavigated,
88
- ctx.setHasNavigated,
89
- ctx.appName,
90
- toolNames,
91
- fullToolName,
92
- toolInput,
93
- ...deps
94
- ]);
95
- };
96
-
97
- // src/react/hooks/useOpenExternal.ts
98
- import { useCallback as useCallback2 } from "react";
99
- function useOpenExternal() {
100
- return useCallback2(
101
- (...args) => window.openai.openExternal(...args),
102
- []
103
- );
104
- }
105
-
106
- // src/react/hooks/useToolOutput.ts
107
- function useToolOutput() {
108
- return useOpenAiGlobal("toolOutput") ?? null;
109
- }
110
-
111
- // src/react/hooks/useToolResponseMetadata.ts
112
- function useToolResponseMetadata() {
113
- return useOpenAiGlobal("toolResponseMetadata") ?? null;
114
- }
115
-
116
- // src/react/hooks/useWidgetState.ts
117
- import { useCallback as useCallback3, useState as useState2 } from "react";
118
- function useWidgetState(defaultState) {
119
- const widgetStateFromWindow = useOpenAiGlobal("widgetState");
120
- const [previousWidgetStateFromWindow, setPreviousWidgetStateFromWindow] = useState2(widgetStateFromWindow);
121
- let [widgetState, _setWidgetState] = useState2(() => {
122
- if (widgetStateFromWindow != null) {
123
- return widgetStateFromWindow;
124
- }
125
- return typeof defaultState === "function" ? defaultState() : defaultState ?? null;
126
- });
127
- if (previousWidgetStateFromWindow !== widgetStateFromWindow) {
128
- _setWidgetState(widgetState = widgetStateFromWindow);
129
- setPreviousWidgetStateFromWindow(widgetStateFromWindow);
130
- }
131
- const setWidgetState = useCallback3((state) => {
132
- _setWidgetState((prevState) => {
133
- const newState = typeof state === "function" ? state(prevState) : state;
134
- if (newState != null && typeof window !== "undefined") {
135
- void window.openai?.setWidgetState?.(newState);
136
- }
137
- return newState;
138
- });
139
- }, []);
140
- return [widgetState, setWidgetState];
141
- }
142
-
143
- // src/index.ts
1
+ export { SET_GLOBALS_EVENT_TYPE, SetGlobalsEvent } from "./types/openai.js";
2
+ export { ToolUseProvider } from "./react/context/ToolUseContext.js";
3
+ export { useOpenAiGlobal } from "./react/hooks/useOpenAiGlobal.js";
4
+ export { useToolName } from "./react/hooks/useToolName.js";
5
+ export { useToolInput } from "./react/hooks/useToolInput.js";
6
+ export { useSendFollowUpMessage } from "./react/hooks/useSendFollowUpMessage.js";
7
+ export { useRequestDisplayMode } from "./react/hooks/useRequestDisplayMode.js";
8
+ export { useToolEffect } from "./react/hooks/useToolEffect.js";
9
+ export { useOpenExternal } from "./react/hooks/useOpenExternal.js";
10
+ export { useToolOutput } from "./react/hooks/useToolOutput.js";
11
+ export { useToolResponseMetadata } from "./react/hooks/useToolResponseMetadata.js";
12
+ export { useWidgetState } from "./react/hooks/useWidgetState.js";
144
13
  export * from "@apollo/client";
145
-
146
- // src/core/ApolloClient.ts
147
- import { ApolloClient as BaseApolloClient } from "@apollo/client";
148
- import { DocumentTransform } from "@apollo/client";
149
- import { removeDirectivesFromDocument } from "@apollo/client/utilities/internal";
150
- import { parse } from "graphql";
151
- import { __DEV__ } from "@apollo/client/utilities/environment";
152
-
153
- // src/link/ToolCallLink.ts
154
- import { ApolloLink } from "@apollo/client";
155
- import { from, map } from "rxjs";
156
- import {
157
- fallbackHttpConfig,
158
- selectHttpOptionsAndBody
159
- } from "@apollo/client/link/http";
160
- var ToolCallLink = class extends ApolloLink {
161
- request(operation) {
162
- const context = operation.getContext();
163
- const contextConfig = {
164
- http: context.http,
165
- options: context.fetchOptions,
166
- credentials: context.credentials,
167
- headers: context.headers
168
- };
169
- const { query, variables } = selectHttpOptionsAndBody(
170
- operation,
171
- fallbackHttpConfig,
172
- contextConfig
173
- ).body;
174
- return from(window.openai.callTool("execute", { query, variables })).pipe(
175
- map((result) => ({ data: result.structuredContent.data }))
176
- );
177
- }
178
- };
179
-
180
- // src/core/ApolloClient.ts
181
- var ApolloClient = class extends BaseApolloClient {
182
- manifest;
183
- constructor(options) {
184
- const link = options.link ?? new ToolCallLink();
185
- if (__DEV__) {
186
- validateTerminatingLink(link);
187
- }
188
- super({
189
- ...options,
190
- link,
191
- // Strip out the prefetch/tool directives so they don't get sent with the operation to the server
192
- documentTransform: new DocumentTransform((document) => {
193
- return removeDirectivesFromDocument(
194
- [{ name: "prefetch" }, { name: "tool" }],
195
- document
196
- );
197
- })
198
- });
199
- this.manifest = options.manifest;
200
- }
201
- async prefetchData() {
202
- this.manifest.operations.forEach((operation) => {
203
- if (operation.prefetch && operation.prefetchID && window.openai.toolOutput?.prefetch?.[operation.prefetchID]) {
204
- this.writeQuery({
205
- query: parse(operation.body),
206
- data: window.openai.toolOutput.prefetch[operation.prefetchID].data
207
- });
208
- }
209
- if (operation.tools?.find(
210
- (tool) => `${this.manifest.name}--${tool.name}` === window.openai.toolResponseMetadata?.toolName
211
- )) {
212
- const variables = Object.keys(window.openai.toolInput).reduce(
213
- (obj, key) => operation.variables?.[key] ? { ...obj, [key]: window.openai.toolInput[key] } : obj,
214
- {}
215
- );
216
- if (window.openai.toolOutput) {
217
- this.writeQuery({
218
- query: parse(operation.body),
219
- data: window.openai.toolOutput.result.data,
220
- variables
221
- });
222
- }
223
- }
224
- });
225
- }
226
- };
227
- function validateTerminatingLink(link) {
228
- let terminatingLink = link;
229
- while (terminatingLink.right) {
230
- terminatingLink = terminatingLink.right;
231
- }
232
- if (terminatingLink.constructor.name !== "ToolCallLink") {
233
- throw new Error(
234
- "The terminating link must be a `ToolCallLink`. If you are using a `split` link, ensure the `right` branch uses a `ToolCallLink` as the terminating link."
235
- );
236
- }
237
- }
238
-
239
- // src/react/ApolloProvider.tsx
240
- import React3, { useEffect as useEffect2, useState as useState3 } from "react";
241
- import { ApolloProvider as BaseApolloProvider } from "@apollo/client/react";
242
- var ApolloProvider = ({ children, client }) => {
243
- const [hasPreloaded, setHasPreloaded] = useState3(false);
244
- useEffect2(() => {
245
- const prefetchData = async () => {
246
- await client.prefetchData();
247
- setHasPreloaded(true);
248
- window.removeEventListener(SET_GLOBALS_EVENT_TYPE, prefetchData);
249
- };
250
- window.addEventListener(SET_GLOBALS_EVENT_TYPE, prefetchData, {
251
- passive: true
252
- });
253
- if (window.openai?.toolOutput) {
254
- window.dispatchEvent(new CustomEvent(SET_GLOBALS_EVENT_TYPE));
255
- }
256
- return () => {
257
- window.removeEventListener(SET_GLOBALS_EVENT_TYPE, prefetchData);
258
- };
259
- }, []);
260
- return hasPreloaded ? /* @__PURE__ */ React3.createElement(BaseApolloProvider, { client }, children) : null;
261
- };
262
- export {
263
- ApolloClient,
264
- ApolloProvider,
265
- SET_GLOBALS_EVENT_TYPE,
266
- SetGlobalsEvent,
267
- ToolCallLink,
268
- ToolUseProvider,
269
- useOpenAiGlobal,
270
- useOpenExternal,
271
- useRequestDisplayMode,
272
- useSendFollowUpMessage,
273
- useToolEffect,
274
- useToolInput,
275
- useToolName,
276
- useToolOutput,
277
- useToolResponseMetadata,
278
- useWidgetState
279
- };
14
+ export { ApolloClient } from "./core/ApolloClient.js";
15
+ export { ApolloProvider } from "./react/ApolloProvider.js";
16
+ export { ToolCallLink } from "./link/ToolCallLink.js";
17
+ //# sourceMappingURL=index.js.map