@meshagent/meshagent-tailwind 0.38.2 → 0.38.3

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.
Files changed (61) hide show
  1. package/CHANGELOG.md +9 -0
  2. package/dist/cjs/Chat.d.ts +11 -3
  3. package/dist/cjs/Chat.js +376 -29
  4. package/dist/cjs/ChatBotView.d.ts +29 -0
  5. package/dist/cjs/ChatBotView.js +491 -0
  6. package/dist/cjs/ChatInput.d.ts +12 -3
  7. package/dist/cjs/ChatInput.js +143 -44
  8. package/dist/cjs/ChatThread.d.ts +17 -3
  9. package/dist/cjs/ChatThread.js +646 -90
  10. package/dist/cjs/ChatTypingIndicator.d.ts +12 -5
  11. package/dist/cjs/ChatTypingIndicator.js +104 -13
  12. package/dist/cjs/FileUploader.d.ts +3 -2
  13. package/dist/cjs/FileUploader.js +35 -11
  14. package/dist/cjs/UploadPill.d.ts +2 -2
  15. package/dist/cjs/UploadPill.js +70 -32
  16. package/dist/cjs/chat-hooks.d.ts +38 -0
  17. package/dist/cjs/chat-hooks.js +390 -0
  18. package/dist/cjs/chat-message.d.ts +11 -0
  19. package/dist/cjs/chat-message.js +33 -0
  20. package/dist/cjs/components/ui/button.d.ts +1 -1
  21. package/dist/cjs/conversation-descriptor.d.ts +59 -0
  22. package/dist/cjs/conversation-descriptor.js +300 -0
  23. package/dist/cjs/file-attachment.d.ts +45 -0
  24. package/dist/cjs/file-attachment.js +171 -0
  25. package/dist/cjs/index.d.ts +5 -0
  26. package/dist/cjs/index.js +5 -0
  27. package/dist/cjs/multi-thread-view.d.ts +18 -0
  28. package/dist/cjs/multi-thread-view.js +88 -0
  29. package/dist/cjs/tools/ui-toolkit.d.ts +1 -1
  30. package/dist/cjs/tools/ui-toolkit.js +2 -1
  31. package/dist/esm/Chat.d.ts +11 -3
  32. package/dist/esm/Chat.js +378 -31
  33. package/dist/esm/ChatBotView.d.ts +29 -0
  34. package/dist/esm/ChatBotView.js +486 -0
  35. package/dist/esm/ChatInput.d.ts +12 -3
  36. package/dist/esm/ChatInput.js +143 -34
  37. package/dist/esm/ChatThread.d.ts +17 -3
  38. package/dist/esm/ChatThread.js +648 -92
  39. package/dist/esm/ChatTypingIndicator.d.ts +12 -5
  40. package/dist/esm/ChatTypingIndicator.js +94 -13
  41. package/dist/esm/FileUploader.d.ts +3 -2
  42. package/dist/esm/FileUploader.js +26 -12
  43. package/dist/esm/UploadPill.d.ts +2 -2
  44. package/dist/esm/UploadPill.js +60 -32
  45. package/dist/esm/chat-hooks.d.ts +38 -0
  46. package/dist/esm/chat-hooks.js +372 -0
  47. package/dist/esm/chat-message.d.ts +11 -0
  48. package/dist/esm/chat-message.js +13 -0
  49. package/dist/esm/components/ui/button.d.ts +1 -1
  50. package/dist/esm/conversation-descriptor.d.ts +59 -0
  51. package/dist/esm/conversation-descriptor.js +280 -0
  52. package/dist/esm/file-attachment.d.ts +45 -0
  53. package/dist/esm/file-attachment.js +151 -0
  54. package/dist/esm/index.d.ts +5 -0
  55. package/dist/esm/index.js +5 -0
  56. package/dist/esm/multi-thread-view.d.ts +18 -0
  57. package/dist/esm/multi-thread-view.js +68 -0
  58. package/dist/esm/tools/ui-toolkit.d.ts +1 -1
  59. package/dist/esm/tools/ui-toolkit.js +2 -1
  60. package/dist/index.css +1 -1
  61. package/package.json +3 -3
package/dist/esm/Chat.js CHANGED
@@ -1,54 +1,192 @@
1
1
  import { jsx, jsxs } from "react/jsx-runtime";
