@assistant-ui/react 0.5.42 → 0.5.46
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.d.mts +36 -6
- package/dist/index.d.ts +36 -6
- package/dist/index.js +253 -67
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +208 -22
- package/dist/index.mjs.map +1 -1
- package/dist/styles/index.css +3 -0
- package/dist/styles/index.css.map +1 -1
- package/dist/styles/tailwindcss/thread.css +1 -1
- package/package.json +3 -3
package/dist/index.mjs
CHANGED
@@ -164,6 +164,7 @@ import { create as create4 } from "zustand";
|
|
164
164
|
var getThreadStateFromRuntime = (runtime) => {
|
165
165
|
const lastMessage = runtime.messages.at(-1);
|
166
166
|
return Object.freeze({
|
167
|
+
threadId: runtime.threadId,
|
167
168
|
capabilities: runtime.capabilities,
|
168
169
|
isDisabled: runtime.isDisabled,
|
169
170
|
isRunning: lastMessage?.role !== "assistant" ? false : lastMessage.status.type === "running"
|
@@ -636,6 +637,9 @@ var useSmooth = (state, smooth = false) => {
|
|
636
637
|
setDisplayedText(text2);
|
637
638
|
useSmoothStatus2?.setState(text2 !== state.part.text ? SMOOTH_STATUS : state.status);
|
638
639
|
});
|
640
|
+
useEffect(() => {
|
641
|
+
useSmoothStatus2?.setState(text !== displayedText ? SMOOTH_STATUS : state.status);
|
642
|
+
}, [useSmoothStatus2, text, displayedText, state.status]);
|
639
643
|
const [animatorRef] = useState2(
|
640
644
|
new TextStreamAnimator(text, setText)
|
641
645
|
);
|
@@ -1077,6 +1081,7 @@ var LocalThreadRuntime = class {
|
|
1077
1081
|
constructor(configProvider, adapter, { initialMessages, ...options }) {
|
1078
1082
|
this.configProvider = configProvider;
|
1079
1083
|
this.adapter = adapter;
|
1084
|
+
this.threadId = generateId();
|
1080
1085
|
this.options = options;
|
1081
1086
|
if (initialMessages) {
|
1082
1087
|
let parentId = null;
|
@@ -1098,6 +1103,7 @@ var LocalThreadRuntime = class {
|
|
1098
1103
|
unstable_copy: true,
|
1099
1104
|
speak: false
|
1100
1105
|
};
|
1106
|
+
threadId;
|
1101
1107
|
isDisabled = false;
|
1102
1108
|
get messages() {
|
1103
1109
|
return this.repository.getMessages();
|
@@ -1400,11 +1406,12 @@ var getAutoStatus = (isLast, isRunning) => isLast && isRunning ? AUTO_STATUS_RUN
|
|
1400
1406
|
|
1401
1407
|
// src/runtimes/external-store/ThreadMessageLike.tsx
|
1402
1408
|
var fromThreadMessageLike = (like, fallbackId, fallbackStatus) => {
|
1403
|
-
const { role,
|
1409
|
+
const { role, id, createdAt, status } = like;
|
1404
1410
|
const common = {
|
1405
1411
|
id: id ?? fallbackId,
|
1406
1412
|
createdAt: createdAt ?? /* @__PURE__ */ new Date()
|
1407
1413
|
};
|
1414
|
+
const content = typeof like.content === "string" ? [{ type: "text", text: like.content }] : like.content;
|
1408
1415
|
switch (role) {
|
1409
1416
|
case "assistant":
|
1410
1417
|
return {
|
@@ -1414,6 +1421,8 @@ var fromThreadMessageLike = (like, fallbackId, fallbackStatus) => {
|
|
1414
1421
|
const type = part.type;
|
1415
1422
|
switch (type) {
|
1416
1423
|
case "text":
|
1424
|
+
if (part.text.trim().length === 0) return null;
|
1425
|
+
return part;
|
1417
1426
|
case "ui":
|
1418
1427
|
return part;
|
1419
1428
|
case "tool-call": {
|
@@ -1428,7 +1437,7 @@ var fromThreadMessageLike = (like, fallbackId, fallbackStatus) => {
|
|
1428
1437
|
throw new Error(`Unknown content part type: ${unhandledType}`);
|
1429
1438
|
}
|
1430
1439
|
}
|
1431
|
-
}),
|
1440
|
+
}).filter((c) => !!c),
|
1432
1441
|
status: status ?? fallbackStatus
|
1433
1442
|
};
|
1434
1443
|
case "user":
|
@@ -1493,8 +1502,9 @@ var ExternalStoreThreadRuntime = class {
|
|
1493
1502
|
get capabilities() {
|
1494
1503
|
return this._capabilities;
|
1495
1504
|
}
|
1496
|
-
|
1497
|
-
|
1505
|
+
threadId;
|
1506
|
+
messages;
|
1507
|
+
isDisabled;
|
1498
1508
|
converter = new ThreadMessageConverter();
|
1499
1509
|
_store;
|
1500
1510
|
composer = {
|
@@ -1507,8 +1517,12 @@ var ExternalStoreThreadRuntime = class {
|
|
1507
1517
|
constructor(store) {
|
1508
1518
|
this.store = store;
|
1509
1519
|
}
|
1520
|
+
get store() {
|
1521
|
+
return this._store;
|
1522
|
+
}
|
1510
1523
|
set store(store) {
|
1511
1524
|
if (this._store === store) return;
|
1525
|
+
this.threadId = store.threadId ?? this.threadId ?? generateId();
|
1512
1526
|
const isRunning = store.isRunning ?? false;
|
1513
1527
|
this.isDisabled = store.isDisabled ?? false;
|
1514
1528
|
const oldStore = this._store;
|
@@ -1644,6 +1658,9 @@ var ExternalStoreRuntime = class extends BaseAssistantRuntime {
|
|
1644
1658
|
constructor(store) {
|
1645
1659
|
super(new ExternalStoreThreadRuntime(store));
|
1646
1660
|
}
|
1661
|
+
get store() {
|
1662
|
+
return this.thread.store;
|
1663
|
+
}
|
1647
1664
|
set store(store) {
|
1648
1665
|
this.thread.store = store;
|
1649
1666
|
}
|
@@ -1684,6 +1701,153 @@ var useExternalStoreRuntime = (store) => {
|
|
1684
1701
|
return runtime;
|
1685
1702
|
};
|
1686
1703
|
|
1704
|
+
// src/runtimes/external-store/external-message-converter.tsx
|
1705
|
+
import { useMemo as useMemo2 } from "react";
|
1706
|
+
var joinExternalMessages = (messages) => {
|
1707
|
+
const assistantMessage = {
|
1708
|
+
role: "assistant",
|
1709
|
+
content: []
|
1710
|
+
};
|
1711
|
+
for (const output of messages) {
|
1712
|
+
if (output.role === "tool") {
|
1713
|
+
const toolCallIdx = assistantMessage.content.findIndex(
|
1714
|
+
(c) => c.type === "tool-call" && c.toolCallId === output.toolCallId
|
1715
|
+
);
|
1716
|
+
if (toolCallIdx !== -1) {
|
1717
|
+
const toolCall = assistantMessage.content[toolCallIdx];
|
1718
|
+
if (output.toolName) {
|
1719
|
+
if (toolCall.toolName !== output.toolName)
|
1720
|
+
throw new Error(
|
1721
|
+
`Tool call name ${output.toolCallId} ${output.toolName} does not match existing tool call ${toolCall.toolName}`
|
1722
|
+
);
|
1723
|
+
}
|
1724
|
+
assistantMessage.content[toolCallIdx] = {
|
1725
|
+
...toolCall,
|
1726
|
+
result: output.result
|
1727
|
+
};
|
1728
|
+
} else {
|
1729
|
+
throw new Error(
|
1730
|
+
`Tool call ${output.toolCallId} ${output.toolName} not found in assistant message`
|
1731
|
+
);
|
1732
|
+
}
|
1733
|
+
} else {
|
1734
|
+
const content = output.content;
|
1735
|
+
const role = output.role;
|
1736
|
+
switch (role) {
|
1737
|
+
case "system":
|
1738
|
+
case "user":
|
1739
|
+
return { role, content };
|
1740
|
+
case "assistant":
|
1741
|
+
if (assistantMessage.content.length === 0) {
|
1742
|
+
assistantMessage.id = output.id;
|
1743
|
+
assistantMessage.createdAt ??= output.createdAt;
|
1744
|
+
assistantMessage.status ??= output.status;
|
1745
|
+
}
|
1746
|
+
assistantMessage.content.push(...content);
|
1747
|
+
break;
|
1748
|
+
default: {
|
1749
|
+
const unsupportedRole = role;
|
1750
|
+
throw new Error(`Unknown message role: ${unsupportedRole}`);
|
1751
|
+
}
|
1752
|
+
}
|
1753
|
+
}
|
1754
|
+
}
|
1755
|
+
return assistantMessage;
|
1756
|
+
};
|
1757
|
+
var chunkExternalMessages = (callbackResults) => {
|
1758
|
+
const results = [];
|
1759
|
+
let isAssistant = false;
|
1760
|
+
let inputs = [];
|
1761
|
+
let outputs = [];
|
1762
|
+
const flush = () => {
|
1763
|
+
if (outputs.length) {
|
1764
|
+
results.push({
|
1765
|
+
inputs,
|
1766
|
+
outputs
|
1767
|
+
});
|
1768
|
+
}
|
1769
|
+
inputs = [];
|
1770
|
+
outputs = [];
|
1771
|
+
};
|
1772
|
+
for (const callbackResult of callbackResults) {
|
1773
|
+
for (const output of callbackResult.outputs) {
|
1774
|
+
if (!isAssistant || output.role === "user" || output.role === "system") {
|
1775
|
+
flush();
|
1776
|
+
}
|
1777
|
+
isAssistant = output.role === "assistant" || output.role === "tool";
|
1778
|
+
if (inputs.at(-1) !== callbackResult.input) {
|
1779
|
+
inputs.push(callbackResult.input);
|
1780
|
+
}
|
1781
|
+
outputs.push(output);
|
1782
|
+
}
|
1783
|
+
}
|
1784
|
+
flush();
|
1785
|
+
return results;
|
1786
|
+
};
|
1787
|
+
var useExternalMessageConverter = ({
|
1788
|
+
callback,
|
1789
|
+
messages,
|
1790
|
+
isRunning
|
1791
|
+
}) => {
|
1792
|
+
const state = useMemo2(
|
1793
|
+
() => ({
|
1794
|
+
callback,
|
1795
|
+
callbackCache: /* @__PURE__ */ new WeakMap(),
|
1796
|
+
chunkCache: /* @__PURE__ */ new WeakMap(),
|
1797
|
+
converterCache: new ThreadMessageConverter()
|
1798
|
+
}),
|
1799
|
+
[callback]
|
1800
|
+
);
|
1801
|
+
return useMemo2(() => {
|
1802
|
+
const callbackResults = [];
|
1803
|
+
for (const message of messages) {
|
1804
|
+
let result = state.callbackCache.get(message);
|
1805
|
+
if (!result) {
|
1806
|
+
const output = state.callback(message);
|
1807
|
+
const outputs = Array.isArray(output) ? output : [output];
|
1808
|
+
result = { input: message, outputs };
|
1809
|
+
state.callbackCache.set(message, result);
|
1810
|
+
}
|
1811
|
+
callbackResults.push(result);
|
1812
|
+
}
|
1813
|
+
const chunks = chunkExternalMessages(callbackResults).map((m) => {
|
1814
|
+
const key = m.outputs[0];
|
1815
|
+
if (!key) return m;
|
1816
|
+
const cached = state.chunkCache.get(key);
|
1817
|
+
if (cached && shallowArrayEqual(cached.outputs, m.outputs)) return cached;
|
1818
|
+
state.chunkCache.set(key, m);
|
1819
|
+
return m;
|
1820
|
+
});
|
1821
|
+
return state.converterCache.convertMessages(
|
1822
|
+
chunks,
|
1823
|
+
(cache, message, idx) => {
|
1824
|
+
const isLast = idx === chunks.length - 1;
|
1825
|
+
const autoStatus = getAutoStatus(isLast, isRunning);
|
1826
|
+
if (cache && (cache.role !== "assistant" || !isAutoStatus(cache.status) || cache.status === autoStatus)) {
|
1827
|
+
const inputs = getExternalStoreMessage(cache);
|
1828
|
+
if (shallowArrayEqual(inputs, message.inputs)) {
|
1829
|
+
return cache;
|
1830
|
+
}
|
1831
|
+
}
|
1832
|
+
const newMessage = fromThreadMessageLike(
|
1833
|
+
joinExternalMessages(message.outputs),
|
1834
|
+
idx.toString(),
|
1835
|
+
autoStatus
|
1836
|
+
);
|
1837
|
+
newMessage[symbolInnerMessage] = message.inputs;
|
1838
|
+
return newMessage;
|
1839
|
+
}
|
1840
|
+
);
|
1841
|
+
}, [state, messages, isRunning]);
|
1842
|
+
};
|
1843
|
+
var shallowArrayEqual = (a, b) => {
|
1844
|
+
if (a.length !== b.length) return false;
|
1845
|
+
for (let i = 0; i < a.length; i++) {
|
1846
|
+
if (a[i] !== b[i]) return false;
|
1847
|
+
}
|
1848
|
+
return true;
|
1849
|
+
};
|
1850
|
+
|
1687
1851
|
// src/runtimes/dangerous-in-browser/useDangerousInBrowserRuntime.ts
|
1688
1852
|
import { useState as useState6 } from "react";
|
1689
1853
|
|
@@ -1788,7 +1952,7 @@ var ThreadProvider = ({
|
|
1788
1952
|
const thread = provider.thread;
|
1789
1953
|
const oldState = context.useThread.getState();
|
1790
1954
|
const state = getThreadStateFromRuntime(thread);
|
1791
|
-
if (oldState.isDisabled !== state.isDisabled || oldState.isRunning !== state.isRunning || // TODO ensure capabilities is memoized
|
1955
|
+
if (oldState.threadId !== state.threadId || oldState.isDisabled !== state.isDisabled || oldState.isRunning !== state.isRunning || // TODO ensure capabilities is memoized
|
1792
1956
|
oldState.capabilities !== state.capabilities) {
|
1793
1957
|
context.useThread.setState(
|
1794
1958
|
state,
|
@@ -1877,7 +2041,7 @@ var AssistantRuntimeProviderImpl = ({ children, runtime }) => {
|
|
1877
2041
|
var AssistantRuntimeProvider = memo(AssistantRuntimeProviderImpl);
|
1878
2042
|
|
1879
2043
|
// src/context/react/ComposerContext.ts
|
1880
|
-
import { useMemo as
|
2044
|
+
import { useMemo as useMemo3 } from "react";
|
1881
2045
|
|
1882
2046
|
// src/context/react/MessageContext.ts
|
1883
2047
|
import { createContext as createContext4, useContext as useContext4 } from "react";
|
@@ -1895,7 +2059,7 @@ function useMessageContext(options) {
|
|
1895
2059
|
var useComposerContext = () => {
|
1896
2060
|
const { useComposer } = useThreadContext();
|
1897
2061
|
const { useEditComposer } = useMessageContext({ optional: true }) ?? {};
|
1898
|
-
return
|
2062
|
+
return useMemo3(
|
1899
2063
|
() => ({
|
1900
2064
|
useComposer: useEditComposer ?? useComposer,
|
1901
2065
|
type: useEditComposer ? "edit" : "new"
|
@@ -1992,6 +2156,7 @@ var makeAssistantTool = (tool) => {
|
|
1992
2156
|
useAssistantTool(tool);
|
1993
2157
|
return null;
|
1994
2158
|
};
|
2159
|
+
Tool.unstable_tool = tool;
|
1995
2160
|
return Tool;
|
1996
2161
|
};
|
1997
2162
|
|
@@ -2013,6 +2178,7 @@ var makeAssistantToolUI = (tool) => {
|
|
2013
2178
|
useAssistantToolUI(tool);
|
2014
2179
|
return null;
|
2015
2180
|
};
|
2181
|
+
ToolUI.unstable_tool = tool;
|
2016
2182
|
return ToolUI;
|
2017
2183
|
};
|
2018
2184
|
|
@@ -2035,7 +2201,7 @@ var useAssistantInstructions = (instruction) => {
|
|
2035
2201
|
import { useCallback as useCallback3 } from "react";
|
2036
2202
|
|
2037
2203
|
// src/utils/combined/useCombinedStore.ts
|
2038
|
-
import { useMemo as
|
2204
|
+
import { useMemo as useMemo4 } from "react";
|
2039
2205
|
|
2040
2206
|
// src/utils/combined/createCombinedStore.ts
|
2041
2207
|
import { useSyncExternalStore } from "react";
|
@@ -2056,7 +2222,7 @@ var createCombinedStore = (stores) => {
|
|
2056
2222
|
|
2057
2223
|
// src/utils/combined/useCombinedStore.ts
|
2058
2224
|
var useCombinedStore = (stores, selector) => {
|
2059
|
-
const useCombined =
|
2225
|
+
const useCombined = useMemo4(() => createCombinedStore(stores), stores);
|
2060
2226
|
return useCombined(selector);
|
2061
2227
|
};
|
2062
2228
|
|
@@ -2869,21 +3035,22 @@ ContentPartPrimitiveInProgress.displayName = "ContentPartPrimitive.InProgress";
|
|
2869
3035
|
|
2870
3036
|
// src/primitives/message/MessageContent.tsx
|
2871
3037
|
import { jsx as jsx22, jsxs as jsxs3 } from "react/jsx-runtime";
|
3038
|
+
var ToolUIDisplay = ({
|
3039
|
+
UI,
|
3040
|
+
...props
|
3041
|
+
}) => {
|
3042
|
+
const { useToolUIs } = useAssistantContext();
|
3043
|
+
const Render = useToolUIs((s) => s.getToolUI(props.part.toolName)) ?? UI;
|
3044
|
+
if (!Render) return null;
|
3045
|
+
return /* @__PURE__ */ jsx22(Render, { ...props });
|
3046
|
+
};
|
2872
3047
|
var defaultComponents = {
|
2873
3048
|
Text: () => /* @__PURE__ */ jsxs3("p", { style: { whiteSpace: "pre-line" }, children: [
|
2874
3049
|
/* @__PURE__ */ jsx22(ContentPartPrimitiveText, {}),
|
2875
3050
|
/* @__PURE__ */ jsx22(ContentPartPrimitiveInProgress, { children: /* @__PURE__ */ jsx22("span", { style: { fontFamily: "revert" }, children: " \u25CF" }) })
|
2876
3051
|
] }),
|
2877
3052
|
Image: () => /* @__PURE__ */ jsx22(ContentPartPrimitiveImage, {}),
|
2878
|
-
UI: () => /* @__PURE__ */ jsx22(ContentPartPrimitiveDisplay, {})
|
2879
|
-
tools: {
|
2880
|
-
Fallback: (props) => {
|
2881
|
-
const { useToolUIs } = useAssistantContext();
|
2882
|
-
const Render = useToolUIs((s) => s.getToolUI(props.part.toolName));
|
2883
|
-
if (!Render) return null;
|
2884
|
-
return /* @__PURE__ */ jsx22(Render, { ...props });
|
2885
|
-
}
|
2886
|
-
}
|
3053
|
+
UI: () => /* @__PURE__ */ jsx22(ContentPartPrimitiveDisplay, {})
|
2887
3054
|
};
|
2888
3055
|
var MessageContentPartComponent = ({
|
2889
3056
|
components: {
|
@@ -2891,7 +3058,7 @@ var MessageContentPartComponent = ({
|
|
2891
3058
|
Text: Text2 = defaultComponents.Text,
|
2892
3059
|
Image: Image2 = defaultComponents.Image,
|
2893
3060
|
UI = defaultComponents.UI,
|
2894
|
-
tools: { by_name = {}, Fallback: Fallback2 =
|
3061
|
+
tools: { by_name = {}, Fallback: Fallback2 = void 0 } = {}
|
2895
3062
|
} = {}
|
2896
3063
|
}) => {
|
2897
3064
|
const { useThreadActions } = useThreadContext();
|
@@ -2918,10 +3085,19 @@ var MessageContentPartComponent = ({
|
|
2918
3085
|
const Tool = by_name[part.toolName] || Fallback2;
|
2919
3086
|
const addResult = (result) => addToolResult({
|
2920
3087
|
messageId: useMessage.getState().message.id,
|
3088
|
+
toolName: part.toolName,
|
2921
3089
|
toolCallId: part.toolCallId,
|
2922
3090
|
result
|
2923
3091
|
});
|
2924
|
-
return /* @__PURE__ */ jsx22(
|
3092
|
+
return /* @__PURE__ */ jsx22(
|
3093
|
+
ToolUIDisplay,
|
3094
|
+
{
|
3095
|
+
UI: Tool,
|
3096
|
+
part,
|
3097
|
+
status,
|
3098
|
+
addResult
|
3099
|
+
}
|
3100
|
+
);
|
2925
3101
|
}
|
2926
3102
|
default:
|
2927
3103
|
const unhandledType = type;
|
@@ -3790,13 +3966,22 @@ var AssistantMessageContentWrapper = withDefaults("div", {
|
|
3790
3966
|
className: "aui-assistant-message-content"
|
3791
3967
|
});
|
3792
3968
|
var AssistantMessageContent = forwardRef22(({ components: componentsProp, ...rest }, ref) => {
|
3793
|
-
const { assistantMessage: { components = {} } = {} } = useThreadConfig();
|
3969
|
+
const { tools, assistantMessage: { components = {} } = {} } = useThreadConfig();
|
3794
3970
|
return /* @__PURE__ */ jsx36(AssistantMessageContentWrapper, { ...rest, ref, children: /* @__PURE__ */ jsx36(
|
3795
3971
|
message_exports.Content,
|
3796
3972
|
{
|
3797
3973
|
components: {
|
3798
3974
|
...componentsProp,
|
3799
|
-
Text: componentsProp?.Text ?? components.Text ?? content_part_default.Text
|
3975
|
+
Text: componentsProp?.Text ?? components.Text ?? content_part_default.Text,
|
3976
|
+
tools: {
|
3977
|
+
by_name: !tools ? void 0 : Object.fromEntries(
|
3978
|
+
tools.map((t) => [
|
3979
|
+
t.unstable_tool.toolName,
|
3980
|
+
t.unstable_tool.render
|
3981
|
+
])
|
3982
|
+
),
|
3983
|
+
Fallback: components.ToolFallback
|
3984
|
+
}
|
3800
3985
|
}
|
3801
3986
|
}
|
3802
3987
|
) });
|
@@ -4327,6 +4512,7 @@ export {
|
|
4327
4512
|
useContentPartText,
|
4328
4513
|
useDangerousInBrowserRuntime,
|
4329
4514
|
useEdgeRuntime,
|
4515
|
+
useExternalMessageConverter,
|
4330
4516
|
useExternalStoreRuntime,
|
4331
4517
|
useLocalRuntime,
|
4332
4518
|
useMessageContext,
|