@copilotkit/react-core 1.4.8-no-pino-redact.1 → 1.4.8
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 +8 -3
- package/dist/{chunk-XBVKTDXP.mjs → chunk-6EMLM6WX.mjs} +17 -14
- package/dist/chunk-6EMLM6WX.mjs.map +1 -0
- package/dist/{chunk-ODN4H66E.mjs → chunk-7LRDVJH5.mjs} +6 -2
- package/dist/chunk-7LRDVJH5.mjs.map +1 -0
- package/dist/{chunk-O22KGHOQ.mjs → chunk-FSC4A3JN.mjs} +17 -13
- package/dist/chunk-FSC4A3JN.mjs.map +1 -0
- package/dist/{chunk-OT67R4NB.mjs → chunk-IFTHM7LF.mjs} +2 -2
- package/dist/{chunk-DHGXL5PC.mjs → chunk-IVYL7JRC.mjs} +7 -4
- package/dist/chunk-IVYL7JRC.mjs.map +1 -0
- package/dist/chunk-NTLCOVE5.mjs +321 -0
- package/dist/chunk-NTLCOVE5.mjs.map +1 -0
- package/dist/chunk-QCUP6HLK.mjs +37 -0
- package/dist/chunk-QCUP6HLK.mjs.map +1 -0
- package/dist/{chunk-2KCEHGSI.mjs → chunk-SFPANIOY.mjs} +99 -49
- package/dist/chunk-SFPANIOY.mjs.map +1 -0
- package/dist/{chunk-JHEAUB3Z.mjs → chunk-X6ZF5WAX.mjs} +1 -1
- package/dist/{chunk-JHEAUB3Z.mjs.map → chunk-X6ZF5WAX.mjs.map} +1 -1
- package/dist/{chunk-Y7MI4PBB.mjs → chunk-YUY5ZAST.mjs} +6 -3
- package/dist/chunk-YUY5ZAST.mjs.map +1 -0
- package/dist/components/copilot-provider/copilotkit.js +156 -91
- package/dist/components/copilot-provider/copilotkit.js.map +1 -1
- package/dist/components/copilot-provider/copilotkit.mjs +4 -3
- package/dist/components/copilot-provider/index.js +156 -91
- package/dist/components/copilot-provider/index.js.map +1 -1
- package/dist/components/copilot-provider/index.mjs +4 -3
- package/dist/components/error-boundary/error-boundary.d.ts +22 -0
- package/dist/components/error-boundary/error-boundary.js +183 -0
- package/dist/components/error-boundary/error-boundary.js.map +1 -0
- package/dist/components/error-boundary/error-boundary.mjs +12 -0
- package/dist/components/error-boundary/error-boundary.mjs.map +1 -0
- package/dist/components/error-boundary/error-utils.d.ts +11 -0
- package/dist/components/error-boundary/error-utils.js +177 -0
- package/dist/components/error-boundary/error-utils.js.map +1 -0
- package/dist/components/error-boundary/error-utils.mjs +13 -0
- package/dist/components/error-boundary/error-utils.mjs.map +1 -0
- package/dist/components/index.js +156 -91
- package/dist/components/index.js.map +1 -1
- package/dist/components/index.mjs +4 -3
- package/dist/components/toast/toast-provider.d.ts +2 -1
- package/dist/components/toast/toast-provider.js +76 -62
- package/dist/components/toast/toast-provider.js.map +1 -1
- package/dist/components/toast/toast-provider.mjs +1 -1
- package/dist/hooks/index.js +398 -253
- package/dist/hooks/index.js.map +1 -1
- package/dist/hooks/index.mjs +9 -8
- package/dist/hooks/use-chat.js +343 -199
- package/dist/hooks/use-chat.js.map +1 -1
- package/dist/hooks/use-chat.mjs +3 -3
- package/dist/hooks/use-coagent-state-render.d.ts +2 -2
- package/dist/hooks/use-coagent-state-render.js.map +1 -1
- package/dist/hooks/use-coagent-state-render.mjs +1 -1
- package/dist/hooks/use-coagent.js +378 -233
- package/dist/hooks/use-coagent.js.map +1 -1
- package/dist/hooks/use-coagent.mjs +7 -6
- package/dist/hooks/use-copilot-action.js +132 -7
- package/dist/hooks/use-copilot-action.js.map +1 -1
- package/dist/hooks/use-copilot-action.mjs +3 -1
- package/dist/hooks/use-copilot-chat.js +367 -223
- package/dist/hooks/use-copilot-chat.js.map +1 -1
- package/dist/hooks/use-copilot-chat.mjs +6 -5
- package/dist/hooks/use-copilot-runtime-client.js +110 -4
- package/dist/hooks/use-copilot-runtime-client.js.map +1 -1
- package/dist/hooks/use-copilot-runtime-client.mjs +2 -2
- package/dist/index.js +439 -335
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +10 -9
- package/dist/lib/copilot-task.js.map +1 -1
- package/dist/lib/copilot-task.mjs +5 -4
- package/dist/lib/index.js.map +1 -1
- package/dist/lib/index.mjs +5 -4
- package/dist/utils/extract.js.map +1 -1
- package/dist/utils/extract.mjs +4 -3
- package/dist/utils/index.js.map +1 -1
- package/dist/utils/index.mjs +4 -3
- package/package.json +3 -3
- package/src/components/copilot-provider/copilotkit.tsx +4 -1
- package/src/components/error-boundary/error-boundary.tsx +42 -0
- package/src/components/error-boundary/error-utils.tsx +95 -0
- package/src/components/toast/toast-provider.tsx +10 -49
- package/src/hooks/use-chat.ts +286 -259
- package/src/hooks/use-coagent-state-render.ts +2 -2
- package/src/hooks/use-coagent.ts +14 -11
- package/src/hooks/use-copilot-action.ts +3 -2
- package/src/hooks/use-copilot-chat.ts +9 -8
- package/src/hooks/use-copilot-runtime-client.ts +4 -0
- package/dist/chunk-2KCEHGSI.mjs.map +0 -1
- package/dist/chunk-DHGXL5PC.mjs.map +0 -1
- package/dist/chunk-EUIBVFV6.mjs +0 -294
- package/dist/chunk-EUIBVFV6.mjs.map +0 -1
- package/dist/chunk-O22KGHOQ.mjs.map +0 -1
- package/dist/chunk-ODN4H66E.mjs.map +0 -1
- package/dist/chunk-XBVKTDXP.mjs.map +0 -1
- package/dist/chunk-Y7MI4PBB.mjs.map +0 -1
- /package/dist/{chunk-OT67R4NB.mjs.map → chunk-IFTHM7LF.mjs.map} +0 -0
package/src/hooks/use-chat.ts
CHANGED
|
@@ -26,6 +26,7 @@ import { CoagentState } from "../types/coagent-state";
|
|
|
26
26
|
import { AgentSession } from "../context/copilot-context";
|
|
27
27
|
import { useToast } from "../components/toast/toast-provider";
|
|
28
28
|
import { useCopilotRuntimeClient } from "./use-copilot-runtime-client";
|
|
29
|
+
import { useAsyncCallback } from "../components/error-boundary/error-utils";
|
|
29
30
|
|
|
30
31
|
export type UseChatOptions = {
|
|
31
32
|
/**
|
|
@@ -167,292 +168,318 @@ export function useChat(options: UseChatOptions): UseChatHelpers {
|
|
|
167
168
|
credentials: copilotConfig.credentials,
|
|
168
169
|
});
|
|
169
170
|
|
|
170
|
-
const runChatCompletion =
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
runtimeClient.
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
(
|
|
197
|
-
action
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
ActionInputAvailability
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
available
|
|
206
|
-
|
|
207
|
-
available
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
171
|
+
const runChatCompletion = useAsyncCallback(
|
|
172
|
+
async (previousMessages: Message[]): Promise<Message[]> => {
|
|
173
|
+
setIsLoading(true);
|
|
174
|
+
|
|
175
|
+
// this message is just a placeholder. It will disappear once the first real message
|
|
176
|
+
// is received
|
|
177
|
+
let newMessages: Message[] = [
|
|
178
|
+
new TextMessage({
|
|
179
|
+
content: "",
|
|
180
|
+
role: Role.Assistant,
|
|
181
|
+
}),
|
|
182
|
+
];
|
|
183
|
+
const abortController = new AbortController();
|
|
184
|
+
abortControllerRef.current = abortController;
|
|
185
|
+
|
|
186
|
+
setMessages([...previousMessages, ...newMessages]);
|
|
187
|
+
|
|
188
|
+
const systemMessage = makeSystemMessageCallback();
|
|
189
|
+
|
|
190
|
+
const messagesWithContext = [systemMessage, ...(initialMessages || []), ...previousMessages];
|
|
191
|
+
|
|
192
|
+
const stream = runtimeClient.asStream(
|
|
193
|
+
runtimeClient.generateCopilotResponse({
|
|
194
|
+
data: {
|
|
195
|
+
frontend: {
|
|
196
|
+
actions: actions
|
|
197
|
+
.filter(
|
|
198
|
+
(action) =>
|
|
199
|
+
action.available !== ActionInputAvailability.Disabled || !action.disabled,
|
|
200
|
+
)
|
|
201
|
+
.map((action) => {
|
|
202
|
+
let available: ActionInputAvailability | undefined =
|
|
203
|
+
ActionInputAvailability.Enabled;
|
|
204
|
+
if (action.disabled) {
|
|
205
|
+
available = ActionInputAvailability.Disabled;
|
|
206
|
+
} else if (action.available === "disabled") {
|
|
207
|
+
available = ActionInputAvailability.Disabled;
|
|
208
|
+
} else if (action.available === "remote") {
|
|
209
|
+
available = ActionInputAvailability.Remote;
|
|
210
|
+
}
|
|
211
|
+
return {
|
|
212
|
+
name: action.name,
|
|
213
|
+
description: action.description || "",
|
|
214
|
+
jsonSchema: JSON.stringify(
|
|
215
|
+
actionParametersToJsonSchema(action.parameters || []),
|
|
216
|
+
),
|
|
217
|
+
available,
|
|
218
|
+
};
|
|
219
|
+
}),
|
|
220
|
+
url: window.location.href,
|
|
221
|
+
},
|
|
222
|
+
threadId: threadIdRef.current,
|
|
223
|
+
runId: runIdRef.current,
|
|
224
|
+
messages: convertMessagesToGqlInput(filterAgentStateMessages(messagesWithContext)),
|
|
225
|
+
...(copilotConfig.cloud
|
|
226
|
+
? {
|
|
227
|
+
cloud: {
|
|
228
|
+
...(copilotConfig.cloud.guardrails?.input?.restrictToTopic?.enabled
|
|
229
|
+
? {
|
|
230
|
+
guardrails: {
|
|
231
|
+
inputValidationRules: {
|
|
232
|
+
allowList:
|
|
233
|
+
copilotConfig.cloud.guardrails.input.restrictToTopic.validTopics,
|
|
234
|
+
denyList:
|
|
235
|
+
copilotConfig.cloud.guardrails.input.restrictToTopic.invalidTopics,
|
|
236
|
+
},
|
|
232
237
|
},
|
|
233
|
-
}
|
|
234
|
-
}
|
|
235
|
-
|
|
236
|
-
}
|
|
237
|
-
}
|
|
238
|
-
: {
|
|
239
|
-
|
|
240
|
-
|
|
238
|
+
}
|
|
239
|
+
: {}),
|
|
240
|
+
},
|
|
241
|
+
}
|
|
242
|
+
: {}),
|
|
243
|
+
metadata: {
|
|
244
|
+
requestType: CopilotRequestType.Chat,
|
|
245
|
+
},
|
|
246
|
+
...(agentSessionRef.current
|
|
247
|
+
? {
|
|
248
|
+
agentSession: agentSessionRef.current,
|
|
249
|
+
}
|
|
250
|
+
: {}),
|
|
251
|
+
agentStates: Object.values(coagentStatesRef.current!).map((state) => ({
|
|
252
|
+
agentName: state.name,
|
|
253
|
+
state: JSON.stringify(state.state),
|
|
254
|
+
})),
|
|
241
255
|
},
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
while (true) {
|
|
268
|
-
let done, value;
|
|
269
|
-
|
|
270
|
-
try {
|
|
271
|
-
const readResult = await reader.read();
|
|
272
|
-
done = readResult.done;
|
|
273
|
-
value = readResult.value;
|
|
274
|
-
} catch (readError) {
|
|
275
|
-
break;
|
|
276
|
-
}
|
|
277
|
-
|
|
278
|
-
if (done) {
|
|
279
|
-
break;
|
|
280
|
-
}
|
|
256
|
+
properties: copilotConfig.properties,
|
|
257
|
+
signal: abortControllerRef.current?.signal,
|
|
258
|
+
}),
|
|
259
|
+
);
|
|
260
|
+
|
|
261
|
+
const guardrailsEnabled =
|
|
262
|
+
copilotConfig.cloud?.guardrails?.input?.restrictToTopic.enabled || false;
|
|
263
|
+
|
|
264
|
+
const reader = stream.getReader();
|
|
265
|
+
|
|
266
|
+
let actionResults: { [id: string]: string } = {};
|
|
267
|
+
let executedCoAgentStateRenders: string[] = [];
|
|
268
|
+
let followUp: FrontendAction["followUp"] = undefined;
|
|
269
|
+
|
|
270
|
+
try {
|
|
271
|
+
while (true) {
|
|
272
|
+
let done, value;
|
|
273
|
+
|
|
274
|
+
try {
|
|
275
|
+
const readResult = await reader.read();
|
|
276
|
+
done = readResult.done;
|
|
277
|
+
value = readResult.value;
|
|
278
|
+
} catch (readError) {
|
|
279
|
+
break;
|
|
280
|
+
}
|
|
281
281
|
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
282
|
+
if (done) {
|
|
283
|
+
break;
|
|
284
|
+
}
|
|
285
285
|
|
|
286
|
-
|
|
287
|
-
|
|
286
|
+
if (!value?.generateCopilotResponse) {
|
|
287
|
+
continue;
|
|
288
|
+
}
|
|
288
289
|
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
);
|
|
290
|
+
threadIdRef.current = value.generateCopilotResponse.threadId || null;
|
|
291
|
+
runIdRef.current = value.generateCopilotResponse.runId || null;
|
|
292
292
|
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
293
|
+
const messages = convertGqlOutputToMessages(
|
|
294
|
+
filterAdjacentAgentStateMessages(value.generateCopilotResponse.messages),
|
|
295
|
+
);
|
|
296
296
|
|
|
297
|
-
|
|
297
|
+
if (messages.length === 0) {
|
|
298
|
+
continue;
|
|
299
|
+
}
|
|
298
300
|
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
301
|
+
newMessages = [];
|
|
302
|
+
|
|
303
|
+
// request failed, display error message
|
|
304
|
+
if (
|
|
305
|
+
value.generateCopilotResponse.status?.__typename === "FailedResponseStatus" &&
|
|
306
|
+
value.generateCopilotResponse.status.reason === "GUARDRAILS_VALIDATION_FAILED"
|
|
307
|
+
) {
|
|
308
|
+
newMessages = [
|
|
309
|
+
new TextMessage({
|
|
310
|
+
role: MessageRole.Assistant,
|
|
311
|
+
content: value.generateCopilotResponse.status.details?.guardrailsReason || "",
|
|
312
|
+
}),
|
|
313
|
+
];
|
|
314
|
+
}
|
|
311
315
|
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
316
|
+
// add messages to the chat
|
|
317
|
+
else {
|
|
318
|
+
for (const message of messages) {
|
|
319
|
+
newMessages.push(message);
|
|
320
|
+
// execute regular action executions
|
|
321
|
+
if (
|
|
322
|
+
message.isActionExecutionMessage() &&
|
|
323
|
+
message.status.code !== MessageStatusCode.Pending &&
|
|
324
|
+
message.scope === "client" &&
|
|
325
|
+
onFunctionCall
|
|
326
|
+
) {
|
|
327
|
+
if (!(message.id in actionResults)) {
|
|
328
|
+
// Do not execute a function call if guardrails are enabled but the status is not known
|
|
329
|
+
if (guardrailsEnabled && value.generateCopilotResponse.status === undefined) {
|
|
330
|
+
break;
|
|
331
|
+
}
|
|
332
|
+
// execute action
|
|
333
|
+
try {
|
|
334
|
+
// We update the message state before calling the handler so that the render
|
|
335
|
+
// function can be called with `executing` state
|
|
336
|
+
setMessages([...previousMessages, ...newMessages]);
|
|
337
|
+
|
|
338
|
+
const action = actions.find((action) => action.name === message.name);
|
|
339
|
+
|
|
340
|
+
if (action) {
|
|
341
|
+
followUp = action.followUp;
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
const result = await onFunctionCall({
|
|
345
|
+
messages: previousMessages,
|
|
346
|
+
name: message.name,
|
|
347
|
+
args: message.arguments,
|
|
348
|
+
});
|
|
349
|
+
actionResults[message.id] = result;
|
|
350
|
+
} catch (e) {
|
|
351
|
+
actionResults[message.id] = `Failed to execute action ${message.name}`;
|
|
352
|
+
console.error(`Failed to execute action ${message.name}: ${e}`);
|
|
353
|
+
}
|
|
354
|
+
}
|
|
355
|
+
// add the result message
|
|
356
|
+
newMessages.push(
|
|
357
|
+
new ResultMessage({
|
|
358
|
+
result: ResultMessage.encodeResult(actionResults[message.id]),
|
|
359
|
+
actionExecutionId: message.id,
|
|
360
|
+
actionName: message.name,
|
|
361
|
+
}),
|
|
362
|
+
);
|
|
363
|
+
}
|
|
364
|
+
// execute coagent actions
|
|
365
|
+
if (
|
|
366
|
+
message.isAgentStateMessage() &&
|
|
367
|
+
!message.active &&
|
|
368
|
+
!executedCoAgentStateRenders.includes(message.id) &&
|
|
369
|
+
onCoAgentStateRender
|
|
370
|
+
) {
|
|
371
|
+
// Do not execute a coagent action if guardrails are enabled but the status is not known
|
|
325
372
|
if (guardrailsEnabled && value.generateCopilotResponse.status === undefined) {
|
|
326
373
|
break;
|
|
327
374
|
}
|
|
328
|
-
// execute action
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
if (action) {
|
|
337
|
-
followUp = action.followUp;
|
|
338
|
-
}
|
|
339
|
-
|
|
340
|
-
const result = await onFunctionCall({
|
|
341
|
-
messages: previousMessages,
|
|
342
|
-
name: message.name,
|
|
343
|
-
args: message.arguments,
|
|
344
|
-
});
|
|
345
|
-
actionResults[message.id] = result;
|
|
346
|
-
} catch (e) {
|
|
347
|
-
actionResults[message.id] = `Failed to execute action ${message.name}`;
|
|
348
|
-
console.error(`Failed to execute action ${message.name}: ${e}`);
|
|
349
|
-
}
|
|
375
|
+
// execute coagent action
|
|
376
|
+
await onCoAgentStateRender({
|
|
377
|
+
name: message.agentName,
|
|
378
|
+
nodeName: message.nodeName,
|
|
379
|
+
state: message.state,
|
|
380
|
+
});
|
|
381
|
+
executedCoAgentStateRenders.push(message.id);
|
|
350
382
|
}
|
|
351
|
-
// add the result message
|
|
352
|
-
newMessages.push(
|
|
353
|
-
new ResultMessage({
|
|
354
|
-
result: ResultMessage.encodeResult(actionResults[message.id]),
|
|
355
|
-
actionExecutionId: message.id,
|
|
356
|
-
actionName: message.name,
|
|
357
|
-
}),
|
|
358
|
-
);
|
|
359
383
|
}
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
384
|
+
|
|
385
|
+
const lastAgentStateMessage = [...messages]
|
|
386
|
+
.reverse()
|
|
387
|
+
.find((message) => message.isAgentStateMessage());
|
|
388
|
+
|
|
389
|
+
if (lastAgentStateMessage) {
|
|
390
|
+
setCoagentStatesWithRef((prevAgentStates) => ({
|
|
391
|
+
...prevAgentStates,
|
|
392
|
+
[lastAgentStateMessage.agentName]: {
|
|
393
|
+
name: lastAgentStateMessage.agentName,
|
|
394
|
+
state: lastAgentStateMessage.state,
|
|
395
|
+
running: lastAgentStateMessage.running,
|
|
396
|
+
active: lastAgentStateMessage.active,
|
|
397
|
+
threadId: lastAgentStateMessage.threadId,
|
|
398
|
+
nodeName: lastAgentStateMessage.nodeName,
|
|
399
|
+
runId: lastAgentStateMessage.runId,
|
|
400
|
+
},
|
|
401
|
+
}));
|
|
402
|
+
if (lastAgentStateMessage.running) {
|
|
403
|
+
setAgentSession({
|
|
404
|
+
threadId: lastAgentStateMessage.threadId,
|
|
405
|
+
agentName: lastAgentStateMessage.agentName,
|
|
406
|
+
nodeName: lastAgentStateMessage.nodeName,
|
|
407
|
+
});
|
|
408
|
+
} else {
|
|
409
|
+
setAgentSession(null);
|
|
370
410
|
}
|
|
371
|
-
// execute coagent action
|
|
372
|
-
await onCoAgentStateRender({
|
|
373
|
-
name: message.agentName,
|
|
374
|
-
nodeName: message.nodeName,
|
|
375
|
-
state: message.state,
|
|
376
|
-
});
|
|
377
|
-
executedCoAgentStateRenders.push(message.id);
|
|
378
411
|
}
|
|
379
412
|
}
|
|
380
413
|
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
if (lastAgentStateMessage) {
|
|
386
|
-
setCoagentStatesWithRef((prevAgentStates) => ({
|
|
387
|
-
...prevAgentStates,
|
|
388
|
-
[lastAgentStateMessage.agentName]: {
|
|
389
|
-
name: lastAgentStateMessage.agentName,
|
|
390
|
-
state: lastAgentStateMessage.state,
|
|
391
|
-
running: lastAgentStateMessage.running,
|
|
392
|
-
active: lastAgentStateMessage.active,
|
|
393
|
-
threadId: lastAgentStateMessage.threadId,
|
|
394
|
-
nodeName: lastAgentStateMessage.nodeName,
|
|
395
|
-
runId: lastAgentStateMessage.runId,
|
|
396
|
-
},
|
|
397
|
-
}));
|
|
398
|
-
if (lastAgentStateMessage.running) {
|
|
399
|
-
setAgentSession({
|
|
400
|
-
threadId: lastAgentStateMessage.threadId,
|
|
401
|
-
agentName: lastAgentStateMessage.agentName,
|
|
402
|
-
nodeName: lastAgentStateMessage.nodeName,
|
|
403
|
-
});
|
|
404
|
-
} else {
|
|
405
|
-
setAgentSession(null);
|
|
406
|
-
}
|
|
414
|
+
if (newMessages.length > 0) {
|
|
415
|
+
// Update message state
|
|
416
|
+
setMessages([...previousMessages, ...newMessages]);
|
|
407
417
|
}
|
|
408
418
|
}
|
|
409
419
|
|
|
410
|
-
if (
|
|
411
|
-
//
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
420
|
+
if (
|
|
421
|
+
// if followUp is not explicitly false
|
|
422
|
+
followUp !== false &&
|
|
423
|
+
// if we have client side results
|
|
424
|
+
(Object.values(actionResults).length ||
|
|
425
|
+
// or the last message we received is a result
|
|
426
|
+
(newMessages.length && newMessages[newMessages.length - 1].isResultMessage()))
|
|
427
|
+
) {
|
|
428
|
+
// run the completion again and return the result
|
|
415
429
|
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
// wait for next tick to make sure all the react state updates
|
|
427
|
-
// - tried using react-dom's flushSync, but it did not work
|
|
428
|
-
await new Promise((resolve) => setTimeout(resolve, 10));
|
|
429
|
-
|
|
430
|
-
return await runChatCompletionRef.current!([...previousMessages, ...newMessages]);
|
|
431
|
-
} else {
|
|
432
|
-
return newMessages.slice();
|
|
430
|
+
// wait for next tick to make sure all the react state updates
|
|
431
|
+
// - tried using react-dom's flushSync, but it did not work
|
|
432
|
+
await new Promise((resolve) => setTimeout(resolve, 10));
|
|
433
|
+
|
|
434
|
+
return await runChatCompletionRef.current!([...previousMessages, ...newMessages]);
|
|
435
|
+
} else {
|
|
436
|
+
return newMessages.slice();
|
|
437
|
+
}
|
|
438
|
+
} finally {
|
|
439
|
+
setIsLoading(false);
|
|
433
440
|
}
|
|
434
|
-
}
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
441
|
+
},
|
|
442
|
+
[
|
|
443
|
+
messages,
|
|
444
|
+
setMessages,
|
|
445
|
+
makeSystemMessageCallback,
|
|
446
|
+
copilotConfig,
|
|
447
|
+
setIsLoading,
|
|
448
|
+
initialMessages,
|
|
449
|
+
isLoading,
|
|
450
|
+
actions,
|
|
451
|
+
onFunctionCall,
|
|
452
|
+
onCoAgentStateRender,
|
|
453
|
+
setCoagentStatesWithRef,
|
|
454
|
+
coagentStatesRef,
|
|
455
|
+
agentSession,
|
|
456
|
+
setAgentSession,
|
|
457
|
+
],
|
|
458
|
+
);
|
|
438
459
|
|
|
439
460
|
runChatCompletionRef.current = runChatCompletion;
|
|
440
461
|
|
|
441
|
-
const runChatCompletionAndHandleFunctionCall =
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
462
|
+
const runChatCompletionAndHandleFunctionCall = useAsyncCallback(
|
|
463
|
+
async (messages: Message[]): Promise<void> => {
|
|
464
|
+
await runChatCompletionRef.current!(messages);
|
|
465
|
+
},
|
|
466
|
+
[messages],
|
|
467
|
+
);
|
|
468
|
+
|
|
469
|
+
const append = useAsyncCallback(
|
|
470
|
+
async (message: Message): Promise<void> => {
|
|
471
|
+
if (isLoading) {
|
|
472
|
+
return;
|
|
473
|
+
}
|
|
449
474
|
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
475
|
+
const newMessages = [...messages, message];
|
|
476
|
+
setMessages(newMessages);
|
|
477
|
+
return runChatCompletionAndHandleFunctionCall(newMessages);
|
|
478
|
+
},
|
|
479
|
+
[isLoading, messages, setMessages, runChatCompletionAndHandleFunctionCall],
|
|
480
|
+
);
|
|
454
481
|
|
|
455
|
-
const reload = async (): Promise<void> => {
|
|
482
|
+
const reload = useAsyncCallback(async (): Promise<void> => {
|
|
456
483
|
if (isLoading || messages.length === 0) {
|
|
457
484
|
return;
|
|
458
485
|
}
|
|
@@ -466,7 +493,7 @@ export function useChat(options: UseChatOptions): UseChatHelpers {
|
|
|
466
493
|
setMessages(newMessages);
|
|
467
494
|
|
|
468
495
|
return runChatCompletionAndHandleFunctionCall(newMessages);
|
|
469
|
-
};
|
|
496
|
+
}, [isLoading, messages, setMessages, runChatCompletionAndHandleFunctionCall]);
|
|
470
497
|
|
|
471
498
|
const stop = (): void => {
|
|
472
499
|
abortControllerRef.current?.abort();
|
|
@@ -12,13 +12,13 @@
|
|
|
12
12
|
* ### Simple Usage
|
|
13
13
|
*
|
|
14
14
|
* ```tsx
|
|
15
|
-
* import {
|
|
15
|
+
* import { useCoAgentStateRender } from "@copilotkit/react-core";
|
|
16
16
|
*
|
|
17
17
|
* type YourAgentState = {
|
|
18
18
|
* agent_state_property: string;
|
|
19
19
|
* }
|
|
20
20
|
*
|
|
21
|
-
*
|
|
21
|
+
* useCoAgentStateRender<YourAgentState>({
|
|
22
22
|
* name: "basic_agent",
|
|
23
23
|
* nodeName: "optionally_specify_a_specific_node",
|
|
24
24
|
* render: ({ status, state, nodeName }) => {
|
package/src/hooks/use-coagent.ts
CHANGED
|
@@ -99,6 +99,7 @@ import { CoagentState } from "../types/coagent-state";
|
|
|
99
99
|
import { useCopilotChat } from "./use-copilot-chat";
|
|
100
100
|
import { Message } from "@copilotkit/runtime-client-gql";
|
|
101
101
|
import { flushSync } from "react-dom";
|
|
102
|
+
import { useAsyncCallback } from "../components/error-boundary/error-utils";
|
|
102
103
|
|
|
103
104
|
interface WithInternalStateManagementAndInitial<T> {
|
|
104
105
|
/**
|
|
@@ -266,22 +267,24 @@ export function useCoAgent<T = any>(options: UseCoagentOptions<T>): UseCoagentRe
|
|
|
266
267
|
}
|
|
267
268
|
}, [isExternalStateManagement(options) ? JSON.stringify(options.state) : undefined]);
|
|
268
269
|
|
|
270
|
+
const runAgentCallback = useAsyncCallback(
|
|
271
|
+
async (hint?: HintFunction) => {
|
|
272
|
+
await runAgent(name, context, appendMessage, runChatCompletion, hint);
|
|
273
|
+
},
|
|
274
|
+
[name, context, appendMessage, runChatCompletion],
|
|
275
|
+
);
|
|
276
|
+
|
|
269
277
|
// Return the state and setState function
|
|
270
278
|
return {
|
|
271
279
|
name,
|
|
272
280
|
nodeName: coagentState.nodeName,
|
|
273
|
-
|
|
274
|
-
setState,
|
|
281
|
+
threadId: coagentState.threadId,
|
|
275
282
|
running: coagentState.running,
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
stop: () =>
|
|
280
|
-
|
|
281
|
-
},
|
|
282
|
-
run: (hint?: HintFunction) => {
|
|
283
|
-
return runAgent(name, context, appendMessage, runChatCompletion, hint);
|
|
284
|
-
},
|
|
283
|
+
state: coagentState.state,
|
|
284
|
+
setState: isExternalStateManagement(options) ? options.setState : setState,
|
|
285
|
+
start: () => startAgent(name, context),
|
|
286
|
+
stop: () => stopAgent(name, context),
|
|
287
|
+
run: runAgentCallback,
|
|
285
288
|
};
|
|
286
289
|
}
|
|
287
290
|
|