@helpai/elements 0.61.2 → 0.61.3

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.
package/index.mjs CHANGED
@@ -29,7 +29,7 @@ var BRAND = {
29
29
  };
30
30
 
31
31
  // src/core/version.ts
32
- var ELEMENTS_VERSION = true ? "0.61.2" : "0.0.0-dev";
32
+ var ELEMENTS_VERSION = true ? "0.61.3" : "0.0.0-dev";
33
33
  var ELEMENTS_VERSION_PARAM = "_ev";
34
34
 
35
35
  // src/i18n/strings.ts
@@ -6973,7 +6973,7 @@ function PanelContent(props2) {
6973
6973
  composerArea = null;
6974
6974
  } else if (canSend) {
6975
6975
  composerArea = /* @__PURE__ */ jsxs18(Fragment5, { children: [
6976
- /* @__PURE__ */ jsx23(Suggestions, { suggestions, onPick: onSuggestion }),
6976
+ !isStreaming && /* @__PURE__ */ jsx23(Suggestions, { suggestions, onPick: onSuggestion }),
6977
6977
  /* @__PURE__ */ jsx23(
6978
6978
  Composer,
6979
6979
  {
@@ -8240,6 +8240,7 @@ function App({ options, hostElement, bus }) {
8240
8240
  const markActiveConversationReadRef = useRef9(null);
8241
8241
  const markReadTimerRef = useRef9();
8242
8242
  useEffect16(() => () => clearTimeout(markReadTimerRef.current), []);
8243
+ const unreadIdsRef = useRef9(/* @__PURE__ */ new Set());
8243
8244
  useEffect16(() => {
8244
8245
  if (!conversationReady || homeNavSeeded.current) return;
8245
8246
  homeNavSeeded.current = true;
@@ -8439,18 +8440,11 @@ function App({ options, hostElement, bus }) {
8439
8440
  useEffect16(() => {
8440
8441
  if (effectiveLocale !== activeLocale) setActiveLocale(effectiveLocale);
8441
8442
  }, [effectiveLocale, activeLocale]);
8442
- const pendingSuggestionsRef = useRef9(null);
8443
8443
  const captureSuggestions = useCallback6((chunk) => {
8444
8444
  if (chunk.type !== "data-suggestions") return false;
8445
- pendingSuggestionsRef.current = parseSuggestions(chunk.data);
8445
+ setSuggestions(parseSuggestions(chunk.data));
8446
8446
  return true;
8447
8447
  }, []);
8448
- const flushSuggestions = useCallback6(() => {
8449
- if (pendingSuggestionsRef.current) {
8450
- setSuggestions(pendingSuggestionsRef.current);
8451
- pendingSuggestionsRef.current = null;
8452
- }
8453
- }, []);
8454
8448
  const adoptConversationRebind = useCallback6(
8455
8449
  (chunk) => {
8456
8450
  if (chunk.type !== "data-conversation-rebind") return false;
@@ -8470,7 +8464,6 @@ function App({ options, hostElement, bus }) {
8470
8464
  const runResume = useCallback6(
8471
8465
  async (handle) => {
8472
8466
  let bubble = null;
8473
- pendingSuggestionsRef.current = null;
8474
8467
  try {
8475
8468
  for await (const evt of handle.iter) {
8476
8469
  if (adoptConversationRebind(evt.chunk) || captureSuggestions(evt.chunk)) continue;
@@ -8499,7 +8492,6 @@ function App({ options, hostElement, bus }) {
8499
8492
  bubble.status = "complete";
8500
8493
  feedback.play("messageReceived");
8501
8494
  emitMessage(bus, options, "assistant", assistantText(bubble));
8502
- flushSuggestions();
8503
8495
  }
8504
8496
  }
8505
8497
  } catch (err) {
@@ -8639,7 +8631,6 @@ function App({ options, hostElement, bus }) {
8639
8631
  userPrefs: persistence.loadUserPrefs()
8640
8632
  });
8641
8633
  setStreaming(true);
8642
- pendingSuggestionsRef.current = null;
8643
8634
  const handle = transport.sendMessage(body);
8644
8635
  setActiveCancel(() => handle.cancel);
8645
8636
  setActiveDetach(() => handle.detach);
@@ -8664,7 +8655,6 @@ function App({ options, hostElement, bus }) {
8664
8655
  assistantMsg.status = "complete";
8665
8656
  feedback.play("messageReceived");
8666
8657
  emitMessage(bus, options, "assistant", assistantText(assistantMsg));
8667
- flushSuggestions();
8668
8658
  }
8669
8659
  } catch (error) {
8670
8660
  if (isAbortError(error)) {
@@ -8913,22 +8903,34 @@ function App({ options, hostElement, bus }) {
8913
8903
  bus.emit("close", void 0);
8914
8904
  options.onClose?.();
8915
8905
  }, [bus, options, persistence, panelSize, forms]);
8906
+ const recomputeUnread = useCallback6(() => {
8907
+ const onScreenConversationId = isChatActive() ? conversationIdSig.value : void 0;
8908
+ hasUnreadSig.value = [...unreadIdsRef.current].some((id) => id !== onScreenConversationId);
8909
+ }, [hasUnreadSig, conversationIdSig]);
8916
8910
  const refreshUnread = useCallback6(() => {
8917
8911
  if (!options.modules.list.some((m) => m.layout === "chat")) return;
8918
8912
  transport.listConversations({ limit: 50 }).then((res) => {
8919
- const onScreenConversationId = isChatActive() ? conversationIdSig.value : void 0;
8920
- hasUnreadSig.value = res.conversations.some((c) => c.hasUnread && c.conversationId !== onScreenConversationId);
8913
+ unreadIdsRef.current = new Set(res.conversations.filter((c) => c.hasUnread).map((c) => c.conversationId));
8914
+ recomputeUnread();
8921
8915
  }).catch((err) => log17.debug("refreshUnread failed (non-fatal)", { err }));
8922
- }, [transport, options.modules, hasUnreadSig, conversationIdSig]);
8916
+ }, [transport, options.modules, recomputeUnread]);
8917
+ const clearUnread = useCallback6(
8918
+ (conversationId) => {
8919
+ unreadIdsRef.current.delete(conversationId);
8920
+ recomputeUnread();
8921
+ },
8922
+ [recomputeUnread]
8923
+ );
8923
8924
  const markActiveConversationRead = useCallback6(() => {
8924
8925
  if (!isChatActive()) return;
8925
8926
  const conversationId = conversationIdSig.value;
8926
8927
  if (!conversationId) return;
8927
8928
  clearTimeout(markReadTimerRef.current);
8928
8929
  markReadTimerRef.current = setTimeout(() => {
8929
- void transport.markRead(conversationId).then(refreshUnread);
8930
+ clearUnread(conversationId);
8931
+ void transport.markRead(conversationId);
8930
8932
  }, MARK_READ_DELAY_MS);
8931
- }, [transport, conversationIdSig, refreshUnread]);
8933
+ }, [transport, conversationIdSig, clearUnread]);
8932
8934
  useEffect16(() => {
8933
8935
  markActiveConversationReadRef.current = markActiveConversationRead;
8934
8936
  }, [markActiveConversationRead]);
@@ -9075,7 +9077,7 @@ function App({ options, hostElement, bus }) {
9075
9077
  setView("chat");
9076
9078
  void resumeInFlight();
9077
9079
  await transport.markRead(targetConversationId);
9078
- refreshUnread();
9080
+ clearUnread(targetConversationId);
9079
9081
  } catch (err) {
9080
9082
  bus.emit("error", err);
9081
9083
  options.onError?.(err);
@@ -9088,7 +9090,7 @@ function App({ options, hostElement, bus }) {
9088
9090
  bus,
9089
9091
  options,
9090
9092
  persistence,
9091
- refreshUnread,
9093
+ clearUnread,
9092
9094
  fetchFormMarkers,
9093
9095
  withWelcomeRows,
9094
9096
  streaming,
package/package.json CHANGED
@@ -80,5 +80,5 @@
80
80
  ],
81
81
  "type": "module",
82
82
  "types": "./index.d.ts",
83
- "version": "0.61.2"
83
+ "version": "0.61.3"
84
84
  }
package/web-component.mjs CHANGED
@@ -1930,7 +1930,7 @@ function createAuth(opts) {
1930
1930
  }
1931
1931
 
1932
1932
  // src/core/version.ts
1933
- var ELEMENTS_VERSION = true ? "0.61.2" : "0.0.0-dev";
1933
+ var ELEMENTS_VERSION = true ? "0.61.3" : "0.0.0-dev";
1934
1934
  var ELEMENTS_VERSION_PARAM = "_ev";
1935
1935
 
1936
1936
  // src/stream/types.ts
@@ -6932,7 +6932,7 @@ function PanelContent(props2) {
6932
6932
  composerArea = null;
6933
6933
  } else if (canSend) {
6934
6934
  composerArea = /* @__PURE__ */ jsxs18(Fragment5, { children: [
6935
- /* @__PURE__ */ jsx23(Suggestions, { suggestions, onPick: onSuggestion }),
6935
+ !isStreaming && /* @__PURE__ */ jsx23(Suggestions, { suggestions, onPick: onSuggestion }),
6936
6936
  /* @__PURE__ */ jsx23(
6937
6937
  Composer,
6938
6938
  {
@@ -8199,6 +8199,7 @@ function App({ options, hostElement, bus }) {
8199
8199
  const markActiveConversationReadRef = useRef9(null);
8200
8200
  const markReadTimerRef = useRef9();
8201
8201
  useEffect16(() => () => clearTimeout(markReadTimerRef.current), []);
8202
+ const unreadIdsRef = useRef9(/* @__PURE__ */ new Set());
8202
8203
  useEffect16(() => {
8203
8204
  if (!conversationReady || homeNavSeeded.current) return;
8204
8205
  homeNavSeeded.current = true;
@@ -8398,18 +8399,11 @@ function App({ options, hostElement, bus }) {
8398
8399
  useEffect16(() => {
8399
8400
  if (effectiveLocale !== activeLocale) setActiveLocale(effectiveLocale);
8400
8401
  }, [effectiveLocale, activeLocale]);
8401
- const pendingSuggestionsRef = useRef9(null);
8402
8402
  const captureSuggestions = useCallback6((chunk) => {
8403
8403
  if (chunk.type !== "data-suggestions") return false;
8404
- pendingSuggestionsRef.current = parseSuggestions(chunk.data);
8404
+ setSuggestions(parseSuggestions(chunk.data));
8405
8405
  return true;
8406
8406
  }, []);
8407
- const flushSuggestions = useCallback6(() => {
8408
- if (pendingSuggestionsRef.current) {
8409
- setSuggestions(pendingSuggestionsRef.current);
8410
- pendingSuggestionsRef.current = null;
8411
- }
8412
- }, []);
8413
8407
  const adoptConversationRebind = useCallback6(
8414
8408
  (chunk) => {
8415
8409
  if (chunk.type !== "data-conversation-rebind") return false;
@@ -8429,7 +8423,6 @@ function App({ options, hostElement, bus }) {
8429
8423
  const runResume = useCallback6(
8430
8424
  async (handle) => {
8431
8425
  let bubble = null;
8432
- pendingSuggestionsRef.current = null;
8433
8426
  try {
8434
8427
  for await (const evt of handle.iter) {
8435
8428
  if (adoptConversationRebind(evt.chunk) || captureSuggestions(evt.chunk)) continue;
@@ -8458,7 +8451,6 @@ function App({ options, hostElement, bus }) {
8458
8451
  bubble.status = "complete";
8459
8452
  feedback.play("messageReceived");
8460
8453
  emitMessage(bus, options, "assistant", assistantText(bubble));
8461
- flushSuggestions();
8462
8454
  }
8463
8455
  }
8464
8456
  } catch (err) {
@@ -8598,7 +8590,6 @@ function App({ options, hostElement, bus }) {
8598
8590
  userPrefs: persistence.loadUserPrefs()
8599
8591
  });
8600
8592
  setStreaming(true);
8601
- pendingSuggestionsRef.current = null;
8602
8593
  const handle = transport.sendMessage(body);
8603
8594
  setActiveCancel(() => handle.cancel);
8604
8595
  setActiveDetach(() => handle.detach);
@@ -8623,7 +8614,6 @@ function App({ options, hostElement, bus }) {
8623
8614
  assistantMsg.status = "complete";
8624
8615
  feedback.play("messageReceived");
8625
8616
  emitMessage(bus, options, "assistant", assistantText(assistantMsg));
8626
- flushSuggestions();
8627
8617
  }
8628
8618
  } catch (error) {
8629
8619
  if (isAbortError(error)) {
@@ -8872,22 +8862,34 @@ function App({ options, hostElement, bus }) {
8872
8862
  bus.emit("close", void 0);
8873
8863
  options.onClose?.();
8874
8864
  }, [bus, options, persistence, panelSize, forms]);
8865
+ const recomputeUnread = useCallback6(() => {
8866
+ const onScreenConversationId = isChatActive() ? conversationIdSig.value : void 0;
8867
+ hasUnreadSig.value = [...unreadIdsRef.current].some((id) => id !== onScreenConversationId);
8868
+ }, [hasUnreadSig, conversationIdSig]);
8875
8869
  const refreshUnread = useCallback6(() => {
8876
8870
  if (!options.modules.list.some((m) => m.layout === "chat")) return;
8877
8871
  transport.listConversations({ limit: 50 }).then((res) => {
8878
- const onScreenConversationId = isChatActive() ? conversationIdSig.value : void 0;
8879
- hasUnreadSig.value = res.conversations.some((c) => c.hasUnread && c.conversationId !== onScreenConversationId);
8872
+ unreadIdsRef.current = new Set(res.conversations.filter((c) => c.hasUnread).map((c) => c.conversationId));
8873
+ recomputeUnread();
8880
8874
  }).catch((err) => log16.debug("refreshUnread failed (non-fatal)", { err }));
8881
- }, [transport, options.modules, hasUnreadSig, conversationIdSig]);
8875
+ }, [transport, options.modules, recomputeUnread]);
8876
+ const clearUnread = useCallback6(
8877
+ (conversationId) => {
8878
+ unreadIdsRef.current.delete(conversationId);
8879
+ recomputeUnread();
8880
+ },
8881
+ [recomputeUnread]
8882
+ );
8882
8883
  const markActiveConversationRead = useCallback6(() => {
8883
8884
  if (!isChatActive()) return;
8884
8885
  const conversationId = conversationIdSig.value;
8885
8886
  if (!conversationId) return;
8886
8887
  clearTimeout(markReadTimerRef.current);
8887
8888
  markReadTimerRef.current = setTimeout(() => {
8888
- void transport.markRead(conversationId).then(refreshUnread);
8889
+ clearUnread(conversationId);
8890
+ void transport.markRead(conversationId);
8889
8891
  }, MARK_READ_DELAY_MS);
8890
- }, [transport, conversationIdSig, refreshUnread]);
8892
+ }, [transport, conversationIdSig, clearUnread]);
8891
8893
  useEffect16(() => {
8892
8894
  markActiveConversationReadRef.current = markActiveConversationRead;
8893
8895
  }, [markActiveConversationRead]);
@@ -9034,7 +9036,7 @@ function App({ options, hostElement, bus }) {
9034
9036
  setView("chat");
9035
9037
  void resumeInFlight();
9036
9038
  await transport.markRead(targetConversationId);
9037
- refreshUnread();
9039
+ clearUnread(targetConversationId);
9038
9040
  } catch (err) {
9039
9041
  bus.emit("error", err);
9040
9042
  options.onError?.(err);
@@ -9047,7 +9049,7 @@ function App({ options, hostElement, bus }) {
9047
9049
  bus,
9048
9050
  options,
9049
9051
  persistence,
9050
- refreshUnread,
9052
+ clearUnread,
9051
9053
  fetchFormMarkers,
9052
9054
  withWelcomeRows,
9053
9055
  streaming,