@meshagent/meshagent-tailwind 0.38.1 → 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 +12 -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
@@ -0,0 +1,491 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+ var ChatBotView_exports = {};
20
+ __export(ChatBotView_exports, {
21
+ ChatBotView: () => ChatBotView,
22
+ ChatThreadDisplayMode: () => import_conversation_descriptor2.ChatThreadDisplayMode,
23
+ chatDocumentPath: () => import_conversation_descriptor2.chatDocumentPath,
24
+ resolvedThreadListPath: () => import_conversation_descriptor2.resolvedThreadListPath
25
+ });
26
+ module.exports = __toCommonJS(ChatBotView_exports);
27
+ var import_jsx_runtime = require("react/jsx-runtime");
28
+ var import_react = require("react");
29
+ var import_meshagent_react = require("@meshagent/meshagent-react");
30
+ var import_lucide_react = require("lucide-react");
31
+ var import_chat_hooks = require("./chat-hooks");
32
+ var import_Chat = require("./Chat");
33
+ var import_button = require("./components/ui/button");
34
+ var import_spinner = require("./components/ui/spinner");
35
+ var import_conversation_descriptor = require("./conversation-descriptor");
36
+ var import_utils = require("./lib/utils");
37
+ var import_multi_thread_view = require("./multi-thread-view");
38
+ var import_conversation_descriptor2 = require("./conversation-descriptor");
39
+ const multiThreadLayoutBreakpointPx = 920;
40
+ function normalizePath(path) {
41
+ const normalized = path?.trim();
42
+ return normalized ? normalized : null;
43
+ }
44
+ function parseDate(value) {
45
+ const parsed = new Date(value);
46
+ return Number.isNaN(parsed.getTime()) ? /* @__PURE__ */ new Date(0) : parsed;
47
+ }
48
+ function compareThreadEntries(left, right) {
49
+ const leftSortDate = left.modifiedAt.trim() ? parseDate(left.modifiedAt) : parseDate(left.createdAt);
50
+ const rightSortDate = right.modifiedAt.trim() ? parseDate(right.modifiedAt) : parseDate(right.createdAt);
51
+ const dateComparison = rightSortDate.getTime() - leftSortDate.getTime();
52
+ if (dateComparison !== 0) {
53
+ return dateComparison;
54
+ }
55
+ const leftCreatedAt = parseDate(left.createdAt);
56
+ const rightCreatedAt = parseDate(right.createdAt);
57
+ const createdDateComparison = rightCreatedAt.getTime() - leftCreatedAt.getTime();
58
+ if (createdDateComparison !== 0) {
59
+ return createdDateComparison;
60
+ }
61
+ return left.path.localeCompare(right.path);
62
+ }
63
+ function parseThreadListEntries(document) {
64
+ const entries = [];
65
+ for (const child of document.root.getChildren()) {
66
+ if (child.tagName !== "thread") {
67
+ continue;
68
+ }
69
+ const rawPath = child.getAttribute("path");
70
+ if (typeof rawPath !== "string" || rawPath.trim() === "") {
71
+ continue;
72
+ }
73
+ const path = rawPath.trim();
74
+ const rawName = child.getAttribute("name");
75
+ const rawCreatedAt = child.getAttribute("created_at");
76
+ const rawModifiedAt = child.getAttribute("modified_at");
77
+ entries.push({
78
+ element: child,
79
+ path,
80
+ name: typeof rawName === "string" && rawName.trim() !== "" ? rawName.trim() : (0, import_conversation_descriptor.defaultThreadDisplayNameFromPath)(path),
81
+ createdAt: typeof rawCreatedAt === "string" ? rawCreatedAt : "",
82
+ modifiedAt: typeof rawModifiedAt === "string" ? rawModifiedAt : ""
83
+ });
84
+ }
85
+ entries.sort(compareThreadEntries);
86
+ return entries;
87
+ }
88
+ function threadEntriesEqual(left, right) {
89
+ return left.length === right.length && left.every((entry, index) => {
90
+ const other = right[index];
91
+ return entry.path === other?.path && entry.name === other.name && entry.createdAt === other.createdAt && entry.modifiedAt === other.modifiedAt;
92
+ });
93
+ }
94
+ function describeError(error) {
95
+ if (error instanceof Error && error.message.trim() !== "") {
96
+ return error.message;
97
+ }
98
+ return `${error}`;
99
+ }
100
+ async function closeDocument(room, path) {
101
+ try {
102
+ await room.sync.close(path);
103
+ } catch {
104
+ }
105
+ }
106
+ function useIsWideLayout(minWidth) {
107
+ const [matches, setMatches] = (0, import_react.useState)(false);
108
+ (0, import_react.useEffect)(() => {
109
+ if (typeof window === "undefined") {
110
+ return;
111
+ }
112
+ const mediaQuery = window.matchMedia(`(min-width: ${minWidth}px)`);
113
+ const updateMatches = (event) => {
114
+ setMatches(event?.matches ?? mediaQuery.matches);
115
+ };
116
+ updateMatches();
117
+ mediaQuery.addEventListener("change", updateMatches);
118
+ return () => {
119
+ mediaQuery.removeEventListener("change", updateMatches);
120
+ };
121
+ }, [minWidth]);
122
+ return matches;
123
+ }
124
+ function useThreadListDocument({
125
+ room,
126
+ path
127
+ }) {
128
+ const [document, setDocument] = (0, import_react.useState)(null);
129
+ const [entries, setEntries] = (0, import_react.useState)([]);
130
+ const [loading, setLoading] = (0, import_react.useState)(path !== null);
131
+ const [error, setError] = (0, import_react.useState)(null);
132
+ const syncDocumentState = (0, import_react.useCallback)((nextDocument) => {
133
+ const nextEntries = parseThreadListEntries(nextDocument);
134
+ setEntries((currentEntries) => threadEntriesEqual(currentEntries, nextEntries) ? currentEntries : nextEntries);
135
+ }, []);
136
+ (0, import_react.useEffect)(() => {
137
+ let cancelled = false;
138
+ let opened = false;
139
+ if (path === null) {
140
+ setDocument(null);
141
+ setEntries([]);
142
+ setLoading(false);
143
+ setError(null);
144
+ return;
145
+ }
146
+ setDocument(null);
147
+ setEntries([]);
148
+ setLoading(true);
149
+ setError(null);
150
+ void room.sync.open(path).then((nextDocument) => {
151
+ if (cancelled) {
152
+ void closeDocument(room, path);
153
+ return;
154
+ }
155
+ opened = true;
156
+ setDocument(nextDocument);
157
+ syncDocumentState(nextDocument);
158
+ setLoading(false);
159
+ setError(null);
160
+ }).catch((nextError) => {
161
+ if (cancelled) {
162
+ return;
163
+ }
164
+ setDocument(null);
165
+ setEntries([]);
166
+ setLoading(false);
167
+ setError(nextError);
168
+ });
169
+ return () => {
170
+ cancelled = true;
171
+ if (opened) {
172
+ void closeDocument(room, path);
173
+ }
174
+ };
175
+ }, [path, room, syncDocumentState]);
176
+ (0, import_meshagent_react.useDocumentChanged)({
177
+ document,
178
+ onChanged: syncDocumentState
179
+ });
180
+ return {
181
+ document,
182
+ entries,
183
+ loading,
184
+ error
185
+ };
186
+ }
187
+ function ThreadListRow({
188
+ title,
189
+ selected,
190
+ onClick,
191
+ icon,
192
+ trailing
193
+ }) {
194
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "px-2 py-1", children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
195
+ "div",
196
+ {
197
+ className: (0, import_utils.cn)(
198
+ "flex min-w-0 items-center rounded-lg border border-transparent transition-colors",
199
+ selected ? "bg-accent text-accent-foreground" : "text-muted-foreground hover:bg-accent/50 hover:text-foreground"
200
+ ),
201
+ children: [
202
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
203
+ "button",
204
+ {
205
+ type: "button",
206
+ className: "flex min-w-0 flex-1 items-center gap-3 px-3 py-2 text-left",
207
+ onClick,
208
+ children: [
209
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "flex h-4 w-4 shrink-0 items-center justify-center", children: icon }),
210
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
211
+ "span",
212
+ {
213
+ className: (0, import_utils.cn)(
214
+ "truncate text-sm font-medium",
215
+ selected ? "text-accent-foreground" : "text-foreground"
216
+ ),
217
+ children: title
218
+ }
219
+ )
220
+ ]
221
+ }
222
+ ),
223
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "shrink-0 pr-1", children: trailing ?? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "h-8 w-8" }) })
224
+ ]
225
+ }
226
+ ) });
227
+ }
228
+ function ThreadListEntryRow({
229
+ room,
230
+ entry,
231
+ agentName,
232
+ selected,
233
+ onSelect,
234
+ onRename
235
+ }) {
236
+ const status = (0, import_chat_hooks.useThreadStatus)({ room, path: entry.path, agentName });
237
+ const iconClassName = selected ? "text-accent-foreground" : "text-muted-foreground";
238
+ const hasStatus = status.text?.trim() !== "";
239
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
240
+ ThreadListRow,
241
+ {
242
+ title: entry.name,
243
+ selected,
244
+ onClick: () => onSelect(entry),
245
+ icon: hasStatus ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_spinner.Spinner, { size: "sm", className: iconClassName }) : selected ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_lucide_react.Check, { className: (0, import_utils.cn)("h-4 w-4", iconClassName) }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_lucide_react.MessageSquare, { className: (0, import_utils.cn)("h-4 w-4", iconClassName) }),
246
+ trailing: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
247
+ import_button.Button,
248
+ {
249
+ type: "button",
250
+ variant: "ghost",
251
+ size: "icon",
252
+ className: "h-8 w-8 rounded-md",
253
+ "aria-label": `Rename ${entry.name}`,
254
+ onClick: () => onRename(entry),
255
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_lucide_react.Pencil, { className: "h-4 w-4" })
256
+ }
257
+ )
258
+ }
259
+ );
260
+ }
261
+ function ThreadListPanel({
262
+ room,
263
+ threadList,
264
+ selectedThreadPath,
265
+ agentName,
266
+ onSelectThread,
267
+ onClearSelection,
268
+ onRenameThread
269
+ }) {
270
+ const { entries, error, loading } = threadList;
271
+ const hasSelectedEntry = selectedThreadPath !== null && entries.some((entry) => entry.path === selectedThreadPath);
272
+ const showPendingNewThreadSelection = selectedThreadPath === null || !hasSelectedEntry;
273
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "flex h-full min-h-0 flex-col overflow-hidden rounded-2xl border bg-background", children: loading ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "flex min-h-0 flex-1 items-center justify-center p-6", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_spinner.Spinner, { size: "lg", className: "text-muted-foreground" }) }) : error ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "flex min-h-0 flex-1 items-center justify-center p-6 text-center text-sm text-muted-foreground", children: `Unable to load threads: ${describeError(error)}` }) : /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "flex min-h-0 flex-1 flex-col overflow-y-auto py-1", children: [
274
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
275
+ ThreadListRow,
276
+ {
277
+ title: "New thread",
278
+ selected: showPendingNewThreadSelection,
279
+ onClick: onClearSelection,
280
+ icon: showPendingNewThreadSelection ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_lucide_react.Check, { className: "h-4 w-4 text-accent-foreground" }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_lucide_react.MessageSquarePlus, { className: "h-4 w-4 text-muted-foreground" })
281
+ }
282
+ ),
283
+ entries.length === 0 && showPendingNewThreadSelection ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "flex min-h-0 flex-1 items-center justify-center px-4 py-6 text-center text-sm text-muted-foreground", children: "No threads yet" }) : null,
284
+ entries.map((entry) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
285
+ ThreadListEntryRow,
286
+ {
287
+ room,
288
+ entry,
289
+ agentName,
290
+ selected: entry.path === selectedThreadPath,
291
+ onSelect: onSelectThread,
292
+ onRename: onRenameThread
293
+ },
294
+ entry.path
295
+ ))
296
+ ] }) });
297
+ }
298
+ function MultiThreadUnavailable() {
299
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "flex min-h-0 flex-1 items-center justify-center px-4 py-8", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "w-full max-w-[912px] rounded-3xl border border-destructive/30 bg-destructive/5 p-6 text-destructive", children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "flex items-start gap-3", children: [
300
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_lucide_react.AlertTriangle, { className: "mt-0.5 h-5 w-5 shrink-0" }),
301
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { children: [
302
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("h2", { className: "text-lg font-semibold", children: "Unable to start a new thread" }),
303
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "mt-1 text-sm text-destructive/80", children: "No chat agent is selected." })
304
+ ] })
305
+ ] }) }) });
306
+ }
307
+ function ChatBotView({
308
+ room,
309
+ path,
310
+ documentPath,
311
+ participants,
312
+ agentName,
313
+ threadDisplayMode = import_conversation_descriptor.ChatThreadDisplayMode.SingleThread,
314
+ threadDir,
315
+ threadListPath,
316
+ toolkit,
317
+ tool,
318
+ centerComposer = false,
319
+ emptyStateTitle = "No threads yet",
320
+ emptyStateDescription = "Start a new conversation to see it here.",
321
+ selectedThreadPath,
322
+ onSelectedThreadPathChanged,
323
+ onSelectedThreadResolved,
324
+ onThreadResolved,
325
+ newThreadResetVersion = 0,
326
+ showThreadList = true,
327
+ threadListWidth = 280,
328
+ threadListCollapsedHeight = 220
329
+ }) {
330
+ const isWideLayout = useIsWideLayout(multiThreadLayoutBreakpointPx);
331
+ const resolvedDocumentPath = (0, import_react.useMemo)(
332
+ () => normalizePath(documentPath ?? path),
333
+ [documentPath, path]
334
+ );
335
+ const resolvedSingleThreadPath = (0, import_react.useMemo)(
336
+ () => resolvedDocumentPath ?? (0, import_conversation_descriptor.chatDocumentPath)(agentName, { threadDir }),
337
+ [agentName, resolvedDocumentPath, threadDir]
338
+ );
339
+ const explicitSelectedThreadPath = selectedThreadPath !== void 0 ? normalizePath(selectedThreadPath) : void 0;
340
+ const legacySelectedThreadPath = threadDisplayMode === import_conversation_descriptor.ChatThreadDisplayMode.MultiThreadComposer ? resolvedDocumentPath : null;
341
+ const [internalSelectedThreadPath, setInternalSelectedThreadPath] = (0, import_react.useState)(() => explicitSelectedThreadPath ?? legacySelectedThreadPath ?? null);
342
+ const previousLegacySelectedThreadPathRef = (0, import_react.useRef)(legacySelectedThreadPath);
343
+ const previousNewThreadResetVersionRef = (0, import_react.useRef)(newThreadResetVersion);
344
+ const activeSelectedThreadPath = explicitSelectedThreadPath ?? internalSelectedThreadPath;
345
+ const resolvedThreadListDocumentPath = (0, import_react.useMemo)(
346
+ () => (0, import_conversation_descriptor.resolvedThreadListPath)(threadListPath, { threadDir, agentName }),
347
+ [agentName, threadDir, threadListPath]
348
+ );
349
+ const threadList = useThreadListDocument({
350
+ room,
351
+ path: threadDisplayMode === import_conversation_descriptor.ChatThreadDisplayMode.MultiThreadComposer && showThreadList && resolvedThreadListDocumentPath !== null ? resolvedThreadListDocumentPath : null
352
+ });
353
+ (0, import_react.useEffect)(() => {
354
+ if (explicitSelectedThreadPath === void 0) {
355
+ return;
356
+ }
357
+ setInternalSelectedThreadPath(explicitSelectedThreadPath);
358
+ }, [explicitSelectedThreadPath]);
359
+ (0, import_react.useEffect)(() => {
360
+ if (explicitSelectedThreadPath !== void 0) {
361
+ previousLegacySelectedThreadPathRef.current = legacySelectedThreadPath;
362
+ return;
363
+ }
364
+ if (legacySelectedThreadPath !== previousLegacySelectedThreadPathRef.current) {
365
+ setInternalSelectedThreadPath(legacySelectedThreadPath);
366
+ }
367
+ previousLegacySelectedThreadPathRef.current = legacySelectedThreadPath;
368
+ }, [explicitSelectedThreadPath, legacySelectedThreadPath]);
369
+ const emitResolvedThread = (0, import_react.useCallback)((nextPath, displayName) => {
370
+ onSelectedThreadResolved?.(nextPath, displayName);
371
+ onThreadResolved?.(nextPath, displayName);
372
+ }, [onSelectedThreadResolved, onThreadResolved]);
373
+ const handleSelectedThreadPathChanged = (0, import_react.useCallback)((nextPath) => {
374
+ const normalizedNextPath = normalizePath(nextPath);
375
+ if (explicitSelectedThreadPath === void 0) {
376
+ setInternalSelectedThreadPath(normalizedNextPath);
377
+ }
378
+ onSelectedThreadPathChanged?.(normalizedNextPath);
379
+ }, [explicitSelectedThreadPath, onSelectedThreadPathChanged]);
380
+ const setSelectedThread = (0, import_react.useCallback)((nextPath, displayName) => {
381
+ const normalizedNextPath = normalizePath(nextPath);
382
+ handleSelectedThreadPathChanged(normalizedNextPath);
383
+ emitResolvedThread(normalizedNextPath, displayName);
384
+ }, [emitResolvedThread, handleSelectedThreadPathChanged]);
385
+ (0, import_react.useEffect)(() => {
386
+ if (threadDisplayMode !== import_conversation_descriptor.ChatThreadDisplayMode.MultiThreadComposer) {
387
+ previousNewThreadResetVersionRef.current = newThreadResetVersion;
388
+ return;
389
+ }
390
+ if (previousNewThreadResetVersionRef.current !== newThreadResetVersion && activeSelectedThreadPath !== null) {
391
+ setSelectedThread(null, null);
392
+ }
393
+ previousNewThreadResetVersionRef.current = newThreadResetVersion;
394
+ }, [activeSelectedThreadPath, newThreadResetVersion, setSelectedThread, threadDisplayMode]);
395
+ const handleRenameThread = (0, import_react.useCallback)((entry) => {
396
+ if (typeof window === "undefined") {
397
+ return;
398
+ }
399
+ const nextName = window.prompt("Rename thread", entry.name);
400
+ if (nextName === null) {
401
+ return;
402
+ }
403
+ const trimmedName = nextName.trim();
404
+ if (trimmedName === "" || trimmedName === entry.name) {
405
+ return;
406
+ }
407
+ entry.element.setAttribute("name", trimmedName);
408
+ if (entry.path === activeSelectedThreadPath) {
409
+ emitResolvedThread(entry.path, trimmedName);
410
+ }
411
+ }, [activeSelectedThreadPath, emitResolvedThread]);
412
+ if (threadDisplayMode !== import_conversation_descriptor.ChatThreadDisplayMode.MultiThreadComposer) {
413
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
414
+ import_Chat.Chat,
415
+ {
416
+ room,
417
+ path: resolvedSingleThreadPath,
418
+ participants,
419
+ agentName,
420
+ toolkit,
421
+ tool,
422
+ centerComposer,
423
+ emptyStateTitle,
424
+ emptyStateDescription,
425
+ onThreadResolved
426
+ }
427
+ );
428
+ }
429
+ if (!agentName?.trim()) {
430
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(MultiThreadUnavailable, {});
431
+ }
432
+ const content = /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
433
+ import_multi_thread_view.MultiThreadView,
434
+ {
435
+ room,
436
+ agentName,
437
+ toolkit,
438
+ tool,
439
+ selectedThreadPath: activeSelectedThreadPath,
440
+ onSelectedThreadPathChanged: handleSelectedThreadPathChanged,
441
+ onSelectedThreadResolved: emitResolvedThread,
442
+ newThreadResetVersion,
443
+ centerComposer,
444
+ emptyStateTitle,
445
+ emptyStateDescription,
446
+ builder: (threadPath) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
447
+ import_Chat.Chat,
448
+ {
449
+ room,
450
+ path: threadPath,
451
+ participants,
452
+ agentName,
453
+ toolkit,
454
+ tool,
455
+ centerComposer,
456
+ emptyStateTitle,
457
+ emptyStateDescription
458
+ }
459
+ )
460
+ }
461
+ );
462
+ if (!showThreadList || resolvedThreadListDocumentPath === null) {
463
+ return content;
464
+ }
465
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: (0, import_utils.cn)("flex flex-1 h-full", isWideLayout ? "flex-row items-stretch" : "flex-col"), children: [
466
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "flex flex-col h-full min-h-0 min-w-0 flex-1", children: content }),
467
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
468
+ "div",
469
+ {
470
+ className: (0, import_utils.cn)("shrink-0 mr-4", isWideLayout ? "ml-3" : "mt-3"),
471
+ style: isWideLayout ? { width: threadListWidth } : { height: threadListCollapsedHeight },
472
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
473
+ ThreadListPanel,
474
+ {
475
+ room,
476
+ threadList,
477
+ selectedThreadPath: activeSelectedThreadPath,
478
+ agentName,
479
+ onSelectThread: (entry) => {
480
+ setSelectedThread(entry.path, entry.name);
481
+ },
482
+ onClearSelection: () => {
483
+ setSelectedThread(null, null);
484
+ },
485
+ onRenameThread: handleRenameThread
486
+ }
487
+ )
488
+ }
489
+ )
490
+ ] });
491
+ }
@@ -1,12 +1,21 @@
1
- import { ChatMessage, FileUpload } from "@meshagent/meshagent-react";
1
+ import type { ReactElement } from "react";
2
+ import { ChatMessage } from "./chat-message";
3
+ import { type FileUpload } from "./file-attachment";
2
4
  interface ChatInputProps {
3
- onSubmit: (message: ChatMessage) => void;
5
+ onSubmit: (message: ChatMessage) => void | Promise<void>;
4
6
  onFilesSelected: (files: File[]) => void;
5
7
  attachments: FileUpload[];
6
8
  setAttachments: (attachments: FileUpload[]) => void;
7
9
  onTextChange?: (text: string) => void;
8
10
  onCancelRequest?: () => void;
9
11
  showCancelButton?: boolean;
12
+ placeholder?: string;
13
+ disabled?: boolean;
14
+ clearOnSubmit?: boolean;
15
+ autoFocus?: boolean;
16
+ value?: string;
17
+ defaultValue?: string;
18
+ onValueChange?: (value: string) => void;
10
19
  }
11
- export declare function ChatInput({ onSubmit, onFilesSelected, attachments, setAttachments, onTextChange, onCancelRequest, showCancelButton }: ChatInputProps): import("react/jsx-runtime").JSX.Element;
20
+ export declare function ChatInput({ onSubmit, onFilesSelected, attachments, setAttachments, onTextChange, onCancelRequest, showCancelButton, placeholder, disabled, clearOnSubmit, autoFocus, value: controlledValue, defaultValue, onValueChange, }: ChatInputProps): ReactElement;
12
21
  export {};