@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
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,13 @@
|
|
|
1
|
+
## [0.41.6]
|
|
2
|
+
- Added convenience dataset helpers and toolkit-config support to the TypeScript SDK, expanding room- and dataset-aware workflows.
|
|
3
|
+
- Extended the TypeScript storage client download URL API with an optional `download` flag so callers can request attachment-style links.
|
|
4
|
+
- Updated the TypeScript agent/chat packages to support room shell and room storage toolkits with richer threaded chat behavior.
|
|
5
|
+
- Improved Powerboards meetings with meeting previews, camera-grid handling, and video-chat collapse fixes.
|
|
6
|
+
- Added syntax-highlighted file previews to the React UI, including `react-syntax-highlighter@^16.1.1` and `@types/react-syntax-highlighter@^15.5.13`.
|
|
7
|
+
|
|
8
|
+
## [0.41.5]
|
|
9
|
+
- Stability
|
|
10
|
+
|
|
1
11
|
## [0.41.4]
|
|
2
12
|
- Stability
|
|
3
13
|
|
package/README.md
CHANGED
|
@@ -38,6 +38,39 @@ MeshAgent removes the infrastructure headaches of building and shipping AI Agent
|
|
|
38
38
|
|
|
39
39
|
Follow our [Getting Started Documentation](https://docs.meshagent.com/introduction/get_started) to setup your MeshAgent account, create your first project, and start building agents!
|
|
40
40
|
|
|
41
|
+
## Meetings
|
|
42
|
+
|
|
43
|
+
The meeting components use a connected `RoomClient` to request LiveKit credentials before joining a meeting. Wrap `MeetingView` in `MeetingScope` and pass the same room client used by the rest of your app:
|
|
44
|
+
|
|
45
|
+
```tsx
|
|
46
|
+
import { MeetingScope, MeetingView } from "@meshagent/meshagent-tailwind";
|
|
47
|
+
import type { RoomClient } from "@meshagent/meshagent";
|
|
48
|
+
|
|
49
|
+
export function MeetingPanel({ roomClient }: { roomClient: RoomClient }) {
|
|
50
|
+
return (
|
|
51
|
+
<MeetingScope client={roomClient}>
|
|
52
|
+
<MeetingView />
|
|
53
|
+
</MeetingScope>
|
|
54
|
+
);
|
|
55
|
+
}
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
`MeetingScope` configures its controller with `roomClient.livekit.getConnectionInfo({ breakoutRoom: "" })` and `MeetingView` uses that connection info when the user starts the main meeting. If you are building a custom meeting UI, request the connection info before calling LiveKit's `connect`:
|
|
59
|
+
|
|
60
|
+
```ts
|
|
61
|
+
import { Room } from "livekit-client";
|
|
62
|
+
import type { RoomClient } from "@meshagent/meshagent";
|
|
63
|
+
|
|
64
|
+
const livekitRoom = new Room();
|
|
65
|
+
const connectionInfo = await roomClient.livekit.getConnectionInfo({
|
|
66
|
+
breakoutRoom: "",
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
await livekitRoom.connect(connectionInfo.url, connectionInfo.token);
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
Pass a non-empty `breakoutRoom` to `MeetingScope` or `roomClient.livekit.getConnectionInfo({ breakoutRoom })` when the meeting should join a specific breakout room.
|
|
73
|
+
|
|
41
74
|
## Next Steps and Examples
|
|
42
75
|
|
|
43
76
|
To see examples of agents in action and to start building your own agents check out the MeshAgent docs at [docs.meshagent.com](https://docs.meshagent.com/)
|
|
@@ -259,7 +259,7 @@ function MarkdownBlock({ text }) {
|
|
|
259
259
|
children
|
|
260
260
|
}
|
|
261
261
|
),
|
|
262
|
-
p: ({ children, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { ...props, className: "mb-2 last:mb-0", children }),
|
|
262
|
+
p: ({ children, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { ...props, className: "mb-2 last:mb-0 overflow-hidden max-w-full", children }),
|
|
263
263
|
table: ({ children, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "my-4 w-full overflow-x-auto", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
264
264
|
"table",
|
|
265
265
|
{
|
|
@@ -299,6 +299,17 @@ function MarkdownBlock({ text }) {
|
|
|
299
299
|
className: "mb-2 ml-6 list-decimal last:mb-0",
|
|
300
300
|
children
|
|
301
301
|
}
|
|
302
|
+
),
|
|
303
|
+
a: ({ children, href, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
304
|
+
"a",
|
|
305
|
+
{
|
|
306
|
+
...props,
|
|
307
|
+
href,
|
|
308
|
+
target: "_blank",
|
|
309
|
+
rel: "noopener noreferrer",
|
|
310
|
+
className: "text-primary underline overflow-ellipsis inline-block max-w-full overflow-x-hidden",
|
|
311
|
+
children
|
|
312
|
+
}
|
|
302
313
|
)
|
|
303
314
|
},
|
|
304
315
|
children: text
|
|
@@ -394,10 +405,7 @@ function ThreadAttachment({ room, attachment, onImageSettled }) {
|
|
|
394
405
|
}
|
|
395
406
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(FileAttachment, { room, path });
|
|
396
407
|
}
|
|
397
|
-
function ChatBubble({
|
|
398
|
-
text,
|
|
399
|
-
mine
|
|
400
|
-
}) {
|
|
408
|
+
function ChatBubble({ text, mine }) {
|
|
401
409
|
if (text.trim() === "") {
|
|
402
410
|
return null;
|
|
403
411
|
}
|
|
@@ -405,7 +413,7 @@ function ChatBubble({
|
|
|
405
413
|
"div",
|
|
406
414
|
{
|
|
407
415
|
className: (0, import_utils.cn)(
|
|
408
|
-
"w-fit max-w-[85%] rounded-md px-4 py-3 text-sm leading-6 shadow-xs sm:
|
|
416
|
+
"w-fit max-w-[85%] rounded-md px-4 py-3 text-sm leading-6 shadow-xs sm:w-2xl",
|
|
409
417
|
mine ? "bg-secondary/85 text-foreground" : "bg-muted/70 text-foreground"
|
|
410
418
|
),
|
|
411
419
|
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(MarkdownBlock, { text })
|
|
@@ -474,10 +482,7 @@ function defaultEventHeadline(kind, state, eventName) {
|
|
|
474
482
|
}
|
|
475
483
|
return eventName.replace(/[._]/gu, " ");
|
|
476
484
|
}
|
|
477
|
-
function EventRow({
|
|
478
|
-
room,
|
|
479
|
-
message
|
|
480
|
-
}) {
|
|
485
|
+
function EventRow({ room, message }) {
|
|
481
486
|
const method = getTrimmedStringAttribute(message, "method") || "agent/event";
|
|
482
487
|
const eventName = getTrimmedStringAttribute(message, "name") || getTrimmedStringAttribute(message, "event_type") || method.replace(/\//gu, ".");
|
|
483
488
|
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;
|
|
@@ -34,7 +34,7 @@ module.exports = __toCommonJS(dataset_chat_thread_exports);
|
|
|
34
34
|
var import_jsx_runtime = require("react/jsx-runtime");
|
|
35
35
|
var import_react = require("react");
|
|
36
36
|
var import_meshagent = require("@meshagent/meshagent");
|
|
37
|
-
var
|
|
37
|
+
var import_meshagent_agents = require("@meshagent/meshagent-agents");
|
|
38
38
|
var import_lucide_react = require("lucide-react");
|
|
39
39
|
var import_react_markdown = __toESM(require("react-markdown"));
|
|
40
40
|
var import_rehype_highlight = __toESM(require("rehype-highlight"));
|
|
@@ -48,34 +48,6 @@ var import_file_attachment = require("./file-attachment");
|
|
|
48
48
|
var import_chat_hooks = require("./chat-hooks");
|
|
49
49
|
var import_utils = require("../lib/utils");
|
|
50
50
|
var import_chat_thread = require("./chat-thread");
|
|
51
|
-
const agentRoomMessageType = "agent-message";
|
|
52
|
-
const agentTurnStartType = "meshagent.agent.turn.start";
|
|
53
|
-
const agentTurnSteerType = "meshagent.agent.turn.steer";
|
|
54
|
-
const agentTurnInterruptType = "meshagent.agent.turn.interrupt";
|
|
55
|
-
const agentThreadOpenType = "meshagent.agent.thread.open";
|
|
56
|
-
const agentThreadCloseType = "meshagent.agent.thread.close";
|
|
57
|
-
const agentTurnStartAcceptedType = "meshagent.agent.turn.start.accepted";
|
|
58
|
-
const agentTurnStartRejectedType = "meshagent.agent.turn.start.rejected";
|
|
59
|
-
const agentTurnSteerAcceptedType = "meshagent.agent.turn.steer.accepted";
|
|
60
|
-
const agentTurnSteerRejectedType = "meshagent.agent.turn.steer.rejected";
|
|
61
|
-
const agentTurnStartedType = "meshagent.agent.turn.started";
|
|
62
|
-
const agentTurnSteeredType = "meshagent.agent.turn.steered";
|
|
63
|
-
const agentTextContentDeltaType = "meshagent.agent.text_content.delta";
|
|
64
|
-
const agentTextContentEndedType = "meshagent.agent.text_content.ended";
|
|
65
|
-
const agentReasoningContentStartedType = "meshagent.agent.reasoning_content.started";
|
|
66
|
-
const agentReasoningContentDeltaType = "meshagent.agent.reasoning_content.delta";
|
|
67
|
-
const agentReasoningContentEndedType = "meshagent.agent.reasoning_content.ended";
|
|
68
|
-
const agentFileContentStartedType = "meshagent.agent.file_content.started";
|
|
69
|
-
const agentFileContentDeltaType = "meshagent.agent.file_content.delta";
|
|
70
|
-
const agentFileContentEndedType = "meshagent.agent.file_content.ended";
|
|
71
|
-
const agentToolCallPendingType = "meshagent.agent.tool_call.pending";
|
|
72
|
-
const agentToolCallInProgressType = "meshagent.agent.tool_call.in_progress";
|
|
73
|
-
const agentToolCallStartedType = "meshagent.agent.tool_call.started";
|
|
74
|
-
const agentToolCallEndedType = "meshagent.agent.tool_call.ended";
|
|
75
|
-
const agentImageGenerationStartedType = "meshagent.agent.image_generation.started";
|
|
76
|
-
const agentImageGenerationPartialType = "meshagent.agent.image_generation.partial";
|
|
77
|
-
const agentImageGenerationCompletedType = "meshagent.agent.image_generation.completed";
|
|
78
|
-
const agentImageGenerationFailedType = "meshagent.agent.image_generation.failed";
|
|
79
51
|
const stickyBottomThresholdPx = 24;
|
|
80
52
|
const maxPreviewEdgePx = 312.5;
|
|
81
53
|
function createDatasetThreadModel() {
|
|
@@ -496,11 +468,11 @@ function timestampFromPayload(payload) {
|
|
|
496
468
|
}
|
|
497
469
|
function imageGenerationStatusFromType(type) {
|
|
498
470
|
switch (type) {
|
|
499
|
-
case agentImageGenerationCompletedType:
|
|
471
|
+
case import_meshagent_agents.agentImageGenerationCompletedType:
|
|
500
472
|
return "completed";
|
|
501
|
-
case agentImageGenerationFailedType:
|
|
473
|
+
case import_meshagent_agents.agentImageGenerationFailedType:
|
|
502
474
|
return "failed";
|
|
503
|
-
case agentImageGenerationPartialType:
|
|
475
|
+
case import_meshagent_agents.agentImageGenerationPartialType:
|
|
504
476
|
return "in_progress";
|
|
505
477
|
default:
|
|
506
478
|
return "pending";
|
|
@@ -668,7 +640,7 @@ function applyAgentMessagePayload(model, payload, path) {
|
|
|
668
640
|
if (!type) {
|
|
669
641
|
return false;
|
|
670
642
|
}
|
|
671
|
-
if (type === agentTurnStartRejectedType || type === agentTurnSteerRejectedType) {
|
|
643
|
+
if (type === import_meshagent_agents.agentTurnStartRejectedType || type === import_meshagent_agents.agentTurnSteerRejectedType) {
|
|
672
644
|
const sourceMessageId = stringValue(payload.source_message_id);
|
|
673
645
|
return sourceMessageId ? model.agentRowsByItemId.delete(sourceMessageId) : false;
|
|
674
646
|
}
|
|
@@ -676,14 +648,14 @@ function applyAgentMessagePayload(model, payload, path) {
|
|
|
676
648
|
const turnId = payloadTurnId(payload);
|
|
677
649
|
let changed = false;
|
|
678
650
|
switch (type) {
|
|
679
|
-
case agentTurnStartAcceptedType:
|
|
680
|
-
case agentTurnSteerAcceptedType:
|
|
651
|
+
case import_meshagent_agents.agentTurnStartAcceptedType:
|
|
652
|
+
case import_meshagent_agents.agentTurnSteerAcceptedType:
|
|
681
653
|
break;
|
|
682
|
-
case agentTurnStartedType:
|
|
683
|
-
case agentTurnSteeredType:
|
|
654
|
+
case import_meshagent_agents.agentTurnStartedType:
|
|
655
|
+
case import_meshagent_agents.agentTurnSteeredType:
|
|
684
656
|
changed = materializeTurnInputPayload(model, payload) || changed;
|
|
685
657
|
break;
|
|
686
|
-
case agentTextContentDeltaType:
|
|
658
|
+
case import_meshagent_agents.agentTextContentDeltaType:
|
|
687
659
|
changed = appendAgentRowText({
|
|
688
660
|
model,
|
|
689
661
|
itemId,
|
|
@@ -693,7 +665,7 @@ function applyAgentMessagePayload(model, payload, path) {
|
|
|
693
665
|
delta: String(payload.text ?? "")
|
|
694
666
|
}) || changed;
|
|
695
667
|
break;
|
|
696
|
-
case agentTextContentEndedType:
|
|
668
|
+
case import_meshagent_agents.agentTextContentEndedType:
|
|
697
669
|
changed = upsertAgentRow({
|
|
698
670
|
model,
|
|
699
671
|
itemId,
|
|
@@ -705,7 +677,7 @@ function applyAgentMessagePayload(model, payload, path) {
|
|
|
705
677
|
}
|
|
706
678
|
}) || changed;
|
|
707
679
|
break;
|
|
708
|
-
case agentReasoningContentStartedType:
|
|
680
|
+
case import_meshagent_agents.agentReasoningContentStartedType:
|
|
709
681
|
changed = upsertAgentRow({
|
|
710
682
|
model,
|
|
711
683
|
itemId,
|
|
@@ -713,7 +685,7 @@ function applyAgentMessagePayload(model, payload, path) {
|
|
|
713
685
|
data: { kind: "reasoning", role: "assistant", text: "" }
|
|
714
686
|
}) || changed;
|
|
715
687
|
break;
|
|
716
|
-
case agentReasoningContentDeltaType:
|
|
688
|
+
case import_meshagent_agents.agentReasoningContentDeltaType:
|
|
717
689
|
changed = appendAgentRowText({
|
|
718
690
|
model,
|
|
719
691
|
itemId,
|
|
@@ -723,7 +695,7 @@ function applyAgentMessagePayload(model, payload, path) {
|
|
|
723
695
|
delta: String(payload.text ?? "")
|
|
724
696
|
}) || changed;
|
|
725
697
|
break;
|
|
726
|
-
case agentReasoningContentEndedType:
|
|
698
|
+
case import_meshagent_agents.agentReasoningContentEndedType:
|
|
727
699
|
changed = upsertAgentRow({
|
|
728
700
|
model,
|
|
729
701
|
itemId,
|
|
@@ -735,7 +707,7 @@ function applyAgentMessagePayload(model, payload, path) {
|
|
|
735
707
|
}
|
|
736
708
|
}) || changed;
|
|
737
709
|
break;
|
|
738
|
-
case agentFileContentStartedType:
|
|
710
|
+
case import_meshagent_agents.agentFileContentStartedType:
|
|
739
711
|
changed = upsertAgentRow({
|
|
740
712
|
model,
|
|
741
713
|
itemId,
|
|
@@ -743,17 +715,17 @@ function applyAgentMessagePayload(model, payload, path) {
|
|
|
743
715
|
data: { kind: "file", role: "assistant", urls: [] }
|
|
744
716
|
}) || changed;
|
|
745
717
|
break;
|
|
746
|
-
case agentFileContentDeltaType:
|
|
747
|
-
case agentFileContentEndedType:
|
|
718
|
+
case import_meshagent_agents.agentFileContentDeltaType:
|
|
719
|
+
case import_meshagent_agents.agentFileContentEndedType:
|
|
748
720
|
changed = appendAgentRowUrl({ model, itemId, turnId, url: payload.url }) || changed;
|
|
749
721
|
break;
|
|
750
|
-
case agentToolCallPendingType:
|
|
751
|
-
case agentToolCallInProgressType:
|
|
752
|
-
case agentToolCallStartedType:
|
|
753
|
-
case agentToolCallEndedType: {
|
|
722
|
+
case import_meshagent_agents.agentToolCallPendingType:
|
|
723
|
+
case import_meshagent_agents.agentToolCallInProgressType:
|
|
724
|
+
case import_meshagent_agents.agentToolCallStartedType:
|
|
725
|
+
case import_meshagent_agents.agentToolCallEndedType: {
|
|
754
726
|
const tool = String(payload.tool ?? payload.tool_name ?? payload.name ?? "");
|
|
755
727
|
const isImageGeneration = tool.trim().toLowerCase() === "image_generation";
|
|
756
|
-
if (isImageGeneration && type === agentToolCallEndedType && payload.error == null) {
|
|
728
|
+
if (isImageGeneration && type === import_meshagent_agents.agentToolCallEndedType && payload.error == null) {
|
|
757
729
|
break;
|
|
758
730
|
}
|
|
759
731
|
changed = upsertAgentRow({
|
|
@@ -772,15 +744,15 @@ function applyAgentMessagePayload(model, payload, path) {
|
|
|
772
744
|
role: "assistant",
|
|
773
745
|
toolkit: String(payload.toolkit ?? payload.toolkit_name ?? ""),
|
|
774
746
|
tool,
|
|
775
|
-
status: type === agentToolCallEndedType ? "completed" : "running"
|
|
747
|
+
status: type === import_meshagent_agents.agentToolCallEndedType ? "completed" : "running"
|
|
776
748
|
}
|
|
777
749
|
}) || changed;
|
|
778
750
|
break;
|
|
779
751
|
}
|
|
780
|
-
case agentImageGenerationStartedType:
|
|
781
|
-
case agentImageGenerationPartialType:
|
|
782
|
-
case agentImageGenerationCompletedType:
|
|
783
|
-
case agentImageGenerationFailedType:
|
|
752
|
+
case import_meshagent_agents.agentImageGenerationStartedType:
|
|
753
|
+
case import_meshagent_agents.agentImageGenerationPartialType:
|
|
754
|
+
case import_meshagent_agents.agentImageGenerationCompletedType:
|
|
755
|
+
case import_meshagent_agents.agentImageGenerationFailedType:
|
|
784
756
|
changed = upsertAgentRow({
|
|
785
757
|
model,
|
|
786
758
|
itemId,
|
|
@@ -1019,6 +991,26 @@ function describeError(error) {
|
|
|
1019
991
|
}
|
|
1020
992
|
return String(error);
|
|
1021
993
|
}
|
|
994
|
+
function pendingAgentMessageFromInput(pending) {
|
|
995
|
+
const payload = pending.payload.toJson();
|
|
996
|
+
const parsed = import_chat_hooks.PendingAgentMessage.fromQueueJson({
|
|
997
|
+
...payload,
|
|
998
|
+
message_type: pending.messageType,
|
|
999
|
+
created_at: pending.createdAt.toISOString()
|
|
1000
|
+
});
|
|
1001
|
+
return new import_chat_hooks.PendingAgentMessage({
|
|
1002
|
+
messageId: parsed.messageId,
|
|
1003
|
+
messageType: parsed.messageType,
|
|
1004
|
+
threadPath: parsed.threadPath,
|
|
1005
|
+
text: parsed.text,
|
|
1006
|
+
attachments: parsed.attachments,
|
|
1007
|
+
senderName: parsed.senderName,
|
|
1008
|
+
createdAt: parsed.createdAt,
|
|
1009
|
+
matchByContentOnly: parsed.matchByContentOnly,
|
|
1010
|
+
awaitingAcceptance: pending.awaitingAcceptance,
|
|
1011
|
+
awaitingOnline: pending.awaitingOnline
|
|
1012
|
+
});
|
|
1013
|
+
}
|
|
1022
1014
|
function MarkdownBlock({ text }) {
|
|
1023
1015
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1024
1016
|
import_react_markdown.default,
|
|
@@ -1435,24 +1427,11 @@ function EmptyState({
|
|
|
1435
1427
|
function ErrorBanner({ message }) {
|
|
1436
1428
|
return /* @__PURE__ */ (0, import_jsx_runtime.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 });
|
|
1437
1429
|
}
|
|
1438
|
-
function sendThreadSubscriptionMessage({
|
|
1439
|
-
room,
|
|
1440
|
-
agent,
|
|
1441
|
-
messageType,
|
|
1442
|
-
path
|
|
1443
|
-
}) {
|
|
1444
|
-
void room.messaging.sendMessage({
|
|
1445
|
-
to: agent,
|
|
1446
|
-
type: agentRoomMessageType,
|
|
1447
|
-
ignoreOffline: true,
|
|
1448
|
-
message: {
|
|
1449
|
-
payload: { type: messageType, thread_id: path }
|
|
1450
|
-
}
|
|
1451
|
-
}).catch(() => void 0);
|
|
1452
|
-
}
|
|
1453
1430
|
function DatasetChatThread({
|
|
1454
1431
|
room,
|
|
1455
1432
|
path,
|
|
1433
|
+
chatClient,
|
|
1434
|
+
disposeChatClient = false,
|
|
1456
1435
|
agentName,
|
|
1457
1436
|
emptyStateTitle,
|
|
1458
1437
|
emptyStateDescription,
|
|
@@ -1466,14 +1445,35 @@ function DatasetChatThread({
|
|
|
1466
1445
|
const [sendError, setSendError] = (0, import_react.useState)(null);
|
|
1467
1446
|
const [showCompletedToolCalls, setShowCompletedToolCalls] = (0, import_react.useState)(initialShowCompletedToolCalls);
|
|
1468
1447
|
const status = (0, import_chat_hooks.useThreadStatus)({ room, path, agentName });
|
|
1469
|
-
const agentParticipant = findAgentParticipant(room, agentName);
|
|
1470
1448
|
const localParticipantName = getParticipantName(room.localParticipant);
|
|
1471
1449
|
const scrollContainerRef = (0, import_react.useRef)(null);
|
|
1472
1450
|
const contentRef = (0, import_react.useRef)(null);
|
|
1473
1451
|
const stickToBottomRef = (0, import_react.useRef)(true);
|
|
1452
|
+
const threadSessionRef = (0, import_react.useRef)(null);
|
|
1453
|
+
const threadSessionCursorRef = (0, import_react.useRef)(0);
|
|
1454
|
+
const [threadSessionVersion, setThreadSessionVersion] = (0, import_react.useState)(0);
|
|
1455
|
+
const ownsChatClient = chatClient == null;
|
|
1456
|
+
const activeChatClient = (0, import_react.useMemo)(
|
|
1457
|
+
() => chatClient ?? new import_meshagent_agents.MessagingChatClient({ room, agentName }),
|
|
1458
|
+
[agentName, chatClient, room]
|
|
1459
|
+
);
|
|
1460
|
+
const agentParticipant = activeChatClient.agentParticipant() ?? findAgentParticipant(room, agentName);
|
|
1474
1461
|
const bumpModelVersion = (0, import_react.useCallback)(() => {
|
|
1475
1462
|
setModelVersion((current) => current + 1);
|
|
1476
1463
|
}, []);
|
|
1464
|
+
(0, import_react.useEffect)(() => {
|
|
1465
|
+
void activeChatClient.start();
|
|
1466
|
+
const handleChange = () => {
|
|
1467
|
+
setThreadSessionVersion((current) => current + 1);
|
|
1468
|
+
};
|
|
1469
|
+
activeChatClient.addListener(handleChange);
|
|
1470
|
+
return () => {
|
|
1471
|
+
activeChatClient.removeListener(handleChange);
|
|
1472
|
+
if (ownsChatClient || disposeChatClient) {
|
|
1473
|
+
void activeChatClient.stop();
|
|
1474
|
+
}
|
|
1475
|
+
};
|
|
1476
|
+
}, [activeChatClient, disposeChatClient, ownsChatClient]);
|
|
1477
1477
|
(0, import_react.useEffect)(() => {
|
|
1478
1478
|
const model2 = createDatasetThreadModel();
|
|
1479
1479
|
modelRef.current = model2;
|
|
@@ -1551,46 +1551,41 @@ function DatasetChatThread({
|
|
|
1551
1551
|
};
|
|
1552
1552
|
}, [bumpModelVersion, path, room]);
|
|
1553
1553
|
(0, import_react.useEffect)(() => {
|
|
1554
|
-
|
|
1555
|
-
|
|
1556
|
-
|
|
1557
|
-
|
|
1558
|
-
|
|
1559
|
-
|
|
1560
|
-
|
|
1561
|
-
|
|
1562
|
-
|
|
1563
|
-
|
|
1564
|
-
|
|
1565
|
-
|
|
1566
|
-
|
|
1567
|
-
|
|
1554
|
+
if (isTmpThreadPath(path)) {
|
|
1555
|
+
threadSessionRef.current = null;
|
|
1556
|
+
threadSessionCursorRef.current = 0;
|
|
1557
|
+
setThreadSessionVersion((current) => current + 1);
|
|
1558
|
+
return;
|
|
1559
|
+
}
|
|
1560
|
+
const session = activeChatClient.openThread(path);
|
|
1561
|
+
threadSessionRef.current = session;
|
|
1562
|
+
threadSessionCursorRef.current = 0;
|
|
1563
|
+
const drainSessionMessages = () => {
|
|
1564
|
+
let changed = false;
|
|
1565
|
+
const messages = session.messages;
|
|
1566
|
+
while (threadSessionCursorRef.current < messages.length) {
|
|
1567
|
+
const event = messages[threadSessionCursorRef.current];
|
|
1568
|
+
threadSessionCursorRef.current += 1;
|
|
1569
|
+
if (applyAgentMessagePayload(modelRef.current, event.payload, path)) {
|
|
1570
|
+
changed = true;
|
|
1568
1571
|
}
|
|
1569
1572
|
}
|
|
1570
|
-
|
|
1571
|
-
|
|
1572
|
-
|
|
1573
|
+
if (changed) {
|
|
1574
|
+
bumpModelVersion();
|
|
1575
|
+
}
|
|
1576
|
+
setThreadSessionVersion((current) => current + 1);
|
|
1573
1577
|
};
|
|
1574
|
-
|
|
1575
|
-
|
|
1576
|
-
if (!agentParticipant) {
|
|
1577
|
-
return;
|
|
1578
|
-
}
|
|
1579
|
-
sendThreadSubscriptionMessage({
|
|
1580
|
-
room,
|
|
1581
|
-
agent: agentParticipant,
|
|
1582
|
-
messageType: agentThreadOpenType,
|
|
1583
|
-
path
|
|
1584
|
-
});
|
|
1578
|
+
session.addListener(drainSessionMessages);
|
|
1579
|
+
drainSessionMessages();
|
|
1585
1580
|
return () => {
|
|
1586
|
-
|
|
1587
|
-
|
|
1588
|
-
|
|
1589
|
-
|
|
1590
|
-
|
|
1591
|
-
|
|
1581
|
+
session.removeListener(drainSessionMessages);
|
|
1582
|
+
if (threadSessionRef.current === session) {
|
|
1583
|
+
threadSessionRef.current = null;
|
|
1584
|
+
threadSessionCursorRef.current = 0;
|
|
1585
|
+
}
|
|
1586
|
+
void session.close().catch(() => void 0);
|
|
1592
1587
|
};
|
|
1593
|
-
}, [
|
|
1588
|
+
}, [activeChatClient, bumpModelVersion, path]);
|
|
1594
1589
|
const allMessages = (0, import_react.useMemo)(() => {
|
|
1595
1590
|
const model2 = modelRef.current;
|
|
1596
1591
|
const mergedRowsByItemId = /* @__PURE__ */ new Map();
|
|
@@ -1615,29 +1610,24 @@ function DatasetChatThread({
|
|
|
1615
1610
|
for (const pending of status.pendingMessages) {
|
|
1616
1611
|
combined.set(pending.messageId, pending);
|
|
1617
1612
|
}
|
|
1613
|
+
for (const pending of threadSessionRef.current?.pendingInputs ?? []) {
|
|
1614
|
+
combined.set(pending.messageId, pendingAgentMessageFromInput(pending));
|
|
1615
|
+
}
|
|
1618
1616
|
const values = Array.from(combined.values()).filter((pending) => !allMessages.some((message) => datasetThreadMessageMatchesPendingAgentMessage(message, pending)));
|
|
1619
1617
|
return [
|
|
1620
1618
|
...values.filter((message) => !message.awaitingAcceptance),
|
|
1621
1619
|
...values.filter((message) => message.awaitingAcceptance)
|
|
1622
1620
|
];
|
|
1623
|
-
}, [allMessages, status.pendingMessages]);
|
|
1624
|
-
const canInterruptActiveTurn = status.
|
|
1621
|
+
}, [allMessages, status.pendingMessages, threadSessionVersion]);
|
|
1622
|
+
const canInterruptActiveTurn = status.turnId != null && (status.supportsAgentMessages || agentParticipant != null || chatClient != null);
|
|
1625
1623
|
const cancelTurn = (0, import_react.useCallback)(async () => {
|
|
1626
|
-
|
|
1624
|
+
const turnId = status.turnId?.trim();
|
|
1625
|
+
const session = threadSessionRef.current;
|
|
1626
|
+
if (!turnId || session == null) {
|
|
1627
1627
|
return;
|
|
1628
1628
|
}
|
|
1629
|
-
await
|
|
1630
|
-
|
|
1631
|
-
type: agentRoomMessageType,
|
|
1632
|
-
message: {
|
|
1633
|
-
payload: {
|
|
1634
|
-
type: agentTurnInterruptType,
|
|
1635
|
-
thread_id: path,
|
|
1636
|
-
turn_id: status.turnId
|
|
1637
|
-
}
|
|
1638
|
-
}
|
|
1639
|
-
});
|
|
1640
|
-
}, [agentParticipant, path, room, status.turnId]);
|
|
1629
|
+
await session.interruptTurn(turnId);
|
|
1630
|
+
}, [status.turnId, threadSessionVersion]);
|
|
1641
1631
|
const selectAttachments = (0, import_react.useCallback)((files) => {
|
|
1642
1632
|
const nextAttachments = files.map((file) => new import_file_attachment.MeshagentFileUpload(
|
|
1643
1633
|
room,
|
|
@@ -1651,56 +1641,39 @@ function DatasetChatThread({
|
|
|
1651
1641
|
if (message.text.trim() === "" && message.attachments.length === 0) {
|
|
1652
1642
|
return;
|
|
1653
1643
|
}
|
|
1654
|
-
if (!agentParticipant) {
|
|
1644
|
+
if (!agentParticipant && chatClient == null) {
|
|
1655
1645
|
setSendError("This thread requires an online agent that supports agent messages.");
|
|
1656
1646
|
return;
|
|
1657
1647
|
}
|
|
1648
|
+
const session = threadSessionRef.current;
|
|
1649
|
+
if (session == null) {
|
|
1650
|
+
setSendError("No thread session is open.");
|
|
1651
|
+
return;
|
|
1652
|
+
}
|
|
1658
1653
|
const isSteer = status.mode === "steerable" && status.turnId != null;
|
|
1659
1654
|
const normalizedAttachments = message.attachments.map(normalizeAgentAttachmentUrl).filter((attachment) => attachment !== null);
|
|
1660
1655
|
const senderName = localParticipantName.trim() || void 0;
|
|
1661
|
-
upsertAgentRow({
|
|
1662
|
-
model: modelRef.current,
|
|
1663
|
-
itemId: message.id,
|
|
1664
|
-
turnId: null,
|
|
1665
|
-
timestamp: /* @__PURE__ */ new Date(),
|
|
1666
|
-
data: {
|
|
1667
|
-
kind: "message",
|
|
1668
|
-
role: "user",
|
|
1669
|
-
text: message.text,
|
|
1670
|
-
sender_name: senderName,
|
|
1671
|
-
attachments: normalizedAttachments
|
|
1672
|
-
}
|
|
1673
|
-
});
|
|
1674
|
-
bumpModelVersion();
|
|
1675
1656
|
try {
|
|
1676
|
-
|
|
1677
|
-
|
|
1678
|
-
|
|
1679
|
-
|
|
1680
|
-
|
|
1681
|
-
|
|
1682
|
-
|
|
1683
|
-
payload.turn_id = status.turnId;
|
|
1684
|
-
}
|
|
1685
|
-
await room.messaging.sendMessage({
|
|
1686
|
-
to: agentParticipant,
|
|
1687
|
-
type: agentRoomMessageType,
|
|
1688
|
-
message: { payload }
|
|
1657
|
+
await session.sendText({
|
|
1658
|
+
messageId: message.id,
|
|
1659
|
+
text: message.text,
|
|
1660
|
+
attachments: normalizedAttachments,
|
|
1661
|
+
steer: isSteer,
|
|
1662
|
+
turnId: status.turnId,
|
|
1663
|
+
senderName
|
|
1689
1664
|
});
|
|
1690
1665
|
setSendError(null);
|
|
1666
|
+
setThreadSessionVersion((current) => current + 1);
|
|
1691
1667
|
} catch (error) {
|
|
1692
|
-
modelRef.current.agentRowsByItemId.delete(message.id);
|
|
1693
|
-
bumpModelVersion();
|
|
1694
1668
|
setSendError(describeError(error));
|
|
1695
1669
|
}
|
|
1696
1670
|
}, [
|
|
1697
1671
|
agentParticipant,
|
|
1698
|
-
|
|
1672
|
+
chatClient,
|
|
1699
1673
|
localParticipantName,
|
|
1700
|
-
path,
|
|
1701
|
-
room,
|
|
1702
1674
|
status.mode,
|
|
1703
|
-
status.turnId
|
|
1675
|
+
status.turnId,
|
|
1676
|
+
threadSessionVersion
|
|
1704
1677
|
]);
|
|
1705
1678
|
const hasWireBackedContent = modelRef.current.agentRowsByItemId.size > 0 || status.pendingMessages.length > 0 || pendingMessages.length > 0;
|
|
1706
1679
|
const model = modelRef.current;
|
|
@@ -1832,8 +1805,8 @@ function DatasetChatThread({
|
|
|
1832
1805
|
attachments,
|
|
1833
1806
|
onFilesSelected: selectAttachments,
|
|
1834
1807
|
setAttachments,
|
|
1835
|
-
disabled: agentParticipant == null,
|
|
1836
|
-
placeholder: inputPlaceholder ?? (agentParticipant ? "Type a message" : `Waiting for ${displayParticipantName(agentName ?? "agent")}`)
|
|
1808
|
+
disabled: agentParticipant == null && chatClient == null,
|
|
1809
|
+
placeholder: inputPlaceholder ?? (agentParticipant || chatClient ? "Type a message" : `Waiting for ${displayParticipantName(agentName ?? "agent")}`)
|
|
1837
1810
|
}
|
|
1838
1811
|
)
|
|
1839
1812
|
] });
|
|
@@ -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;
|
|
@@ -30,6 +30,8 @@ function normalizeSelectedThreadPath(path) {
|
|
|
30
30
|
}
|
|
31
31
|
function MultiThreadView({
|
|
32
32
|
room,
|
|
33
|
+
chatClient,
|
|
34
|
+
disposeChatClient = false,
|
|
33
35
|
agentName,
|
|
34
36
|
builder,
|
|
35
37
|
toolkit = "chat",
|
|
@@ -68,6 +70,8 @@ function MultiThreadView({
|
|
|
68
70
|
import_new_chat_thread.NewChatThread,
|
|
69
71
|
{
|
|
70
72
|
room,
|
|
73
|
+
chatClient,
|
|
74
|
+
disposeChatClient,
|
|
71
75
|
agentName,
|
|
72
76
|
builder,
|
|
73
77
|
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;
|