@copilotkit/react-core 1.5.0-tyler-reset-chat.0 → 1.5.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 +158 -4
- package/README.md +2 -0
- package/dist/{chunk-3AYELZJS.mjs → chunk-35EN6BG4.mjs} +2 -2
- package/dist/{chunk-3AYELZJS.mjs.map → chunk-35EN6BG4.mjs.map} +1 -1
- package/dist/{chunk-SEPYQHH7.mjs → chunk-42N5VKIX.mjs} +34 -28
- package/dist/chunk-42N5VKIX.mjs.map +1 -0
- package/dist/{chunk-USL3EHJB.mjs → chunk-5FYKUKG3.mjs} +2 -2
- package/dist/{chunk-ODN4H66E.mjs → chunk-7LRDVJH5.mjs} +6 -2
- package/dist/chunk-7LRDVJH5.mjs.map +1 -0
- package/dist/{chunk-CZMEZR6F.mjs → chunk-BT6WK2JZ.mjs} +34 -19
- package/dist/chunk-BT6WK2JZ.mjs.map +1 -0
- package/dist/{chunk-3R4J2TPH.mjs → chunk-EUU6NNYU.mjs} +29 -13
- package/dist/chunk-EUU6NNYU.mjs.map +1 -0
- package/dist/chunk-QCUP6HLK.mjs +37 -0
- package/dist/chunk-QCUP6HLK.mjs.map +1 -0
- package/dist/chunk-QTDCEDOC.mjs +392 -0
- package/dist/chunk-QTDCEDOC.mjs.map +1 -0
- package/dist/{chunk-JR55I3FL.mjs → chunk-QX6V774L.mjs} +6 -8
- package/dist/chunk-QX6V774L.mjs.map +1 -0
- package/dist/{chunk-2KCEHGSI.mjs → chunk-SFPANIOY.mjs} +99 -49
- package/dist/chunk-SFPANIOY.mjs.map +1 -0
- package/dist/{chunk-2JP64U3A.mjs → chunk-TQN3EZWQ.mjs} +4 -1
- package/dist/chunk-TQN3EZWQ.mjs.map +1 -0
- package/dist/{chunk-XUPO37VH.mjs → chunk-V3PFWGIY.mjs} +2 -2
- package/dist/{chunk-6QKA3SNN.mjs → chunk-VMP6JWBB.mjs} +21 -5
- package/dist/chunk-VMP6JWBB.mjs.map +1 -0
- package/dist/chunk-XERJQUHA.mjs +31 -0
- package/dist/chunk-XERJQUHA.mjs.map +1 -0
- package/dist/components/copilot-provider/copilotkit.js +173 -92
- package/dist/components/copilot-provider/copilotkit.js.map +1 -1
- package/dist/components/copilot-provider/copilotkit.mjs +5 -4
- package/dist/components/copilot-provider/index.js +173 -92
- package/dist/components/copilot-provider/index.js.map +1 -1
- package/dist/components/copilot-provider/index.mjs +5 -4
- package/dist/components/error-boundary/error-boundary.d.ts +22 -0
- package/dist/components/error-boundary/error-boundary.js +183 -0
- package/dist/components/error-boundary/error-boundary.js.map +1 -0
- package/dist/components/error-boundary/error-boundary.mjs +12 -0
- package/dist/components/error-boundary/error-boundary.mjs.map +1 -0
- package/dist/components/error-boundary/error-utils.d.ts +11 -0
- package/dist/components/error-boundary/error-utils.js +177 -0
- package/dist/components/error-boundary/error-utils.js.map +1 -0
- package/dist/components/error-boundary/error-utils.mjs +13 -0
- package/dist/components/error-boundary/error-utils.mjs.map +1 -0
- package/dist/components/index.js +173 -92
- package/dist/components/index.js.map +1 -1
- package/dist/components/index.mjs +5 -4
- package/dist/components/toast/toast-provider.d.ts +2 -1
- package/dist/components/toast/toast-provider.js +76 -62
- package/dist/components/toast/toast-provider.js.map +1 -1
- package/dist/components/toast/toast-provider.mjs +1 -1
- package/dist/context/copilot-context.d.ts +4 -2
- package/dist/context/copilot-context.js +3 -0
- package/dist/context/copilot-context.js.map +1 -1
- package/dist/context/copilot-context.mjs +1 -1
- package/dist/context/index.d.ts +1 -1
- package/dist/context/index.js +3 -0
- package/dist/context/index.js.map +1 -1
- package/dist/context/index.mjs +1 -1
- package/dist/hooks/index.js +554 -308
- package/dist/hooks/index.js.map +1 -1
- package/dist/hooks/index.mjs +13 -11
- package/dist/hooks/use-chat.d.ts +6 -2
- package/dist/hooks/use-chat.js +434 -219
- package/dist/hooks/use-chat.js.map +1 -1
- package/dist/hooks/use-chat.mjs +4 -3
- package/dist/hooks/use-coagent-state-render.d.ts +2 -2
- package/dist/hooks/use-coagent-state-render.js +3 -0
- package/dist/hooks/use-coagent-state-render.js.map +1 -1
- package/dist/hooks/use-coagent-state-render.mjs +2 -2
- package/dist/hooks/use-coagent.d.ts +1 -1
- package/dist/hooks/use-coagent.js +510 -277
- package/dist/hooks/use-coagent.js.map +1 -1
- package/dist/hooks/use-coagent.mjs +9 -7
- package/dist/hooks/use-copilot-action.d.ts +12 -2
- package/dist/hooks/use-copilot-action.js +157 -16
- package/dist/hooks/use-copilot-action.js.map +1 -1
- package/dist/hooks/use-copilot-action.mjs +4 -2
- package/dist/hooks/use-copilot-chat.d.ts +1 -0
- package/dist/hooks/use-copilot-chat.js +483 -253
- package/dist/hooks/use-copilot-chat.js.map +1 -1
- package/dist/hooks/use-copilot-chat.mjs +8 -6
- package/dist/hooks/use-copilot-readable.js +3 -0
- package/dist/hooks/use-copilot-readable.js.map +1 -1
- package/dist/hooks/use-copilot-readable.mjs +2 -2
- package/dist/hooks/use-copilot-runtime-client.js +110 -4
- package/dist/hooks/use-copilot-runtime-client.js.map +1 -1
- package/dist/hooks/use-copilot-runtime-client.mjs +2 -2
- package/dist/hooks/use-make-copilot-document-readable.js +3 -0
- package/dist/hooks/use-make-copilot-document-readable.js.map +1 -1
- package/dist/hooks/use-make-copilot-document-readable.mjs +2 -2
- package/dist/index.d.ts +1 -1
- package/dist/index.js +616 -401
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +14 -12
- package/dist/lib/copilot-task.d.ts +1 -1
- package/dist/lib/copilot-task.js +33 -13
- package/dist/lib/copilot-task.js.map +1 -1
- package/dist/lib/copilot-task.mjs +7 -5
- package/dist/lib/index.d.ts +1 -1
- package/dist/lib/index.js +33 -13
- package/dist/lib/index.js.map +1 -1
- package/dist/lib/index.mjs +7 -5
- package/dist/types/frontend-action.d.ts +21 -2
- package/dist/types/frontend-action.js +34 -0
- package/dist/types/frontend-action.js.map +1 -1
- package/dist/types/frontend-action.mjs +7 -0
- package/dist/types/index.d.ts +2 -1
- package/dist/types/index.js.map +1 -1
- package/dist/utils/extract.js.map +1 -1
- package/dist/utils/extract.mjs +5 -4
- package/dist/utils/index.js.map +1 -1
- package/dist/utils/index.mjs +5 -4
- package/package.json +5 -5
- package/src/components/copilot-provider/copilotkit.tsx +22 -1
- package/src/components/error-boundary/error-boundary.tsx +42 -0
- package/src/components/error-boundary/error-utils.tsx +95 -0
- package/src/components/toast/toast-provider.tsx +10 -49
- package/src/context/copilot-context.tsx +17 -2
- package/src/hooks/use-chat.ts +375 -279
- package/src/hooks/use-coagent-state-render.ts +2 -2
- package/src/hooks/use-coagent.ts +34 -28
- package/src/hooks/use-copilot-action.ts +50 -15
- package/src/hooks/use-copilot-chat.ts +28 -14
- package/src/hooks/use-copilot-runtime-client.ts +4 -0
- package/src/lib/copilot-task.ts +2 -8
- package/src/types/frontend-action.ts +55 -2
- package/src/types/index.ts +5 -1
- package/dist/chunk-2JP64U3A.mjs.map +0 -1
- package/dist/chunk-2KCEHGSI.mjs.map +0 -1
- package/dist/chunk-3R4J2TPH.mjs.map +0 -1
- package/dist/chunk-6EN7J4V2.mjs +0 -317
- package/dist/chunk-6EN7J4V2.mjs.map +0 -1
- package/dist/chunk-6QKA3SNN.mjs.map +0 -1
- package/dist/chunk-CZMEZR6F.mjs.map +0 -1
- package/dist/chunk-JR55I3FL.mjs.map +0 -1
- package/dist/chunk-ODN4H66E.mjs.map +0 -1
- package/dist/chunk-SEPYQHH7.mjs.map +0 -1
- /package/dist/{chunk-USL3EHJB.mjs.map → chunk-5FYKUKG3.mjs.map} +0 -0
- /package/dist/{chunk-XUPO37VH.mjs.map → chunk-V3PFWGIY.mjs.map} +0 -0
|
@@ -12,13 +12,13 @@
|
|
|
12
12
|
* ### Simple Usage
|
|
13
13
|
*
|
|
14
14
|
* ```tsx
|
|
15
|
-
* import {
|
|
15
|
+
* import { useCoAgentStateRender } from "@copilotkit/react-core";
|
|
16
16
|
*
|
|
17
17
|
* type YourAgentState = {
|
|
18
18
|
* agent_state_property: string;
|
|
19
19
|
* }
|
|
20
20
|
*
|
|
21
|
-
*
|
|
21
|
+
* useCoAgentStateRender<YourAgentState>({
|
|
22
22
|
* name: "basic_agent",
|
|
23
23
|
* nodeName: "optionally_specify_a_specific_node",
|
|
24
24
|
* render: ({ status, state, nodeName }) => {
|
package/src/hooks/use-coagent.ts
CHANGED
|
@@ -97,7 +97,9 @@ import {
|
|
|
97
97
|
} from "../context";
|
|
98
98
|
import { CoagentState } from "../types/coagent-state";
|
|
99
99
|
import { useCopilotChat } from "./use-copilot-chat";
|
|
100
|
-
import {
|
|
100
|
+
import { Message } from "@copilotkit/runtime-client-gql";
|
|
101
|
+
import { flushSync } from "react-dom";
|
|
102
|
+
import { useAsyncCallback } from "../components/error-boundary/error-utils";
|
|
101
103
|
|
|
102
104
|
interface WithInternalStateManagementAndInitial<T> {
|
|
103
105
|
/**
|
|
@@ -218,8 +220,8 @@ export function useCoAgent<T = any>(options: UseCoagentOptions<T>): UseCoagentRe
|
|
|
218
220
|
const generalContext = useCopilotContext();
|
|
219
221
|
const messagesContext = useCopilotMessagesContext();
|
|
220
222
|
const context = { ...generalContext, ...messagesContext };
|
|
221
|
-
const { coagentStates,
|
|
222
|
-
const { appendMessage } = useCopilotChat();
|
|
223
|
+
const { coagentStates, coagentStatesRef, setCoagentStatesWithRef } = context;
|
|
224
|
+
const { appendMessage, runChatCompletion } = useCopilotChat();
|
|
223
225
|
|
|
224
226
|
const getCoagentState = (coagentStates: Record<string, CoagentState>, name: string) => {
|
|
225
227
|
if (coagentStates[name]) {
|
|
@@ -239,19 +241,16 @@ export function useCoAgent<T = any>(options: UseCoagentOptions<T>): UseCoagentRe
|
|
|
239
241
|
|
|
240
242
|
// if we manage state internally, we need to provide a function to set the state
|
|
241
243
|
const setState = (newState: T | ((prevState: T | undefined) => T)) => {
|
|
242
|
-
|
|
243
|
-
|
|
244
|
+
let coagentState: CoagentState = getCoagentState(coagentStatesRef.current || {}, name);
|
|
245
|
+
const updatedState =
|
|
246
|
+
typeof newState === "function" ? (newState as Function)(coagentState.state) : newState;
|
|
244
247
|
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
...coagentState,
|
|
252
|
-
state: updatedState,
|
|
253
|
-
},
|
|
254
|
-
};
|
|
248
|
+
setCoagentStatesWithRef({
|
|
249
|
+
...coagentStatesRef.current,
|
|
250
|
+
[name]: {
|
|
251
|
+
...coagentState,
|
|
252
|
+
state: updatedState,
|
|
253
|
+
},
|
|
255
254
|
});
|
|
256
255
|
};
|
|
257
256
|
|
|
@@ -269,25 +268,27 @@ export function useCoAgent<T = any>(options: UseCoagentOptions<T>): UseCoagentRe
|
|
|
269
268
|
}, [
|
|
270
269
|
isExternalStateManagement(options) ? JSON.stringify(options.state) : undefined,
|
|
271
270
|
// reset initialstate on reset
|
|
272
|
-
coagentStates === undefined,
|
|
271
|
+
coagentStates[name] === undefined,
|
|
273
272
|
]);
|
|
274
273
|
|
|
274
|
+
const runAgentCallback = useAsyncCallback(
|
|
275
|
+
async (hint?: HintFunction) => {
|
|
276
|
+
await runAgent(name, context, appendMessage, runChatCompletion, hint);
|
|
277
|
+
},
|
|
278
|
+
[name, context, appendMessage, runChatCompletion],
|
|
279
|
+
);
|
|
280
|
+
|
|
275
281
|
// Return the state and setState function
|
|
276
282
|
return {
|
|
277
283
|
name,
|
|
278
284
|
nodeName: coagentState.nodeName,
|
|
279
|
-
|
|
280
|
-
setState,
|
|
285
|
+
threadId: coagentState.threadId,
|
|
281
286
|
running: coagentState.running,
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
stop: () =>
|
|
286
|
-
|
|
287
|
-
},
|
|
288
|
-
run: (hint?: HintFunction) => {
|
|
289
|
-
return runAgent(name, context, appendMessage, hint);
|
|
290
|
-
},
|
|
287
|
+
state: coagentState.state,
|
|
288
|
+
setState: isExternalStateManagement(options) ? options.setState : setState,
|
|
289
|
+
start: () => startAgent(name, context),
|
|
290
|
+
stop: () => stopAgent(name, context),
|
|
291
|
+
run: runAgentCallback,
|
|
291
292
|
};
|
|
292
293
|
}
|
|
293
294
|
|
|
@@ -324,6 +325,7 @@ export async function runAgent(
|
|
|
324
325
|
name: string,
|
|
325
326
|
context: CopilotContextParams & CopilotMessagesContextParams,
|
|
326
327
|
appendMessage: (message: Message) => Promise<void>,
|
|
328
|
+
runChatCompletion: () => Promise<Message[]>,
|
|
327
329
|
hint?: HintFunction,
|
|
328
330
|
) {
|
|
329
331
|
const { agentSession, setAgentSession } = context;
|
|
@@ -341,12 +343,16 @@ export async function runAgent(
|
|
|
341
343
|
}
|
|
342
344
|
}
|
|
343
345
|
|
|
344
|
-
let state = context.
|
|
346
|
+
let state = context.coagentStatesRef.current?.[name]?.state || {};
|
|
345
347
|
|
|
346
348
|
if (hint) {
|
|
347
349
|
const hintMessage = hint({ previousState, currentState: state });
|
|
348
350
|
if (hintMessage) {
|
|
349
351
|
await appendMessage(hintMessage);
|
|
352
|
+
} else {
|
|
353
|
+
await runChatCompletion();
|
|
350
354
|
}
|
|
355
|
+
} else {
|
|
356
|
+
await runChatCompletion();
|
|
351
357
|
}
|
|
352
358
|
}
|
|
@@ -71,6 +71,15 @@
|
|
|
71
71
|
* );
|
|
72
72
|
* },
|
|
73
73
|
* });
|
|
74
|
+
*
|
|
75
|
+
* @example
|
|
76
|
+
* // Catch all action allows you to render actions that are not defined in the frontend
|
|
77
|
+
* useCopilotAction({
|
|
78
|
+
* name: "*",
|
|
79
|
+
* render: ({ name, args, status, result, handler, respond }) => {
|
|
80
|
+
* return <div>Rendering action: {name}</div>;
|
|
81
|
+
* },
|
|
82
|
+
* });
|
|
74
83
|
*/
|
|
75
84
|
|
|
76
85
|
/**
|
|
@@ -124,10 +133,12 @@
|
|
|
124
133
|
import { Parameter, randomId } from "@copilotkit/shared";
|
|
125
134
|
import { createElement, Fragment, useEffect, useRef } from "react";
|
|
126
135
|
import { useCopilotContext } from "../context/copilot-context";
|
|
136
|
+
import { useAsyncCallback } from "../components/error-boundary/error-utils";
|
|
127
137
|
import {
|
|
128
138
|
ActionRenderProps,
|
|
129
139
|
ActionRenderPropsNoArgsWait,
|
|
130
140
|
ActionRenderPropsWait,
|
|
141
|
+
CatchAllFrontendAction,
|
|
131
142
|
FrontendAction,
|
|
132
143
|
} from "../types/frontend-action";
|
|
133
144
|
|
|
@@ -141,7 +152,7 @@ import {
|
|
|
141
152
|
// useCallback, useMemo or other memoization techniques are not suitable here,
|
|
142
153
|
// because they will cause a infinite rerender loop.
|
|
143
154
|
export function useCopilotAction<const T extends Parameter[] | [] = []>(
|
|
144
|
-
action: FrontendAction<T
|
|
155
|
+
action: FrontendAction<T> | CatchAllFrontendAction,
|
|
145
156
|
dependencies?: any[],
|
|
146
157
|
): void {
|
|
147
158
|
const { setAction, removeAction, actions, chatComponentsCache } = useCopilotContext();
|
|
@@ -151,15 +162,20 @@ export function useCopilotAction<const T extends Parameter[] | [] = []>(
|
|
|
151
162
|
// clone the action to avoid mutating the original object
|
|
152
163
|
action = { ...action };
|
|
153
164
|
|
|
154
|
-
// If the developer provides a
|
|
165
|
+
// If the developer provides a renderAndWaitForResponse function, we transform the action
|
|
155
166
|
// to use a promise internally, so that we can treat it like a normal action.
|
|
156
|
-
if (
|
|
167
|
+
if (
|
|
168
|
+
// renderAndWaitForResponse is not available for catch all actions
|
|
169
|
+
isFrontendAction(action) &&
|
|
170
|
+
// check if renderAndWaitForResponse is set
|
|
171
|
+
(action.renderAndWait || action.renderAndWaitForResponse)
|
|
172
|
+
) {
|
|
157
173
|
const renderAndWait = action.renderAndWait || action.renderAndWaitForResponse;
|
|
158
174
|
// remove the renderAndWait function from the action
|
|
159
175
|
action.renderAndWait = undefined;
|
|
160
176
|
action.renderAndWaitForResponse = undefined;
|
|
161
177
|
// add a handler that will be called when the action is executed
|
|
162
|
-
action.handler = (async () => {
|
|
178
|
+
action.handler = useAsyncCallback(async () => {
|
|
163
179
|
// we create a new promise when the handler is called
|
|
164
180
|
let resolve: (result: any) => void;
|
|
165
181
|
let reject: (error: any) => void;
|
|
@@ -170,17 +186,23 @@ export function useCopilotAction<const T extends Parameter[] | [] = []>(
|
|
|
170
186
|
renderAndWaitRef.current = { promise, resolve: resolve!, reject: reject! };
|
|
171
187
|
// then we await the promise (it will be resolved in the original renderAndWait function)
|
|
172
188
|
return await promise;
|
|
173
|
-
}) as any;
|
|
189
|
+
}, []) as any;
|
|
174
190
|
|
|
175
191
|
// add a render function that will be called when the action is rendered
|
|
176
192
|
action.render = ((props: ActionRenderProps<T>): React.ReactElement => {
|
|
193
|
+
// Specifically for renderAndWaitForResponse the executing state is set too early, causing a race condition
|
|
194
|
+
// To fit it: we will wait for the handler to be ready
|
|
195
|
+
let status = props.status;
|
|
196
|
+
if (props.status === "executing" && !renderAndWaitRef.current) {
|
|
197
|
+
status = "inProgress";
|
|
198
|
+
}
|
|
177
199
|
// Create type safe waitProps based on whether T extends empty array or not
|
|
178
200
|
const waitProps = {
|
|
179
|
-
status
|
|
201
|
+
status,
|
|
180
202
|
args: props.args,
|
|
181
203
|
result: props.result,
|
|
182
|
-
handler:
|
|
183
|
-
respond:
|
|
204
|
+
handler: status === "executing" ? renderAndWaitRef.current!.resolve : undefined,
|
|
205
|
+
respond: status === "executing" ? renderAndWaitRef.current!.resolve : undefined,
|
|
184
206
|
} as T extends [] ? ActionRenderPropsNoArgsWait<T> : ActionRenderPropsWait<T>;
|
|
185
207
|
|
|
186
208
|
// Type guard to check if renderAndWait is for no args case
|
|
@@ -211,10 +233,15 @@ export function useCopilotAction<const T extends Parameter[] | [] = []>(
|
|
|
211
233
|
// This ensures that any captured variables in the handler are up to date.
|
|
212
234
|
if (dependencies === undefined) {
|
|
213
235
|
if (actions[idRef.current]) {
|
|
214
|
-
actions
|
|
236
|
+
// catch all actions don't have a handler
|
|
237
|
+
if (isFrontendAction(action)) {
|
|
238
|
+
actions[idRef.current].handler = action.handler as any;
|
|
239
|
+
}
|
|
215
240
|
if (typeof action.render === "function") {
|
|
216
241
|
if (chatComponentsCache.current !== null) {
|
|
217
|
-
|
|
242
|
+
// TODO: using as any here because the type definitions are getting to tricky
|
|
243
|
+
// not wasting time on this now - we know the types are compatible
|
|
244
|
+
chatComponentsCache.current.actions[action.name] = action.render as any;
|
|
218
245
|
}
|
|
219
246
|
}
|
|
220
247
|
}
|
|
@@ -223,23 +250,25 @@ export function useCopilotAction<const T extends Parameter[] | [] = []>(
|
|
|
223
250
|
useEffect(() => {
|
|
224
251
|
setAction(idRef.current, action as any);
|
|
225
252
|
if (chatComponentsCache.current !== null && action.render !== undefined) {
|
|
226
|
-
|
|
253
|
+
// see comment about type safety above
|
|
254
|
+
chatComponentsCache.current.actions[action.name] = action.render as any;
|
|
227
255
|
}
|
|
228
256
|
return () => {
|
|
229
257
|
// NOTE: For now, we don't remove the chatComponentsCache entry when the action is removed.
|
|
230
258
|
// This is because we currently don't have access to the messages array in CopilotContext.
|
|
259
|
+
// UPDATE: We now have access, we should remove the entry if not referenced by any message.
|
|
231
260
|
removeAction(idRef.current);
|
|
232
261
|
};
|
|
233
262
|
}, [
|
|
234
263
|
setAction,
|
|
235
264
|
removeAction,
|
|
236
|
-
action.description,
|
|
265
|
+
isFrontendAction(action) ? action.description : undefined,
|
|
237
266
|
action.name,
|
|
238
|
-
action.disabled,
|
|
239
|
-
action.available,
|
|
267
|
+
isFrontendAction(action) ? action.disabled : undefined,
|
|
268
|
+
isFrontendAction(action) ? action.available : undefined,
|
|
240
269
|
// This should be faster than deep equality checking
|
|
241
270
|
// In addition, all major JS engines guarantee the order of object keys
|
|
242
|
-
JSON.stringify(action.parameters),
|
|
271
|
+
JSON.stringify(isFrontendAction(action) ? action.parameters : []),
|
|
243
272
|
// include render only if it's a string
|
|
244
273
|
typeof action.render === "string" ? action.render : undefined,
|
|
245
274
|
// dependencies set by the developer
|
|
@@ -247,6 +276,12 @@ export function useCopilotAction<const T extends Parameter[] | [] = []>(
|
|
|
247
276
|
]);
|
|
248
277
|
}
|
|
249
278
|
|
|
279
|
+
function isFrontendAction<T extends Parameter[]>(
|
|
280
|
+
action: FrontendAction<T> | CatchAllFrontendAction,
|
|
281
|
+
): action is FrontendAction<T> {
|
|
282
|
+
return action.name !== "*";
|
|
283
|
+
}
|
|
284
|
+
|
|
250
285
|
interface RenderAndWaitForResponse {
|
|
251
286
|
promise: Promise<any>;
|
|
252
287
|
resolve: (result: any) => void;
|
|
@@ -47,6 +47,7 @@ import { defaultCopilotContextCategories } from "../components";
|
|
|
47
47
|
import { MessageStatusCode } from "@copilotkit/runtime-client-gql";
|
|
48
48
|
import { CoAgentStateRenderHandlerArguments } from "@copilotkit/shared";
|
|
49
49
|
import { useCopilotMessagesContext } from "../context";
|
|
50
|
+
import { useAsyncCallback } from "../components/error-boundary/error-utils";
|
|
50
51
|
|
|
51
52
|
export interface UseCopilotChatOptions {
|
|
52
53
|
/**
|
|
@@ -80,6 +81,7 @@ export interface UseCopilotChatReturn {
|
|
|
80
81
|
stopGeneration: () => void;
|
|
81
82
|
reset: () => void;
|
|
82
83
|
isLoading: boolean;
|
|
84
|
+
runChatCompletion: () => Promise<Message[]>;
|
|
83
85
|
}
|
|
84
86
|
|
|
85
87
|
export function useCopilotChat({
|
|
@@ -94,9 +96,8 @@ export function useCopilotChat({
|
|
|
94
96
|
setIsLoading,
|
|
95
97
|
chatInstructions,
|
|
96
98
|
actions,
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
setCoagentStates,
|
|
99
|
+
coagentStatesRef,
|
|
100
|
+
setCoagentStatesWithRef,
|
|
100
101
|
coAgentStateRenders,
|
|
101
102
|
agentSession,
|
|
102
103
|
setAgentSession,
|
|
@@ -130,7 +131,7 @@ export function useCopilotChat({
|
|
|
130
131
|
});
|
|
131
132
|
}, [getContextString, makeSystemMessage, chatInstructions]);
|
|
132
133
|
|
|
133
|
-
const onCoAgentStateRender =
|
|
134
|
+
const onCoAgentStateRender = useAsyncCallback(
|
|
134
135
|
async (args: CoAgentStateRenderHandlerArguments) => {
|
|
135
136
|
const { name, nodeName, state } = args;
|
|
136
137
|
let action = Object.values(coAgentStateRenders).find(
|
|
@@ -148,7 +149,7 @@ export function useCopilotChat({
|
|
|
148
149
|
[coAgentStateRenders],
|
|
149
150
|
);
|
|
150
151
|
|
|
151
|
-
const { append, reload, stop } = useChat({
|
|
152
|
+
const { append, reload, stop, runChatCompletion } = useChat({
|
|
152
153
|
...options,
|
|
153
154
|
actions: Object.values(actions),
|
|
154
155
|
copilotConfig: copilotApiConfig,
|
|
@@ -160,8 +161,8 @@ export function useCopilotChat({
|
|
|
160
161
|
makeSystemMessageCallback,
|
|
161
162
|
isLoading,
|
|
162
163
|
setIsLoading,
|
|
163
|
-
|
|
164
|
-
|
|
164
|
+
coagentStatesRef,
|
|
165
|
+
setCoagentStatesWithRef,
|
|
165
166
|
agentSession,
|
|
166
167
|
setAgentSession,
|
|
167
168
|
threadId,
|
|
@@ -180,16 +181,16 @@ export function useCopilotChat({
|
|
|
180
181
|
// How does this work?
|
|
181
182
|
// we store the relevant function in a ref that is always up-to-date, and then we use that ref in the callback.
|
|
182
183
|
const latestAppend = useUpdatedRef(append);
|
|
183
|
-
const latestAppendFunc =
|
|
184
|
-
(message: Message) => {
|
|
185
|
-
return latestAppend.current(message);
|
|
184
|
+
const latestAppendFunc = useAsyncCallback(
|
|
185
|
+
async (message: Message) => {
|
|
186
|
+
return await latestAppend.current(message);
|
|
186
187
|
},
|
|
187
188
|
[latestAppend],
|
|
188
189
|
);
|
|
189
190
|
|
|
190
191
|
const latestReload = useUpdatedRef(reload);
|
|
191
|
-
const latestReloadFunc =
|
|
192
|
-
return latestReload.current();
|
|
192
|
+
const latestReloadFunc = useAsyncCallback(async () => {
|
|
193
|
+
return await latestReload.current();
|
|
193
194
|
}, [latestReload]);
|
|
194
195
|
|
|
195
196
|
const latestStop = useUpdatedRef(stop);
|
|
@@ -213,12 +214,17 @@ export function useCopilotChat({
|
|
|
213
214
|
[latestSetMessages],
|
|
214
215
|
);
|
|
215
216
|
|
|
217
|
+
const latestRunChatCompletion = useUpdatedRef(runChatCompletion);
|
|
218
|
+
const latestRunChatCompletionFunc = useAsyncCallback(async () => {
|
|
219
|
+
return await latestRunChatCompletion.current!();
|
|
220
|
+
}, [latestRunChatCompletion]);
|
|
221
|
+
|
|
216
222
|
const reset = useCallback(() => {
|
|
217
223
|
latestStopFunc();
|
|
218
224
|
setMessages([]);
|
|
219
225
|
setThreadId(null);
|
|
220
226
|
setRunId(null);
|
|
221
|
-
|
|
227
|
+
setCoagentStatesWithRef({});
|
|
222
228
|
let initialAgentSession: AgentSession | null = null;
|
|
223
229
|
if (agentLock) {
|
|
224
230
|
initialAgentSession = {
|
|
@@ -226,7 +232,14 @@ export function useCopilotChat({
|
|
|
226
232
|
};
|
|
227
233
|
}
|
|
228
234
|
setAgentSession(initialAgentSession);
|
|
229
|
-
}, [
|
|
235
|
+
}, [
|
|
236
|
+
latestStopFunc,
|
|
237
|
+
setMessages,
|
|
238
|
+
setThreadId,
|
|
239
|
+
setCoagentStatesWithRef,
|
|
240
|
+
setAgentSession,
|
|
241
|
+
agentLock,
|
|
242
|
+
]);
|
|
230
243
|
|
|
231
244
|
const latestReset = useUpdatedRef(reset);
|
|
232
245
|
const latestResetFunc = useCallback(() => {
|
|
@@ -241,6 +254,7 @@ export function useCopilotChat({
|
|
|
241
254
|
stopGeneration: latestStopFunc,
|
|
242
255
|
reset: latestResetFunc,
|
|
243
256
|
deleteMessage: latestDeleteFunc,
|
|
257
|
+
runChatCompletion: latestRunChatCompletionFunc,
|
|
244
258
|
isLoading,
|
|
245
259
|
};
|
|
246
260
|
}
|
|
@@ -5,9 +5,11 @@ import {
|
|
|
5
5
|
} from "@copilotkit/runtime-client-gql";
|
|
6
6
|
import { useToast } from "../components/toast/toast-provider";
|
|
7
7
|
import { useMemo } from "react";
|
|
8
|
+
import { useErrorToast } from "../components/error-boundary/error-utils";
|
|
8
9
|
|
|
9
10
|
export const useCopilotRuntimeClient = (options: CopilotRuntimeClientOptions) => {
|
|
10
11
|
const { addGraphQLErrorsToast } = useToast();
|
|
12
|
+
const addErrorToast = useErrorToast();
|
|
11
13
|
|
|
12
14
|
const runtimeClient = useMemo(() => {
|
|
13
15
|
return new CopilotRuntimeClient({
|
|
@@ -15,6 +17,8 @@ export const useCopilotRuntimeClient = (options: CopilotRuntimeClientOptions) =>
|
|
|
15
17
|
handleGQLErrors: (error) => {
|
|
16
18
|
if ((error as any).graphQLErrors.length) {
|
|
17
19
|
addGraphQLErrorsToast((error as any).graphQLErrors as GraphQLError[]);
|
|
20
|
+
} else {
|
|
21
|
+
addErrorToast([error]);
|
|
18
22
|
}
|
|
19
23
|
},
|
|
20
24
|
});
|
package/src/lib/copilot-task.ts
CHANGED
|
@@ -57,11 +57,9 @@ import {
|
|
|
57
57
|
filterAgentStateMessages,
|
|
58
58
|
CopilotRequestType,
|
|
59
59
|
} from "@copilotkit/runtime-client-gql";
|
|
60
|
-
import { FrontendAction } from "../types/frontend-action";
|
|
60
|
+
import { FrontendAction, processActionsForRuntimeRequest } from "../types/frontend-action";
|
|
61
61
|
import { CopilotContextParams } from "../context";
|
|
62
62
|
import { defaultCopilotContextCategories } from "../components";
|
|
63
|
-
import { MessageStatusCode } from "@copilotkit/runtime-client-gql";
|
|
64
|
-
import { actionParametersToJsonSchema } from "@copilotkit/shared";
|
|
65
63
|
|
|
66
64
|
export interface CopilotTaskConfig {
|
|
67
65
|
/**
|
|
@@ -137,11 +135,7 @@ export class CopilotTask<T = any> {
|
|
|
137
135
|
.generateCopilotResponse({
|
|
138
136
|
data: {
|
|
139
137
|
frontend: {
|
|
140
|
-
actions: Object.values(actions)
|
|
141
|
-
name: action.name,
|
|
142
|
-
description: action.description || "",
|
|
143
|
-
jsonSchema: JSON.stringify(actionParametersToJsonSchema(action.parameters || [])),
|
|
144
|
-
})),
|
|
138
|
+
actions: processActionsForRuntimeRequest(Object.values(actions)),
|
|
145
139
|
url: window.location.href,
|
|
146
140
|
},
|
|
147
141
|
messages: convertMessagesToGqlInput(filterAgentStateMessages(messages)),
|
|
@@ -1,4 +1,10 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { ActionInputAvailability } from "@copilotkit/runtime-client-gql";
|
|
2
|
+
import {
|
|
3
|
+
Action,
|
|
4
|
+
Parameter,
|
|
5
|
+
MappedParameterTypes,
|
|
6
|
+
actionParametersToJsonSchema,
|
|
7
|
+
} from "@copilotkit/shared";
|
|
2
8
|
import React from "react";
|
|
3
9
|
|
|
4
10
|
interface InProgressState<T extends Parameter[] | [] = []> {
|
|
@@ -110,9 +116,24 @@ export type ActionRenderPropsNoArgsWait<T extends Parameter[] | [] = []> =
|
|
|
110
116
|
| ExecutingStateNoArgsWait<T>
|
|
111
117
|
| InProgressStateNoArgsWait<T>;
|
|
112
118
|
|
|
119
|
+
export type CatchAllActionRenderProps<T extends Parameter[] | [] = []> =
|
|
120
|
+
| (CompleteState<T> & {
|
|
121
|
+
name: string;
|
|
122
|
+
})
|
|
123
|
+
| (ExecutingState<T> & {
|
|
124
|
+
name: string;
|
|
125
|
+
})
|
|
126
|
+
| (InProgressState<T> & {
|
|
127
|
+
name: string;
|
|
128
|
+
});
|
|
129
|
+
|
|
113
130
|
export type FrontendActionAvailability = "disabled" | "enabled" | "remote";
|
|
114
131
|
|
|
115
|
-
export type FrontendAction<
|
|
132
|
+
export type FrontendAction<
|
|
133
|
+
T extends Parameter[] | [] = [],
|
|
134
|
+
N extends string = string,
|
|
135
|
+
> = Action<T> & {
|
|
136
|
+
name: Exclude<N, "*">;
|
|
116
137
|
/**
|
|
117
138
|
* @deprecated Use `available` instead.
|
|
118
139
|
*/
|
|
@@ -143,4 +164,36 @@ export type FrontendAction<T extends Parameter[] | [] = []> = Action<T> & {
|
|
|
143
164
|
}
|
|
144
165
|
);
|
|
145
166
|
|
|
167
|
+
export type CatchAllFrontendAction = {
|
|
168
|
+
name: "*";
|
|
169
|
+
render: (props: CatchAllActionRenderProps<any>) => React.ReactElement;
|
|
170
|
+
};
|
|
171
|
+
|
|
146
172
|
export type RenderFunctionStatus = ActionRenderProps<any>["status"];
|
|
173
|
+
|
|
174
|
+
export function processActionsForRuntimeRequest(actions: FrontendAction<any>[]) {
|
|
175
|
+
const filteredActions = actions
|
|
176
|
+
.filter(
|
|
177
|
+
(action) =>
|
|
178
|
+
action.available !== ActionInputAvailability.Disabled &&
|
|
179
|
+
action.disabled !== true &&
|
|
180
|
+
action.name !== "*",
|
|
181
|
+
)
|
|
182
|
+
.map((action) => {
|
|
183
|
+
let available: ActionInputAvailability | undefined = ActionInputAvailability.Enabled;
|
|
184
|
+
if (action.disabled) {
|
|
185
|
+
available = ActionInputAvailability.Disabled;
|
|
186
|
+
} else if (action.available === "disabled") {
|
|
187
|
+
available = ActionInputAvailability.Disabled;
|
|
188
|
+
} else if (action.available === "remote") {
|
|
189
|
+
available = ActionInputAvailability.Remote;
|
|
190
|
+
}
|
|
191
|
+
return {
|
|
192
|
+
name: action.name,
|
|
193
|
+
description: action.description || "",
|
|
194
|
+
jsonSchema: JSON.stringify(actionParametersToJsonSchema(action.parameters || [])),
|
|
195
|
+
available,
|
|
196
|
+
};
|
|
197
|
+
});
|
|
198
|
+
return filteredActions;
|
|
199
|
+
}
|
package/src/types/index.ts
CHANGED
|
@@ -1,4 +1,8 @@
|
|
|
1
1
|
export type { DocumentPointer } from "./document-pointer";
|
|
2
2
|
export type { SystemMessageFunction } from "./system-message";
|
|
3
|
-
export type {
|
|
3
|
+
export type {
|
|
4
|
+
ActionRenderProps,
|
|
5
|
+
RenderFunctionStatus,
|
|
6
|
+
CatchAllActionRenderProps,
|
|
7
|
+
} from "./frontend-action";
|
|
4
8
|
export type { CopilotChatSuggestionConfiguration } from "./chat-suggestion-configuration";
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/context/copilot-context.tsx"],"sourcesContent":["import { CopilotCloudConfig, FunctionCallHandler } from \"@copilotkit/shared\";\nimport { ActionRenderProps, FrontendAction } from \"../types/frontend-action\";\nimport React from \"react\";\nimport { TreeNodeId } from \"../hooks/use-tree\";\nimport { DocumentPointer } from \"../types\";\nimport { CopilotChatSuggestionConfiguration } from \"../types/chat-suggestion-configuration\";\nimport { CoAgentStateRender, CoAgentStateRenderProps } from \"../types/coagent-action\";\nimport { CoagentState } from \"../types/coagent-state\";\nimport { CopilotRuntimeClient } from \"@copilotkit/runtime-client-gql\";\n\n/**\n * Interface for the configuration of the Copilot API.\n */\nexport interface CopilotApiConfig {\n /**\n * The public API key for Copilot Cloud.\n */\n publicApiKey?: string;\n\n /**\n * The configuration for Copilot Cloud.\n */\n cloud?: CopilotCloudConfig;\n\n /**\n * The endpoint for the chat API.\n */\n chatApiEndpoint: string;\n\n /**\n * The endpoint for the Copilot transcribe audio service.\n */\n transcribeAudioUrl?: string;\n\n /**\n * The endpoint for the Copilot text to speech service.\n */\n textToSpeechUrl?: string;\n\n /**\n * additional headers to be sent with the request\n * @default {}\n * @example\n * ```\n * {\n * 'Authorization': 'Bearer your_token_here'\n * }\n * ```\n */\n headers: Record<string, string>;\n\n /**\n * Custom properties to be sent with the request\n * @default {}\n * @example\n * ```\n * {\n * 'user_id': 'user_id'\n * }\n * ```\n */\n properties?: Record<string, any>;\n\n /**\n * Indicates whether the user agent should send or receive cookies from the other domain\n * in the case of cross-origin requests.\n */\n credentials?: RequestCredentials;\n}\n\nexport type InChatRenderFunction = (props: ActionRenderProps<any>) => string | JSX.Element;\nexport type CoagentInChatRenderFunction = (\n props: CoAgentStateRenderProps<any>,\n) => string | JSX.Element | undefined | null;\n\nexport interface ChatComponentsCache {\n actions: Record<string, InChatRenderFunction | string>;\n coAgentStateRenders: Record<string, CoagentInChatRenderFunction | string>;\n}\n\nexport interface AgentSession {\n agentName: string;\n threadId?: string;\n nodeName?: string;\n}\n\nexport interface CopilotContextParams {\n // function-calling\n actions: Record<string, FrontendAction<any>>;\n setAction: (id: string, action: FrontendAction<any>) => void;\n removeAction: (id: string) => void;\n\n // coagent actions\n coAgentStateRenders: Record<string, CoAgentStateRender<any>>;\n setCoAgentStateRender: (id: string, stateRender: CoAgentStateRender<any>) => void;\n removeCoAgentStateRender: (id: string) => void;\n\n chatComponentsCache: React.RefObject<ChatComponentsCache>;\n\n getFunctionCallHandler: (\n customEntryPoints?: Record<string, FrontendAction<any>>,\n ) => FunctionCallHandler;\n\n // text context\n addContext: (context: string, parentId?: string, categories?: string[]) => TreeNodeId;\n removeContext: (id: TreeNodeId) => void;\n getContextString: (documents: DocumentPointer[], categories: string[]) => string;\n\n // document context\n addDocumentContext: (documentPointer: DocumentPointer, categories?: string[]) => TreeNodeId;\n removeDocumentContext: (documentId: string) => void;\n getDocumentsContext: (categories: string[]) => DocumentPointer[];\n\n isLoading: boolean;\n setIsLoading: React.Dispatch<React.SetStateAction<boolean>>;\n\n chatSuggestionConfiguration: { [key: string]: CopilotChatSuggestionConfiguration };\n addChatSuggestionConfiguration: (\n id: string,\n suggestion: CopilotChatSuggestionConfiguration,\n ) => void;\n removeChatSuggestionConfiguration: (id: string) => void;\n\n chatInstructions: string;\n setChatInstructions: React.Dispatch<React.SetStateAction<string>>;\n\n // api endpoints\n copilotApiConfig: CopilotApiConfig;\n\n showDevConsole: boolean | \"auto\";\n\n // agents\n coagentStates: Record<string, CoagentState>;\n setCoagentStates: React.Dispatch<React.SetStateAction<Record<string, CoagentState>>>;\n agentSession: AgentSession | null;\n setAgentSession: React.Dispatch<React.SetStateAction<AgentSession | null>>;\n\n agentLock: string | null;\n\n threadId: string | null;\n setThreadId: React.Dispatch<React.SetStateAction<string | null>>;\n\n runId: string | null;\n setRunId: React.Dispatch<React.SetStateAction<string | null>>;\n\n // The chat abort controller can be used to stop generation globally,\n // i.e. when using `stop()` from `useChat`\n chatAbortControllerRef: React.MutableRefObject<AbortController | null>;\n\n // runtime\n runtimeClient: CopilotRuntimeClient;\n}\n\nconst emptyCopilotContext: CopilotContextParams = {\n actions: {},\n setAction: () => {},\n removeAction: () => {},\n\n coAgentStateRenders: {},\n setCoAgentStateRender: () => {},\n removeCoAgentStateRender: () => {},\n\n chatComponentsCache: { current: { actions: {}, coAgentStateRenders: {} } },\n getContextString: (documents: DocumentPointer[], categories: string[]) =>\n returnAndThrowInDebug(\"\"),\n addContext: () => \"\",\n removeContext: () => {},\n\n getFunctionCallHandler: () => returnAndThrowInDebug(async () => {}),\n\n isLoading: false,\n setIsLoading: () => returnAndThrowInDebug(false),\n\n chatInstructions: \"\",\n setChatInstructions: () => returnAndThrowInDebug(\"\"),\n\n getDocumentsContext: (categories: string[]) => returnAndThrowInDebug([]),\n addDocumentContext: () => returnAndThrowInDebug(\"\"),\n removeDocumentContext: () => {},\n runtimeClient: {} as any,\n\n copilotApiConfig: new (class implements CopilotApiConfig {\n get chatApiEndpoint(): string {\n throw new Error(\"Remember to wrap your app in a `<CopilotKit> {...} </CopilotKit>` !!!\");\n }\n\n get headers(): Record<string, string> {\n return {};\n }\n get body(): Record<string, any> {\n return {};\n }\n })(),\n\n chatSuggestionConfiguration: {},\n addChatSuggestionConfiguration: () => {},\n removeChatSuggestionConfiguration: () => {},\n showDevConsole: \"auto\",\n coagentStates: {},\n setCoagentStates: () => {},\n\n agentSession: null,\n setAgentSession: () => {},\n\n agentLock: null,\n\n threadId: null,\n setThreadId: () => {},\n\n runId: null,\n setRunId: () => {},\n\n chatAbortControllerRef: { current: null },\n};\n\nexport const CopilotContext = React.createContext<CopilotContextParams>(emptyCopilotContext);\n\nexport function useCopilotContext(): CopilotContextParams {\n const context = React.useContext(CopilotContext);\n if (context === emptyCopilotContext) {\n throw new Error(\"Remember to wrap your app in a `<CopilotKit> {...} </CopilotKit>` !!!\");\n }\n return context;\n}\n\nfunction returnAndThrowInDebug<T>(value: T): T {\n throw new Error(\"Remember to wrap your app in a `<CopilotKit> {...} </CopilotKit>` !!!\");\n return value;\n}\n"],"mappings":";;;;;AAEA,OAAO,WAAW;AAuJlB,IAAM,sBAA4C;AAAA,EAChD,SAAS,CAAC;AAAA,EACV,WAAW,MAAM;AAAA,EAAC;AAAA,EAClB,cAAc,MAAM;AAAA,EAAC;AAAA,EAErB,qBAAqB,CAAC;AAAA,EACtB,uBAAuB,MAAM;AAAA,EAAC;AAAA,EAC9B,0BAA0B,MAAM;AAAA,EAAC;AAAA,EAEjC,qBAAqB,EAAE,SAAS,EAAE,SAAS,CAAC,GAAG,qBAAqB,CAAC,EAAE,EAAE;AAAA,EACzE,kBAAkB,CAAC,WAA8B,eAC/C,sBAAsB,EAAE;AAAA,EAC1B,YAAY,MAAM;AAAA,EAClB,eAAe,MAAM;AAAA,EAAC;AAAA,EAEtB,wBAAwB,MAAM,sBAAsB,MAAY;AAAA,EAAC,EAAC;AAAA,EAElE,WAAW;AAAA,EACX,cAAc,MAAM,sBAAsB,KAAK;AAAA,EAE/C,kBAAkB;AAAA,EAClB,qBAAqB,MAAM,sBAAsB,EAAE;AAAA,EAEnD,qBAAqB,CAAC,eAAyB,sBAAsB,CAAC,CAAC;AAAA,EACvE,oBAAoB,MAAM,sBAAsB,EAAE;AAAA,EAClD,uBAAuB,MAAM;AAAA,EAAC;AAAA,EAC9B,eAAe,CAAC;AAAA,EAEhB,kBAAkB,IAAK,MAAkC;AAAA,IACvD,IAAI,kBAA0B;AAC5B,YAAM,IAAI,MAAM,uEAAuE;AAAA,IACzF;AAAA,IAEA,IAAI,UAAkC;AACpC,aAAO,CAAC;AAAA,IACV;AAAA,IACA,IAAI,OAA4B;AAC9B,aAAO,CAAC;AAAA,IACV;AAAA,EACF,EAAG;AAAA,EAEH,6BAA6B,CAAC;AAAA,EAC9B,gCAAgC,MAAM;AAAA,EAAC;AAAA,EACvC,mCAAmC,MAAM;AAAA,EAAC;AAAA,EAC1C,gBAAgB;AAAA,EAChB,eAAe,CAAC;AAAA,EAChB,kBAAkB,MAAM;AAAA,EAAC;AAAA,EAEzB,cAAc;AAAA,EACd,iBAAiB,MAAM;AAAA,EAAC;AAAA,EAExB,WAAW;AAAA,EAEX,UAAU;AAAA,EACV,aAAa,MAAM;AAAA,EAAC;AAAA,EAEpB,OAAO;AAAA,EACP,UAAU,MAAM;AAAA,EAAC;AAAA,EAEjB,wBAAwB,EAAE,SAAS,KAAK;AAC1C;AAEO,IAAM,iBAAiB,MAAM,cAAoC,mBAAmB;AAEpF,SAAS,oBAA0C;AACxD,QAAM,UAAU,MAAM,WAAW,cAAc;AAC/C,MAAI,YAAY,qBAAqB;AACnC,UAAM,IAAI,MAAM,uEAAuE;AAAA,EACzF;AACA,SAAO;AACT;AAEA,SAAS,sBAAyB,OAAa;AAC7C,QAAM,IAAI,MAAM,uEAAuE;AACvF,SAAO;AACT;","names":[]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/components/toast/toast-provider.tsx"],"sourcesContent":["import { useCopilotContext } from \"../../context\";\nimport { GraphQLError } from \"@copilotkit/runtime-client-gql\";\nimport React, { createContext, useContext, useState, useCallback } from \"react\";\nimport { ExclamationMarkIcon } from \"./exclamation-mark-icon\";\n\ninterface Toast {\n id: string;\n message: string | React.ReactNode;\n type: \"info\" | \"success\" | \"warning\" | \"error\";\n duration?: number;\n}\n\ninterface ToastContextValue {\n toasts: Toast[];\n addToast: (toast: Omit<Toast, \"id\">) => void;\n addGraphQLErrorsToast: (errors: GraphQLError[]) => void;\n removeToast: (id: string) => void;\n enabled: boolean;\n}\n\nconst ToastContext = createContext<ToastContextValue | undefined>(undefined);\n\nexport function useToast() {\n const context = useContext(ToastContext);\n if (!context) {\n throw new Error(\"useToast must be used within a ToastProvider\");\n }\n return context;\n}\n\nexport function ToastProvider({\n enabled,\n children,\n}: {\n enabled: boolean;\n children: React.ReactNode;\n}) {\n const [toasts, setToasts] = useState<Toast[]>([]);\n const addToast = useCallback((toast: Omit<Toast, \"id\">) => {\n const id = Math.random().toString(36).substring(2, 9);\n\n setToasts((currentToasts) => [...currentToasts, { ...toast, id }]);\n\n if (toast.duration) {\n setTimeout(() => {\n removeToast(id);\n }, toast.duration);\n }\n }, []);\n\n const addGraphQLErrorsToast = useCallback((errors: GraphQLError[]) => {\n // We do not display these errors unless we are in dev mode.\n // if (!showDevConsole) {\n // return;\n // }\n\n const errorsToRender = errors.map((error, idx) => {\n const message = error.message;\n const code = error.extensions?.code as string;\n\n return (\n <div\n key={idx}\n style={{\n marginTop: idx === 0 ? 0 : 10,\n marginBottom: 14,\n }}\n >\n <ExclamationMarkIcon style={{ marginBottom: 4 }} />\n\n {code && (\n <div\n style={{\n fontWeight: \"600\",\n marginBottom: 4,\n }}\n >\n Copilot Cloud Error:{\" \"}\n <span style={{ fontFamily: \"monospace\", fontWeight: \"normal\" }}>{code}</span>\n </div>\n )}\n <div>{message}</div>\n </div>\n );\n });\n\n addToast({\n type: \"error\",\n message: (\n <div\n style={{\n fontSize: \"13px\",\n maxWidth: \"600px\",\n }}\n >\n {errorsToRender}\n <div style={{ fontSize: \"11px\", opacity: 0.75 }}>\n NOTE: This is a Copilot Cloud error, and it only displays during local development.\n </div>\n </div>\n ),\n });\n }, []);\n\n const removeToast = useCallback((id: string) => {\n setToasts((currentToasts) => currentToasts.filter((toast) => toast.id !== id));\n }, []);\n\n const value = {\n toasts,\n addToast,\n addGraphQLErrorsToast,\n removeToast,\n enabled,\n };\n\n return (\n <ToastContext.Provider value={value}>\n <div\n style={{\n position: \"fixed\",\n bottom: \"1rem\",\n left: \"50%\",\n transform: \"translateX(-50%)\",\n zIndex: 50,\n display: \"flex\",\n flexDirection: \"column\",\n gap: \"0.5rem\",\n }}\n >\n {toasts.length > 1 && (\n <div style={{ textAlign: \"right\" }}>\n <button\n onClick={() => setToasts([])}\n style={{\n padding: \"4px 8px\",\n fontSize: \"12px\",\n cursor: \"pointer\",\n background: \"white\",\n border: \"1px solid rgba(0,0,0,0.2)\",\n borderRadius: \"4px\",\n }}\n >\n Close All\n </button>\n </div>\n )}\n {toasts.map((toast) => (\n <Toast\n key={toast.id}\n message={toast.message}\n type={toast.type}\n onClose={() => removeToast(toast.id)}\n />\n ))}\n </div>\n {children}\n </ToastContext.Provider>\n );\n}\n\nfunction Toast({\n message,\n type = \"info\",\n onClose,\n}: {\n message: string | React.ReactNode;\n type: \"info\" | \"success\" | \"warning\" | \"error\";\n onClose: () => void;\n}) {\n const bgColors = {\n info: \"#3b82f6\",\n success: \"#22c55e\",\n warning: \"#eab308\",\n error: \"#ef4444\",\n };\n\n return (\n <div\n style={{\n backgroundColor: bgColors[type],\n color: \"white\",\n padding: \"0.5rem 1rem\",\n borderRadius: \"0.25rem\",\n boxShadow: \"0 2px 4px rgba(0,0,0,0.1)\",\n position: \"relative\",\n minWidth: \"200px\",\n }}\n >\n <div>{message}</div>\n <button\n onClick={onClose}\n style={{\n position: \"absolute\",\n top: \"0\",\n right: \"0\",\n background: \"none\",\n border: \"none\",\n color: \"white\",\n cursor: \"pointer\",\n padding: \"0.5rem\",\n fontSize: \"1rem\",\n }}\n >\n ✕\n </button>\n </div>\n );\n}\n"],"mappings":";;;;;;;;;AAEA,SAAgB,eAAe,YAAY,UAAU,mBAAmB;AAkE9D,cAGE,YAHF;AAhDV,IAAM,eAAe,cAA6C,MAAS;AAEpE,SAAS,WAAW;AACzB,QAAM,UAAU,WAAW,YAAY;AACvC,MAAI,CAAC,SAAS;AACZ,UAAM,IAAI,MAAM,8CAA8C;AAAA,EAChE;AACA,SAAO;AACT;AAEO,SAAS,cAAc;AAAA,EAC5B;AAAA,EACA;AACF,GAGG;AACD,QAAM,CAAC,QAAQ,SAAS,IAAI,SAAkB,CAAC,CAAC;AAChD,QAAM,WAAW,YAAY,CAAC,UAA6B;AACzD,UAAM,KAAK,KAAK,OAAO,EAAE,SAAS,EAAE,EAAE,UAAU,GAAG,CAAC;AAEpD,cAAU,CAAC,kBAAkB,CAAC,GAAG,eAAe,iCAAK,QAAL,EAAY,GAAG,EAAC,CAAC;AAEjE,QAAI,MAAM,UAAU;AAClB,iBAAW,MAAM;AACf,oBAAY,EAAE;AAAA,MAChB,GAAG,MAAM,QAAQ;AAAA,IACnB;AAAA,EACF,GAAG,CAAC,CAAC;AAEL,QAAM,wBAAwB,YAAY,CAAC,WAA2B;AAMpE,UAAM,iBAAiB,OAAO,IAAI,CAAC,OAAO,QAAQ;AAxDtD;AAyDM,YAAM,UAAU,MAAM;AACtB,YAAM,QAAO,WAAM,eAAN,mBAAkB;AAE/B,aACE;AAAA,QAAC;AAAA;AAAA,UAEC,OAAO;AAAA,YACL,WAAW,QAAQ,IAAI,IAAI;AAAA,YAC3B,cAAc;AAAA,UAChB;AAAA,UAEA;AAAA,gCAAC,uBAAoB,OAAO,EAAE,cAAc,EAAE,GAAG;AAAA,YAEhD,QACC;AAAA,cAAC;AAAA;AAAA,gBACC,OAAO;AAAA,kBACL,YAAY;AAAA,kBACZ,cAAc;AAAA,gBAChB;AAAA,gBACD;AAAA;AAAA,kBACsB;AAAA,kBACrB,oBAAC,UAAK,OAAO,EAAE,YAAY,aAAa,YAAY,SAAS,GAAI,gBAAK;AAAA;AAAA;AAAA,YACxE;AAAA,YAEF,oBAAC,SAAK,mBAAQ;AAAA;AAAA;AAAA,QAnBT;AAAA,MAoBP;AAAA,IAEJ,CAAC;AAED,aAAS;AAAA,MACP,MAAM;AAAA,MACN,SACE;AAAA,QAAC;AAAA;AAAA,UACC,OAAO;AAAA,YACL,UAAU;AAAA,YACV,UAAU;AAAA,UACZ;AAAA,UAEC;AAAA;AAAA,YACD,oBAAC,SAAI,OAAO,EAAE,UAAU,QAAQ,SAAS,KAAK,GAAG,iGAEjD;AAAA;AAAA;AAAA,MACF;AAAA,IAEJ,CAAC;AAAA,EACH,GAAG,CAAC,CAAC;AAEL,QAAM,cAAc,YAAY,CAAC,OAAe;AAC9C,cAAU,CAAC,kBAAkB,cAAc,OAAO,CAAC,UAAU,MAAM,OAAO,EAAE,CAAC;AAAA,EAC/E,GAAG,CAAC,CAAC;AAEL,QAAM,QAAQ;AAAA,IACZ;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AAEA,SACE,qBAAC,aAAa,UAAb,EAAsB,OACrB;AAAA;AAAA,MAAC;AAAA;AAAA,QACC,OAAO;AAAA,UACL,UAAU;AAAA,UACV,QAAQ;AAAA,UACR,MAAM;AAAA,UACN,WAAW;AAAA,UACX,QAAQ;AAAA,UACR,SAAS;AAAA,UACT,eAAe;AAAA,UACf,KAAK;AAAA,QACP;AAAA,QAEC;AAAA,iBAAO,SAAS,KACf,oBAAC,SAAI,OAAO,EAAE,WAAW,QAAQ,GAC/B;AAAA,YAAC;AAAA;AAAA,cACC,SAAS,MAAM,UAAU,CAAC,CAAC;AAAA,cAC3B,OAAO;AAAA,gBACL,SAAS;AAAA,gBACT,UAAU;AAAA,gBACV,QAAQ;AAAA,gBACR,YAAY;AAAA,gBACZ,QAAQ;AAAA,gBACR,cAAc;AAAA,cAChB;AAAA,cACD;AAAA;AAAA,UAED,GACF;AAAA,UAED,OAAO,IAAI,CAAC,UACX;AAAA,YAAC;AAAA;AAAA,cAEC,SAAS,MAAM;AAAA,cACf,MAAM,MAAM;AAAA,cACZ,SAAS,MAAM,YAAY,MAAM,EAAE;AAAA;AAAA,YAH9B,MAAM;AAAA,UAIb,CACD;AAAA;AAAA;AAAA,IACH;AAAA,IACC;AAAA,KACH;AAEJ;AAEA,SAAS,MAAM;AAAA,EACb;AAAA,EACA,OAAO;AAAA,EACP;AACF,GAIG;AACD,QAAM,WAAW;AAAA,IACf,MAAM;AAAA,IACN,SAAS;AAAA,IACT,SAAS;AAAA,IACT,OAAO;AAAA,EACT;AAEA,SACE;AAAA,IAAC;AAAA;AAAA,MACC,OAAO;AAAA,QACL,iBAAiB,SAAS,IAAI;AAAA,QAC9B,OAAO;AAAA,QACP,SAAS;AAAA,QACT,cAAc;AAAA,QACd,WAAW;AAAA,QACX,UAAU;AAAA,QACV,UAAU;AAAA,MACZ;AAAA,MAEA;AAAA,4BAAC,SAAK,mBAAQ;AAAA,QACd;AAAA,UAAC;AAAA;AAAA,YACC,SAAS;AAAA,YACT,OAAO;AAAA,cACL,UAAU;AAAA,cACV,KAAK;AAAA,cACL,OAAO;AAAA,cACP,YAAY;AAAA,cACZ,QAAQ;AAAA,cACR,OAAO;AAAA,cACP,QAAQ;AAAA,cACR,SAAS;AAAA,cACT,UAAU;AAAA,YACZ;AAAA,YACD;AAAA;AAAA,QAED;AAAA;AAAA;AAAA,EACF;AAEJ;","names":[]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/hooks/use-copilot-action.ts"],"sourcesContent":["/**\n * Example usage of useCopilotAction with complex parameters:\n *\n * @example\n * useCopilotAction({\n * name: \"myAction\",\n * parameters: [\n * { name: \"arg1\", type: \"string\", enum: [\"option1\", \"option2\", \"option3\"], required: false },\n * { name: \"arg2\", type: \"number\" },\n * {\n * name: \"arg3\",\n * type: \"object\",\n * attributes: [\n * { name: \"nestedArg1\", type: \"boolean\" },\n * { name: \"xyz\", required: false },\n * ],\n * },\n * { name: \"arg4\", type: \"number[]\" },\n * ],\n * handler: ({ arg1, arg2, arg3, arg4 }) => {\n * const x = arg3.nestedArg1;\n * const z = arg3.xyz;\n * console.log(arg1, arg2, arg3);\n * },\n * });\n *\n * @example\n * // Simple action without parameters\n * useCopilotAction({\n * name: \"myAction\",\n * handler: () => {\n * console.log(\"No parameters provided.\");\n * },\n * });\n *\n * @example\n * // Interactive action with UI rendering and response handling\n * useCopilotAction({\n * name: \"handleMeeting\",\n * description: \"Handle a meeting by booking or canceling\",\n * parameters: [\n * {\n * name: \"meeting\",\n * type: \"string\",\n * description: \"The meeting to handle\",\n * required: true,\n * },\n * {\n * name: \"date\",\n * type: \"string\",\n * description: \"The date of the meeting\",\n * required: true,\n * },\n * {\n * name: \"title\",\n * type: \"string\",\n * description: \"The title of the meeting\",\n * required: true,\n * },\n * ],\n * renderAndWaitForResponse: ({ args, respond, status }) => {\n * const { meeting, date, title } = args;\n * return (\n * <MeetingConfirmationDialog\n * meeting={meeting}\n * date={date}\n * title={title}\n * onConfirm={() => respond('meeting confirmed')}\n * onCancel={() => respond('meeting canceled')}\n * />\n * );\n * },\n * });\n */\n\n/**\n * <img src=\"/images/use-copilot-action/useCopilotAction.gif\" width=\"500\" />\n * `useCopilotAction` is a React hook that you can use in your application to provide\n * custom actions that can be called by the AI. Essentially, it allows the Copilot to\n * execute these actions contextually during a chat, based on the user's interactions\n * and needs.\n *\n * Here's how it works:\n *\n * Use `useCopilotAction` to set up actions that the Copilot can call. To provide\n * more context to the Copilot, you can provide it with a `description` (for example to explain\n * what the action does, under which conditions it can be called, etc.).\n *\n * Then you define the parameters of the action, which can be simple, e.g. primitives like strings or numbers,\n * or complex, e.g. objects or arrays.\n *\n * Finally, you provide a `handler` function that receives the parameters and returns a result.\n * CopilotKit takes care of automatically inferring the parameter types, so you get type safety\n * and autocompletion for free.\n *\n * To render a custom UI for the action, you can provide a `render()` function. This function\n * lets you render a custom component or return a string to display.\n *\n * ## Usage\n *\n * ### Simple Usage\n *\n * ```tsx\n * useCopilotAction({\n * name: \"sayHello\",\n * description: \"Say hello to someone.\",\n * parameters: [\n * {\n * name: \"name\",\n * type: \"string\",\n * description: \"name of the person to say greet\",\n * },\n * ],\n * handler: async ({ name }) => {\n * alert(`Hello, ${name}!`);\n * },\n * });\n * ```\n *\n * ## Generative UI\n *\n * This hooks enables you to dynamically generate UI elements and render them in the copilot chat. For more information, check out the [Generative UI](/guides/generative-ui) page.\n */\nimport { Parameter, randomId } from \"@copilotkit/shared\";\nimport { createElement, Fragment, useEffect, useRef } from \"react\";\nimport { useCopilotContext } from \"../context/copilot-context\";\nimport {\n ActionRenderProps,\n ActionRenderPropsNoArgsWait,\n ActionRenderPropsWait,\n FrontendAction,\n} from \"../types/frontend-action\";\n\n// We implement useCopilotAction dependency handling so that\n// the developer has the option to not provide any dependencies.\n// In this case, we assume they want to update the handler on each rerender.\n// To avoid getting stuck in an infinite loop, we update the handler directly,\n// skipping React state updates.\n// This is ok in this case, because the handler is not part of any UI that\n// needs to be updated.\n// useCallback, useMemo or other memoization techniques are not suitable here,\n// because they will cause a infinite rerender loop.\nexport function useCopilotAction<const T extends Parameter[] | [] = []>(\n action: FrontendAction<T>,\n dependencies?: any[],\n): void {\n const { setAction, removeAction, actions, chatComponentsCache } = useCopilotContext();\n const idRef = useRef<string>(randomId());\n const renderAndWaitRef = useRef<RenderAndWaitForResponse | null>(null);\n\n // clone the action to avoid mutating the original object\n action = { ...action };\n\n // If the developer provides a renderAndWait function, we transform the action\n // to use a promise internally, so that we can treat it like a normal action.\n if (action.renderAndWait || action.renderAndWaitForResponse) {\n const renderAndWait = action.renderAndWait || action.renderAndWaitForResponse;\n // remove the renderAndWait function from the action\n action.renderAndWait = undefined;\n action.renderAndWaitForResponse = undefined;\n // add a handler that will be called when the action is executed\n action.handler = (async () => {\n // we create a new promise when the handler is called\n let resolve: (result: any) => void;\n let reject: (error: any) => void;\n const promise = new Promise<any>((resolvePromise, rejectPromise) => {\n resolve = resolvePromise;\n reject = rejectPromise;\n });\n renderAndWaitRef.current = { promise, resolve: resolve!, reject: reject! };\n // then we await the promise (it will be resolved in the original renderAndWait function)\n return await promise;\n }) as any;\n\n // add a render function that will be called when the action is rendered\n action.render = ((props: ActionRenderProps<T>): React.ReactElement => {\n // Create type safe waitProps based on whether T extends empty array or not\n const waitProps = {\n status: props.status,\n args: props.args,\n result: props.result,\n handler: props.status === \"executing\" ? renderAndWaitRef.current!.resolve : undefined,\n respond: props.status === \"executing\" ? renderAndWaitRef.current!.resolve : undefined,\n } as T extends [] ? ActionRenderPropsNoArgsWait<T> : ActionRenderPropsWait<T>;\n\n // Type guard to check if renderAndWait is for no args case\n const isNoArgsRenderWait = (\n _fn:\n | ((props: ActionRenderPropsNoArgsWait<T>) => React.ReactElement)\n | ((props: ActionRenderPropsWait<T>) => React.ReactElement),\n ): _fn is (props: ActionRenderPropsNoArgsWait<T>) => React.ReactElement => {\n return action.parameters?.length === 0;\n };\n\n // Safely call renderAndWait with correct props type\n if (renderAndWait) {\n if (isNoArgsRenderWait(renderAndWait)) {\n return renderAndWait(waitProps as ActionRenderPropsNoArgsWait<T>);\n } else {\n return renderAndWait(waitProps as ActionRenderPropsWait<T>);\n }\n }\n\n // Return empty Fragment instead of null\n return createElement(Fragment);\n }) as any;\n }\n\n // If the developer doesn't provide dependencies, we assume they want to\n // update handler and render function when the action object changes.\n // This ensures that any captured variables in the handler are up to date.\n if (dependencies === undefined) {\n if (actions[idRef.current]) {\n actions[idRef.current].handler = action.handler as any;\n if (typeof action.render === \"function\") {\n if (chatComponentsCache.current !== null) {\n chatComponentsCache.current.actions[action.name] = action.render;\n }\n }\n }\n }\n\n useEffect(() => {\n setAction(idRef.current, action as any);\n if (chatComponentsCache.current !== null && action.render !== undefined) {\n chatComponentsCache.current.actions[action.name] = action.render;\n }\n return () => {\n // NOTE: For now, we don't remove the chatComponentsCache entry when the action is removed.\n // This is because we currently don't have access to the messages array in CopilotContext.\n removeAction(idRef.current);\n };\n }, [\n setAction,\n removeAction,\n action.description,\n action.name,\n action.disabled,\n action.available,\n // This should be faster than deep equality checking\n // In addition, all major JS engines guarantee the order of object keys\n JSON.stringify(action.parameters),\n // include render only if it's a string\n typeof action.render === \"string\" ? action.render : undefined,\n // dependencies set by the developer\n ...(dependencies || []),\n ]);\n}\n\ninterface RenderAndWaitForResponse {\n promise: Promise<any>;\n resolve: (result: any) => void;\n reject: (error: any) => void;\n}\n"],"mappings":";;;;;;;;;AA2HA,SAAoB,gBAAgB;AACpC,SAAS,eAAe,UAAU,WAAW,cAAc;AAkBpD,SAAS,iBACd,QACA,cACM;AACN,QAAM,EAAE,WAAW,cAAc,SAAS,oBAAoB,IAAI,kBAAkB;AACpF,QAAM,QAAQ,OAAe,SAAS,CAAC;AACvC,QAAM,mBAAmB,OAAwC,IAAI;AAGrE,WAAS,mBAAK;AAId,MAAI,OAAO,iBAAiB,OAAO,0BAA0B;AAC3D,UAAM,gBAAgB,OAAO,iBAAiB,OAAO;AAErD,WAAO,gBAAgB;AACvB,WAAO,2BAA2B;AAElC,WAAO,UAAW,MAAY;AAE5B,UAAI;AACJ,UAAI;AACJ,YAAM,UAAU,IAAI,QAAa,CAAC,gBAAgB,kBAAkB;AAClE,kBAAU;AACV,iBAAS;AAAA,MACX,CAAC;AACD,uBAAiB,UAAU,EAAE,SAAS,SAAmB,OAAgB;AAEzE,aAAO,MAAM;AAAA,IACf;AAGA,WAAO,SAAU,CAAC,UAAoD;AAEpE,YAAM,YAAY;AAAA,QAChB,QAAQ,MAAM;AAAA,QACd,MAAM,MAAM;AAAA,QACZ,QAAQ,MAAM;AAAA,QACd,SAAS,MAAM,WAAW,cAAc,iBAAiB,QAAS,UAAU;AAAA,QAC5E,SAAS,MAAM,WAAW,cAAc,iBAAiB,QAAS,UAAU;AAAA,MAC9E;AAGA,YAAM,qBAAqB,CACzB,QAGyE;AA9LjF;AA+LQ,iBAAO,YAAO,eAAP,mBAAmB,YAAW;AAAA,MACvC;AAGA,UAAI,eAAe;AACjB,YAAI,mBAAmB,aAAa,GAAG;AACrC,iBAAO,cAAc,SAA2C;AAAA,QAClE,OAAO;AACL,iBAAO,cAAc,SAAqC;AAAA,QAC5D;AAAA,MACF;AAGA,aAAO,cAAc,QAAQ;AAAA,IAC/B;AAAA,EACF;AAKA,MAAI,iBAAiB,QAAW;AAC9B,QAAI,QAAQ,MAAM,OAAO,GAAG;AAC1B,cAAQ,MAAM,OAAO,EAAE,UAAU,OAAO;AACxC,UAAI,OAAO,OAAO,WAAW,YAAY;AACvC,YAAI,oBAAoB,YAAY,MAAM;AACxC,8BAAoB,QAAQ,QAAQ,OAAO,IAAI,IAAI,OAAO;AAAA,QAC5D;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAEA,YAAU,MAAM;AACd,cAAU,MAAM,SAAS,MAAa;AACtC,QAAI,oBAAoB,YAAY,QAAQ,OAAO,WAAW,QAAW;AACvE,0BAAoB,QAAQ,QAAQ,OAAO,IAAI,IAAI,OAAO;AAAA,IAC5D;AACA,WAAO,MAAM;AAGX,mBAAa,MAAM,OAAO;AAAA,IAC5B;AAAA,EACF,GAAG;AAAA,IACD;AAAA,IACA;AAAA,IACA,OAAO;AAAA,IACP,OAAO;AAAA,IACP,OAAO;AAAA,IACP,OAAO;AAAA;AAAA;AAAA,IAGP,KAAK,UAAU,OAAO,UAAU;AAAA;AAAA,IAEhC,OAAO,OAAO,WAAW,WAAW,OAAO,SAAS;AAAA;AAAA,IAEpD,GAAI,gBAAgB,CAAC;AAAA,EACvB,CAAC;AACH;","names":[]}
|