@apollo/client-ai-apps 0.3.0 → 0.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.github/workflows/compare-build-output.yml +28 -0
- package/config/compare-build-output-to.sh +90 -0
- package/dist/core/ApolloClient.d.ts +14 -0
- package/dist/index.d.ts +17 -11
- package/dist/index.js +96 -44
- package/dist/react/ApolloProvider.d.ts +9 -0
- package/dist/react/context/ToolUseContext.d.ts +15 -0
- package/dist/{hooks → react/hooks}/useOpenAiGlobal.d.ts +1 -1
- package/dist/react/hooks/useOpenExternal.d.ts +3 -0
- package/dist/{hooks → react/hooks}/useRequestDisplayMode.d.ts +1 -1
- package/dist/{hooks → react/hooks}/useToolEffect.d.ts +0 -4
- package/dist/react/hooks/useToolOutput.d.ts +1 -0
- package/dist/react/hooks/useToolResponseMetadata.d.ts +1 -0
- package/dist/react/hooks/useWidgetState.d.ts +4 -0
- package/dist/types/openai.d.ts +1 -2
- package/package.json +5 -1
- package/src/{apollo_client/client.ts → core/ApolloClient.ts} +21 -17
- package/src/{apollo_client/client.test.ts → core/__tests__/ApolloClient.test.ts} +8 -9
- package/src/index.ts +36 -11
- package/src/{apollo_client/provider.tsx → react/ApolloProvider.tsx} +12 -8
- package/src/{apollo_client/provider.test.tsx → react/__tests__/ApolloProvider.test.tsx} +9 -9
- package/src/react/context/ToolUseContext.tsx +30 -0
- package/src/{hooks → react/hooks/__tests__}/useCallTool.test.ts +1 -1
- package/src/{hooks → react/hooks/__tests__}/useOpenAiGlobal.test.ts +2 -2
- package/src/react/hooks/__tests__/useOpenExternal.test.tsx +24 -0
- package/src/{hooks → react/hooks/__tests__}/useRequestDisplayMode.test.ts +2 -2
- package/src/{hooks → react/hooks/__tests__}/useSendFollowUpMessage.test.ts +1 -1
- package/src/{hooks → react/hooks/__tests__}/useToolEffect.test.tsx +2 -1
- package/src/{hooks → react/hooks/__tests__}/useToolInput.test.ts +1 -1
- package/src/{hooks → react/hooks/__tests__}/useToolName.test.ts +1 -1
- package/src/react/hooks/__tests__/useToolOutput.test.tsx +49 -0
- package/src/react/hooks/__tests__/useToolResponseMetadata.test.tsx +49 -0
- package/src/react/hooks/__tests__/useWidgetState.test.tsx +158 -0
- package/src/{hooks → react/hooks}/useOpenAiGlobal.ts +4 -4
- package/src/react/hooks/useOpenExternal.ts +11 -0
- package/src/{hooks → react/hooks}/useRequestDisplayMode.ts +1 -1
- package/src/{hooks → react/hooks}/useToolEffect.tsx +3 -26
- package/src/{hooks → react/hooks}/useToolName.ts +1 -1
- package/src/react/hooks/useToolOutput.ts +5 -0
- package/src/react/hooks/useToolResponseMetadata.ts +5 -0
- package/src/react/hooks/useWidgetState.ts +48 -0
- package/src/testing/internal/index.ts +2 -0
- package/src/testing/internal/matchers/index.d.ts +9 -0
- package/src/testing/internal/matchers/index.ts +1 -0
- package/src/testing/internal/matchers/toRerender.ts +49 -0
- package/src/testing/internal/openai/dispatchStateChange.ts +9 -0
- package/src/testing/internal/openai/stubOpenAiGlobals.ts +13 -0
- package/src/types/openai.ts +1 -1
- package/src/vite/{absolute_asset_imports_plugin.test.ts → __tests__/absolute_asset_imports_plugin.test.ts} +1 -1
- package/src/vite/{application_manifest_plugin.test.ts → __tests__/application_manifest_plugin.test.ts} +7 -7
- package/vitest-setup.ts +1 -0
- package/dist/apollo_client/client.d.ts +0 -13
- package/dist/apollo_client/provider.d.ts +0 -5
- /package/dist/{apollo_client/link → link}/ToolCallLink.d.ts +0 -0
- /package/dist/{hooks → react/hooks}/useSendFollowUpMessage.d.ts +0 -0
- /package/dist/{hooks → react/hooks}/useToolInput.d.ts +0 -0
- /package/dist/{hooks → react/hooks}/useToolName.d.ts +0 -0
- /package/src/{apollo_client/link → link}/ToolCallLink.ts +0 -0
- /package/src/{hooks → react/hooks}/useCallTool.ts +0 -0
- /package/src/{hooks → react/hooks}/useSendFollowUpMessage.ts +0 -0
- /package/src/{hooks → react/hooks}/useToolInput.ts +0 -0
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
name: Compare Build Output
|
|
2
|
+
on:
|
|
3
|
+
pull_request:
|
|
4
|
+
|
|
5
|
+
concurrency: ${{ github.workflow }}-${{ github.ref }}
|
|
6
|
+
|
|
7
|
+
jobs:
|
|
8
|
+
comparebuildoutput:
|
|
9
|
+
name: Compare Build Output
|
|
10
|
+
runs-on: ubuntu-latest
|
|
11
|
+
steps:
|
|
12
|
+
- name: Checkout repo
|
|
13
|
+
uses: actions/checkout@v5
|
|
14
|
+
with:
|
|
15
|
+
# Fetch entire git history so we have the parent commit to compare against
|
|
16
|
+
fetch-depth: 0
|
|
17
|
+
- name: Setup Node.js
|
|
18
|
+
uses: actions/setup-node@v6
|
|
19
|
+
with:
|
|
20
|
+
node-version: ">=23.6.0"
|
|
21
|
+
- name: Install dependencies (with cache)
|
|
22
|
+
uses: bahmutov/npm-install@v1
|
|
23
|
+
|
|
24
|
+
- name: Run comparison script
|
|
25
|
+
id: attw
|
|
26
|
+
run: ./config/compare-build-output-to.sh $(git merge-base HEAD origin/${{ github.base_ref }}) | tee $GITHUB_STEP_SUMMARY
|
|
27
|
+
env:
|
|
28
|
+
RUNNER_TEMP: ${{ runner.temp }}
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
set -euo pipefail
|
|
3
|
+
upstream=$1
|
|
4
|
+
comparison="${RUNNER_TEMP:-/tmp}/comparison_checkout"
|
|
5
|
+
root=$(git rev-parse --show-toplevel)
|
|
6
|
+
|
|
7
|
+
temp=$(mktemp --tmpdir="${RUNNER_TEMP:-/tmp}")
|
|
8
|
+
trap 'rm -f "$temp"' EXIT
|
|
9
|
+
|
|
10
|
+
patterndiff(){
|
|
11
|
+
cd dist || { echo "dist folder not found"; exit 1; }
|
|
12
|
+
count=0
|
|
13
|
+
while IFS= read -r -d '' file
|
|
14
|
+
do
|
|
15
|
+
if ! filediff="$(diff <(tr "'" '"' < "$comparison/dist/$file") <(tr "'" '"' < "$root/dist/$file"))"; then
|
|
16
|
+
(( count++ ))
|
|
17
|
+
echo "$file"
|
|
18
|
+
if [[ "$file" == *.min.* ]]; then
|
|
19
|
+
echo "> Minified file differs."
|
|
20
|
+
else
|
|
21
|
+
echo "$filediff"
|
|
22
|
+
fi
|
|
23
|
+
fi
|
|
24
|
+
done >"$temp" < <(find . -name "$1" -print0)
|
|
25
|
+
|
|
26
|
+
output="$(cat <"$temp")"
|
|
27
|
+
|
|
28
|
+
cat <<EOF
|
|
29
|
+
|
|
30
|
+
## differences in $1 files
|
|
31
|
+
|
|
32
|
+
<details>
|
|
33
|
+
<summary>
|
|
34
|
+
|
|
35
|
+
### $count files with differences
|
|
36
|
+
|
|
37
|
+
</summary>
|
|
38
|
+
|
|
39
|
+
\`\`\`diff
|
|
40
|
+
|
|
41
|
+
$output
|
|
42
|
+
|
|
43
|
+
\`\`\`
|
|
44
|
+
|
|
45
|
+
</details>
|
|
46
|
+
EOF
|
|
47
|
+
|
|
48
|
+
cd ..
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
[ -z "$upstream" ] && { echo "need upstream argument"; exit 1; }
|
|
52
|
+
|
|
53
|
+
git worktree add --force --detach --checkout "$comparison" "$upstream" || { cd "$comparison" && git checkout "$upstream"; } || exit 1
|
|
54
|
+
|
|
55
|
+
cd "$comparison" || { echo "checkout failed"; exit 1; }
|
|
56
|
+
[ -d node_modules ] || cp -r "$root/node_modules" .
|
|
57
|
+
npm i >&2
|
|
58
|
+
git status >&2
|
|
59
|
+
npm run build >&2
|
|
60
|
+
cd "$root" || exit 1
|
|
61
|
+
git status >&2
|
|
62
|
+
npm run build >&2
|
|
63
|
+
|
|
64
|
+
set +e
|
|
65
|
+
|
|
66
|
+
patterndiff "*.js"
|
|
67
|
+
patterndiff "*.cjs"
|
|
68
|
+
patterndiff "*.d.ts"
|
|
69
|
+
patterndiff "*.d.cts"
|
|
70
|
+
|
|
71
|
+
cat <<EOF
|
|
72
|
+
|
|
73
|
+
## differences in other files
|
|
74
|
+
|
|
75
|
+
<details>
|
|
76
|
+
<summary>
|
|
77
|
+
|
|
78
|
+
### $(diff -qr "$comparison/dist" "dist" -x "*.map" -x "*.native.*" -x "*.js" -x "*.cjs" -x "*.d.ts" -x "*.d.cts" -w | wc -l) files with differences
|
|
79
|
+
|
|
80
|
+
</summary>
|
|
81
|
+
|
|
82
|
+
\`\`\`diff
|
|
83
|
+
|
|
84
|
+
$(diff -r "$comparison/dist" "dist" -x "*.map" -x "*.native.*" -x "*.js" -x "*.cjs" -x "*.d.ts" -x "*.d.cts" -w)
|
|
85
|
+
|
|
86
|
+
\`\`\`
|
|
87
|
+
|
|
88
|
+
</details>
|
|
89
|
+
EOF
|
|
90
|
+
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { ApolloClient as BaseApolloClient } from "@apollo/client";
|
|
2
|
+
import "../types/openai";
|
|
3
|
+
import { ApplicationManifest } from "../types/application-manifest";
|
|
4
|
+
export declare namespace ApolloClient {
|
|
5
|
+
interface Options extends Omit<BaseApolloClient.Options, "link"> {
|
|
6
|
+
link?: BaseApolloClient.Options["link"];
|
|
7
|
+
manifest: ApplicationManifest;
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
export declare class ApolloClient extends BaseApolloClient {
|
|
11
|
+
manifest: ApplicationManifest;
|
|
12
|
+
constructor(options: ApolloClient.Options);
|
|
13
|
+
prefetchData(): Promise<void>;
|
|
14
|
+
}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,12 +1,18 @@
|
|
|
1
|
-
export
|
|
2
|
-
export
|
|
3
|
-
export
|
|
4
|
-
export
|
|
5
|
-
export
|
|
6
|
-
export
|
|
7
|
-
export
|
|
8
|
-
export
|
|
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";
|
|
9
15
|
export * from "@apollo/client";
|
|
10
|
-
export {
|
|
11
|
-
export {
|
|
12
|
-
export { ToolCallLink } from "./
|
|
16
|
+
export { ApolloClient } from "./core/ApolloClient";
|
|
17
|
+
export { ApolloProvider } from "./react/ApolloProvider";
|
|
18
|
+
export { ToolCallLink } from "./link/ToolCallLink";
|
package/dist/index.js
CHANGED
|
@@ -4,11 +4,22 @@ var SetGlobalsEvent = class extends CustomEvent {
|
|
|
4
4
|
type = SET_GLOBALS_EVENT_TYPE;
|
|
5
5
|
};
|
|
6
6
|
|
|
7
|
-
// src/
|
|
8
|
-
import {
|
|
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";
|
|
9
20
|
function useOpenAiGlobal(key) {
|
|
10
21
|
return useSyncExternalStore(
|
|
11
|
-
(onChange) => {
|
|
22
|
+
useCallback((onChange) => {
|
|
12
23
|
const handleSetGlobal = (event) => {
|
|
13
24
|
const value = event.detail.globals[key];
|
|
14
25
|
if (value === void 0) {
|
|
@@ -22,24 +33,24 @@ function useOpenAiGlobal(key) {
|
|
|
22
33
|
return () => {
|
|
23
34
|
window.removeEventListener(SET_GLOBALS_EVENT_TYPE, handleSetGlobal);
|
|
24
35
|
};
|
|
25
|
-
},
|
|
36
|
+
}, []),
|
|
26
37
|
() => window.openai[key]
|
|
27
38
|
);
|
|
28
39
|
}
|
|
29
40
|
|
|
30
|
-
// src/hooks/useToolName.ts
|
|
41
|
+
// src/react/hooks/useToolName.ts
|
|
31
42
|
var useToolName = () => {
|
|
32
43
|
const toolResponseMetadata = useOpenAiGlobal("toolResponseMetadata");
|
|
33
44
|
return toolResponseMetadata?.toolName;
|
|
34
45
|
};
|
|
35
46
|
|
|
36
|
-
// src/hooks/useToolInput.ts
|
|
47
|
+
// src/react/hooks/useToolInput.ts
|
|
37
48
|
var useToolInput = () => {
|
|
38
49
|
const toolInput = useOpenAiGlobal("toolInput");
|
|
39
50
|
return toolInput;
|
|
40
51
|
};
|
|
41
52
|
|
|
42
|
-
// src/hooks/useSendFollowUpMessage.ts
|
|
53
|
+
// src/react/hooks/useSendFollowUpMessage.ts
|
|
43
54
|
var useSendFollowUpMessage = () => {
|
|
44
55
|
return async (prompt) => {
|
|
45
56
|
await window.openai?.sendFollowUpMessage({
|
|
@@ -48,25 +59,17 @@ var useSendFollowUpMessage = () => {
|
|
|
48
59
|
};
|
|
49
60
|
};
|
|
50
61
|
|
|
51
|
-
// src/hooks/useRequestDisplayMode.ts
|
|
62
|
+
// src/react/hooks/useRequestDisplayMode.ts
|
|
52
63
|
var useRequestDisplayMode = () => {
|
|
53
64
|
return async (args) => {
|
|
54
65
|
return await window.openai?.requestDisplayMode(args);
|
|
55
66
|
};
|
|
56
67
|
};
|
|
57
68
|
|
|
58
|
-
// src/hooks/useToolEffect.tsx
|
|
59
|
-
import
|
|
60
|
-
var ToolUseContext = React.createContext(null);
|
|
61
|
-
function ToolUseProvider({
|
|
62
|
-
children,
|
|
63
|
-
appName
|
|
64
|
-
}) {
|
|
65
|
-
const [hasNavigated, setHasNavigated] = useState(false);
|
|
66
|
-
return /* @__PURE__ */ React.createElement(ToolUseContext.Provider, { value: { hasNavigated, setHasNavigated, appName } }, children);
|
|
67
|
-
}
|
|
69
|
+
// src/react/hooks/useToolEffect.tsx
|
|
70
|
+
import { useEffect } from "react";
|
|
68
71
|
var useToolEffect = (toolName, effect, deps = []) => {
|
|
69
|
-
const ctx =
|
|
72
|
+
const ctx = useToolUseState();
|
|
70
73
|
const fullToolName = useToolName();
|
|
71
74
|
const toolInput = useToolInput();
|
|
72
75
|
if (!ctx)
|
|
@@ -91,17 +94,63 @@ var useToolEffect = (toolName, effect, deps = []) => {
|
|
|
91
94
|
]);
|
|
92
95
|
};
|
|
93
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
|
+
|
|
94
143
|
// src/index.ts
|
|
95
144
|
export * from "@apollo/client";
|
|
96
145
|
|
|
97
|
-
// src/
|
|
98
|
-
import { ApolloClient } from "@apollo/client";
|
|
146
|
+
// src/core/ApolloClient.ts
|
|
147
|
+
import { ApolloClient as BaseApolloClient } from "@apollo/client";
|
|
99
148
|
import { DocumentTransform } from "@apollo/client";
|
|
100
149
|
import { removeDirectivesFromDocument } from "@apollo/client/utilities/internal";
|
|
101
150
|
import { parse } from "graphql";
|
|
102
151
|
import { __DEV__ } from "@apollo/client/utilities/environment";
|
|
103
152
|
|
|
104
|
-
// src/
|
|
153
|
+
// src/link/ToolCallLink.ts
|
|
105
154
|
import { ApolloLink } from "@apollo/client";
|
|
106
155
|
import { from, map } from "rxjs";
|
|
107
156
|
import {
|
|
@@ -128,8 +177,8 @@ var ToolCallLink = class extends ApolloLink {
|
|
|
128
177
|
}
|
|
129
178
|
};
|
|
130
179
|
|
|
131
|
-
// src/
|
|
132
|
-
var
|
|
180
|
+
// src/core/ApolloClient.ts
|
|
181
|
+
var ApolloClient = class extends BaseApolloClient {
|
|
133
182
|
manifest;
|
|
134
183
|
constructor(options) {
|
|
135
184
|
const link = options.link ?? new ToolCallLink();
|
|
@@ -151,24 +200,26 @@ var ExtendedApolloClient = class extends ApolloClient {
|
|
|
151
200
|
}
|
|
152
201
|
async prefetchData() {
|
|
153
202
|
this.manifest.operations.forEach((operation) => {
|
|
154
|
-
if (operation.prefetch && operation.prefetchID && window.openai.toolOutput
|
|
203
|
+
if (operation.prefetch && operation.prefetchID && window.openai.toolOutput?.prefetch?.[operation.prefetchID]) {
|
|
155
204
|
this.writeQuery({
|
|
156
205
|
query: parse(operation.body),
|
|
157
206
|
data: window.openai.toolOutput.prefetch[operation.prefetchID].data
|
|
158
207
|
});
|
|
159
208
|
}
|
|
160
209
|
if (operation.tools?.find(
|
|
161
|
-
(tool) => `${this.manifest.name}--${tool.name}` === window.openai.toolResponseMetadata
|
|
210
|
+
(tool) => `${this.manifest.name}--${tool.name}` === window.openai.toolResponseMetadata?.toolName
|
|
162
211
|
)) {
|
|
163
212
|
const variables = Object.keys(window.openai.toolInput).reduce(
|
|
164
|
-
(obj, key) => operation.variables[key] ? { ...obj, [key]: window.openai.toolInput[key] } : obj,
|
|
213
|
+
(obj, key) => operation.variables?.[key] ? { ...obj, [key]: window.openai.toolInput[key] } : obj,
|
|
165
214
|
{}
|
|
166
215
|
);
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
216
|
+
if (window.openai.toolOutput) {
|
|
217
|
+
this.writeQuery({
|
|
218
|
+
query: parse(operation.body),
|
|
219
|
+
data: window.openai.toolOutput.result.data,
|
|
220
|
+
variables
|
|
221
|
+
});
|
|
222
|
+
}
|
|
172
223
|
}
|
|
173
224
|
});
|
|
174
225
|
}
|
|
@@ -185,14 +236,11 @@ function validateTerminatingLink(link) {
|
|
|
185
236
|
}
|
|
186
237
|
}
|
|
187
238
|
|
|
188
|
-
// src/
|
|
189
|
-
import
|
|
190
|
-
import { ApolloProvider } from "@apollo/client/react";
|
|
191
|
-
var
|
|
192
|
-
|
|
193
|
-
client
|
|
194
|
-
}) => {
|
|
195
|
-
const [hasPreloaded, setHasPreloaded] = useState2(false);
|
|
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);
|
|
196
244
|
useEffect2(() => {
|
|
197
245
|
const prefetchData = async () => {
|
|
198
246
|
await client.prefetchData();
|
|
@@ -209,19 +257,23 @@ var ExtendedApolloProvider = ({
|
|
|
209
257
|
window.removeEventListener(SET_GLOBALS_EVENT_TYPE, prefetchData);
|
|
210
258
|
};
|
|
211
259
|
}, []);
|
|
212
|
-
return hasPreloaded ? /* @__PURE__ */
|
|
260
|
+
return hasPreloaded ? /* @__PURE__ */ React3.createElement(BaseApolloProvider, { client }, children) : null;
|
|
213
261
|
};
|
|
214
262
|
export {
|
|
215
|
-
|
|
216
|
-
|
|
263
|
+
ApolloClient,
|
|
264
|
+
ApolloProvider,
|
|
217
265
|
SET_GLOBALS_EVENT_TYPE,
|
|
218
266
|
SetGlobalsEvent,
|
|
219
267
|
ToolCallLink,
|
|
220
268
|
ToolUseProvider,
|
|
221
269
|
useOpenAiGlobal,
|
|
270
|
+
useOpenExternal,
|
|
222
271
|
useRequestDisplayMode,
|
|
223
272
|
useSendFollowUpMessage,
|
|
224
273
|
useToolEffect,
|
|
225
274
|
useToolInput,
|
|
226
|
-
useToolName
|
|
275
|
+
useToolName,
|
|
276
|
+
useToolOutput,
|
|
277
|
+
useToolResponseMetadata,
|
|
278
|
+
useWidgetState
|
|
227
279
|
};
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import React, { ReactNode } from "react";
|
|
2
|
+
import { ApolloClient } from "../core/ApolloClient";
|
|
3
|
+
export declare namespace ApolloProvider {
|
|
4
|
+
interface Props {
|
|
5
|
+
children?: ReactNode;
|
|
6
|
+
client: ApolloClient;
|
|
7
|
+
}
|
|
8
|
+
}
|
|
9
|
+
export declare const ApolloProvider: ({ children, client }: ApolloProvider.Props) => React.JSX.Element;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import React, { ReactNode } from "react";
|
|
2
|
+
interface ToolUseState {
|
|
3
|
+
appName: string;
|
|
4
|
+
hasNavigated: boolean;
|
|
5
|
+
setHasNavigated: (v: boolean) => void;
|
|
6
|
+
}
|
|
7
|
+
export declare namespace ToolUseProvider {
|
|
8
|
+
interface Props {
|
|
9
|
+
children?: ReactNode;
|
|
10
|
+
appName: string;
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
export declare function ToolUseProvider({ children, appName }: ToolUseProvider.Props): React.JSX.Element;
|
|
14
|
+
export declare function useToolUseState(): ToolUseState;
|
|
15
|
+
export {};
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { OpenAiGlobals } from "
|
|
1
|
+
import { OpenAiGlobals } from "../../types/openai";
|
|
2
2
|
export declare function useOpenAiGlobal<K extends keyof OpenAiGlobals>(key: K): OpenAiGlobals[K];
|
|
@@ -1,6 +1,2 @@
|
|
|
1
1
|
import React from "react";
|
|
2
|
-
export declare function ToolUseProvider({ children, appName, }: {
|
|
3
|
-
children: any;
|
|
4
|
-
appName: string;
|
|
5
|
-
}): React.JSX.Element;
|
|
6
2
|
export declare const useToolEffect: (toolName: string | string[], effect: (toolInput: any) => void, deps?: React.DependencyList) => void;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function useToolOutput(): import("../..").UnknownObject;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function useToolResponseMetadata(): import("../..").UnknownObject;
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import { SetStateAction } from "react";
|
|
2
|
+
import { UnknownObject } from "../../types/openai";
|
|
3
|
+
export declare function useWidgetState<T extends UnknownObject>(defaultState: T | (() => T)): readonly [T, (state: SetStateAction<T>) => void];
|
|
4
|
+
export declare function useWidgetState<T extends UnknownObject>(defaultState?: T | (() => T | null) | null): readonly [T | null, (state: SetStateAction<T | null>) => void];
|
package/dist/types/openai.d.ts
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@apollo/client-ai-apps",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.1",
|
|
4
4
|
"publishConfig": {
|
|
5
5
|
"access": "public"
|
|
6
6
|
},
|
|
@@ -17,9 +17,11 @@
|
|
|
17
17
|
},
|
|
18
18
|
"scripts": {
|
|
19
19
|
"dev": "node ./scripts/dev.mjs",
|
|
20
|
+
"prebuild": "npm run clean",
|
|
20
21
|
"build": "npm run build:react && npm run build:vite",
|
|
21
22
|
"build:react": "node ./scripts/build.mjs && tsc src/index.ts --emitDeclarationOnly --declaration --outDir dist --skipLibCheck --lib ES2015,DOM --target ES2015 --moduleResolution bundler --jsx react",
|
|
22
23
|
"build:vite": "node ./scripts/build-vite.mjs && tsc src/vite/index.ts --emitDeclarationOnly --declaration --outDir dist/vite --skipLibCheck --lib ES2015,DOM --target ES2020 --module esnext --moduleResolution node --allowSyntheticDefaultImports",
|
|
24
|
+
"clean": "rimraf dist",
|
|
23
25
|
"test": "vitest run --coverage",
|
|
24
26
|
"test:watch": "vitest --coverage",
|
|
25
27
|
"changeset": "knope document-change",
|
|
@@ -33,6 +35,7 @@
|
|
|
33
35
|
"devDependencies": {
|
|
34
36
|
"@testing-library/jest-dom": "^6.9.1",
|
|
35
37
|
"@testing-library/react": "^16.3.0",
|
|
38
|
+
"@testing-library/react-render-stream": "^2.0.2",
|
|
36
39
|
"@types/node": "^24.10.0",
|
|
37
40
|
"@types/react": "^19.2.2",
|
|
38
41
|
"@vitejs/plugin-react": "^5.1.1",
|
|
@@ -41,6 +44,7 @@
|
|
|
41
44
|
"graphql": "^16.9.0",
|
|
42
45
|
"happy-dom": "^20.0.10",
|
|
43
46
|
"prettier": "^3.7.4",
|
|
47
|
+
"rimraf": "^6.1.2",
|
|
44
48
|
"rxjs": "^7.8.1",
|
|
45
49
|
"typescript": "^5.9.3",
|
|
46
50
|
"vitest": "^4.0.13"
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import type { ApolloLink } from "@apollo/client";
|
|
2
|
-
import { ApolloClient } from "@apollo/client";
|
|
2
|
+
import { ApolloClient as BaseApolloClient } from "@apollo/client";
|
|
3
3
|
import { DocumentTransform } from "@apollo/client";
|
|
4
4
|
import { removeDirectivesFromDocument } from "@apollo/client/utilities/internal";
|
|
5
5
|
import { parse } from "graphql";
|
|
6
6
|
import { __DEV__ } from "@apollo/client/utilities/environment";
|
|
7
7
|
import "../types/openai";
|
|
8
8
|
import { ApplicationManifest } from "../types/application-manifest";
|
|
9
|
-
import { ToolCallLink } from "
|
|
9
|
+
import { ToolCallLink } from "../link/ToolCallLink";
|
|
10
10
|
|
|
11
11
|
// TODO: In the future if/when we support PQs again, do pqLink.concat(toolCallLink)
|
|
12
12
|
// Commenting this out for now.
|
|
@@ -16,16 +16,18 @@ import { ToolCallLink } from "./link/ToolCallLink";
|
|
|
16
16
|
// sha256: (queryString) => sha256(queryString),
|
|
17
17
|
// });
|
|
18
18
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
19
|
+
export declare namespace ApolloClient {
|
|
20
|
+
// This allows us to extend the options with the "manifest" option AND make link optional (it is normally required)
|
|
21
|
+
export interface Options extends Omit<BaseApolloClient.Options, "link"> {
|
|
22
|
+
link?: BaseApolloClient.Options["link"];
|
|
23
|
+
manifest: ApplicationManifest;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
24
26
|
|
|
25
|
-
export class
|
|
27
|
+
export class ApolloClient extends BaseApolloClient {
|
|
26
28
|
manifest: ApplicationManifest;
|
|
27
29
|
|
|
28
|
-
constructor(options:
|
|
30
|
+
constructor(options: ApolloClient.Options) {
|
|
29
31
|
const link = options.link ?? new ToolCallLink();
|
|
30
32
|
|
|
31
33
|
if (__DEV__) {
|
|
@@ -53,7 +55,7 @@ export class ExtendedApolloClient extends ApolloClient {
|
|
|
53
55
|
if (
|
|
54
56
|
operation.prefetch &&
|
|
55
57
|
operation.prefetchID &&
|
|
56
|
-
window.openai.toolOutput
|
|
58
|
+
window.openai.toolOutput?.prefetch?.[operation.prefetchID]
|
|
57
59
|
) {
|
|
58
60
|
this.writeQuery({
|
|
59
61
|
query: parse(operation.body),
|
|
@@ -66,24 +68,26 @@ export class ExtendedApolloClient extends ApolloClient {
|
|
|
66
68
|
operation.tools?.find(
|
|
67
69
|
(tool) =>
|
|
68
70
|
`${this.manifest.name}--${tool.name}` ===
|
|
69
|
-
window.openai.toolResponseMetadata
|
|
71
|
+
window.openai.toolResponseMetadata?.toolName
|
|
70
72
|
)
|
|
71
73
|
) {
|
|
72
74
|
// We need to include the variables that were used as part of the tool call so that we get a proper cache entry
|
|
73
75
|
// However, we only want to include toolInput's that were graphql operation (ignore extraInputs)
|
|
74
76
|
const variables = Object.keys(window.openai.toolInput).reduce(
|
|
75
77
|
(obj, key) =>
|
|
76
|
-
operation.variables[key] ?
|
|
78
|
+
operation.variables?.[key] ?
|
|
77
79
|
{ ...obj, [key]: window.openai.toolInput[key] }
|
|
78
80
|
: obj,
|
|
79
81
|
{}
|
|
80
82
|
);
|
|
81
83
|
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
84
|
+
if (window.openai.toolOutput) {
|
|
85
|
+
this.writeQuery({
|
|
86
|
+
query: parse(operation.body),
|
|
87
|
+
data: (window.openai.toolOutput.result as any).data,
|
|
88
|
+
variables,
|
|
89
|
+
});
|
|
90
|
+
}
|
|
87
91
|
}
|
|
88
92
|
});
|
|
89
93
|
}
|
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
import { expect, test, describe, vi } from "vitest";
|
|
2
|
-
import {
|
|
3
|
-
import { ApplicationManifest } from "
|
|
2
|
+
import { ApolloClient } from "../ApolloClient";
|
|
3
|
+
import { ApplicationManifest } from "../../types/application-manifest";
|
|
4
4
|
import { parse } from "graphql";
|
|
5
5
|
import { ApolloLink, HttpLink, InMemoryCache } from "@apollo/client";
|
|
6
|
-
import {
|
|
7
|
-
import { ToolCallLink } from "./link/ToolCallLink";
|
|
6
|
+
import { ToolCallLink } from "../../link/ToolCallLink";
|
|
8
7
|
|
|
9
8
|
describe("Client Basics", () => {
|
|
10
9
|
test("Should execute tool call when client.query is called", async () => {
|
|
@@ -59,7 +58,7 @@ describe("Client Basics", () => {
|
|
|
59
58
|
resource: "index.html",
|
|
60
59
|
};
|
|
61
60
|
|
|
62
|
-
const client = new
|
|
61
|
+
const client = new ApolloClient({
|
|
63
62
|
cache: new InMemoryCache(),
|
|
64
63
|
manifest: manifest as ApplicationManifest,
|
|
65
64
|
});
|
|
@@ -148,7 +147,7 @@ describe("prefetchData", () => {
|
|
|
148
147
|
resource: "index.html",
|
|
149
148
|
};
|
|
150
149
|
|
|
151
|
-
const client = new
|
|
150
|
+
const client = new ApolloClient({
|
|
152
151
|
cache: new InMemoryCache(),
|
|
153
152
|
manifest: manifest as ApplicationManifest,
|
|
154
153
|
});
|
|
@@ -230,7 +229,7 @@ describe("prefetchData", () => {
|
|
|
230
229
|
resource: "index.html",
|
|
231
230
|
};
|
|
232
231
|
|
|
233
|
-
const client = new
|
|
232
|
+
const client = new ApolloClient({
|
|
234
233
|
cache: new InMemoryCache(),
|
|
235
234
|
manifest: manifest as ApplicationManifest,
|
|
236
235
|
});
|
|
@@ -340,7 +339,7 @@ describe("prefetchData", () => {
|
|
|
340
339
|
resource: "index.html",
|
|
341
340
|
};
|
|
342
341
|
|
|
343
|
-
const client = new
|
|
342
|
+
const client = new ApolloClient({
|
|
344
343
|
cache: new InMemoryCache(),
|
|
345
344
|
manifest: manifest as ApplicationManifest,
|
|
346
345
|
});
|
|
@@ -431,7 +430,7 @@ describe("prefetchData", () => {
|
|
|
431
430
|
resource: "index.html",
|
|
432
431
|
};
|
|
433
432
|
|
|
434
|
-
const client = new
|
|
433
|
+
const client = new ApolloClient({
|
|
435
434
|
cache: new InMemoryCache(),
|
|
436
435
|
manifest: manifest as ApplicationManifest,
|
|
437
436
|
});
|