@gendive/chatllm 0.21.6 → 0.21.7

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.
@@ -3603,13 +3603,17 @@ ${finalContent}`;
3603
3603
  for (const [skillName, skillConfig] of attachmentSkills) {
3604
3604
  let matchedFiles = currentAttachments.filter((att) => {
3605
3605
  if (!skillConfig.acceptedTypes || skillConfig.acceptedTypes.length === 0) return true;
3606
+ const fileName = (att.name || "").toLowerCase();
3607
+ const fileMime = (att.mimeType || "").toLowerCase();
3608
+ const fileExt = fileName.includes(".") ? fileName.slice(fileName.lastIndexOf(".")) : "";
3606
3609
  return skillConfig.acceptedTypes.some((type) => {
3607
- if (type.startsWith(".")) return att.name.toLowerCase().endsWith(type.toLowerCase());
3608
- if (type.includes("*")) {
3609
- const regex = new RegExp("^" + type.replace("*", ".*") + "$");
3610
- return regex.test(att.mimeType);
3610
+ const t = type.toLowerCase();
3611
+ if (t.startsWith(".")) return fileExt === t || fileName.endsWith(t);
3612
+ if (t.includes("*")) {
3613
+ const regex = new RegExp("^" + t.replace(/[.*+?^${}()|[\]\\]/g, "\\$&").replace("\\*", ".*") + "$");
3614
+ return regex.test(fileMime);
3611
3615
  }
3612
- return att.mimeType === type;
3616
+ return fileMime === t;
3613
3617
  });
3614
3618
  });
3615
3619
  if (skipImageAttachmentSkill) {
@@ -4064,25 +4068,26 @@ ${attachmentContext}
4064
4068
  }
4065
4069
  }
4066
4070
  }
4067
- const saveMessagesOnEarlyReturn = () => {
4071
+ const saveMessagesOnEarlyReturn = (overrideContentParts) => {
4068
4072
  if (!useExternalStorage || !capturedSessionId) return;
4069
- queueMicrotask(() => {
4073
+ setTimeout(() => {
4070
4074
  const latestSession = sessionsRef.current.find((s) => s.id === capturedSessionId);
4071
4075
  if (!latestSession) return;
4072
4076
  const latestMessages = latestSession.messages;
4073
4077
  const assistantMsg = [...latestMessages].reverse().find((m) => m.role === "assistant");
4074
4078
  const userMsg = latestMessages.find((m) => m.role === "user" && m.content === finalContent);
4075
4079
  const assistantContent = assistantMsg?.content || "";
4076
- if (assistantContent && onSaveMessagesRef.current) {
4080
+ const finalContentParts = overrideContentParts || assistantMsg?.contentParts;
4081
+ if ((assistantContent || finalContentParts) && onSaveMessagesRef.current) {
4077
4082
  onSaveMessagesRef.current(capturedSessionId, [
4078
4083
  { role: "user", message: finalContent, ...userMsg?.contentParts && { contentParts: userMsg.contentParts } },
4079
- { role: "assistant", message: assistantContent, ...assistantMsg?.contentParts && { contentParts: assistantMsg.contentParts } }
4084
+ { role: "assistant", message: assistantContent, ...finalContentParts && { contentParts: finalContentParts } }
4080
4085
  ]).catch((e) => console.error("[useChatUI] Failed to save messages:", e));
4081
4086
  }
4082
4087
  if (latestSession.messages.length > 0) {
4083
4088
  writeSessionCache(storageKey, latestSession);
4084
4089
  }
4085
- });
4090
+ }, 0);
4086
4091
  };
4087
4092
  if (!shouldSkipSkillParsing) {
4088
4093
  const assistantContent = accumulatedContent;
@@ -4272,7 +4277,7 @@ ${attachmentContext}
4272
4277
  promoteToSessionContext(capturedSessionId, toolName, result.content, result.metadata, toolLabel || toolName);
4273
4278
  }
4274
4279
  if (resultType === "image" || resultType === "file") {
4275
- saveMessagesOnEarlyReturn();
4280
+ saveMessagesOnEarlyReturn(parts);
4276
4281
  removeLoadingSession(capturedSessionId);
4277
4282
  abortControllersRef.current.delete(capturedSessionId);
4278
4283
  return;
@@ -4283,7 +4288,7 @@ ${attachmentContext}
4283
4288
  shouldContinue = decision === "continue";
4284
4289
  }
4285
4290
  if (!shouldContinue) {
4286
- saveMessagesOnEarlyReturn();
4291
+ saveMessagesOnEarlyReturn(parts);
4287
4292
  removeLoadingSession(capturedSessionId);
4288
4293
  abortControllersRef.current.delete(capturedSessionId);
4289
4294
  return;
@@ -4358,13 +4363,13 @@ ${result.content}
4358
4363
  shouldContinueImgFile = decision === "continue";
4359
4364
  }
4360
4365
  if (!shouldContinueImgFile) {
4361
- saveMessagesOnEarlyReturn();
4366
+ saveMessagesOnEarlyReturn(imgFileParts);
4362
4367
  removeLoadingSession(capturedSessionId);
4363
4368
  abortControllersRef.current.delete(capturedSessionId);
4364
4369
  return;
4365
4370
  }
4366
4371
  skipNextSkillParsingRef.current = true;
4367
- saveMessagesOnEarlyReturn();
4372
+ saveMessagesOnEarlyReturn(imgFileParts);
4368
4373
  const imgFilePrompt = skillResultType === "image" ? `"${detectedSkill.name}" \uC2A4\uD0AC\uB85C \uC774\uBBF8\uC9C0\uAC00 \uC0DD\uC131\uB418\uC5B4 \uC0AC\uC6A9\uC790\uC5D0\uAC8C \uD45C\uC2DC\uB418\uC5C8\uC2B5\uB2C8\uB2E4. \uC774\uBBF8\uC9C0 URL\uC744 \uD14D\uC2A4\uD2B8\uC5D0 \uD3EC\uD568\uD558\uC9C0 \uB9D0\uACE0, \uC0DD\uC131\uB41C \uC774\uBBF8\uC9C0\uC5D0 \uB300\uD574 \uAC04\uB2E8\uD788 \uC548\uB0B4\uD574\uC8FC\uC138\uC694. skill_use \uD0DC\uADF8\uB294 \uC0AC\uC6A9\uD558\uC9C0 \uB9C8\uC138\uC694.` : `"${detectedSkill.name}" \uC2A4\uD0AC\uB85C \uD30C\uC77C\uC774 \uC0DD\uC131\uB418\uC5B4 \uC0AC\uC6A9\uC790\uC5D0\uAC8C \uD45C\uC2DC\uB418\uC5C8\uC2B5\uB2C8\uB2E4. \uD30C\uC77C URL\uC744 \uD14D\uC2A4\uD2B8\uC5D0 \uD3EC\uD568\uD558\uC9C0 \uB9D0\uACE0, \uACB0\uACFC\uC5D0 \uB300\uD574 \uAC04\uB2E8\uD788 \uC548\uB0B4\uD574\uC8FC\uC138\uC694. skill_use \uD0DC\uADF8\uB294 \uC0AC\uC6A9\uD558\uC9C0 \uB9C8\uC138\uC694.`;
4369
4374
  setTimeout(() => {
4370
4375
  sendMessage(imgFilePrompt, { hiddenUserMessage: true });