@assistant-ui/react 0.4.2 → 0.4.3

Sign up to get free protection for your applications and to get access to all the features.
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() {