@assistant-ui/react 0.5.41 → 0.5.42
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 +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
|
};
|