@copilotkitnext/react 0.0.7 → 0.0.9-alpha.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/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 = ({ children, labels = {}, inputValue, onSubmitInput, onChangeInput }) => {
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
- inputValue,
42
- onSubmitInput,
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 { inputValue, onSubmitInput, onChangeInput } = useCopilotChatConfiguration();
494
- value ??= inputValue;
495
- onSubmitMessage ??= onSubmitInput;
496
- onChange ??= onChangeInput;
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
- onChange?.(e.target.value);
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
- const trimmed = value?.trim();
523
- if (trimmed) {
524
- onSubmitMessage?.(trimmed);
525
- if (inputRef.current) {
526
- inputRef.current.focus();
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: !value?.trim() || !onSubmitMessage
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
@@ -979,13 +1000,9 @@ var CopilotKitProvider = ({
979
1000
  return { tools: processedTools, renderToolCalls: processedRenderToolCalls };
980
1001
  }, [humanInTheLoopList]);
981
1002
  const allTools = useMemo(() => {
982
- const tools = {};
983
- frontendToolsList.forEach((tool) => {
984
- tools[tool.name] = tool;
985
- });
986
- processedHumanInTheLoopTools.tools.forEach((tool) => {
987
- tools[tool.name] = tool;
988
- });
1003
+ const tools = [];
1004
+ tools.push(...frontendToolsList);
1005
+ tools.push(...processedHumanInTheLoopTools.tools);
989
1006
  return tools;
990
1007
  }, [frontendToolsList, processedHumanInTheLoopTools]);
991
1008
  const allRenderToolCalls = useMemo(() => {
@@ -1015,9 +1032,30 @@ var CopilotKitProvider = ({
1015
1032
  return copilotkit2;
1016
1033
  }, [allTools]);
1017
1034
  useEffect3(() => {
1018
- setCurrentRenderToolCalls(
1019
- (prev) => prev === allRenderToolCalls ? prev : allRenderToolCalls
1020
- );
1035
+ setCurrentRenderToolCalls((prev) => {
1036
+ const keyOf = (rc) => `${rc?.agentId ?? ""}:${rc?.name ?? ""}`;
1037
+ const computedMap = /* @__PURE__ */ new Map();
1038
+ for (const rc of allRenderToolCalls) {
1039
+ computedMap.set(keyOf(rc), rc);
1040
+ }
1041
+ const merged = [...computedMap.values()];
1042
+ for (const rc of prev) {
1043
+ const k = keyOf(rc);
1044
+ if (!computedMap.has(k)) merged.push(rc);
1045
+ }
1046
+ const sameLength = merged.length === prev.length;
1047
+ if (sameLength) {
1048
+ let same = true;
1049
+ for (let i = 0; i < merged.length; i++) {
1050
+ if (merged[i] !== prev[i]) {
1051
+ same = false;
1052
+ break;
1053
+ }
1054
+ }
1055
+ if (same) return prev;
1056
+ }
1057
+ return merged;
1058
+ });
1021
1059
  }, [allRenderToolCalls]);
1022
1060
  useEffect3(() => {
1023
1061
  copilotkit.setRuntimeUrl(runtimeUrl);
@@ -1046,10 +1084,7 @@ var useCopilotKit = () => {
1046
1084
  }
1047
1085
  useEffect3(() => {
1048
1086
  const unsubscribe = context.copilotkit.subscribe({
1049
- onRuntimeLoaded: () => {
1050
- forceUpdate();
1051
- },
1052
- onRuntimeLoadError: () => {
1087
+ onRuntimeConnectionStatusChanged: () => {
1053
1088
  forceUpdate();
1054
1089
  }
1055
1090
  });
@@ -1064,35 +1099,73 @@ var useCopilotKit = () => {
1064
1099
  import { partialJSONParse } from "@copilotkitnext/shared";
1065
1100
  import { jsx as jsx8 } from "react/jsx-runtime";
1066
1101
  function useRenderToolCall() {
1067
- const { currentRenderToolCalls } = useCopilotKit();
1102
+ const { currentRenderToolCalls, copilotkit } = useCopilotKit();
1103
+ const { agentId } = useCopilotChatConfiguration();
1104
+ const [executingToolCallIds, setExecutingToolCallIds] = useState3(() => /* @__PURE__ */ new Set());
1105
+ useEffect4(() => {
1106
+ const unsubscribe = copilotkit.subscribe({
1107
+ onToolExecutionStart: ({ toolCallId }) => {
1108
+ setExecutingToolCallIds((prev) => {
1109
+ if (prev.has(toolCallId)) return prev;
1110
+ const next = new Set(prev);
1111
+ next.add(toolCallId);
1112
+ return next;
1113
+ });
1114
+ },
1115
+ onToolExecutionEnd: ({ toolCallId }) => {
1116
+ setExecutingToolCallIds((prev) => {
1117
+ if (!prev.has(toolCallId)) return prev;
1118
+ const next = new Set(prev);
1119
+ next.delete(toolCallId);
1120
+ return next;
1121
+ });
1122
+ }
1123
+ });
1124
+ return () => unsubscribe();
1125
+ }, [copilotkit]);
1068
1126
  const renderToolCall = useCallback(
1069
1127
  ({
1070
1128
  toolCall,
1071
1129
  toolMessage,
1072
- isLoading
1130
+ isRunning
1073
1131
  }) => {
1074
- const renderConfig = currentRenderToolCalls.find(
1132
+ const exactMatches = currentRenderToolCalls.filter(
1075
1133
  (rc) => rc.name === toolCall.function.name
1076
- ) || currentRenderToolCalls.find((rc) => rc.name === "*");
1134
+ );
1135
+ const renderConfig = exactMatches.find((rc) => rc.agentId === agentId) || exactMatches.find((rc) => !rc.agentId) || exactMatches[0] || currentRenderToolCalls.find((rc) => rc.name === "*");
1077
1136
  if (!renderConfig) {
1078
1137
  return null;
1079
1138
  }
1080
1139
  const RenderComponent = renderConfig.render;
1081
1140
  const args = partialJSONParse(toolCall.function.arguments);
1141
+ const toolName = toolCall.function.name;
1082
1142
  if (toolMessage) {
1083
1143
  return /* @__PURE__ */ jsx8(
1084
1144
  RenderComponent,
1085
1145
  {
1146
+ name: toolName,
1086
1147
  args,
1087
1148
  status: ToolCallStatus.Complete,
1088
1149
  result: toolMessage.content
1089
1150
  },
1090
1151
  toolCall.id
1091
1152
  );
1092
- } else if (isLoading) {
1153
+ } else if (executingToolCallIds.has(toolCall.id)) {
1154
+ return /* @__PURE__ */ jsx8(
1155
+ RenderComponent,
1156
+ {
1157
+ name: toolName,
1158
+ args,
1159
+ status: ToolCallStatus.Executing,
1160
+ result: void 0
1161
+ },
1162
+ toolCall.id
1163
+ );
1164
+ } else if (isRunning) {
1093
1165
  return /* @__PURE__ */ jsx8(
1094
1166
  RenderComponent,
1095
1167
  {
1168
+ name: toolName,
1096
1169
  args,
1097
1170
  status: ToolCallStatus.InProgress,
1098
1171
  result: void 0
@@ -1103,6 +1176,7 @@ function useRenderToolCall() {
1103
1176
  return /* @__PURE__ */ jsx8(
1104
1177
  RenderComponent,
1105
1178
  {
1179
+ name: toolName,
1106
1180
  args,
1107
1181
  status: ToolCallStatus.Complete,
1108
1182
  result: ""
@@ -1111,54 +1185,57 @@ function useRenderToolCall() {
1111
1185
  );
1112
1186
  }
1113
1187
  },
1114
- [currentRenderToolCalls]
1188
+ [currentRenderToolCalls, executingToolCallIds, agentId]
1115
1189
  );
1116
1190
  return renderToolCall;
1117
1191
  }
1118
1192
 
1119
1193
  // src/hooks/use-frontend-tool.tsx
1120
- import { useEffect as useEffect4 } from "react";
1194
+ import { useEffect as useEffect5 } from "react";
1121
1195
  function useFrontendTool(tool) {
1122
- const { renderToolCalls, copilotkit, setCurrentRenderToolCalls } = useCopilotKit();
1123
- useEffect4(() => {
1124
- if (tool.name in copilotkit.tools) {
1196
+ const { copilotkit, setCurrentRenderToolCalls } = useCopilotKit();
1197
+ useEffect5(() => {
1198
+ const name = tool.name;
1199
+ if (copilotkit.getTool({ toolName: name, agentId: tool.agentId })) {
1125
1200
  console.warn(
1126
- `Tool '${tool.name}' already exists. It will be overridden.`
1201
+ `Tool '${name}' already exists for agent '${tool.agentId || "global"}'. Overriding with latest registration.`
1127
1202
  );
1203
+ copilotkit.removeTool(name, tool.agentId);
1128
1204
  }
1129
1205
  copilotkit.addTool(tool);
1130
- if (tool.render && tool.name in renderToolCalls) {
1131
- console.warn(
1132
- `Render component for tool '${tool.name}' already exists. It will be overridden.`
1133
- );
1134
- }
1135
- if (tool.render && tool.parameters) {
1136
- setCurrentRenderToolCalls((prev) => [
1137
- ...prev,
1138
- {
1139
- name: tool.name,
1140
- args: tool.parameters,
1141
- render: tool.render
1142
- }
1143
- ]);
1206
+ if (tool.render) {
1207
+ setCurrentRenderToolCalls((prev) => {
1208
+ const replaced = prev.filter(
1209
+ (rc) => !(rc.name === name && rc.agentId === tool.agentId)
1210
+ );
1211
+ return [
1212
+ ...replaced,
1213
+ {
1214
+ name,
1215
+ args: tool.parameters,
1216
+ agentId: tool.agentId,
1217
+ render: tool.render
1218
+ }
1219
+ ];
1220
+ });
1144
1221
  }
1145
1222
  return () => {
1146
- copilotkit.removeTool(tool.name);
1147
- setCurrentRenderToolCalls(
1148
- (prev) => prev.filter((rc) => rc.name !== tool.name)
1149
- );
1223
+ copilotkit.removeTool(name, tool.agentId);
1150
1224
  };
1151
- }, [tool, copilotkit, renderToolCalls, setCurrentRenderToolCalls]);
1225
+ }, [tool.name, copilotkit, setCurrentRenderToolCalls]);
1152
1226
  }
1153
1227
 
1154
1228
  // src/hooks/use-human-in-the-loop.tsx
1155
- import { useState as useState3, useCallback as useCallback2, useRef as useRef4 } from "react";
1229
+ import { useState as useState4, useCallback as useCallback2, useRef as useRef4, useEffect as useEffect6 } from "react";
1156
1230
  import React6 from "react";
1157
1231
  function useHumanInTheLoop(tool) {
1158
- const [status, setStatus] = useState3(
1232
+ const [status, setStatus] = useState4(
1159
1233
  "inProgress"
1160
1234
  );
1235
+ const statusRef = useRef4(status);
1161
1236
  const resolvePromiseRef = useRef4(null);
1237
+ const { setCurrentRenderToolCalls } = useCopilotKit();
1238
+ statusRef.current = status;
1162
1239
  const respond = useCallback2(async (result) => {
1163
1240
  if (resolvePromiseRef.current) {
1164
1241
  resolvePromiseRef.current(result);
@@ -1175,7 +1252,8 @@ function useHumanInTheLoop(tool) {
1175
1252
  const RenderComponent = useCallback2(
1176
1253
  (props) => {
1177
1254
  const ToolComponent = tool.render;
1178
- if (status === "inProgress" && props.status === "inProgress") {
1255
+ const currentStatus = statusRef.current;
1256
+ if (currentStatus === "inProgress" && props.status === "inProgress") {
1179
1257
  const enhancedProps = {
1180
1258
  ...props,
1181
1259
  name: tool.name,
@@ -1183,7 +1261,7 @@ function useHumanInTheLoop(tool) {
1183
1261
  respond: void 0
1184
1262
  };
1185
1263
  return React6.createElement(ToolComponent, enhancedProps);
1186
- } else if (status === "executing" && props.status === "executing") {
1264
+ } else if (currentStatus === "executing" && props.status === "executing") {
1187
1265
  const enhancedProps = {
1188
1266
  ...props,
1189
1267
  name: tool.name,
@@ -1191,7 +1269,7 @@ function useHumanInTheLoop(tool) {
1191
1269
  respond
1192
1270
  };
1193
1271
  return React6.createElement(ToolComponent, enhancedProps);
1194
- } else if (status === "complete" && props.status === "complete") {
1272
+ } else if (currentStatus === "complete" && props.status === "complete") {
1195
1273
  const enhancedProps = {
1196
1274
  ...props,
1197
1275
  name: tool.name,
@@ -1202,7 +1280,7 @@ function useHumanInTheLoop(tool) {
1202
1280
  }
1203
1281
  return React6.createElement(ToolComponent, props);
1204
1282
  },
1205
- [tool.render, tool.name, tool.description, status, respond]
1283
+ [tool.render, tool.name, tool.description, respond]
1206
1284
  );
1207
1285
  const frontendTool = {
1208
1286
  ...tool,
@@ -1210,51 +1288,84 @@ function useHumanInTheLoop(tool) {
1210
1288
  render: RenderComponent
1211
1289
  };
1212
1290
  useFrontendTool(frontendTool);
1291
+ useEffect6(() => {
1292
+ return () => {
1293
+ setCurrentRenderToolCalls(
1294
+ (prev) => prev.filter(
1295
+ (rc) => rc.name !== tool.name || rc.agentId !== tool.agentId
1296
+ )
1297
+ );
1298
+ };
1299
+ }, [setCurrentRenderToolCalls, tool.name, tool.agentId]);
1213
1300
  }
1214
1301
 
1215
1302
  // src/hooks/use-agent.tsx
1216
- import { useMemo as useMemo2, useEffect as useEffect5, useReducer as useReducer2, useState as useState4 } from "react";
1217
- import { DEFAULT_AGENT_ID } from "@copilotkitnext/shared";
1218
- function useAgent({ agentId } = {}) {
1219
- agentId ??= DEFAULT_AGENT_ID;
1303
+ import { useMemo as useMemo2, useEffect as useEffect7, useReducer as useReducer2 } from "react";
1304
+ import { DEFAULT_AGENT_ID as DEFAULT_AGENT_ID2 } from "@copilotkitnext/shared";
1305
+ var ALL_UPDATES = [
1306
+ "OnMessagesChanged" /* OnMessagesChanged */,
1307
+ "OnStateChanged" /* OnStateChanged */,
1308
+ "OnRunStatusChanged" /* OnRunStatusChanged */
1309
+ ];
1310
+ function useAgent({ agentId, updates } = {}) {
1311
+ agentId ??= DEFAULT_AGENT_ID2;
1220
1312
  const { copilotkit } = useCopilotKit();
1221
1313
  const [, forceUpdate] = useReducer2((x) => x + 1, 0);
1222
- const [isRunning, setIsRunning] = useState4(false);
1314
+ const updateFlags = useMemo2(
1315
+ () => updates ?? ALL_UPDATES,
1316
+ [JSON.stringify(updates)]
1317
+ );
1223
1318
  const agent = useMemo2(() => {
1224
1319
  return copilotkit.getAgent(agentId);
1225
- }, [agentId, copilotkit.agents, copilotkit.didLoadRuntime, copilotkit]);
1226
- useEffect5(() => {
1227
- const subscription = agent?.subscribe({
1228
- onMessagesChanged() {
1320
+ }, [
1321
+ agentId,
1322
+ copilotkit.agents,
1323
+ copilotkit.runtimeConnectionStatus,
1324
+ copilotkit
1325
+ ]);
1326
+ useEffect7(() => {
1327
+ if (!agent) {
1328
+ return;
1329
+ }
1330
+ if (updateFlags.length === 0) {
1331
+ return;
1332
+ }
1333
+ const handlers = {};
1334
+ if (updateFlags.includes("OnMessagesChanged" /* OnMessagesChanged */)) {
1335
+ handlers.onMessagesChanged = () => {
1229
1336
  forceUpdate();
1230
- },
1231
- onStateChanged() {
1337
+ };
1338
+ }
1339
+ if (updateFlags.includes("OnStateChanged" /* OnStateChanged */)) {
1340
+ handlers.onStateChanged = () => {
1232
1341
  forceUpdate();
1233
- },
1234
- onRunInitialized() {
1235
- setIsRunning(true);
1236
- },
1237
- onRunFinalized() {
1238
- setIsRunning(false);
1239
- },
1240
- onRunFailed() {
1241
- setIsRunning(false);
1242
- }
1243
- });
1244
- return () => subscription?.unsubscribe();
1245
- }, [agent]);
1342
+ };
1343
+ }
1344
+ if (updateFlags.includes("OnRunStatusChanged" /* OnRunStatusChanged */)) {
1345
+ handlers.onRunInitialized = () => {
1346
+ forceUpdate();
1347
+ };
1348
+ handlers.onRunFinalized = () => {
1349
+ forceUpdate();
1350
+ };
1351
+ handlers.onRunFailed = () => {
1352
+ forceUpdate();
1353
+ };
1354
+ }
1355
+ const subscription = agent.subscribe(handlers);
1356
+ return () => subscription.unsubscribe();
1357
+ }, [agent, forceUpdate, JSON.stringify(updateFlags)]);
1246
1358
  return {
1247
- agent,
1248
- isRunning
1359
+ agent
1249
1360
  };
1250
1361
  }
1251
1362
 
1252
1363
  // src/hooks/use-agent-context.tsx
1253
- import { useEffect as useEffect6 } from "react";
1364
+ import { useEffect as useEffect8 } from "react";
1254
1365
  function useAgentContext(context) {
1255
1366
  const { description, value } = context;
1256
1367
  const { copilotkit } = useCopilotKit();
1257
- useEffect6(() => {
1368
+ useEffect8(() => {
1258
1369
  if (!copilotkit) return;
1259
1370
  const id = copilotkit.addContext(context);
1260
1371
  return () => {
@@ -1269,7 +1380,7 @@ import { Fragment as Fragment2, jsx as jsx9 } from "react/jsx-runtime";
1269
1380
  function CopilotChatToolCallsView({
1270
1381
  message,
1271
1382
  messages = [],
1272
- isLoading = false
1383
+ isRunning = false
1273
1384
  }) {
1274
1385
  const renderToolCall = useRenderToolCall();
1275
1386
  if (!message.toolCalls || message.toolCalls.length === 0) {
@@ -1282,7 +1393,7 @@ function CopilotChatToolCallsView({
1282
1393
  return /* @__PURE__ */ jsx9(React7.Fragment, { children: renderToolCall({
1283
1394
  toolCall,
1284
1395
  toolMessage,
1285
- isLoading
1396
+ isRunning
1286
1397
  }) }, toolCall.id);
1287
1398
  }) });
1288
1399
  }
@@ -1293,7 +1404,7 @@ import { Fragment as Fragment3, jsx as jsx10, jsxs as jsxs4 } from "react/jsx-ru
1293
1404
  function CopilotChatAssistantMessage({
1294
1405
  message,
1295
1406
  messages,
1296
- isLoading,
1407
+ isRunning,
1297
1408
  onThumbsUp,
1298
1409
  onThumbsDown,
1299
1410
  onReadAloud,
@@ -1382,7 +1493,7 @@ function CopilotChatAssistantMessage({
1382
1493
  {
1383
1494
  message,
1384
1495
  messages,
1385
- isLoading
1496
+ isRunning
1386
1497
  }
1387
1498
  );
1388
1499
  if (children) {
@@ -1397,7 +1508,7 @@ function CopilotChatAssistantMessage({
1397
1508
  regenerateButton: boundRegenerateButton,
1398
1509
  message,
1399
1510
  messages,
1400
- isLoading,
1511
+ isRunning,
1401
1512
  onThumbsUp,
1402
1513
  onThumbsDown,
1403
1514
  onReadAloud,
@@ -1870,7 +1981,7 @@ function CopilotChatMessageView({
1870
1981
  assistantMessage,
1871
1982
  userMessage,
1872
1983
  cursor,
1873
- isLoading = false,
1984
+ isRunning = false,
1874
1985
  children,
1875
1986
  className,
1876
1987
  ...props
@@ -1881,7 +1992,7 @@ function CopilotChatMessageView({
1881
1992
  key: message.id,
1882
1993
  message,
1883
1994
  messages,
1884
- isLoading
1995
+ isRunning
1885
1996
  });
1886
1997
  } else if (message.role === "user") {
1887
1998
  return renderSlot(userMessage, CopilotChatUserMessage_default, {
@@ -1892,11 +2003,11 @@ function CopilotChatMessageView({
1892
2003
  return;
1893
2004
  }).filter(Boolean);
1894
2005
  if (children) {
1895
- return children({ messageElements, messages, isLoading });
2006
+ return children({ messageElements, messages, isRunning });
1896
2007
  }
1897
2008
  return /* @__PURE__ */ jsxs6("div", { className: twMerge6("flex flex-col", className), ...props, children: [
1898
2009
  messageElements,
1899
- isLoading && renderSlot(cursor, CopilotChatMessageView.Cursor, {})
2010
+ isRunning && renderSlot(cursor, CopilotChatMessageView.Cursor, {})
1900
2011
  ] });
1901
2012
  }
1902
2013
  CopilotChatMessageView.Cursor = function Cursor({
@@ -1917,7 +2028,7 @@ CopilotChatMessageView.Cursor = function Cursor({
1917
2028
  var CopilotChatMessageView_default = CopilotChatMessageView;
1918
2029
 
1919
2030
  // src/components/chat/CopilotChatView.tsx
1920
- import React8, { useRef as useRef5, useState as useState7, useEffect as useEffect7 } from "react";
2031
+ import React8, { useRef as useRef5, useState as useState7, useEffect as useEffect9 } from "react";
1921
2032
  import { twMerge as twMerge7 } from "tailwind-merge";
1922
2033
  import { StickToBottom, useStickToBottom, useStickToBottomContext } from "use-stick-to-bottom";
1923
2034
  import { ChevronDown } from "lucide-react";
@@ -1932,6 +2043,8 @@ function CopilotChatView({
1932
2043
  disclaimer,
1933
2044
  messages = [],
1934
2045
  autoScroll = true,
2046
+ inputProps,
2047
+ isRunning = false,
1935
2048
  children,
1936
2049
  className,
1937
2050
  ...props
@@ -1940,7 +2053,7 @@ function CopilotChatView({
1940
2053
  const [inputContainerHeight, setInputContainerHeight] = useState7(0);
1941
2054
  const [isResizing, setIsResizing] = useState7(false);
1942
2055
  const resizeTimeoutRef = useRef5(null);
1943
- useEffect7(() => {
2056
+ useEffect9(() => {
1944
2057
  const element = inputContainerRef.current;
1945
2058
  if (!element) return;
1946
2059
  const resizeObserver = new ResizeObserver((entries) => {
@@ -1971,9 +2084,14 @@ function CopilotChatView({
1971
2084
  };
1972
2085
  }, []);
1973
2086
  const BoundMessageView = renderSlot(messageView, CopilotChatMessageView_default, {
1974
- messages
2087
+ messages,
2088
+ isRunning
1975
2089
  });
1976
- const BoundInput = renderSlot(input, CopilotChatInput_default, {});
2090
+ const BoundInput = renderSlot(
2091
+ input,
2092
+ CopilotChatInput_default,
2093
+ inputProps ?? {}
2094
+ );
1977
2095
  const BoundFeather = renderSlot(feather, CopilotChatView.Feather, {});
1978
2096
  const BoundScrollView = renderSlot(scrollView, CopilotChatView.ScrollView, {
1979
2097
  autoScroll,
@@ -2055,10 +2173,10 @@ function CopilotChatView({
2055
2173
  const [hasMounted, setHasMounted] = useState7(false);
2056
2174
  const { scrollRef, contentRef, scrollToBottom } = useStickToBottom();
2057
2175
  const [showScrollButton, setShowScrollButton] = useState7(false);
2058
- useEffect7(() => {
2176
+ useEffect9(() => {
2059
2177
  setHasMounted(true);
2060
2178
  }, []);
2061
- useEffect7(() => {
2179
+ useEffect9(() => {
2062
2180
  if (autoScroll) return;
2063
2181
  const scrollElement = scrollRef.current;
2064
2182
  if (!scrollElement) return;
@@ -2191,83 +2309,100 @@ function CopilotChatView({
2191
2309
  var CopilotChatView_default = CopilotChatView;
2192
2310
 
2193
2311
  // src/components/chat/CopilotChat.tsx
2194
- import { DEFAULT_AGENT_ID as DEFAULT_AGENT_ID2, randomUUID } from "@copilotkitnext/shared";
2195
- import { useCallback as useCallback3, useState as useState8, useEffect as useEffect8, useMemo as useMemo3 } from "react";
2312
+ import { DEFAULT_AGENT_ID as DEFAULT_AGENT_ID3, randomUUID } from "@copilotkitnext/shared";
2313
+ import { useCallback as useCallback3, useEffect as useEffect10, useMemo as useMemo3 } from "react";
2196
2314
  import { merge } from "ts-deepmerge";
2315
+ import { AGUIConnectNotImplementedError } from "@ag-ui/client";
2197
2316
  import { jsx as jsx14 } from "react/jsx-runtime";
2198
2317
  function CopilotChat({
2199
- agentId = DEFAULT_AGENT_ID2,
2318
+ agentId = DEFAULT_AGENT_ID3,
2200
2319
  threadId,
2201
2320
  ...props
2202
2321
  }) {
2203
2322
  const { agent } = useAgent({ agentId });
2204
- const [isLoading, setIsLoading] = useState8(false);
2205
- threadId = threadId ?? useMemo3(() => randomUUID(), []);
2206
- const subscriber = {
2207
- onTextMessageStartEvent: () => setIsLoading(false),
2208
- onToolCallStartEvent: () => setIsLoading(false)
2209
- };
2210
- useEffect8(() => {
2211
- const connect = async () => {
2212
- setIsLoading(true);
2213
- await agent?.runAgent(
2214
- {
2215
- forwardedProps: { __copilotkitConnect: true }
2216
- },
2217
- subscriber
2218
- );
2219
- setIsLoading(false);
2323
+ const { copilotkit } = useCopilotKit();
2324
+ const resolvedThreadId = useMemo3(() => threadId ?? randomUUID(), [threadId]);
2325
+ useEffect10(() => {
2326
+ const connect = async (agent2) => {
2327
+ try {
2328
+ await copilotkit.connectAgent({ agent: agent2, agentId });
2329
+ } catch (error) {
2330
+ if (error instanceof AGUIConnectNotImplementedError) {
2331
+ } else {
2332
+ throw error;
2333
+ }
2334
+ }
2220
2335
  };
2221
2336
  if (agent) {
2222
- agent.threadId = threadId;
2223
- if ("isCopilotKitAgent" in agent) {
2224
- connect();
2225
- } else {
2226
- setIsLoading(false);
2227
- }
2337
+ agent.threadId = resolvedThreadId;
2338
+ connect(agent);
2228
2339
  }
2229
2340
  return () => {
2230
2341
  };
2231
- }, [threadId, agent]);
2232
- const [inputValue, setInputValue] = useState8("");
2342
+ }, [resolvedThreadId, agent, copilotkit, agentId]);
2233
2343
  const onSubmitInput = useCallback3(
2234
2344
  async (value) => {
2235
- setInputValue("");
2236
2345
  agent?.addMessage({
2237
2346
  id: randomUUID(),
2238
2347
  role: "user",
2239
2348
  content: value
2240
2349
  });
2241
- setIsLoading(true);
2242
- await agent?.runAgent({}, subscriber);
2243
- setIsLoading(false);
2350
+ if (agent) {
2351
+ try {
2352
+ await copilotkit.runAgent({ agent, agentId });
2353
+ } catch (error) {
2354
+ console.error("CopilotChat: runAgent failed", error);
2355
+ }
2356
+ }
2244
2357
  },
2245
- [agent]
2358
+ [agent, copilotkit, agentId]
2246
2359
  );
2360
+ const {
2361
+ inputProps: providedInputProps,
2362
+ messageView: providedMessageView,
2363
+ ...restProps
2364
+ } = props;
2247
2365
  const mergedProps = merge(
2248
2366
  {
2249
- messageView: { isLoading }
2367
+ isRunning: agent?.isRunning ?? false
2250
2368
  },
2251
2369
  {
2252
- ...props,
2253
- ...typeof props.messageView === "string" ? { messageView: { className: props.messageView } } : props.messageView !== void 0 ? { messageView: props.messageView } : {}
2370
+ ...restProps,
2371
+ ...typeof providedMessageView === "string" ? { messageView: { className: providedMessageView } } : providedMessageView !== void 0 ? { messageView: providedMessageView } : {}
2254
2372
  }
2255
2373
  );
2256
2374
  return /* @__PURE__ */ jsx14(
2257
2375
  CopilotChatConfigurationProvider,
2258
2376
  {
2259
- inputValue,
2260
- onSubmitInput,
2261
- onChangeInput: setInputValue,
2377
+ agentId,
2378
+ threadId: resolvedThreadId,
2262
2379
  children: /* @__PURE__ */ jsx14(
2263
2380
  CopilotChatView,
2264
2381
  {
2265
- ...{ messages: agent?.messages ?? [], ...mergedProps }
2382
+ ...{
2383
+ messages: agent?.messages ?? [],
2384
+ inputProps: {
2385
+ onSubmitMessage: onSubmitInput,
2386
+ ...providedInputProps
2387
+ },
2388
+ ...mergedProps
2389
+ }
2266
2390
  }
2267
2391
  )
2268
2392
  }
2269
2393
  );
2270
2394
  }
2395
+
2396
+ // src/types/defineToolCallRender.ts
2397
+ function defineToolCallRender(def) {
2398
+ return {
2399
+ name: def.name,
2400
+ args: def.args,
2401
+ // Coerce to ComponentType to align with ReactToolCallRender
2402
+ render: def.render,
2403
+ ...def.agentId ? { agentId: def.agentId } : {}
2404
+ };
2405
+ }
2271
2406
  export {
2272
2407
  AudioRecorderError,
2273
2408
  CopilotChat,
@@ -2280,6 +2415,7 @@ export {
2280
2415
  CopilotChatUserMessage_default as CopilotChatUserMessage,
2281
2416
  CopilotChatView_default as CopilotChatView,
2282
2417
  CopilotKitProvider,
2418
+ defineToolCallRender,
2283
2419
  useAgent,
2284
2420
  useAgentContext,
2285
2421
  useCopilotChatConfiguration,