@copilotkit/react-core 1.56.0 → 1.56.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/dist/{copilotkit-Dv8zU8_U.d.cts → copilotkit-BtP7w7cT.d.cts} +10 -1
- package/dist/{copilotkit-Dv8zU8_U.d.cts.map → copilotkit-BtP7w7cT.d.cts.map} +1 -1
- package/dist/{copilotkit-f2Uq0RwG.d.mts → copilotkit-CCbxm6JM.d.mts} +10 -1
- package/dist/{copilotkit-f2Uq0RwG.d.mts.map → copilotkit-CCbxm6JM.d.mts.map} +1 -1
- package/dist/{copilotkit-Cvb6WpAX.cjs → copilotkit-CSJw5BG8.cjs} +32 -17
- package/dist/copilotkit-CSJw5BG8.cjs.map +1 -0
- package/dist/{copilotkit-BebqQrYT.mjs → copilotkit-Cj2ZIxVr.mjs} +32 -17
- package/dist/copilotkit-Cj2ZIxVr.mjs.map +1 -0
- package/dist/index.cjs +1 -1
- package/dist/index.d.cts +1 -1
- package/dist/index.d.mts +1 -1
- package/dist/index.mjs +1 -1
- package/dist/index.umd.js +14 -6
- package/dist/index.umd.js.map +1 -1
- package/dist/v2/index.cjs +1 -1
- package/dist/v2/index.d.cts +1 -1
- package/dist/v2/index.d.mts +1 -1
- package/dist/v2/index.mjs +1 -1
- package/dist/v2/index.umd.js +32 -17
- package/dist/v2/index.umd.js.map +1 -1
- package/package.json +6 -6
- package/src/components/CopilotListeners.tsx +15 -4
- package/src/components/__tests__/CopilotListeners.test.tsx +38 -0
- package/src/v2/components/chat/CopilotChatAssistantMessage.tsx +4 -4
- package/src/v2/components/chat/CopilotChatInput.tsx +21 -2
- package/src/v2/components/chat/__tests__/CopilotChatAssistantMessage.thumbs.test.tsx +72 -0
- package/src/v2/components/chat/__tests__/CopilotChatInput.test.tsx +38 -0
- package/src/v2/components/ui/button.tsx +12 -11
- package/src/v2/hooks/__tests__/use-render-custom-messages.test.tsx +55 -0
- package/src/v2/hooks/use-render-custom-messages.tsx +1 -1
- package/src/v2/hooks/use-render-tool-call.tsx +3 -0
- package/src/v2/hooks/use-render-tool.tsx +3 -0
- package/src/v2/types/defineToolCallRenderer.ts +3 -0
- package/src/v2/types/react-tool-call-renderer.ts +3 -0
- package/dist/copilotkit-BebqQrYT.mjs.map +0 -1
- package/dist/copilotkit-Cvb6WpAX.cjs.map +0 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@copilotkit/react-core",
|
|
3
|
-
"version": "1.56.
|
|
3
|
+
"version": "1.56.2",
|
|
4
4
|
"private": false,
|
|
5
5
|
"keywords": [
|
|
6
6
|
"ai",
|
|
@@ -73,11 +73,11 @@
|
|
|
73
73
|
"untruncate-json": "^0.0.1",
|
|
74
74
|
"use-stick-to-bottom": "^1.1.1",
|
|
75
75
|
"zod-to-json-schema": "^3.24.5",
|
|
76
|
-
"@copilotkit/a2ui-renderer": "1.56.
|
|
77
|
-
"@copilotkit/
|
|
78
|
-
"@copilotkit/
|
|
79
|
-
"@copilotkit/
|
|
80
|
-
"@copilotkit/
|
|
76
|
+
"@copilotkit/a2ui-renderer": "1.56.2",
|
|
77
|
+
"@copilotkit/shared": "1.56.2",
|
|
78
|
+
"@copilotkit/web-inspector": "1.56.2",
|
|
79
|
+
"@copilotkit/core": "1.56.2",
|
|
80
|
+
"@copilotkit/runtime-client-gql": "1.56.2"
|
|
81
81
|
},
|
|
82
82
|
"devDependencies": {
|
|
83
83
|
"@tailwindcss/cli": "^4.1.11",
|
|
@@ -60,16 +60,27 @@ const usePredictStateSubscription = (agent?: AbstractAgent) => {
|
|
|
60
60
|
}, [agent, getSubscriber]);
|
|
61
61
|
};
|
|
62
62
|
|
|
63
|
-
|
|
64
|
-
const { copilotkit } = useCopilotKit();
|
|
63
|
+
function CopilotListenersAgentSubscription() {
|
|
65
64
|
const existingConfig = useCopilotChatConfiguration();
|
|
66
65
|
const resolvedAgentId = existingConfig?.agentId;
|
|
67
|
-
const { setBannerError } = useToast();
|
|
68
66
|
|
|
69
67
|
const { agent } = useAgent({ agentId: resolvedAgentId });
|
|
70
68
|
|
|
71
69
|
usePredictStateSubscription(agent);
|
|
72
70
|
|
|
71
|
+
return null;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
export function CopilotListeners() {
|
|
75
|
+
const { copilotkit } = useCopilotKit();
|
|
76
|
+
const { setBannerError } = useToast();
|
|
77
|
+
|
|
78
|
+
// Only render the agent subscription when agents are registered or a runtime
|
|
79
|
+
// is configured. Without this guard, useAgent() throws when the agents map is
|
|
80
|
+
// empty and no runtimeUrl is set (#3249).
|
|
81
|
+
const hasAgents = Object.keys(copilotkit.agents ?? {}).length > 0;
|
|
82
|
+
const hasRuntime = copilotkit.runtimeUrl !== undefined;
|
|
83
|
+
|
|
73
84
|
useEffect(() => {
|
|
74
85
|
const subscriber: CopilotKitCoreSubscriber = {
|
|
75
86
|
onError: ({ error, code, context }) => {
|
|
@@ -122,5 +133,5 @@ export function CopilotListeners() {
|
|
|
122
133
|
};
|
|
123
134
|
}, [copilotkit?.subscribe]);
|
|
124
135
|
|
|
125
|
-
return null;
|
|
136
|
+
return hasAgents || hasRuntime ? <CopilotListenersAgentSubscription /> : null;
|
|
126
137
|
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { describe, it, expect, vi, beforeEach } from "vitest";
|
|
3
|
+
import { render } from "@testing-library/react";
|
|
4
|
+
import { CopilotListeners } from "../CopilotListeners";
|
|
5
|
+
import { CopilotKitProvider } from "../../v2/providers/CopilotKitProvider";
|
|
6
|
+
import { CopilotChatConfigurationProvider } from "../../v2/providers/CopilotChatConfigurationProvider";
|
|
7
|
+
import { ToastProvider } from "../toast/toast-provider";
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Regression test for #3249: CopilotListeners throws when no agents registered.
|
|
11
|
+
*
|
|
12
|
+
* When CopilotKitProvider has no agents registered (empty agents map) and no
|
|
13
|
+
* runtimeUrl, useAgent() inside CopilotListeners throws. The component should
|
|
14
|
+
* handle this gracefully and render null without crashing.
|
|
15
|
+
*/
|
|
16
|
+
describe("CopilotListeners (#3249)", () => {
|
|
17
|
+
beforeEach(() => {
|
|
18
|
+
vi.spyOn(console, "error").mockImplementation(() => {});
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
it("does not throw when no agents are registered", () => {
|
|
22
|
+
// No agents, no runtimeUrl - should not crash
|
|
23
|
+
expect(() => {
|
|
24
|
+
render(
|
|
25
|
+
<ToastProvider enabled={false}>
|
|
26
|
+
<CopilotKitProvider>
|
|
27
|
+
<CopilotChatConfigurationProvider
|
|
28
|
+
agentId="default"
|
|
29
|
+
threadId="test-thread"
|
|
30
|
+
>
|
|
31
|
+
<CopilotListeners />
|
|
32
|
+
</CopilotChatConfigurationProvider>
|
|
33
|
+
</CopilotKitProvider>
|
|
34
|
+
</ToastProvider>,
|
|
35
|
+
);
|
|
36
|
+
}).not.toThrow();
|
|
37
|
+
});
|
|
38
|
+
});
|
|
@@ -98,7 +98,7 @@ export function CopilotChatAssistantMessage({
|
|
|
98
98
|
thumbsUpButton,
|
|
99
99
|
CopilotChatAssistantMessage.ThumbsUpButton,
|
|
100
100
|
{
|
|
101
|
-
onClick: onThumbsUp,
|
|
101
|
+
onClick: onThumbsUp ? () => onThumbsUp(message) : undefined,
|
|
102
102
|
},
|
|
103
103
|
);
|
|
104
104
|
|
|
@@ -106,7 +106,7 @@ export function CopilotChatAssistantMessage({
|
|
|
106
106
|
thumbsDownButton,
|
|
107
107
|
CopilotChatAssistantMessage.ThumbsDownButton,
|
|
108
108
|
{
|
|
109
|
-
onClick: onThumbsDown,
|
|
109
|
+
onClick: onThumbsDown ? () => onThumbsDown(message) : undefined,
|
|
110
110
|
},
|
|
111
111
|
);
|
|
112
112
|
|
|
@@ -114,7 +114,7 @@ export function CopilotChatAssistantMessage({
|
|
|
114
114
|
readAloudButton,
|
|
115
115
|
CopilotChatAssistantMessage.ReadAloudButton,
|
|
116
116
|
{
|
|
117
|
-
onClick: onReadAloud,
|
|
117
|
+
onClick: onReadAloud ? () => onReadAloud(message) : undefined,
|
|
118
118
|
},
|
|
119
119
|
);
|
|
120
120
|
|
|
@@ -122,7 +122,7 @@ export function CopilotChatAssistantMessage({
|
|
|
122
122
|
regenerateButton,
|
|
123
123
|
CopilotChatAssistantMessage.RegenerateButton,
|
|
124
124
|
{
|
|
125
|
-
onClick: onRegenerate,
|
|
125
|
+
onClick: onRegenerate ? () => onRegenerate(message) : undefined,
|
|
126
126
|
},
|
|
127
127
|
);
|
|
128
128
|
|
|
@@ -384,6 +384,12 @@ export function CopilotChatInput({
|
|
|
384
384
|
);
|
|
385
385
|
|
|
386
386
|
const handleKeyDown = (e: KeyboardEvent<HTMLTextAreaElement>) => {
|
|
387
|
+
// Skip key handling during IME composition (e.g. CJK input).
|
|
388
|
+
// The compositionend event will fire separately when composition ends.
|
|
389
|
+
if (e.nativeEvent.isComposing || e.keyCode === 229) {
|
|
390
|
+
return;
|
|
391
|
+
}
|
|
392
|
+
|
|
387
393
|
if (commandQuery !== null && mode === "input") {
|
|
388
394
|
if (e.key === "ArrowDown") {
|
|
389
395
|
if (filteredCommands.length > 0) {
|
|
@@ -455,10 +461,12 @@ export function CopilotChatInput({
|
|
|
455
461
|
|
|
456
462
|
onSubmitMessage(trimmed);
|
|
457
463
|
|
|
464
|
+
// Always clear the input after sending, including controlled mode.
|
|
465
|
+
// In controlled mode, onChange("") notifies the parent to reset its state.
|
|
458
466
|
if (!isControlled) {
|
|
459
467
|
setInternalValue("");
|
|
460
|
-
onChange?.("");
|
|
461
468
|
}
|
|
469
|
+
onChange?.("");
|
|
462
470
|
|
|
463
471
|
if (inputRef.current) {
|
|
464
472
|
inputRef.current.focus();
|
|
@@ -470,6 +478,12 @@ export function CopilotChatInput({
|
|
|
470
478
|
value: resolvedValue,
|
|
471
479
|
onChange: handleChange,
|
|
472
480
|
onKeyDown: handleKeyDown,
|
|
481
|
+
onCompositionStart: () => {
|
|
482
|
+
isComposingRef.current = true;
|
|
483
|
+
},
|
|
484
|
+
onCompositionEnd: () => {
|
|
485
|
+
isComposingRef.current = false;
|
|
486
|
+
},
|
|
473
487
|
autoFocus: autoFocus,
|
|
474
488
|
className: twMerge(
|
|
475
489
|
"cpk:w-full cpk:py-3",
|
|
@@ -612,9 +626,14 @@ export function CopilotChatInput({
|
|
|
612
626
|
}
|
|
613
627
|
};
|
|
614
628
|
|
|
629
|
+
// Track whether an IME composition is active so we can avoid
|
|
630
|
+
// resetting textarea.value during measurement (which would break
|
|
631
|
+
// the composition session).
|
|
632
|
+
const isComposingRef = useRef(false);
|
|
633
|
+
|
|
615
634
|
const ensureMeasurements = useCallback(() => {
|
|
616
635
|
const textarea = inputRef.current;
|
|
617
|
-
if (!textarea) {
|
|
636
|
+
if (!textarea || isComposingRef.current) {
|
|
618
637
|
return;
|
|
619
638
|
}
|
|
620
639
|
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { describe, it, expect, vi, beforeEach } from "vitest";
|
|
3
|
+
import { render, screen, fireEvent } from "@testing-library/react";
|
|
4
|
+
import { AssistantMessage } from "@ag-ui/core";
|
|
5
|
+
import { CopilotChatAssistantMessage } from "../CopilotChatAssistantMessage";
|
|
6
|
+
import { CopilotChatConfigurationProvider } from "../../../providers/CopilotChatConfigurationProvider";
|
|
7
|
+
import { CopilotKitProvider } from "../../../providers/CopilotKitProvider";
|
|
8
|
+
|
|
9
|
+
const TEST_THREAD_ID = "test-thread";
|
|
10
|
+
|
|
11
|
+
const renderWithProvider = (component: React.ReactElement) => {
|
|
12
|
+
return render(
|
|
13
|
+
<CopilotKitProvider>
|
|
14
|
+
<CopilotChatConfigurationProvider threadId={TEST_THREAD_ID}>
|
|
15
|
+
{component}
|
|
16
|
+
</CopilotChatConfigurationProvider>
|
|
17
|
+
</CopilotKitProvider>,
|
|
18
|
+
);
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
describe("CopilotChatAssistantMessage thumbs callbacks (#3457)", () => {
|
|
22
|
+
const message: AssistantMessage = {
|
|
23
|
+
id: "msg-1",
|
|
24
|
+
role: "assistant",
|
|
25
|
+
content: "Hello from the assistant",
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
it("onThumbsUp receives AssistantMessage, not SyntheticEvent", () => {
|
|
29
|
+
const onThumbsUp = vi.fn();
|
|
30
|
+
|
|
31
|
+
renderWithProvider(
|
|
32
|
+
<CopilotChatAssistantMessage message={message} onThumbsUp={onThumbsUp} />,
|
|
33
|
+
);
|
|
34
|
+
|
|
35
|
+
const thumbsUpButton = screen.getByRole("button", {
|
|
36
|
+
name: /good response/i,
|
|
37
|
+
});
|
|
38
|
+
fireEvent.click(thumbsUpButton);
|
|
39
|
+
|
|
40
|
+
expect(onThumbsUp).toHaveBeenCalledTimes(1);
|
|
41
|
+
const arg = onThumbsUp.mock.calls[0][0];
|
|
42
|
+
// Should receive AssistantMessage
|
|
43
|
+
expect(arg).toHaveProperty("id", "msg-1");
|
|
44
|
+
expect(arg).toHaveProperty("role", "assistant");
|
|
45
|
+
expect(arg).toHaveProperty("content", "Hello from the assistant");
|
|
46
|
+
// Should NOT receive a SyntheticEvent (which has nativeEvent, target, etc.)
|
|
47
|
+
expect(arg).not.toHaveProperty("nativeEvent");
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
it("onThumbsDown receives AssistantMessage, not SyntheticEvent", () => {
|
|
51
|
+
const onThumbsDown = vi.fn();
|
|
52
|
+
|
|
53
|
+
renderWithProvider(
|
|
54
|
+
<CopilotChatAssistantMessage
|
|
55
|
+
message={message}
|
|
56
|
+
onThumbsDown={onThumbsDown}
|
|
57
|
+
/>,
|
|
58
|
+
);
|
|
59
|
+
|
|
60
|
+
const thumbsDownButton = screen.getByRole("button", {
|
|
61
|
+
name: /bad response/i,
|
|
62
|
+
});
|
|
63
|
+
fireEvent.click(thumbsDownButton);
|
|
64
|
+
|
|
65
|
+
expect(onThumbsDown).toHaveBeenCalledTimes(1);
|
|
66
|
+
const arg = onThumbsDown.mock.calls[0][0];
|
|
67
|
+
expect(arg).toHaveProperty("id", "msg-1");
|
|
68
|
+
expect(arg).toHaveProperty("role", "assistant");
|
|
69
|
+
expect(arg).toHaveProperty("content", "Hello from the assistant");
|
|
70
|
+
expect(arg).not.toHaveProperty("nativeEvent");
|
|
71
|
+
});
|
|
72
|
+
});
|
|
@@ -985,6 +985,44 @@ describe("CopilotChatInput", () => {
|
|
|
985
985
|
expect((input as HTMLTextAreaElement).value).toBe("test message");
|
|
986
986
|
expect(mockOnSubmitMessage).toHaveBeenCalledWith("test message");
|
|
987
987
|
});
|
|
988
|
+
|
|
989
|
+
it("calls onChange with empty string after submission in controlled mode", () => {
|
|
990
|
+
const mockOnChange = vi.fn();
|
|
991
|
+
const mockOnSubmitMessage = vi.fn();
|
|
992
|
+
|
|
993
|
+
const { container } = renderWithProvider(
|
|
994
|
+
<CopilotChatInput
|
|
995
|
+
value="test message"
|
|
996
|
+
onChange={mockOnChange}
|
|
997
|
+
onSubmitMessage={mockOnSubmitMessage}
|
|
998
|
+
/>,
|
|
999
|
+
);
|
|
1000
|
+
|
|
1001
|
+
const sendButton = getSendButton(container);
|
|
1002
|
+
fireEvent.click(sendButton!);
|
|
1003
|
+
|
|
1004
|
+
expect(mockOnSubmitMessage).toHaveBeenCalledWith("test message");
|
|
1005
|
+
expect(mockOnChange).toHaveBeenCalledWith("");
|
|
1006
|
+
});
|
|
1007
|
+
|
|
1008
|
+
it("calls onChange with empty string after Enter submission in controlled mode", () => {
|
|
1009
|
+
const mockOnChange = vi.fn();
|
|
1010
|
+
const mockOnSubmitMessage = vi.fn();
|
|
1011
|
+
|
|
1012
|
+
renderWithProvider(
|
|
1013
|
+
<CopilotChatInput
|
|
1014
|
+
value="hello world"
|
|
1015
|
+
onChange={mockOnChange}
|
|
1016
|
+
onSubmitMessage={mockOnSubmitMessage}
|
|
1017
|
+
/>,
|
|
1018
|
+
);
|
|
1019
|
+
|
|
1020
|
+
const input = screen.getByRole("textbox");
|
|
1021
|
+
fireEvent.keyDown(input, { key: "Enter", shiftKey: false });
|
|
1022
|
+
|
|
1023
|
+
expect(mockOnSubmitMessage).toHaveBeenCalledWith("hello world");
|
|
1024
|
+
expect(mockOnChange).toHaveBeenCalledWith("");
|
|
1025
|
+
});
|
|
988
1026
|
});
|
|
989
1027
|
|
|
990
1028
|
describe("Container dimension cache", () => {
|
|
@@ -99,25 +99,26 @@ const buttonVariants = cva(
|
|
|
99
99
|
},
|
|
100
100
|
);
|
|
101
101
|
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
102
|
+
const Button = React.forwardRef<
|
|
103
|
+
HTMLButtonElement,
|
|
104
|
+
React.ComponentProps<"button"> &
|
|
105
|
+
VariantProps<typeof buttonVariants> & {
|
|
106
|
+
asChild?: boolean;
|
|
107
|
+
}
|
|
108
|
+
>(function Button(
|
|
109
|
+
{ className, variant, size, asChild = false, ...props },
|
|
110
|
+
ref,
|
|
111
|
+
) {
|
|
112
112
|
const Comp = asChild ? Slot : "button";
|
|
113
113
|
|
|
114
114
|
return (
|
|
115
115
|
<Comp
|
|
116
|
+
ref={ref}
|
|
116
117
|
data-slot="button"
|
|
117
118
|
className={cn(buttonVariants({ variant, size, className }))}
|
|
118
119
|
{...props}
|
|
119
120
|
/>
|
|
120
121
|
);
|
|
121
|
-
}
|
|
122
|
+
});
|
|
122
123
|
|
|
123
124
|
export { Button, buttonVariants };
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { describe, it, expect, vi } from "vitest";
|
|
3
|
+
import { renderHook } from "@testing-library/react";
|
|
4
|
+
import { useRenderCustomMessages } from "../use-render-custom-messages";
|
|
5
|
+
import { CopilotKitProvider } from "../../providers/CopilotKitProvider";
|
|
6
|
+
import { CopilotChatConfigurationProvider } from "../../providers/CopilotChatConfigurationProvider";
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Regression test for #3497: useRenderCustomMessages throws "Agent not found"
|
|
10
|
+
* when the agent is undefined during the connecting state.
|
|
11
|
+
*
|
|
12
|
+
* During initial connection, the agent may not yet be registered in the
|
|
13
|
+
* CopilotKit registry. The hook should return null gracefully instead of
|
|
14
|
+
* throwing an error.
|
|
15
|
+
*/
|
|
16
|
+
describe("useRenderCustomMessages (#3497)", () => {
|
|
17
|
+
it("returns null instead of throwing when agent is not found", () => {
|
|
18
|
+
// Render the hook inside a CopilotKitProvider with an agentId that
|
|
19
|
+
// does NOT exist in the registry (simulating connecting state).
|
|
20
|
+
// The hook should not throw.
|
|
21
|
+
const wrapper = ({ children }: { children: React.ReactNode }) => (
|
|
22
|
+
<CopilotKitProvider
|
|
23
|
+
renderCustomMessages={[
|
|
24
|
+
{
|
|
25
|
+
agentId: "nonexistent-agent",
|
|
26
|
+
render: () => <div>Custom</div>,
|
|
27
|
+
},
|
|
28
|
+
]}
|
|
29
|
+
>
|
|
30
|
+
<CopilotChatConfigurationProvider
|
|
31
|
+
agentId="nonexistent-agent"
|
|
32
|
+
threadId="test-thread"
|
|
33
|
+
>
|
|
34
|
+
{children}
|
|
35
|
+
</CopilotChatConfigurationProvider>
|
|
36
|
+
</CopilotKitProvider>
|
|
37
|
+
);
|
|
38
|
+
|
|
39
|
+
const { result } = renderHook(() => useRenderCustomMessages(), { wrapper });
|
|
40
|
+
|
|
41
|
+
// The hook should return a function (the render function), not throw
|
|
42
|
+
// When called, it should handle missing agent gracefully
|
|
43
|
+
if (typeof result.current === "function") {
|
|
44
|
+
const output = result.current({
|
|
45
|
+
message: { id: "msg-1", role: "assistant", content: "test" },
|
|
46
|
+
position: "after",
|
|
47
|
+
});
|
|
48
|
+
// Should return null since agent isn't found
|
|
49
|
+
expect(output).toBeNull();
|
|
50
|
+
} else {
|
|
51
|
+
// If result.current is null, that's also acceptable
|
|
52
|
+
expect(result.current).toBeNull();
|
|
53
|
+
}
|
|
54
|
+
});
|
|
55
|
+
});
|
|
@@ -45,7 +45,7 @@ export function useRenderCustomMessages() {
|
|
|
45
45
|
const registryAgent = copilotkit.getAgent(agentId);
|
|
46
46
|
const agent = getThreadClone(registryAgent, threadId) ?? registryAgent;
|
|
47
47
|
if (!agent) {
|
|
48
|
-
|
|
48
|
+
return null;
|
|
49
49
|
}
|
|
50
50
|
|
|
51
51
|
const messagesIdsInRun = resolvedRunId
|
|
@@ -47,6 +47,7 @@ const ToolCallRenderer = React.memo(
|
|
|
47
47
|
return (
|
|
48
48
|
<RenderComponent
|
|
49
49
|
name={toolName}
|
|
50
|
+
toolCallId={toolCall.id}
|
|
50
51
|
args={args}
|
|
51
52
|
status={ToolCallStatus.Complete}
|
|
52
53
|
result={toolMessage.content}
|
|
@@ -56,6 +57,7 @@ const ToolCallRenderer = React.memo(
|
|
|
56
57
|
return (
|
|
57
58
|
<RenderComponent
|
|
58
59
|
name={toolName}
|
|
60
|
+
toolCallId={toolCall.id}
|
|
59
61
|
args={args}
|
|
60
62
|
status={ToolCallStatus.Executing}
|
|
61
63
|
result={undefined}
|
|
@@ -65,6 +67,7 @@ const ToolCallRenderer = React.memo(
|
|
|
65
67
|
return (
|
|
66
68
|
<RenderComponent
|
|
67
69
|
name={toolName}
|
|
70
|
+
toolCallId={toolCall.id}
|
|
68
71
|
args={args}
|
|
69
72
|
status={ToolCallStatus.InProgress}
|
|
70
73
|
result={undefined}
|
|
@@ -7,6 +7,7 @@ const EMPTY_DEPS: ReadonlyArray<unknown> = [];
|
|
|
7
7
|
|
|
8
8
|
export interface RenderToolInProgressProps<S extends StandardSchemaV1> {
|
|
9
9
|
name: string;
|
|
10
|
+
toolCallId: string;
|
|
10
11
|
parameters: Partial<InferSchemaOutput<S>>;
|
|
11
12
|
status: "inProgress";
|
|
12
13
|
result: undefined;
|
|
@@ -14,6 +15,7 @@ export interface RenderToolInProgressProps<S extends StandardSchemaV1> {
|
|
|
14
15
|
|
|
15
16
|
export interface RenderToolExecutingProps<S extends StandardSchemaV1> {
|
|
16
17
|
name: string;
|
|
18
|
+
toolCallId: string;
|
|
17
19
|
parameters: InferSchemaOutput<S>;
|
|
18
20
|
status: "executing";
|
|
19
21
|
result: undefined;
|
|
@@ -21,6 +23,7 @@ export interface RenderToolExecutingProps<S extends StandardSchemaV1> {
|
|
|
21
23
|
|
|
22
24
|
export interface RenderToolCompleteProps<S extends StandardSchemaV1> {
|
|
23
25
|
name: string;
|
|
26
|
+
toolCallId: string;
|
|
24
27
|
parameters: InferSchemaOutput<S>;
|
|
25
28
|
status: "complete";
|
|
26
29
|
result: string;
|
|
@@ -14,18 +14,21 @@ import { ToolCallStatus } from "@copilotkit/core";
|
|
|
14
14
|
type RenderProps<T> =
|
|
15
15
|
| {
|
|
16
16
|
name: string;
|
|
17
|
+
toolCallId: string;
|
|
17
18
|
args: Partial<T>;
|
|
18
19
|
status: ToolCallStatus.InProgress;
|
|
19
20
|
result: undefined;
|
|
20
21
|
}
|
|
21
22
|
| {
|
|
22
23
|
name: string;
|
|
24
|
+
toolCallId: string;
|
|
23
25
|
args: T;
|
|
24
26
|
status: ToolCallStatus.Executing;
|
|
25
27
|
result: undefined;
|
|
26
28
|
}
|
|
27
29
|
| {
|
|
28
30
|
name: string;
|
|
31
|
+
toolCallId: string;
|
|
29
32
|
args: T;
|
|
30
33
|
status: ToolCallStatus.Complete;
|
|
31
34
|
result: string;
|
|
@@ -12,18 +12,21 @@ export interface ReactToolCallRenderer<T = unknown> {
|
|
|
12
12
|
render: React.ComponentType<
|
|
13
13
|
| {
|
|
14
14
|
name: string;
|
|
15
|
+
toolCallId: string;
|
|
15
16
|
args: Partial<T>;
|
|
16
17
|
status: ToolCallStatus.InProgress;
|
|
17
18
|
result: undefined;
|
|
18
19
|
}
|
|
19
20
|
| {
|
|
20
21
|
name: string;
|
|
22
|
+
toolCallId: string;
|
|
21
23
|
args: T;
|
|
22
24
|
status: ToolCallStatus.Executing;
|
|
23
25
|
result: undefined;
|
|
24
26
|
}
|
|
25
27
|
| {
|
|
26
28
|
name: string;
|
|
29
|
+
toolCallId: string;
|
|
27
30
|
args: T;
|
|
28
31
|
status: ToolCallStatus.Complete;
|
|
29
32
|
result: string;
|