@gendive/chatllm 0.15.2 → 0.15.4

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.
@@ -1330,6 +1330,7 @@ var useChatUI = (options) => {
1330
1330
  const [isSessionsLoading, setIsSessionsLoading] = useState4(false);
1331
1331
  const [isSessionLoading, setIsSessionLoading] = useState4(false);
1332
1332
  const [isDeepResearchMode, setIsDeepResearchMode] = useState4(false);
1333
+ const [attachments, setAttachments] = useState4([]);
1333
1334
  const [deepResearchProgress, setDeepResearchProgress] = useState4(
1334
1335
  null
1335
1336
  );
@@ -1834,6 +1835,30 @@ ${newConversation}
1834
1835
  const savePersonalization = useCallback4(() => {
1835
1836
  options.onPersonalizationSave?.(personalization);
1836
1837
  }, [options.onPersonalizationSave, personalization]);
1838
+ const addAttachments = useCallback4((files) => {
1839
+ const newAttachments = files.map((file) => {
1840
+ const isImage = file.type.startsWith("image/");
1841
+ return {
1842
+ id: generateId2("attach"),
1843
+ file,
1844
+ name: file.name,
1845
+ type: isImage ? "image" : "file",
1846
+ previewUrl: isImage ? URL.createObjectURL(file) : void 0,
1847
+ mimeType: file.type,
1848
+ size: file.size
1849
+ };
1850
+ });
1851
+ setAttachments((prev) => [...prev, ...newAttachments]);
1852
+ }, []);
1853
+ const removeAttachment = useCallback4((id) => {
1854
+ setAttachments((prev) => {
1855
+ const target = prev.find((a) => a.id === id);
1856
+ if (target?.previewUrl) {
1857
+ URL.revokeObjectURL(target.previewUrl);
1858
+ }
1859
+ return prev.filter((a) => a.id !== id);
1860
+ });
1861
+ }, []);
1837
1862
  const toggleDeepResearchMode = useCallback4(() => {
1838
1863
  setIsDeepResearchMode((prev) => !prev);
1839
1864
  }, []);
@@ -1888,12 +1913,28 @@ ${finalContent}`;
1888
1913
  }
1889
1914
  const actionPrompt = selectedAction?.systemPrompt;
1890
1915
  const isHidden = options2?.hiddenUserMessage ?? false;
1916
+ const currentAttachments = attachments;
1917
+ let userContentParts;
1918
+ if (currentAttachments.length > 0) {
1919
+ userContentParts = [];
1920
+ if (finalContent.trim()) {
1921
+ userContentParts.push({ type: "text", content: finalContent });
1922
+ }
1923
+ for (const att of currentAttachments) {
1924
+ if (att.type === "image" && att.previewUrl) {
1925
+ userContentParts.push({ type: "image", url: att.previewUrl, alt: att.name });
1926
+ } else {
1927
+ userContentParts.push({ type: "file", name: att.name, url: att.previewUrl || "", mimeType: att.mimeType, size: att.size });
1928
+ }
1929
+ }
1930
+ }
1891
1931
  const userMessage = {
1892
1932
  id: generateId2("msg"),
1893
1933
  role: "user",
1894
1934
  content: finalContent,
1895
1935
  timestamp: Date.now(),
1896
- ...isHidden && { hidden: true }
1936
+ ...isHidden && { hidden: true },
1937
+ ...userContentParts && { contentParts: userContentParts }
1897
1938
  };
1898
1939
  const assistantMessageId = generateId2("msg");
1899
1940
  const assistantMessage = {
@@ -1906,6 +1947,7 @@ ${finalContent}`;
1906
1947
  setInput("");
1907
1948
  setQuotedText(null);
1908
1949
  setSelectedAction(null);
1950
+ setAttachments([]);
1909
1951
  const capturedSessionId = sessionId;
1910
1952
  const currentSession2 = sessions.find((s) => s.id === capturedSessionId);
1911
1953
  const existingMessages = currentSession2?.messages || [];
@@ -2069,6 +2111,7 @@ ${currentContextSummary}` },
2069
2111
  const decoder = new TextDecoder();
2070
2112
  let buffer = "";
2071
2113
  let accumulatedContent = "";
2114
+ let skillTagDetected = false;
2072
2115
  while (true) {
2073
2116
  const { done, value } = await reader.read();
2074
2117
  if (done) break;
@@ -2088,6 +2131,12 @@ ${currentContextSummary}` },
2088
2131
  const thinking = parsed.message?.thinking || "";
2089
2132
  if (content2 || thinking) {
2090
2133
  if (content2) accumulatedContent += content2;
2134
+ if (!skipNextSkillParsingRef.current && accumulatedContent.includes("</skill_use>")) {
2135
+ const endIdx = accumulatedContent.indexOf("</skill_use>");
2136
+ accumulatedContent = accumulatedContent.substring(0, endIdx + "</skill_use>".length);
2137
+ skillTagDetected = true;
2138
+ }
2139
+ const displayContent = skillTagDetected ? accumulatedContent : null;
2091
2140
  setSessions(
2092
2141
  (prev) => prev.map((s) => {
2093
2142
  if (s.id === capturedSessionId) {
@@ -2095,6 +2144,9 @@ ${currentContextSummary}` },
2095
2144
  ...s,
2096
2145
  messages: s.messages.map((m) => {
2097
2146
  if (m.id !== assistantMessageId) return m;
2147
+ if (displayContent) {
2148
+ return { ...m, content: displayContent };
2149
+ }
2098
2150
  let newContent = m.content;
2099
2151
  if (thinking) {
2100
2152
  if (!newContent.includes("<thinking>")) {
@@ -2116,10 +2168,12 @@ ${currentContextSummary}` },
2116
2168
  return s;
2117
2169
  })
2118
2170
  );
2171
+ if (skillTagDetected) break;
2119
2172
  }
2120
2173
  } catch {
2121
2174
  }
2122
2175
  }
2176
+ if (skillTagDetected) break;
2123
2177
  }
