@assistant-ui/react 0.5.10 → 0.5.12

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
@@ -1192,7 +1192,7 @@ var toContentPartStatus = (message, partIndex, part) => {
1192
1192
  return message.status;
1193
1193
  };
1194
1194
  var EMPTY_CONTENT = Object.freeze({ type: "text", text: "" });
1195
- var syncContentPart = ({ message }, useContentPart, partIndex) => {
1195
+ var getContentPartState = ({ message }, useContentPart, partIndex) => {
1196
1196
  let part = message.content[partIndex];
1197
1197
  if (!part) {
1198
1198
  if (message.content.length === 0 && partIndex === 0) {
@@ -1202,29 +1202,32 @@ var syncContentPart = ({ message }, useContentPart, partIndex) => {
1202
1202
  }
1203
1203
  }
1204
1204
  const status = toContentPartStatus(message, partIndex, part);
1205
- const currentState = useContentPart.getState();
1206
- if (currentState.part === part && currentState.status === status) return;
1207
- useContentPart.setState(
1208
- Object.freeze({
1209
- part,
1210
- status
1211
- })
1212
- );
1205
+ const currentState = useContentPart?.getState();
1206
+ if (currentState && currentState.part === part && currentState.status === status)
1207
+ return null;
1208
+ return Object.freeze({ part, status });
1213
1209
  };
1214
1210
  var useContentPartContext2 = (partIndex) => {
1215
1211
  const { useMessage } = useMessageContext();
1216
1212
  const [context] = useState4(() => {
1217
1213
  const useContentPart = create10(
1218
- () => ({})
1214
+ () => getContentPartState(useMessage.getState(), void 0, partIndex)
1219
1215
  );
1220
- syncContentPart(useMessage.getState(), useContentPart, partIndex);
1216
+ getContentPartState(useMessage.getState(), useContentPart, partIndex);
1221
1217
  return { useContentPart };
1222
1218
  });
1223
1219
  useEffect6(() => {
1224
- syncContentPart(useMessage.getState(), context.useContentPart, partIndex);
1225
- return useMessage.subscribe((message) => {
1226
- syncContentPart(message, context.useContentPart, partIndex);
1227
- });
1220
+ const syncContentPart = (message) => {
1221
+ const newState = getContentPartState(
1222
+ message,
1223
+ context.useContentPart,
1224
+ partIndex
1225
+ );
1226
+ if (!newState) return;
1227
+ context.useContentPart.setState(newState, true);
1228
+ };
1229
+ syncContentPart(useMessage.getState());
1230
+ return useMessage.subscribe(syncContentPart);
1228
1231
  }, [context, useMessage, partIndex]);
1229
1232
  return context;
1230
1233
  };
@@ -1828,16 +1831,15 @@ import { jsx as jsx23 } from "react/jsx-runtime";
1828
1831
  var getIsLast = (messages, message) => {
1829
1832
  return messages[messages.length - 1]?.id === message.id;
1830
1833
  };
1831
- var syncMessage = (messages, getBranches, useMessage, messageIndex) => {
1834
+ var getMessageState = (messages, getBranches, useMessage, messageIndex) => {
1832
1835
  const parentId = messages[messageIndex - 1]?.id ?? null;
1833
1836
  const message = messages[messageIndex];
1834
- if (!message) return;
1835
1837
  const isLast = getIsLast(messages, message);
1836
1838
  const branches = getBranches(message.id);
1837
- const currentState = useMessage.getState();
1838
- if (currentState.message === message && currentState.parentId === parentId && currentState.branches === branches && currentState.isLast === isLast)
1839
- return;
1840
- useMessage.setState({
1839
+ const currentState = useMessage?.getState();
1840
+ if (currentState && currentState.message === message && currentState.parentId === parentId && currentState.branches === branches && currentState.isLast === isLast)
1841
+ return null;
1842
+ return Object.freeze({
1841
1843
  message,
1842
1844
  parentId,
1843
1845
  branches,
@@ -1847,7 +1849,14 @@ var syncMessage = (messages, getBranches, useMessage, messageIndex) => {
1847
1849
  var useMessageContext2 = (messageIndex) => {
1848
1850
  const { useThreadMessages, useThreadActions } = useThreadContext();
1849
1851
  const [context] = useState6(() => {
1850
- const useMessage = create13(() => ({}));
1852
+ const useMessage = create13(
1853
+ () => getMessageState(
1854
+ useThreadMessages.getState(),
1855
+ useThreadActions.getState().getBranches,
1856
+ void 0,
1857
+ messageIndex
1858
+ )
1859
+ );
1851
1860
  const useMessageUtils = makeMessageUtilsStore();
1852
1861
  const useEditComposer = makeEditComposerStore({
1853
1862
  onEdit: () => {
@@ -1875,23 +1884,24 @@ var useMessageContext2 = (messageIndex) => {
1875
1884
  });
1876
1885
  }
1877
1886
  });
1878
- syncMessage(
1879
- useThreadMessages.getState(),
1880
- useThreadActions.getState().getBranches,
1881
- useMessage,
1882
- messageIndex
1883
- );
1884
1887
  return { useMessage, useMessageUtils, useEditComposer };
1885
1888
  });
1886
1889
  useEffect10(() => {
1887
- return useThreadMessages.subscribe((thread) => {
1888
- syncMessage(
1890
+ const syncMessage = (thread) => {
1891
+ const newState = getMessageState(
1889
1892
  thread,
1890
1893
  useThreadActions.getState().getBranches,
1891
1894
  context.useMessage,
1892
1895
  messageIndex
1893
1896
  );
1894
- });
1897
+ if (!newState) return;
1898
+ context.useMessage.setState(
1899
+ newState,
1900
+ true
1901
+ );
1902
+ };
1903
+ syncMessage(useThreadMessages.getState());
1904
+ return useThreadMessages.subscribe(syncMessage);
1895
1905
  }, [useThreadMessages, useThreadActions, context, messageIndex]);
1896
1906
  return context;
1897
1907
  };
@@ -3572,7 +3582,7 @@ var getExternalStoreMessage = (message) => {
3572
3582
  };
3573
3583
 
3574
3584
  // src/runtimes/external-store/useExternalStoreSync.tsx
3575
- import { useEffect as useEffect11, useMemo as useMemo3 } from "react";
3585
+ import { useEffect as useEffect11, useInsertionEffect as useInsertionEffect4, useMemo as useMemo3, useRef as useRef6 } from "react";
3576
3586
 
3577
3587
  // src/runtimes/external-store/ThreadMessageConverter.ts
3578
3588
  var ThreadMessageConverter = class {
@@ -3588,13 +3598,104 @@ var ThreadMessageConverter = class {
3588
3598
  }
3589
3599
  };
3590
3600
 
3601
+ // src/runtimes/external-store/auto-status.tsx
3602
+ var AUTO_STATUS_RUNNING = Object.freeze({ type: "running" });
3603
+ var AUTO_STATUS_COMPLETE = Object.freeze({
3604
+ type: "complete",
3605
+ reason: "unknown"
3606
+ });
3607
+ var isAutoStatus = (status) => status === AUTO_STATUS_RUNNING || status === AUTO_STATUS_COMPLETE;
3608
+ var getAutoStatus = (isLast, isRunning) => isLast && isRunning ? AUTO_STATUS_RUNNING : AUTO_STATUS_COMPLETE;
3609
+
3610
+ // src/runtimes/external-store/ThreadMessageLike.tsx
3611
+ var fromThreadMessageLike = (like, fallbackId, fallbackStatus) => {
3612
+ const { role, content, id, createdAt, status } = like;
3613
+ const common = {
3614
+ id: id ?? fallbackId,
3615
+ createdAt: createdAt ?? /* @__PURE__ */ new Date()
3616
+ };
3617
+ switch (role) {
3618
+ case "assistant":
3619
+ return {
3620
+ ...common,
3621
+ role,
3622
+ content: content.map((part) => {
3623
+ const type = part.type;
3624
+ switch (type) {
3625
+ case "text":
3626
+ case "ui":
3627
+ return part;
3628
+ case "tool-call": {
3629
+ if ("argsText" in part) return part;
3630
+ return {
3631
+ ...part,
3632
+ argsText: JSON.stringify(part.args)
3633
+ };
3634
+ }
3635
+ default: {
3636
+ const unhandledType = type;
3637
+ throw new Error(`Unknown content part type: ${unhandledType}`);
3638
+ }
3639
+ }
3640
+ }),
3641
+ status: status ?? fallbackStatus
3642
+ };
3643
+ case "user":
3644
+ return {
3645
+ ...common,
3646
+ role,
3647
+ content: content.map((part) => {
3648
+ const type = part.type;
3649
+ switch (type) {
3650
+ case "text":
3651
+ case "ui":
3652
+ case "image":
3653
+ return part;
3654
+ default: {
3655
+ const unhandledType = type;
3656
+ throw new Error(`Unknown content part type: ${unhandledType}`);
3657
+ }
3658
+ }
3659
+ })
3660
+ };
3661
+ case "system":
3662
+ if (content.length !== 1 || content[0].type !== "text")
3663
+ throw new Error(
3664
+ "System messages must have exactly one text content part."
3665
+ );
3666
+ return {
3667
+ ...common,
3668
+ role,
3669
+ content
3670
+ };
3671
+ default: {
3672
+ const unsupportedRole = role;
3673
+ throw new Error(`Unknown message role: ${unsupportedRole}`);
3674
+ }
3675
+ }
3676
+ };
3677
+
3591
3678
  // src/runtimes/external-store/useExternalStoreSync.tsx
3592
3679
  var useExternalStoreSync = (adapter, updateData) => {
3680
+ const adapterRef = useRef6(adapter);
3681
+ useInsertionEffect4(() => {
3682
+ adapterRef.current = adapter;
3683
+ });
3593
3684
  const [converter, convertCallback] = useMemo3(() => {
3594
3685
  const converter2 = adapter.convertMessage ?? ((m) => m);
3595
3686
  const convertCallback2 = (cache, m, idx) => {
3687
+ const autoStatus = getAutoStatus(
3688
+ adapterRef.current.messages.at(-1) === m,
3689
+ adapterRef.current.isRunning ?? false
3690
+ );
3691
+ if (cache && (cache.role !== "assistant" || !isAutoStatus(cache.status) || cache.status.type === autoStatus.type))
3692
+ return cache;
3596
3693
  if (cache) return cache;
3597
- const newMessage = converter2(m, idx);
3694
+ const newMessage = fromThreadMessageLike(
3695
+ converter2(m, idx),
3696
+ idx.toString(),
3697
+ autoStatus
3698
+ );
3598
3699
  newMessage[symbolInnerMessage] = m;
3599
3700
  return newMessage;
3600
3701
  };
@@ -3760,10 +3861,10 @@ var ExternalStoreRuntime = class extends BaseAssistantRuntime {
3760
3861
  };
3761
3862
 
3762
3863
  // src/runtimes/external-store/useExternalStoreRuntime.tsx
3763
- import { useEffect as useEffect12, useInsertionEffect as useInsertionEffect4, useState as useState9 } from "react";
3864
+ import { useEffect as useEffect12, useInsertionEffect as useInsertionEffect5, useState as useState9 } from "react";
3764
3865
  var useExternalStoreRuntime = (store) => {
3765
3866
  const [runtime] = useState9(() => new ExternalStoreRuntime(store));
3766
- useInsertionEffect4(() => {
3867
+ useInsertionEffect5(() => {
3767
3868
  runtime.store = store;
3768
3869
  });
3769
3870
  useEffect12(() => {