@coral-ai/chat 0.4.2 → 0.6.0
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/README.md +14 -0
- package/dist/index.d.ts +35 -11
- package/dist/index.js +140 -277
- package/dist/index.js.map +1 -1
- package/package.json +7 -7
package/dist/index.js
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
// src/Chat.tsx
|
|
2
|
-
import { useLayoutEffect as useLayoutEffect3, useRef as useRef7, useState as useState7 } from "react";
|
|
3
2
|
import {
|
|
4
|
-
Caption1 as
|
|
3
|
+
Caption1 as Caption13,
|
|
5
4
|
Title3,
|
|
6
5
|
makeStyles as makeStyles10,
|
|
7
6
|
motionTokens
|
|
@@ -183,7 +182,7 @@ var useStyles2 = makeStyles2({
|
|
|
183
182
|
zIndex: 1e3,
|
|
184
183
|
cursor: "pointer",
|
|
185
184
|
boxShadow: tokens2.shadow8,
|
|
186
|
-
marginBottom: "
|
|
185
|
+
marginBottom: "12px",
|
|
187
186
|
backgroundColor: "var(--colorNeutralBackgroundAlpha2)",
|
|
188
187
|
backdropFilter: "blur(40px) saturate(150%)"
|
|
189
188
|
}
|
|
@@ -424,32 +423,54 @@ var ChatCanvas = ({
|
|
|
424
423
|
const response = await resolvedHandler(textToSend, historyForAI, snapshotAttachments.map((a) => a.file));
|
|
425
424
|
if (isAsyncIterable(response)) {
|
|
426
425
|
let assistantContent = "";
|
|
426
|
+
const blocks = [];
|
|
427
|
+
let openText = "";
|
|
428
|
+
let todosIndex = null;
|
|
427
429
|
let rafId = null;
|
|
428
|
-
let pendingContent = "";
|
|
429
430
|
let streamedApproval;
|
|
430
|
-
|
|
431
|
-
|
|
431
|
+
const snapshotBlocks = () => openText ? [...blocks, { type: "text", content: openText }] : blocks;
|
|
432
|
+
const flushOpenText = () => {
|
|
433
|
+
if (openText) {
|
|
434
|
+
blocks.push({ type: "text", content: openText });
|
|
435
|
+
openText = "";
|
|
436
|
+
}
|
|
437
|
+
};
|
|
438
|
+
const commit = () => {
|
|
439
|
+
const nextBlocks = snapshotBlocks();
|
|
440
|
+
let nextMsg = {
|
|
441
|
+
id: assistantId,
|
|
442
|
+
role: "assistant",
|
|
443
|
+
content: assistantContent,
|
|
444
|
+
blocks: nextBlocks
|
|
445
|
+
};
|
|
446
|
+
setMessages((prev) => {
|
|
447
|
+
const updated = [...prev];
|
|
448
|
+
const last = updated[updated.length - 1];
|
|
449
|
+
if (last && last.id === assistantId) {
|
|
450
|
+
nextMsg = {
|
|
451
|
+
...last,
|
|
452
|
+
content: assistantContent,
|
|
453
|
+
blocks: nextBlocks
|
|
454
|
+
};
|
|
455
|
+
}
|
|
456
|
+
updated[updated.length - 1] = nextMsg;
|
|
457
|
+
return updated;
|
|
458
|
+
});
|
|
459
|
+
onMessagesChange?.(
|
|
460
|
+
[...updatedMessages, nextMsg],
|
|
461
|
+
sessionAtSend
|
|
462
|
+
);
|
|
463
|
+
};
|
|
432
464
|
for await (const chunk of response) {
|
|
433
465
|
if (shouldStopRef.current) break;
|
|
434
466
|
if (sessionAtSend !== void 0 && currentConversationIdRef.current !== sessionAtSend) break;
|
|
435
467
|
if (typeof chunk === "string") {
|
|
436
468
|
assistantContent += chunk;
|
|
437
|
-
|
|
469
|
+
openText += chunk;
|
|
438
470
|
if (rafId === null) {
|
|
439
471
|
rafId = requestAnimationFrame(() => {
|
|
440
|
-
const content = pendingContent;
|
|
441
|
-
let nextMsg = { id: assistantId, role: "assistant", content };
|
|
442
|
-
setMessages((prev) => {
|
|
443
|
-
const updated = [...prev];
|
|
444
|
-
const last = updated[updated.length - 1];
|
|
445
|
-
if (last && last.id === assistantId) {
|
|
446
|
-
nextMsg = { ...last, content };
|
|
447
|
-
}
|
|
448
|
-
updated[updated.length - 1] = nextMsg;
|
|
449
|
-
return updated;
|
|
450
|
-
});
|
|
451
|
-
onMessagesChange?.([...updatedMessages, nextMsg], sessionAtSend);
|
|
452
472
|
rafId = null;
|
|
473
|
+
commit();
|
|
453
474
|
});
|
|
454
475
|
}
|
|
455
476
|
} else if (chunk.type === "reasoning") {
|
|
@@ -468,26 +489,18 @@ var ChatCanvas = ({
|
|
|
468
489
|
return updated;
|
|
469
490
|
});
|
|
470
491
|
} else if (chunk.type === "todos") {
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
});
|
|
492
|
+
if (todosIndex === null) {
|
|
493
|
+
flushOpenText();
|
|
494
|
+
todosIndex = blocks.length;
|
|
495
|
+
blocks.push({ type: "todos", todos: chunk.todos });
|
|
496
|
+
} else {
|
|
497
|
+
blocks[todosIndex] = { type: "todos", todos: chunk.todos };
|
|
498
|
+
}
|
|
499
|
+
commit();
|
|
480
500
|
} else if (chunk.type === "chart") {
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
const updated = [...prev];
|
|
485
|
-
const last = updated[updated.length - 1];
|
|
486
|
-
if (last && last.id === assistantId) {
|
|
487
|
-
updated[updated.length - 1] = { ...last, charts: nextCharts };
|
|
488
|
-
}
|
|
489
|
-
return updated;
|
|
490
|
-
});
|
|
501
|
+
flushOpenText();
|
|
502
|
+
blocks.push({ type: "chart", spec: chunk.spec });
|
|
503
|
+
commit();
|
|
491
504
|
}
|
|
492
505
|
}
|
|
493
506
|
if (rafId !== null) cancelAnimationFrame(rafId);
|
|
@@ -495,14 +508,14 @@ var ChatCanvas = ({
|
|
|
495
508
|
if (sessionAtSend !== void 0 && currentConversationIdRef.current !== sessionAtSend) {
|
|
496
509
|
break;
|
|
497
510
|
}
|
|
511
|
+
flushOpenText();
|
|
498
512
|
const finalMsg = {
|
|
499
513
|
id: assistantId,
|
|
500
514
|
role: "assistant",
|
|
501
515
|
content: assistantContent,
|
|
516
|
+
blocks,
|
|
502
517
|
...reasoningRef.current ? { metadata: { reasoning: reasoningRef.current } } : {},
|
|
503
|
-
...streamedApproval ? { approval: streamedApproval } : {}
|
|
504
|
-
...streamedTodos ? { todos: streamedTodos } : {},
|
|
505
|
-
...streamedCharts ? { charts: streamedCharts } : {}
|
|
518
|
+
...streamedApproval ? { approval: streamedApproval } : {}
|
|
506
519
|
};
|
|
507
520
|
const finalMessages = [...updatedMessages, finalMsg];
|
|
508
521
|
setMessages(finalMessages);
|
|
@@ -661,29 +674,12 @@ var ChatCanvas = ({
|
|
|
661
674
|
const baseMessages = messages.slice(0, userIdx + 1);
|
|
662
675
|
await runHandler(userMsg.content, baseMessages, []);
|
|
663
676
|
};
|
|
664
|
-
const editMessage = async (messageId, newContent) => {
|
|
665
|
-
const idx = messages.findIndex((m) => m.id === messageId);
|
|
666
|
-
if (idx === -1) return;
|
|
667
|
-
if (messages[idx].role !== "user") return;
|
|
668
|
-
const trimmed = newContent.replace(/^[\n\r]+|[\n\r]+$/g, "");
|
|
669
|
-
if (!trimmed.trim()) return;
|
|
670
|
-
const editedMessage = {
|
|
671
|
-
...messages[idx],
|
|
672
|
-
content: trimmed
|
|
673
|
-
};
|
|
674
|
-
const baseMessages = [
|
|
675
|
-
...messages.slice(0, idx),
|
|
676
|
-
editedMessage
|
|
677
|
-
];
|
|
678
|
-
await runHandler(trimmed, baseMessages, []);
|
|
679
|
-
};
|
|
680
677
|
return /* @__PURE__ */ jsx2(
|
|
681
678
|
ChatContext.Provider,
|
|
682
679
|
{
|
|
683
680
|
value: {
|
|
684
681
|
sendMessage,
|
|
685
682
|
regenerate,
|
|
686
|
-
editMessage,
|
|
687
683
|
scrollToBottom,
|
|
688
684
|
handleCopy,
|
|
689
685
|
messages,
|
|
@@ -719,6 +715,7 @@ var ChatCanvas = ({
|
|
|
719
715
|
Button2,
|
|
720
716
|
{
|
|
721
717
|
onClick: scrollToBottom,
|
|
718
|
+
"aria-label": "Scroll to bottom",
|
|
722
719
|
className: styles.scrollToBottom,
|
|
723
720
|
shape: "circular",
|
|
724
721
|
style: {
|
|
@@ -741,15 +738,12 @@ import React5, { useEffect as useEffect4, useLayoutEffect as useLayoutEffect2, u
|
|
|
741
738
|
import {
|
|
742
739
|
Body1 as Body15,
|
|
743
740
|
Button as Button4,
|
|
744
|
-
Caption1 as Caption12,
|
|
745
741
|
makeStyles as makeStyles7,
|
|
746
742
|
tokens as tokens7
|
|
747
743
|
} from "@fluentui/react-components";
|
|
748
744
|
import {
|
|
749
745
|
ArrowClockwise,
|
|
750
|
-
Copy
|
|
751
|
-
Edit as EditIcon,
|
|
752
|
-
Info
|
|
746
|
+
Copy
|
|
753
747
|
} from "@coral-ai/bundleicons";
|
|
754
748
|
import {
|
|
755
749
|
CoralMarkdown
|
|
@@ -1214,7 +1208,19 @@ var Chat_TodoList_default = ChatTodoList;
|
|
|
1214
1208
|
// src/Chat.Messages.tsx
|
|
1215
1209
|
import { CoralChart } from "@coral-ai/charts";
|
|
1216
1210
|
import { CheckmarkCircle20Filled } from "@fluentui/react-icons";
|
|
1217
|
-
import {
|
|
1211
|
+
import { jsx as jsx7, jsxs as jsxs7 } from "react/jsx-runtime";
|
|
1212
|
+
function resolveBlocks(msg) {
|
|
1213
|
+
if (msg.blocks) return msg.blocks;
|
|
1214
|
+
const legacy = [];
|
|
1215
|
+
if (msg.todos && msg.todos.length > 0) {
|
|
1216
|
+
legacy.push({ type: "todos", todos: msg.todos });
|
|
1217
|
+
}
|
|
1218
|
+
if (msg.charts) {
|
|
1219
|
+
for (const spec of msg.charts) legacy.push({ type: "chart", spec });
|
|
1220
|
+
}
|
|
1221
|
+
if (msg.content) legacy.push({ type: "text", content: msg.content });
|
|
1222
|
+
return legacy;
|
|
1223
|
+
}
|
|
1218
1224
|
var useStyles7 = makeStyles7({
|
|
1219
1225
|
messages: {
|
|
1220
1226
|
flex: "1",
|
|
@@ -1230,7 +1236,7 @@ var useStyles7 = makeStyles7({
|
|
|
1230
1236
|
messageWrapper: {
|
|
1231
1237
|
display: "flex",
|
|
1232
1238
|
flexDirection: "column",
|
|
1233
|
-
gap: "
|
|
1239
|
+
gap: "0px",
|
|
1234
1240
|
width: "100%",
|
|
1235
1241
|
maxWidth: "768px",
|
|
1236
1242
|
padding: "0 16px",
|
|
@@ -1260,51 +1266,12 @@ var useStyles7 = makeStyles7({
|
|
|
1260
1266
|
display: "flex",
|
|
1261
1267
|
justifyContent: "flex-end",
|
|
1262
1268
|
marginTop: "6px",
|
|
1263
|
-
marginRight: "-10px",
|
|
1264
1269
|
opacity: 0,
|
|
1265
1270
|
transition: "opacity 120ms ease-in-out"
|
|
1266
1271
|
},
|
|
1267
1272
|
userActions: {
|
|
1268
|
-
display: "flex"
|
|
1269
|
-
},
|
|
1270
|
-
// ── Inline edit mode ──
|
|
1271
|
-
userEditWrap: {
|
|
1272
|
-
display: "flex",
|
|
1273
|
-
flexDirection: "column",
|
|
1274
|
-
alignItems: "stretch",
|
|
1275
|
-
width: "min(640px, 80vw)",
|
|
1276
|
-
gap: "8px"
|
|
1277
|
-
},
|
|
1278
|
-
userEditTextarea: {
|
|
1279
|
-
backgroundColor: tokens7.colorNeutralBackground2,
|
|
1280
|
-
color: tokens7.colorNeutralForeground2,
|
|
1281
|
-
border: `1px solid ${tokens7.colorNeutralStroke1}`,
|
|
1282
|
-
padding: "8px 12px",
|
|
1283
|
-
borderRadius: tokens7.borderRadiusLarge,
|
|
1284
|
-
fontFamily: tokens7.fontFamilyBase,
|
|
1285
|
-
fontSize: tokens7.fontSizeBase300,
|
|
1286
|
-
lineHeight: tokens7.lineHeightBase300,
|
|
1287
|
-
resize: "none",
|
|
1288
|
-
outline: "none",
|
|
1289
|
-
width: "100%",
|
|
1290
|
-
boxSizing: "border-box",
|
|
1291
|
-
minHeight: "40px",
|
|
1292
|
-
"&:focus": {
|
|
1293
|
-
border: `1px solid ${tokens7.colorNeutralStroke3}`
|
|
1294
|
-
}
|
|
1295
|
-
},
|
|
1296
|
-
userEditFooter: {
|
|
1297
1273
|
display: "flex",
|
|
1298
|
-
|
|
1299
|
-
// marginLeft: "12px",
|
|
1300
|
-
color: `${tokens7.colorNeutralForeground3}`,
|
|
1301
|
-
gap: "12px",
|
|
1302
|
-
alignItems: "center"
|
|
1303
|
-
},
|
|
1304
|
-
userEditActions: {
|
|
1305
|
-
display: "flex",
|
|
1306
|
-
justifyContent: "flex-end",
|
|
1307
|
-
gap: "8px"
|
|
1274
|
+
gap: "2px"
|
|
1308
1275
|
},
|
|
1309
1276
|
// ── Assistant message ──
|
|
1310
1277
|
messageAssistant: {
|
|
@@ -1321,20 +1288,20 @@ var useStyles7 = makeStyles7({
|
|
|
1321
1288
|
display: "flex",
|
|
1322
1289
|
justifyContent: "space-between",
|
|
1323
1290
|
marginTop: "6px",
|
|
1324
|
-
marginLeft: "-10px",
|
|
1325
1291
|
// Hover-only by default; the latest message overrides this to stay visible.
|
|
1326
1292
|
opacity: 0,
|
|
1327
1293
|
transition: "opacity 120ms ease-in-out"
|
|
1328
1294
|
},
|
|
1329
1295
|
assistantActions: {
|
|
1330
|
-
display: "flex"
|
|
1296
|
+
display: "flex",
|
|
1297
|
+
gap: "2px"
|
|
1331
1298
|
},
|
|
1332
1299
|
copiedBadge: {
|
|
1333
1300
|
display: "inline-flex",
|
|
1334
1301
|
alignItems: "center",
|
|
1335
1302
|
justifyContent: "center",
|
|
1336
|
-
width: "
|
|
1337
|
-
height: "
|
|
1303
|
+
width: "24px",
|
|
1304
|
+
height: "24px",
|
|
1338
1305
|
color: tokens7.colorPaletteSeafoamForeground2
|
|
1339
1306
|
},
|
|
1340
1307
|
footerIconButton: {
|
|
@@ -1361,7 +1328,6 @@ var ChatMessages = ({
|
|
|
1361
1328
|
thinkingStatus,
|
|
1362
1329
|
sendMessage,
|
|
1363
1330
|
regenerate,
|
|
1364
|
-
editMessage,
|
|
1365
1331
|
handleCopy,
|
|
1366
1332
|
lastUserInputRef,
|
|
1367
1333
|
registerMessagesContainer,
|
|
@@ -1376,55 +1342,10 @@ var ChatMessages = ({
|
|
|
1376
1342
|
const isSidecar = surface === "panel-right";
|
|
1377
1343
|
const [copiedKey, setCopiedKey] = useState5(null);
|
|
1378
1344
|
const copiedTimerRef = useRef4(null);
|
|
1379
|
-
const [editingId, setEditingId] = useState5(null);
|
|
1380
|
-
const [editDraft, setEditDraft] = useState5("");
|
|
1381
|
-
const editTextareaRef = useRef4(null);
|
|
1382
1345
|
useEffect4(() => {
|
|
1383
1346
|
registerMessagesContainer(containerRef.current);
|
|
1384
1347
|
return () => registerMessagesContainer(null);
|
|
1385
1348
|
}, []);
|
|
1386
|
-
useLayoutEffect2(() => {
|
|
1387
|
-
if (editingId && editTextareaRef.current) {
|
|
1388
|
-
const ta = editTextareaRef.current;
|
|
1389
|
-
ta.focus();
|
|
1390
|
-
ta.setSelectionRange(ta.value.length, ta.value.length);
|
|
1391
|
-
ta.style.height = "auto";
|
|
1392
|
-
ta.style.height = `${ta.scrollHeight}px`;
|
|
1393
|
-
}
|
|
1394
|
-
}, [editingId]);
|
|
1395
|
-
const startEdit = (msg) => {
|
|
1396
|
-
if (!msg.id) return;
|
|
1397
|
-
setEditingId(msg.id);
|
|
1398
|
-
setEditDraft(msg.content);
|
|
1399
|
-
};
|
|
1400
|
-
const cancelEdit = () => {
|
|
1401
|
-
setEditingId(null);
|
|
1402
|
-
setEditDraft("");
|
|
1403
|
-
};
|
|
1404
|
-
const saveEdit = async () => {
|
|
1405
|
-
if (!editingId) return;
|
|
1406
|
-
const trimmed = editDraft.trim();
|
|
1407
|
-
if (!trimmed) return;
|
|
1408
|
-
const id = editingId;
|
|
1409
|
-
setEditingId(null);
|
|
1410
|
-
setEditDraft("");
|
|
1411
|
-
await editMessage(id, trimmed);
|
|
1412
|
-
};
|
|
1413
|
-
const handleEditTextareaInput = (e) => {
|
|
1414
|
-
setEditDraft(e.target.value);
|
|
1415
|
-
const ta = e.target;
|
|
1416
|
-
ta.style.height = "auto";
|
|
1417
|
-
ta.style.height = `${ta.scrollHeight}px`;
|
|
1418
|
-
};
|
|
1419
|
-
const handleEditKeyDown = (e) => {
|
|
1420
|
-
if (e.key === "Escape") {
|
|
1421
|
-
e.preventDefault();
|
|
1422
|
-
cancelEdit();
|
|
1423
|
-
} else if (e.key === "Enter" && !e.shiftKey) {
|
|
1424
|
-
e.preventDefault();
|
|
1425
|
-
void saveEdit();
|
|
1426
|
-
}
|
|
1427
|
-
};
|
|
1428
1349
|
const onCopyMerged = (content, key) => {
|
|
1429
1350
|
handleCopy(content);
|
|
1430
1351
|
onCopy?.(content);
|
|
@@ -1434,7 +1355,6 @@ var ChatMessages = ({
|
|
|
1434
1355
|
};
|
|
1435
1356
|
const renderUserMessage = (msg, index) => {
|
|
1436
1357
|
const key = msg.id ?? `idx-${index}`;
|
|
1437
|
-
const isEditing = !!msg.id && editingId === msg.id;
|
|
1438
1358
|
const attachments = Array.isArray(msg.metadata?.attachments) ? msg.metadata.attachments : null;
|
|
1439
1359
|
return /* @__PURE__ */ jsxs7("div", { className: styles.userRow, children: [
|
|
1440
1360
|
attachments && /* @__PURE__ */ jsx7(
|
|
@@ -1480,73 +1400,21 @@ var ChatMessages = ({
|
|
|
1480
1400
|
)
|
|
1481
1401
|
}
|
|
1482
1402
|
),
|
|
1483
|
-
|
|
1484
|
-
|
|
1485
|
-
|
|
1486
|
-
|
|
1487
|
-
|
|
1488
|
-
|
|
1489
|
-
|
|
1490
|
-
|
|
1491
|
-
|
|
1492
|
-
|
|
1493
|
-
|
|
1494
|
-
|
|
1495
|
-
|
|
1496
|
-
|
|
1497
|
-
|
|
1498
|
-
{
|
|
1499
|
-
style: {
|
|
1500
|
-
marginRight: "6px",
|
|
1501
|
-
color: `${tokens7.colorNeutralForeground3}`,
|
|
1502
|
-
fontSize: "20px",
|
|
1503
|
-
boxSizing: "border-box",
|
|
1504
|
-
flexShrink: 0
|
|
1505
|
-
}
|
|
1506
|
-
}
|
|
1507
|
-
),
|
|
1508
|
-
/* @__PURE__ */ jsx7(Caption12, { children: "Editing this message will discard the current response and regenerate from here." }),
|
|
1509
|
-
/* @__PURE__ */ jsxs7("div", { className: styles.userEditActions, children: [
|
|
1510
|
-
/* @__PURE__ */ jsx7(Button4, { appearance: "subtle", onClick: cancelEdit, children: "Cancel" }),
|
|
1511
|
-
/* @__PURE__ */ jsx7(
|
|
1512
|
-
Button4,
|
|
1513
|
-
{
|
|
1514
|
-
appearance: "primary",
|
|
1515
|
-
onClick: saveEdit,
|
|
1516
|
-
disabled: !editDraft.trim(),
|
|
1517
|
-
children: "Save"
|
|
1518
|
-
}
|
|
1519
|
-
)
|
|
1520
|
-
] })
|
|
1521
|
-
] })
|
|
1522
|
-
] }) : /* @__PURE__ */ jsxs7(Fragment, { children: [
|
|
1523
|
-
/* @__PURE__ */ jsx7("div", { className: styles.userBubble, children: /* @__PURE__ */ jsx7(Body15, { children: msg.content.split("\n").map((line, i, arr) => /* @__PURE__ */ jsxs7(React5.Fragment, { children: [
|
|
1524
|
-
line,
|
|
1525
|
-
i < arr.length - 1 && /* @__PURE__ */ jsx7("br", {})
|
|
1526
|
-
] }, i)) }) }),
|
|
1527
|
-
msg.id && /* @__PURE__ */ jsx7("div", { className: `${styles.userFooter} coral-user-footer`, children: /* @__PURE__ */ jsxs7("div", { className: styles.userActions, children: [
|
|
1528
|
-
copiedKey === `user-${key}` ? /* @__PURE__ */ jsx7("span", { className: styles.copiedBadge, children: /* @__PURE__ */ jsx7(CheckmarkCircle20Filled, {}) }) : /* @__PURE__ */ jsx7(
|
|
1529
|
-
Button4,
|
|
1530
|
-
{
|
|
1531
|
-
onClick: () => onCopyMerged(msg.content, `user-${key}`),
|
|
1532
|
-
title: "Copy message",
|
|
1533
|
-
appearance: "subtle",
|
|
1534
|
-
className: styles.footerIconButton,
|
|
1535
|
-
icon: /* @__PURE__ */ jsx7(Copy, {})
|
|
1536
|
-
}
|
|
1537
|
-
),
|
|
1538
|
-
/* @__PURE__ */ jsx7(
|
|
1539
|
-
Button4,
|
|
1540
|
-
{
|
|
1541
|
-
onClick: () => startEdit(msg),
|
|
1542
|
-
title: "Edit message",
|
|
1543
|
-
appearance: "subtle",
|
|
1544
|
-
className: styles.footerIconButton,
|
|
1545
|
-
icon: /* @__PURE__ */ jsx7(EditIcon, {})
|
|
1546
|
-
}
|
|
1547
|
-
)
|
|
1548
|
-
] }) })
|
|
1549
|
-
] })
|
|
1403
|
+
/* @__PURE__ */ jsx7("div", { className: styles.userBubble, children: /* @__PURE__ */ jsx7(Body15, { children: msg.content.split("\n").map((line, i, arr) => /* @__PURE__ */ jsxs7(React5.Fragment, { children: [
|
|
1404
|
+
line,
|
|
1405
|
+
i < arr.length - 1 && /* @__PURE__ */ jsx7("br", {})
|
|
1406
|
+
] }, i)) }) }),
|
|
1407
|
+
msg.id && /* @__PURE__ */ jsx7("div", { className: `${styles.userFooter} coral-user-footer`, children: /* @__PURE__ */ jsx7("div", { className: styles.userActions, children: copiedKey === `user-${key}` ? /* @__PURE__ */ jsx7("span", { className: styles.copiedBadge, children: /* @__PURE__ */ jsx7(CheckmarkCircle20Filled, {}) }) : /* @__PURE__ */ jsx7(
|
|
1408
|
+
Button4,
|
|
1409
|
+
{
|
|
1410
|
+
onClick: () => onCopyMerged(msg.content, `user-${key}`),
|
|
1411
|
+
title: "Copy message",
|
|
1412
|
+
appearance: "subtle",
|
|
1413
|
+
size: "small",
|
|
1414
|
+
className: styles.footerIconButton,
|
|
1415
|
+
icon: /* @__PURE__ */ jsx7(Copy, {})
|
|
1416
|
+
}
|
|
1417
|
+
) }) })
|
|
1550
1418
|
] }, key);
|
|
1551
1419
|
};
|
|
1552
1420
|
const renderAssistantMessage = (msg, index) => {
|
|
@@ -1578,17 +1446,24 @@ var ChatMessages = ({
|
|
|
1578
1446
|
isStreaming: isLatest && isTyping && !msg.content
|
|
1579
1447
|
}
|
|
1580
1448
|
),
|
|
1581
|
-
msg.
|
|
1582
|
-
|
|
1583
|
-
|
|
1584
|
-
CoralMarkdown,
|
|
1585
|
-
{
|
|
1586
|
-
onNavigate,
|
|
1587
|
-
fontSize,
|
|
1588
|
-
fontFamily,
|
|
1589
|
-
children: msg.content
|
|
1449
|
+
resolveBlocks(msg).map((block, i) => {
|
|
1450
|
+
if (block.type === "todos") {
|
|
1451
|
+
return /* @__PURE__ */ jsx7(Chat_TodoList_default, { todos: block.todos }, `todos-${i}`);
|
|
1590
1452
|
}
|
|
1591
|
-
|
|
1453
|
+
if (block.type === "chart") {
|
|
1454
|
+
return /* @__PURE__ */ jsx7(CoralChart, { spec: block.spec }, `chart-${i}`);
|
|
1455
|
+
}
|
|
1456
|
+
return /* @__PURE__ */ jsx7(
|
|
1457
|
+
CoralMarkdown,
|
|
1458
|
+
{
|
|
1459
|
+
onNavigate,
|
|
1460
|
+
fontSize,
|
|
1461
|
+
fontFamily,
|
|
1462
|
+
children: block.content
|
|
1463
|
+
},
|
|
1464
|
+
`text-${i}`
|
|
1465
|
+
);
|
|
1466
|
+
}),
|
|
1592
1467
|
msg.error && /* @__PURE__ */ jsx7(
|
|
1593
1468
|
Chat_Error_default,
|
|
1594
1469
|
{
|
|
@@ -1618,6 +1493,7 @@ var ChatMessages = ({
|
|
|
1618
1493
|
onClick: () => onCopyMerged(msg.content, `assistant-${key}`),
|
|
1619
1494
|
title: "Copy response",
|
|
1620
1495
|
appearance: "subtle",
|
|
1496
|
+
size: "small",
|
|
1621
1497
|
className: styles.footerIconButton,
|
|
1622
1498
|
icon: /* @__PURE__ */ jsx7(Copy, {})
|
|
1623
1499
|
}
|
|
@@ -1628,6 +1504,7 @@ var ChatMessages = ({
|
|
|
1628
1504
|
onClick: () => regenerate(msg.id),
|
|
1629
1505
|
title: "Regenerate response",
|
|
1630
1506
|
appearance: "subtle",
|
|
1507
|
+
size: "small",
|
|
1631
1508
|
className: styles.footerIconButton,
|
|
1632
1509
|
icon: /* @__PURE__ */ jsx7(ArrowClockwise, {})
|
|
1633
1510
|
}
|
|
@@ -1641,7 +1518,7 @@ var ChatMessages = ({
|
|
|
1641
1518
|
"div",
|
|
1642
1519
|
{
|
|
1643
1520
|
className: styles.messageWrapper,
|
|
1644
|
-
style: isSidecar ? { padding: "0
|
|
1521
|
+
style: isSidecar ? { padding: "0 16px" } : void 0,
|
|
1645
1522
|
children: [
|
|
1646
1523
|
messages.map((msg, index) => {
|
|
1647
1524
|
if (msg.role === "user") {
|
|
@@ -1695,7 +1572,7 @@ import {
|
|
|
1695
1572
|
MenuItem
|
|
1696
1573
|
} from "@fluentui/react-components";
|
|
1697
1574
|
import { Add, DocumentAdd, ImageAdd } from "@coral-ai/bundleicons";
|
|
1698
|
-
import { Fragment
|
|
1575
|
+
import { Fragment, jsx as jsx8, jsxs as jsxs8 } from "react/jsx-runtime";
|
|
1699
1576
|
var ChatAttachButton = ({
|
|
1700
1577
|
types = ["files", "photos"]
|
|
1701
1578
|
}) => {
|
|
@@ -1704,7 +1581,7 @@ var ChatAttachButton = ({
|
|
|
1704
1581
|
const photoRef = useRef5(null);
|
|
1705
1582
|
const showFiles = types.includes("files");
|
|
1706
1583
|
const showPhotos = types.includes("photos");
|
|
1707
|
-
return /* @__PURE__ */ jsxs8(
|
|
1584
|
+
return /* @__PURE__ */ jsxs8(Fragment, { children: [
|
|
1708
1585
|
showFiles && /* @__PURE__ */ jsx8(
|
|
1709
1586
|
"input",
|
|
1710
1587
|
{
|
|
@@ -1779,9 +1656,6 @@ var useStyles8 = makeStyles8({
|
|
|
1779
1656
|
boxSizing: "border-box",
|
|
1780
1657
|
overflow: "hidden"
|
|
1781
1658
|
},
|
|
1782
|
-
cardFocused: {
|
|
1783
|
-
boxShadow: tokens8.shadow28
|
|
1784
|
-
},
|
|
1785
1659
|
cardDisabled: {
|
|
1786
1660
|
opacity: "0.3",
|
|
1787
1661
|
pointerEvents: "none"
|
|
@@ -1957,7 +1831,7 @@ var ChatInput = forwardRef(
|
|
|
1957
1831
|
return /* @__PURE__ */ jsx9("div", { ref: containerRef, className: styles.wrapper, style, children: /* @__PURE__ */ jsxs9(
|
|
1958
1832
|
"div",
|
|
1959
1833
|
{
|
|
1960
|
-
className: `${styles.card}${
|
|
1834
|
+
className: `${styles.card}${disabled ? ` ${styles.cardDisabled}` : ""}`,
|
|
1961
1835
|
style: {
|
|
1962
1836
|
border: isFocused ? `1px solid ${tokens8.colorNeutralStroke1}` : `1px solid ${tokens8.colorNeutralStroke2}`
|
|
1963
1837
|
},
|
|
@@ -2031,7 +1905,7 @@ var ChatInput = forwardRef(
|
|
|
2031
1905
|
var Chat_Input_default = ChatInput;
|
|
2032
1906
|
|
|
2033
1907
|
// src/Chat.Approval.tsx
|
|
2034
|
-
import { Body1 as Body17, Body1Strong, Button as Button7, Caption1 as
|
|
1908
|
+
import { Body1 as Body17, Body1Strong, Button as Button7, Caption1 as Caption12, makeStyles as makeStyles9, tokens as tokens9 } from "@fluentui/react-components";
|
|
2035
1909
|
import { jsx as jsx10, jsxs as jsxs10 } from "react/jsx-runtime";
|
|
2036
1910
|
var useStyles9 = makeStyles9({
|
|
2037
1911
|
root: {
|
|
@@ -2126,7 +2000,7 @@ var ChatApproval = ({
|
|
|
2126
2000
|
opt.id
|
|
2127
2001
|
);
|
|
2128
2002
|
}) }),
|
|
2129
|
-
awaitingFreeform && !isAnswered && /* @__PURE__ */ jsx10(
|
|
2003
|
+
awaitingFreeform && !isAnswered && /* @__PURE__ */ jsx10(Caption12, { className: styles.hint, children: "Type your reply in the message box below." })
|
|
2130
2004
|
]
|
|
2131
2005
|
}
|
|
2132
2006
|
);
|
|
@@ -2134,7 +2008,7 @@ var ChatApproval = ({
|
|
|
2134
2008
|
var Chat_Approval_default = ChatApproval;
|
|
2135
2009
|
|
|
2136
2010
|
// src/Chat.tsx
|
|
2137
|
-
import { Fragment as
|
|
2011
|
+
import { Fragment as Fragment2, jsx as jsx11, jsxs as jsxs11 } from "react/jsx-runtime";
|
|
2138
2012
|
var useStyles10 = makeStyles10({
|
|
2139
2013
|
emptySlot: {
|
|
2140
2014
|
width: "100%",
|
|
@@ -2175,15 +2049,10 @@ var useStyles10 = makeStyles10({
|
|
|
2175
2049
|
justifyContent: "center"
|
|
2176
2050
|
}
|
|
2177
2051
|
});
|
|
2178
|
-
var remapFontSizeForSurface = (size, surface) => {
|
|
2179
|
-
if (surface === "panel-right" && (size === void 0 || size === "default")) {
|
|
2180
|
-
return "small";
|
|
2181
|
-
}
|
|
2182
|
-
return size;
|
|
2183
|
-
};
|
|
2184
2052
|
var ChatLayout = ({
|
|
2185
2053
|
welcomeMessage,
|
|
2186
2054
|
promptSuggestions,
|
|
2055
|
+
disclaimer,
|
|
2187
2056
|
surfaceMotion,
|
|
2188
2057
|
placeholder,
|
|
2189
2058
|
disabled,
|
|
@@ -2198,13 +2067,6 @@ var ChatLayout = ({
|
|
|
2198
2067
|
const welcomeIsFill = welcomeMessage !== void 0 && typeof welcomeMessage !== "string";
|
|
2199
2068
|
const welcomeNode = typeof welcomeMessage === "string" ? /* @__PURE__ */ jsx11(Title3, { children: welcomeMessage }) : welcomeMessage;
|
|
2200
2069
|
const styles = useStyles10();
|
|
2201
|
-
const surfaceProbeRef = useRef7(null);
|
|
2202
|
-
const [surface, setSurface] = useState7(null);
|
|
2203
|
-
useLayoutEffect3(() => {
|
|
2204
|
-
const el = surfaceProbeRef.current?.closest("[data-coral-surface]");
|
|
2205
|
-
setSurface(el?.getAttribute("data-coral-surface") ?? null);
|
|
2206
|
-
}, []);
|
|
2207
|
-
const effectiveFontSize = remapFontSizeForSurface(fontSize, surface);
|
|
2208
2070
|
const { messages, isTyping, pendingApproval, awaitingFreeformApproval } = useChatContext();
|
|
2209
2071
|
const empty = messages.every((m) => m.role === "system") && !isTyping;
|
|
2210
2072
|
const approvalLocksInput = pendingApproval !== null && awaitingFreeformApproval === null;
|
|
@@ -2213,11 +2075,10 @@ var ChatLayout = ({
|
|
|
2213
2075
|
const curve = motionTokens.curveDecelerateMax;
|
|
2214
2076
|
const spacerTransition = motionEnabled ? `flex-grow 300ms ${curve}` : "none";
|
|
2215
2077
|
const gapTransition = motionEnabled ? `height 300ms ${curve}` : "none";
|
|
2216
|
-
return /* @__PURE__ */ jsxs11(
|
|
2078
|
+
return /* @__PURE__ */ jsxs11(Fragment2, { children: [
|
|
2217
2079
|
/* @__PURE__ */ jsx11(
|
|
2218
2080
|
"div",
|
|
2219
2081
|
{
|
|
2220
|
-
ref: surfaceProbeRef,
|
|
2221
2082
|
style: {
|
|
2222
2083
|
flexGrow: empty && !welcomeIsFill ? 1 : 0,
|
|
2223
2084
|
flexShrink: 1,
|
|
@@ -2252,7 +2113,7 @@ var ChatLayout = ({
|
|
|
2252
2113
|
components,
|
|
2253
2114
|
onCopy,
|
|
2254
2115
|
onNavigate,
|
|
2255
|
-
fontSize
|
|
2116
|
+
fontSize,
|
|
2256
2117
|
fontFamily
|
|
2257
2118
|
}
|
|
2258
2119
|
)
|
|
@@ -2284,8 +2145,8 @@ var ChatLayout = ({
|
|
|
2284
2145
|
}
|
|
2285
2146
|
}
|
|
2286
2147
|
),
|
|
2287
|
-
/* @__PURE__ */ jsx11(
|
|
2288
|
-
|
|
2148
|
+
disclaimer != null && disclaimer !== false && /* @__PURE__ */ jsx11(
|
|
2149
|
+
Caption13,
|
|
2289
2150
|
{
|
|
2290
2151
|
style: {
|
|
2291
2152
|
display: "flex",
|
|
@@ -2294,7 +2155,7 @@ var ChatLayout = ({
|
|
|
2294
2155
|
height: "32px",
|
|
2295
2156
|
opacity: 0.5
|
|
2296
2157
|
},
|
|
2297
|
-
children:
|
|
2158
|
+
children: disclaimer
|
|
2298
2159
|
}
|
|
2299
2160
|
)
|
|
2300
2161
|
] });
|
|
@@ -2314,6 +2175,7 @@ var Chat = ({
|
|
|
2314
2175
|
onStop,
|
|
2315
2176
|
welcomeMessage,
|
|
2316
2177
|
promptSuggestions,
|
|
2178
|
+
disclaimer,
|
|
2317
2179
|
surfaceMotion,
|
|
2318
2180
|
components,
|
|
2319
2181
|
onCopy,
|
|
@@ -2348,6 +2210,7 @@ var Chat = ({
|
|
|
2348
2210
|
{
|
|
2349
2211
|
welcomeMessage,
|
|
2350
2212
|
promptSuggestions,
|
|
2213
|
+
disclaimer,
|
|
2351
2214
|
surfaceMotion,
|
|
2352
2215
|
placeholder,
|
|
2353
2216
|
disabled,
|
|
@@ -2704,13 +2567,13 @@ function createAgentHandler(options) {
|
|
|
2704
2567
|
}
|
|
2705
2568
|
|
|
2706
2569
|
// src/Chat.Threads.tsx
|
|
2707
|
-
import * as
|
|
2570
|
+
import * as React8 from "react";
|
|
2708
2571
|
import { jsx as jsx12 } from "react/jsx-runtime";
|
|
2709
|
-
var ChatThreadsContext =
|
|
2572
|
+
var ChatThreadsContext = React8.createContext(
|
|
2710
2573
|
null
|
|
2711
2574
|
);
|
|
2712
2575
|
function useChatThreads() {
|
|
2713
|
-
const value =
|
|
2576
|
+
const value = React8.useContext(ChatThreadsContext);
|
|
2714
2577
|
if (!value) {
|
|
2715
2578
|
throw new Error(
|
|
2716
2579
|
"useChatThreads must be used inside <ChatThreadsProvider>."
|
|
@@ -2756,25 +2619,25 @@ function ChatThreadsProvider({
|
|
|
2756
2619
|
onActiveThreadChange,
|
|
2757
2620
|
children
|
|
2758
2621
|
}) {
|
|
2759
|
-
const adapter =
|
|
2622
|
+
const adapter = React8.useMemo(
|
|
2760
2623
|
() => providedAdapter ?? createMemoryThreadsAdapter(),
|
|
2761
2624
|
[providedAdapter]
|
|
2762
2625
|
);
|
|
2763
|
-
const [threads, setThreads] =
|
|
2764
|
-
const [uncontrolledId, setUncontrolledId] =
|
|
2626
|
+
const [threads, setThreads] = React8.useState([]);
|
|
2627
|
+
const [uncontrolledId, setUncontrolledId] = React8.useState(
|
|
2765
2628
|
defaultActiveThreadId
|
|
2766
2629
|
);
|
|
2767
|
-
const [isLoading, setIsLoading] =
|
|
2630
|
+
const [isLoading, setIsLoading] = React8.useState(true);
|
|
2768
2631
|
const isControlled = controlledId !== void 0;
|
|
2769
2632
|
const activeThreadId = isControlled ? controlledId : uncontrolledId;
|
|
2770
|
-
const setActiveThreadId =
|
|
2633
|
+
const setActiveThreadId = React8.useCallback(
|
|
2771
2634
|
(id) => {
|
|
2772
2635
|
if (!isControlled) setUncontrolledId(id);
|
|
2773
2636
|
onActiveThreadChange?.(id);
|
|
2774
2637
|
},
|
|
2775
2638
|
[isControlled, onActiveThreadChange]
|
|
2776
2639
|
);
|
|
2777
|
-
|
|
2640
|
+
React8.useEffect(() => {
|
|
2778
2641
|
let cancelled = false;
|
|
2779
2642
|
(async () => {
|
|
2780
2643
|
setIsLoading(true);
|
|
@@ -2787,7 +2650,7 @@ function ChatThreadsProvider({
|
|
|
2787
2650
|
cancelled = true;
|
|
2788
2651
|
};
|
|
2789
2652
|
}, [adapter]);
|
|
2790
|
-
const createThread =
|
|
2653
|
+
const createThread = React8.useCallback(
|
|
2791
2654
|
async (initial) => {
|
|
2792
2655
|
const thread = await adapter.create(initial);
|
|
2793
2656
|
setThreads((prev) => [thread, ...prev.filter((t) => t.id !== thread.id)]);
|
|
@@ -2795,7 +2658,7 @@ function ChatThreadsProvider({
|
|
|
2795
2658
|
},
|
|
2796
2659
|
[adapter]
|
|
2797
2660
|
);
|
|
2798
|
-
const renameThread =
|
|
2661
|
+
const renameThread = React8.useCallback(
|
|
2799
2662
|
async (id, newTitle) => {
|
|
2800
2663
|
await adapter.rename(id, newTitle);
|
|
2801
2664
|
setThreads(
|
|
@@ -2806,7 +2669,7 @@ function ChatThreadsProvider({
|
|
|
2806
2669
|
},
|
|
2807
2670
|
[adapter]
|
|
2808
2671
|
);
|
|
2809
|
-
const removeThread =
|
|
2672
|
+
const removeThread = React8.useCallback(
|
|
2810
2673
|
async (id) => {
|
|
2811
2674
|
await adapter.remove(id);
|
|
2812
2675
|
setThreads((prev) => prev.filter((t) => t.id !== id));
|
|
@@ -2814,9 +2677,9 @@ function ChatThreadsProvider({
|
|
|
2814
2677
|
},
|
|
2815
2678
|
[adapter, activeThreadId, setActiveThreadId]
|
|
2816
2679
|
);
|
|
2817
|
-
const threadsRef =
|
|
2680
|
+
const threadsRef = React8.useRef(threads);
|
|
2818
2681
|
threadsRef.current = threads;
|
|
2819
|
-
const updateThreadMessages =
|
|
2682
|
+
const updateThreadMessages = React8.useCallback(
|
|
2820
2683
|
(id, messages) => {
|
|
2821
2684
|
const existing = threadsRef.current.find((t) => t.id === id);
|
|
2822
2685
|
if (!existing) return;
|
|
@@ -2830,11 +2693,11 @@ function ChatThreadsProvider({
|
|
|
2830
2693
|
},
|
|
2831
2694
|
[adapter]
|
|
2832
2695
|
);
|
|
2833
|
-
const activeThread =
|
|
2696
|
+
const activeThread = React8.useMemo(
|
|
2834
2697
|
() => threads.find((t) => t.id === activeThreadId),
|
|
2835
2698
|
[threads, activeThreadId]
|
|
2836
2699
|
);
|
|
2837
|
-
const value =
|
|
2700
|
+
const value = React8.useMemo(
|
|
2838
2701
|
() => ({
|
|
2839
2702
|
threads,
|
|
2840
2703
|
activeThreadId,
|