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