@assistant-ui/react 0.4.2 → 0.4.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/dist/index.mjs CHANGED
@@ -1179,7 +1179,7 @@ import { Primitive as Primitive4 } from "@radix-ui/react-primitive";
1179
1179
  import { forwardRef as forwardRef7 } from "react";
1180
1180
 
1181
1181
  // src/utils/hooks/useSmooth.tsx
1182
- import { useEffect as useEffect8, useState as useState5 } from "react";
1182
+ import { useEffect as useEffect8, useRef as useRef4, useState as useState5 } from "react";
1183
1183
  var TextStreamAnimator = class {
1184
1184
  constructor(currentText, setText) {
1185
1185
  this.currentText = currentText;
@@ -1225,6 +1225,9 @@ var TextStreamAnimator = class {
1225
1225
  };
1226
1226
  };
1227
1227
  var useSmooth = (text, smooth = false) => {
1228
+ const { useMessage } = useMessageContext();
1229
+ const id = useMessage((m) => m.message.id);
1230
+ const idRef = useRef4(id);
1228
1231
  const [displayedText, setDisplayedText] = useState5(text);
1229
1232
  const [animatorRef] = useState5(
1230
1233
  new TextStreamAnimator(text, setDisplayedText)
@@ -1234,7 +1237,8 @@ var useSmooth = (text, smooth = false) => {
1234
1237
  animatorRef.stop();
1235
1238
  return;
1236
1239
  }
1237
- if (!text.startsWith(animatorRef.targetText)) {
1240
+ if (idRef.current !== id || !text.startsWith(animatorRef.targetText)) {
1241
+ idRef.current = id;
1238
1242
  setDisplayedText(text);
1239
1243
  animatorRef.currentText = text;
1240
1244
  animatorRef.targetText = text;
@@ -1243,7 +1247,7 @@ var useSmooth = (text, smooth = false) => {
1243
1247
  }
1244
1248
  animatorRef.targetText = text;
1245
1249
  animatorRef.start();
1246
- }, [animatorRef, smooth, text]);
1250
+ }, [animatorRef, id, smooth, text]);
1247
1251
  useEffect8(() => {
1248
1252
  return () => {
1249
1253
  animatorRef.stop();
@@ -1431,7 +1435,7 @@ import {
1431
1435
  forwardRef as forwardRef11,
1432
1436
  useCallback as useCallback15,
1433
1437
  useEffect as useEffect9,
1434
- useRef as useRef4
1438
+ useRef as useRef5
1435
1439
  } from "react";
1436
1440
  import TextareaAutosize from "react-textarea-autosize";
1437
1441
  import { useEscapeKeydown } from "@radix-ui/react-use-escape-keydown";
@@ -1445,7 +1449,7 @@ var ComposerPrimitiveInput = forwardRef11(
1445
1449
  return c.value;
1446
1450
  });
1447
1451
  const Component = asChild ? Slot : TextareaAutosize;
1448
- const textareaRef = useRef4(null);
1452
+ const textareaRef = useRef5(null);
1449
1453
  const ref = useComposedRefs2(forwardedRef, textareaRef);
1450
1454
  useEscapeKeydown((e) => {
1451
1455
  const composer = useComposer.getState();
@@ -1591,7 +1595,7 @@ import { forwardRef as forwardRef14 } from "react";
1591
1595
 
1592
1596
  // src/primitive-hooks/thread/useThreadViewportAutoScroll.tsx
1593
1597
  import { useComposedRefs as useComposedRefs3 } from "@radix-ui/react-compose-refs";
1594
- import { useRef as useRef5 } from "react";
1598
+ import { useRef as useRef6 } from "react";
1595
1599
 
1596
1600
  // src/utils/hooks/useOnResizeContent.tsx
1597
1601
  import { useCallbackRef as useCallbackRef2 } from "@radix-ui/react-use-callback-ref";
@@ -1650,16 +1654,13 @@ var useOnScrollToBottom = (callback) => {
1650
1654
  var useThreadViewportAutoScroll = ({
1651
1655
  autoScroll = true
1652
1656
  }) => {
1653
- const divRef = useRef5(null);
1657
+ const divRef = useRef6(null);
1654
1658
  const { useViewport } = useThreadContext();
1655
- const firstRenderRef = useRef5(true);
1656
- const lastScrollTop = useRef5(0);
1657
- const isScrollingToBottomRef = useRef5(false);
1658
- const scrollToBottom = () => {
1659
+ const lastScrollTop = useRef6(0);
1660
+ const isScrollingToBottomRef = useRef6(false);
1661
+ const scrollToBottom = (behavior) => {
1659
1662
  const div = divRef.current;
1660
1663
  if (!div || !autoScroll) return;
1661
- const behavior = firstRenderRef.current ? "instant" : "auto";
1662
- firstRenderRef.current = false;
1663
1664
  isScrollingToBottomRef.current = true;
1664
1665
  div.scrollTo({ top: div.scrollHeight, behavior });
1665
1666
  };
@@ -1670,7 +1671,9 @@ var useThreadViewportAutoScroll = ({
1670
1671
  const newIsAtBottom = div.scrollHeight - div.scrollTop <= div.clientHeight;
1671
1672
  if (!newIsAtBottom && lastScrollTop.current < div.scrollTop) {
1672
1673
  } else {
1673
- isScrollingToBottomRef.current = newIsAtBottom;
1674
+ if (newIsAtBottom) {
1675
+ isScrollingToBottomRef.current = false;
1676
+ }
1674
1677
  if (newIsAtBottom !== isAtBottom) {
1675
1678
  useViewport.setState({
1676
1679
  isAtBottom: newIsAtBottom
@@ -1680,11 +1683,10 @@ var useThreadViewportAutoScroll = ({
1680
1683
  lastScrollTop.current = div.scrollTop;
1681
1684
  };
1682
1685
  const resizeRef = useOnResizeContent(() => {
1683
- if (!isScrollingToBottomRef.current && !useViewport.getState().isAtBottom && !firstRenderRef.current) {
1684
- handleScroll();
1685
- } else {
1686
- scrollToBottom();
1686
+ if (isScrollingToBottomRef.current || useViewport.getState().isAtBottom) {
1687
+ scrollToBottom("instant");
1687
1688
  }
1689
+ handleScroll();
1688
1690
  });
1689
1691
  const scrollRef = useManagedRef((el) => {
1690
1692
  el.addEventListener("scroll", handleScroll);
@@ -1694,7 +1696,7 @@ var useThreadViewportAutoScroll = ({
1694
1696
  });
1695
1697
  const autoScrollRef = useComposedRefs3(resizeRef, scrollRef, divRef);
1696
1698
  useOnScrollToBottom(() => {
1697
- scrollToBottom();
1699
+ scrollToBottom("auto");
1698
1700
  });
1699
1701
  return autoScrollRef;
1700
1702
  };
@@ -2289,7 +2291,7 @@ function assistantDecoderStream() {
2289
2291
  let currentToolCall;
2290
2292
  return new TransformStream({
2291
2293
  transform(chunk, controller) {
2292
- const [code, valueJson] = chunk.split(":");
2294
+ const [code, valueJson] = parseStreamPart(chunk);
2293
2295
  const value = JSON.parse(valueJson);
2294
2296
  if (currentToolCall && code !== "2" /* ToolCallArgsTextDelta */ && code !== "E" /* Error */) {
2295
2297
  controller.enqueue({
@@ -2348,6 +2350,14 @@ function assistantDecoderStream() {
2348
2350
  }
2349
2351
  });
2350
2352
  }
2353
+ var parseStreamPart = (part) => {
2354
+ const index = part.indexOf(":");
2355
+ if (index === -1) throw new Error("Invalid stream part");
2356
+ return [
2357
+ part.slice(0, index),
2358
+ part.slice(index + 1)
2359
+ ];
2360
+ };
2351
2361
 
2352
2362
  // src/runtimes/edge/streams/chunkByLineStream.ts
2353
2363
  function chunkByLineStream() {