@copilotkitnext/react 0.0.8 → 0.0.9-alpha.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.mts +62 -19
- package/dist/index.d.ts +62 -19
- package/dist/index.js +290 -146
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +301 -158
- package/dist/index.mjs.map +1 -1
- package/dist/styles.css +1 -1
- package/package.json +6 -5
package/dist/index.mjs
CHANGED
|
@@ -11,6 +11,7 @@ import { Plus, Settings2, Mic, ArrowUp, X, Check } from "lucide-react";
|
|
|
11
11
|
|
|
12
12
|
// src/providers/CopilotChatConfigurationProvider.tsx
|
|
13
13
|
import { createContext, useContext } from "react";
|
|
14
|
+
import { DEFAULT_AGENT_ID } from "@copilotkitnext/shared";
|
|
14
15
|
import { jsx } from "react/jsx-runtime";
|
|
15
16
|
var CopilotChatDefaultLabels = {
|
|
16
17
|
chatInputPlaceholder: "Type a message...",
|
|
@@ -31,16 +32,20 @@ var CopilotChatDefaultLabels = {
|
|
|
31
32
|
chatDisclaimerText: "AI can make mistakes. Please verify important information."
|
|
32
33
|
};
|
|
33
34
|
var CopilotChatConfiguration = createContext(null);
|
|
34
|
-
var CopilotChatConfigurationProvider = ({
|
|
35
|
+
var CopilotChatConfigurationProvider = ({
|
|
36
|
+
children,
|
|
37
|
+
labels = {},
|
|
38
|
+
agentId,
|
|
39
|
+
threadId
|
|
40
|
+
}) => {
|
|
35
41
|
const mergedLabels = {
|
|
36
42
|
...CopilotChatDefaultLabels,
|
|
37
43
|
...labels
|
|
38
44
|
};
|
|
39
45
|
const configurationValue = {
|
|
40
46
|
labels: mergedLabels,
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
onChangeInput
|
|
47
|
+
agentId: agentId ?? DEFAULT_AGENT_ID,
|
|
48
|
+
threadId
|
|
44
49
|
};
|
|
45
50
|
return /* @__PURE__ */ jsx(CopilotChatConfiguration.Provider, { value: configurationValue, children });
|
|
46
51
|
};
|
|
@@ -490,10 +495,14 @@ function CopilotChatInput({
|
|
|
490
495
|
className,
|
|
491
496
|
...props
|
|
492
497
|
}) {
|
|
493
|
-
const
|
|
494
|
-
value
|
|
495
|
-
|
|
496
|
-
|
|
498
|
+
const isControlled = value !== void 0;
|
|
499
|
+
const [internalValue, setInternalValue] = useState(() => value ?? "");
|
|
500
|
+
useEffect2(() => {
|
|
501
|
+
if (!isControlled && value !== void 0) {
|
|
502
|
+
setInternalValue(value);
|
|
503
|
+
}
|
|
504
|
+
}, [isControlled, value]);
|
|
505
|
+
const resolvedValue = isControlled ? value ?? "" : internalValue;
|
|
497
506
|
const inputRef = useRef2(null);
|
|
498
507
|
const audioRecorderRef = useRef2(null);
|
|
499
508
|
useEffect2(() => {
|
|
@@ -510,7 +519,11 @@ function CopilotChatInput({
|
|
|
510
519
|
}
|
|
511
520
|
}, [mode]);
|
|
512
521
|
const handleChange = (e) => {
|
|
513
|
-
|
|
522
|
+
const nextValue = e.target.value;
|
|
523
|
+
if (!isControlled) {
|
|
524
|
+
setInternalValue(nextValue);
|
|
525
|
+
}
|
|
526
|
+
onChange?.(nextValue);
|
|
514
527
|
};
|
|
515
528
|
const handleKeyDown = (e) => {
|
|
516
529
|
if (e.key === "Enter" && !e.shiftKey) {
|
|
@@ -519,17 +532,25 @@ function CopilotChatInput({
|
|
|
519
532
|
}
|
|
520
533
|
};
|
|
521
534
|
const send = () => {
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
535
|
+
if (!onSubmitMessage) {
|
|
536
|
+
return;
|
|
537
|
+
}
|
|
538
|
+
const trimmed = resolvedValue.trim();
|
|
539
|
+
if (!trimmed) {
|
|
540
|
+
return;
|
|
541
|
+
}
|
|
542
|
+
onSubmitMessage(trimmed);
|
|
543
|
+
if (!isControlled) {
|
|
544
|
+
setInternalValue("");
|
|
545
|
+
onChange?.("");
|
|
546
|
+
}
|
|
547
|
+
if (inputRef.current) {
|
|
548
|
+
inputRef.current.focus();
|
|
528
549
|
}
|
|
529
550
|
};
|
|
530
551
|
const BoundTextArea = renderSlot(textArea, CopilotChatInput.TextArea, {
|
|
531
552
|
ref: inputRef,
|
|
532
|
-
value,
|
|
553
|
+
value: resolvedValue,
|
|
533
554
|
onChange: handleChange,
|
|
534
555
|
onKeyDown: handleKeyDown,
|
|
535
556
|
autoFocus
|
|
@@ -543,7 +564,7 @@ function CopilotChatInput({
|
|
|
543
564
|
);
|
|
544
565
|
const BoundSendButton = renderSlot(sendButton, CopilotChatInput.SendButton, {
|
|
545
566
|
onClick: send,
|
|
546
|
-
disabled: !
|
|
567
|
+
disabled: !resolvedValue.trim() || !onSubmitMessage
|
|
547
568
|
});
|
|
548
569
|
const BoundStartTranscribeButton = renderSlot(
|
|
549
570
|
startTranscribeButton,
|
|
@@ -879,7 +900,7 @@ import "katex/dist/katex.min.css";
|
|
|
879
900
|
import { completePartialMarkdown } from "@copilotkitnext/core";
|
|
880
901
|
|
|
881
902
|
// src/hooks/use-render-tool-call.tsx
|
|
882
|
-
import { useCallback } from "react";
|
|
903
|
+
import { useCallback, useEffect as useEffect4, useState as useState3 } from "react";
|
|
883
904
|
import { ToolCallStatus } from "@copilotkitnext/core";
|
|
884
905
|
|
|
885
906
|
// src/providers/CopilotKitProvider.tsx
|
|
@@ -892,6 +913,7 @@ import {
|
|
|
892
913
|
useReducer,
|
|
893
914
|
useRef as useRef3
|
|
894
915
|
} from "react";
|
|
916
|
+
import { z } from "zod";
|
|
895
917
|
import {
|
|
896
918
|
CopilotKitCore
|
|
897
919
|
} from "@copilotkitnext/core";
|
|
@@ -979,24 +1001,23 @@ var CopilotKitProvider = ({
|
|
|
979
1001
|
return { tools: processedTools, renderToolCalls: processedRenderToolCalls };
|
|
980
1002
|
}, [humanInTheLoopList]);
|
|
981
1003
|
const allTools = useMemo(() => {
|
|
982
|
-
const tools =
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
});
|
|
986
|
-
processedHumanInTheLoopTools.tools.forEach((tool) => {
|
|
987
|
-
tools[tool.name] = tool;
|
|
988
|
-
});
|
|
1004
|
+
const tools = [];
|
|
1005
|
+
tools.push(...frontendToolsList);
|
|
1006
|
+
tools.push(...processedHumanInTheLoopTools.tools);
|
|
989
1007
|
return tools;
|
|
990
1008
|
}, [frontendToolsList, processedHumanInTheLoopTools]);
|
|
991
1009
|
const allRenderToolCalls = useMemo(() => {
|
|
992
1010
|
const combined = [...renderToolCallsList];
|
|
993
1011
|
frontendToolsList.forEach((tool) => {
|
|
994
|
-
if (tool.render
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
|
|
1012
|
+
if (tool.render) {
|
|
1013
|
+
const args = tool.parameters || (tool.name === "*" ? z.any() : void 0);
|
|
1014
|
+
if (args) {
|
|
1015
|
+
combined.push({
|
|
1016
|
+
name: tool.name,
|
|
1017
|
+
args,
|
|
1018
|
+
render: tool.render
|
|
1019
|
+
});
|
|
1020
|
+
}
|
|
1000
1021
|
}
|
|
1001
1022
|
});
|
|
1002
1023
|
combined.push(...processedHumanInTheLoopTools.renderToolCalls);
|
|
@@ -1015,9 +1036,30 @@ var CopilotKitProvider = ({
|
|
|
1015
1036
|
return copilotkit2;
|
|
1016
1037
|
}, [allTools]);
|
|
1017
1038
|
useEffect3(() => {
|
|
1018
|
-
setCurrentRenderToolCalls(
|
|
1019
|
-
(
|
|
1020
|
-
|
|
1039
|
+
setCurrentRenderToolCalls((prev) => {
|
|
1040
|
+
const keyOf = (rc) => `${rc?.agentId ?? ""}:${rc?.name ?? ""}`;
|
|
1041
|
+
const computedMap = /* @__PURE__ */ new Map();
|
|
1042
|
+
for (const rc of allRenderToolCalls) {
|
|
1043
|
+
computedMap.set(keyOf(rc), rc);
|
|
1044
|
+
}
|
|
1045
|
+
const merged = [...computedMap.values()];
|
|
1046
|
+
for (const rc of prev) {
|
|
1047
|
+
const k = keyOf(rc);
|
|
1048
|
+
if (!computedMap.has(k)) merged.push(rc);
|
|
1049
|
+
}
|
|
1050
|
+
const sameLength = merged.length === prev.length;
|
|
1051
|
+
if (sameLength) {
|
|
1052
|
+
let same = true;
|
|
1053
|
+
for (let i = 0; i < merged.length; i++) {
|
|
1054
|
+
if (merged[i] !== prev[i]) {
|
|
1055
|
+
same = false;
|
|
1056
|
+
break;
|
|
1057
|
+
}
|
|
1058
|
+
}
|
|
1059
|
+
if (same) return prev;
|
|
1060
|
+
}
|
|
1061
|
+
return merged;
|
|
1062
|
+
});
|
|
1021
1063
|
}, [allRenderToolCalls]);
|
|
1022
1064
|
useEffect3(() => {
|
|
1023
1065
|
copilotkit.setRuntimeUrl(runtimeUrl);
|
|
@@ -1046,10 +1088,7 @@ var useCopilotKit = () => {
|
|
|
1046
1088
|
}
|
|
1047
1089
|
useEffect3(() => {
|
|
1048
1090
|
const unsubscribe = context.copilotkit.subscribe({
|
|
1049
|
-
|
|
1050
|
-
forceUpdate();
|
|
1051
|
-
},
|
|
1052
|
-
onRuntimeLoadError: () => {
|
|
1091
|
+
onRuntimeConnectionStatusChanged: () => {
|
|
1053
1092
|
forceUpdate();
|
|
1054
1093
|
}
|
|
1055
1094
|
});
|
|
@@ -1064,35 +1103,73 @@ var useCopilotKit = () => {
|
|
|
1064
1103
|
import { partialJSONParse } from "@copilotkitnext/shared";
|
|
1065
1104
|
import { jsx as jsx8 } from "react/jsx-runtime";
|
|
1066
1105
|
function useRenderToolCall() {
|
|
1067
|
-
const { currentRenderToolCalls } = useCopilotKit();
|
|
1106
|
+
const { currentRenderToolCalls, copilotkit } = useCopilotKit();
|
|
1107
|
+
const { agentId } = useCopilotChatConfiguration();
|
|
1108
|
+
const [executingToolCallIds, setExecutingToolCallIds] = useState3(() => /* @__PURE__ */ new Set());
|
|
1109
|
+
useEffect4(() => {
|
|
1110
|
+
const unsubscribe = copilotkit.subscribe({
|
|
1111
|
+
onToolExecutionStart: ({ toolCallId }) => {
|
|
1112
|
+
setExecutingToolCallIds((prev) => {
|
|
1113
|
+
if (prev.has(toolCallId)) return prev;
|
|
1114
|
+
const next = new Set(prev);
|
|
1115
|
+
next.add(toolCallId);
|
|
1116
|
+
return next;
|
|
1117
|
+
});
|
|
1118
|
+
},
|
|
1119
|
+
onToolExecutionEnd: ({ toolCallId }) => {
|
|
1120
|
+
setExecutingToolCallIds((prev) => {
|
|
1121
|
+
if (!prev.has(toolCallId)) return prev;
|
|
1122
|
+
const next = new Set(prev);
|
|
1123
|
+
next.delete(toolCallId);
|
|
1124
|
+
return next;
|
|
1125
|
+
});
|
|
1126
|
+
}
|
|
1127
|
+
});
|
|
1128
|
+
return () => unsubscribe();
|
|
1129
|
+
}, [copilotkit]);
|
|
1068
1130
|
const renderToolCall = useCallback(
|
|
1069
1131
|
({
|
|
1070
1132
|
toolCall,
|
|
1071
1133
|
toolMessage,
|
|
1072
|
-
|
|
1134
|
+
isRunning
|
|
1073
1135
|
}) => {
|
|
1074
|
-
const
|
|
1136
|
+
const exactMatches = currentRenderToolCalls.filter(
|
|
1075
1137
|
(rc) => rc.name === toolCall.function.name
|
|
1076
|
-
)
|
|
1138
|
+
);
|
|
1139
|
+
const renderConfig = exactMatches.find((rc) => rc.agentId === agentId) || exactMatches.find((rc) => !rc.agentId) || exactMatches[0] || currentRenderToolCalls.find((rc) => rc.name === "*");
|
|
1077
1140
|
if (!renderConfig) {
|
|
1078
1141
|
return null;
|
|
1079
1142
|
}
|
|
1080
1143
|
const RenderComponent = renderConfig.render;
|
|
1081
1144
|
const args = partialJSONParse(toolCall.function.arguments);
|
|
1145
|
+
const toolName = toolCall.function.name;
|
|
1082
1146
|
if (toolMessage) {
|
|
1083
1147
|
return /* @__PURE__ */ jsx8(
|
|
1084
1148
|
RenderComponent,
|
|
1085
1149
|
{
|
|
1150
|
+
name: toolName,
|
|
1086
1151
|
args,
|
|
1087
1152
|
status: ToolCallStatus.Complete,
|
|
1088
1153
|
result: toolMessage.content
|
|
1089
1154
|
},
|
|
1090
1155
|
toolCall.id
|
|
1091
1156
|
);
|
|
1092
|
-
} else if (
|
|
1157
|
+
} else if (executingToolCallIds.has(toolCall.id)) {
|
|
1093
1158
|
return /* @__PURE__ */ jsx8(
|
|
1094
1159
|
RenderComponent,
|
|
1095
1160
|
{
|
|
1161
|
+
name: toolName,
|
|
1162
|
+
args,
|
|
1163
|
+
status: ToolCallStatus.Executing,
|
|
1164
|
+
result: void 0
|
|
1165
|
+
},
|
|
1166
|
+
toolCall.id
|
|
1167
|
+
);
|
|
1168
|
+
} else if (isRunning) {
|
|
1169
|
+
return /* @__PURE__ */ jsx8(
|
|
1170
|
+
RenderComponent,
|
|
1171
|
+
{
|
|
1172
|
+
name: toolName,
|
|
1096
1173
|
args,
|
|
1097
1174
|
status: ToolCallStatus.InProgress,
|
|
1098
1175
|
result: void 0
|
|
@@ -1103,6 +1180,7 @@ function useRenderToolCall() {
|
|
|
1103
1180
|
return /* @__PURE__ */ jsx8(
|
|
1104
1181
|
RenderComponent,
|
|
1105
1182
|
{
|
|
1183
|
+
name: toolName,
|
|
1106
1184
|
args,
|
|
1107
1185
|
status: ToolCallStatus.Complete,
|
|
1108
1186
|
result: ""
|
|
@@ -1111,54 +1189,57 @@ function useRenderToolCall() {
|
|
|
1111
1189
|
);
|
|
1112
1190
|
}
|
|
1113
1191
|
},
|
|
1114
|
-
[currentRenderToolCalls]
|
|
1192
|
+
[currentRenderToolCalls, executingToolCallIds, agentId]
|
|
1115
1193
|
);
|
|
1116
1194
|
return renderToolCall;
|
|
1117
1195
|
}
|
|
1118
1196
|
|
|
1119
1197
|
// src/hooks/use-frontend-tool.tsx
|
|
1120
|
-
import { useEffect as
|
|
1198
|
+
import { useEffect as useEffect5 } from "react";
|
|
1121
1199
|
function useFrontendTool(tool) {
|
|
1122
|
-
const {
|
|
1123
|
-
|
|
1124
|
-
|
|
1200
|
+
const { copilotkit, setCurrentRenderToolCalls } = useCopilotKit();
|
|
1201
|
+
useEffect5(() => {
|
|
1202
|
+
const name = tool.name;
|
|
1203
|
+
if (copilotkit.getTool({ toolName: name, agentId: tool.agentId })) {
|
|
1125
1204
|
console.warn(
|
|
1126
|
-
`Tool '${
|
|
1205
|
+
`Tool '${name}' already exists for agent '${tool.agentId || "global"}'. Overriding with latest registration.`
|
|
1127
1206
|
);
|
|
1207
|
+
copilotkit.removeTool(name, tool.agentId);
|
|
1128
1208
|
}
|
|
1129
1209
|
copilotkit.addTool(tool);
|
|
1130
|
-
if (tool.render
|
|
1131
|
-
|
|
1132
|
-
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
-
|
|
1210
|
+
if (tool.render) {
|
|
1211
|
+
setCurrentRenderToolCalls((prev) => {
|
|
1212
|
+
const replaced = prev.filter(
|
|
1213
|
+
(rc) => !(rc.name === name && rc.agentId === tool.agentId)
|
|
1214
|
+
);
|
|
1215
|
+
return [
|
|
1216
|
+
...replaced,
|
|
1217
|
+
{
|
|
1218
|
+
name,
|
|
1219
|
+
args: tool.parameters,
|
|
1220
|
+
agentId: tool.agentId,
|
|
1221
|
+
render: tool.render
|
|
1222
|
+
}
|
|
1223
|
+
];
|
|
1224
|
+
});
|
|
1144
1225
|
}
|
|
1145
1226
|
return () => {
|
|
1146
|
-
copilotkit.removeTool(tool.
|
|
1147
|
-
setCurrentRenderToolCalls(
|
|
1148
|
-
(prev) => prev.filter((rc) => rc.name !== tool.name)
|
|
1149
|
-
);
|
|
1227
|
+
copilotkit.removeTool(name, tool.agentId);
|
|
1150
1228
|
};
|
|
1151
|
-
}, [tool, copilotkit,
|
|
1229
|
+
}, [tool.name, copilotkit, setCurrentRenderToolCalls]);
|
|
1152
1230
|
}
|
|
1153
1231
|
|
|
1154
1232
|
// src/hooks/use-human-in-the-loop.tsx
|
|
1155
|
-
import { useState as
|
|
1233
|
+
import { useState as useState4, useCallback as useCallback2, useRef as useRef4, useEffect as useEffect6 } from "react";
|
|
1156
1234
|
import React6 from "react";
|
|
1157
1235
|
function useHumanInTheLoop(tool) {
|
|
1158
|
-
const [status, setStatus] =
|
|
1236
|
+
const [status, setStatus] = useState4(
|
|
1159
1237
|
"inProgress"
|
|
1160
1238
|
);
|
|
1239
|
+
const statusRef = useRef4(status);
|
|
1161
1240
|
const resolvePromiseRef = useRef4(null);
|
|
1241
|
+
const { setCurrentRenderToolCalls } = useCopilotKit();
|
|
1242
|
+
statusRef.current = status;
|
|
1162
1243
|
const respond = useCallback2(async (result) => {
|
|
1163
1244
|
if (resolvePromiseRef.current) {
|
|
1164
1245
|
resolvePromiseRef.current(result);
|
|
@@ -1175,7 +1256,8 @@ function useHumanInTheLoop(tool) {
|
|
|
1175
1256
|
const RenderComponent = useCallback2(
|
|
1176
1257
|
(props) => {
|
|
1177
1258
|
const ToolComponent = tool.render;
|
|
1178
|
-
|
|
1259
|
+
const currentStatus = statusRef.current;
|
|
1260
|
+
if (currentStatus === "inProgress" && props.status === "inProgress") {
|
|
1179
1261
|
const enhancedProps = {
|
|
1180
1262
|
...props,
|
|
1181
1263
|
name: tool.name,
|
|
@@ -1183,7 +1265,7 @@ function useHumanInTheLoop(tool) {
|
|
|
1183
1265
|
respond: void 0
|
|
1184
1266
|
};
|
|
1185
1267
|
return React6.createElement(ToolComponent, enhancedProps);
|
|
1186
|
-
} else if (
|
|
1268
|
+
} else if (currentStatus === "executing" && props.status === "executing") {
|
|
1187
1269
|
const enhancedProps = {
|
|
1188
1270
|
...props,
|
|
1189
1271
|
name: tool.name,
|
|
@@ -1191,7 +1273,7 @@ function useHumanInTheLoop(tool) {
|
|
|
1191
1273
|
respond
|
|
1192
1274
|
};
|
|
1193
1275
|
return React6.createElement(ToolComponent, enhancedProps);
|
|
1194
|
-
} else if (
|
|
1276
|
+
} else if (currentStatus === "complete" && props.status === "complete") {
|
|
1195
1277
|
const enhancedProps = {
|
|
1196
1278
|
...props,
|
|
1197
1279
|
name: tool.name,
|
|
@@ -1202,7 +1284,7 @@ function useHumanInTheLoop(tool) {
|
|
|
1202
1284
|
}
|
|
1203
1285
|
return React6.createElement(ToolComponent, props);
|
|
1204
1286
|
},
|
|
1205
|
-
[tool.render, tool.name, tool.description,
|
|
1287
|
+
[tool.render, tool.name, tool.description, respond]
|
|
1206
1288
|
);
|
|
1207
1289
|
const frontendTool = {
|
|
1208
1290
|
...tool,
|
|
@@ -1210,51 +1292,84 @@ function useHumanInTheLoop(tool) {
|
|
|
1210
1292
|
render: RenderComponent
|
|
1211
1293
|
};
|
|
1212
1294
|
useFrontendTool(frontendTool);
|
|
1295
|
+
useEffect6(() => {
|
|
1296
|
+
return () => {
|
|
1297
|
+
setCurrentRenderToolCalls(
|
|
1298
|
+
(prev) => prev.filter(
|
|
1299
|
+
(rc) => rc.name !== tool.name || rc.agentId !== tool.agentId
|
|
1300
|
+
)
|
|
1301
|
+
);
|
|
1302
|
+
};
|
|
1303
|
+
}, [setCurrentRenderToolCalls, tool.name, tool.agentId]);
|
|
1213
1304
|
}
|
|
1214
1305
|
|
|
1215
1306
|
// src/hooks/use-agent.tsx
|
|
1216
|
-
import { useMemo as useMemo2, useEffect as
|
|
1217
|
-
import { DEFAULT_AGENT_ID } from "@copilotkitnext/shared";
|
|
1218
|
-
|
|
1219
|
-
|
|
1307
|
+
import { useMemo as useMemo2, useEffect as useEffect7, useReducer as useReducer2 } from "react";
|
|
1308
|
+
import { DEFAULT_AGENT_ID as DEFAULT_AGENT_ID2 } from "@copilotkitnext/shared";
|
|
1309
|
+
var ALL_UPDATES = [
|
|
1310
|
+
"OnMessagesChanged" /* OnMessagesChanged */,
|
|
1311
|
+
"OnStateChanged" /* OnStateChanged */,
|
|
1312
|
+
"OnRunStatusChanged" /* OnRunStatusChanged */
|
|
1313
|
+
];
|
|
1314
|
+
function useAgent({ agentId, updates } = {}) {
|
|
1315
|
+
agentId ??= DEFAULT_AGENT_ID2;
|
|
1220
1316
|
const { copilotkit } = useCopilotKit();
|
|
1221
1317
|
const [, forceUpdate] = useReducer2((x) => x + 1, 0);
|
|
1222
|
-
const
|
|
1318
|
+
const updateFlags = useMemo2(
|
|
1319
|
+
() => updates ?? ALL_UPDATES,
|
|
1320
|
+
[JSON.stringify(updates)]
|
|
1321
|
+
);
|
|
1223
1322
|
const agent = useMemo2(() => {
|
|
1224
1323
|
return copilotkit.getAgent(agentId);
|
|
1225
|
-
}, [
|
|
1226
|
-
|
|
1227
|
-
|
|
1228
|
-
|
|
1324
|
+
}, [
|
|
1325
|
+
agentId,
|
|
1326
|
+
copilotkit.agents,
|
|
1327
|
+
copilotkit.runtimeConnectionStatus,
|
|
1328
|
+
copilotkit
|
|
1329
|
+
]);
|
|
1330
|
+
useEffect7(() => {
|
|
1331
|
+
if (!agent) {
|
|
1332
|
+
return;
|
|
1333
|
+
}
|
|
1334
|
+
if (updateFlags.length === 0) {
|
|
1335
|
+
return;
|
|
1336
|
+
}
|
|
1337
|
+
const handlers = {};
|
|
1338
|
+
if (updateFlags.includes("OnMessagesChanged" /* OnMessagesChanged */)) {
|
|
1339
|
+
handlers.onMessagesChanged = () => {
|
|
1229
1340
|
forceUpdate();
|
|
1230
|
-
}
|
|
1231
|
-
|
|
1341
|
+
};
|
|
1342
|
+
}
|
|
1343
|
+
if (updateFlags.includes("OnStateChanged" /* OnStateChanged */)) {
|
|
1344
|
+
handlers.onStateChanged = () => {
|
|
1232
1345
|
forceUpdate();
|
|
1233
|
-
}
|
|
1234
|
-
|
|
1235
|
-
|
|
1236
|
-
|
|
1237
|
-
|
|
1238
|
-
|
|
1239
|
-
|
|
1240
|
-
|
|
1241
|
-
|
|
1242
|
-
|
|
1243
|
-
|
|
1244
|
-
|
|
1245
|
-
|
|
1346
|
+
};
|
|
1347
|
+
}
|
|
1348
|
+
if (updateFlags.includes("OnRunStatusChanged" /* OnRunStatusChanged */)) {
|
|
1349
|
+
handlers.onRunInitialized = () => {
|
|
1350
|
+
forceUpdate();
|
|
1351
|
+
};
|
|
1352
|
+
handlers.onRunFinalized = () => {
|
|
1353
|
+
forceUpdate();
|
|
1354
|
+
};
|
|
1355
|
+
handlers.onRunFailed = () => {
|
|
1356
|
+
forceUpdate();
|
|
1357
|
+
};
|
|
1358
|
+
}
|
|
1359
|
+
const subscription = agent.subscribe(handlers);
|
|
1360
|
+
return () => subscription.unsubscribe();
|
|
1361
|
+
}, [agent, forceUpdate, JSON.stringify(updateFlags)]);
|
|
1246
1362
|
return {
|
|
1247
|
-
agent
|
|
1248
|
-
isRunning
|
|
1363
|
+
agent
|
|
1249
1364
|
};
|
|
1250
1365
|
}
|
|
1251
1366
|
|
|
1252
1367
|
// src/hooks/use-agent-context.tsx
|
|
1253
|
-
import { useEffect as
|
|
1368
|
+
import { useEffect as useEffect8 } from "react";
|
|
1254
1369
|
function useAgentContext(context) {
|
|
1255
1370
|
const { description, value } = context;
|
|
1256
1371
|
const { copilotkit } = useCopilotKit();
|
|
1257
|
-
|
|
1372
|
+
useEffect8(() => {
|
|
1258
1373
|
if (!copilotkit) return;
|
|
1259
1374
|
const id = copilotkit.addContext(context);
|
|
1260
1375
|
return () => {
|
|
@@ -1269,7 +1384,7 @@ import { Fragment as Fragment2, jsx as jsx9 } from "react/jsx-runtime";
|
|
|
1269
1384
|
function CopilotChatToolCallsView({
|
|
1270
1385
|
message,
|
|
1271
1386
|
messages = [],
|
|
1272
|
-
|
|
1387
|
+
isRunning = false
|
|
1273
1388
|
}) {
|
|
1274
1389
|
const renderToolCall = useRenderToolCall();
|
|
1275
1390
|
if (!message.toolCalls || message.toolCalls.length === 0) {
|
|
@@ -1282,7 +1397,7 @@ function CopilotChatToolCallsView({
|
|
|
1282
1397
|
return /* @__PURE__ */ jsx9(React7.Fragment, { children: renderToolCall({
|
|
1283
1398
|
toolCall,
|
|
1284
1399
|
toolMessage,
|
|
1285
|
-
|
|
1400
|
+
isRunning
|
|
1286
1401
|
}) }, toolCall.id);
|
|
1287
1402
|
}) });
|
|
1288
1403
|
}
|
|
@@ -1293,7 +1408,7 @@ import { Fragment as Fragment3, jsx as jsx10, jsxs as jsxs4 } from "react/jsx-ru
|
|
|
1293
1408
|
function CopilotChatAssistantMessage({
|
|
1294
1409
|
message,
|
|
1295
1410
|
messages,
|
|
1296
|
-
|
|
1411
|
+
isRunning,
|
|
1297
1412
|
onThumbsUp,
|
|
1298
1413
|
onThumbsDown,
|
|
1299
1414
|
onReadAloud,
|
|
@@ -1382,9 +1497,11 @@ function CopilotChatAssistantMessage({
|
|
|
1382
1497
|
{
|
|
1383
1498
|
message,
|
|
1384
1499
|
messages,
|
|
1385
|
-
|
|
1500
|
+
isRunning
|
|
1386
1501
|
}
|
|
1387
1502
|
);
|
|
1503
|
+
const hasContent = !!(message.content && message.content.trim().length > 0);
|
|
1504
|
+
const shouldShowToolbar = toolbarVisible && hasContent;
|
|
1388
1505
|
if (children) {
|
|
1389
1506
|
return /* @__PURE__ */ jsx10(Fragment3, { children: children({
|
|
1390
1507
|
markdownRenderer: boundMarkdownRenderer,
|
|
@@ -1397,13 +1514,13 @@ function CopilotChatAssistantMessage({
|
|
|
1397
1514
|
regenerateButton: boundRegenerateButton,
|
|
1398
1515
|
message,
|
|
1399
1516
|
messages,
|
|
1400
|
-
|
|
1517
|
+
isRunning,
|
|
1401
1518
|
onThumbsUp,
|
|
1402
1519
|
onThumbsDown,
|
|
1403
1520
|
onReadAloud,
|
|
1404
1521
|
onRegenerate,
|
|
1405
1522
|
additionalToolbarItems,
|
|
1406
|
-
toolbarVisible
|
|
1523
|
+
toolbarVisible: shouldShowToolbar
|
|
1407
1524
|
}) });
|
|
1408
1525
|
}
|
|
1409
1526
|
return /* @__PURE__ */ jsxs4(
|
|
@@ -1418,7 +1535,7 @@ function CopilotChatAssistantMessage({
|
|
|
1418
1535
|
children: [
|
|
1419
1536
|
boundMarkdownRenderer,
|
|
1420
1537
|
boundToolCallsView,
|
|
1421
|
-
|
|
1538
|
+
shouldShowToolbar && boundToolbar
|
|
1422
1539
|
]
|
|
1423
1540
|
}
|
|
1424
1541
|
);
|
|
@@ -1870,7 +1987,7 @@ function CopilotChatMessageView({
|
|
|
1870
1987
|
assistantMessage,
|
|
1871
1988
|
userMessage,
|
|
1872
1989
|
cursor,
|
|
1873
|
-
|
|
1990
|
+
isRunning = false,
|
|
1874
1991
|
children,
|
|
1875
1992
|
className,
|
|
1876
1993
|
...props
|
|
@@ -1881,7 +1998,7 @@ function CopilotChatMessageView({
|
|
|
1881
1998
|
key: message.id,
|
|
1882
1999
|
message,
|
|
1883
2000
|
messages,
|
|
1884
|
-
|
|
2001
|
+
isRunning
|
|
1885
2002
|
});
|
|
1886
2003
|
} else if (message.role === "user") {
|
|
1887
2004
|
return renderSlot(userMessage, CopilotChatUserMessage_default, {
|
|
@@ -1892,11 +2009,11 @@ function CopilotChatMessageView({
|
|
|
1892
2009
|
return;
|
|
1893
2010
|
}).filter(Boolean);
|
|
1894
2011
|
if (children) {
|
|
1895
|
-
return children({ messageElements, messages,
|
|
2012
|
+
return children({ messageElements, messages, isRunning });
|
|
1896
2013
|
}
|
|
1897
2014
|
return /* @__PURE__ */ jsxs6("div", { className: twMerge6("flex flex-col", className), ...props, children: [
|
|
1898
2015
|
messageElements,
|
|
1899
|
-
|
|
2016
|
+
isRunning && renderSlot(cursor, CopilotChatMessageView.Cursor, {})
|
|
1900
2017
|
] });
|
|
1901
2018
|
}
|
|
1902
2019
|
CopilotChatMessageView.Cursor = function Cursor({
|
|
@@ -1917,7 +2034,7 @@ CopilotChatMessageView.Cursor = function Cursor({
|
|
|
1917
2034
|
var CopilotChatMessageView_default = CopilotChatMessageView;
|
|
1918
2035
|
|
|
1919
2036
|
// src/components/chat/CopilotChatView.tsx
|
|
1920
|
-
import React8, { useRef as useRef5, useState as useState7, useEffect as
|
|
2037
|
+
import React8, { useRef as useRef5, useState as useState7, useEffect as useEffect9 } from "react";
|
|
1921
2038
|
import { twMerge as twMerge7 } from "tailwind-merge";
|
|
1922
2039
|
import { StickToBottom, useStickToBottom, useStickToBottomContext } from "use-stick-to-bottom";
|
|
1923
2040
|
import { ChevronDown } from "lucide-react";
|
|
@@ -1932,6 +2049,8 @@ function CopilotChatView({
|
|
|
1932
2049
|
disclaimer,
|
|
1933
2050
|
messages = [],
|
|
1934
2051
|
autoScroll = true,
|
|
2052
|
+
inputProps,
|
|
2053
|
+
isRunning = false,
|
|
1935
2054
|
children,
|
|
1936
2055
|
className,
|
|
1937
2056
|
...props
|
|
@@ -1940,7 +2059,7 @@ function CopilotChatView({
|
|
|
1940
2059
|
const [inputContainerHeight, setInputContainerHeight] = useState7(0);
|
|
1941
2060
|
const [isResizing, setIsResizing] = useState7(false);
|
|
1942
2061
|
const resizeTimeoutRef = useRef5(null);
|
|
1943
|
-
|
|
2062
|
+
useEffect9(() => {
|
|
1944
2063
|
const element = inputContainerRef.current;
|
|
1945
2064
|
if (!element) return;
|
|
1946
2065
|
const resizeObserver = new ResizeObserver((entries) => {
|
|
@@ -1971,9 +2090,14 @@ function CopilotChatView({
|
|
|
1971
2090
|
};
|
|
1972
2091
|
}, []);
|
|
1973
2092
|
const BoundMessageView = renderSlot(messageView, CopilotChatMessageView_default, {
|
|
1974
|
-
messages
|
|
2093
|
+
messages,
|
|
2094
|
+
isRunning
|
|
1975
2095
|
});
|
|
1976
|
-
const BoundInput = renderSlot(
|
|
2096
|
+
const BoundInput = renderSlot(
|
|
2097
|
+
input,
|
|
2098
|
+
CopilotChatInput_default,
|
|
2099
|
+
inputProps ?? {}
|
|
2100
|
+
);
|
|
1977
2101
|
const BoundFeather = renderSlot(feather, CopilotChatView.Feather, {});
|
|
1978
2102
|
const BoundScrollView = renderSlot(scrollView, CopilotChatView.ScrollView, {
|
|
1979
2103
|
autoScroll,
|
|
@@ -2055,10 +2179,10 @@ function CopilotChatView({
|
|
|
2055
2179
|
const [hasMounted, setHasMounted] = useState7(false);
|
|
2056
2180
|
const { scrollRef, contentRef, scrollToBottom } = useStickToBottom();
|
|
2057
2181
|
const [showScrollButton, setShowScrollButton] = useState7(false);
|
|
2058
|
-
|
|
2182
|
+
useEffect9(() => {
|
|
2059
2183
|
setHasMounted(true);
|
|
2060
2184
|
}, []);
|
|
2061
|
-
|
|
2185
|
+
useEffect9(() => {
|
|
2062
2186
|
if (autoScroll) return;
|
|
2063
2187
|
const scrollElement = scrollRef.current;
|
|
2064
2188
|
if (!scrollElement) return;
|
|
@@ -2191,83 +2315,101 @@ function CopilotChatView({
|
|
|
2191
2315
|
var CopilotChatView_default = CopilotChatView;
|
|
2192
2316
|
|
|
2193
2317
|
// src/components/chat/CopilotChat.tsx
|
|
2194
|
-
import { DEFAULT_AGENT_ID as
|
|
2195
|
-
import { useCallback as useCallback3,
|
|
2318
|
+
import { DEFAULT_AGENT_ID as DEFAULT_AGENT_ID3, randomUUID } from "@copilotkitnext/shared";
|
|
2319
|
+
import { useCallback as useCallback3, useEffect as useEffect10, useMemo as useMemo3 } from "react";
|
|
2196
2320
|
import { merge } from "ts-deepmerge";
|
|
2321
|
+
import { AGUIConnectNotImplementedError } from "@ag-ui/client";
|
|
2197
2322
|
import { jsx as jsx14 } from "react/jsx-runtime";
|
|
2198
2323
|
function CopilotChat({
|
|
2199
|
-
agentId =
|
|
2324
|
+
agentId = DEFAULT_AGENT_ID3,
|
|
2200
2325
|
threadId,
|
|
2201
2326
|
...props
|
|
2202
2327
|
}) {
|
|
2203
2328
|
const { agent } = useAgent({ agentId });
|
|
2204
|
-
const
|
|
2205
|
-
|
|
2206
|
-
|
|
2207
|
-
|
|
2208
|
-
|
|
2209
|
-
|
|
2210
|
-
|
|
2211
|
-
|
|
2212
|
-
|
|
2213
|
-
|
|
2214
|
-
|
|
2215
|
-
|
|
2216
|
-
},
|
|
2217
|
-
subscriber
|
|
2218
|
-
);
|
|
2219
|
-
setIsLoading(false);
|
|
2329
|
+
const { copilotkit } = useCopilotKit();
|
|
2330
|
+
const resolvedThreadId = useMemo3(() => threadId ?? randomUUID(), [threadId]);
|
|
2331
|
+
useEffect10(() => {
|
|
2332
|
+
const connect = async (agent2) => {
|
|
2333
|
+
try {
|
|
2334
|
+
await copilotkit.connectAgent({ agent: agent2, agentId });
|
|
2335
|
+
} catch (error) {
|
|
2336
|
+
if (error instanceof AGUIConnectNotImplementedError) {
|
|
2337
|
+
} else {
|
|
2338
|
+
throw error;
|
|
2339
|
+
}
|
|
2340
|
+
}
|
|
2220
2341
|
};
|
|
2221
2342
|
if (agent) {
|
|
2222
|
-
agent.threadId =
|
|
2223
|
-
|
|
2224
|
-
connect();
|
|
2225
|
-
} else {
|
|
2226
|
-
setIsLoading(false);
|
|
2227
|
-
}
|
|
2343
|
+
agent.threadId = resolvedThreadId;
|
|
2344
|
+
connect(agent);
|
|
2228
2345
|
}
|
|
2229
2346
|
return () => {
|
|
2230
2347
|
};
|
|
2231
|
-
}, [
|
|
2232
|
-
const [inputValue, setInputValue] = useState8("");
|
|
2348
|
+
}, [resolvedThreadId, agent, copilotkit, agentId]);
|
|
2233
2349
|
const onSubmitInput = useCallback3(
|
|
2234
2350
|
async (value) => {
|
|
2235
|
-
setInputValue("");
|
|
2236
2351
|
agent?.addMessage({
|
|
2237
2352
|
id: randomUUID(),
|
|
2238
2353
|
role: "user",
|
|
2239
2354
|
content: value
|
|
2240
2355
|
});
|
|
2241
|
-
|
|
2242
|
-
|
|
2243
|
-
|
|
2356
|
+
if (agent) {
|
|
2357
|
+
try {
|
|
2358
|
+
await copilotkit.runAgent({ agent, agentId });
|
|
2359
|
+
} catch (error) {
|
|
2360
|
+
console.error("CopilotChat: runAgent failed", error);
|
|
2361
|
+
}
|
|
2362
|
+
}
|
|
2244
2363
|
},
|
|
2245
|
-
[agent]
|
|
2364
|
+
[agent, copilotkit, agentId]
|
|
2246
2365
|
);
|
|
2366
|
+
const {
|
|
2367
|
+
inputProps: providedInputProps,
|
|
2368
|
+
messageView: providedMessageView,
|
|
2369
|
+
...restProps
|
|
2370
|
+
} = props;
|
|
2247
2371
|
const mergedProps = merge(
|
|
2248
2372
|
{
|
|
2249
|
-
|
|
2373
|
+
isRunning: agent?.isRunning ?? false
|
|
2250
2374
|
},
|
|
2251
2375
|
{
|
|
2252
|
-
...
|
|
2253
|
-
...typeof
|
|
2376
|
+
...restProps,
|
|
2377
|
+
...typeof providedMessageView === "string" ? { messageView: { className: providedMessageView } } : providedMessageView !== void 0 ? { messageView: providedMessageView } : {}
|
|
2254
2378
|
}
|
|
2255
2379
|
);
|
|
2256
2380
|
return /* @__PURE__ */ jsx14(
|
|
2257
2381
|
CopilotChatConfigurationProvider,
|
|
2258
2382
|
{
|
|
2259
|
-
|
|
2260
|
-
|
|
2261
|
-
onChangeInput: setInputValue,
|
|
2383
|
+
agentId,
|
|
2384
|
+
threadId: resolvedThreadId,
|
|
2262
2385
|
children: /* @__PURE__ */ jsx14(
|
|
2263
2386
|
CopilotChatView,
|
|
2264
2387
|
{
|
|
2265
|
-
...{
|
|
2388
|
+
...{
|
|
2389
|
+
messages: agent?.messages ?? [],
|
|
2390
|
+
inputProps: {
|
|
2391
|
+
onSubmitMessage: onSubmitInput,
|
|
2392
|
+
...providedInputProps
|
|
2393
|
+
},
|
|
2394
|
+
...mergedProps
|
|
2395
|
+
}
|
|
2266
2396
|
}
|
|
2267
2397
|
)
|
|
2268
2398
|
}
|
|
2269
2399
|
);
|
|
2270
2400
|
}
|
|
2401
|
+
|
|
2402
|
+
// src/types/defineToolCallRender.ts
|
|
2403
|
+
import { z as z2 } from "zod";
|
|
2404
|
+
function defineToolCallRender(def) {
|
|
2405
|
+
const argsSchema = def.name === "*" && !def.args ? z2.any() : def.args;
|
|
2406
|
+
return {
|
|
2407
|
+
name: def.name,
|
|
2408
|
+
args: argsSchema,
|
|
2409
|
+
render: def.render,
|
|
2410
|
+
...def.agentId ? { agentId: def.agentId } : {}
|
|
2411
|
+
};
|
|
2412
|
+
}
|
|
2271
2413
|
export {
|
|
2272
2414
|
AudioRecorderError,
|
|
2273
2415
|
CopilotChat,
|
|
@@ -2280,6 +2422,7 @@ export {
|
|
|
2280
2422
|
CopilotChatUserMessage_default as CopilotChatUserMessage,
|
|
2281
2423
|
CopilotChatView_default as CopilotChatView,
|
|
2282
2424
|
CopilotKitProvider,
|
|
2425
|
+
defineToolCallRender,
|
|
2283
2426
|
useAgent,
|
|
2284
2427
|
useAgentContext,
|
|
2285
2428
|
useCopilotChatConfiguration,
|