@copilotz/chat-adapter 0.1.23 → 0.1.25
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.ts +3 -4
- package/dist/index.js +102 -150
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -130,10 +130,9 @@ type RestMessage = {
|
|
|
130
130
|
updatedAt?: string;
|
|
131
131
|
};
|
|
132
132
|
type StreamCallbacks = {
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
onToken?: (text: string, isComplete: boolean, raw?: any, reasoningText?: string) => void;
|
|
133
|
+
onToken?: (token: string, isComplete: boolean, raw?: any, options?: {
|
|
134
|
+
isReasoning?: boolean;
|
|
135
|
+
}) => void;
|
|
137
136
|
onMessageEvent?: (payload: any) => void;
|
|
138
137
|
onAssetEvent?: (payload: any) => void;
|
|
139
138
|
signal?: AbortSignal;
|
package/dist/index.js
CHANGED
|
@@ -406,6 +406,8 @@ async function runCopilotzStream(options) {
|
|
|
406
406
|
let buffer = "";
|
|
407
407
|
let aggregatedText = "";
|
|
408
408
|
let aggregatedReasoning = "";
|
|
409
|
+
let lastTokenWasReasoning = false;
|
|
410
|
+
let hadNonReasoningContent = false;
|
|
409
411
|
const collectedMessages = [];
|
|
410
412
|
let collectedMedia = null;
|
|
411
413
|
const processEvent = (eventChunk) => {
|
|
@@ -431,9 +433,15 @@ async function runCopilotzStream(options) {
|
|
|
431
433
|
switch (eventType) {
|
|
432
434
|
case "TOKEN": {
|
|
433
435
|
const inner = payload2?.payload ?? payload2;
|
|
434
|
-
const chunk = typeof inner?.token === "string" ? inner.token :
|
|
436
|
+
const chunk = typeof inner?.token === "string" ? inner.token : "";
|
|
435
437
|
const isReasoning = Boolean(inner?.isReasoning);
|
|
436
|
-
|
|
438
|
+
if (isReasoning && !lastTokenWasReasoning && hadNonReasoningContent) {
|
|
439
|
+
aggregatedReasoning = "";
|
|
440
|
+
aggregatedText = "";
|
|
441
|
+
hadNonReasoningContent = false;
|
|
442
|
+
}
|
|
443
|
+
lastTokenWasReasoning = isReasoning;
|
|
444
|
+
if (!isReasoning) hadNonReasoningContent = true;
|
|
437
445
|
if (chunk) {
|
|
438
446
|
if (isReasoning) {
|
|
439
447
|
aggregatedReasoning = appendChunk(aggregatedReasoning, chunk);
|
|
@@ -441,12 +449,16 @@ async function runCopilotzStream(options) {
|
|
|
441
449
|
aggregatedText = appendChunk(aggregatedText, chunk);
|
|
442
450
|
}
|
|
443
451
|
}
|
|
452
|
+
const isComplete = Boolean(inner?.isComplete);
|
|
444
453
|
if (chunk || isComplete) {
|
|
445
|
-
|
|
454
|
+
const tokenText = isReasoning ? aggregatedReasoning : aggregatedText;
|
|
455
|
+
onToken?.(tokenText, isComplete, payload2, { isReasoning });
|
|
446
456
|
}
|
|
447
457
|
break;
|
|
448
458
|
}
|
|
449
459
|
case "MESSAGE": {
|
|
460
|
+
hadNonReasoningContent = true;
|
|
461
|
+
lastTokenWasReasoning = false;
|
|
450
462
|
collectedMessages.push(payload2);
|
|
451
463
|
onMessageEvent?.(payload2);
|
|
452
464
|
const senderType = payload2?.payload?.senderType ?? payload2?.payload?.sender?.type;
|
|
@@ -456,6 +468,8 @@ async function runCopilotzStream(options) {
|
|
|
456
468
|
break;
|
|
457
469
|
}
|
|
458
470
|
case "TOOL_CALL": {
|
|
471
|
+
hadNonReasoningContent = true;
|
|
472
|
+
lastTokenWasReasoning = false;
|
|
459
473
|
onMessageEvent?.(payload2);
|
|
460
474
|
break;
|
|
461
475
|
}
|
|
@@ -510,12 +524,11 @@ async function fetchThreads(userId, getRequestHeaders) {
|
|
|
510
524
|
const errorText = await res.text().catch(() => res.statusText);
|
|
511
525
|
throw new Error(errorText || `Failed to load threads (${res.status})`);
|
|
512
526
|
}
|
|
513
|
-
const
|
|
514
|
-
|
|
515
|
-
if (!Array.isArray(list)) {
|
|
527
|
+
const { data } = await res.json();
|
|
528
|
+
if (!Array.isArray(data)) {
|
|
516
529
|
return [];
|
|
517
530
|
}
|
|
518
|
-
return
|
|
531
|
+
return data;
|
|
519
532
|
}
|
|
520
533
|
async function fetchThreadMessages(threadId, getRequestHeaders) {
|
|
521
534
|
const graphParams = new URLSearchParams();
|
|
@@ -555,12 +568,11 @@ async function fetchThreadMessages(threadId, getRequestHeaders) {
|
|
|
555
568
|
const errorText = await res.text().catch(() => res.statusText);
|
|
556
569
|
throw new Error(errorText || `Failed to load thread messages (${res.status})`);
|
|
557
570
|
}
|
|
558
|
-
const
|
|
559
|
-
|
|
560
|
-
if (!Array.isArray(list)) {
|
|
571
|
+
const { data } = await res.json();
|
|
572
|
+
if (!Array.isArray(data)) {
|
|
561
573
|
return [];
|
|
562
574
|
}
|
|
563
|
-
return
|
|
575
|
+
return data;
|
|
564
576
|
}
|
|
565
577
|
async function updateThread(threadId, updates, getRequestHeaders) {
|
|
566
578
|
const res = await fetch(apiUrl(`/v1/rest/threads/${threadId}`), {
|
|
@@ -805,23 +817,6 @@ var generateId = () => globalThis.crypto?.randomUUID?.() ?? `id-${Date.now()}-${
|
|
|
805
817
|
var isAbortError = (error) => error instanceof DOMException && error.name === "AbortError" || typeof error === "object" && error !== null && "name" in error && error.name === "AbortError";
|
|
806
818
|
var getEventPayload = (event) => event?.payload ?? event;
|
|
807
819
|
var getEventSenderType = (payload) => payload?.senderType || payload?.sender?.type;
|
|
808
|
-
var hasToolCallsInPayload = (payload) => {
|
|
809
|
-
if (!payload || typeof payload !== "object") return false;
|
|
810
|
-
const p = payload;
|
|
811
|
-
if (Array.isArray(p.toolCalls) && p.toolCalls.length > 0) return true;
|
|
812
|
-
const meta = p.metadata;
|
|
813
|
-
if (!meta || typeof meta !== "object" || Array.isArray(meta)) return false;
|
|
814
|
-
const m = meta.toolCalls;
|
|
815
|
-
return Array.isArray(m) && m.length > 0;
|
|
816
|
-
};
|
|
817
|
-
var isAgentToolOnlyPlaceholderPayload = (payload) => {
|
|
818
|
-
if (!payload || typeof payload !== "object") return false;
|
|
819
|
-
const p = payload;
|
|
820
|
-
if (getEventSenderType(p) !== "agent") return false;
|
|
821
|
-
const content = typeof p.content === "string" ? p.content : "";
|
|
822
|
-
if (content.trim().length > 0) return false;
|
|
823
|
-
return hasToolCallsInPayload(p);
|
|
824
|
-
};
|
|
825
820
|
var hasVisibleAssistantOutput = (message) => {
|
|
826
821
|
if (message.role !== "assistant") return false;
|
|
827
822
|
if (typeof message.content === "string" && message.content.trim().length > 0) return true;
|
|
@@ -856,29 +851,16 @@ var extractToolCallsFromServerMessage = (msg) => {
|
|
|
856
851
|
const metadataToolCalls = Array.isArray(metadata?.toolCalls) ? metadata.toolCalls : [];
|
|
857
852
|
const usedMetadataIndexes = /* @__PURE__ */ new Set();
|
|
858
853
|
const parsed = [];
|
|
859
|
-
const candidateToolLabel = (c) => {
|
|
860
|
-
if (typeof c.name === "string") return c.name;
|
|
861
|
-
const t = c.tool && typeof c.tool === "object" && c.tool !== null && !Array.isArray(c.tool) ? c.tool : void 0;
|
|
862
|
-
if (typeof t?.name === "string") return t.name;
|
|
863
|
-
if (typeof t?.id === "string") return t.id;
|
|
864
|
-
return void 0;
|
|
865
|
-
};
|
|
866
854
|
const findMatchingMetadataIndex = (toolCall) => {
|
|
867
855
|
const id = typeof toolCall.id === "string" ? toolCall.id : void 0;
|
|
868
|
-
const
|
|
869
|
-
const name = (typeof toolCall.name === "string" ? toolCall.name : void 0) || (typeof nested?.name === "string" ? nested.name : void 0) || (typeof nested?.id === "string" ? nested.id : void 0);
|
|
856
|
+
const name = typeof toolCall.name === "string" ? toolCall.name : void 0;
|
|
870
857
|
const byId = id ? metadataToolCalls.findIndex((candidate, idx) => !usedMetadataIndexes.has(idx) && candidate?.id === id) : -1;
|
|
871
858
|
if (byId >= 0) return byId;
|
|
872
|
-
return name ? metadataToolCalls.findIndex((candidate, idx) =>
|
|
873
|
-
if (usedMetadataIndexes.has(idx)) return false;
|
|
874
|
-
const label = candidateToolLabel(candidate);
|
|
875
|
-
return label === name;
|
|
876
|
-
}) : -1;
|
|
859
|
+
return name ? metadataToolCalls.findIndex((candidate, idx) => !usedMetadataIndexes.has(idx) && candidate?.name === name) : -1;
|
|
877
860
|
};
|
|
878
861
|
const parseToolCall = (primary, secondary) => {
|
|
879
|
-
const nestedTool = primary && typeof primary.tool === "object" && primary.tool !== null && !Array.isArray(primary.tool) ? primary.tool : void 0;
|
|
880
862
|
const id = typeof primary.id === "string" ? primary.id : typeof secondary?.id === "string" ? secondary.id : void 0;
|
|
881
|
-
const name = typeof primary.name === "string" ? primary.name :
|
|
863
|
+
const name = typeof primary.name === "string" ? primary.name : typeof secondary?.name === "string" ? secondary.name : "tool";
|
|
882
864
|
const argsRaw = primary.args ?? primary.arguments ?? secondary?.args ?? secondary?.arguments;
|
|
883
865
|
const result = primary.output !== void 0 ? primary.output : primary.result !== void 0 ? primary.result : secondary?.output !== void 0 ? secondary.output : secondary?.result;
|
|
884
866
|
const status = normalizeToolStatus(primary.status ?? secondary?.status);
|
|
@@ -900,17 +882,7 @@ var extractToolCallsFromServerMessage = (msg) => {
|
|
|
900
882
|
if (usedMetadataIndexes.has(index)) return;
|
|
901
883
|
parsed.push(parseToolCall(toolCall));
|
|
902
884
|
});
|
|
903
|
-
|
|
904
|
-
const deduped = [];
|
|
905
|
-
for (const p of parsed) {
|
|
906
|
-
const id = p.id;
|
|
907
|
-
if (typeof id === "string" && id.length > 0) {
|
|
908
|
-
if (seenIds.has(id)) continue;
|
|
909
|
-
seenIds.add(id);
|
|
910
|
-
}
|
|
911
|
-
deduped.push(p);
|
|
912
|
-
}
|
|
913
|
-
return deduped;
|
|
885
|
+
return parsed;
|
|
914
886
|
};
|
|
915
887
|
var extractToolResultUpdateFromMessage = (msg) => {
|
|
916
888
|
if (msg.senderType !== "tool") return null;
|
|
@@ -1148,11 +1120,6 @@ function useCopilotz({
|
|
|
1148
1120
|
return;
|
|
1149
1121
|
}
|
|
1150
1122
|
if (senderType === "agent" && typeof payload.content === "string") {
|
|
1151
|
-
const trimmedContent = payload.content.trim();
|
|
1152
|
-
const hasToolCalls = hasToolCallsInPayload(payload);
|
|
1153
|
-
if (!trimmedContent && hasToolCalls) {
|
|
1154
|
-
return;
|
|
1155
|
-
}
|
|
1156
1123
|
setMessages((prev) => {
|
|
1157
1124
|
const next = [...prev];
|
|
1158
1125
|
for (let i = next.length - 1; i >= 0; i--) {
|
|
@@ -1162,6 +1129,7 @@ function useCopilotz({
|
|
|
1162
1129
|
return next;
|
|
1163
1130
|
}
|
|
1164
1131
|
}
|
|
1132
|
+
const trimmedContent = payload.content.trim();
|
|
1165
1133
|
if (!trimmedContent) {
|
|
1166
1134
|
return prev;
|
|
1167
1135
|
}
|
|
@@ -1218,11 +1186,9 @@ function useCopilotz({
|
|
|
1218
1186
|
if (!nextThreadId && normalized.length > 0) {
|
|
1219
1187
|
nextThreadId = normalized[0].id;
|
|
1220
1188
|
}
|
|
1221
|
-
|
|
1222
|
-
|
|
1223
|
-
|
|
1224
|
-
}
|
|
1225
|
-
return nextThreadId ?? curId ?? null;
|
|
1189
|
+
setCurrentThreadId(nextThreadId ?? null);
|
|
1190
|
+
setCurrentThreadExternalId(nextThreadId ? externalMap[nextThreadId] ?? null : null);
|
|
1191
|
+
return nextThreadId;
|
|
1226
1192
|
}, []);
|
|
1227
1193
|
const fetchAndSetThreadsState = useCallback2(async (uid, preferredExternalId) => {
|
|
1228
1194
|
try {
|
|
@@ -1417,60 +1383,57 @@ function useCopilotz({
|
|
|
1417
1383
|
params.onBeforeStart?.(currentAssistantId);
|
|
1418
1384
|
let hasStreamProgress = false;
|
|
1419
1385
|
let pendingStartNewAssistantBubble = false;
|
|
1420
|
-
const updateStreamingMessage = (partial,
|
|
1386
|
+
const updateStreamingMessage = (partial, opts) => {
|
|
1421
1387
|
if (partial && partial.length > 0) {
|
|
1422
1388
|
hasStreamProgress = true;
|
|
1423
1389
|
}
|
|
1424
|
-
if (reasoningPartial !== void 0 && reasoningPartial.length > 0) {
|
|
1425
|
-
hasStreamProgress = true;
|
|
1426
|
-
}
|
|
1427
1390
|
const nextStreaming = true;
|
|
1428
1391
|
const nextComplete = false;
|
|
1392
|
+
const isReasoning = opts?.isReasoning ?? false;
|
|
1393
|
+
const applyUpdate = (msg) => {
|
|
1394
|
+
if (isReasoning) {
|
|
1395
|
+
return { ...msg, reasoning: partial, isReasoningStreaming: true, isStreaming: nextStreaming, isComplete: nextComplete };
|
|
1396
|
+
}
|
|
1397
|
+
const reasoningPatch = msg.reasoning ? { isReasoningStreaming: false } : {};
|
|
1398
|
+
return { ...msg, content: partial, ...reasoningPatch, isStreaming: nextStreaming, isComplete: nextComplete };
|
|
1399
|
+
};
|
|
1429
1400
|
setMessages((prev) => {
|
|
1430
|
-
const patch = (msg) => ({
|
|
1431
|
-
...msg,
|
|
1432
|
-
content: partial,
|
|
1433
|
-
...reasoningPartial !== void 0 ? { reasoning: reasoningPartial } : {},
|
|
1434
|
-
isStreaming: nextStreaming,
|
|
1435
|
-
isComplete: nextComplete
|
|
1436
|
-
});
|
|
1437
1401
|
const idx = prev.findIndex((m) => m.id === currentAssistantId);
|
|
1438
1402
|
if (idx >= 0 && prev[idx].role === "assistant" && prev[idx].isStreaming) {
|
|
1439
1403
|
const msg = prev[idx];
|
|
1440
|
-
|
|
1404
|
+
const next = applyUpdate(msg);
|
|
1405
|
+
if (msg.content === next.content && msg.reasoning === next.reasoning && msg.isReasoningStreaming === next.isReasoningStreaming && msg.isStreaming === next.isStreaming && msg.isComplete === next.isComplete) {
|
|
1441
1406
|
return prev;
|
|
1442
1407
|
}
|
|
1443
1408
|
const updated = [...prev];
|
|
1444
|
-
updated[idx] =
|
|
1409
|
+
updated[idx] = next;
|
|
1445
1410
|
return updated;
|
|
1446
1411
|
}
|
|
1447
1412
|
const last = prev[prev.length - 1];
|
|
1448
1413
|
if (last && last.role === "assistant" && last.isStreaming) {
|
|
1449
1414
|
currentAssistantId = last.id;
|
|
1450
1415
|
pendingStartNewAssistantBubble = false;
|
|
1451
|
-
|
|
1416
|
+
const next = applyUpdate(last);
|
|
1417
|
+
if (last.content === next.content && last.reasoning === next.reasoning && last.isReasoningStreaming === next.isReasoningStreaming && last.isStreaming === next.isStreaming && last.isComplete === next.isComplete) {
|
|
1452
1418
|
return prev;
|
|
1453
1419
|
}
|
|
1454
1420
|
const updated = [...prev];
|
|
1455
|
-
updated[prev.length - 1] =
|
|
1421
|
+
updated[prev.length - 1] = next;
|
|
1456
1422
|
return updated;
|
|
1457
1423
|
}
|
|
1458
1424
|
if (pendingStartNewAssistantBubble || !prev.length || (prev[prev.length - 1].role !== "assistant" || !prev[prev.length - 1].isStreaming)) {
|
|
1459
1425
|
const newId = generateId();
|
|
1460
1426
|
currentAssistantId = newId;
|
|
1461
1427
|
pendingStartNewAssistantBubble = false;
|
|
1462
|
-
|
|
1463
|
-
|
|
1464
|
-
|
|
1465
|
-
|
|
1466
|
-
|
|
1467
|
-
|
|
1468
|
-
|
|
1469
|
-
|
|
1470
|
-
|
|
1471
|
-
isComplete: nextComplete
|
|
1472
|
-
}
|
|
1473
|
-
];
|
|
1428
|
+
const base = {
|
|
1429
|
+
id: newId,
|
|
1430
|
+
role: "assistant",
|
|
1431
|
+
content: "",
|
|
1432
|
+
timestamp: nowTs(),
|
|
1433
|
+
isStreaming: nextStreaming,
|
|
1434
|
+
isComplete: nextComplete
|
|
1435
|
+
};
|
|
1436
|
+
return [...prev, applyUpdate(base)];
|
|
1474
1437
|
}
|
|
1475
1438
|
return prev;
|
|
1476
1439
|
});
|
|
@@ -1493,21 +1456,37 @@ function useCopilotz({
|
|
|
1493
1456
|
const payload = event?.payload ?? event;
|
|
1494
1457
|
if (type === "TOOL_CALL") {
|
|
1495
1458
|
const metadata = payload?.metadata ?? {};
|
|
1496
|
-
const tc = payload?.toolCall ??
|
|
1497
|
-
const
|
|
1498
|
-
const
|
|
1459
|
+
const tc = payload?.toolCall ?? void 0;
|
|
1460
|
+
const tcTool = tc?.tool ?? void 0;
|
|
1461
|
+
const call = payload?.call ?? metadata?.call;
|
|
1462
|
+
const func = call?.function ?? payload?.function;
|
|
1463
|
+
const toolName = tcTool?.name || func?.name || payload?.name || call?.name || metadata.toolName || metadata.tool || "tool";
|
|
1499
1464
|
let argsObj = {};
|
|
1500
|
-
const
|
|
1501
|
-
|
|
1465
|
+
const possibleArgs = [
|
|
1466
|
+
tc?.args,
|
|
1467
|
+
func?.arguments,
|
|
1468
|
+
payload?.args,
|
|
1469
|
+
call?.arguments,
|
|
1470
|
+
metadata?.args,
|
|
1471
|
+
metadata?.arguments
|
|
1472
|
+
];
|
|
1473
|
+
for (const candidate of possibleArgs) {
|
|
1474
|
+
if (candidate === void 0 || candidate === null) continue;
|
|
1502
1475
|
try {
|
|
1503
|
-
|
|
1476
|
+
if (typeof candidate === "string") {
|
|
1477
|
+
argsObj = JSON.parse(candidate);
|
|
1478
|
+
break;
|
|
1479
|
+
}
|
|
1480
|
+
if (typeof candidate === "object") {
|
|
1481
|
+
argsObj = candidate;
|
|
1482
|
+
break;
|
|
1483
|
+
}
|
|
1504
1484
|
} catch {
|
|
1505
1485
|
}
|
|
1506
|
-
} else if (argsRaw && typeof argsRaw === "object" && !Array.isArray(argsRaw)) {
|
|
1507
|
-
argsObj = argsRaw;
|
|
1508
1486
|
}
|
|
1509
|
-
const
|
|
1510
|
-
const
|
|
1487
|
+
const output = (tc?.output !== void 0 ? tc.output : void 0) ?? (metadata?.output !== void 0 ? metadata.output : void 0) ?? (payload?.output !== void 0 ? payload.output : void 0);
|
|
1488
|
+
const callId = tc?.id || call?.id || func?.id || payload?.id || generateId();
|
|
1489
|
+
const statusVal = tc?.status || payload?.status || event?.status || "pending";
|
|
1511
1490
|
return {
|
|
1512
1491
|
id: generateId(),
|
|
1513
1492
|
threadId: curThreadId ?? "",
|
|
@@ -1517,6 +1496,7 @@ function useCopilotz({
|
|
|
1517
1496
|
id: callId,
|
|
1518
1497
|
name: toolName,
|
|
1519
1498
|
args: argsObj,
|
|
1499
|
+
output,
|
|
1520
1500
|
status: statusVal
|
|
1521
1501
|
}]
|
|
1522
1502
|
};
|
|
@@ -1595,9 +1575,7 @@ function useCopilotz({
|
|
|
1595
1575
|
toolCalls: params.toolCalls,
|
|
1596
1576
|
selectedAgent: params.agentName ?? preferredAgentRef.current ?? null,
|
|
1597
1577
|
getRequestHeaders,
|
|
1598
|
-
onToken: (token,
|
|
1599
|
-
updateStreamingMessage(token, isComplete, raw, reasoning);
|
|
1600
|
-
},
|
|
1578
|
+
onToken: (token, _isComplete, _raw, opts) => updateStreamingMessage(token, opts),
|
|
1601
1579
|
onMessageEvent: async (event) => {
|
|
1602
1580
|
const intercepted = applyEventInterceptor(event);
|
|
1603
1581
|
if (intercepted?.handled) {
|
|
@@ -1607,9 +1585,6 @@ function useCopilotz({
|
|
|
1607
1585
|
const payload = getEventPayload(event);
|
|
1608
1586
|
if (type === "MESSAGE" || type === "NEW_MESSAGE") {
|
|
1609
1587
|
const senderType = getEventSenderType(payload);
|
|
1610
|
-
if (senderType === "agent" && hasStreamProgress) {
|
|
1611
|
-
return;
|
|
1612
|
-
}
|
|
1613
1588
|
if (senderType === "tool") {
|
|
1614
1589
|
const metadata = payload?.metadata ?? {};
|
|
1615
1590
|
const toolCallsArray = metadata?.toolCalls;
|
|
@@ -1619,16 +1594,8 @@ function useCopilotz({
|
|
|
1619
1594
|
}
|
|
1620
1595
|
processToolOutput(metadata);
|
|
1621
1596
|
const toolCallId = toolCallData.id;
|
|
1622
|
-
const
|
|
1623
|
-
const
|
|
1624
|
-
const toolResultRaw = toolCallData.output || payload?.content;
|
|
1625
|
-
const toolResult = typeof toolResultRaw === "string" ? (() => {
|
|
1626
|
-
try {
|
|
1627
|
-
return JSON.parse(toolResultRaw);
|
|
1628
|
-
} catch {
|
|
1629
|
-
return toolResultRaw;
|
|
1630
|
-
}
|
|
1631
|
-
})() : toolResultRaw;
|
|
1597
|
+
const toolCallName = toolCallData.name;
|
|
1598
|
+
const toolResult = toolCallData.output || payload?.content;
|
|
1632
1599
|
const toolStatus = toolCallData.status || "completed";
|
|
1633
1600
|
const isFailed = toolStatus === "failed" || toolCallData?.error;
|
|
1634
1601
|
setMessages((prev) => {
|
|
@@ -1667,7 +1634,7 @@ function useCopilotz({
|
|
|
1667
1634
|
return;
|
|
1668
1635
|
}
|
|
1669
1636
|
handleStreamMessageEvent(event);
|
|
1670
|
-
if (senderType === "agent"
|
|
1637
|
+
if (senderType === "agent") {
|
|
1671
1638
|
currentAssistantId = generateId();
|
|
1672
1639
|
pendingStartNewAssistantBubble = true;
|
|
1673
1640
|
}
|
|
@@ -1680,27 +1647,20 @@ function useCopilotz({
|
|
|
1680
1647
|
if (!toolCall) return;
|
|
1681
1648
|
setMessages(
|
|
1682
1649
|
(prev) => (() => {
|
|
1683
|
-
const appendToolCall = (msg) => {
|
|
1684
|
-
|
|
1685
|
-
|
|
1686
|
-
|
|
1687
|
-
|
|
1688
|
-
|
|
1689
|
-
|
|
1690
|
-
|
|
1691
|
-
|
|
1692
|
-
|
|
1693
|
-
|
|
1694
|
-
|
|
1695
|
-
|
|
1696
|
-
|
|
1697
|
-
result: toolCall.output,
|
|
1698
|
-
status: toolCall.status ?? "running",
|
|
1699
|
-
startTime: Date.now()
|
|
1700
|
-
}
|
|
1701
|
-
]
|
|
1702
|
-
};
|
|
1703
|
-
};
|
|
1650
|
+
const appendToolCall = (msg) => ({
|
|
1651
|
+
...msg,
|
|
1652
|
+
toolCalls: [
|
|
1653
|
+
...Array.isArray(msg.toolCalls) ? msg.toolCalls : [],
|
|
1654
|
+
{
|
|
1655
|
+
id: toolCall.id ?? generateId(),
|
|
1656
|
+
name: toolCall.name ?? "tool",
|
|
1657
|
+
arguments: toolCall.args ?? toolCall.arguments ?? {},
|
|
1658
|
+
result: toolCall.output,
|
|
1659
|
+
status: toolCall.status ?? "running",
|
|
1660
|
+
startTime: Date.now()
|
|
1661
|
+
}
|
|
1662
|
+
]
|
|
1663
|
+
});
|
|
1704
1664
|
const currentIdx = prev.findIndex((message) => message.id === currentAssistantId && message.role === "assistant" && message.isStreaming);
|
|
1705
1665
|
if (currentIdx >= 0) {
|
|
1706
1666
|
const next = [...prev];
|
|
@@ -1712,7 +1672,7 @@ function useCopilotz({
|
|
|
1712
1672
|
return next;
|
|
1713
1673
|
}
|
|
1714
1674
|
const last = prev[prev.length - 1];
|
|
1715
|
-
if (last?.role === "assistant" && last.isStreaming) {
|
|
1675
|
+
if (!pendingStartNewAssistantBubble && last?.role === "assistant" && last.isStreaming) {
|
|
1716
1676
|
currentAssistantId = last.id;
|
|
1717
1677
|
const next = [...prev];
|
|
1718
1678
|
next[prev.length - 1] = appendToolCall({
|
|
@@ -1739,6 +1699,7 @@ function useCopilotz({
|
|
|
1739
1699
|
})()
|
|
1740
1700
|
);
|
|
1741
1701
|
hasStreamProgress = true;
|
|
1702
|
+
pendingStartNewAssistantBubble = true;
|
|
1742
1703
|
return;
|
|
1743
1704
|
}
|
|
1744
1705
|
const sm = await toServerMessageFromEvent(event);
|
|
@@ -1797,10 +1758,8 @@ function useCopilotz({
|
|
|
1797
1758
|
effectiveThreadExternalId = generateId();
|
|
1798
1759
|
}
|
|
1799
1760
|
setCurrentThreadExternalId(effectiveThreadExternalId);
|
|
1800
|
-
currentThreadExternalIdRef.current = effectiveThreadExternalId;
|
|
1801
1761
|
} else if (curThreadExtId !== (effectiveThreadExternalId ?? null)) {
|
|
1802
1762
|
setCurrentThreadExternalId(effectiveThreadExternalId ?? null);
|
|
1803
|
-
currentThreadExternalIdRef.current = effectiveThreadExternalId ?? null;
|
|
1804
1763
|
}
|
|
1805
1764
|
const conversationKey = threadIdForSend ?? effectiveThreadExternalId;
|
|
1806
1765
|
const currentMetadata = threadMetadataMapRef.current[conversationKey];
|
|
@@ -1834,13 +1793,6 @@ function useCopilotz({
|
|
|
1834
1793
|
setThreads((prev) => [newThread, ...prev]);
|
|
1835
1794
|
setThreadMetadataMap((prev) => ({ ...prev, [conversationKey]: {} }));
|
|
1836
1795
|
setThreadExternalIdMap((prev) => ({ ...prev, [conversationKey]: effectiveThreadExternalId ?? null }));
|
|
1837
|
-
setCurrentThreadId(conversationKey);
|
|
1838
|
-
currentThreadIdRef.current = conversationKey;
|
|
1839
|
-
threadsRef.current = [newThread, ...threadsRef.current];
|
|
1840
|
-
threadExternalIdMapRef.current = {
|
|
1841
|
-
...threadExternalIdMapRef.current,
|
|
1842
|
-
[conversationKey]: effectiveThreadExternalId ?? null
|
|
1843
|
-
};
|
|
1844
1796
|
}
|
|
1845
1797
|
try {
|
|
1846
1798
|
await sendCopilotzMessage({
|