@assistant-ui/react 0.5.42 → 0.5.46
Sign up to get free protection for your applications and to get access to all the features.
- 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,
|