2124
2178
  if (buffer.trim()) {
2125
2179
  try {
@@ -2246,8 +2300,15 @@ ${currentContextSummary}` },
2246
2300
  };
2247
2301
  })
2248
2302
  );
2303
+ if (resultType === "image" || resultType === "file") {
2304
+ setIsLoading(false);
2305
+ abortControllerRef.current = null;
2306
+ return;
2307
+ }
2249
2308
  skipNextSkillParsingRef.current = true;
2250
- const feedbackPrompt = resultType === "image" ? `\uB3C4\uAD6C "${toolName}": \uC774\uBBF8\uC9C0 \uC0DD\uC131 \uC644\uB8CC. \uC0AC\uC6A9\uC790\uC5D0\uAC8C \uACB0\uACFC\uB97C \uC124\uBA85\uD574\uC8FC\uC138\uC694. skill_use \uD0DC\uADF8\uB294 \uC0AC\uC6A9\uD558\uC9C0 \uB9C8\uC138\uC694.` : `\uB3C4\uAD6C "${toolName}" \uACB0\uACFC:
2309
+ const feedbackPrompt = resultType === "error" ? `\uB3C4\uAD6C "${toolName}" \uC2E4\uD589 \uC911 \uC624\uB958 \uBC1C\uC0DD: ${result.content}
2310
+
2311
+ \uC0AC\uC6A9\uC790\uC5D0\uAC8C \uC624\uB958\uB97C \uC548\uB0B4\uD574\uC8FC\uC138\uC694. skill_use \uD0DC\uADF8\uB294 \uC0AC\uC6A9\uD558\uC9C0 \uB9C8\uC138\uC694.` : `\uB3C4\uAD6C "${toolName}" \uACB0\uACFC:
2251
2312
 
2252
2313
  ${result.content}
2253
2314
 
@@ -2899,6 +2960,22 @@ ${currentSession.contextSummary}` },
2899
2960
  * @Todo vibecode - 사용자가 선택지 선택 완료 시 호출
2900
2961
  */
2901
2962
  handlePollSubmit,
2963
+ // Attachments
2964
+ /**
2965
+ * @description 현재 첨부된 파일 목록
2966
+ * @Todo vibecode - 입력창 파일 첨부 상태
2967
+ */
2968
+ attachments,
2969
+ /**
2970
+ * @description 파일 첨부 추가 핸들러
2971
+ * @Todo vibecode - File[] → ChatAttachment 변환
2972
+ */
2973
+ addAttachments,
2974
+ /**
2975
+ * @description 첨부 파일 제거 핸들러
2976
+ * @Todo vibecode - objectURL 해제 포함
2977
+ */
2978
+ removeAttachment,
2902
2979
  // Skills
2903
2980
  /**
2904
2981
  * @description 현재 실행 중인 스킬 상태
@@ -3663,7 +3740,7 @@ var ChatHeader = ({
3663
3740
 
3664
3741
  // src/react/components/ChatInput.tsx
3665
3742
  import React3, { useRef as useRef5, useEffect as useEffect4, useState as useState7 } from "react";
3666
- import { jsx as jsx4, jsxs as jsxs3 } from "react/jsx-runtime";
3743
+ import { Fragment as Fragment3, jsx as jsx4, jsxs as jsxs3 } from "react/jsx-runtime";
3667
3744
  var ChatInput = ({
3668
3745
  value,
3669
3746
  onChange,
@@ -3682,11 +3759,17 @@ var ChatInput = ({
3682
3759
  deepResearchEnabled,
3683
3760
  manualSkills = [],
3684
3761
  onSkillSelect,
3685
- activeSkillExecution
3762
+ activeSkillExecution,
3763
+ attachments = [],
3764
+ onFileAttach,
3765
+ onRemoveAttachment,
3766
+ acceptedFileTypes
3686
3767
  }) => {
3687
3768
  const [mainMenuOpen, setMainMenuOpen] = React3.useState(false);
3688
3769
  const textareaRef = useRef5(null);
3770
+ const fileInputRef = useRef5(null);
3689
3771
  const [actionMenuOpen, setActionMenuOpen] = useState7(false);
3772
+ const [isDragOver, setIsDragOver] = useState7(false);
3690
3773
  const mainMenuRef = useRef5(null);
3691
3774
  const actionMenuRef = useRef5(null);
3692
3775
  useEffect4(() => {
@@ -3711,6 +3794,38 @@ var ChatInput = ({
3711
3794
  document.removeEventListener("mousedown", handleClickOutside);
3712
3795
  };
3713
3796
  }, [mainMenuOpen, actionMenuOpen]);
3797
+ const handlePaste = (e) => {
3798
+ const files = Array.from(e.clipboardData.files);
3799
+ if (files.length > 0 && onFileAttach) {
3800
+ e.preventDefault();
3801
+ onFileAttach(files);
3802
+ }
3803
+ };
3804
+ const handleDrop = (e) => {
3805
+ e.preventDefault();
3806
+ setIsDragOver(false);
3807
+ const files = Array.from(e.dataTransfer.files);
3808
+ if (files.length > 0 && onFileAttach) {
3809
+ onFileAttach(files);
3810
+ }
3811
+ };
3812
+ const handleDragOver = (e) => {
3813
+ e.preventDefault();
3814
+ setIsDragOver(true);
3815
+ };
3816
+ const handleDragLeave = (e) => {
3817
+ e.preventDefault();
3818
+ setIsDragOver(false);
3819
+ };
3820
+ const handleFileSelect = (e) => {
3821
+ const files = Array.from(e.target.files || []);
3822
+ if (files.length > 0 && onFileAttach) {
3823
+ onFileAttach(files);
3824
+ }
3825
+ if (fileInputRef.current) {
3826
+ fileInputRef.current.value = "";
3827
+ }
3828
+ };
3714
3829
  const handleKeyDown = (e) => {
3715
3830
  if (e.key === "Enter" && !e.shiftKey) {
3716
3831
  e.preventDefault();
@@ -3879,371 +3994,464 @@ var ChatInput = ({
3879
3994
  }
3880
3995
  )
3881
3996
  ] }),
3882
- /* @__PURE__ */ jsxs3("div", { className: "chatllm-input-container", children: [
3883
- /* @__PURE__ */ jsx4(
3884
- "textarea",
3885
- {
3886
- ref: textareaRef,
3887
- value,
3888
- onChange: (e) => onChange(e.target.value),
3889
- onKeyDown: handleKeyDown,
3890
- placeholder,
3891
- rows: 1,
3892
- style: {
3893
- width: "100%",
3894
- minHeight: "60px",
3895
- maxHeight: "200px",
3896
- padding: "24px 32px 8px 32px",
3897
- backgroundColor: "transparent",
3898
- border: "none",
3899
- outline: "none",
3900
- fontSize: "16px",
3901
- lineHeight: "1.5",
3902
- resize: "none",
3903
- color: "var(--chatllm-text)"
3904
- }
3905
- }
3906
- ),
3907
- /* @__PURE__ */ jsxs3(
3908
- "div",
3909
- {
3910
- style: {
3911
- display: "flex",
3912
- alignItems: "center",
3913
- justifyContent: "space-between",
3914
- padding: "0 24px 20px 24px"
3915
- },
3916
- children: [
3917
- /* @__PURE__ */ jsxs3("div", { style: { display: "flex", alignItems: "center", gap: "4px" }, children: [
3918
- actions.length > 0 && /* @__PURE__ */ jsxs3("div", { ref: actionMenuRef, style: { position: "relative" }, children: [
3919
- /* @__PURE__ */ jsx4(
3920
- "button",
3921
- {
3922
- onClick: () => setActionMenuOpen(!actionMenuOpen),
3923
- style: iconButtonStyle,
3924
- title: "\uAE30\uB2A5 \uCD94\uAC00",
3925
- children: /* @__PURE__ */ jsx4(IconSvg, { name: "add-line", size: 22, color: "var(--chatllm-text-muted)" })
3926
- }
3927
- ),
3928
- actionMenuOpen && /* @__PURE__ */ jsx4(
3929
- "div",
3930
- {
3931
- style: {
3932
- position: "absolute",
3933
- bottom: "100%",
3934
- left: 0,
3935
- marginBottom: "8px",
3936
- backgroundColor: "var(--chatllm-content-bg)",
3937
- borderRadius: "16px",
3938
- boxShadow: "var(--chatllm-shadow-sheet)",
3939
- border: "1px solid var(--chatllm-border)",
3940
- padding: "8px",
3941
- minWidth: "220px",
3942
- zIndex: 100
3943
- },
3944
- children: actions.map((action) => /* @__PURE__ */ jsxs3(
3997
+ /* @__PURE__ */ jsx4(
3998
+ "input",
3999
+ {
4000
+ ref: fileInputRef,
4001
+ type: "file",
4002
+ multiple: true,
4003
+ accept: acceptedFileTypes?.join(",") || void 0,
4004
+ onChange: handleFileSelect,
4005
+ style: { display: "none" }
4006
+ }
4007
+ ),
4008
+ /* @__PURE__ */ jsxs3(
4009
+ "div",
4010
+ {
4011
+ className: "chatllm-input-container",
4012
+ onDrop: handleDrop,
4013
+ onDragOver: handleDragOver,
4014
+ onDragLeave: handleDragLeave,
4015
+ style: isDragOver ? { outline: "2px dashed var(--chatllm-primary)", outlineOffset: "-2px" } : void 0,
4016
+ children: [
4017
+ attachments.length > 0 && /* @__PURE__ */ jsx4(
4018
+ "div",
4019
+ {
4020
+ style: {
4021
+ display: "flex",
4022
+ gap: "8px",
4023
+ padding: "12px 24px 0 24px",
4024
+ flexWrap: "wrap"
4025
+ },
4026
+ children: attachments.map((att) => /* @__PURE__ */ jsxs3(
4027
+ "div",
4028
+ {
4029
+ style: {
4030
+ position: "relative",
4031
+ display: "flex",
4032
+ alignItems: "center",
4033
+ gap: "8px",
4034
+ padding: att.type === "image" ? "0" : "8px 12px",
4035
+ backgroundColor: "var(--chatllm-content-bg)",
4036
+ borderRadius: "12px",
4037
+ border: "1px solid var(--chatllm-border)",
4038
+ overflow: "hidden"
4039
+ },
4040
+ children: [
4041
+ att.type === "image" && att.previewUrl ? /* @__PURE__ */ jsx4(
4042
+ "img",
4043
+ {
4044
+ src: att.previewUrl,
4045
+ alt: att.name,
4046
+ style: {
4047
+ width: "64px",
4048
+ height: "64px",
4049
+ objectFit: "cover",
4050
+ borderRadius: "12px"
4051
+ }
4052
+ }
4053
+ ) : /* @__PURE__ */ jsxs3(Fragment3, { children: [
4054
+ /* @__PURE__ */ jsx4(IconSvg, { name: "file-text-line", size: 16, color: "var(--chatllm-text-muted)" }),
4055
+ /* @__PURE__ */ jsx4("span", { style: { fontSize: "13px", color: "var(--chatllm-text)", maxWidth: "120px", overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }, children: att.name })
4056
+ ] }),
4057
+ /* @__PURE__ */ jsx4(
3945
4058
  "button",
3946
4059
  {
3947
- onClick: () => handleActionSelect(action),
4060
+ onClick: () => onRemoveAttachment?.(att.id),
3948
4061
  style: {
3949
- width: "100%",
4062
+ position: "absolute",
4063
+ top: "2px",
4064
+ right: "2px",
4065
+ width: "20px",
4066
+ height: "20px",
3950
4067
  display: "flex",
3951
4068
  alignItems: "center",
3952
- gap: "12px",
3953
- padding: "12px",
3954
- backgroundColor: "transparent",
4069
+ justifyContent: "center",
4070
+ backgroundColor: "rgba(0,0,0,0.5)",
3955
4071
  border: "none",
3956
- borderRadius: "12px",
4072
+ borderRadius: "50%",
3957
4073
  cursor: "pointer",
3958
- textAlign: "left",
3959
- transition: "background-color 0.2s"
4074
+ padding: 0
3960
4075
  },
3961
- onMouseOver: (e) => {
3962
- e.currentTarget.style.backgroundColor = "var(--chatllm-bg-hover)";
4076
+ children: /* @__PURE__ */ jsx4(IconSvg, { name: "close-line", size: 12, color: "#fff" })
4077
+ }
4078
+ )
4079
+ ]
4080
+ },
4081
+ att.id
4082
+ ))
4083
+ }
4084
+ ),
4085
+ /* @__PURE__ */ jsx4(
4086
+ "textarea",
4087
+ {
4088
+ ref: textareaRef,
4089
+ value,
4090
+ onChange: (e) => onChange(e.target.value),
4091
+ onKeyDown: handleKeyDown,
4092
+ onPaste: handlePaste,
4093
+ placeholder,
4094
+ rows: 1,
4095
+ style: {
4096
+ width: "100%",
4097
+ minHeight: "60px",
4098
+ maxHeight: "200px",
4099
+ padding: "24px 32px 8px 32px",
4100
+ backgroundColor: "transparent",
4101
+ border: "none",
4102
+ outline: "none",
4103
+ fontSize: "16px",
4104
+ lineHeight: "1.5",
4105
+ resize: "none",
4106
+ color: "var(--chatllm-text)"
4107
+ }
4108
+ }
4109
+ ),
4110
+ /* @__PURE__ */ jsxs3(
4111
+ "div",
4112
+ {
4113
+ style: {
4114
+ display: "flex",
4115
+ alignItems: "center",
4116
+ justifyContent: "space-between",
4117
+ padding: "0 24px 20px 24px"
4118
+ },
4119
+ children: [
4120
+ /* @__PURE__ */ jsxs3("div", { style: { display: "flex", alignItems: "center", gap: "4px" }, children: [
4121
+ actions.length > 0 && /* @__PURE__ */ jsxs3("div", { ref: actionMenuRef, style: { position: "relative" }, children: [
4122
+ /* @__PURE__ */ jsx4(
4123
+ "button",
4124
+ {
4125
+ onClick: () => setActionMenuOpen(!actionMenuOpen),
4126
+ style: iconButtonStyle,
4127
+ title: "\uAE30\uB2A5 \uCD94\uAC00",
4128
+ children: /* @__PURE__ */ jsx4(IconSvg, { name: "add-line", size: 22, color: "var(--chatllm-text-muted)" })
4129
+ }
4130
+ ),
4131
+ actionMenuOpen && /* @__PURE__ */ jsx4(
4132
+ "div",
4133
+ {
4134
+ style: {
4135
+ position: "absolute",
4136
+ bottom: "100%",
4137
+ left: 0,
4138
+ marginBottom: "8px",
4139
+ backgroundColor: "var(--chatllm-content-bg)",
4140
+ borderRadius: "16px",
4141
+ boxShadow: "var(--chatllm-shadow-sheet)",
4142
+ border: "1px solid var(--chatllm-border)",
4143
+ padding: "8px",
4144
+ minWidth: "220px",
4145
+ zIndex: 100
4146
+ },
4147
+ children: actions.map((action) => /* @__PURE__ */ jsxs3(
4148
+ "button",
4149
+ {
4150
+ onClick: () => handleActionSelect(action),
4151
+ style: {
4152
+ width: "100%",
4153
+ display: "flex",
4154
+ alignItems: "center",
4155
+ gap: "12px",
4156
+ padding: "12px",
4157
+ backgroundColor: "transparent",
4158
+ border: "none",
4159
+ borderRadius: "12px",
4160
+ cursor: "pointer",
4161
+ textAlign: "left",
4162
+ transition: "background-color 0.2s"
4163
+ },
4164
+ onMouseOver: (e) => {
4165
+ e.currentTarget.style.backgroundColor = "var(--chatllm-bg-hover)";
4166
+ },
4167
+ onMouseOut: (e) => {
4168
+ e.currentTarget.style.backgroundColor = "transparent";
4169
+ },
4170
+ children: [
4171
+ /* @__PURE__ */ jsx4(
4172
+ "div",
4173
+ {
4174
+ style: {
4175
+ width: "36px",
4176
+ height: "36px",
4177
+ display: "flex",
4178
+ alignItems: "center",
4179
+ justifyContent: "center",
4180
+ backgroundColor: "var(--chatllm-primary-light)",
4181
+ borderRadius: "10px"
4182
+ },
4183
+ children: /* @__PURE__ */ jsx4(
4184
+ IconSvg,
4185
+ {
4186
+ name: action.icon === "search" ? "search-line" : action.icon === "image" ? "image-line" : action.icon === "code" ? "code-s-slash-line" : "file-text-line",
4187
+ size: 20,
4188
+ color: "var(--chatllm-primary)"
4189
+ }
4190
+ )
4191
+ }
4192
+ ),
4193
+ /* @__PURE__ */ jsxs3("div", { children: [
4194
+ /* @__PURE__ */ jsx4("div", { style: { fontSize: "14px", fontWeight: 600, color: "var(--chatllm-text)" }, children: action.label }),
4195
+ /* @__PURE__ */ jsx4("div", { style: { fontSize: "12px", color: "var(--chatllm-text-muted)" }, children: action.description })
4196
+ ] })
4197
+ ]
4198
+ },
4199
+ action.id
4200
+ ))
4201
+ }
4202
+ )
4203
+ ] }),
4204
+ /* @__PURE__ */ jsxs3("div", { ref: mainMenuRef, style: { position: "relative" }, children: [
4205
+ /* @__PURE__ */ jsx4(
4206
+ "button",
4207
+ {
4208
+ onClick: () => setMainMenuOpen(!mainMenuOpen),
4209
+ style: {
4210
+ ...iconButtonStyle,
4211
+ backgroundColor: mainMenuOpen ? "var(--chatllm-bg-hover)" : "transparent"
3963
4212
  },
3964
- onMouseOut: (e) => {
3965
- e.currentTarget.style.backgroundColor = "transparent";
4213
+ title: "\uBA54\uB274",
4214
+ children: /* @__PURE__ */ jsx4(IconSvg, { name: "add-line", size: 22, color: "var(--chatllm-text-muted)" })
4215
+ }
4216
+ ),
4217
+ mainMenuOpen && /* @__PURE__ */ jsxs3(
4218
+ "div",
4219
+ {
4220
+ style: {
4221
+ position: "absolute",
4222
+ bottom: "100%",
4223
+ left: 0,
4224
+ marginBottom: "8px",
4225
+ backgroundColor: "var(--chatllm-content-bg)",
4226
+ borderRadius: "16px",
4227
+ boxShadow: "var(--chatllm-shadow-sheet)",
4228
+ border: "1px solid var(--chatllm-border)",
4229
+ padding: "8px",
4230
+ minWidth: "240px",
4231
+ zIndex: 100
3966
4232
  },
3967
4233
  children: [
3968
- /* @__PURE__ */ jsx4(
3969
- "div",
4234
+ /* @__PURE__ */ jsxs3(
4235
+ "button",
3970
4236
  {
3971
4237
  style: {
3972
- width: "36px",
3973
- height: "36px",
4238
+ width: "100%",
3974
4239
  display: "flex",
3975
4240
  alignItems: "center",
3976
- justifyContent: "center",
3977
- backgroundColor: "var(--chatllm-primary-light)",
3978
- borderRadius: "10px"
4241
+ gap: "12px",
4242
+ padding: "12px",
4243
+ backgroundColor: "transparent",
4244
+ border: "none",
4245
+ borderRadius: "12px",
4246
+ cursor: "pointer",
4247
+ textAlign: "left",
4248
+ transition: "background-color 0.2s"
3979
4249
  },
3980
- children: /* @__PURE__ */ jsx4(
3981
- IconSvg,
3982
- {
3983
- name: action.icon === "search" ? "search-line" : action.icon === "image" ? "image-line" : action.icon === "code" ? "code-s-slash-line" : "file-text-line",
3984
- size: 20,
3985
- color: "var(--chatllm-primary)"
3986
- }
3987
- )
4250
+ onMouseOver: (e) => {
4251
+ e.currentTarget.style.backgroundColor = "var(--chatllm-bg-hover)";
4252
+ },
4253
+ onMouseOut: (e) => {
4254
+ e.currentTarget.style.backgroundColor = "transparent";
4255
+ },
4256
+ onClick: () => {
4257
+ fileInputRef.current?.click();
4258
+ setMainMenuOpen(false);
4259
+ },
4260
+ children: [
4261
+ /* @__PURE__ */ jsx4(IconSvg, { name: "attachment-line", size: 20, color: "var(--chatllm-text-secondary)" }),
4262
+ /* @__PURE__ */ jsx4("span", { style: { fontSize: "14px", color: "var(--chatllm-text)" }, children: "\uD30C\uC77C \uB610\uB294 \uC0AC\uC9C4 \uCD94\uAC00" })
4263
+ ]
4264
+ }
4265
+ ),
4266
+ deepResearchEnabled && /* @__PURE__ */ jsxs3(
4267
+ "button",
4268
+ {
4269
+ onClick: () => {
4270
+ onDeepResearch?.();
4271
+ setMainMenuOpen(false);
4272
+ },
4273
+ style: {
4274
+ width: "100%",
4275
+ display: "flex",
4276
+ alignItems: "center",
4277
+ gap: "12px",
4278
+ padding: "12px",
4279
+ backgroundColor: "transparent",
4280
+ border: "none",
4281
+ borderRadius: "12px",
4282
+ cursor: "pointer",
4283
+ textAlign: "left",
4284
+ transition: "background-color 0.2s"
4285
+ },
4286
+ onMouseOver: (e) => {
4287
+ e.currentTarget.style.backgroundColor = "var(--chatllm-bg-hover)";
4288
+ },
4289
+ onMouseOut: (e) => {
4290
+ e.currentTarget.style.backgroundColor = "transparent";
4291
+ },
4292
+ children: [
4293
+ /* @__PURE__ */ jsx4(
4294
+ IconSvg,
4295
+ {
4296
+ name: "search-eye-line",
4297
+ size: 20,
4298
+ color: isDeepResearchMode ? "var(--chatllm-primary)" : "var(--chatllm-text-secondary)"
4299
+ }
4300
+ ),
4301
+ /* @__PURE__ */ jsx4(
4302
+ "span",
4303
+ {
4304
+ style: {
4305
+ flex: 1,
4306
+ fontSize: "14px",
4307
+ color: isDeepResearchMode ? "var(--chatllm-primary)" : "var(--chatllm-text)"
4308
+ },
4309
+ children: "\uC5F0\uAD6C"
4310
+ }
4311
+ ),
4312
+ isDeepResearchMode && /* @__PURE__ */ jsx4(IconSvg, { name: "check-line", size: 16, color: "var(--chatllm-primary)" })
4313
+ ]
3988
4314
  }
3989
4315
  ),
3990
- /* @__PURE__ */ jsxs3("div", { children: [
3991
- /* @__PURE__ */ jsx4("div", { style: { fontSize: "14px", fontWeight: 600, color: "var(--chatllm-text)" }, children: action.label }),
3992
- /* @__PURE__ */ jsx4("div", { style: { fontSize: "12px", color: "var(--chatllm-text-muted)" }, children: action.description })
3993
- ] })
4316
+ manualSkills.map((skill) => /* @__PURE__ */ jsxs3(
4317
+ "button",
4318
+ {
4319
+ onClick: () => {
4320
+ onSkillSelect?.(skill.name);
4321
+ setMainMenuOpen(false);
4322
+ },
4323
+ disabled: skill.disabled,
4324
+ style: {
4325
+ width: "100%",
4326
+ display: "flex",
4327
+ alignItems: "center",
4328
+ gap: "12px",
4329
+ padding: "12px",
4330
+ backgroundColor: "transparent",
4331
+ border: "none",
4332
+ borderRadius: "12px",
4333
+ cursor: skill.disabled ? "not-allowed" : "pointer",
4334
+ textAlign: "left",
4335
+ transition: "background-color 0.2s",
4336
+ opacity: skill.disabled ? 0.5 : 1
4337
+ },
4338
+ onMouseOver: (e) => {
4339
+ if (!skill.disabled) {
4340
+ e.currentTarget.style.backgroundColor = "var(--chatllm-bg-hover)";
4341
+ }
4342
+ },
4343
+ onMouseOut: (e) => {
4344
+ e.currentTarget.style.backgroundColor = "transparent";
4345
+ },
4346
+ children: [
4347
+ /* @__PURE__ */ jsx4(
4348
+ "div",
4349
+ {
4350
+ style: {
4351
+ width: "36px",
4352
+ height: "36px",
4353
+ display: "flex",
4354
+ alignItems: "center",
4355
+ justifyContent: "center",
4356
+ backgroundColor: "var(--chatllm-primary-light)",
4357
+ borderRadius: "10px"
4358
+ },
4359
+ children: /* @__PURE__ */ jsx4(
4360
+ IconSvg,
4361
+ {
4362
+ name: mapSkillIcon(skill.icon),
4363
+ size: 20,
4364
+ color: "var(--chatllm-primary)"
4365
+ }
4366
+ )
4367
+ }
4368
+ ),
4369
+ /* @__PURE__ */ jsxs3("div", { children: [
4370
+ /* @__PURE__ */ jsx4("div", { style: { fontSize: "14px", fontWeight: 600, color: "var(--chatllm-text)" }, children: skill.label }),
4371
+ /* @__PURE__ */ jsx4("div", { style: { fontSize: "12px", color: "var(--chatllm-text-muted)", maxWidth: "180px", overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }, children: skill.description })
4372
+ ] })
4373
+ ]
4374
+ },
4375
+ skill.name
4376
+ ))
3994
4377
  ]
3995
- },
3996
- action.id
3997
- ))
3998
- }
3999
- )
4000
- ] }),
4001
- /* @__PURE__ */ jsxs3("div", { ref: mainMenuRef, style: { position: "relative" }, children: [
4002
- /* @__PURE__ */ jsx4(
4378
+ }
4379
+ )
4380
+ ] })
4381
+ ] }),
4382
+ isLoading ? /* @__PURE__ */ jsxs3(
4003
4383
  "button",
4004
4384
  {
4005
- onClick: () => setMainMenuOpen(!mainMenuOpen),
4006
- style: {
4007
- ...iconButtonStyle,
4008
- backgroundColor: mainMenuOpen ? "var(--chatllm-bg-hover)" : "transparent"
4009
- },
4010
- title: "\uBA54\uB274",
4011
- children: /* @__PURE__ */ jsx4(IconSvg, { name: "add-line", size: 22, color: "var(--chatllm-text-muted)" })
4012
- }
4013
- ),
4014
- mainMenuOpen && /* @__PURE__ */ jsxs3(
4015
- "div",
4016
- {
4385
+ onClick: onStop,
4017
4386
  style: {
4018
- position: "absolute",
4019
- bottom: "100%",
4020
- left: 0,
4021
- marginBottom: "8px",
4022
- backgroundColor: "var(--chatllm-content-bg)",
4023
- borderRadius: "16px",
4024
- boxShadow: "var(--chatllm-shadow-sheet)",
4387
+ display: "flex",
4388
+ alignItems: "center",
4389
+ justifyContent: "center",
4390
+ height: "48px",
4391
+ padding: "0 32px",
4392
+ backgroundColor: "var(--chatllm-bg-tertiary)",
4025
4393
  border: "1px solid var(--chatllm-border)",
4026
- padding: "8px",
4027
- minWidth: "240px",
4028
- zIndex: 100
4394
+ borderRadius: "12px",
4395
+ cursor: "pointer",
4396
+ transition: "all 0.2s",
4397
+ gap: "8px"
4029
4398
  },
4030
4399
  children: [
4031
- /* @__PURE__ */ jsxs3(
4032
- "button",
4400
+ /* @__PURE__ */ jsx4(
4401
+ "span",
4033
4402
  {
4034
4403
  style: {
4035
- width: "100%",
4036
- display: "flex",
4037
- alignItems: "center",
4038
- gap: "12px",
4039
- padding: "12px",
4040
- backgroundColor: "transparent",
4041
- border: "none",
4042
- borderRadius: "12px",
4043
- cursor: "pointer",
4044
- textAlign: "left",
4045
- transition: "background-color 0.2s"
4404
+ fontSize: "14px",
4405
+ fontWeight: 700,
4406
+ color: "var(--chatllm-text-secondary)",
4407
+ textTransform: "uppercase",
4408
+ letterSpacing: "0.02em"
4046
4409
  },
4047
- onMouseOver: (e) => {
4048
- e.currentTarget.style.backgroundColor = "var(--chatllm-bg-hover)";
4049
- },
4050
- onMouseOut: (e) => {
4051
- e.currentTarget.style.backgroundColor = "transparent";
4052
- },
4053
- onClick: () => setMainMenuOpen(false),
4054
- children: [
4055
- /* @__PURE__ */ jsx4(IconSvg, { name: "attachment-line", size: 20, color: "var(--chatllm-text-secondary)" }),
4056
- /* @__PURE__ */ jsx4("span", { style: { fontSize: "14px", color: "var(--chatllm-text)" }, children: "\uD30C\uC77C \uB610\uB294 \uC0AC\uC9C4 \uCD94\uAC00" })
4057
- ]
4410
+ children: "\uC911\uC9C0"
4058
4411
  }
4059
4412
  ),
4060
- deepResearchEnabled && /* @__PURE__ */ jsxs3(
4061
- "button",
4413
+ /* @__PURE__ */ jsx4(IconSvg, { name: "stop-circle-line", size: 18, color: "var(--chatllm-text-secondary)" })
4414
+ ]
4415
+ }
4416
+ ) : /* @__PURE__ */ jsxs3(
4417
+ "button",
4418
+ {
4419
+ onClick: onSubmit,
4420
+ disabled: !value.trim() && attachments.length === 0,
4421
+ className: "chatllm-btn-primary",
4422
+ style: {
4423
+ display: "flex",
4424
+ alignItems: "center",
4425
+ justifyContent: "center",
4426
+ height: "48px",
4427
+ padding: "0 32px",
4428
+ borderRadius: "12px",
4429
+ cursor: value.trim() || attachments.length > 0 ? "pointer" : "not-allowed",
4430
+ opacity: value.trim() || attachments.length > 0 ? 1 : 0.5,
4431
+ gap: "8px"
4432
+ },
4433
+ children: [
4434
+ /* @__PURE__ */ jsx4(
4435
+ "span",
4062
4436
  {
4063
- onClick: () => {
4064
- onDeepResearch?.();
4065
- setMainMenuOpen(false);
4066
- },
4067
4437
  style: {
4068
- width: "100%",
4069
- display: "flex",
4070
- alignItems: "center",
4071
- gap: "12px",
4072
- padding: "12px",
4073
- backgroundColor: "transparent",
4074
- border: "none",
4075
- borderRadius: "12px",
4076
- cursor: "pointer",
4077
- textAlign: "left",
4078
- transition: "background-color 0.2s"
4438
+ fontSize: "14px",
4439
+ fontWeight: 700,
4440
+ letterSpacing: "0.02em"
4079
4441
  },
4080
- onMouseOver: (e) => {
4081
- e.currentTarget.style.backgroundColor = "var(--chatllm-bg-hover)";
4082
- },
4083
- onMouseOut: (e) => {
4084
- e.currentTarget.style.backgroundColor = "transparent";
4085
- },
4086
- children: [
4087
- /* @__PURE__ */ jsx4(
4088
- IconSvg,
4089
- {
4090
- name: "search-eye-line",
4091
- size: 20,
4092
- color: isDeepResearchMode ? "var(--chatllm-primary)" : "var(--chatllm-text-secondary)"
4093
- }
4094
- ),
4095
- /* @__PURE__ */ jsx4(
4096
- "span",
4097
- {
4098
- style: {
4099
- flex: 1,
4100
- fontSize: "14px",
4101
- color: isDeepResearchMode ? "var(--chatllm-primary)" : "var(--chatllm-text)"
4102
- },
4103
- children: "\uC5F0\uAD6C"
4104
- }
4105
- ),
4106
- isDeepResearchMode && /* @__PURE__ */ jsx4(IconSvg, { name: "check-line", size: 16, color: "var(--chatllm-primary)" })
4107
- ]
4442
+ children: "\uBCF4\uB0B4\uAE30"
4108
4443
  }
4109
4444
  ),
4110
- manualSkills.map((skill) => /* @__PURE__ */ jsxs3(
4111
- "button",
4112
- {
4113
- onClick: () => {
4114
- onSkillSelect?.(skill.name);
4115
- setMainMenuOpen(false);
4116
- },
4117
- disabled: skill.disabled,
4118
- style: {
4119
- width: "100%",
4120
- display: "flex",
4121
- alignItems: "center",
4122
- gap: "12px",
4123
- padding: "12px",
4124
- backgroundColor: "transparent",
4125
- border: "none",
4126
- borderRadius: "12px",
4127
- cursor: skill.disabled ? "not-allowed" : "pointer",
4128
- textAlign: "left",
4129
- transition: "background-color 0.2s",
4130
- opacity: skill.disabled ? 0.5 : 1
4131
- },
4132
- onMouseOver: (e) => {
4133
- if (!skill.disabled) {
4134
- e.currentTarget.style.backgroundColor = "var(--chatllm-bg-hover)";
4135
- }
4136
- },
4137
- onMouseOut: (e) => {
4138
- e.currentTarget.style.backgroundColor = "transparent";
4139
- },
4140
- children: [
4141
- /* @__PURE__ */ jsx4(
4142
- "div",
4143
- {
4144
- style: {
4145
- width: "36px",
4146
- height: "36px",
4147
- display: "flex",
4148
- alignItems: "center",
4149
- justifyContent: "center",
4150
- backgroundColor: "var(--chatllm-primary-light)",
4151
- borderRadius: "10px"
4152
- },
4153
- children: /* @__PURE__ */ jsx4(
4154
- IconSvg,
4155
- {
4156
- name: mapSkillIcon(skill.icon),
4157
- size: 20,
4158
- color: "var(--chatllm-primary)"
4159
- }
4160
- )
4161
- }
4162
- ),
4163
- /* @__PURE__ */ jsxs3("div", { children: [
4164
- /* @__PURE__ */ jsx4("div", { style: { fontSize: "14px", fontWeight: 600, color: "var(--chatllm-text)" }, children: skill.label }),
4165
- /* @__PURE__ */ jsx4("div", { style: { fontSize: "12px", color: "var(--chatllm-text-muted)", maxWidth: "180px", overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }, children: skill.description })
4166
- ] })
4167
- ]
4168
- },
4169
- skill.name
4170
- ))
4445
+ /* @__PURE__ */ jsx4(IconSvg, { name: "arrow-up-s-line", size: 20, color: "#ffffff" })
4171
4446
  ]
4172
4447
  }
4173
4448
  )
4174
- ] })
4175
- ] }),
4176
- isLoading ? /* @__PURE__ */ jsxs3(
4177
- "button",
4178
- {
4179
- onClick: onStop,
4180
- style: {
4181
- display: "flex",
4182
- alignItems: "center",
4183
- justifyContent: "center",
4184
- height: "48px",
4185
- padding: "0 32px",
4186
- backgroundColor: "var(--chatllm-bg-tertiary)",
4187
- border: "1px solid var(--chatllm-border)",
4188
- borderRadius: "12px",
4189
- cursor: "pointer",
4190
- transition: "all 0.2s",
4191
- gap: "8px"
4192
- },
4193
- children: [
4194
- /* @__PURE__ */ jsx4(
4195
- "span",
4196
- {
4197
- style: {
4198
- fontSize: "14px",
4199
- fontWeight: 700,
4200
- color: "var(--chatllm-text-secondary)",
4201
- textTransform: "uppercase",
4202
- letterSpacing: "0.02em"
4203
- },
4204
- children: "\uC911\uC9C0"
4205
- }
4206
- ),
4207
- /* @__PURE__ */ jsx4(IconSvg, { name: "stop-circle-line", size: 18, color: "var(--chatllm-text-secondary)" })
4208
- ]
4209
- }
4210
- ) : /* @__PURE__ */ jsxs3(
4211
- "button",
4212
- {
4213
- onClick: onSubmit,
4214
- disabled: !value.trim(),
4215
- className: "chatllm-btn-primary",
4216
- style: {
4217
- display: "flex",
4218
- alignItems: "center",
4219
- justifyContent: "center",
4220
- height: "48px",
4221
- padding: "0 32px",
4222
- borderRadius: "12px",
4223
- cursor: value.trim() ? "pointer" : "not-allowed",
4224
- opacity: value.trim() ? 1 : 0.5,
4225
- gap: "8px"
4226
- },
4227
- children: [
4228
- /* @__PURE__ */ jsx4(
4229
- "span",
4230
- {
4231
- style: {
4232
- fontSize: "14px",
4233
- fontWeight: 700,
4234
- letterSpacing: "0.02em"
4235
- },
4236
- children: "\uBCF4\uB0B4\uAE30"
4237
- }
4238
- ),
4239
- /* @__PURE__ */ jsx4(IconSvg, { name: "arrow-up-s-line", size: 20, color: "#ffffff" })
4240
- ]
4241
- }
4242
- )
4243
- ]
4244
- }
4245
- )
4246
- ] })
4449
+ ]
4450
+ }
4451
+ )
4452
+ ]
4453
+ }
4454
+ )
4247
4455
  ]
4248
4456
  }
4249
4457
  )
@@ -4436,7 +4644,7 @@ var LinkChip = ({
4436
4644
  };
4437
4645
 
4438
4646
  // src/react/components/MarkdownRenderer.tsx
4439
- import { Fragment as Fragment3, jsx as jsx6, jsxs as jsxs5 } from "react/jsx-runtime";
4647
+ import { Fragment as Fragment4, jsx as jsx6, jsxs as jsxs5 } from "react/jsx-runtime";
4440
4648
  var IMAGE_REGEX = /!\[([^\]]*)\]\(([^)]+)\)/g;
4441
4649
  var LINK_REGEX = /(?<!!)\[([^\]]+)\]\(([^)]+)\)/g;
