@copilotkit/react-core 1.9.2-next.8 → 1.9.2
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 +193 -0
- package/dist/{chunk-ERXWDCY6.mjs → chunk-36MGCCPZ.mjs} +2 -2
- package/dist/{chunk-CCESTGAM.mjs → chunk-3OQM3NEK.mjs} +2 -2
- package/dist/{chunk-7G6RR4HE.mjs → chunk-3Q4F7RF2.mjs} +2 -2
- package/dist/chunk-57K2ZJ5F.mjs +348 -0
- package/dist/chunk-57K2ZJ5F.mjs.map +1 -0
- package/dist/{chunk-UBNRUXEK.mjs → chunk-5BSUSFHM.mjs} +2 -2
- package/dist/{chunk-RN3ZRHI7.mjs → chunk-AD7DWJNW.mjs} +66 -25
- package/dist/chunk-AD7DWJNW.mjs.map +1 -0
- package/dist/{chunk-JPMIAGI6.mjs → chunk-BVK7PLK6.mjs} +2 -2
- package/dist/{chunk-VJCHRQ7Q.mjs → chunk-DGON3GZX.mjs} +39 -6
- package/dist/chunk-DGON3GZX.mjs.map +1 -0
- package/dist/{chunk-XFOTNHYA.mjs → chunk-DKZTPL66.mjs} +2 -2
- package/dist/{chunk-XFOTNHYA.mjs.map → chunk-DKZTPL66.mjs.map} +1 -1
- package/dist/{chunk-S4BOATBG.mjs → chunk-FN3UA2ZE.mjs} +3 -3
- package/dist/{chunk-ISYBUDL4.mjs → chunk-JWAXDYOW.mjs} +11 -12
- package/dist/chunk-JWAXDYOW.mjs.map +1 -0
- package/dist/{chunk-T4ZKC4X4.mjs → chunk-KIXKBJUV.mjs} +3 -3
- package/dist/{chunk-I4JPQECN.mjs → chunk-LFAZTKBK.mjs} +5 -5
- package/dist/{chunk-JHIZ5HAI.mjs → chunk-NJA5ZLAZ.mjs} +29 -10
- package/dist/chunk-NJA5ZLAZ.mjs.map +1 -0
- package/dist/{chunk-ZHEEHGLS.mjs → chunk-QGT4JO7R.mjs} +35 -6
- package/dist/chunk-QGT4JO7R.mjs.map +1 -0
- package/dist/{chunk-JXF732XG.mjs → chunk-S5QUEHJC.mjs} +195 -77
- package/dist/chunk-S5QUEHJC.mjs.map +1 -0
- package/dist/{chunk-QQZLIEXK.mjs → chunk-SJJNFYGQ.mjs} +3 -3
- package/dist/{chunk-CMQV4XNY.mjs → chunk-VDADWRS3.mjs} +2 -2
- package/dist/chunk-YAF2LATQ.mjs +310 -0
- package/dist/chunk-YAF2LATQ.mjs.map +1 -0
- package/dist/{chunk-VF6UPRKM.mjs → chunk-ZGMZ5WJI.mjs} +4 -4
- package/dist/components/copilot-provider/copilot-messages.js +37 -4
- package/dist/components/copilot-provider/copilot-messages.js.map +1 -1
- package/dist/components/copilot-provider/copilot-messages.mjs +3 -3
- package/dist/components/copilot-provider/copilotkit-props.d.ts +14 -9
- package/dist/components/copilot-provider/copilotkit-props.js.map +1 -1
- package/dist/components/copilot-provider/copilotkit.d.ts +1 -1
- package/dist/components/copilot-provider/copilotkit.js +354 -258
- package/dist/components/copilot-provider/copilotkit.js.map +1 -1
- package/dist/components/copilot-provider/copilotkit.mjs +10 -10
- package/dist/components/copilot-provider/index.d.ts +1 -1
- package/dist/components/copilot-provider/index.js +354 -258
- package/dist/components/copilot-provider/index.js.map +1 -1
- package/dist/components/copilot-provider/index.mjs +10 -10
- package/dist/components/error-boundary/error-boundary.js +135 -146
- package/dist/components/error-boundary/error-boundary.js.map +1 -1
- package/dist/components/error-boundary/error-boundary.mjs +4 -4
- package/dist/components/error-boundary/error-utils.js.map +1 -1
- package/dist/components/error-boundary/error-utils.mjs +2 -2
- package/dist/components/index.d.ts +1 -1
- package/dist/components/index.js +354 -258
- package/dist/components/index.js.map +1 -1
- package/dist/components/index.mjs +10 -10
- package/dist/components/toast/toast-provider.js +118 -85
- package/dist/components/toast/toast-provider.js.map +1 -1
- package/dist/components/toast/toast-provider.mjs +1 -1
- package/dist/components/usage-banner.js +135 -146
- package/dist/components/usage-banner.js.map +1 -1
- package/dist/components/usage-banner.mjs +1 -1
- package/dist/context/copilot-context.d.ts +1 -1
- package/dist/context/copilot-context.js +1 -1
- 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 +1 -1
- package/dist/context/index.js.map +1 -1
- package/dist/context/index.mjs +1 -1
- package/dist/{copilot-context-3da805ab.d.ts → copilot-context-3ab4fdf5.d.ts} +3 -3
- package/dist/hooks/index.d.ts +1 -1
- package/dist/hooks/index.js +249 -88
- package/dist/hooks/index.js.map +1 -1
- package/dist/hooks/index.mjs +32 -32
- package/dist/hooks/use-chat.d.ts +1 -1
- package/dist/hooks/use-chat.js +287 -174
- package/dist/hooks/use-chat.js.map +1 -1
- package/dist/hooks/use-chat.mjs +5 -5
- package/dist/hooks/use-coagent-state-render.js +1 -1
- package/dist/hooks/use-coagent-state-render.js.map +1 -1
- package/dist/hooks/use-coagent-state-render.mjs +3 -3
- package/dist/hooks/use-coagent.d.ts +1 -1
- package/dist/hooks/use-coagent.js +224 -82
- package/dist/hooks/use-coagent.js.map +1 -1
- package/dist/hooks/use-coagent.mjs +14 -14
- package/dist/hooks/use-copilot-action.js +26 -7
- package/dist/hooks/use-copilot-action.js.map +1 -1
- package/dist/hooks/use-copilot-action.mjs +4 -4
- package/dist/hooks/use-copilot-additional-instructions.js +1 -1
- package/dist/hooks/use-copilot-additional-instructions.js.map +1 -1
- package/dist/hooks/use-copilot-additional-instructions.mjs +2 -2
- package/dist/hooks/use-copilot-authenticated-action.js +26 -7
- package/dist/hooks/use-copilot-authenticated-action.js.map +1 -1
- package/dist/hooks/use-copilot-authenticated-action.mjs +5 -5
- package/dist/hooks/use-copilot-chat.d.ts +1 -1
- package/dist/hooks/use-copilot-chat.js +195 -82
- package/dist/hooks/use-copilot-chat.js.map +1 -1
- package/dist/hooks/use-copilot-chat.mjs +13 -13
- package/dist/hooks/use-copilot-readable.js +1 -1
- 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.d.ts +2 -2
- package/dist/hooks/use-copilot-runtime-client.js +8 -8
- 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-langgraph-interrupt-render.js +1 -1
- package/dist/hooks/use-langgraph-interrupt-render.js.map +1 -1
- package/dist/hooks/use-langgraph-interrupt-render.mjs +2 -2
- package/dist/hooks/use-langgraph-interrupt.d.ts +1 -1
- package/dist/hooks/use-langgraph-interrupt.js +195 -82
- package/dist/hooks/use-langgraph-interrupt.js.map +1 -1
- package/dist/hooks/use-langgraph-interrupt.mjs +14 -14
- package/dist/hooks/use-make-copilot-document-readable.js +1 -1
- 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 +593 -336
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +33 -33
- package/dist/lib/copilot-task.d.ts +1 -1
- package/dist/lib/copilot-task.js.map +1 -1
- package/dist/lib/copilot-task.mjs +11 -11
- package/dist/lib/index.d.ts +1 -1
- package/dist/lib/index.js.map +1 -1
- package/dist/lib/index.mjs +11 -11
- package/dist/setupTests.d.ts +2 -0
- package/dist/setupTests.js +26 -0
- package/dist/setupTests.js.map +1 -0
- package/dist/setupTests.mjs +24 -0
- package/dist/setupTests.mjs.map +1 -0
- package/dist/types/interrupt-action.d.ts +1 -1
- package/dist/utils/extract.d.ts +1 -1
- package/dist/utils/extract.js.map +1 -1
- package/dist/utils/extract.mjs +10 -10
- package/dist/utils/index.d.ts +1 -1
- package/dist/utils/index.js.map +1 -1
- package/dist/utils/index.mjs +10 -10
- package/jest.config.js +4 -0
- package/package.json +6 -3
- package/src/components/copilot-provider/__tests__/{copilotkit-trace.test.tsx → copilotkit-error.test.tsx} +17 -17
- package/src/components/copilot-provider/copilot-messages.tsx +43 -4
- package/src/components/copilot-provider/copilotkit-props.tsx +13 -8
- package/src/components/copilot-provider/copilotkit.tsx +61 -19
- package/src/components/toast/toast-provider.tsx +49 -24
- package/src/components/usage-banner.tsx +144 -147
- package/src/context/copilot-context.tsx +4 -4
- package/src/hooks/__tests__/use-coagent-config.test.ts +284 -0
- package/src/hooks/use-chat.ts +249 -61
- package/src/hooks/use-coagent.ts +41 -0
- package/src/hooks/use-copilot-action.ts +51 -9
- package/src/hooks/use-copilot-runtime-client.ts +12 -50
- package/src/setupTests.ts +26 -0
- package/tsconfig.json +5 -2
- package/dist/chunk-HD2GE3DK.mjs +0 -359
- package/dist/chunk-HD2GE3DK.mjs.map +0 -1
- package/dist/chunk-ISYBUDL4.mjs.map +0 -1
- package/dist/chunk-JHIZ5HAI.mjs.map +0 -1
- package/dist/chunk-JXF732XG.mjs.map +0 -1
- package/dist/chunk-RN3ZRHI7.mjs.map +0 -1
- package/dist/chunk-VJCHRQ7Q.mjs.map +0 -1
- package/dist/chunk-VRXANACV.mjs +0 -277
- package/dist/chunk-VRXANACV.mjs.map +0 -1
- package/dist/chunk-ZHEEHGLS.mjs.map +0 -1
- /package/dist/{chunk-ERXWDCY6.mjs.map → chunk-36MGCCPZ.mjs.map} +0 -0
- /package/dist/{chunk-CCESTGAM.mjs.map → chunk-3OQM3NEK.mjs.map} +0 -0
- /package/dist/{chunk-7G6RR4HE.mjs.map → chunk-3Q4F7RF2.mjs.map} +0 -0
- /package/dist/{chunk-UBNRUXEK.mjs.map → chunk-5BSUSFHM.mjs.map} +0 -0
- /package/dist/{chunk-JPMIAGI6.mjs.map → chunk-BVK7PLK6.mjs.map} +0 -0
- /package/dist/{chunk-S4BOATBG.mjs.map → chunk-FN3UA2ZE.mjs.map} +0 -0
- /package/dist/{chunk-T4ZKC4X4.mjs.map → chunk-KIXKBJUV.mjs.map} +0 -0
- /package/dist/{chunk-I4JPQECN.mjs.map → chunk-LFAZTKBK.mjs.map} +0 -0
- /package/dist/{chunk-QQZLIEXK.mjs.map → chunk-SJJNFYGQ.mjs.map} +0 -0
- /package/dist/{chunk-CMQV4XNY.mjs.map → chunk-VDADWRS3.mjs.map} +0 -0
- /package/dist/{chunk-VF6UPRKM.mjs.map → chunk-ZGMZ5WJI.mjs.map} +0 -0
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import {
|
|
2
2
|
useAsyncCallback
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-3OQM3NEK.mjs";
|
|
4
4
|
import {
|
|
5
5
|
useToast
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-YAF2LATQ.mjs";
|
|
7
7
|
import {
|
|
8
8
|
useCopilotContext
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-DKZTPL66.mjs";
|
|
10
10
|
import {
|
|
11
11
|
__async,
|
|
12
12
|
__spreadValues
|
|
@@ -19,6 +19,7 @@ function useCopilotAction(action, dependencies) {
|
|
|
19
19
|
const { setAction, removeAction, actions, chatComponentsCache } = useCopilotContext();
|
|
20
20
|
const idRef = useRef(randomId());
|
|
21
21
|
const renderAndWaitRef = useRef(null);
|
|
22
|
+
const activatingMessageIdRef = useRef(null);
|
|
22
23
|
const { addToast } = useToast();
|
|
23
24
|
action = __spreadValues({}, action);
|
|
24
25
|
if (
|
|
@@ -26,30 +27,48 @@ function useCopilotAction(action, dependencies) {
|
|
|
26
27
|
isFrontendAction(action) && // check if renderAndWaitForResponse is set
|
|
27
28
|
(action.renderAndWait || action.renderAndWaitForResponse)
|
|
28
29
|
) {
|
|
30
|
+
action._isRenderAndWait = true;
|
|
29
31
|
const renderAndWait = action.renderAndWait || action.renderAndWaitForResponse;
|
|
30
32
|
action.renderAndWait = void 0;
|
|
31
33
|
action.renderAndWaitForResponse = void 0;
|
|
34
|
+
action._setActivatingMessageId = (id) => {
|
|
35
|
+
activatingMessageIdRef.current = id;
|
|
36
|
+
};
|
|
32
37
|
action.handler = useAsyncCallback(() => __async(this, null, function* () {
|
|
38
|
+
const currentActivatingId = activatingMessageIdRef.current;
|
|
33
39
|
let resolve;
|
|
34
40
|
let reject;
|
|
35
41
|
const promise = new Promise((resolvePromise, rejectPromise) => {
|
|
36
42
|
resolve = resolvePromise;
|
|
37
43
|
reject = rejectPromise;
|
|
38
44
|
});
|
|
39
|
-
renderAndWaitRef.current = {
|
|
40
|
-
|
|
45
|
+
renderAndWaitRef.current = {
|
|
46
|
+
promise,
|
|
47
|
+
resolve,
|
|
48
|
+
reject,
|
|
49
|
+
messageId: currentActivatingId
|
|
50
|
+
};
|
|
51
|
+
const result = yield promise;
|
|
52
|
+
return result;
|
|
41
53
|
}), []);
|
|
42
54
|
action.render = (props) => {
|
|
55
|
+
const currentRenderMessageId = props.messageId;
|
|
43
56
|
let status = props.status;
|
|
44
|
-
if (props.status === "executing"
|
|
45
|
-
|
|
57
|
+
if (props.status === "executing") {
|
|
58
|
+
if (!renderAndWaitRef.current || !renderAndWaitRef.current.promise) {
|
|
59
|
+
status = "inProgress";
|
|
60
|
+
} else if (renderAndWaitRef.current.messageId !== currentRenderMessageId && activatingMessageIdRef.current !== currentRenderMessageId) {
|
|
61
|
+
status = "inProgress";
|
|
62
|
+
}
|
|
46
63
|
}
|
|
47
64
|
const waitProps = {
|
|
48
65
|
status,
|
|
49
66
|
args: props.args,
|
|
50
67
|
result: props.result,
|
|
51
|
-
handler
|
|
52
|
-
|
|
68
|
+
// handler and respond should only be provided if this is the truly active instance
|
|
69
|
+
// and its promise infrastructure is ready.
|
|
70
|
+
handler: status === "executing" && renderAndWaitRef.current && renderAndWaitRef.current.messageId === currentRenderMessageId ? renderAndWaitRef.current.resolve : void 0,
|
|
71
|
+
respond: status === "executing" && renderAndWaitRef.current && renderAndWaitRef.current.messageId === currentRenderMessageId ? renderAndWaitRef.current.resolve : void 0
|
|
53
72
|
};
|
|
54
73
|
const isNoArgsRenderWait = (_fn) => {
|
|
55
74
|
var _a;
|
|
@@ -120,4 +139,4 @@ function isFrontendAction(action) {
|
|
|
120
139
|
export {
|
|
121
140
|
useCopilotAction
|
|
122
141
|
};
|
|
123
|
-
//# sourceMappingURL=chunk-
|
|
142
|
+
//# sourceMappingURL=chunk-NJA5ZLAZ.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
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 * @example\n * // Catch all action allows you to render actions that are not defined in the frontend\n * useCopilotAction({\n * name: \"*\",\n * render: ({ name, args, status, result, handler, respond }) => {\n * return <div>Rendering action: {name}</div>;\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 { useAsyncCallback } from \"../components/error-boundary/error-utils\";\nimport {\n ActionRenderProps,\n ActionRenderPropsNoArgsWait,\n ActionRenderPropsWait,\n CatchAllFrontendAction,\n FrontendAction,\n} from \"../types/frontend-action\";\nimport { useToast } from \"../components/toast/toast-provider\";\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> | CatchAllFrontendAction,\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 const activatingMessageIdRef = useRef<string | null>(null);\n const { addToast } = useToast();\n\n // clone the action to avoid mutating the original object\n action = { ...action };\n\n // const { currentlyActivatingHitlActionMessageIdRef } = useCopilotContext() as any; // <-- REMOVE THIS FOR NOW\n\n // If the developer provides a renderAndWaitForResponse function, we transform the action\n // to use a promise internally, so that we can treat it like a normal action.\n if (\n // renderAndWaitForResponse is not available for catch all actions\n isFrontendAction(action) &&\n // check if renderAndWaitForResponse is set\n (action.renderAndWait || action.renderAndWaitForResponse)\n ) {\n (action as any)._isRenderAndWait = true; // Internal flag to identify this action type later\n const renderAndWait = action.renderAndWait || action.renderAndWaitForResponse;\n // remove the renderAndWait function from the action\n action.renderAndWait = undefined;\n action.renderAndWaitForResponse = undefined;\n\n // Add a method for use-chat.ts to set the activating message ID.\n // This helps correlate the action instance with the message being processed by use-chat.\n (action as any)._setActivatingMessageId = (id: string | null) => {\n activatingMessageIdRef.current = id;\n };\n\n // add a handler that will be called when the action is executed\n action.handler = useAsyncCallback(async () => {\n const currentActivatingId = activatingMessageIdRef.current;\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 = {\n promise,\n resolve: resolve!,\n reject: reject!,\n messageId: currentActivatingId,\n };\n // then we await the promise (it will be resolved in the original renderAndWait function)\n const result = await promise;\n return result;\n }, []) as any;\n\n // add a render function that will be called when the action is rendered\n action.render = ((props: ActionRenderProps<T> & { messageId?: string }): React.ReactElement => {\n const currentRenderMessageId = props.messageId;\n // For renderAndWaitForResponse, the 'executing' state might be set by use-chat before\n // this specific action instance's handler (and thus its promise) is ready.\n // This logic adjusts the status to 'inProgress' if the current render\n // isn't for the actively processing HITL action, preventing premature interaction.\n let status = props.status;\n if (props.status === \"executing\") {\n if (!renderAndWaitRef.current || !renderAndWaitRef.current.promise) {\n status = \"inProgress\";\n } else if (\n renderAndWaitRef.current.messageId !== currentRenderMessageId &&\n activatingMessageIdRef.current !== currentRenderMessageId\n ) {\n status = \"inProgress\";\n }\n // If conditions met, status remains 'executing'\n }\n // Create type safe waitProps based on whether T extends empty array or not\n const waitProps = {\n status,\n args: props.args,\n result: props.result,\n // handler and respond should only be provided if this is the truly active instance\n // and its promise infrastructure is ready.\n handler:\n status === \"executing\" &&\n renderAndWaitRef.current &&\n renderAndWaitRef.current.messageId === currentRenderMessageId\n ? renderAndWaitRef.current!.resolve\n : undefined,\n respond:\n status === \"executing\" &&\n renderAndWaitRef.current &&\n renderAndWaitRef.current.messageId === currentRenderMessageId\n ? renderAndWaitRef.current!.resolve\n : 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 // catch all actions don't have a handler\n if (isFrontendAction(action)) {\n actions[idRef.current].handler = action.handler as any;\n }\n if (typeof action.render === \"function\") {\n if (chatComponentsCache.current !== null) {\n // TODO: using as any here because the type definitions are getting to tricky\n // not wasting time on this now - we know the types are compatible\n chatComponentsCache.current.actions[action.name] = action.render as any;\n }\n }\n }\n }\n\n useEffect(() => {\n const hasDuplicate = Object.values(actions).some(\n (otherAction) => otherAction.name === action.name && otherAction !== actions[idRef.current],\n );\n\n if (hasDuplicate) {\n addToast({\n type: \"warning\",\n message: `Found an already registered action with name ${action.name}.`,\n id: `dup-action-${action.name}`,\n });\n }\n }, [actions]);\n\n useEffect(() => {\n setAction(idRef.current, action as any);\n if (chatComponentsCache.current !== null && action.render !== undefined) {\n // see comment about type safety above\n chatComponentsCache.current.actions[action.name] = action.render as any;\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 // UPDATE: We now have access, we should remove the entry if not referenced by any message.\n removeAction(idRef.current);\n };\n }, [\n setAction,\n removeAction,\n isFrontendAction(action) ? action.description : undefined,\n action.name,\n isFrontendAction(action) ? action.disabled : undefined,\n isFrontendAction(action) ? action.available : undefined,\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(isFrontendAction(action) ? 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\nfunction isFrontendAction<T extends Parameter[]>(\n action: FrontendAction<T> | CatchAllFrontendAction,\n): action is FrontendAction<T> {\n return action.name !== \"*\";\n}\n\ninterface RenderAndWaitForResponse {\n promise: Promise<any>;\n resolve: (result: any) => void;\n reject: (error: any) => void;\n messageId: string | null;\n}\n"],"mappings":"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","names":[]}
|
|
@@ -1,21 +1,21 @@
|
|
|
1
1
|
import {
|
|
2
2
|
useCopilotChat
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-LFAZTKBK.mjs";
|
|
4
4
|
import {
|
|
5
5
|
useCopilotMessagesContext
|
|
6
6
|
} from "./chunk-DCTJZ742.mjs";
|
|
7
7
|
import {
|
|
8
8
|
useAsyncCallback
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-3OQM3NEK.mjs";
|
|
10
10
|
import {
|
|
11
11
|
useCopilotRuntimeClient
|
|
12
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-JWAXDYOW.mjs";
|
|
13
13
|
import {
|
|
14
14
|
useToast
|
|
15
|
-
} from "./chunk-
|
|
15
|
+
} from "./chunk-YAF2LATQ.mjs";
|
|
16
16
|
import {
|
|
17
17
|
useCopilotContext
|
|
18
|
-
} from "./chunk-
|
|
18
|
+
} from "./chunk-DKZTPL66.mjs";
|
|
19
19
|
import {
|
|
20
20
|
__async,
|
|
21
21
|
__spreadProps,
|
|
@@ -76,6 +76,9 @@ function useCoAgent(options) {
|
|
|
76
76
|
threadId,
|
|
77
77
|
agentName: name
|
|
78
78
|
});
|
|
79
|
+
if (result.error) {
|
|
80
|
+
return;
|
|
81
|
+
}
|
|
79
82
|
const newState = (_b = (_a = result.data) == null ? void 0 : _a.loadAgentState) == null ? void 0 : _b.state;
|
|
80
83
|
if (newState === lastLoadedState.current)
|
|
81
84
|
return;
|
|
@@ -99,6 +102,32 @@ function useCoAgent(options) {
|
|
|
99
102
|
// reset initialstate on reset
|
|
100
103
|
coagentStates[name] === void 0
|
|
101
104
|
]);
|
|
105
|
+
useEffect(() => {
|
|
106
|
+
const newConfig = options.config ? options.config : options.configurable ? { configurable: options.configurable } : void 0;
|
|
107
|
+
if (newConfig === void 0)
|
|
108
|
+
return;
|
|
109
|
+
setCoagentStatesWithRef((prev) => {
|
|
110
|
+
var _a;
|
|
111
|
+
const existing = (_a = prev[name]) != null ? _a : {
|
|
112
|
+
name,
|
|
113
|
+
state: isInternalStateManagementWithInitial(options) ? options.initialState : {},
|
|
114
|
+
config: {},
|
|
115
|
+
running: false,
|
|
116
|
+
active: false,
|
|
117
|
+
threadId: void 0,
|
|
118
|
+
nodeName: void 0,
|
|
119
|
+
runId: void 0
|
|
120
|
+
};
|
|
121
|
+
if (JSON.stringify(existing.config) === JSON.stringify(newConfig)) {
|
|
122
|
+
return prev;
|
|
123
|
+
}
|
|
124
|
+
return __spreadProps(__spreadValues({}, prev), {
|
|
125
|
+
[name]: __spreadProps(__spreadValues({}, existing), {
|
|
126
|
+
config: newConfig
|
|
127
|
+
})
|
|
128
|
+
});
|
|
129
|
+
});
|
|
130
|
+
}, [JSON.stringify(options.config), JSON.stringify(options.configurable)]);
|
|
102
131
|
const runAgentCallback = useAsyncCallback(
|
|
103
132
|
(hint) => __async(this, null, function* () {
|
|
104
133
|
yield runAgent(name, context, appendMessage, runChatCompletion, hint);
|
|
@@ -207,4 +236,4 @@ export {
|
|
|
207
236
|
stopAgent,
|
|
208
237
|
runAgent
|
|
209
238
|
};
|
|
210
|
-
//# sourceMappingURL=chunk-
|
|
239
|
+
//# sourceMappingURL=chunk-QGT4JO7R.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/hooks/use-coagent.ts"],"sourcesContent":["/**\n * <Callout type=\"info\">\n * Usage of this hook assumes some additional setup in your application, for more information\n * on that see the CoAgents <span className=\"text-blue-500\">[getting started guide](/coagents/quickstart/langgraph)</span>.\n * </Callout>\n * <Frame className=\"my-12\">\n * <img\n * src=\"/images/coagents/SharedStateCoAgents.gif\"\n * alt=\"CoAgents demonstration\"\n * className=\"w-auto\"\n * />\n * </Frame>\n *\n * This hook is used to integrate an agent into your application. With its use, you can\n * render and update the state of an agent, allowing for a dynamic and interactive experience.\n * We call these shared state experiences agentic copilots, or CoAgents for short.\n *\n * ## Usage\n *\n * ### Simple Usage\n *\n * ```tsx\n * import { useCoAgent } from \"@copilotkit/react-core\";\n *\n * type AgentState = {\n * count: number;\n * }\n *\n * const agent = useCoAgent<AgentState>({\n * name: \"my-agent\",\n * initialState: {\n * count: 0,\n * },\n * });\n *\n * ```\n *\n * `useCoAgent` returns an object with the following properties:\n *\n * ```tsx\n * const {\n * name, // The name of the agent currently being used.\n * nodeName, // The name of the current LangGraph node.\n * state, // The current state of the agent.\n * setState, // A function to update the state of the agent.\n * running, // A boolean indicating if the agent is currently running.\n * start, // A function to start the agent.\n * stop, // A function to stop the agent.\n * run, // A function to re-run the agent. Takes a HintFunction to inform the agent why it is being re-run.\n * } = agent;\n * ```\n *\n * Finally we can leverage these properties to create reactive experiences with the agent!\n *\n * ```tsx\n * const { state, setState } = useCoAgent<AgentState>({\n * name: \"my-agent\",\n * initialState: {\n * count: 0,\n * },\n * });\n *\n * return (\n * <div>\n * <p>Count: {state.count}</p>\n * <button onClick={() => setState({ count: state.count + 1 })}>Increment</button>\n * </div>\n * );\n * ```\n *\n * This reactivity is bidirectional, meaning that changes to the state from the agent will be reflected in the UI and vice versa.\n *\n * ## Parameters\n * <PropertyReference name=\"options\" type=\"UseCoagentOptions<T>\" required>\n * The options to use when creating the coagent.\n * <PropertyReference name=\"name\" type=\"string\" required>\n * The name of the agent to use.\n * </PropertyReference>\n * <PropertyReference name=\"initialState\" type=\"T | any\">\n * The initial state of the agent.\n * </PropertyReference>\n * <PropertyReference name=\"state\" type=\"T | any\">\n * State to manage externally if you are using this hook with external state management.\n * </PropertyReference>\n * <PropertyReference name=\"setState\" type=\"(newState: T | ((prevState: T | undefined) => T)) => void\">\n * A function to update the state of the agent if you are using this hook with external state management.\n * </PropertyReference>\n * </PropertyReference>\n */\n\nimport { useCallback, useEffect, useMemo, useRef } from \"react\";\nimport {\n CopilotContextParams,\n CopilotMessagesContextParams,\n useCopilotContext,\n useCopilotMessagesContext,\n} from \"../context\";\nimport { CoagentState } from \"../types/coagent-state\";\nimport { useCopilotChat } from \"./use-copilot-chat\";\nimport { Message } from \"@copilotkit/runtime-client-gql\";\nimport { useAsyncCallback } from \"../components/error-boundary/error-utils\";\nimport { useToast } from \"../components/toast/toast-provider\";\nimport { useCopilotRuntimeClient } from \"./use-copilot-runtime-client\";\nimport { parseJson, CopilotKitAgentDiscoveryError } from \"@copilotkit/shared\";\n\ninterface UseCoagentOptionsBase {\n /**\n * The name of the agent being used.\n */\n name: string;\n /**\n * @deprecated - use \"config.configurable\"\n * Config to pass to a LangGraph Agent\n */\n configurable?: Record<string, any>;\n /**\n * Config to pass to a LangGraph Agent\n */\n config?: {\n configurable?: Record<string, any>;\n [key: string]: any;\n };\n}\n\ninterface WithInternalStateManagementAndInitial<T> extends UseCoagentOptionsBase {\n /**\n * The initial state of the agent.\n */\n initialState: T;\n}\n\ninterface WithInternalStateManagement extends UseCoagentOptionsBase {\n /**\n * Optional initialState with default type any\n */\n initialState?: any;\n}\n\ninterface WithExternalStateManagement<T> extends UseCoagentOptionsBase {\n /**\n * The current state of the agent.\n */\n state: T;\n /**\n * A function to update the state of the agent.\n */\n setState: (newState: T | ((prevState: T | undefined) => T)) => void;\n}\n\ntype UseCoagentOptions<T> =\n | WithInternalStateManagementAndInitial<T>\n | WithInternalStateManagement\n | WithExternalStateManagement<T>;\n\nexport interface UseCoagentReturnType<T> {\n /**\n * The name of the agent being used.\n */\n name: string;\n /**\n * The name of the current LangGraph node.\n */\n nodeName?: string;\n /**\n * The ID of the thread the agent is running in.\n */\n threadId?: string;\n /**\n * A boolean indicating if the agent is currently running.\n */\n running: boolean;\n /**\n * The current state of the agent.\n */\n state: T;\n /**\n * A function to update the state of the agent.\n */\n setState: (newState: T | ((prevState: T | undefined) => T)) => void;\n /**\n * A function to start the agent.\n */\n start: () => void;\n /**\n * A function to stop the agent.\n */\n stop: () => void;\n /**\n * A function to re-run the agent. The hint function can be used to provide a hint to the agent\n * about why it is being re-run again.\n */\n run: (hint?: HintFunction) => Promise<void>;\n}\n\nexport interface HintFunctionParams {\n /**\n * The previous state of the agent.\n */\n previousState: any;\n /**\n * The current state of the agent.\n */\n currentState: any;\n}\n\nexport type HintFunction = (params: HintFunctionParams) => Message | undefined;\n\n/**\n * This hook is used to integrate an agent into your application. With its use, you can\n * render and update the state of the agent, allowing for a dynamic and interactive experience.\n * We call these shared state experiences \"agentic copilots\". To get started using agentic copilots, which\n * we refer to as CoAgents, checkout the documentation at https://docs.copilotkit.ai/coagents/quickstart/langgraph.\n */\nexport function useCoAgent<T = any>(options: UseCoagentOptions<T>): UseCoagentReturnType<T> {\n const generalContext = useCopilotContext();\n const { availableAgents } = generalContext;\n const { setBannerError } = useToast();\n const lastLoadedThreadId = useRef<string>();\n const lastLoadedState = useRef<any>();\n\n const { name } = options;\n useEffect(() => {\n if (availableAgents?.length && !availableAgents.some((a) => a.name === name)) {\n const message = `(useCoAgent): Agent \"${name}\" not found. Make sure the agent exists and is properly configured.`;\n console.warn(message);\n\n // Route to banner instead of toast for consistency\n const agentError = new CopilotKitAgentDiscoveryError({\n agentName: name,\n availableAgents: availableAgents.map((a) => ({ name: a.name, id: a.id })),\n });\n setBannerError(agentError);\n }\n }, [availableAgents]);\n\n const messagesContext = useCopilotMessagesContext();\n const context = { ...generalContext, ...messagesContext };\n const { coagentStates, coagentStatesRef, setCoagentStatesWithRef, threadId, copilotApiConfig } =\n context;\n const { appendMessage, runChatCompletion } = useCopilotChat();\n const headers = {\n ...(copilotApiConfig.headers || {}),\n };\n\n const runtimeClient = useCopilotRuntimeClient({\n url: copilotApiConfig.chatApiEndpoint,\n publicApiKey: copilotApiConfig.publicApiKey,\n headers,\n credentials: copilotApiConfig.credentials,\n showDevConsole: context.showDevConsole,\n });\n\n // if we manage state internally, we need to provide a function to set the state\n const setState = useCallback(\n (newState: T | ((prevState: T | undefined) => T)) => {\n // coagentStatesRef.current || {}\n let coagentState: CoagentState = getCoagentState({ coagentStates, name, options });\n const updatedState =\n typeof newState === \"function\" ? (newState as Function)(coagentState.state) : newState;\n\n setCoagentStatesWithRef({\n ...coagentStatesRef.current,\n [name]: {\n ...coagentState,\n state: updatedState,\n },\n });\n },\n [coagentStates, name],\n );\n\n useEffect(() => {\n const fetchAgentState = async () => {\n if (!threadId || threadId === lastLoadedThreadId.current) return;\n\n const result = await runtimeClient.loadAgentState({\n threadId,\n agentName: name,\n });\n\n // Runtime client handles errors automatically via handleGQLErrors\n if (result.error) {\n return; // Don't process data on error\n }\n\n const newState = result.data?.loadAgentState?.state;\n if (newState === lastLoadedState.current) return;\n\n if (result.data?.loadAgentState?.threadExists && newState && newState != \"{}\") {\n lastLoadedState.current = newState;\n lastLoadedThreadId.current = threadId;\n const fetchedState = parseJson(newState, {});\n isExternalStateManagement(options)\n ? options.setState(fetchedState)\n : setState(fetchedState);\n }\n };\n void fetchAgentState();\n }, [threadId]);\n\n // Sync internal state with external state if state management is external\n useEffect(() => {\n if (isExternalStateManagement(options)) {\n setState(options.state);\n } else if (coagentStates[name] === undefined) {\n setState(options.initialState === undefined ? {} : options.initialState);\n }\n }, [\n isExternalStateManagement(options) ? JSON.stringify(options.state) : undefined,\n // reset initialstate on reset\n coagentStates[name] === undefined,\n ]);\n\n // Sync config when runtime configuration changes\n useEffect(() => {\n const newConfig = options.config\n ? options.config\n : options.configurable\n ? { configurable: options.configurable }\n : undefined;\n\n if (newConfig === undefined) return;\n\n setCoagentStatesWithRef((prev) => {\n const existing = prev[name] ?? {\n name,\n state: isInternalStateManagementWithInitial(options) ? options.initialState : {},\n config: {},\n running: false,\n active: false,\n threadId: undefined,\n nodeName: undefined,\n runId: undefined,\n };\n\n if (JSON.stringify(existing.config) === JSON.stringify(newConfig)) {\n return prev;\n }\n\n return {\n ...prev,\n [name]: {\n ...existing,\n config: newConfig,\n },\n };\n });\n }, [JSON.stringify(options.config), JSON.stringify(options.configurable)]);\n\n const runAgentCallback = useAsyncCallback(\n async (hint?: HintFunction) => {\n await runAgent(name, context, appendMessage, runChatCompletion, hint);\n },\n [name, context, appendMessage, runChatCompletion],\n );\n\n // Return the state and setState function\n return useMemo(() => {\n const coagentState = getCoagentState({ coagentStates, name, options });\n return {\n name,\n nodeName: coagentState.nodeName,\n threadId: coagentState.threadId,\n running: coagentState.running,\n state: coagentState.state,\n setState: isExternalStateManagement(options) ? options.setState : setState,\n start: () => startAgent(name, context),\n stop: () => stopAgent(name, context),\n run: runAgentCallback,\n };\n }, [name, coagentStates, options, setState, runAgentCallback]);\n}\n\nexport function startAgent(name: string, context: CopilotContextParams) {\n const { setAgentSession } = context;\n setAgentSession({\n agentName: name,\n });\n}\n\nexport function stopAgent(name: string, context: CopilotContextParams) {\n const { agentSession, setAgentSession } = context;\n if (agentSession && agentSession.agentName === name) {\n setAgentSession(null);\n context.setCoagentStates((prevAgentStates) => {\n return {\n ...prevAgentStates,\n [name]: {\n ...prevAgentStates[name],\n running: false,\n active: false,\n threadId: undefined,\n nodeName: undefined,\n runId: undefined,\n },\n };\n });\n } else {\n console.warn(`No agent session found for ${name}`);\n }\n}\n\nexport async function runAgent(\n name: string,\n context: CopilotContextParams & CopilotMessagesContextParams,\n appendMessage: (message: Message) => Promise<void>,\n runChatCompletion: () => Promise<Message[]>,\n hint?: HintFunction,\n) {\n const { agentSession, setAgentSession } = context;\n if (!agentSession || agentSession.agentName !== name) {\n setAgentSession({\n agentName: name,\n });\n }\n\n let previousState: any = null;\n for (let i = context.messages.length - 1; i >= 0; i--) {\n const message = context.messages[i];\n if (message.isAgentStateMessage() && message.agentName === name) {\n previousState = message.state;\n }\n }\n\n let state = context.coagentStatesRef.current?.[name]?.state || {};\n\n if (hint) {\n const hintMessage = hint({ previousState, currentState: state });\n if (hintMessage) {\n await appendMessage(hintMessage);\n } else {\n await runChatCompletion();\n }\n } else {\n await runChatCompletion();\n }\n}\n\nconst isExternalStateManagement = <T>(\n options: UseCoagentOptions<T>,\n): options is WithExternalStateManagement<T> => {\n return \"state\" in options && \"setState\" in options;\n};\n\nconst isInternalStateManagementWithInitial = <T>(\n options: UseCoagentOptions<T>,\n): options is WithInternalStateManagementAndInitial<T> => {\n return \"initialState\" in options;\n};\n\nconst getCoagentState = <T>({\n coagentStates,\n name,\n options,\n}: {\n coagentStates: Record<string, CoagentState>;\n name: string;\n options: UseCoagentOptions<T>;\n}) => {\n if (coagentStates[name]) {\n return coagentStates[name];\n } else {\n return {\n name,\n state: isInternalStateManagementWithInitial<T>(options) ? options.initialState : {},\n config: options.config\n ? options.config\n : options.configurable\n ? { configurable: options.configurable }\n : {},\n running: false,\n active: false,\n threadId: undefined,\n nodeName: undefined,\n runId: undefined,\n };\n }\n};\n"],"mappings":"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","names":[]}
|
|
@@ -4,13 +4,16 @@ import {
|
|
|
4
4
|
import {
|
|
5
5
|
useAsyncCallback,
|
|
6
6
|
useErrorToast
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-3OQM3NEK.mjs";
|
|
8
8
|
import {
|
|
9
9
|
useCopilotRuntimeClient
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-JWAXDYOW.mjs";
|
|
11
|
+
import {
|
|
12
|
+
useToast
|
|
13
|
+
} from "./chunk-YAF2LATQ.mjs";
|
|
11
14
|
import {
|
|
12
15
|
useCopilotContext
|
|
13
|
-
} from "./chunk-
|
|
16
|
+
} from "./chunk-DKZTPL66.mjs";
|
|
14
17
|
import {
|
|
15
18
|
__async,
|
|
16
19
|
__spreadProps,
|
|
@@ -19,10 +22,13 @@ import {
|
|
|
19
22
|
|
|
20
23
|
// src/hooks/use-chat.ts
|
|
21
24
|
import { useCallback, useEffect, useRef } from "react";
|
|
25
|
+
import { flushSync } from "react-dom";
|
|
22
26
|
import {
|
|
23
27
|
COPILOT_CLOUD_PUBLIC_API_KEY_HEADER,
|
|
24
28
|
randomId,
|
|
25
|
-
parseJson
|
|
29
|
+
parseJson,
|
|
30
|
+
CopilotKitError,
|
|
31
|
+
CopilotKitErrorCode
|
|
26
32
|
} from "@copilotkit/shared";
|
|
27
33
|
import {
|
|
28
34
|
TextMessage,
|
|
@@ -70,6 +76,35 @@ function useChat(options) {
|
|
|
70
76
|
} = options;
|
|
71
77
|
const runChatCompletionRef = useRef();
|
|
72
78
|
const addErrorToast = useErrorToast();
|
|
79
|
+
const { setBannerError } = useToast();
|
|
80
|
+
const { onError } = useCopilotContext();
|
|
81
|
+
const traceUIError = (error, originalError) => __async(this, null, function* () {
|
|
82
|
+
if (!onError || !(copilotConfig == null ? void 0 : copilotConfig.publicApiKey))
|
|
83
|
+
return;
|
|
84
|
+
try {
|
|
85
|
+
const traceEvent = {
|
|
86
|
+
type: "error",
|
|
87
|
+
timestamp: Date.now(),
|
|
88
|
+
context: {
|
|
89
|
+
source: "ui",
|
|
90
|
+
request: {
|
|
91
|
+
operation: "useChatCompletion",
|
|
92
|
+
url: copilotConfig.chatApiEndpoint,
|
|
93
|
+
startTime: Date.now()
|
|
94
|
+
},
|
|
95
|
+
technical: {
|
|
96
|
+
environment: "browser",
|
|
97
|
+
userAgent: typeof navigator !== "undefined" ? navigator.userAgent : void 0,
|
|
98
|
+
stackTrace: originalError instanceof Error ? originalError.stack : void 0
|
|
99
|
+
}
|
|
100
|
+
},
|
|
101
|
+
error
|
|
102
|
+
};
|
|
103
|
+
yield onError(traceEvent);
|
|
104
|
+
} catch (traceError) {
|
|
105
|
+
console.error("Error in use-chat onError handler:", traceError);
|
|
106
|
+
}
|
|
107
|
+
});
|
|
73
108
|
const agentSessionRef = useRef(agentSession);
|
|
74
109
|
agentSessionRef.current = agentSession;
|
|
75
110
|
const runIdRef = useRef(runId);
|
|
@@ -89,7 +124,7 @@ function useChat(options) {
|
|
|
89
124
|
const pendingAppendsRef = useRef([]);
|
|
90
125
|
const runChatCompletion = useAsyncCallback(
|
|
91
126
|
(previousMessages) => __async(this, null, function* () {
|
|
92
|
-
var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o;
|
|
127
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p, _q, _r, _s, _t;
|
|
93
128
|
setIsLoading(true);
|
|
94
129
|
const interruptEvent = langGraphInterruptAction == null ? void 0 : langGraphInterruptAction.event;
|
|
95
130
|
if ((interruptEvent == null ? void 0 : interruptEvent.name) === MetaEventName.LangGraphInterruptEvent && (interruptEvent == null ? void 0 : interruptEvent.value) && !(interruptEvent == null ? void 0 : interruptEvent.response) && agentSessionRef.current) {
|
|
@@ -221,20 +256,53 @@ function useChat(options) {
|
|
|
221
256
|
messages2 = convertGqlOutputToMessages(
|
|
222
257
|
filterAdjacentAgentStateMessages(rawMessagesResponse)
|
|
223
258
|
);
|
|
224
|
-
if (messages2.length === 0) {
|
|
225
|
-
continue;
|
|
226
|
-
}
|
|
227
259
|
newMessages = [];
|
|
228
260
|
if (((_k = value.generateCopilotResponse.status) == null ? void 0 : _k.__typename) === "FailedResponseStatus" && value.generateCopilotResponse.status.reason === "GUARDRAILS_VALIDATION_FAILED") {
|
|
261
|
+
const guardrailsReason = ((_l = value.generateCopilotResponse.status.details) == null ? void 0 : _l.guardrailsReason) || "";
|
|
229
262
|
newMessages = [
|
|
230
263
|
new TextMessage({
|
|
231
264
|
role: MessageRole.Assistant,
|
|
232
|
-
content:
|
|
265
|
+
content: guardrailsReason
|
|
233
266
|
})
|
|
234
267
|
];
|
|
268
|
+
const guardrailsError = new CopilotKitError({
|
|
269
|
+
message: `Guardrails validation failed: ${guardrailsReason}`,
|
|
270
|
+
code: CopilotKitErrorCode.MISUSE
|
|
271
|
+
});
|
|
272
|
+
yield traceUIError(guardrailsError, {
|
|
273
|
+
statusReason: value.generateCopilotResponse.status.reason,
|
|
274
|
+
statusDetails: value.generateCopilotResponse.status.details
|
|
275
|
+
});
|
|
235
276
|
setMessages([...previousMessages, ...newMessages]);
|
|
236
277
|
break;
|
|
237
|
-
}
|
|
278
|
+
}
|
|
279
|
+
if (((_m = value.generateCopilotResponse.status) == null ? void 0 : _m.__typename) === "FailedResponseStatus" && value.generateCopilotResponse.status.reason === "UNKNOWN_ERROR") {
|
|
280
|
+
const errorMessage = ((_n = value.generateCopilotResponse.status.details) == null ? void 0 : _n.description) || "An unknown error occurred";
|
|
281
|
+
const statusDetails = value.generateCopilotResponse.status.details;
|
|
282
|
+
const originalError = (statusDetails == null ? void 0 : statusDetails.originalError) || (statusDetails == null ? void 0 : statusDetails.error);
|
|
283
|
+
const originalCode = (originalError == null ? void 0 : originalError.code) || ((_o = originalError == null ? void 0 : originalError.extensions) == null ? void 0 : _o.code);
|
|
284
|
+
const originalSeverity = (originalError == null ? void 0 : originalError.severity) || ((_p = originalError == null ? void 0 : originalError.extensions) == null ? void 0 : _p.severity);
|
|
285
|
+
const originalVisibility = (originalError == null ? void 0 : originalError.visibility) || ((_q = originalError == null ? void 0 : originalError.extensions) == null ? void 0 : _q.visibility);
|
|
286
|
+
let errorCode = CopilotKitErrorCode.NETWORK_ERROR;
|
|
287
|
+
if (originalCode && Object.values(CopilotKitErrorCode).includes(originalCode)) {
|
|
288
|
+
errorCode = originalCode;
|
|
289
|
+
}
|
|
290
|
+
const structuredError = new CopilotKitError({
|
|
291
|
+
message: errorMessage,
|
|
292
|
+
code: errorCode,
|
|
293
|
+
severity: originalSeverity,
|
|
294
|
+
visibility: originalVisibility
|
|
295
|
+
});
|
|
296
|
+
setBannerError(structuredError);
|
|
297
|
+
yield traceUIError(structuredError, {
|
|
298
|
+
statusReason: value.generateCopilotResponse.status.reason,
|
|
299
|
+
statusDetails: value.generateCopilotResponse.status.details,
|
|
300
|
+
originalErrorCode: originalCode,
|
|
301
|
+
preservedStructure: !!originalCode
|
|
302
|
+
});
|
|
303
|
+
setIsLoading(false);
|
|
304
|
+
break;
|
|
305
|
+
} else if (messages2.length > 0) {
|
|
238
306
|
newMessages = [...messages2];
|
|
239
307
|
for (const message of messages2) {
|
|
240
308
|
if (message.isAgentStateMessage() && !message.active && !executedCoAgentStateRenders.includes(message.id) && onCoAgentStateRender) {
|
|
@@ -256,17 +324,22 @@ function useChat(options) {
|
|
|
256
324
|
lastAgentStateMessage.state.messages
|
|
257
325
|
);
|
|
258
326
|
}
|
|
259
|
-
setCoagentStatesWithRef((prevAgentStates) =>
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
327
|
+
setCoagentStatesWithRef((prevAgentStates) => {
|
|
328
|
+
var _a2;
|
|
329
|
+
return __spreadProps(__spreadValues({}, prevAgentStates), {
|
|
330
|
+
[lastAgentStateMessage.agentName]: {
|
|
331
|
+
name: lastAgentStateMessage.agentName,
|
|
332
|
+
state: lastAgentStateMessage.state,
|
|
333
|
+
running: lastAgentStateMessage.running,
|
|
334
|
+
active: lastAgentStateMessage.active,
|
|
335
|
+
threadId: lastAgentStateMessage.threadId,
|
|
336
|
+
nodeName: lastAgentStateMessage.nodeName,
|
|
337
|
+
runId: lastAgentStateMessage.runId,
|
|
338
|
+
// Preserve existing config from previous state
|
|
339
|
+
config: (_a2 = prevAgentStates[lastAgentStateMessage.agentName]) == null ? void 0 : _a2.config
|
|
340
|
+
}
|
|
341
|
+
});
|
|
342
|
+
});
|
|
270
343
|
if (lastAgentStateMessage.running) {
|
|
271
344
|
setAgentSession({
|
|
272
345
|
threadId: lastAgentStateMessage.threadId,
|
|
@@ -296,6 +369,39 @@ function useChat(options) {
|
|
|
296
369
|
newMessages
|
|
297
370
|
);
|
|
298
371
|
let didExecuteAction = false;
|
|
372
|
+
const executeActionFromMessage = (currentAction, actionMessage) => __async(this, null, function* () {
|
|
373
|
+
var _a2;
|
|
374
|
+
const isInterruptAction = interruptMessages.find((m) => m.id === actionMessage.id);
|
|
375
|
+
followUp = (_a2 = currentAction == null ? void 0 : currentAction.followUp) != null ? _a2 : !isInterruptAction;
|
|
376
|
+
if (currentAction == null ? void 0 : currentAction._setActivatingMessageId) {
|
|
377
|
+
currentAction._setActivatingMessageId(actionMessage.id);
|
|
378
|
+
}
|
|
379
|
+
const resultMessage = yield executeAction({
|
|
380
|
+
onFunctionCall,
|
|
381
|
+
message: actionMessage,
|
|
382
|
+
chatAbortControllerRef,
|
|
383
|
+
onError: (error) => {
|
|
384
|
+
addErrorToast([error]);
|
|
385
|
+
console.error(`Failed to execute action ${actionMessage.name}: ${error}`);
|
|
386
|
+
},
|
|
387
|
+
setMessages,
|
|
388
|
+
getFinalMessages: () => finalMessages,
|
|
389
|
+
isRenderAndWait: (currentAction == null ? void 0 : currentAction._isRenderAndWait) || false
|
|
390
|
+
});
|
|
391
|
+
didExecuteAction = true;
|
|
392
|
+
const messageIndex = finalMessages.findIndex((msg) => msg.id === actionMessage.id);
|
|
393
|
+
finalMessages.splice(messageIndex + 1, 0, resultMessage);
|
|
394
|
+
if (currentAction == null ? void 0 : currentAction._isRenderAndWait) {
|
|
395
|
+
const messagesForImmediateUpdate = [...finalMessages];
|
|
396
|
+
flushSync(() => {
|
|
397
|
+
setMessages(messagesForImmediateUpdate);
|
|
398
|
+
});
|
|
399
|
+
}
|
|
400
|
+
if (currentAction == null ? void 0 : currentAction._setActivatingMessageId) {
|
|
401
|
+
currentAction._setActivatingMessageId(null);
|
|
402
|
+
}
|
|
403
|
+
return resultMessage;
|
|
404
|
+
});
|
|
299
405
|
if (onFunctionCall) {
|
|
300
406
|
const lastMessages = [];
|
|
301
407
|
for (let i = finalMessages.length - 1; i >= 0; i--) {
|
|
@@ -312,37 +418,28 @@ function useChat(options) {
|
|
|
312
418
|
(action2) => action2.name === message.name
|
|
313
419
|
);
|
|
314
420
|
const currentResultMessagePairedFeAction = message.isResultMessage() ? getPairedFeAction(actions, message) : null;
|
|
315
|
-
const executeActionFromMessage = (action2, message2) => __async(this, null, function* () {
|
|
316
|
-
var _a2;
|
|
317
|
-
const isInterruptAction = interruptMessages.find((m) => m.id === message2.id);
|
|
318
|
-
followUp = (_a2 = action2 == null ? void 0 : action2.followUp) != null ? _a2 : !isInterruptAction;
|
|
319
|
-
const resultMessage = yield executeAction({
|
|
320
|
-
onFunctionCall,
|
|
321
|
-
previousMessages,
|
|
322
|
-
message: message2,
|
|
323
|
-
chatAbortControllerRef,
|
|
324
|
-
onError: (error) => {
|
|
325
|
-
addErrorToast([error]);
|
|
326
|
-
console.error(`Failed to execute action ${message2.name}: ${error}`);
|
|
327
|
-
}
|
|
328
|
-
});
|
|
329
|
-
didExecuteAction = true;
|
|
330
|
-
const messageIndex = finalMessages.findIndex((msg) => msg.id === message2.id);
|
|
331
|
-
finalMessages.splice(messageIndex + 1, 0, resultMessage);
|
|
332
|
-
return resultMessage;
|
|
333
|
-
});
|
|
334
421
|
if (action && message.isActionExecutionMessage()) {
|
|
335
|
-
const
|
|
336
|
-
const
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
422
|
+
const isRenderAndWaitAction = (action == null ? void 0 : action._isRenderAndWait) || false;
|
|
423
|
+
const alreadyProcessed = isRenderAndWaitAction && finalMessages.some(
|
|
424
|
+
(fm) => fm.isResultMessage() && fm.actionExecutionId === message.id
|
|
425
|
+
);
|
|
426
|
+
if (alreadyProcessed) {
|
|
427
|
+
} else {
|
|
428
|
+
const resultMessage = yield executeActionFromMessage(
|
|
429
|
+
action,
|
|
430
|
+
message
|
|
431
|
+
);
|
|
432
|
+
const pairedFeAction = getPairedFeAction(actions, resultMessage);
|
|
433
|
+
if (pairedFeAction) {
|
|
434
|
+
const newExecutionMessage = new ActionExecutionMessage({
|
|
435
|
+
name: pairedFeAction.name,
|
|
436
|
+
arguments: parseJson(resultMessage.result, resultMessage.result),
|
|
437
|
+
status: message.status,
|
|
438
|
+
createdAt: message.createdAt,
|
|
439
|
+
parentMessageId: message.parentMessageId
|
|
440
|
+
});
|
|
441
|
+
yield executeActionFromMessage(pairedFeAction, newExecutionMessage);
|
|
442
|
+
}
|
|
346
443
|
}
|
|
347
444
|
} else if (message.isResultMessage() && currentResultMessagePairedFeAction) {
|
|
348
445
|
const newExecutionMessage = new ActionExecutionMessage({
|
|
@@ -360,16 +457,12 @@ function useChat(options) {
|
|
|
360
457
|
}
|
|
361
458
|
setMessages(finalMessages);
|
|
362
459
|
}
|
|
363
|
-
if (
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
(didExecuteAction || // the last message is a server side result
|
|
367
|
-
!isAgentRun && finalMessages.length && finalMessages[finalMessages.length - 1].isResultMessage()) && // the user did not stop generation
|
|
368
|
-
!((_m = chatAbortControllerRef.current) == null ? void 0 : _m.signal.aborted)
|
|
369
|
-
) {
|
|
460
|
+
if (followUp !== false && (didExecuteAction || // the last message is a server side result
|
|
461
|
+
!isAgentRun && finalMessages.length && finalMessages[finalMessages.length - 1].isResultMessage()) && // the user did not stop generation
|
|
462
|
+
!((_r = chatAbortControllerRef.current) == null ? void 0 : _r.signal.aborted)) {
|
|
370
463
|
yield new Promise((resolve) => setTimeout(resolve, 10));
|
|
371
464
|
return yield runChatCompletionRef.current(finalMessages);
|
|
372
|
-
} else if ((
|
|
465
|
+
} else if ((_s = chatAbortControllerRef.current) == null ? void 0 : _s.signal.aborted) {
|
|
373
466
|
const repairedMessages = finalMessages.filter((message, actionExecutionIndex) => {
|
|
374
467
|
if (message.isActionExecutionMessage()) {
|
|
375
468
|
return finalMessages.find(
|
|
@@ -380,7 +473,7 @@ function useChat(options) {
|
|
|
380
473
|
});
|
|
381
474
|
const repairedMessageIds = repairedMessages.map((message) => message.id);
|
|
382
475
|
setMessages(repairedMessages);
|
|
383
|
-
if ((
|
|
476
|
+
if ((_t = agentSessionRef.current) == null ? void 0 : _t.nodeName) {
|
|
384
477
|
setAgentSession({
|
|
385
478
|
threadId: agentSessionRef.current.threadId,
|
|
386
479
|
agentName: agentSessionRef.current.agentName,
|
|
@@ -474,21 +567,35 @@ function useChat(options) {
|
|
|
474
567
|
[isLoading, messages, setMessages, runChatCompletionAndHandleFunctionCall]
|
|
475
568
|
);
|
|
476
569
|
const reload = useAsyncCallback(
|
|
477
|
-
(
|
|
570
|
+
(reloadMessageId) => __async(this, null, function* () {
|
|
478
571
|
if (isLoading || messages.length === 0) {
|
|
479
572
|
return;
|
|
480
573
|
}
|
|
481
|
-
const
|
|
482
|
-
if (
|
|
483
|
-
console.warn(`Message with id ${
|
|
574
|
+
const reloadMessageIndex = messages.findIndex((msg) => msg.id === reloadMessageId);
|
|
575
|
+
if (reloadMessageIndex === -1) {
|
|
576
|
+
console.warn(`Message with id ${reloadMessageId} not found`);
|
|
484
577
|
return;
|
|
485
578
|
}
|
|
486
|
-
|
|
487
|
-
if (
|
|
488
|
-
|
|
579
|
+
const reloadMessageRole = messages[reloadMessageIndex].role;
|
|
580
|
+
if (reloadMessageRole !== MessageRole.Assistant) {
|
|
581
|
+
console.warn(`Regenerate cannot be performed on ${reloadMessageRole} role`);
|
|
582
|
+
return;
|
|
489
583
|
}
|
|
490
|
-
|
|
491
|
-
|
|
584
|
+
let historyCutoff = [];
|
|
585
|
+
if (messages.length > 2) {
|
|
586
|
+
const lastUserMessageBeforeRegenerate = messages.slice(0, reloadMessageIndex).reverse().find(
|
|
587
|
+
(msg) => (
|
|
588
|
+
// @ts-expect-error -- message has role
|
|
589
|
+
msg.role === MessageRole.User
|
|
590
|
+
)
|
|
591
|
+
);
|
|
592
|
+
const indexOfLastUserMessageBeforeRegenerate = messages.findIndex(
|
|
593
|
+
(msg) => msg.id === lastUserMessageBeforeRegenerate.id
|
|
594
|
+
);
|
|
595
|
+
historyCutoff = messages.slice(0, indexOfLastUserMessageBeforeRegenerate + 1);
|
|
596
|
+
}
|
|
597
|
+
setMessages(historyCutoff);
|
|
598
|
+
return runChatCompletionAndHandleFunctionCall(historyCutoff);
|
|
492
599
|
}),
|
|
493
600
|
[isLoading, messages, setMessages, runChatCompletionAndHandleFunctionCall]
|
|
494
601
|
);
|
|
@@ -523,20 +630,31 @@ function constructFinalMessages(syncedMessages, previousMessages, newMessages) {
|
|
|
523
630
|
function executeAction(_0) {
|
|
524
631
|
return __async(this, arguments, function* ({
|
|
525
632
|
onFunctionCall,
|
|
526
|
-
previousMessages,
|
|
527
633
|
message,
|
|
528
634
|
chatAbortControllerRef,
|
|
529
|
-
onError
|
|
635
|
+
onError,
|
|
636
|
+
setMessages,
|
|
637
|
+
getFinalMessages,
|
|
638
|
+
isRenderAndWait
|
|
530
639
|
}) {
|
|
531
640
|
let result;
|
|
532
641
|
let error = null;
|
|
642
|
+
const currentMessagesForHandler = getFinalMessages();
|
|
643
|
+
const handlerReturnedPromise = onFunctionCall({
|
|
644
|
+
messages: currentMessagesForHandler,
|
|
645
|
+
name: message.name,
|
|
646
|
+
args: message.arguments
|
|
647
|
+
});
|
|
648
|
+
if (isRenderAndWait) {
|
|
649
|
+
const currentMessagesForRender = getFinalMessages();
|
|
650
|
+
flushSync(() => {
|
|
651
|
+
setMessages([...currentMessagesForRender]);
|
|
652
|
+
});
|
|
653
|
+
}
|
|
533
654
|
try {
|
|
534
655
|
result = yield Promise.race([
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
name: message.name,
|
|
538
|
-
args: message.arguments
|
|
539
|
-
}),
|
|
656
|
+
handlerReturnedPromise,
|
|
657
|
+
// Await the promise returned by the handler
|
|
540
658
|
new Promise(
|
|
541
659
|
(resolve) => {
|
|
542
660
|
var _a;
|
|
@@ -585,4 +703,4 @@ function getPairedFeAction(actions, message) {
|
|
|
585
703
|
export {
|
|
586
704
|
useChat
|
|
587
705
|
};
|
|
588
|
-
//# sourceMappingURL=chunk-
|
|
706
|
+
//# sourceMappingURL=chunk-S5QUEHJC.mjs.map
|