@copilotz/chat-adapter 0.9.42 → 0.9.43

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 CHANGED
@@ -57,8 +57,8 @@ type StreamCallbacks = {
57
57
  onToken?: (token: string, isComplete: boolean, raw?: any, options?: {
58
58
  isReasoning?: boolean;
59
59
  }) => void;
60
- onMessageEvent?: (payload: any) => void;
61
- onAssetEvent?: (payload: any) => void;
60
+ onMessageEvent?: (payload: any) => void | Promise<void>;
61
+ onAssetEvent?: (payload: any) => void | Promise<void>;
62
62
  signal?: AbortSignal;
63
63
  };
64
64
  type RunOptions = {
package/dist/index.js CHANGED
@@ -436,7 +436,7 @@ async function runCopilotzStream(options) {
436
436
  lastTokenWasReasoning = false;
437
437
  hadNonReasoningContent = false;
438
438
  };
439
- const processEvent = (eventChunk) => {
439
+ const processEvent = async (eventChunk) => {
440
440
  if (!eventChunk.trim()) return;
441
441
  const lines = eventChunk.split("\n");
442
442
  let eventType = "message";
@@ -496,13 +496,13 @@ async function runCopilotzStream(options) {
496
496
  hadNonReasoningContent = true;
497
497
  lastTokenWasReasoning = false;
498
498
  collectedMessages.push(payload2);
499
- onMessageEvent?.(payload2);
499
+ await onMessageEvent?.(payload2);
500
500
  break;
501
501
  }
502
502
  case "TOOL_CALL": {
503
503
  hadNonReasoningContent = true;
504
504
  lastTokenWasReasoning = false;
505
- onMessageEvent?.(payload2);
505
+ await onMessageEvent?.(payload2);
506
506
  break;
507
507
  }
508
508
  case "TOOL_RESULT":
@@ -512,7 +512,7 @@ async function runCopilotzStream(options) {
512
512
  lastCompletedText = resultAnswer;
513
513
  }
514
514
  resetTokenAggregation();
515
- onMessageEvent?.(payload2);
515
+ await onMessageEvent?.(payload2);
516
516
  break;
517
517
  }
518
518
  case "ASSET_CREATED": {
@@ -522,7 +522,7 @@ async function runCopilotzStream(options) {
522
522
  [assetPayload.assetId || "0"]: assetPayload.dataUrl
523
523
  };
524
524
  }
525
- onAssetEvent?.(assetPayload);
525
+ await onAssetEvent?.(assetPayload);
526
526
  break;
527
527
  }
528
528
  case "ERROR":
@@ -530,9 +530,9 @@ async function runCopilotzStream(options) {
530
530
  default: {
531
531
  const hasEnvelope = payload2 && typeof payload2 === "object" && "type" in payload2;
532
532
  if (hasEnvelope) {
533
- onMessageEvent?.(payload2);
533
+ await onMessageEvent?.(payload2);
534
534
  } else {
535
- onMessageEvent?.({ type: eventType, payload: payload2 });
535
+ await onMessageEvent?.({ type: eventType, payload: payload2 });
536
536
  }
537
537
  break;
538
538
  }
@@ -549,12 +549,12 @@ async function runCopilotzStream(options) {
549
549
  while (eventBoundary >= 0) {
550
550
  const chunk = buffer.slice(0, eventBoundary);
551
551
  buffer = buffer.slice(eventBoundary + SSE_LINE_BREAK.length);
552
- processEvent(chunk);
552
+ await processEvent(chunk);
553
553
  eventBoundary = buffer.indexOf(SSE_LINE_BREAK);
554
554
  }
555
555
  }
556
556
  if (buffer.length > 0) {
557
- processEvent(buffer);
557
+ await processEvent(buffer);
558
558
  }
559
559
  return {
560
560
  text: lastCompletedText || aggregatedText,
@@ -925,27 +925,33 @@ var applyAssistantToolResult = (message, update) => {
925
925
  const index = items.findIndex((item2) => item2.kind === "tool" && (update.id && item2.id === update.id || !update.id && item2.toolName === update.name));
926
926
  if (index === -1) return message;
927
927
  const item = items[index];
928
+ const { error, ...toolCallUpdate } = update;
928
929
  const toolCall = item.details?.toolCall;
929
- const nextToolCall = toolCall ? { ...toolCall, ...update } : {
930
- id: update.id ?? item.id,
931
- name: update.name,
930
+ const nextToolCall = toolCall ? { ...toolCall, ...toolCallUpdate } : {
931
+ id: toolCallUpdate.id ?? item.id,
932
+ name: toolCallUpdate.name,
932
933
  arguments: {},
933
- status: update.status,
934
- ...update.result !== void 0 ? { result: update.result } : {},
935
- ...update.endTime !== void 0 ? { endTime: update.endTime } : {}
934
+ status: toolCallUpdate.status,
935
+ ...toolCallUpdate.result !== void 0 ? { result: toolCallUpdate.result } : {},
936
+ ...toolCallUpdate.endTime !== void 0 ? { endTime: toolCallUpdate.endTime } : {}
936
937
  };
937
938
  const status = toolStatusToActivityStatus(update.status);
939
+ const details = {
940
+ ...item.details ?? {},
941
+ toolCall: nextToolCall,
942
+ ...update.result !== void 0 ? { result: update.result } : {},
943
+ ...error !== void 0 ? { error } : {}
944
+ };
945
+ if (error === void 0 && update.status !== "failed") {
946
+ delete details.error;
947
+ }
938
948
  const next = [...items];
939
949
  next[index] = {
940
950
  ...item,
941
951
  status,
942
952
  toolName: update.name,
943
953
  ...status !== "active" ? { completedAt: update.endTime ?? Date.now() } : {},
944
- details: {
945
- ...item.details ?? {},
946
- toolCall: nextToolCall,
947
- ...update.result !== void 0 ? { result: update.result } : {}
948
- }
954
+ details
949
955
  };
950
956
  return setItems(message, next);
951
957
  };
@@ -1243,8 +1249,18 @@ var expectToolStatus = (status, path) => {
1243
1249
  if (status === "pending") return "pending";
1244
1250
  if (status === "running" || status === "processing") return "running";
1245
1251
  if (status === "failed") return "failed";
1252
+ if (status === "cancelled") return "failed";
1246
1253
  if (status === "completed") return "completed";
1247
- return fail(`${path} must be pending, running, processing, completed, or failed`);
1254
+ return fail(`${path} must be pending, running, processing, completed, failed, or cancelled`);
1255
+ };
1256
+ var formatToolError = (error) => {
1257
+ if (error === void 0) return void 0;
1258
+ if (typeof error === "string") return error;
1259
+ try {
1260
+ return JSON.stringify(error);
1261
+ } catch {
1262
+ return String(error);
1263
+ }
1248
1264
  };
1249
1265
  var expectToolArguments = (value, path) => {
1250
1266
  if (isRecord(value)) return value;
@@ -1271,7 +1287,7 @@ var matchesToolResultUpdate = (target, update) => {
1271
1287
  var findMatchingToolItem = (toolItems, update) => toolItems.find((item) => matchesToolResultUpdate(
1272
1288
  { id: item.id, name: item.toolName },
1273
1289
  update
1274
- ) && (item.status === "active" || item.details?.result === void 0));
1290
+ ) && (item.status === "active" || item.details?.result === void 0 && item.details?.error === void 0));
1275
1291
  var applyToolResultUpdateToMessages = (messages, update, assistantPatch) => {
1276
1292
  const nextMessages = [...messages];
1277
1293
  for (let i = nextMessages.length - 1; i >= 0; i--) {
@@ -1289,6 +1305,7 @@ var applyToolResultUpdateToMessages = (messages, update, assistantPatch) => {
1289
1305
  name: update.name ?? toolItem.toolName ?? toolItem.id,
1290
1306
  status: update.status,
1291
1307
  ...update.result !== void 0 ? { result: update.result } : {},
1308
+ ...update.error !== void 0 ? { error: update.error } : {},
1292
1309
  endTime: update.endTime
1293
1310
  }),
1294
1311
  ...assistantPatch ?? {}
@@ -1314,12 +1331,13 @@ var extractLiveToolResultUpdate = (payload, now = () => Date.now()) => {
1314
1331
  const payloadRecord = expectRecord(payload, "TOOL_RESULT payload");
1315
1332
  const tool = expectRecord(payloadRecord.tool, "TOOL_RESULT payload.tool");
1316
1333
  const result = payloadRecord.projectedOutput !== void 0 ? payloadRecord.projectedOutput : payloadRecord.output;
1317
- if (result === void 0) fail("TOOL_RESULT payload requires output or projectedOutput");
1334
+ const error = formatToolError(payloadRecord.error);
1318
1335
  return {
1319
1336
  id: expectString(payloadRecord.toolCallId, "TOOL_RESULT payload.toolCallId"),
1320
1337
  name: expectToolName(tool, "TOOL_RESULT payload.tool.id"),
1321
1338
  status: expectToolStatus(payloadRecord.status, "TOOL_RESULT payload.status"),
1322
- result,
1339
+ ...result !== void 0 ? { result } : {},
1340
+ ...error !== void 0 ? { error } : {},
1323
1341
  endTime: now()
1324
1342
  };
1325
1343
  };
@@ -1342,6 +1360,7 @@ var extractToolCallsFromServerMessage = (msg) => {
1342
1360
  const name = expectToolName(tool, "toolCall.tool.id");
1343
1361
  const argsRaw = primary.args ?? secondary?.args;
1344
1362
  const result = primary.output !== void 0 ? primary.output : secondary?.output !== void 0 ? secondary.output : primary.projectedOutput !== void 0 ? primary.projectedOutput : secondary?.projectedOutput;
1363
+ const error = formatToolError(primary.error !== void 0 ? primary.error : secondary?.error);
1345
1364
  const rawStatus = primary.status ?? secondary?.status;
1346
1365
  return {
1347
1366
  id,
@@ -1349,6 +1368,7 @@ var extractToolCallsFromServerMessage = (msg) => {
1349
1368
  name,
1350
1369
  arguments: expectToolArguments(argsRaw, "toolCall.args"),
1351
1370
  ...result !== void 0 ? { result } : {},
1371
+ ...error !== void 0 ? { error } : {},
1352
1372
  status: rawStatus === void 0 ? "running" : expectToolStatus(rawStatus, "toolCall.status")
1353
1373
  };
1354
1374
  };
@@ -1374,13 +1394,13 @@ var extractToolResultUpdateFromMessage = (msg, now = () => Date.now()) => {
1374
1394
  const toolCalls = extractToolCallsFromServerMessage(msg);
1375
1395
  if (toolCalls.length === 0) fail("tool message requires metadata.toolCalls");
1376
1396
  const firstToolCall = toolCalls[0];
1377
- if (firstToolCall.result === void 0) fail("tool result message requires tool call output");
1378
1397
  expectStringValue(msg.createdAt, "tool result message.createdAt");
1379
1398
  return {
1380
1399
  id: firstToolCall.id,
1381
1400
  ...firstToolCall.toolExecutionId ? { toolExecutionId: firstToolCall.toolExecutionId } : {},
1382
1401
  name: firstToolCall.name,
1383
- result: firstToolCall.result,
1402
+ ...firstToolCall.result !== void 0 ? { result: firstToolCall.result } : {},
1403
+ ...firstToolCall.error !== void 0 ? { error: firstToolCall.error } : {},
1384
1404
  status: firstToolCall.status,
1385
1405
  endTime: new Date(msg.createdAt).getTime()
1386
1406
  };
@@ -1632,6 +1652,15 @@ var isTerminalEmptyLlmResultEvent = (event) => {
1632
1652
  return true;
1633
1653
  };
1634
1654
 
1655
+ // src/threadIdentity.ts
1656
+ var identityValues = ({ id, externalId }) => [id, externalId].filter((value) => typeof value === "string" && value.length > 0);
1657
+ var isSameThreadIdentity = (owner, current) => {
1658
+ const ownerValues = identityValues(owner);
1659
+ if (ownerValues.length === 0) return true;
1660
+ const currentValues = new Set(identityValues(current));
1661
+ return ownerValues.some((value) => currentValues.has(value));
1662
+ };
1663
+
1635
1664
  // src/useCopilotzChat.ts
1636
1665
  var nowTs = () => Date.now();
1637
1666
  var generateId = () => globalThis.crypto?.randomUUID?.() ?? `id-${Date.now()}-${Math.random().toString(36).slice(2, 10)}`;
@@ -2328,7 +2357,10 @@ function useCopilotz({ userId, userName, userAvatar, assistantName, agentOptions
2328
2357
  let currentAssistantSender = params.assistantSender;
2329
2358
  const streamOwnerThreadId = currentThreadIdRef.current;
2330
2359
  const streamOwnerThreadExternalId = params.threadExternalId ?? currentThreadExternalIdRef.current;
2331
- const streamStillOwnsVisibleThread = () => streamOwnerThreadId ? currentThreadIdRef.current === streamOwnerThreadId : !streamOwnerThreadExternalId || currentThreadExternalIdRef.current === streamOwnerThreadExternalId || currentThreadIdRef.current === streamOwnerThreadExternalId;
2360
+ const streamStillOwnsVisibleThread = () => isSameThreadIdentity(
2361
+ { id: streamOwnerThreadId, externalId: streamOwnerThreadExternalId },
2362
+ { id: currentThreadIdRef.current, externalId: currentThreadExternalIdRef.current }
2363
+ );
2332
2364
  params.onBeforeStart?.(currentAssistantId);
2333
2365
  let hasStreamProgress = false;
2334
2366
  const updateStreamingMessage = (partial, opts) => {
@@ -2724,7 +2756,10 @@ function useCopilotz({ userId, userName, userAvatar, assistantName, agentOptions
2724
2756
  }
2725
2757
  const conversationKey = threadIdForSend ?? effectiveThreadExternalId;
2726
2758
  const sendOwnerThreadExternalId = effectiveThreadExternalId ?? curThreadExtId;
2727
- const stillShowingSendOwnerThread = () => sendOwnerThreadId ? currentThreadIdRef.current === sendOwnerThreadId : !sendOwnerThreadExternalId || currentThreadExternalIdRef.current === sendOwnerThreadExternalId || currentThreadIdRef.current === sendOwnerThreadExternalId;
2759
+ const stillShowingSendOwnerThread = () => isSameThreadIdentity(
2760
+ { id: sendOwnerThreadId, externalId: sendOwnerThreadExternalId },
2761
+ { id: currentThreadIdRef.current, externalId: currentThreadExternalIdRef.current }
2762
+ );
2728
2763
  const currentMetadata = threadMetadataMapRef.current[conversationKey];
2729
2764
  const pendingTitle = currentMetadata?.pendingTitle;
2730
2765
  const userMessage = {