@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.
@@ -3520,13 +3520,17 @@ ${finalContent}`;
3520
3520
  for (const [skillName, skillConfig] of attachmentSkills) {
3521
3521
  let matchedFiles = currentAttachments.filter((att) => {
3522
3522
  if (!skillConfig.acceptedTypes || skillConfig.acceptedTypes.length === 0) return true;
3523
+ const fileName = (att.name || "").toLowerCase();
3524
+ const fileMime = (att.mimeType || "").toLowerCase();
3525
+ const fileExt = fileName.includes(".") ? fileName.slice(fileName.lastIndexOf(".")) : "";
3523
3526
  return skillConfig.acceptedTypes.some((type) => {
3524
- if (type.startsWith(".")) return att.name.toLowerCase().endsWith(type.toLowerCase());
3525
- if (type.includes("*")) {
3526
- const regex = new RegExp("^" + type.replace("*", ".*") + "$");
3527
- return regex.test(att.mimeType);
3527
+ const t = type.toLowerCase();
3528
+ if (t.startsWith(".")) return fileExt === t || fileName.endsWith(t);
3529
+ if (t.includes("*")) {
3530
+ const regex = new RegExp("^" + t.replace(/[.*+?^${}()|[\]\\]/g, "\\$&").replace("\\*", ".*") + "$");
3531
+ return regex.test(fileMime);
3528
3532
  }
3529
- return att.mimeType === type;
3533
+ return fileMime === t;
3530
3534
  });
3531
3535
  });
3532
3536
  if (skipImageAttachmentSkill) {
@@ -3981,25 +3985,26 @@ ${attachmentContext}
3981
3985
  }
3982
3986
  }
3983
3987
  }
3984
- const saveMessagesOnEarlyReturn = () => {
3988
+ const saveMessagesOnEarlyReturn = (overrideContentParts) => {
3985
3989
  if (!useExternalStorage || !capturedSessionId) return;
3986
- queueMicrotask(() => {
3990
+ setTimeout(() => {
3987
3991
  const latestSession = sessionsRef.current.find((s) => s.id === capturedSessionId);
3988
3992
  if (!latestSession) return;
3989
3993
  const latestMessages = latestSession.messages;
3990
3994
  const assistantMsg = [...latestMessages].reverse().find((m) => m.role === "assistant");
3991
3995
  const userMsg = latestMessages.find((m) => m.role === "user" && m.content === finalContent);
3992
3996
  const assistantContent = assistantMsg?.content || "";
3993
- if (assistantContent && onSaveMessagesRef.current) {
3997
+ const finalContentParts = overrideContentParts || assistantMsg?.contentParts;
3998
+ if ((assistantContent || finalContentParts) && onSaveMessagesRef.current) {
3994
3999
  onSaveMessagesRef.current(capturedSessionId, [
3995
4000
  { role: "user", message: finalContent, ...userMsg?.contentParts && { contentParts: userMsg.contentParts } },
3996
- { role: "assistant", message: assistantContent, ...assistantMsg?.contentParts && { contentParts: assistantMsg.contentParts } }
4001
+ { role: "assistant", message: assistantContent, ...finalContentParts && { contentParts: finalContentParts } }
3997
4002
  ]).catch((e) => console.error("[useChatUI] Failed to save messages:", e));
3998
4003
  }
3999
4004
  if (latestSession.messages.length > 0) {
4000
4005
  writeSessionCache(storageKey, latestSession);
4001
4006
  }
4002
- });
4007
+ }, 0);
4003
4008
  };
4004
4009
  if (!shouldSkipSkillParsing) {
4005
4010
  const assistantContent = accumulatedContent;
@@ -4189,7 +4194,7 @@ ${attachmentContext}
4189
4194
  promoteToSessionContext(capturedSessionId, toolName, result.content, result.metadata, toolLabel || toolName);
4190
4195
  }
4191
4196
  if (resultType === "image" || resultType === "file") {
4192
- saveMessagesOnEarlyReturn();
4197
+ saveMessagesOnEarlyReturn(parts);
4193
4198
  removeLoadingSession(capturedSessionId);
4194
4199
  abortControllersRef.current.delete(capturedSessionId);
4195
4200
  return;
@@ -4200,7 +4205,7 @@ ${attachmentContext}
4200
4205
  shouldContinue = decision === "continue";
4201
4206
  }
4202
4207
  if (!shouldContinue) {
4203
- saveMessagesOnEarlyReturn();
4208
+ saveMessagesOnEarlyReturn(parts);
4204
4209
  removeLoadingSession(capturedSessionId);
4205
4210
  abortControllersRef.current.delete(capturedSessionId);
4206
4211
  return;
@@ -4275,13 +4280,13 @@ ${result.content}
4275
4280
  shouldContinueImgFile = decision === "continue";
4276
4281
  }
4277
4282
  if (!shouldContinueImgFile) {
4278
- saveMessagesOnEarlyReturn();
4283
+ saveMessagesOnEarlyReturn(imgFileParts);
4279
4284
  removeLoadingSession(capturedSessionId);
4280
4285
  abortControllersRef.current.delete(capturedSessionId);
4281
4286
  return;
4282
4287
  }
4283
4288
  skipNextSkillParsingRef.current = true;
4284
- saveMessagesOnEarlyReturn();
4289
+ saveMessagesOnEarlyReturn(imgFileParts);
4285
4290
  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.`;
4286
4291
  setTimeout(() => {
4287
4292
  sendMessage(imgFilePrompt, { hiddenUserMessage: true });