@assistant-ui/react 0.3.0 → 0.3.2
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 +46 -9
- package/dist/index.d.ts +46 -9
- package/dist/index.js +162 -68
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +135 -41
- package/dist/index.mjs.map +1 -1
- package/package.json +2 -2
package/dist/index.mjs
CHANGED
@@ -148,11 +148,14 @@ var makeBaseComposer = (set) => ({
|
|
148
148
|
});
|
149
149
|
|
150
150
|
// src/context/stores/Composer.ts
|
151
|
-
var makeComposerStore = (
|
151
|
+
var makeComposerStore = (useThreadMessages, useThreadActions) => {
|
152
152
|
const focusListeners = /* @__PURE__ */ new Set();
|
153
153
|
return create3()((set, get, store) => {
|
154
154
|
return {
|
155
155
|
...makeBaseComposer(set, get, store),
|
156
|
+
get canCancel() {
|
157
|
+
return useThreadActions.getState().capabilities.cancel;
|
158
|
+
},
|
156
159
|
isEditing: true,
|
157
160
|
send: () => {
|
158
161
|
const { setValue, value } = get();
|
@@ -164,10 +167,7 @@ var makeComposerStore = (useThread, useThreadMessages, useThreadActions) => {
|
|
164
167
|
});
|
165
168
|
},
|
166
169
|
cancel: () => {
|
167
|
-
const thread = useThread.getState();
|
168
|
-
if (!thread.isRunning) return false;
|
169
170
|
useThreadActions.getState().cancelRun();
|
170
|
-
return true;
|
171
171
|
},
|
172
172
|
focus: () => {
|
173
173
|
for (const listener of focusListeners) {
|
@@ -217,6 +217,9 @@ import { create as create6 } from "zustand";
|
|
217
217
|
var makeThreadActionStore = (runtimeRef) => {
|
218
218
|
return create6(
|
219
219
|
() => Object.freeze({
|
220
|
+
get capabilities() {
|
221
|
+
return runtimeRef.current.capabilities;
|
222
|
+
},
|
220
223
|
getBranches: (messageId) => runtimeRef.current.getBranches(messageId),
|
221
224
|
switchToBranch: (branchId) => runtimeRef.current.switchToBranch(branchId),
|
222
225
|
startRun: (parentId) => runtimeRef.current.startRun(parentId),
|
@@ -248,11 +251,7 @@ var ThreadProvider = ({
|
|
248
251
|
const useThreadMessages = makeThreadMessagesStore(runtimeRef);
|
249
252
|
const useThreadActions = makeThreadActionStore(runtimeRef);
|
250
253
|
const useViewport = makeThreadViewportStore();
|
251
|
-
const useComposer = makeComposerStore(
|
252
|
-
useThread,
|
253
|
-
useThreadMessages,
|
254
|
-
useThreadActions
|
255
|
-
);
|
254
|
+
const useComposer = makeComposerStore(useThreadMessages, useThreadActions);
|
256
255
|
return {
|
257
256
|
useThread,
|
258
257
|
useThreadMessages,
|
@@ -625,7 +624,7 @@ var useBranchPickerPrevious = () => {
|
|
625
624
|
import { useCallback as useCallback9 } from "react";
|
626
625
|
var useComposerCancel = () => {
|
627
626
|
const { useComposer } = useComposerContext();
|
628
|
-
const disabled = useComposer((c) => !c.
|
627
|
+
const disabled = useComposer((c) => !c.canCancel);
|
629
628
|
const callback = useCallback9(() => {
|
630
629
|
const { cancel } = useComposer.getState();
|
631
630
|
cancel();
|
@@ -669,7 +668,7 @@ var useContentPartDisplay = () => {
|
|
669
668
|
throw new Error(
|
670
669
|
"This component can only be used inside ui content parts."
|
671
670
|
);
|
672
|
-
return c
|
671
|
+
return c;
|
673
672
|
});
|
674
673
|
return display;
|
675
674
|
};
|
@@ -682,7 +681,7 @@ var useContentPartImage = () => {
|
|
682
681
|
throw new Error(
|
683
682
|
"ContentPartImage can only be used inside image content parts."
|
684
683
|
);
|
685
|
-
return c
|
684
|
+
return c;
|
686
685
|
});
|
687
686
|
return image;
|
688
687
|
};
|
@@ -757,15 +756,18 @@ var useThreadSuggestion = ({
|
|
757
756
|
autoSend
|
758
757
|
}) => {
|
759
758
|
const { useThread, useComposer } = useThreadContext();
|
759
|
+
const append = useAppendMessage();
|
760
760
|
const disabled = useThread((t) => t.isRunning);
|
761
761
|
const callback = useCallback12(() => {
|
762
762
|
const thread = useThread.getState();
|
763
763
|
const composer = useComposer.getState();
|
764
|
-
composer.setValue(prompt);
|
765
764
|
if (autoSend && !thread.isRunning) {
|
766
|
-
|
765
|
+
append(prompt);
|
766
|
+
composer.setValue("");
|
767
|
+
} else {
|
768
|
+
composer.setValue(prompt);
|
767
769
|
}
|
768
|
-
}, [useThread, useComposer,
|
770
|
+
}, [useThread, useComposer, autoSend, append, prompt]);
|
769
771
|
if (disabled) return null;
|
770
772
|
return callback;
|
771
773
|
};
|
@@ -1161,13 +1163,86 @@ var ContentPartProvider = ({
|
|
1161
1163
|
// src/primitives/contentPart/ContentPartText.tsx
|
1162
1164
|
import { Primitive as Primitive4 } from "@radix-ui/react-primitive";
|
1163
1165
|
import { forwardRef as forwardRef7 } from "react";
|
1166
|
+
|
1167
|
+
// src/utils/hooks/useSmooth.tsx
|
1168
|
+
import { useEffect as useEffect8, useState as useState5 } from "react";
|
1169
|
+
var TextStreamAnimator = class {
|
1170
|
+
constructor(setText) {
|
1171
|
+
this.setText = setText;
|
1172
|
+
}
|
1173
|
+
animationFrameId = null;
|
1174
|
+
lastUpdateTime = Date.now();
|
1175
|
+
decayFactor = 0.99;
|
1176
|
+
targetText = "";
|
1177
|
+
start() {
|
1178
|
+
if (this.animationFrameId !== null) return;
|
1179
|
+
this.animate();
|
1180
|
+
}
|
1181
|
+
stop() {
|
1182
|
+
if (this.animationFrameId !== null) {
|
1183
|
+
cancelAnimationFrame(this.animationFrameId);
|
1184
|
+
this.animationFrameId = null;
|
1185
|
+
}
|
1186
|
+
}
|
1187
|
+
animate = () => {
|
1188
|
+
const currentTime = Date.now();
|
1189
|
+
const deltaTime = currentTime - this.lastUpdateTime;
|
1190
|
+
this.lastUpdateTime = currentTime;
|
1191
|
+
this.setText((currentText) => {
|
1192
|
+
const targetText = this.targetText;
|
1193
|
+
if (currentText === targetText) {
|
1194
|
+
this.animationFrameId = null;
|
1195
|
+
return currentText;
|
1196
|
+
}
|
1197
|
+
const remainingChars = targetText.length - currentText.length;
|
1198
|
+
const charsToAdd = Math.max(
|
1199
|
+
1,
|
1200
|
+
Math.floor(
|
1201
|
+
remainingChars * (1 - Math.pow(this.decayFactor, deltaTime))
|
1202
|
+
)
|
1203
|
+
);
|
1204
|
+
const newText = targetText.slice(0, currentText.length + charsToAdd);
|
1205
|
+
this.animationFrameId = requestAnimationFrame(this.animate);
|
1206
|
+
return newText;
|
1207
|
+
});
|
1208
|
+
};
|
1209
|
+
};
|
1210
|
+
var useSmooth = (text, smooth = false) => {
|
1211
|
+
const [displayedText, setDisplayedText] = useState5(text);
|
1212
|
+
const [animatorRef] = useState5(
|
1213
|
+
new TextStreamAnimator(setDisplayedText)
|
1214
|
+
);
|
1215
|
+
useEffect8(() => {
|
1216
|
+
if (!smooth) {
|
1217
|
+
animatorRef.stop();
|
1218
|
+
return;
|
1219
|
+
}
|
1220
|
+
if (!text.startsWith(animatorRef.targetText)) {
|
1221
|
+
setDisplayedText(text);
|
1222
|
+
animatorRef.targetText = text;
|
1223
|
+
animatorRef.stop();
|
1224
|
+
return;
|
1225
|
+
}
|
1226
|
+
animatorRef.targetText = text;
|
1227
|
+
animatorRef.start();
|
1228
|
+
}, [animatorRef, smooth, text]);
|
1229
|
+
useEffect8(() => {
|
1230
|
+
return () => {
|
1231
|
+
animatorRef.stop();
|
1232
|
+
};
|
1233
|
+
}, [animatorRef]);
|
1234
|
+
return smooth ? displayedText : text;
|
1235
|
+
};
|
1236
|
+
|
1237
|
+
// src/primitives/contentPart/ContentPartText.tsx
|
1164
1238
|
import { jsx as jsx14 } from "react/jsx-runtime";
|
1165
|
-
var ContentPartPrimitiveText = forwardRef7((
|
1239
|
+
var ContentPartPrimitiveText = forwardRef7(({ smooth, ...rest }, forwardedRef) => {
|
1166
1240
|
const {
|
1167
|
-
|
1168
|
-
|
1241
|
+
status,
|
1242
|
+
part: { text }
|
1169
1243
|
} = useContentPartText();
|
1170
|
-
|
1244
|
+
const smoothText = useSmooth(text, smooth);
|
1245
|
+
return /* @__PURE__ */ jsx14(Primitive4.span, { "data-status": status, ...rest, ref: forwardedRef, children: smoothText });
|
1171
1246
|
});
|
1172
1247
|
ContentPartPrimitiveText.displayName = "ContentPartPrimitive.Text";
|
1173
1248
|
|
@@ -1176,14 +1251,18 @@ import { Primitive as Primitive5 } from "@radix-ui/react-primitive";
|
|
1176
1251
|
import { forwardRef as forwardRef8 } from "react";
|
1177
1252
|
import { jsx as jsx15 } from "react/jsx-runtime";
|
1178
1253
|
var ContentPartPrimitiveImage = forwardRef8((props, forwardedRef) => {
|
1179
|
-
const
|
1254
|
+
const {
|
1255
|
+
part: { image }
|
1256
|
+
} = useContentPartImage();
|
1180
1257
|
return /* @__PURE__ */ jsx15(Primitive5.img, { src: image, ...props, ref: forwardedRef });
|
1181
1258
|
});
|
1182
1259
|
ContentPartPrimitiveImage.displayName = "ContentPartPrimitive.Image";
|
1183
1260
|
|
1184
1261
|
// src/primitives/contentPart/ContentPartDisplay.tsx
|
1185
1262
|
var ContentPartPrimitiveDisplay = () => {
|
1186
|
-
const
|
1263
|
+
const {
|
1264
|
+
part: { display }
|
1265
|
+
} = useContentPartDisplay();
|
1187
1266
|
return display ?? null;
|
1188
1267
|
};
|
1189
1268
|
ContentPartPrimitiveDisplay.displayName = "ContentPartPrimitive.Display";
|
@@ -1203,7 +1282,7 @@ import { jsx as jsx16, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
1203
1282
|
var defaultComponents = {
|
1204
1283
|
Text: () => /* @__PURE__ */ jsxs2("p", { style: { whiteSpace: "pre-line" }, children: [
|
1205
1284
|
/* @__PURE__ */ jsx16(ContentPartPrimitiveText, {}),
|
1206
|
-
/* @__PURE__ */ jsx16(ContentPartPrimitiveInProgress, { children: " \u25CF" })
|
1285
|
+
/* @__PURE__ */ jsx16(ContentPartPrimitiveInProgress, { children: /* @__PURE__ */ jsx16("span", { style: { fontFamily: "revert" }, children: " \u25CF" }) })
|
1207
1286
|
] }),
|
1208
1287
|
Image: () => /* @__PURE__ */ jsx16(ContentPartPrimitiveImage, {}),
|
1209
1288
|
UI: () => /* @__PURE__ */ jsx16(ContentPartPrimitiveDisplay, {}),
|
@@ -1329,7 +1408,7 @@ import { Slot } from "@radix-ui/react-slot";
|
|
1329
1408
|
import {
|
1330
1409
|
forwardRef as forwardRef11,
|
1331
1410
|
useCallback as useCallback15,
|
1332
|
-
useEffect as
|
1411
|
+
useEffect as useEffect9,
|
1333
1412
|
useRef as useRef4
|
1334
1413
|
} from "react";
|
1335
1414
|
import TextareaAutosize from "react-textarea-autosize";
|
@@ -1348,7 +1427,8 @@ var ComposerPrimitiveInput = forwardRef11(
|
|
1348
1427
|
const ref = useComposedRefs2(forwardedRef, textareaRef);
|
1349
1428
|
useEscapeKeydown((e) => {
|
1350
1429
|
const composer = useComposer.getState();
|
1351
|
-
if (composer.
|
1430
|
+
if (composer.canCancel) {
|
1431
|
+
composer.cancel();
|
1352
1432
|
e.preventDefault();
|
1353
1433
|
}
|
1354
1434
|
});
|
@@ -1372,7 +1452,7 @@ var ComposerPrimitiveInput = forwardRef11(
|
|
1372
1452
|
textareaRef.current.value.length
|
1373
1453
|
);
|
1374
1454
|
}, [autoFocusEnabled]);
|
1375
|
-
|
1455
|
+
useEffect9(() => focus(), [focus]);
|
1376
1456
|
useOnComposerFocus(() => {
|
1377
1457
|
if (type === "new") {
|
1378
1458
|
focus();
|
@@ -1533,11 +1613,11 @@ var useOnResizeContent = (callback) => {
|
|
1533
1613
|
|
1534
1614
|
// src/utils/hooks/useOnScrollToBottom.tsx
|
1535
1615
|
import { useCallbackRef as useCallbackRef3 } from "@radix-ui/react-use-callback-ref";
|
1536
|
-
import { useEffect as
|
1616
|
+
import { useEffect as useEffect10 } from "react";
|
1537
1617
|
var useOnScrollToBottom = (callback) => {
|
1538
1618
|
const callbackRef = useCallbackRef3(callback);
|
1539
1619
|
const { useViewport } = useThreadContext();
|
1540
|
-
|
1620
|
+
useEffect10(() => {
|
1541
1621
|
return useViewport.getState().onScrollToBottom(() => {
|
1542
1622
|
callbackRef();
|
1543
1623
|
});
|
@@ -1612,7 +1692,7 @@ ThreadPrimitiveViewport.displayName = "ThreadPrimitive.Viewport";
|
|
1612
1692
|
import { memo as memo3 } from "react";
|
1613
1693
|
|
1614
1694
|
// src/context/providers/MessageProvider.tsx
|
1615
|
-
import { useEffect as
|
1695
|
+
import { useEffect as useEffect11, useState as useState6 } from "react";
|
1616
1696
|
import { create as create12 } from "zustand";
|
1617
1697
|
|
1618
1698
|
// src/context/stores/EditComposer.ts
|
@@ -1622,20 +1702,19 @@ var makeEditComposerStore = ({
|
|
1622
1702
|
onSend
|
1623
1703
|
}) => create10()((set, get, store) => ({
|
1624
1704
|
...makeBaseComposer(set, get, store),
|
1705
|
+
canCancel: false,
|
1625
1706
|
isEditing: false,
|
1626
1707
|
edit: () => {
|
1627
1708
|
const value = onEdit();
|
1628
|
-
set({ isEditing: true, value });
|
1709
|
+
set({ isEditing: true, canCancel: true, value });
|
1629
1710
|
},
|
1630
1711
|
send: () => {
|
1631
1712
|
const value = get().value;
|
1632
|
-
set({ isEditing: false });
|
1713
|
+
set({ isEditing: false, canCancel: false });
|
1633
1714
|
onSend(value);
|
1634
1715
|
},
|
1635
1716
|
cancel: () => {
|
1636
|
-
|
1637
|
-
set({ isEditing: false });
|
1638
|
-
return true;
|
1717
|
+
set({ isEditing: false, canCancel: false });
|
1639
1718
|
}
|
1640
1719
|
}));
|
1641
1720
|
|
@@ -1675,7 +1754,7 @@ var syncMessage = (messages, getBranches, useMessage, messageIndex) => {
|
|
1675
1754
|
};
|
1676
1755
|
var useMessageContext2 = (messageIndex) => {
|
1677
1756
|
const { useThreadMessages, useThreadActions } = useThreadContext();
|
1678
|
-
const [context] =
|
1757
|
+
const [context] = useState6(() => {
|
1679
1758
|
const useMessage = create12(() => ({}));
|
1680
1759
|
const useMessageUtils = makeMessageUtilsStore();
|
1681
1760
|
const useEditComposer = makeEditComposerStore({
|
@@ -1712,7 +1791,7 @@ var useMessageContext2 = (messageIndex) => {
|
|
1712
1791
|
);
|
1713
1792
|
return { useMessage, useMessageUtils, useEditComposer };
|
1714
1793
|
});
|
1715
|
-
|
1794
|
+
useEffect11(() => {
|
1716
1795
|
return useThreadMessages.subscribe((thread) => {
|
1717
1796
|
syncMessage(
|
1718
1797
|
thread,
|
@@ -1756,9 +1835,9 @@ var ThreadMessageImpl = ({
|
|
1756
1835
|
};
|
1757
1836
|
var ThreadMessage = memo3(
|
1758
1837
|
ThreadMessageImpl,
|
1759
|
-
(prev, next) => prev.messageIndex === next.messageIndex && prev.components.UserMessage === next.components.UserMessage && prev.components.EditComposer === next.components.EditComposer && prev.components.AssistantMessage === next.components.AssistantMessage
|
1838
|
+
(prev, next) => prev.messageIndex === next.messageIndex && prev.components.Message === next.components.Message && prev.components.UserMessage === next.components.UserMessage && prev.components.EditComposer === next.components.EditComposer && prev.components.AssistantMessage === next.components.AssistantMessage
|
1760
1839
|
);
|
1761
|
-
var
|
1840
|
+
var ThreadPrimitiveMessagesImpl = ({
|
1762
1841
|
components
|
1763
1842
|
}) => {
|
1764
1843
|
const { useThreadMessages } = useThreadContext();
|
@@ -1776,7 +1855,11 @@ var ThreadPrimitiveMessages = ({
|
|
1776
1855
|
);
|
1777
1856
|
});
|
1778
1857
|
};
|
1779
|
-
|
1858
|
+
ThreadPrimitiveMessagesImpl.displayName = "ThreadPrimitive.Messages";
|
1859
|
+
var ThreadPrimitiveMessages = memo3(
|
1860
|
+
ThreadPrimitiveMessagesImpl,
|
1861
|
+
(prev, next) => prev.components?.Message === next.components?.Message && prev.components?.UserMessage === next.components?.UserMessage && prev.components?.EditComposer === next.components?.EditComposer && prev.components?.AssistantMessage === next.components?.AssistantMessage
|
1862
|
+
);
|
1780
1863
|
|
1781
1864
|
// src/primitives/thread/ThreadScrollToBottom.tsx
|
1782
1865
|
var ThreadPrimitiveScrollToBottom = createActionButton(
|
@@ -1791,7 +1874,7 @@ var ThreadPrimitiveSuggestion = createActionButton(
|
|
1791
1874
|
);
|
1792
1875
|
|
1793
1876
|
// src/runtime/local/useLocalRuntime.tsx
|
1794
|
-
import { useInsertionEffect as useInsertionEffect3, useState as
|
1877
|
+
import { useInsertionEffect as useInsertionEffect3, useState as useState7 } from "react";
|
1795
1878
|
|
1796
1879
|
// src/runtime/utils/idUtils.tsx
|
1797
1880
|
import { customAlphabet } from "nanoid/non-secure";
|
@@ -1960,6 +2043,9 @@ var BaseAssistantRuntime = class {
|
|
1960
2043
|
this._thread = _thread;
|
1961
2044
|
this._unsubscribe = this._thread.subscribe(this.subscriptionHandler);
|
1962
2045
|
}
|
2046
|
+
get capabilities() {
|
2047
|
+
return this._thread.capabilities;
|
2048
|
+
}
|
1963
2049
|
_unsubscribe;
|
1964
2050
|
get thread() {
|
1965
2051
|
return this._thread;
|
@@ -2032,6 +2118,12 @@ var LocalRuntime = class extends BaseAssistantRuntime {
|
|
2032
2118
|
);
|
2033
2119
|
}
|
2034
2120
|
};
|
2121
|
+
var CAPABILITIES = Object.freeze({
|
2122
|
+
edit: true,
|
2123
|
+
reload: true,
|
2124
|
+
cancel: true,
|
2125
|
+
copy: true
|
2126
|
+
});
|
2035
2127
|
var LocalThreadRuntime = class {
|
2036
2128
|
constructor(_configProviders, adapter) {
|
2037
2129
|
this._configProviders = _configProviders;
|
@@ -2040,6 +2132,7 @@ var LocalThreadRuntime = class {
|
|
2040
2132
|
_subscriptions = /* @__PURE__ */ new Set();
|
2041
2133
|
abortController = null;
|
2042
2134
|
repository = new MessageRepository();
|
2135
|
+
capabilities = CAPABILITIES;
|
2043
2136
|
get messages() {
|
2044
2137
|
return this.repository.getMessages();
|
2045
2138
|
}
|
@@ -2123,7 +2216,7 @@ var LocalThreadRuntime = class {
|
|
2123
2216
|
|
2124
2217
|
// src/runtime/local/useLocalRuntime.tsx
|
2125
2218
|
var useLocalRuntime = (adapter) => {
|
2126
|
-
const [runtime] =
|
2219
|
+
const [runtime] = useState7(() => new LocalRuntime(adapter));
|
2127
2220
|
useInsertionEffect3(() => {
|
2128
2221
|
runtime.adapter = adapter;
|
2129
2222
|
});
|
@@ -2135,7 +2228,8 @@ var internal_exports = {};
|
|
2135
2228
|
__export(internal_exports, {
|
2136
2229
|
BaseAssistantRuntime: () => BaseAssistantRuntime,
|
2137
2230
|
MessageRepository: () => MessageRepository,
|
2138
|
-
ProxyConfigProvider: () => ProxyConfigProvider
|
2231
|
+
ProxyConfigProvider: () => ProxyConfigProvider,
|
2232
|
+
useSmooth: () => useSmooth
|
2139
2233
|
});
|
2140
2234
|
export {
|
2141
2235
|
actionBar_exports as ActionBarPrimitive,
|