@meshagent/meshagent-tailwind 0.41.4 → 0.41.6
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/CHANGELOG.md +10 -0
- package/README.md +33 -0
- package/dist/cjs/chat/chat-thread.js +15 -10
- package/dist/cjs/chat/dataset-chat-thread.d.ts +4 -1
- package/dist/cjs/chat/dataset-chat-thread.js +130 -157
- package/dist/cjs/chat/multi-thread-view.d.ts +4 -1
- package/dist/cjs/chat/multi-thread-view.js +4 -0
- package/dist/cjs/chat/new-chat-thread.d.ts +4 -1
- package/dist/cjs/chat/new-chat-thread.js +43 -87
- package/dist/cjs/file-preview/file-preview.d.ts +6 -0
- package/dist/cjs/file-preview/file-preview.js +220 -0
- package/dist/cjs/meetings/camera-grid.d.ts +46 -0
- package/dist/cjs/meetings/camera-grid.js +435 -0
- package/dist/cjs/meetings/controls.d.ts +4 -2
- package/dist/cjs/meetings/controls.js +9 -3
- package/dist/cjs/meetings/lobby.d.ts +17 -0
- package/dist/cjs/meetings/lobby.js +595 -0
- package/dist/cjs/meetings/meeting-scope.d.ts +7 -6
- package/dist/cjs/meetings/meeting-scope.js +64 -15
- package/dist/cjs/meetings/meeting-view.d.ts +6 -0
- package/dist/cjs/meetings/meeting-view.js +635 -0
- package/dist/cjs/meetings/meetings.d.ts +3 -0
- package/dist/cjs/meetings/meetings.js +3 -0
- package/dist/cjs/meetings/wake-lock.js +2 -2
- package/dist/esm/chat/chat-thread.js +15 -10
- package/dist/esm/chat/dataset-chat-thread.d.ts +4 -1
- package/dist/esm/chat/dataset-chat-thread.js +129 -133
- package/dist/esm/chat/multi-thread-view.d.ts +4 -1
- package/dist/esm/chat/multi-thread-view.js +4 -0
- package/dist/esm/chat/new-chat-thread.d.ts +4 -1
- package/dist/esm/chat/new-chat-thread.js +43 -87
- package/dist/esm/file-preview/file-preview.d.ts +6 -0
- package/dist/esm/file-preview/file-preview.js +220 -0
- package/dist/esm/meetings/camera-grid.d.ts +46 -0
- package/dist/esm/meetings/camera-grid.js +405 -0
- package/dist/esm/meetings/controls.d.ts +4 -2
- package/dist/esm/meetings/controls.js +9 -3
- package/dist/esm/meetings/lobby.d.ts +17 -0
- package/dist/esm/meetings/lobby.js +595 -0
- package/dist/esm/meetings/meeting-scope.d.ts +7 -6
- package/dist/esm/meetings/meeting-scope.js +71 -16
- package/dist/esm/meetings/meeting-view.d.ts +6 -0
- package/dist/esm/meetings/meeting-view.js +630 -0
- package/dist/esm/meetings/meetings.d.ts +3 -0
- package/dist/esm/meetings/meetings.js +3 -0
- package/dist/esm/meetings/wake-lock.js +2 -2
- package/dist/index.css +1 -1
- package/package.json +9 -5
|
@@ -225,7 +225,7 @@ function MarkdownBlock({ text }) {
|
|
|
225
225
|
children
|
|
226
226
|
}
|
|
227
227
|
),
|
|
228
|
-
p: ({ children, ...props }) => /* @__PURE__ */ jsx("p", { ...props, className: "mb-2 last:mb-0", children }),
|
|
228
|
+
p: ({ children, ...props }) => /* @__PURE__ */ jsx("p", { ...props, className: "mb-2 last:mb-0 overflow-hidden max-w-full", children }),
|
|
229
229
|
table: ({ children, ...props }) => /* @__PURE__ */ jsx("div", { className: "my-4 w-full overflow-x-auto", children: /* @__PURE__ */ jsx(
|
|
230
230
|
"table",
|
|
231
231
|
{
|
|
@@ -265,6 +265,17 @@ function MarkdownBlock({ text }) {
|
|
|
265
265
|
className: "mb-2 ml-6 list-decimal last:mb-0",
|
|
266
266
|
children
|
|
267
267
|
}
|
|
268
|
+
),
|
|
269
|
+
a: ({ children, href, ...props }) => /* @__PURE__ */ jsx(
|
|
270
|
+
"a",
|
|
271
|
+
{
|
|
272
|
+
...props,
|
|
273
|
+
href,
|
|
274
|
+
target: "_blank",
|
|
275
|
+
rel: "noopener noreferrer",
|
|
276
|
+
className: "text-primary underline overflow-ellipsis inline-block max-w-full overflow-x-hidden",
|
|
277
|
+
children
|
|
278
|
+
}
|
|
268
279
|
)
|
|
269
280
|
},
|
|
270
281
|
children: text
|
|
@@ -360,10 +371,7 @@ function ThreadAttachment({ room, attachment, onImageSettled }) {
|
|
|
360
371
|
}
|
|
361
372
|
return /* @__PURE__ */ jsx(FileAttachment, { room, path });
|
|
362
373
|
}
|
|
363
|
-
function ChatBubble({
|
|
364
|
-
text,
|
|
365
|
-
mine
|
|
366
|
-
}) {
|
|
374
|
+
function ChatBubble({ text, mine }) {
|
|
367
375
|
if (text.trim() === "") {
|
|
368
376
|
return null;
|
|
369
377
|
}
|
|
@@ -371,7 +379,7 @@ function ChatBubble({
|
|
|
371
379
|
"div",
|
|
372
380
|
{
|
|
373
381
|
className: cn(
|
|
374
|
-
"w-fit max-w-[85%] rounded-md px-4 py-3 text-sm leading-6 shadow-xs sm:
|
|
382
|
+
"w-fit max-w-[85%] rounded-md px-4 py-3 text-sm leading-6 shadow-xs sm:w-2xl",
|
|
375
383
|
mine ? "bg-secondary/85 text-foreground" : "bg-muted/70 text-foreground"
|
|
376
384
|
),
|
|
377
385
|
children: /* @__PURE__ */ jsx(MarkdownBlock, { text })
|
|
@@ -440,10 +448,7 @@ function defaultEventHeadline(kind, state, eventName) {
|
|
|
440
448
|
}
|
|
441
449
|
return eventName.replace(/[._]/gu, " ");
|
|
442
450
|
}
|
|
443
|
-
function EventRow({
|
|
444
|
-
room,
|
|
445
|
-
message
|
|
446
|
-
}) {
|
|
451
|
+
function EventRow({ room, message }) {
|
|
447
452
|
const method = getTrimmedStringAttribute(message, "method") || "agent/event";
|
|
448
453
|
const eventName = getTrimmedStringAttribute(message, "name") || getTrimmedStringAttribute(message, "event_type") || method.replace(/\//gu, ".");
|
|
449
454
|
const kind = getTrimmedStringAttribute(message, "kind").toLowerCase();
|
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
import type { ReactElement } from "react";
|
|
2
2
|
import type { RoomClient } from "@meshagent/meshagent";
|
|
3
|
+
import type { BaseChatClient } from "@meshagent/meshagent-agents";
|
|
3
4
|
export interface DatasetChatThreadProps {
|
|
4
5
|
room: RoomClient;
|
|
5
6
|
path: string;
|
|
7
|
+
chatClient?: BaseChatClient;
|
|
8
|
+
disposeChatClient?: boolean;
|
|
6
9
|
agentName?: string;
|
|
7
10
|
emptyStateTitle?: string;
|
|
8
11
|
emptyStateDescription?: string;
|
|
@@ -10,4 +13,4 @@ export interface DatasetChatThreadProps {
|
|
|
10
13
|
initialShowCompletedToolCalls?: boolean;
|
|
11
14
|
openFile?: (path: string) => void | Promise<void>;
|
|
12
15
|
}
|
|
13
|
-
export declare function DatasetChatThread({ room, path, agentName, emptyStateTitle, emptyStateDescription, inputPlaceholder, initialShowCompletedToolCalls, openFile, }: DatasetChatThreadProps): ReactElement;
|
|
16
|
+
export declare function DatasetChatThread({ room, path, chatClient, disposeChatClient, agentName, emptyStateTitle, emptyStateDescription, inputPlaceholder, initialShowCompletedToolCalls, openFile, }: DatasetChatThreadProps): ReactElement;
|
|
@@ -3,10 +3,33 @@ import { useCallback, useEffect, useMemo, useRef, useState } from "react";
|
|
|
3
3
|
import {
|
|
4
4
|
DatasetJson,
|
|
5
5
|
DatasetStruct,
|
|
6
|
-
RoomMessageEvent,
|
|
7
6
|
RoomServerException
|
|
8
7
|
} from "@meshagent/meshagent";
|
|
9
|
-
import {
|
|
8
|
+
import {
|
|
9
|
+
MessagingChatClient,
|
|
10
|
+
agentFileContentDeltaType,
|
|
11
|
+
agentFileContentEndedType,
|
|
12
|
+
agentFileContentStartedType,
|
|
13
|
+
agentImageGenerationCompletedType,
|
|
14
|
+
agentImageGenerationFailedType,
|
|
15
|
+
agentImageGenerationPartialType,
|
|
16
|
+
agentImageGenerationStartedType,
|
|
17
|
+
agentReasoningContentDeltaType,
|
|
18
|
+
agentReasoningContentEndedType,
|
|
19
|
+
agentReasoningContentStartedType,
|
|
20
|
+
agentTextContentDeltaType,
|
|
21
|
+
agentTextContentEndedType,
|
|
22
|
+
agentToolCallEndedType,
|
|
23
|
+
agentToolCallInProgressType,
|
|
24
|
+
agentToolCallPendingType,
|
|
25
|
+
agentToolCallStartedType,
|
|
26
|
+
agentTurnStartAcceptedType,
|
|
27
|
+
agentTurnStartRejectedType,
|
|
28
|
+
agentTurnStartedType,
|
|
29
|
+
agentTurnSteerAcceptedType,
|
|
30
|
+
agentTurnSteerRejectedType,
|
|
31
|
+
agentTurnSteeredType
|
|
32
|
+
} from "@meshagent/meshagent-agents";
|
|
10
33
|
import { Download, FileText, ImageOff } from "lucide-react";
|
|
11
34
|
import ReactMarkdown from "react-markdown";
|
|
12
35
|
import rehypeHighlight from "rehype-highlight";
|
|
@@ -17,37 +40,9 @@ import { ChatTypingIndicator } from "./chat-typing-indicator";
|
|
|
17
40
|
import { Button } from "../components/ui/button";
|
|
18
41
|
import { Spinner } from "../components/ui/spinner";
|
|
19
42
|
import { MeshagentFileUpload, fileToAsyncIterable } from "./file-attachment";
|
|
20
|
-
import { useThreadStatus } from "./chat-hooks";
|
|
43
|
+
import { PendingAgentMessage, useThreadStatus } from "./chat-hooks";
|
|
21
44
|
import { cn } from "../lib/utils";
|
|
22
45
|
import { timeAgo } from "./chat-thread";
|
|
23
|
-
const agentRoomMessageType = "agent-message";
|
|
24
|
-
const agentTurnStartType = "meshagent.agent.turn.start";
|
|
25
|
-
const agentTurnSteerType = "meshagent.agent.turn.steer";
|
|
26
|
-
const agentTurnInterruptType = "meshagent.agent.turn.interrupt";
|
|
27
|
-
const agentThreadOpenType = "meshagent.agent.thread.open";
|
|
28
|
-
const agentThreadCloseType = "meshagent.agent.thread.close";
|
|
29
|
-
const agentTurnStartAcceptedType = "meshagent.agent.turn.start.accepted";
|
|
30
|
-
const agentTurnStartRejectedType = "meshagent.agent.turn.start.rejected";
|
|
31
|
-
const agentTurnSteerAcceptedType = "meshagent.agent.turn.steer.accepted";
|
|
32
|
-
const agentTurnSteerRejectedType = "meshagent.agent.turn.steer.rejected";
|
|
33
|
-
const agentTurnStartedType = "meshagent.agent.turn.started";
|
|
34
|
-
const agentTurnSteeredType = "meshagent.agent.turn.steered";
|
|
35
|
-
const agentTextContentDeltaType = "meshagent.agent.text_content.delta";
|
|
36
|
-
const agentTextContentEndedType = "meshagent.agent.text_content.ended";
|
|
37
|
-
const agentReasoningContentStartedType = "meshagent.agent.reasoning_content.started";
|
|
38
|
-
const agentReasoningContentDeltaType = "meshagent.agent.reasoning_content.delta";
|
|
39
|
-
const agentReasoningContentEndedType = "meshagent.agent.reasoning_content.ended";
|
|
40
|
-
const agentFileContentStartedType = "meshagent.agent.file_content.started";
|
|
41
|
-
const agentFileContentDeltaType = "meshagent.agent.file_content.delta";
|
|
42
|
-
const agentFileContentEndedType = "meshagent.agent.file_content.ended";
|
|
43
|
-
const agentToolCallPendingType = "meshagent.agent.tool_call.pending";
|
|
44
|
-
const agentToolCallInProgressType = "meshagent.agent.tool_call.in_progress";
|
|
45
|
-
const agentToolCallStartedType = "meshagent.agent.tool_call.started";
|
|
46
|
-
const agentToolCallEndedType = "meshagent.agent.tool_call.ended";
|
|
47
|
-
const agentImageGenerationStartedType = "meshagent.agent.image_generation.started";
|
|
48
|
-
const agentImageGenerationPartialType = "meshagent.agent.image_generation.partial";
|
|
49
|
-
const agentImageGenerationCompletedType = "meshagent.agent.image_generation.completed";
|
|
50
|
-
const agentImageGenerationFailedType = "meshagent.agent.image_generation.failed";
|
|
51
46
|
const stickyBottomThresholdPx = 24;
|
|
52
47
|
const maxPreviewEdgePx = 312.5;
|
|
53
48
|
function createDatasetThreadModel() {
|
|
@@ -991,6 +986,26 @@ function describeError(error) {
|
|
|
991
986
|
}
|
|
992
987
|
return String(error);
|
|
993
988
|
}
|
|
989
|
+
function pendingAgentMessageFromInput(pending) {
|
|
990
|
+
const payload = pending.payload.toJson();
|
|
991
|
+
const parsed = PendingAgentMessage.fromQueueJson({
|
|
992
|
+
...payload,
|
|
993
|
+
message_type: pending.messageType,
|
|
994
|
+
created_at: pending.createdAt.toISOString()
|
|
995
|
+
});
|
|
996
|
+
return new PendingAgentMessage({
|
|
997
|
+
messageId: parsed.messageId,
|
|
998
|
+
messageType: parsed.messageType,
|
|
999
|
+
threadPath: parsed.threadPath,
|
|
1000
|
+
text: parsed.text,
|
|
1001
|
+
attachments: parsed.attachments,
|
|
1002
|
+
senderName: parsed.senderName,
|
|
1003
|
+
createdAt: parsed.createdAt,
|
|
1004
|
+
matchByContentOnly: parsed.matchByContentOnly,
|
|
1005
|
+
awaitingAcceptance: pending.awaitingAcceptance,
|
|
1006
|
+
awaitingOnline: pending.awaitingOnline
|
|
1007
|
+
});
|
|
1008
|
+
}
|
|
994
1009
|
function MarkdownBlock({ text }) {
|
|
995
1010
|
return /* @__PURE__ */ jsx(
|
|
996
1011
|
ReactMarkdown,
|
|
@@ -1407,24 +1422,11 @@ function EmptyState({
|
|
|
1407
1422
|
function ErrorBanner({ message }) {
|
|
1408
1423
|
return /* @__PURE__ */ jsx("div", { className: "mx-auto w-full max-w-[912px] whitespace-pre-wrap rounded-md border border-destructive/30 bg-destructive/5 px-4 py-3 text-sm text-destructive", children: message });
|
|
1409
1424
|
}
|
|
1410
|
-
function sendThreadSubscriptionMessage({
|
|
1411
|
-
room,
|
|
1412
|
-
agent,
|
|
1413
|
-
messageType,
|
|
1414
|
-
path
|
|
1415
|
-
}) {
|
|
1416
|
-
void room.messaging.sendMessage({
|
|
1417
|
-
to: agent,
|
|
1418
|
-
type: agentRoomMessageType,
|
|
1419
|
-
ignoreOffline: true,
|
|
1420
|
-
message: {
|
|
1421
|
-
payload: { type: messageType, thread_id: path }
|
|
1422
|
-
}
|
|
1423
|
-
}).catch(() => void 0);
|
|
1424
|
-
}
|
|
1425
1425
|
function DatasetChatThread({
|
|
1426
1426
|
room,
|
|
1427
1427
|
path,
|
|
1428
|
+
chatClient,
|
|
1429
|
+
disposeChatClient = false,
|
|
1428
1430
|
agentName,
|
|
1429
1431
|
emptyStateTitle,
|
|
1430
1432
|
emptyStateDescription,
|
|
@@ -1438,14 +1440,35 @@ function DatasetChatThread({
|
|
|
1438
1440
|
const [sendError, setSendError] = useState(null);
|
|
1439
1441
|
const [showCompletedToolCalls, setShowCompletedToolCalls] = useState(initialShowCompletedToolCalls);
|
|
1440
1442
|
const status = useThreadStatus({ room, path, agentName });
|
|
1441
|
-
const agentParticipant = findAgentParticipant(room, agentName);
|
|
1442
1443
|
const localParticipantName = getParticipantName(room.localParticipant);
|
|
1443
1444
|
const scrollContainerRef = useRef(null);
|
|
1444
1445
|
const contentRef = useRef(null);
|
|
1445
1446
|
const stickToBottomRef = useRef(true);
|
|
1447
|
+
const threadSessionRef = useRef(null);
|
|
1448
|
+
const threadSessionCursorRef = useRef(0);
|
|
1449
|
+
const [threadSessionVersion, setThreadSessionVersion] = useState(0);
|
|
1450
|
+
const ownsChatClient = chatClient == null;
|
|
1451
|
+
const activeChatClient = useMemo(
|
|
1452
|
+
() => chatClient ?? new MessagingChatClient({ room, agentName }),
|
|
1453
|
+
[agentName, chatClient, room]
|
|
1454
|
+
);
|
|
1455
|
+
const agentParticipant = activeChatClient.agentParticipant() ?? findAgentParticipant(room, agentName);
|
|
1446
1456
|
const bumpModelVersion = useCallback(() => {
|
|
1447
1457
|
setModelVersion((current) => current + 1);
|
|
1448
1458
|
}, []);
|
|
1459
|
+
useEffect(() => {
|
|
1460
|
+
void activeChatClient.start();
|
|
1461
|
+
const handleChange = () => {
|
|
1462
|
+
setThreadSessionVersion((current) => current + 1);
|
|
1463
|
+
};
|
|
1464
|
+
activeChatClient.addListener(handleChange);
|
|
1465
|
+
return () => {
|
|
1466
|
+
activeChatClient.removeListener(handleChange);
|
|
1467
|
+
if (ownsChatClient || disposeChatClient) {
|
|
1468
|
+
void activeChatClient.stop();
|
|
1469
|
+
}
|
|
1470
|
+
};
|
|
1471
|
+
}, [activeChatClient, disposeChatClient, ownsChatClient]);
|
|
1449
1472
|
useEffect(() => {
|
|
1450
1473
|
const model2 = createDatasetThreadModel();
|
|
1451
1474
|
modelRef.current = model2;
|
|
@@ -1523,46 +1546,41 @@ function DatasetChatThread({
|
|
|
1523
1546
|
};
|
|
1524
1547
|
}, [bumpModelVersion, path, room]);
|
|
1525
1548
|
useEffect(() => {
|
|
1526
|
-
|
|
1527
|
-
|
|
1528
|
-
|
|
1529
|
-
|
|
1530
|
-
|
|
1531
|
-
|
|
1532
|
-
|
|
1533
|
-
|
|
1534
|
-
|
|
1535
|
-
|
|
1536
|
-
|
|
1537
|
-
|
|
1538
|
-
|
|
1539
|
-
|
|
1549
|
+
if (isTmpThreadPath(path)) {
|
|
1550
|
+
threadSessionRef.current = null;
|
|
1551
|
+
threadSessionCursorRef.current = 0;
|
|
1552
|
+
setThreadSessionVersion((current) => current + 1);
|
|
1553
|
+
return;
|
|
1554
|
+
}
|
|
1555
|
+
const session = activeChatClient.openThread(path);
|
|
1556
|
+
threadSessionRef.current = session;
|
|
1557
|
+
threadSessionCursorRef.current = 0;
|
|
1558
|
+
const drainSessionMessages = () => {
|
|
1559
|
+
let changed = false;
|
|
1560
|
+
const messages = session.messages;
|
|
1561
|
+
while (threadSessionCursorRef.current < messages.length) {
|
|
1562
|
+
const event = messages[threadSessionCursorRef.current];
|
|
1563
|
+
threadSessionCursorRef.current += 1;
|
|
1564
|
+
if (applyAgentMessagePayload(modelRef.current, event.payload, path)) {
|
|
1565
|
+
changed = true;
|
|
1540
1566
|
}
|
|
1541
1567
|
}
|
|
1542
|
-
|
|
1543
|
-
|
|
1544
|
-
|
|
1568
|
+
if (changed) {
|
|
1569
|
+
bumpModelVersion();
|
|
1570
|
+
}
|
|
1571
|
+
setThreadSessionVersion((current) => current + 1);
|
|
1545
1572
|
};
|
|
1546
|
-
|
|
1547
|
-
|
|
1548
|
-
if (!agentParticipant) {
|
|
1549
|
-
return;
|
|
1550
|
-
}
|
|
1551
|
-
sendThreadSubscriptionMessage({
|
|
1552
|
-
room,
|
|
1553
|
-
agent: agentParticipant,
|
|
1554
|
-
messageType: agentThreadOpenType,
|
|
1555
|
-
path
|
|
1556
|
-
});
|
|
1573
|
+
session.addListener(drainSessionMessages);
|
|
1574
|
+
drainSessionMessages();
|
|
1557
1575
|
return () => {
|
|
1558
|
-
|
|
1559
|
-
|
|
1560
|
-
|
|
1561
|
-
|
|
1562
|
-
|
|
1563
|
-
|
|
1576
|
+
session.removeListener(drainSessionMessages);
|
|
1577
|
+
if (threadSessionRef.current === session) {
|
|
1578
|
+
threadSessionRef.current = null;
|
|
1579
|
+
threadSessionCursorRef.current = 0;
|
|
1580
|
+
}
|
|
1581
|
+
void session.close().catch(() => void 0);
|
|
1564
1582
|
};
|
|
1565
|
-
}, [
|
|
1583
|
+
}, [activeChatClient, bumpModelVersion, path]);
|
|
1566
1584
|
const allMessages = useMemo(() => {
|
|
1567
1585
|
const model2 = modelRef.current;
|
|
1568
1586
|
const mergedRowsByItemId = /* @__PURE__ */ new Map();
|
|
@@ -1587,29 +1605,24 @@ function DatasetChatThread({
|
|
|
1587
1605
|
for (const pending of status.pendingMessages) {
|
|
1588
1606
|
combined.set(pending.messageId, pending);
|
|
1589
1607
|
}
|
|
1608
|
+
for (const pending of threadSessionRef.current?.pendingInputs ?? []) {
|
|
1609
|
+
combined.set(pending.messageId, pendingAgentMessageFromInput(pending));
|
|
1610
|
+
}
|
|
1590
1611
|
const values = Array.from(combined.values()).filter((pending) => !allMessages.some((message) => datasetThreadMessageMatchesPendingAgentMessage(message, pending)));
|
|
1591
1612
|
return [
|
|
1592
1613
|
...values.filter((message) => !message.awaitingAcceptance),
|
|
1593
1614
|
...values.filter((message) => message.awaitingAcceptance)
|
|
1594
1615
|
];
|
|
1595
|
-
}, [allMessages, status.pendingMessages]);
|
|
1596
|
-
const canInterruptActiveTurn = status.
|
|
1616
|
+
}, [allMessages, status.pendingMessages, threadSessionVersion]);
|
|
1617
|
+
const canInterruptActiveTurn = status.turnId != null && (status.supportsAgentMessages || agentParticipant != null || chatClient != null);
|
|
1597
1618
|
const cancelTurn = useCallback(async () => {
|
|
1598
|
-
|
|
1619
|
+
const turnId = status.turnId?.trim();
|
|
1620
|
+
const session = threadSessionRef.current;
|
|
1621
|
+
if (!turnId || session == null) {
|
|
1599
1622
|
return;
|
|
1600
1623
|
}
|
|
1601
|
-
await
|
|
1602
|
-
|
|
1603
|
-
type: agentRoomMessageType,
|
|
1604
|
-
message: {
|
|
1605
|
-
payload: {
|
|
1606
|
-
type: agentTurnInterruptType,
|
|
1607
|
-
thread_id: path,
|
|
1608
|
-
turn_id: status.turnId
|
|
1609
|
-
}
|
|
1610
|
-
}
|
|
1611
|
-
});
|
|
1612
|
-
}, [agentParticipant, path, room, status.turnId]);
|
|
1624
|
+
await session.interruptTurn(turnId);
|
|
1625
|
+
}, [status.turnId, threadSessionVersion]);
|
|
1613
1626
|
const selectAttachments = useCallback((files) => {
|
|
1614
1627
|
const nextAttachments = files.map((file) => new MeshagentFileUpload(
|
|
1615
1628
|
room,
|
|
@@ -1623,56 +1636,39 @@ function DatasetChatThread({
|
|
|
1623
1636
|
if (message.text.trim() === "" && message.attachments.length === 0) {
|
|
1624
1637
|
return;
|
|
1625
1638
|
}
|
|
1626
|
-
if (!agentParticipant) {
|
|
1639
|
+
if (!agentParticipant && chatClient == null) {
|
|
1627
1640
|
setSendError("This thread requires an online agent that supports agent messages.");
|
|
1628
1641
|
return;
|
|
1629
1642
|
}
|
|
1643
|
+
const session = threadSessionRef.current;
|
|
1644
|
+
if (session == null) {
|
|
1645
|
+
setSendError("No thread session is open.");
|
|
1646
|
+
return;
|
|
1647
|
+
}
|
|
1630
1648
|
const isSteer = status.mode === "steerable" && status.turnId != null;
|
|
1631
1649
|
const normalizedAttachments = message.attachments.map(normalizeAgentAttachmentUrl).filter((attachment) => attachment !== null);
|
|
1632
1650
|
const senderName = localParticipantName.trim() || void 0;
|
|
1633
|
-
upsertAgentRow({
|
|
1634
|
-
model: modelRef.current,
|
|
1635
|
-
itemId: message.id,
|
|
1636
|
-
turnId: null,
|
|
1637
|
-
timestamp: /* @__PURE__ */ new Date(),
|
|
1638
|
-
data: {
|
|
1639
|
-
kind: "message",
|
|
1640
|
-
role: "user",
|
|
1641
|
-
text: message.text,
|
|
1642
|
-
sender_name: senderName,
|
|
1643
|
-
attachments: normalizedAttachments
|
|
1644
|
-
}
|
|
1645
|
-
});
|
|
1646
|
-
bumpModelVersion();
|
|
1647
1651
|
try {
|
|
1648
|
-
|
|
1649
|
-
|
|
1650
|
-
|
|
1651
|
-
|
|
1652
|
-
|
|
1653
|
-
|
|
1654
|
-
|
|
1655
|
-
payload.turn_id = status.turnId;
|
|
1656
|
-
}
|
|
1657
|
-
await room.messaging.sendMessage({
|
|
1658
|
-
to: agentParticipant,
|
|
1659
|
-
type: agentRoomMessageType,
|
|
1660
|
-
message: { payload }
|
|
1652
|
+
await session.sendText({
|
|
1653
|
+
messageId: message.id,
|
|
1654
|
+
text: message.text,
|
|
1655
|
+
attachments: normalizedAttachments,
|
|
1656
|
+
steer: isSteer,
|
|
1657
|
+
turnId: status.turnId,
|
|
1658
|
+
senderName
|
|
1661
1659
|
});
|
|
1662
1660
|
setSendError(null);
|
|
1661
|
+
setThreadSessionVersion((current) => current + 1);
|
|
1663
1662
|
} catch (error) {
|
|
1664
|
-
modelRef.current.agentRowsByItemId.delete(message.id);
|
|
1665
|
-
bumpModelVersion();
|
|
1666
1663
|
setSendError(describeError(error));
|
|
1667
1664
|
}
|
|
1668
1665
|
}, [
|
|
1669
1666
|
agentParticipant,
|
|
1670
|
-
|
|
1667
|
+
chatClient,
|
|
1671
1668
|
localParticipantName,
|
|
1672
|
-
path,
|
|
1673
|
-
room,
|
|
1674
1669
|
status.mode,
|
|
1675
|
-
status.turnId
|
|
1670
|
+
status.turnId,
|
|
1671
|
+
threadSessionVersion
|
|
1676
1672
|
]);
|
|
1677
1673
|
const hasWireBackedContent = modelRef.current.agentRowsByItemId.size > 0 || status.pendingMessages.length > 0 || pendingMessages.length > 0;
|
|
1678
1674
|
const model = modelRef.current;
|
|
@@ -1804,8 +1800,8 @@ function DatasetChatThread({
|
|
|
1804
1800
|
attachments,
|
|
1805
1801
|
onFilesSelected: selectAttachments,
|
|
1806
1802
|
setAttachments,
|
|
1807
|
-
disabled: agentParticipant == null,
|
|
1808
|
-
placeholder: inputPlaceholder ?? (agentParticipant ? "Type a message" : `Waiting for ${displayParticipantName(agentName ?? "agent")}`)
|
|
1803
|
+
disabled: agentParticipant == null && chatClient == null,
|
|
1804
|
+
placeholder: inputPlaceholder ?? (agentParticipant || chatClient ? "Type a message" : `Waiting for ${displayParticipantName(agentName ?? "agent")}`)
|
|
1809
1805
|
}
|
|
1810
1806
|
)
|
|
1811
1807
|
] });
|
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
import type { ReactElement } from "react";
|
|
2
2
|
import { RoomClient } from "@meshagent/meshagent";
|
|
3
|
+
import type { BaseChatClient } from "@meshagent/meshagent-agents";
|
|
3
4
|
export type MultiThreadContentBuilder = (threadPath: string) => ReactElement;
|
|
4
5
|
export interface MultiThreadViewProps {
|
|
5
6
|
room: RoomClient;
|
|
7
|
+
chatClient?: BaseChatClient;
|
|
8
|
+
disposeChatClient?: boolean;
|
|
6
9
|
agentName: string;
|
|
7
10
|
builder: MultiThreadContentBuilder;
|
|
8
11
|
toolkit?: string;
|
|
@@ -15,4 +18,4 @@ export interface MultiThreadViewProps {
|
|
|
15
18
|
emptyStateTitle?: string;
|
|
16
19
|
emptyStateDescription?: string;
|
|
17
20
|
}
|
|
18
|
-
export declare function MultiThreadView({ room, agentName, builder, toolkit, tool, selectedThreadPath, onSelectedThreadPathChanged, onSelectedThreadResolved, newThreadResetVersion, centerComposer, emptyStateTitle, emptyStateDescription, }: MultiThreadViewProps): ReactElement;
|
|
21
|
+
export declare function MultiThreadView({ room, chatClient, disposeChatClient, agentName, builder, toolkit, tool, selectedThreadPath, onSelectedThreadPathChanged, onSelectedThreadResolved, newThreadResetVersion, centerComposer, emptyStateTitle, emptyStateDescription, }: MultiThreadViewProps): ReactElement;
|
|
@@ -7,6 +7,8 @@ function normalizeSelectedThreadPath(path) {
|
|
|
7
7
|
}
|
|
8
8
|
function MultiThreadView({
|
|
9
9
|
room,
|
|
10
|
+
chatClient,
|
|
11
|
+
disposeChatClient = false,
|
|
10
12
|
agentName,
|
|
11
13
|
builder,
|
|
12
14
|
toolkit = "chat",
|
|
@@ -45,6 +47,8 @@ function MultiThreadView({
|
|
|
45
47
|
NewChatThread,
|
|
46
48
|
{
|
|
47
49
|
room,
|
|
50
|
+
chatClient,
|
|
51
|
+
disposeChatClient,
|
|
48
52
|
agentName,
|
|
49
53
|
builder,
|
|
50
54
|
toolkit,
|
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
import type { ReactElement } from "react";
|
|
2
2
|
import { RoomClient } from "@meshagent/meshagent";
|
|
3
|
+
import type { BaseChatClient } from "@meshagent/meshagent-agents";
|
|
3
4
|
export type NewChatThreadBuilder = (threadPath: string) => ReactElement;
|
|
4
5
|
export interface NewChatThreadProps {
|
|
5
6
|
room: RoomClient;
|
|
7
|
+
chatClient?: BaseChatClient;
|
|
8
|
+
disposeChatClient?: boolean;
|
|
6
9
|
agentName: string;
|
|
7
10
|
builder: NewChatThreadBuilder;
|
|
8
11
|
toolkit?: string;
|
|
@@ -14,4 +17,4 @@ export interface NewChatThreadProps {
|
|
|
14
17
|
emptyStateTitle?: string;
|
|
15
18
|
emptyStateDescription?: string;
|
|
16
19
|
}
|
|
17
|
-
export declare function NewChatThread({ room,
|
|
20
|
+
export declare function NewChatThread({ room, chatClient, disposeChatClient, agentName, builder, selectedThreadPath, onThreadPathChanged, onThreadResolved, centerComposer, emptyStateTitle, emptyStateDescription, }: NewChatThreadProps): ReactElement;
|