@yushaw/sanqian-chat 0.2.30 → 0.2.33

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.
@@ -5991,7 +5991,7 @@ function createIpcAdapter() {
5991
5991
  onEvent({ ...event, stream_id: streamId });
5992
5992
  });
5993
5993
  try {
5994
- await api.stream({
5994
+ const streamPromise = api.stream({
5995
5995
  streamId,
5996
5996
  messages,
5997
5997
  conversationId,
@@ -5999,6 +5999,11 @@ function createIpcAdapter() {
5999
5999
  attachedResources: options?.attachedResources,
6000
6000
  sessionResources: options?.sessionResources
6001
6001
  });
6002
+ void streamPromise.catch((e) => {
6003
+ streamCallbacks.delete(streamId);
6004
+ const errorMessage = e instanceof Error ? e.message : "Stream error";
6005
+ onEvent({ type: "error", error: errorMessage, stream_id: streamId });
6006
+ });
6002
6007
  return {
6003
6008
  cancel: async () => {
6004
6009
  await api.cancelStream({ streamId });
@@ -7895,6 +7900,7 @@ var ChatInput = (0, import_react23.memo)(
7895
7900
  const textareaRef = (0, import_react23.useRef)(null);
7896
7901
  const submitInFlightRef = (0, import_react23.useRef)(false);
7897
7902
  const inputRevisionRef = (0, import_react23.useRef)(0);
7903
+ const buttonActionRef = (0, import_react23.useRef)(null);
7898
7904
  const canSend = (text.trim().length > 0 || allowEmptySubmit) && !disabled && !isLoading;
7899
7905
  const showStopButton = isStreaming && !!onStop;
7900
7906
  const showSpinner = isLoading && !showStopButton;
@@ -7943,6 +7949,28 @@ var ChatInput = (0, import_react23.memo)(
7943
7949
  },
7944
7950
  [text, canSend, onSend]
7945
7951
  );
7952
+ const handleActionPointerDown = (0, import_react23.useCallback)(
7953
+ (_e) => {
7954
+ buttonActionRef.current = showStopButton ? "stop" : "send";
7955
+ },
7956
+ [showStopButton]
7957
+ );
7958
+ const clearButtonAction = (0, import_react23.useCallback)(() => {
7959
+ buttonActionRef.current = null;
7960
+ }, []);
7961
+ const handleActionClick = (0, import_react23.useCallback)(
7962
+ (e) => {
7963
+ const action = buttonActionRef.current ?? (showStopButton ? "stop" : "send");
7964
+ buttonActionRef.current = null;
7965
+ if (action === "stop") {
7966
+ e.preventDefault();
7967
+ onStop?.();
7968
+ return;
7969
+ }
7970
+ void handleSubmit(e);
7971
+ },
7972
+ [showStopButton, onStop, handleSubmit]
7973
+ );
7946
7974
  const handleKeyDown = (0, import_react23.useCallback)(
7947
7975
  (e) => {
7948
7976
  if (e.key === "Enter" && !e.shiftKey && !e.nativeEvent.isComposing) {
@@ -8001,8 +8029,11 @@ var ChatInput = (0, import_react23.memo)(
8001
8029
  /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
8002
8030
  "button",
8003
8031
  {
8004
- type: showStopButton ? "button" : "submit",
8005
- onClick: showStopButton ? onStop : void 0,
8032
+ type: "button",
8033
+ onPointerDown: handleActionPointerDown,
8034
+ onPointerCancel: clearButtonAction,
8035
+ onBlur: clearButtonAction,
8036
+ onClick: handleActionClick,
8006
8037
  disabled: !showStopButton && !canSend,
8007
8038
  className: "chat-input-send-btn",
8008
8039
  "aria-label": showStopButton ? stopLabel : sendLabel,
@@ -8233,7 +8264,6 @@ var HitlCard = (0, import_react24.memo)(function HitlCard2({
8233
8264
  borderColor: "rgba(220, 38, 38, 0.45)",
8234
8265
  boxShadow: "0 0 0 2px rgba(220, 38, 38, 0.11)"
8235
8266
  } : void 0;
8236
- const requiredHintStyle = isDarkMode ? { color: "rgba(252, 165, 165, 0.92)" } : { color: "rgba(185, 28, 28, 0.84)" };
8237
8267
  return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(
8238
8268
  "div",
8239
8269
  {
@@ -8282,74 +8312,46 @@ var HitlCard = (0, import_react24.memo)(function HitlCard2({
8282
8312
  /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("code", { className: "text-[10px]", children: JSON.stringify(interrupt.args, null, 0) })
8283
8313
  ] })
8284
8314
  ] }),
8285
- isUserInput && interrupt.options && interrupt.options.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "space-y-1.5", children: [
8286
- interrupt.options.map((option, index) => {
8287
- const isSelected = selectedIndices.includes(index);
8288
- const optionStyle = isSelected ? isDarkMode ? { borderColor: "rgba(96, 165, 250, 0.75)", background: "rgba(59, 130, 246, 0.24)" } : { borderColor: "rgba(37, 99, 235, 0.36)", background: "rgba(239, 246, 255, 0.98)" } : isDarkMode ? { borderColor: "rgba(113, 113, 122, 0.6)", background: "rgba(9, 9, 11, 0.84)" } : { borderColor: "rgba(113, 113, 122, 0.34)", background: "rgba(250, 250, 250, 0.96)" };
8289
- return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(
8290
- "label",
8291
- {
8292
- className: `flex cursor-pointer items-center gap-2 rounded p-2 transition-colors ${isSelected ? isDarkMode ? "border-blue-500/50 bg-blue-500/20" : "border-blue-200 bg-blue-50" : `${inputBg} border-transparent hover:border-zinc-300`} border`,
8293
- style: optionStyle,
8294
- children: [
8295
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
8296
- "input",
8297
- {
8298
- type: interrupt.multi_select ? "checkbox" : "radio",
8299
- name: "hitl-options",
8300
- checked: isSelected,
8301
- onChange: () => handleOptionToggle(index),
8302
- style: optionControlStyle
8303
- }
8304
- ),
8305
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { className: `text-sm ${textPrimary} break-words ${isSelected ? "font-semibold" : "font-medium"}`, children: option })
8306
- ]
8307
- },
8308
- index
8309
- );
8310
- }),
8311
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: "min-h-[18px]", children: /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(
8312
- "div",
8313
- {
8314
- className: `flex items-center gap-1 text-xs transition-all duration-150 ${showRequiredError ? "translate-y-0 opacity-100" : "-translate-y-1 opacity-0"}`,
8315
- style: requiredHintStyle,
8316
- "aria-live": "polite",
8317
- children: [
8318
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { className: "inline-block h-1.5 w-1.5 rounded-full bg-current opacity-75" }),
8319
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { children: t.requiredField })
8320
- ]
8321
- }
8322
- ) })
8323
- ] }),
8324
- isUserInput && (!interrupt.options || interrupt.options.length === 0) && /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { children: [
8325
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
8326
- "input",
8315
+ isUserInput && interrupt.options && interrupt.options.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: "space-y-1.5", children: interrupt.options.map((option, index) => {
8316
+ const isSelected = selectedIndices.includes(index);
8317
+ const optionStyle = isSelected ? isDarkMode ? { borderColor: "rgba(96, 165, 250, 0.75)", background: "rgba(59, 130, 246, 0.24)" } : { borderColor: "rgba(37, 99, 235, 0.36)", background: "rgba(239, 246, 255, 0.98)" } : isDarkMode ? { borderColor: "rgba(113, 113, 122, 0.6)", background: "rgba(9, 9, 11, 0.84)" } : { borderColor: "rgba(113, 113, 122, 0.34)", background: "rgba(250, 250, 250, 0.96)" };
8318
+ return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(
8319
+ "label",
8327
8320
  {
8328
- ref: inputRef,
8329
- type: "text",
8330
- value: answer,
8331
- onChange: (e) => handleAnswerChange(e.target.value),
8332
- onKeyDown: handleKeyDown,
8333
- onCompositionStart: () => setIsComposing(true),
8334
- onCompositionEnd: () => setIsComposing(false),
8335
- placeholder: interrupt.default ? `${t.defaultPrefix}: ${interrupt.default}` : t.enterResponse,
8336
- className: `w-full rounded-lg border px-3 py-2 text-sm ${inputBorder} ${inputBg} ${textPrimary} placeholder:${textSecondary} ${showRequiredError ? "focus:border-red-400 focus:ring-red-400/25" : "focus:border-blue-500 focus:ring-blue-500/40"} focus:outline-none focus:ring-2`,
8337
- style: inputValidationStyle
8338
- }
8339
- ),
8340
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: "mt-1 min-h-[18px]", children: /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(
8341
- "div",
8342
- {
8343
- className: `flex items-center gap-1 text-xs transition-all duration-150 ${showRequiredError ? "translate-y-0 opacity-100" : "-translate-y-1 opacity-0"}`,
8344
- style: requiredHintStyle,
8345
- "aria-live": "polite",
8321
+ className: `flex cursor-pointer items-center gap-2 rounded p-2 transition-colors ${isSelected ? isDarkMode ? "border-blue-500/50 bg-blue-500/20" : "border-blue-200 bg-blue-50" : `${inputBg} border-transparent hover:border-zinc-300`} border`,
8322
+ style: optionStyle,
8346
8323
  children: [
8347
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { className: "inline-block h-1.5 w-1.5 rounded-full bg-current opacity-75" }),
8348
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { children: t.requiredField })
8324
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
8325
+ "input",
8326
+ {
8327
+ type: interrupt.multi_select ? "checkbox" : "radio",
8328
+ name: "hitl-options",
8329
+ checked: isSelected,
8330
+ onChange: () => handleOptionToggle(index),
8331
+ style: optionControlStyle
8332
+ }
8333
+ ),
8334
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { className: `text-sm ${textPrimary} break-words ${isSelected ? "font-semibold" : "font-medium"}`, children: option })
8349
8335
  ]
8350
- }
8351
- ) })
8352
- ] }),
8336
+ },
8337
+ index
8338
+ );
8339
+ }) }),
8340
+ isUserInput && (!interrupt.options || interrupt.options.length === 0) && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
8341
+ "input",
8342
+ {
8343
+ ref: inputRef,
8344
+ type: "text",
8345
+ value: answer,
8346
+ onChange: (e) => handleAnswerChange(e.target.value),
8347
+ onKeyDown: handleKeyDown,
8348
+ onCompositionStart: () => setIsComposing(true),
8349
+ onCompositionEnd: () => setIsComposing(false),
8350
+ placeholder: interrupt.default ? `${t.defaultPrefix}: ${interrupt.default}` : t.enterResponse,
8351
+ className: `w-full rounded-lg border px-3 py-2 text-sm ${inputBorder} ${inputBg} ${textPrimary} placeholder:${textSecondary} ${showRequiredError ? "focus:border-red-400 focus:ring-red-400/25" : "focus:border-blue-500 focus:ring-blue-500/40"} focus:outline-none focus:ring-2`,
8352
+ style: inputValidationStyle
8353
+ }
8354
+ ) }),
8353
8355
  isApproval && /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(
8354
8356
  "label",
8355
8357
  {
@@ -5903,7 +5903,7 @@ function createIpcAdapter() {
5903
5903
  onEvent({ ...event, stream_id: streamId });
5904
5904
  });
5905
5905
  try {
5906
- await api.stream({
5906
+ const streamPromise = api.stream({
5907
5907
  streamId,
5908
5908
  messages,
5909
5909
  conversationId,
@@ -5911,6 +5911,11 @@ function createIpcAdapter() {
5911
5911
  attachedResources: options?.attachedResources,
5912
5912
  sessionResources: options?.sessionResources
5913
5913
  });
5914
+ void streamPromise.catch((e) => {
5915
+ streamCallbacks.delete(streamId);
5916
+ const errorMessage = e instanceof Error ? e.message : "Stream error";
5917
+ onEvent({ type: "error", error: errorMessage, stream_id: streamId });
5918
+ });
5914
5919
  return {
5915
5920
  cancel: async () => {
5916
5921
  await api.cancelStream({ streamId });
@@ -7823,6 +7828,7 @@ var ChatInput = memo7(
7823
7828
  const textareaRef = useRef9(null);
7824
7829
  const submitInFlightRef = useRef9(false);
7825
7830
  const inputRevisionRef = useRef9(0);
7831
+ const buttonActionRef = useRef9(null);
7826
7832
  const canSend = (text.trim().length > 0 || allowEmptySubmit) && !disabled && !isLoading;
7827
7833
  const showStopButton = isStreaming && !!onStop;
7828
7834
  const showSpinner = isLoading && !showStopButton;
@@ -7871,6 +7877,28 @@ var ChatInput = memo7(
7871
7877
  },
7872
7878
  [text, canSend, onSend]
7873
7879
  );
7880
+ const handleActionPointerDown = useCallback14(
7881
+ (_e) => {
7882
+ buttonActionRef.current = showStopButton ? "stop" : "send";
7883
+ },
7884
+ [showStopButton]
7885
+ );
7886
+ const clearButtonAction = useCallback14(() => {
7887
+ buttonActionRef.current = null;
7888
+ }, []);
7889
+ const handleActionClick = useCallback14(
7890
+ (e) => {
7891
+ const action = buttonActionRef.current ?? (showStopButton ? "stop" : "send");
7892
+ buttonActionRef.current = null;
7893
+ if (action === "stop") {
7894
+ e.preventDefault();
7895
+ onStop?.();
7896
+ return;
7897
+ }
7898
+ void handleSubmit(e);
7899
+ },
7900
+ [showStopButton, onStop, handleSubmit]
7901
+ );
7874
7902
  const handleKeyDown = useCallback14(
7875
7903
  (e) => {
7876
7904
  if (e.key === "Enter" && !e.shiftKey && !e.nativeEvent.isComposing) {
@@ -7929,8 +7957,11 @@ var ChatInput = memo7(
7929
7957
  /* @__PURE__ */ jsx11(
7930
7958
  "button",
7931
7959
  {
7932
- type: showStopButton ? "button" : "submit",
7933
- onClick: showStopButton ? onStop : void 0,
7960
+ type: "button",
7961
+ onPointerDown: handleActionPointerDown,
7962
+ onPointerCancel: clearButtonAction,
7963
+ onBlur: clearButtonAction,
7964
+ onClick: handleActionClick,
7934
7965
  disabled: !showStopButton && !canSend,
7935
7966
  className: "chat-input-send-btn",
7936
7967
  "aria-label": showStopButton ? stopLabel : sendLabel,
@@ -8161,7 +8192,6 @@ var HitlCard = memo8(function HitlCard2({
8161
8192
  borderColor: "rgba(220, 38, 38, 0.45)",
8162
8193
  boxShadow: "0 0 0 2px rgba(220, 38, 38, 0.11)"
8163
8194
  } : void 0;
8164
- const requiredHintStyle = isDarkMode ? { color: "rgba(252, 165, 165, 0.92)" } : { color: "rgba(185, 28, 28, 0.84)" };
8165
8195
  return /* @__PURE__ */ jsxs6(
8166
8196
  "div",
8167
8197
  {
@@ -8210,74 +8240,46 @@ var HitlCard = memo8(function HitlCard2({
8210
8240
  /* @__PURE__ */ jsx12("code", { className: "text-[10px]", children: JSON.stringify(interrupt.args, null, 0) })
8211
8241
  ] })
8212
8242
  ] }),
8213
- isUserInput && interrupt.options && interrupt.options.length > 0 && /* @__PURE__ */ jsxs6("div", { className: "space-y-1.5", children: [
8214
- interrupt.options.map((option, index) => {
8215
- const isSelected = selectedIndices.includes(index);
8216
- const optionStyle = isSelected ? isDarkMode ? { borderColor: "rgba(96, 165, 250, 0.75)", background: "rgba(59, 130, 246, 0.24)" } : { borderColor: "rgba(37, 99, 235, 0.36)", background: "rgba(239, 246, 255, 0.98)" } : isDarkMode ? { borderColor: "rgba(113, 113, 122, 0.6)", background: "rgba(9, 9, 11, 0.84)" } : { borderColor: "rgba(113, 113, 122, 0.34)", background: "rgba(250, 250, 250, 0.96)" };
8217
- return /* @__PURE__ */ jsxs6(
8218
- "label",
8219
- {
8220
- className: `flex cursor-pointer items-center gap-2 rounded p-2 transition-colors ${isSelected ? isDarkMode ? "border-blue-500/50 bg-blue-500/20" : "border-blue-200 bg-blue-50" : `${inputBg} border-transparent hover:border-zinc-300`} border`,
8221
- style: optionStyle,
8222
- children: [
8223
- /* @__PURE__ */ jsx12(
8224
- "input",
8225
- {
8226
- type: interrupt.multi_select ? "checkbox" : "radio",
8227
- name: "hitl-options",
8228
- checked: isSelected,
8229
- onChange: () => handleOptionToggle(index),
8230
- style: optionControlStyle
8231
- }
8232
- ),
8233
- /* @__PURE__ */ jsx12("span", { className: `text-sm ${textPrimary} break-words ${isSelected ? "font-semibold" : "font-medium"}`, children: option })
8234
- ]
8235
- },
8236
- index
8237
- );
8238
- }),
8239
- /* @__PURE__ */ jsx12("div", { className: "min-h-[18px]", children: /* @__PURE__ */ jsxs6(
8240
- "div",
8241
- {
8242
- className: `flex items-center gap-1 text-xs transition-all duration-150 ${showRequiredError ? "translate-y-0 opacity-100" : "-translate-y-1 opacity-0"}`,
8243
- style: requiredHintStyle,
8244
- "aria-live": "polite",
8245
- children: [
8246
- /* @__PURE__ */ jsx12("span", { className: "inline-block h-1.5 w-1.5 rounded-full bg-current opacity-75" }),
8247
- /* @__PURE__ */ jsx12("span", { children: t.requiredField })
8248
- ]
8249
- }
8250
- ) })
8251
- ] }),
8252
- isUserInput && (!interrupt.options || interrupt.options.length === 0) && /* @__PURE__ */ jsxs6("div", { children: [
8253
- /* @__PURE__ */ jsx12(
8254
- "input",
8243
+ isUserInput && interrupt.options && interrupt.options.length > 0 && /* @__PURE__ */ jsx12("div", { className: "space-y-1.5", children: interrupt.options.map((option, index) => {
8244
+ const isSelected = selectedIndices.includes(index);
8245
+ const optionStyle = isSelected ? isDarkMode ? { borderColor: "rgba(96, 165, 250, 0.75)", background: "rgba(59, 130, 246, 0.24)" } : { borderColor: "rgba(37, 99, 235, 0.36)", background: "rgba(239, 246, 255, 0.98)" } : isDarkMode ? { borderColor: "rgba(113, 113, 122, 0.6)", background: "rgba(9, 9, 11, 0.84)" } : { borderColor: "rgba(113, 113, 122, 0.34)", background: "rgba(250, 250, 250, 0.96)" };
8246
+ return /* @__PURE__ */ jsxs6(
8247
+ "label",
8255
8248
  {
8256
- ref: inputRef,
8257
- type: "text",
8258
- value: answer,
8259
- onChange: (e) => handleAnswerChange(e.target.value),
8260
- onKeyDown: handleKeyDown,
8261
- onCompositionStart: () => setIsComposing(true),
8262
- onCompositionEnd: () => setIsComposing(false),
8263
- placeholder: interrupt.default ? `${t.defaultPrefix}: ${interrupt.default}` : t.enterResponse,
8264
- className: `w-full rounded-lg border px-3 py-2 text-sm ${inputBorder} ${inputBg} ${textPrimary} placeholder:${textSecondary} ${showRequiredError ? "focus:border-red-400 focus:ring-red-400/25" : "focus:border-blue-500 focus:ring-blue-500/40"} focus:outline-none focus:ring-2`,
8265
- style: inputValidationStyle
8266
- }
8267
- ),
8268
- /* @__PURE__ */ jsx12("div", { className: "mt-1 min-h-[18px]", children: /* @__PURE__ */ jsxs6(
8269
- "div",
8270
- {
8271
- className: `flex items-center gap-1 text-xs transition-all duration-150 ${showRequiredError ? "translate-y-0 opacity-100" : "-translate-y-1 opacity-0"}`,
8272
- style: requiredHintStyle,
8273
- "aria-live": "polite",
8249
+ className: `flex cursor-pointer items-center gap-2 rounded p-2 transition-colors ${isSelected ? isDarkMode ? "border-blue-500/50 bg-blue-500/20" : "border-blue-200 bg-blue-50" : `${inputBg} border-transparent hover:border-zinc-300`} border`,
8250
+ style: optionStyle,
8274
8251
  children: [
8275
- /* @__PURE__ */ jsx12("span", { className: "inline-block h-1.5 w-1.5 rounded-full bg-current opacity-75" }),
8276
- /* @__PURE__ */ jsx12("span", { children: t.requiredField })
8252
+ /* @__PURE__ */ jsx12(
8253
+ "input",
8254
+ {
8255
+ type: interrupt.multi_select ? "checkbox" : "radio",
8256
+ name: "hitl-options",
8257
+ checked: isSelected,
8258
+ onChange: () => handleOptionToggle(index),
8259
+ style: optionControlStyle
8260
+ }
8261
+ ),
8262
+ /* @__PURE__ */ jsx12("span", { className: `text-sm ${textPrimary} break-words ${isSelected ? "font-semibold" : "font-medium"}`, children: option })
8277
8263
  ]
8278
- }
8279
- ) })
8280
- ] }),
8264
+ },
8265
+ index
8266
+ );
8267
+ }) }),
8268
+ isUserInput && (!interrupt.options || interrupt.options.length === 0) && /* @__PURE__ */ jsx12("div", { children: /* @__PURE__ */ jsx12(
8269
+ "input",
8270
+ {
8271
+ ref: inputRef,
8272
+ type: "text",
8273
+ value: answer,
8274
+ onChange: (e) => handleAnswerChange(e.target.value),
8275
+ onKeyDown: handleKeyDown,
8276
+ onCompositionStart: () => setIsComposing(true),
8277
+ onCompositionEnd: () => setIsComposing(false),
8278
+ placeholder: interrupt.default ? `${t.defaultPrefix}: ${interrupt.default}` : t.enterResponse,
8279
+ className: `w-full rounded-lg border px-3 py-2 text-sm ${inputBorder} ${inputBg} ${textPrimary} placeholder:${textSecondary} ${showRequiredError ? "focus:border-red-400 focus:ring-red-400/25" : "focus:border-blue-500 focus:ring-blue-500/40"} focus:outline-none focus:ring-2`,
8280
+ style: inputValidationStyle
8281
+ }
8282
+ ) }),
8281
8283
  isApproval && /* @__PURE__ */ jsxs6(
8282
8284
  "label",
8283
8285
  {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@yushaw/sanqian-chat",
3
- "version": "0.2.30",
3
+ "version": "0.2.33",
4
4
  "description": "Floating chat window SDK for Sanqian AI Assistant",
5
5
  "main": "./dist/main/index.js",
6
6
  "types": "./dist/main/index.d.ts",