@gendive/chatllm 0.17.25 → 0.17.27

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.
@@ -2634,6 +2634,7 @@ ${finalContent}`;
2634
2634
  try {
2635
2635
  const shouldSkipSkillParsing = skipNextSkillParsingRef.current;
2636
2636
  skipNextSkillParsingRef.current = false;
2637
+ let accumulatedContent = "";
2637
2638
  let messagesToSend = [...existingMessages, userMessage];
2638
2639
  const recompressionThreshold = DEFAULT_RECOMPRESSION_THRESHOLD;
2639
2640
  const tokenLimit = DEFAULT_TOKEN_LIMIT;
@@ -2722,6 +2723,7 @@ ${attachmentContext}
2722
2723
  systemPrompt: combinedSystemPrompt
2723
2724
  });
2724
2725
  if (typeof result === "string") {
2726
+ accumulatedContent = result;
2725
2727
  setSessions(
2726
2728
  (prev) => prev.map((s) => {
2727
2729
  if (s.id === capturedSessionId) {
@@ -2735,9 +2737,8 @@ ${attachmentContext}
2735
2737
  return s;
2736
2738
  })
2737
2739
  );
2738
- return;
2739
- }
2740
- if (typeof result === "object" && "content" in result) {
2740
+ } else if (typeof result === "object" && "content" in result) {
2741
+ accumulatedContent = result.content;
2741
2742
  setSessions(
2742
2743
  (prev) => prev.map((s) => {
2743
2744
  if (s.id === capturedSessionId) {
@@ -2751,9 +2752,9 @@ ${attachmentContext}
2751
2752
  return s;
2752
2753
  })
2753
2754
  );
2754
- return;
2755
+ } else {
2756
+ response = new Response(result);
2755
2757
  }
2756
- response = new Response(result);
2757
2758
  } else {
2758
2759
  const isOllama = provider === "ollama" || apiEndpoint.includes("ollama") || apiEndpoint.includes("11434");
2759
2760
  const requestBody = isOllama ? { model: selectedModel, messages: messagesForApi, stream: true } : {
@@ -2770,104 +2771,105 @@ ${attachmentContext}
2770
2771
  signal: abortControllerRef.current.signal
2771
2772
  });
2772
2773
  }
2773
- if (!response.ok) throw new Error("API error");
2774
- const reader = response.body?.getReader();
2775
- if (!reader) throw new Error("No reader");
2776
- const decoder = new TextDecoder();
2777
- let buffer = "";
2778
- let accumulatedContent = "";
2779
- let skillTagDetected = false;
2780
- let checklistTagDetected = false;
2781
- while (true) {
2782
- const { done, value } = await reader.read();
2783
- if (done) break;
2784
- buffer += decoder.decode(value, { stream: true });
2785
- const lines = buffer.split("\n");
2786
- buffer = lines.pop() || "";
2787
- for (const line of lines) {
2788
- if (!line.trim()) continue;
2789
- let data = line;
2790
- if (line.startsWith("data: ")) {
2791
- data = line.slice(6);
2792
- if (data === "[DONE]") continue;
2774
+ if (response) {
2775
+ if (!response.ok) throw new Error("API error");
2776
+ const reader = response.body?.getReader();
2777
+ if (!reader) throw new Error("No reader");
2778
+ const decoder = new TextDecoder();
2779
+ let buffer = "";
2780
+ let skillTagDetected = false;
2781
+ let checklistTagDetected = false;
2782
+ while (true) {
2783
+ const { done, value } = await reader.read();
2784
+ if (done) break;
2785
+ buffer += decoder.decode(value, { stream: true });
2786
+ const lines = buffer.split("\n");
2787
+ buffer = lines.pop() || "";
2788
+ for (const line of lines) {
2789
+ if (!line.trim()) continue;
2790
+ let data = line;
2791
+ if (line.startsWith("data: ")) {
2792
+ data = line.slice(6);
2793
+ if (data === "[DONE]") continue;
2794
+ }
2795
+ try {
2796
+ const parsed = JSON.parse(data);
2797
+ const content2 = parsed.message?.content || parsed.content || parsed.text || "";
2798
+ const thinking = parsed.message?.thinking || "";
2799
+ if (content2 || thinking) {
2800
+ if (content2) accumulatedContent += content2;
2801
+ if (!shouldSkipSkillParsing && accumulatedContent.includes("</skill_use>")) {
2802
+ const endIdx = accumulatedContent.indexOf("</skill_use>");
2803
+ accumulatedContent = accumulatedContent.substring(0, endIdx + "</skill_use>".length);
2804
+ skillTagDetected = true;
2805
+ }
2806
+ if (!skipNextChecklistParsingRef.current && accumulatedContent.includes("</checklist>")) {
2807
+ const endIdx = accumulatedContent.indexOf("</checklist>");
2808
+ accumulatedContent = accumulatedContent.substring(0, endIdx + "</checklist>".length);
2809
+ checklistTagDetected = true;
2810
+ }
2811
+ const displayContent = skillTagDetected ? accumulatedContent : null;
2812
+ setSessions(
2813
+ (prev) => prev.map((s) => {
2814
+ if (s.id === capturedSessionId) {
2815
+ return {
2816
+ ...s,
2817
+ messages: s.messages.map((m) => {
2818
+ if (m.id !== assistantMessageId) return m;
2819
+ if (displayContent) {
2820
+ return { ...m, content: displayContent };
2821
+ }
2822
+ let newContent = m.content;
2823
+ if (thinking) {
2824
+ if (!newContent.includes("<thinking>")) {
2825
+ newContent = "<thinking>" + thinking;
2826
+ } else if (!newContent.includes("</thinking>")) {
2827
+ newContent += thinking;
2828
+ }
2829
+ }
2830
+ if (content2) {
2831
+ if (newContent.includes("<thinking>") && !newContent.includes("</thinking>")) {
2832
+ newContent += "</thinking>\n\n";
2833
+ }
2834
+ newContent += content2;
2835
+ }
2836
+ return { ...m, content: newContent };
2837
+ })
2838
+ };
2839
+ }
2840
+ return s;
2841
+ })
2842
+ );
2843
+ if (skillTagDetected || checklistTagDetected) break;
2844
+ }
2845
+ } catch {
2846
+ }
2793
2847
  }
2848
+ if (skillTagDetected || checklistTagDetected) break;
2849
+ }
2850
+ if (buffer.trim()) {
2794
2851
  try {
2795
- const parsed = JSON.parse(data);
2796
- const content2 = parsed.message?.content || parsed.content || parsed.text || "";
2797
- const thinking = parsed.message?.thinking || "";
2798
- if (content2 || thinking) {
2799
- if (content2) accumulatedContent += content2;
2800
- if (!shouldSkipSkillParsing && accumulatedContent.includes("</skill_use>")) {
2801
- const endIdx = accumulatedContent.indexOf("</skill_use>");
2802
- accumulatedContent = accumulatedContent.substring(0, endIdx + "</skill_use>".length);
2803
- skillTagDetected = true;
2804
- }
2805
- if (!skipNextChecklistParsingRef.current && accumulatedContent.includes("</checklist>")) {
2806
- const endIdx = accumulatedContent.indexOf("</checklist>");
2807
- accumulatedContent = accumulatedContent.substring(0, endIdx + "</checklist>".length);
2808
- checklistTagDetected = true;
2809
- }
2810
- const displayContent = skillTagDetected ? accumulatedContent : null;
2852
+ const parsed = JSON.parse(buffer);
2853
+ const content2 = parsed.message?.content || parsed.content || parsed.text;
2854
+ if (content2) {
2855
+ accumulatedContent += content2;
2811
2856
  setSessions(
2812
2857
  (prev) => prev.map((s) => {
2813
2858
  if (s.id === capturedSessionId) {
2814
2859
  return {
2815
2860
  ...s,
2816
- messages: s.messages.map((m) => {
2817
- if (m.id !== assistantMessageId) return m;
2818
- if (displayContent) {
2819
- return { ...m, content: displayContent };
2820
- }
2821
- let newContent = m.content;
2822
- if (thinking) {
2823
- if (!newContent.includes("<thinking>")) {
2824
- newContent = "<thinking>" + thinking;
2825
- } else if (!newContent.includes("</thinking>")) {
2826
- newContent += thinking;
2827
- }
2828
- }
2829
- if (content2) {
2830
- if (newContent.includes("<thinking>") && !newContent.includes("</thinking>")) {
2831
- newContent += "</thinking>\n\n";
2832
- }
2833
- newContent += content2;
2834
- }
2835
- return { ...m, content: newContent };
2836
- })
2861
+ messages: s.messages.map(
2862
+ (m) => m.id === assistantMessageId ? { ...m, content: m.content + content2 } : m
2863
+ )
2837
2864
  };
2838
2865
  }
2839
2866
  return s;
2840
2867
  })
2841
2868
  );
2842
- if (skillTagDetected || checklistTagDetected) break;
2843
2869
  }
2844
2870
  } catch {
2845
2871
  }
2846
2872
  }
2847
- if (skillTagDetected || checklistTagDetected) break;
2848
- }
2849
- if (buffer.trim()) {
2850
- try {
2851
- const parsed = JSON.parse(buffer);
2852
- const content2 = parsed.message?.content || parsed.content || parsed.text;
2853
- if (content2) {
2854
- accumulatedContent += content2;
2855
- setSessions(
2856
- (prev) => prev.map((s) => {
2857
- if (s.id === capturedSessionId) {
2858
- return {
2859
- ...s,
2860
- messages: s.messages.map(
2861
- (m) => m.id === assistantMessageId ? { ...m, content: m.content + content2 } : m
2862
- )
2863
- };
2864
- }
2865
- return s;
2866
- })
2867
- );
2868
- }
2869
- } catch {
2870
- }
2871
2873
  }
2872
2874
  const saveMessagesOnEarlyReturn = () => {
2873
2875
  if (!useExternalStorage || !capturedSessionId) return;
@@ -2891,7 +2893,26 @@ ${attachmentContext}
2891
2893
  };
2892
2894
  if (!shouldSkipSkillParsing) {
2893
2895
  const assistantContent = accumulatedContent;
2896
+ console.log("[useChatUI] Post-processing \u2014 accumulatedContent \uAE38\uC774:", assistantContent.length, ", skill_use \uD3EC\uD568:", assistantContent.includes("<skill_use"));
2894
2897
  const { skillCall: detectedSkill, cleanContent: skillCleanContent } = parseSkillCallFromContent(assistantContent);
2898
+ if (detectedSkill) {
2899
+ console.log("[useChatUI] \uC2A4\uD0AC \uAC10\uC9C0:", detectedSkill.name, ", resolvedSkills \uD0A4:", Object.keys(resolvedSkills));
2900
+ }
2901
+ if (detectedSkill && !resolvedSkills[detectedSkill.name]) {
2902
+ console.warn(`[useChatUI] \uC2A4\uD0AC "${detectedSkill.name}" \uAC10\uC9C0\uB418\uC5C8\uC73C\uB098 \uBBF8\uB4F1\uB85D. \uB4F1\uB85D\uB41C \uC2A4\uD0AC:`, Object.keys(resolvedSkills));
2903
+ setSessions(
2904
+ (prev) => prev.map((s) => {
2905
+ if (s.id !== capturedSessionId) return s;
2906
+ return {
2907
+ ...s,
2908
+ messages: s.messages.map((m) => {
2909
+ if (m.id !== assistantMessageId) return m;
2910
+ return { ...m, content: skillCleanContent };
2911
+ })
2912
+ };
2913
+ })
2914
+ );
2915
+ }
2895
2916
  if (detectedSkill && resolvedSkills[detectedSkill.name]) {
2896
2917
  setSessions(
2897
2918
  (prev) => prev.map((s) => {