@apollo/client-ai-apps 0.2.3 → 0.3.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/.git-blame-ignore-revs +2 -0
- package/.github/workflows/pr.yaml +23 -15
- package/.github/workflows/release.yaml +46 -46
- package/.prettierrc +9 -0
- package/dist/apollo_client/client.d.ts +1 -2
- package/dist/apollo_client/link/ToolCallLink.d.ts +26 -0
- package/dist/hooks/useToolEffect.d.ts +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.js +75 -25
- package/dist/vite/absolute_asset_imports_plugin.d.ts +4 -0
- package/dist/vite/index.d.ts +1 -0
- package/dist/vite/index.js +90 -25
- package/package.json +5 -2
- package/scripts/dev.mjs +3 -1
- package/src/apollo_client/client.test.ts +226 -13
- package/src/apollo_client/client.ts +44 -30
- package/src/apollo_client/link/ToolCallLink.ts +49 -0
- package/src/apollo_client/provider.tsx +8 -2
- package/src/hooks/useCallTool.ts +8 -3
- package/src/hooks/useOpenAiGlobal.test.ts +3 -1
- package/src/hooks/useOpenAiGlobal.ts +8 -2
- package/src/hooks/useSendFollowUpMessage.test.ts +3 -1
- package/src/hooks/useToolEffect.test.tsx +25 -9
- package/src/hooks/useToolEffect.tsx +24 -5
- package/src/index.ts +1 -0
- package/src/types/openai.ts +5 -2
- package/src/vite/absolute_asset_imports_plugin.test.ts +102 -0
- package/src/vite/absolute_asset_imports_plugin.ts +22 -0
- package/src/vite/application_manifest_plugin.test.ts +195 -72
- package/src/vite/application_manifest_plugin.ts +88 -28
- package/src/vite/index.ts +1 -0
|
@@ -10,11 +10,19 @@ type ToolUseState = {
|
|
|
10
10
|
|
|
11
11
|
const ToolUseContext = React.createContext<ToolUseState | null>(null);
|
|
12
12
|
|
|
13
|
-
export function ToolUseProvider({
|
|
13
|
+
export function ToolUseProvider({
|
|
14
|
+
children,
|
|
15
|
+
appName,
|
|
16
|
+
}: {
|
|
17
|
+
children: any;
|
|
18
|
+
appName: string;
|
|
19
|
+
}) {
|
|
14
20
|
const [hasNavigated, setHasNavigated] = useState(false);
|
|
15
21
|
|
|
16
22
|
return (
|
|
17
|
-
<ToolUseContext.Provider value={{ hasNavigated, setHasNavigated, appName }}>
|
|
23
|
+
<ToolUseContext.Provider value={{ hasNavigated, setHasNavigated, appName }}>
|
|
24
|
+
{children}
|
|
25
|
+
</ToolUseContext.Provider>
|
|
18
26
|
);
|
|
19
27
|
}
|
|
20
28
|
|
|
@@ -26,16 +34,27 @@ export const useToolEffect = (
|
|
|
26
34
|
const ctx = React.useContext(ToolUseContext);
|
|
27
35
|
const fullToolName = useToolName();
|
|
28
36
|
const toolInput = useToolInput();
|
|
29
|
-
if (!ctx)
|
|
37
|
+
if (!ctx)
|
|
38
|
+
throw new Error("useToolEffect must be used within ToolUseProvider");
|
|
30
39
|
|
|
31
40
|
const toolNames = Array.isArray(toolName) ? toolName : [toolName];
|
|
32
41
|
|
|
33
42
|
useEffect(() => {
|
|
34
|
-
const matches = toolNames.some(
|
|
43
|
+
const matches = toolNames.some(
|
|
44
|
+
(name) => fullToolName === `${ctx.appName}--${name}`
|
|
45
|
+
);
|
|
35
46
|
|
|
36
47
|
if (!ctx.hasNavigated && matches) {
|
|
37
48
|
effect(toolInput);
|
|
38
49
|
ctx.setHasNavigated(true);
|
|
39
50
|
}
|
|
40
|
-
}, [
|
|
51
|
+
}, [
|
|
52
|
+
ctx.hasNavigated,
|
|
53
|
+
ctx.setHasNavigated,
|
|
54
|
+
ctx.appName,
|
|
55
|
+
toolNames,
|
|
56
|
+
fullToolName,
|
|
57
|
+
toolInput,
|
|
58
|
+
...deps,
|
|
59
|
+
]);
|
|
41
60
|
};
|
package/src/index.ts
CHANGED
|
@@ -10,3 +10,4 @@ export * from "./hooks/useToolEffect";
|
|
|
10
10
|
export * from "@apollo/client";
|
|
11
11
|
export { ExtendedApolloClient as ApolloClient } from "./apollo_client/client";
|
|
12
12
|
export { ExtendedApolloProvider as ApolloProvider } from "./apollo_client/provider";
|
|
13
|
+
export { ToolCallLink } from "./apollo_client/link/ToolCallLink";
|
package/src/types/openai.ts
CHANGED
|
@@ -14,7 +14,7 @@ export type OpenAiGlobals<
|
|
|
14
14
|
ToolInput extends UnknownObject = UnknownObject,
|
|
15
15
|
ToolOutput extends UnknownObject = UnknownObject,
|
|
16
16
|
ToolResponseMetadata extends UnknownObject = UnknownObject,
|
|
17
|
-
WidgetState extends UnknownObject = UnknownObject
|
|
17
|
+
WidgetState extends UnknownObject = UnknownObject,
|
|
18
18
|
> = {
|
|
19
19
|
theme: Theme;
|
|
20
20
|
userAgent: UserAgent;
|
|
@@ -62,7 +62,10 @@ export class SetGlobalsEvent extends CustomEvent<{
|
|
|
62
62
|
readonly type = SET_GLOBALS_EVENT_TYPE;
|
|
63
63
|
}
|
|
64
64
|
|
|
65
|
-
export type CallTool = (
|
|
65
|
+
export type CallTool = (
|
|
66
|
+
name: string,
|
|
67
|
+
args: Record<string, unknown>
|
|
68
|
+
) => Promise<any>;
|
|
66
69
|
|
|
67
70
|
export type DisplayMode = "pip" | "inline" | "fullscreen";
|
|
68
71
|
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import { expect, test, vi, describe, beforeEach, Mock } from "vitest";
|
|
2
|
+
import { AbsoluteAssetImportsPlugin } from "./absolute_asset_imports_plugin";
|
|
3
|
+
|
|
4
|
+
test("Should replace root relative scripts with full url when origin is provided", () => {
|
|
5
|
+
const ctx = {
|
|
6
|
+
server: {
|
|
7
|
+
config: {
|
|
8
|
+
server: {
|
|
9
|
+
origin: "http://localhost:3000/",
|
|
10
|
+
},
|
|
11
|
+
},
|
|
12
|
+
},
|
|
13
|
+
};
|
|
14
|
+
const html = `<html><head><script type="module" src="/@vite/client"></script></head><body><script module src="/assets/main.ts?t=12345"></script></body></html>`;
|
|
15
|
+
const plugin = AbsoluteAssetImportsPlugin();
|
|
16
|
+
|
|
17
|
+
let result = plugin.transformIndexHtml(html, ctx);
|
|
18
|
+
|
|
19
|
+
expect(result).toMatchInlineSnapshot(
|
|
20
|
+
`"<html><head><script type="module" src="http://localhost:3000/@vite/client"></script></head><body><script module src="http://localhost:3000/assets/main.ts?t=12345"></script></body></html>"`
|
|
21
|
+
);
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
test("Should replace root relative scripts with full url when origin is not provided", () => {
|
|
25
|
+
const ctx = {
|
|
26
|
+
server: {
|
|
27
|
+
resolvedUrls: {
|
|
28
|
+
local: ["http://localhost:3000/"],
|
|
29
|
+
},
|
|
30
|
+
},
|
|
31
|
+
};
|
|
32
|
+
const html = `<html><head> <script type="module">import { injectIntoGlobalHook } from "/@react-refresh";
|
|
33
|
+
injectIntoGlobalHook(window);
|
|
34
|
+
window.$RefreshReg$ = () => {};
|
|
35
|
+
window.$RefreshSig$ = () => (type) => type;</script></head></html>`;
|
|
36
|
+
const plugin = AbsoluteAssetImportsPlugin();
|
|
37
|
+
|
|
38
|
+
let result = plugin.transformIndexHtml(html, ctx);
|
|
39
|
+
|
|
40
|
+
expect(result).toMatchInlineSnapshot(`
|
|
41
|
+
"<html><head> <script type="module">import { injectIntoGlobalHook } from "http://localhost:3000/@react-refresh";
|
|
42
|
+
injectIntoGlobalHook(window);
|
|
43
|
+
window.$RefreshReg$ = () => {};
|
|
44
|
+
window.$RefreshSig$ = () => (type) => type;</script></head></html>"
|
|
45
|
+
`);
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
test("Should replace root relative imports with full url when origin is provided", () => {
|
|
49
|
+
const ctx = {
|
|
50
|
+
server: {
|
|
51
|
+
config: {
|
|
52
|
+
server: {
|
|
53
|
+
origin: "http://localhost:3000/",
|
|
54
|
+
},
|
|
55
|
+
},
|
|
56
|
+
},
|
|
57
|
+
};
|
|
58
|
+
const html = `<html><head> <script type="module">import { injectIntoGlobalHook } from "/@react-refresh";
|
|
59
|
+
injectIntoGlobalHook(window);
|
|
60
|
+
window.$RefreshReg$ = () => {};
|
|
61
|
+
window.$RefreshSig$ = () => (type) => type;</script></head></html>`;
|
|
62
|
+
const plugin = AbsoluteAssetImportsPlugin();
|
|
63
|
+
|
|
64
|
+
let result = plugin.transformIndexHtml(html, ctx);
|
|
65
|
+
|
|
66
|
+
expect(result).toMatchInlineSnapshot(`
|
|
67
|
+
"<html><head> <script type="module">import { injectIntoGlobalHook } from "http://localhost:3000/@react-refresh";
|
|
68
|
+
injectIntoGlobalHook(window);
|
|
69
|
+
window.$RefreshReg$ = () => {};
|
|
70
|
+
window.$RefreshSig$ = () => (type) => type;</script></head></html>"
|
|
71
|
+
`);
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
test("Should replace root relative imports with full url when origin is not provided", () => {
|
|
75
|
+
const ctx = {
|
|
76
|
+
server: {
|
|
77
|
+
resolvedUrls: {
|
|
78
|
+
local: ["http://localhost:3000/"],
|
|
79
|
+
},
|
|
80
|
+
},
|
|
81
|
+
};
|
|
82
|
+
const html = `<html><body><script module src="/assets/main.ts?t=12345"></script></body></html>`;
|
|
83
|
+
const plugin = AbsoluteAssetImportsPlugin();
|
|
84
|
+
|
|
85
|
+
let result = plugin.transformIndexHtml(html, ctx);
|
|
86
|
+
|
|
87
|
+
expect(result).toMatchInlineSnapshot(
|
|
88
|
+
`"<html><body><script module src="http://localhost:3000/assets/main.ts?t=12345"></script></body></html>"`
|
|
89
|
+
);
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
test("Should not modify html when not running a local server", () => {
|
|
93
|
+
const ctx = {};
|
|
94
|
+
const html = `<html><head><script type="module" src="/@vite/client"></script></head><body><script module src="/assets/main.ts?t=12345"></script></body></html>`;
|
|
95
|
+
const plugin = AbsoluteAssetImportsPlugin();
|
|
96
|
+
|
|
97
|
+
let result = plugin.transformIndexHtml(html, ctx);
|
|
98
|
+
|
|
99
|
+
expect(result).toMatchInlineSnapshot(
|
|
100
|
+
`"<html><head><script type="module" src="/@vite/client"></script></head><body><script module src="/assets/main.ts?t=12345"></script></body></html>"`
|
|
101
|
+
);
|
|
102
|
+
});
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
export const AbsoluteAssetImportsPlugin = () => {
|
|
2
|
+
return {
|
|
3
|
+
name: "absolute-asset-imports",
|
|
4
|
+
|
|
5
|
+
transformIndexHtml(html: string, ctx: any) {
|
|
6
|
+
if (!ctx.server) return html;
|
|
7
|
+
|
|
8
|
+
let baseUrl = (
|
|
9
|
+
ctx.server.config?.server?.origin ?? ctx.server.resolvedUrls?.local[0]
|
|
10
|
+
).replace(/\/$/, "");
|
|
11
|
+
baseUrl = baseUrl.replace(/\/$/, "");
|
|
12
|
+
|
|
13
|
+
return (
|
|
14
|
+
html
|
|
15
|
+
// import "/@vite/..." or "/@react-refresh"
|
|
16
|
+
.replace(/(from\s+["'])\/([^"']+)/g, `$1${baseUrl}/$2`)
|
|
17
|
+
// src="/src/..."
|
|
18
|
+
.replace(/(src=["'])\/([^"']+)/gi, `$1${baseUrl}/$2`)
|
|
19
|
+
);
|
|
20
|
+
},
|
|
21
|
+
};
|
|
22
|
+
};
|