4442
4650
  var SOURCE_LINKS_REGEX = /(\*{0,2}출처:?\*{0,2}\s*)?((?:(?<!!)\[`?[^\]]+`?\]\([^)]+\)\s*)+)/gi;
@@ -5014,7 +5222,7 @@ var ImageWithCopyButton = ({ src, alt, imageKey }) => {
5014
5222
  onMouseOut: (e) => {
5015
5223
  e.currentTarget.style.backgroundColor = "transparent";
5016
5224
  },
5017
- children: /* @__PURE__ */ jsx6("svg", { width: "18", height: "18", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: copyState === "copied" ? /* @__PURE__ */ jsx6("polyline", { points: "20 6 9 17 4 12" }) : /* @__PURE__ */ jsxs5(Fragment3, { children: [
5225
+ children: /* @__PURE__ */ jsx6("svg", { width: "18", height: "18", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: copyState === "copied" ? /* @__PURE__ */ jsx6("polyline", { points: "20 6 9 17 4 12" }) : /* @__PURE__ */ jsxs5(Fragment4, { children: [
5018
5226
  /* @__PURE__ */ jsx6("rect", { x: "9", y: "9", width: "13", height: "13", rx: "2", ry: "2" }),
5019
5227
  /* @__PURE__ */ jsx6("path", { d: "M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1" })
5020
5228
  ] }) })
@@ -5812,7 +6020,7 @@ var DeepResearchProgressUI = ({ progress }) => {
5812
6020
 
5813
6021
  // src/react/components/PollCard.tsx
5814
6022
  import { useState as useState9, useCallback as useCallback5, useEffect as useEffect5 } from "react";
5815
- import { Fragment as Fragment4, jsx as jsx8, jsxs as jsxs7 } from "react/jsx-runtime";
6023
+ import { Fragment as Fragment5, jsx as jsx8, jsxs as jsxs7 } from "react/jsx-runtime";
5816
6024
  var stripMarkdown = (text) => text.replace(/\*\*(.+?)\*\*/g, "$1").replace(/__(.+?)__/g, "$1").replace(/\*(.+?)\*/g, "$1").replace(/_(.+?)_/g, "$1").replace(/`(.+?)`/g, "$1").replace(/~~(.+?)~~/g, "$1");
5817
6025
  var PollCard = ({
5818
6026
  questions,
@@ -6059,7 +6267,7 @@ var PollCard = ({
6059
6267
  option.id
6060
6268
  );
6061
6269
  }),
6062
- currentQuestion.allowOther !== false && /* @__PURE__ */ jsxs7(Fragment4, { children: [
6270
+ currentQuestion.allowOther !== false && /* @__PURE__ */ jsxs7(Fragment5, { children: [
6063
6271
  /* @__PURE__ */ jsxs7(
6064
6272
  "button",
6065
6273
  {
@@ -6299,7 +6507,7 @@ var SkillProgressUI = ({
6299
6507
 
6300
6508
  // src/react/components/ImageContentCard.tsx
6301
6509
  import { useState as useState10 } from "react";
6302
- import { Fragment as Fragment5, jsx as jsx10, jsxs as jsxs9 } from "react/jsx-runtime";
6510
+ import { Fragment as Fragment6, jsx as jsx10, jsxs as jsxs9 } from "react/jsx-runtime";
6303
6511
  var ImageContentCard = ({ part }) => {
6304
6512
  const [isExpanded, setIsExpanded] = useState10(false);
6305
6513
  const [isLoaded, setIsLoaded] = useState10(false);
@@ -6326,7 +6534,7 @@ var ImageContentCard = ({ part }) => {
6326
6534
  }
6327
6535
  );
6328
6536
  }
6329
- return /* @__PURE__ */ jsxs9(Fragment5, { children: [
6537
+ return /* @__PURE__ */ jsxs9(Fragment6, { children: [
6330
6538
  /* @__PURE__ */ jsxs9(
6331
6539
  "div",
6332
6540
  {
@@ -6713,7 +6921,62 @@ var MessageBubble = ({
6713
6921
  borderRadius: "16px",
6714
6922
  borderTopRightRadius: "4px"
6715
6923
  },
6716
- children: /* @__PURE__ */ jsx13(
6924
+ children: message.contentParts?.length ? /* @__PURE__ */ jsx13("div", { style: { display: "flex", flexDirection: "column", gap: "8px" }, children: message.contentParts.map((part, idx) => {
6925
+ if (part.type === "text") {
6926
+ return /* @__PURE__ */ jsx13(
6927
+ "div",
6928
+ {
6929
+ style: {
6930
+ fontSize: "14px",
6931
+ lineHeight: "1.5",
6932
+ color: "var(--chatllm-text)",
6933
+ whiteSpace: "pre-wrap"
6934
+ },
6935
+ children: part.content
6936
+ },
6937
+ idx
6938
+ );
6939
+ }
6940
+ if (part.type === "image") {
6941
+ return /* @__PURE__ */ jsx13(
6942
+ "img",
6943
+ {
6944
+ src: part.url,
6945
+ alt: part.alt || "\uCCA8\uBD80 \uC774\uBBF8\uC9C0",
6946
+ style: {
6947
+ maxWidth: "100%",
6948
+ maxHeight: "300px",
6949
+ borderRadius: "8px",
6950
+ objectFit: "contain"
6951
+ }
6952
+ },
6953
+ idx
6954
+ );
6955
+ }
6956
+ if (part.type === "file") {
6957
+ return /* @__PURE__ */ jsxs12(
6958
+ "div",
6959
+ {
6960
+ style: {
6961
+ display: "flex",
6962
+ alignItems: "center",
6963
+ gap: "8px",
6964
+ padding: "8px 12px",
6965
+ backgroundColor: "rgba(0,0,0,0.05)",
6966
+ borderRadius: "8px",
6967
+ fontSize: "13px",
6968
+ color: "var(--chatllm-text)"
6969
+ },
6970
+ children: [
6971
+ /* @__PURE__ */ jsx13(IconSvg, { name: "file-text-line", size: 16, color: "var(--chatllm-text-muted)" }),
6972
+ /* @__PURE__ */ jsx13("span", { style: { overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }, children: part.name })
6973
+ ]
6974
+ },
6975
+ idx
6976
+ );
6977
+ }
6978
+ return null;
6979
+ }) }) : /* @__PURE__ */ jsx13(
6717
6980
  "div",
6718
6981
  {
6719
6982
  style: {
@@ -8479,7 +8742,10 @@ var ChatUIView = ({
8479
8742
  compressionState,
8480
8743
  manualSkills,
8481
8744
  activeSkillExecution,
8482
- executeManualSkill
8745
+ executeManualSkill,
8746
+ attachments,
8747
+ addAttachments,
8748
+ removeAttachment
8483
8749
  } = state;
8484
8750
  const greeting = currentPersonalization.userProfile.nickname ? `\uC548\uB155\uD558\uC138\uC694, ${currentPersonalization.userProfile.nickname}\uB2D8` : "\uC548\uB155\uD558\uC138\uC694";
8485
8751
  const handleTemplateClick = (template) => {
@@ -8614,7 +8880,10 @@ var ChatUIView = ({
8614
8880
  deepResearchEnabled,
8615
8881
  manualSkills,
8616
8882
  onSkillSelect: executeManualSkill,
8617
- activeSkillExecution
8883
+ activeSkillExecution,
8884
+ attachments,
8885
+ onFileAttach: addAttachments,
8886
+ onRemoveAttachment: removeAttachment
8618
8887
  }
8619
8888
  )
8620
8889
  ]