2
- import { useMemo, useCallback } from "react";
3
- import { useChat, useClientToolkits, useRoomIndicators } from "@meshagent/meshagent-react";
4
- import { ChatThread } from "./ChatThread";
2
+ import { useState, useRef, useMemo, useEffect, useCallback } from "react";
3
+ import { JsonContent } from "@meshagent/meshagent";
4
+ import { useRoomIndicators } from "@meshagent/meshagent-react";
5
+ import { Plus } from "lucide-react";
5
6
  import { ChatInput } from "./ChatInput";
6
- import { ChatTypingIndicator } from "./ChatTypingIndicator";
7
- import { UIToolkit } from "./tools/ui-toolkit";
7
+ import { ChatThread } from "./ChatThread";
8
+ import { Button } from "./components/ui/button";
8
9
  import { Toaster } from "./components/ui/sonner";
10
+ import { MeshagentFileUpload, fileToAsyncIterable } from "./file-attachment";
11
+ import { useChatThread, useThreadStatus } from "./chat-hooks";
12
+ class NewThreadCancelledError extends Error {
13
+ constructor() {
14
+ super("new thread creation cancelled");
15
+ this.name = "NewThreadCancelledError";
16
+ }
17
+ }
18
+ function normalizeThreadPath(path) {
19
+ const normalizedPath = path?.trim();
20
+ return normalizedPath ? normalizedPath : null;
21
+ }
9
22
  function getParticipantName(participant) {
10
- const name = participant?.getAttribute("name");
11
- return typeof name === "string" ? name : "";
23
+ const name = participant.getAttribute("name");
24
+ return typeof name === "string" ? name.trim() : "";
25
+ }
26
+ function displayParticipantName(name) {
27
+ const normalizedName = name?.trim();
28
+ if (!normalizedName) {
29
+ return "agent";
30
+ }
31
+ return normalizedName.split("@")[0]?.trim() || normalizedName;
32
+ }
33
+ function isAgentParticipant(participant) {
34
+ return participant.role === "agent" || participant.getAttribute("supports_agent_messages") === true;
35
+ }
36
+ function findTargetAgent(room, agentName) {
37
+ const normalizedAgentName = agentName?.trim();
38
+ for (const participant of room.messaging.remoteParticipants) {
39
+ if (!isAgentParticipant(participant)) {
40
+ continue;
41
+ }
42
+ if (normalizedAgentName && getParticipantName(participant) !== normalizedAgentName) {
43
+ continue;
44
+ }
45
+ return participant;
46
+ }
47
+ return null;
48
+ }
49
+ function ensureOperationActive(operationId, activeOperationRef) {
50
+ if (activeOperationRef.current !== operationId) {
51
+ throw new NewThreadCancelledError();
52
+ }
53
+ }
54
+ function delay(milliseconds) {
55
+ return new Promise((resolve) => {
56
+ window.setTimeout(resolve, milliseconds);
57
+ });
12
58
  }
