@assistant-ui/react 0.5.41 → 0.5.42
Sign up to get free protection for your applications and to get access to all the features.
- package/dist/index.d.mts +45 -35
- package/dist/index.d.ts +45 -35
- package/dist/index.js +117 -100
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +86 -69
- package/dist/index.mjs.map +1 -1
- package/dist/styles/index.css +27 -18
- package/dist/styles/index.css.map +1 -1
- package/dist/styles/tailwindcss/thread.css +4 -4
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
@@ -1072,54 +1072,6 @@ var useEdgeRuntime = ({
|
|
1072
1072
|
// src/runtimes/local/shouldContinue.tsx
|
1073
1073
|
var shouldContinue = (result) => result.status?.type === "requires-action" && result.status.reason === "tool-calls" && result.content.every((c) => c.type !== "tool-call" || !!c.result);
|
1074
1074
|
|
1075
|
-
// src/utils/getThreadMessageText.tsx
|
1076
|
-
var getThreadMessageText = (message) => {
|
1077
|
-
const textParts = message.content.filter(
|
1078
|
-
(part) => part.type === "text"
|
1079
|
-
);
|
1080
|
-
return textParts.map((part) => part.text).join("\n\n");
|
1081
|
-
};
|
1082
|
-
|
1083
|
-
// src/runtimes/speech/WebSpeechSynthesisAdapter.ts
|
1084
|
-
var WebSpeechSynthesisAdapter = class {
|
1085
|
-
speak(message) {
|
1086
|
-
const text = getThreadMessageText(message);
|
1087
|
-
const utterance = new SpeechSynthesisUtterance(text);
|
1088
|
-
let ended = false;
|
1089
|
-
const endHandlers = /* @__PURE__ */ new Set();
|
1090
|
-
const handleEnd = () => {
|
1091
|
-
if (ended) return;
|
1092
|
-
ended = true;
|
1093
|
-
endHandlers.forEach((handler) => handler());
|
1094
|
-
};
|
1095
|
-
utterance.addEventListener("end", handleEnd);
|
1096
|
-
utterance.addEventListener("error", handleEnd);
|
1097
|
-
window.speechSynthesis.speak(utterance);
|
1098
|
-
return {
|
1099
|
-
stop: () => {
|
1100
|
-
window.speechSynthesis.cancel();
|
1101
|
-
handleEnd();
|
1102
|
-
},
|
1103
|
-
onEnd: (callback) => {
|
1104
|
-
if (ended) {
|
1105
|
-
let cancelled = false;
|
1106
|
-
queueMicrotask(() => {
|
1107
|
-
if (!cancelled) callback();
|
1108
|
-
});
|
1109
|
-
return () => {
|
1110
|
-
cancelled = true;
|
1111
|
-
};
|
1112
|
-
} else {
|
1113
|
-
endHandlers.add(callback);
|
1114
|
-
return () => {
|
1115
|
-
endHandlers.delete(callback);
|
1116
|
-
};
|
1117
|
-
}
|
1118
|
-
}
|
1119
|
-
};
|
1120
|
-
}
|
1121
|
-
};
|
1122
|
-
|
1123
1075
|
// src/runtimes/local/LocalThreadRuntime.tsx
|
1124
1076
|
var LocalThreadRuntime = class {
|
1125
1077
|
constructor(configProvider, adapter, { initialMessages, ...options }) {
|
@@ -1158,6 +1110,9 @@ var LocalThreadRuntime = class {
|
|
1158
1110
|
}
|
1159
1111
|
};
|
1160
1112
|
_options;
|
1113
|
+
get options() {
|
1114
|
+
return this._options;
|
1115
|
+
}
|
1161
1116
|
set options({ initialMessages, ...options }) {
|
1162
1117
|
this._options = options;
|
1163
1118
|
const canSpeak = options.adapters?.speech !== void 0;
|
@@ -1239,7 +1194,7 @@ var LocalThreadRuntime = class {
|
|
1239
1194
|
this.repository.addOrUpdateMessage(parentId, message);
|
1240
1195
|
this.notifySubscribers();
|
1241
1196
|
};
|
1242
|
-
const maxToolRoundtrips = this.
|
1197
|
+
const maxToolRoundtrips = this.options.maxToolRoundtrips ?? 1;
|
1243
1198
|
const toolRoundtrips = message.metadata?.roundtrips?.length ?? 0;
|
1244
1199
|
if (toolRoundtrips > maxToolRoundtrips) {
|
1245
1200
|
updateMessage({
|
@@ -1334,10 +1289,24 @@ var LocalThreadRuntime = class {
|
|
1334
1289
|
this.performRoundtrip(parentId, message);
|
1335
1290
|
}
|
1336
1291
|
}
|
1292
|
+
// TODO lift utterance state to thread runtime
|
1293
|
+
_utterance;
|
1337
1294
|
speak(messageId) {
|
1295
|
+
const adapter = this.options.adapters?.speech;
|
1296
|
+
if (!adapter) throw new Error("Speech adapter not configured");
|
1338
1297
|
const { message } = this.repository.getMessage(messageId);
|
1339
|
-
|
1340
|
-
|
1298
|
+
if (this._utterance) {
|
1299
|
+
this._utterance.cancel();
|
1300
|
+
this._utterance = void 0;
|
1301
|
+
}
|
1302
|
+
const utterance = adapter.speak(message);
|
1303
|
+
utterance.onEnd(() => {
|
1304
|
+
if (this._utterance === utterance) {
|
1305
|
+
this._utterance = void 0;
|
1306
|
+
}
|
1307
|
+
});
|
1308
|
+
this._utterance = utterance;
|
1309
|
+
return this._utterance;
|
1341
1310
|
}
|
1342
1311
|
export() {
|
1343
1312
|
return this.repository.export();
|
@@ -1497,6 +1466,14 @@ var fromThreadMessageLike = (like, fallbackId, fallbackStatus) => {
|
|
1497
1466
|
}
|
1498
1467
|
};
|
1499
1468
|
|
1469
|
+
// src/utils/getThreadMessageText.tsx
|
1470
|
+
var getThreadMessageText = (message) => {
|
1471
|
+
const textParts = message.content.filter(
|
1472
|
+
(part) => part.type === "text"
|
1473
|
+
);
|
1474
|
+
return textParts.map((part) => part.text).join("\n\n");
|
1475
|
+
};
|
1476
|
+
|
1500
1477
|
// src/runtimes/external-store/ExternalStoreThreadRuntime.tsx
|
1501
1478
|
var hasUpcomingMessage = (isRunning, messages) => {
|
1502
1479
|
return isRunning && messages[messages.length - 1]?.role !== "assistant";
|
@@ -1743,6 +1720,47 @@ var useDangerousInBrowserRuntime = ({
|
|
1743
1720
|
return useLocalRuntime(adapter, { initialMessages });
|
1744
1721
|
};
|
1745
1722
|
|
1723
|
+
// src/runtimes/speech/WebSpeechSynthesisAdapter.ts
|
1724
|
+
var WebSpeechSynthesisAdapter = class {
|
1725
|
+
speak(message) {
|
1726
|
+
const text = getThreadMessageText(message);
|
1727
|
+
const utterance = new SpeechSynthesisUtterance(text);
|
1728
|
+
const endHandlers = /* @__PURE__ */ new Set();
|
1729
|
+
const handleEnd = (reason, error) => {
|
1730
|
+
if (res.status.type === "ended") return;
|
1731
|
+
res.status = { type: "ended", reason, error };
|
1732
|
+
endHandlers.forEach((handler) => handler());
|
1733
|
+
};
|
1734
|
+
utterance.addEventListener("end", () => handleEnd("finished"));
|
1735
|
+
utterance.addEventListener("error", (e) => handleEnd("error", e.error));
|
1736
|
+
window.speechSynthesis.speak(utterance);
|
1737
|
+
const res = {
|
1738
|
+
status: { type: "running" },
|
1739
|
+
cancel: () => {
|
1740
|
+
window.speechSynthesis.cancel();
|
1741
|
+
handleEnd("cancelled");
|
1742
|
+
},
|
1743
|
+
onEnd: (callback) => {
|
1744
|
+
if (res.status.type === "ended") {
|
1745
|
+
let cancelled = false;
|
1746
|
+
queueMicrotask(() => {
|
1747
|
+
if (!cancelled) callback();
|
1748
|
+
});
|
1749
|
+
return () => {
|
1750
|
+
cancelled = true;
|
1751
|
+
};
|
1752
|
+
} else {
|
1753
|
+
endHandlers.add(callback);
|
1754
|
+
return () => {
|
1755
|
+
endHandlers.delete(callback);
|
1756
|
+
};
|
1757
|
+
}
|
1758
|
+
}
|
1759
|
+
};
|
1760
|
+
return res;
|
1761
|
+
}
|
1762
|
+
};
|
1763
|
+
|
1746
1764
|
// src/context/providers/ThreadProvider.tsx
|
1747
1765
|
import { jsx as jsx6, jsxs as jsxs2 } from "react/jsx-runtime";
|
1748
1766
|
var ThreadProvider = ({
|
@@ -3335,7 +3353,7 @@ var makeMessageUtilsStore = () => create14((set) => {
|
|
3335
3353
|
},
|
3336
3354
|
isSpeaking: false,
|
3337
3355
|
stopSpeaking: () => {
|
3338
|
-
utterance?.
|
3356
|
+
utterance?.cancel();
|
3339
3357
|
},
|
3340
3358
|
addUtterance: (utt) => {
|
3341
3359
|
utterance = utt;
|
@@ -3537,28 +3555,29 @@ import {
|
|
3537
3555
|
StopCircleIcon
|
3538
3556
|
} from "lucide-react";
|
3539
3557
|
import { Fragment as Fragment4, jsx as jsx32, jsxs as jsxs5 } from "react/jsx-runtime";
|
3540
|
-
var useAllowCopy = () => {
|
3558
|
+
var useAllowCopy = (ensureCapability = false) => {
|
3541
3559
|
const { assistantMessage: { allowCopy = true } = {} } = useThreadConfig();
|
3542
3560
|
const { useThread } = useThreadContext();
|
3543
3561
|
const copySupported = useThread((t) => t.capabilities.unstable_copy);
|
3544
|
-
return
|
3562
|
+
return allowCopy && (!ensureCapability || copySupported);
|
3545
3563
|
};
|
3546
|
-
var useAllowSpeak = () => {
|
3564
|
+
var useAllowSpeak = (ensureCapability = false) => {
|
3547
3565
|
const { assistantMessage: { allowSpeak = true } = {} } = useThreadConfig();
|
3548
3566
|
const { useThread } = useThreadContext();
|
3549
3567
|
const speakSupported = useThread((t) => t.capabilities.speak);
|
3550
|
-
return
|
3568
|
+
return allowSpeak && (!ensureCapability || speakSupported);
|
3551
3569
|
};
|
3552
|
-
var useAllowReload = () => {
|
3570
|
+
var useAllowReload = (ensureCapability = false) => {
|
3553
3571
|
const { assistantMessage: { allowReload = true } = {} } = useThreadConfig();
|
3554
3572
|
const { useThread } = useThreadContext();
|
3555
3573
|
const reloadSupported = useThread((t) => t.capabilities.reload);
|
3556
|
-
return
|
3574
|
+
return allowReload && (!ensureCapability || reloadSupported);
|
3557
3575
|
};
|
3558
3576
|
var AssistantActionBar = () => {
|
3559
|
-
const allowCopy = useAllowCopy();
|
3560
|
-
const allowReload = useAllowReload();
|
3561
|
-
|
3577
|
+
const allowCopy = useAllowCopy(true);
|
3578
|
+
const allowReload = useAllowReload(true);
|
3579
|
+
const allowSpeak = useAllowSpeak(true);
|
3580
|
+
if (!allowCopy && !allowReload && !allowSpeak) return null;
|
3562
3581
|
return /* @__PURE__ */ jsxs5(
|
3563
3582
|
AssistantActionBarRoot,
|
3564
3583
|
{
|
@@ -3566,9 +3585,9 @@ var AssistantActionBar = () => {
|
|
3566
3585
|
autohide: "not-last",
|
3567
3586
|
autohideFloat: "single-branch",
|
3568
3587
|
children: [
|
3569
|
-
/* @__PURE__ */ jsx32(AssistantActionBarSpeechControl, {}),
|
3570
|
-
/* @__PURE__ */ jsx32(AssistantActionBarCopy, {}),
|
3571
|
-
/* @__PURE__ */ jsx32(AssistantActionBarReload, {})
|
3588
|
+
allowSpeak && /* @__PURE__ */ jsx32(AssistantActionBarSpeechControl, {}),
|
3589
|
+
allowCopy && /* @__PURE__ */ jsx32(AssistantActionBarCopy, {}),
|
3590
|
+
allowReload && /* @__PURE__ */ jsx32(AssistantActionBarReload, {})
|
3572
3591
|
]
|
3573
3592
|
}
|
3574
3593
|
);
|
@@ -3584,8 +3603,6 @@ var AssistantActionBarCopy = forwardRef20((props, ref) => {
|
|
3584
3603
|
assistantMessage: { copy: { tooltip = "Copy" } = {} } = {}
|
3585
3604
|
} = {}
|
3586
3605
|
} = useThreadConfig();
|
3587
|
-
const allowCopy = useAllowCopy();
|
3588
|
-
if (!allowCopy) return null;
|
3589
3606
|
return /* @__PURE__ */ jsx32(actionBar_exports.Copy, { asChild: true, children: /* @__PURE__ */ jsx32(TooltipIconButton, { tooltip, ...props, ref, children: props.children ?? /* @__PURE__ */ jsxs5(Fragment4, { children: [
|
3590
3607
|
/* @__PURE__ */ jsx32(message_exports.If, { copied: true, children: /* @__PURE__ */ jsx32(CheckIcon, {}) }),
|
3591
3608
|
/* @__PURE__ */ jsx32(message_exports.If, { copied: false, children: /* @__PURE__ */ jsx32(CopyIcon, {}) })
|
@@ -3979,14 +3996,14 @@ import { forwardRef as forwardRef26 } from "react";
|
|
3979
3996
|
import { forwardRef as forwardRef25 } from "react";
|
3980
3997
|
import { PencilIcon } from "lucide-react";
|
3981
3998
|
import { jsx as jsx40 } from "react/jsx-runtime";
|
3982
|
-
var useAllowEdit = () => {
|
3999
|
+
var useAllowEdit = (ensureCapability = false) => {
|
3983
4000
|
const { userMessage: { allowEdit = true } = {} } = useThreadConfig();
|
3984
4001
|
const { useThread } = useThreadContext();
|
3985
4002
|
const editSupported = useThread((t) => t.capabilities.edit);
|
3986
|
-
return
|
4003
|
+
return allowEdit && (!ensureCapability || editSupported);
|
3987
4004
|
};
|
3988
4005
|
var UserActionBar = () => {
|
3989
|
-
const allowEdit = useAllowEdit();
|
4006
|
+
const allowEdit = useAllowEdit(true);
|
3990
4007
|
if (!allowEdit) return null;
|
3991
4008
|
return /* @__PURE__ */ jsx40(UserActionBarRoot, { hideWhenRunning: true, autohide: "not-last", children: /* @__PURE__ */ jsx40(UserActionBarEdit, {}) });
|
3992
4009
|
};
|