13
- function Chat({ room, path, participants }) {
59
+ async function waitForTargetAgent(params) {
60
+ const { room, agentName, operationId, activeOperationRef } = params;
61
+ while (true) {
62
+ ensureOperationActive(operationId, activeOperationRef);
63
+ const targetAgent = findTargetAgent(room, agentName);
64
+ if (targetAgent) {
65
+ return targetAgent;
66
+ }
67
+ await delay(250);
68
+ }
69
+ }
70
+ async function waitForToolkitAvailable(params) {
14
71
  const {
72
+ room,
73
+ participantId,
74
+ toolkit,
75
+ operationId,
76
+ activeOperationRef
77
+ } = params;
78
+ while (true) {
79
+ ensureOperationActive(operationId, activeOperationRef);
80
+ try {
81
+ const toolkits = await room.agents.listToolkits({ participantId, timeout: 1e3 });
82
+ if (toolkits.some((toolkitDescription) => toolkitDescription.name === toolkit)) {
83
+ return;
84
+ }
85
+ } catch {
86
+ }
87
+ await delay(250);
88
+ }
89
+ }
90
+ function getStringField(record, key) {
91
+ const value = record[key];
92
+ return typeof value === "string" && value.trim() !== "" ? value.trim() : null;
93
+ }
94
+ function parseThreadToolResult(toolkit, tool, content) {
95
+ const path = getStringField(content.json, "path");
96
+ if (!path) {
97
+ throw new Error(`${toolkit}.${tool} response missing path`);
98
+ }
99
+ return {
100
+ path,
101
+ displayName: getStringField(content.json, "name")
102
+ };
103
+ }
104
+ function describeError(error) {
105
+ if (error instanceof Error && error.message.trim() !== "") {
106
+ return error.message;
107
+ }
108
+ return `${error}`;
109
+ }
110
+ function EmptyState({
111
+ title,
112
+ description
113
+ }) {
114
+ return /* @__PURE__ */ jsxs("div", { className: "mx-auto flex max-w-2xl flex-col items-center justify-center px-6 py-20 text-center", children: [
115
+ /* @__PURE__ */ jsx("h2", { className: "text-4xl font-semibold tracking-tight text-foreground sm:text-5xl", children: title }),
116
+ description?.trim() ? /* @__PURE__ */ jsx("p", { className: "mt-3 max-w-xl text-sm leading-6 text-muted-foreground sm:text-base", children: description }) : null
117
+ ] });
118
+ }
119
+ function ErrorBanner({ message }) {
120
+ return /* @__PURE__ */ jsx("div", { className: "mx-auto w-full max-w-[912px] whitespace-pre-wrap rounded-3xl border border-destructive/30 bg-destructive/5 px-6 py-5 text-sm text-destructive", children: message });
121
+ }
122
+ function ResolvedChatView({
123
+ room,
124
+ path,
125
+ participants,
126
+ agentName,
127
+ emptyStateTitle,
128
+ emptyStateDescription,
129
+ showNewThreadButton = false,
130
+ onStartNewThread
131
+ }) {
132
+ const {
133
+ document,
15
134
  messages,
16
135
  sendMessage,
17
136
  selectAttachments,
18
137
  attachments,
19
138
  setAttachments,
20
- schemaFileExists,
139
+ onlineParticipants,
140
+ localParticipantName,
21
141
  cancelRequest
22
- } = useChat({ room, path, participants });
23
- const { thinking } = useRoomIndicators({ room, path });
24
- const toolkits = useMemo(() => [
25
- new UIToolkit()
26
- ], []);
27
- useClientToolkits({ room, toolkits, public: false });
28
- const onTextChange = useCallback((_) => {
29
- const removeParticipant = room.messaging.remoteParticipants;
30
- for (const part of removeParticipant) {
142
+ } = useChatThread({ room, path, participants, agentName });
143
+ const { typing, thinking } = useRoomIndicators({ room, path });
144
+ const threadStatus = useThreadStatus({ room, path, agentName });
145
+ const [showCompletedToolCalls, setShowCompletedToolCalls] = useState(false);
146
+ const onTextChange = useCallback(() => {
147
+ for (const participant of onlineParticipants) {
31
148
  room.messaging.sendMessage({
32
- to: part,
149
+ to: participant,
33
150
  type: "typing",
34
151
  message: { path }
35
152
  });
36
153
  }
37
- }, [room, path]);
38
- const localParticipantName = getParticipantName(room?.localParticipant);
39
- if (schemaFileExists === false) {
40
- return /* @__PURE__ */ jsx("div", { className: "flex flex-col flex-1 min-h-0 gap-2 p-4", children: /* @__PURE__ */ jsx("p", { className: "text-red-500", children: 'No AI agent found in this room. Run `meshagent chatbot join --room [room-name] --agent-name "Chat Agent" --name "Chat Friend"` and try again.' }) });
41
- }
42
- return /* @__PURE__ */ jsxs("div", { className: "flex flex-col flex-1 min-h-0 gap-2 p-0", children: [
154
+ }, [onlineParticipants, path, room]);
155
+ return /* @__PURE__ */ jsxs("div", { className: "flex min-h-0 flex-1 flex-col", children: [
156
+ showNewThreadButton && onStartNewThread ? /* @__PURE__ */ jsx("div", { className: "px-4 pt-3", children: /* @__PURE__ */ jsx("div", { className: "mx-auto flex w-full max-w-[912px] justify-end", children: /* @__PURE__ */ jsxs(
157
+ Button,
158
+ {
159
+ type: "button",
160
+ variant: "outline",
161
+ size: "sm",
162
+ className: "rounded-full shadow-xs",
163
+ onClick: onStartNewThread,
164
+ children: [
165
+ /* @__PURE__ */ jsx(Plus, { className: "mr-2 h-4 w-4" }),
166
+ "New thread"
167
+ ]
168
+ }
169
+ ) }) }) : null,
43
170
  /* @__PURE__ */ jsx(
44
171
  ChatThread,
45
172
  {
46
173
  room,
174
+ path,
47
175
  messages,
48
- localParticipantName
176
+ isLoading: document === null,
177
+ localParticipantName,
178
+ showCompletedToolCalls,
179
+ onShowCompletedToolCallsChanged: setShowCompletedToolCalls,
180
+ typing,
181
+ thinking,
182
+ threadStatusText: threadStatus.text,
183
+ threadStatusStartedAt: threadStatus.startedAt,
184
+ threadStatusMode: threadStatus.mode,
185
+ onCancelRequest: cancelRequest,
186
+ emptyStateTitle,
187
+ emptyStateDescription
49
188
  }
50
189
  ),
51
- /* @__PURE__ */ jsx(ChatTypingIndicator, { room, path }),
52
190
  /* @__PURE__ */ jsx(
53
191
  ChatInput,
54
192
  {
@@ -56,11 +194,220 @@ function Chat({ room, path, participants }) {
56
194
  attachments,
57
195
  onFilesSelected: selectAttachments,
58
196
  setAttachments,
59
- onTextChange,
60
- onCancelRequest: cancelRequest,
61
- showCancelButton: thinking
197
+ onTextChange
62
198
  }
63
- ),
199
+ )
200
+ ] });
201
+ }
202
+ function Chat({
203
+ room,
204
+ path,
205
+ participants,
206
+ agentName,
207
+ toolkit = "chat",
208
+ tool = "new_thread",
209
+ centerComposer = true,
210
+ emptyStateTitle,
211
+ emptyStateDescription,
212
+ onThreadResolved
213
+ }) {
214
+ const [internalThreadPath, setInternalThreadPath] = useState(null);
215
+ const [newThreadDraft, setNewThreadDraft] = useState("");
216
+ const [newThreadAttachments, setNewThreadAttachments] = useState([]);
217
+ const [newThreadError, setNewThreadError] = useState(null);
218
+ const [creatingNewThread, setCreatingNewThread] = useState(false);
219
+ const [waitingForAgent, setWaitingForAgent] = useState(false);
220
+ const activeOperationRef = useRef(0);
221
+ const controlledPath = useMemo(() => normalizeThreadPath(path), [path]);
222
+ const managesOwnThread = controlledPath === null;
223
+ const activePath = controlledPath ?? internalThreadPath;
224
+ useEffect(() => {
225
+ return () => {
226
+ activeOperationRef.current += 1;
227
+ };
228
+ }, []);
229
+ useEffect(() => {
230
+ if (controlledPath !== null) {
231
+ setInternalThreadPath(null);
232
+ }
233
+ }, [controlledPath]);
234
+ useEffect(() => {
235
+ activeOperationRef.current += 1;
236
+ setInternalThreadPath(null);
237
+ setNewThreadDraft("");
238
+ setNewThreadAttachments([]);
239
+ setNewThreadError(null);
240
+ setCreatingNewThread(false);
241
+ setWaitingForAgent(false);
242
+ }, [agentName, managesOwnThread, room]);
243
+ const selectNewThreadAttachments = useCallback((files) => {
244
+ const nextAttachments = files.map((file) => new MeshagentFileUpload(
245
+ room,
246
+ `uploaded-files/${file.name}`,
247
+ fileToAsyncIterable(file),
248
+ file.size
249
+ ));
250
+ setNewThreadAttachments((currentAttachments) => [...currentAttachments, ...nextAttachments]);
251
+ }, [room]);
252
+ const cancelPendingNewThread = useCallback(() => {
253
+ activeOperationRef.current += 1;
254
+ setCreatingNewThread(false);
255
+ setWaitingForAgent(false);
256
+ setNewThreadError(null);
257
+ }, []);
258
+ const openNewThreadComposer = useCallback(() => {
259
+ activeOperationRef.current += 1;
260
+ setInternalThreadPath(null);
261
+ setNewThreadDraft("");
262
+ setNewThreadAttachments([]);
263
+ setNewThreadError(null);
264
+ setCreatingNewThread(false);
265
+ setWaitingForAgent(false);
266
+ }, []);
267
+ const handleCreateThread = useCallback(async () => {
268
+ const text = newThreadDraft.trim();
269
+ const hasDraft = text !== "" || newThreadAttachments.length > 0;
270
+ if (!hasDraft || creatingNewThread || waitingForAgent) {
271
+ return;
272
+ }
273
+ const operationId = activeOperationRef.current + 1;
274
+ activeOperationRef.current = operationId;
275
+ const initialTargetAgent = findTargetAgent(room, agentName);
276
+ setWaitingForAgent(initialTargetAgent === null);
277
+ setCreatingNewThread(initialTargetAgent !== null);
278
+ setNewThreadError(null);
279
+ try {
280
+ const targetAgent = initialTargetAgent ?? await waitForTargetAgent({
281
+ room,
282
+ agentName,
283
+ operationId,
284
+ activeOperationRef
285
+ });
286
+ ensureOperationActive(operationId, activeOperationRef);
287
+ if (initialTargetAgent === null) {
288
+ setWaitingForAgent(false);
289
+ setCreatingNewThread(true);
290
+ }
291
+ await waitForToolkitAvailable({
292
+ room,
293
+ participantId: targetAgent.id,
294
+ toolkit,
295
+ operationId,
296
+ activeOperationRef
297
+ });
298
+ ensureOperationActive(operationId, activeOperationRef);
299
+ const response = await room.agents.invokeTool({
300
+ toolkit,
301
+ tool,
302
+ arguments: {
303
+ message: {
304
+ text,
305
+ attachments: newThreadAttachments.map((attachment) => ({ path: attachment.path }))
306
+ }
307
+ }
308
+ });
309
+ ensureOperationActive(operationId, activeOperationRef);
310
+ if (!(response instanceof JsonContent)) {
311
+ throw new Error(`${toolkit}.${tool} returned non-JSON content`);
312
+ }
313
+ const result = parseThreadToolResult(toolkit, tool, response);
314
+ if (controlledPath === null) {
315
+ setInternalThreadPath(result.path);
316
+ }
317
+ setNewThreadDraft("");
318
+ setNewThreadAttachments([]);
319
+ setNewThreadError(null);
320
+ setCreatingNewThread(false);
321
+ setWaitingForAgent(false);
322
+ onThreadResolved?.(result.path, result.displayName);
323
+ } catch (error) {
324
+ if (error instanceof NewThreadCancelledError) {
325
+ return;
326
+ }
327
+ setCreatingNewThread(false);
328
+ setWaitingForAgent(false);
329
+ setNewThreadError(describeError(error));
330
+ }
331
+ }, [
332
+ agentName,
333
+ controlledPath,
334
+ creatingNewThread,
335
+ newThreadAttachments,
336
+ newThreadDraft,
337
+ onThreadResolved,
338
+ room,
339
+ toolkit,
340
+ tool,
341
+ waitingForAgent
342
+ ]);
343
+ useEffect(() => {
344
+ if (!managesOwnThread) {
345
+ return;
346
+ }
347
+ const handleKeyDown = (event) => {
348
+ if (!(event.ctrlKey || event.metaKey) || event.key.toLowerCase() !== "n") {
349
+ return;
350
+ }
351
+ event.preventDefault();
352
+ openNewThreadComposer();
353
+ };
354
+ window.addEventListener("keydown", handleKeyDown);
355
+ return () => {
356
+ window.removeEventListener("keydown", handleKeyDown);
357
+ };
358
+ }, [managesOwnThread, openNewThreadComposer]);
359
+ const targetAgentLabel = useMemo(() => {
360
+ const knownAgentName = agentName?.trim();
361
+ if (knownAgentName) {
362
+ return displayParticipantName(knownAgentName);
363
+ }
364
+ const targetAgent = findTargetAgent(room);
365
+ return displayParticipantName(targetAgent ? getParticipantName(targetAgent) : null);
366
+ }, [agentName, room]);
367
+ const pendingStatusText = waitingForAgent ? `Waiting for ${targetAgentLabel} to be ready.` : creatingNewThread ? `Starting a thread with ${targetAgentLabel}.` : null;
368
+ const composer = /* @__PURE__ */ jsx(
369
+ ChatInput,
370
+ {
371
+ onSubmit: handleCreateThread,
372
+ attachments: newThreadAttachments,
373
+ onFilesSelected: selectNewThreadAttachments,
374
+ setAttachments: setNewThreadAttachments,
375
+ value: newThreadDraft,
376
+ onValueChange: setNewThreadDraft,
377
+ clearOnSubmit: false,
378
+ showCancelButton: creatingNewThread || waitingForAgent,
379
+ onCancelRequest: cancelPendingNewThread,
380
+ disabled: creatingNewThread || waitingForAgent,
381
+ placeholder: agentName?.trim() ? `Type a message or @${displayParticipantName(agentName)}` : "Type a message"
382
+ }
383
+ );
384
+ return /* @__PURE__ */ jsxs("div", { className: "flex min-h-0 flex-1 flex-col", children: [
385
+ activePath ? /* @__PURE__ */ jsx(
386
+ ResolvedChatView,
387
+ {
388
+ room,
389
+ path: activePath,
390
+ participants,
391
+ agentName,
392
+ emptyStateTitle,
393
+ emptyStateDescription,
394
+ showNewThreadButton: managesOwnThread,
395
+ onStartNewThread: openNewThreadComposer
396
+ },
397
+ activePath
398
+ ) : centerComposer ? /* @__PURE__ */ jsx("div", { className: "flex min-h-0 flex-1 items-center justify-center px-4 py-6", children: /* @__PURE__ */ jsxs("div", { className: "w-full max-w-[912px] space-y-5", children: [
399
+ /* @__PURE__ */ jsxs("div", { className: "space-y-2 text-center", children: [
400
+ /* @__PURE__ */ jsx("h2", { className: "text-4xl font-semibold tracking-tight text-foreground sm:text-5xl", children: "Start a new thread" }),
401
+ pendingStatusText ? /* @__PURE__ */ jsx("p", { className: "text-sm text-muted-foreground sm:text-base", children: pendingStatusText }) : null
402
+ ] }),
403
+ composer,
404
+ newThreadError ? /* @__PURE__ */ jsx(ErrorBanner, { message: newThreadError }) : null
405
+ ] }) }) : /* @__PURE__ */ jsxs("div", { className: "flex min-h-0 flex-1 flex-col", children: [
406
+ /* @__PURE__ */ jsx("div", { className: "flex-1", children: emptyStateTitle ? /* @__PURE__ */ jsx(EmptyState, { title: emptyStateTitle, description: emptyStateDescription }) : null }),
407
+ pendingStatusText ? /* @__PURE__ */ jsx("div", { className: "px-4 pb-2", children: /* @__PURE__ */ jsx("div", { className: "mx-auto w-full max-w-[912px] text-sm text-muted-foreground", children: pendingStatusText }) }) : null,
408
+ newThreadError ? /* @__PURE__ */ jsx("div", { className: "px-4 pb-2", children: /* @__PURE__ */ jsx(ErrorBanner, { message: newThreadError }) }) : null,
409
+ composer
410
+ ] }),
64
411
  /* @__PURE__ */ jsx(Toaster, {})
65
412
  ] });
66
413
  }
@@ -0,0 +1,29 @@
1
+ import type { ReactElement } from "react";
2
+ import { Participant, RoomClient } from "@meshagent/meshagent";
3
+ import { ChatThreadDisplayMode } from "./conversation-descriptor";
4
+ export { ChatThreadDisplayMode, chatDocumentPath, resolvedThreadListPath, } from "./conversation-descriptor";
5
+ export interface ChatBotViewProps {
6
+ room: RoomClient;
7
+ path?: string;
8
+ documentPath?: string;
9
+ participants?: Participant[];
10
+ agentName?: string;
11
+ threadDisplayMode?: ChatThreadDisplayMode;
12
+ threadDir?: string;
13
+ threadListPath?: string;
14
+ toolkit?: string;
15
+ tool?: string;
16
+ centerComposer?: boolean;
17
+ emptyStateTitle?: string;
18
+ emptyStateDescription?: string;
19
+ selectedThreadPath?: string | null;
20
+ selectedThreadDisplayName?: string | null;
21
+ onSelectedThreadPathChanged?: (path: string | null) => void;
22
+ onSelectedThreadResolved?: (path: string | null, displayName: string | null) => void;
23
+ onThreadResolved?: (path: string | null, displayName: string | null) => void;
24
+ newThreadResetVersion?: number;
25
+ showThreadList?: boolean;
26
+ threadListWidth?: number;
27
+ threadListCollapsedHeight?: number;
28
+ }
29
+ export declare function ChatBotView({ room, path, documentPath, participants, agentName, threadDisplayMode, threadDir, threadListPath, toolkit, tool, centerComposer, emptyStateTitle, emptyStateDescription, selectedThreadPath, onSelectedThreadPathChanged, onSelectedThreadResolved, onThreadResolved, newThreadResetVersion, showThreadList, threadListWidth, threadListCollapsedHeight, }: ChatBotViewProps): ReactElement;