@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/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 Caption14,
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: "48px",
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
- let streamedTodos;
431
- let streamedCharts;
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
- pendingContent = assistantContent;
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
- streamedTodos = chunk.todos;
472
- setMessages((prev) => {
473
- const updated = [...prev];
474
- const last = updated[updated.length - 1];
475
- if (last && last.id === assistantId) {
476
- updated[updated.length - 1] = { ...last, todos: chunk.todos };
477
- }
478
- return updated;
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
- streamedCharts = [...streamedCharts ?? [], chunk.spec];
482
- const nextCharts = streamedCharts;
483
- setMessages((prev) => {
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 { Fragment, jsx as jsx7, jsxs as jsxs7 } from "react/jsx-runtime";
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: "24px",
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
- marginTop: "8px",
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: "32px",
1337
- height: "32px",
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
- isEditing ? /* @__PURE__ */ jsxs7("div", { className: styles.userEditWrap, children: [
1484
- /* @__PURE__ */ jsx7(
1485
- "textarea",
1486
- {
1487
- ref: editTextareaRef,
1488
- className: styles.userEditTextarea,
1489
- value: editDraft,
1490
- onChange: handleEditTextareaInput,
1491
- onKeyDown: handleEditKeyDown,
1492
- rows: 1
1493
- }
1494
- ),
1495
- /* @__PURE__ */ jsxs7("div", { className: styles.userEditFooter, children: [
1496
- /* @__PURE__ */ jsx7(
1497
- Info,
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.todos && msg.todos.length > 0 && /* @__PURE__ */ jsx7(Chat_TodoList_default, { todos: msg.todos }),
1582
- msg.charts && msg.charts.length > 0 && /* @__PURE__ */ jsx7(Fragment, { children: msg.charts.map((spec, i) => /* @__PURE__ */ jsx7(CoralChart, { spec }, i)) }),
1583
- /* @__PURE__ */ jsx7(
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 8px" } : void 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 as Fragment2, jsx as jsx8, jsxs as jsxs8 } from "react/jsx-runtime";
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(Fragment2, { children: [
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}${isFocused ? ` ${styles.cardFocused}` : ""}${disabled ? ` ${styles.cardDisabled}` : ""}`,
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 Caption13, makeStyles as makeStyles9, tokens as tokens9 } from "@fluentui/react-components";
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(Caption13, { className: styles.hint, children: "Type your reply in the message box below." })
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 Fragment3, jsx as jsx11, jsxs as jsxs11 } from "react/jsx-runtime";
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(Fragment3, { children: [
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: effectiveFontSize,
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
- Caption14,
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: "AI makes mistakes. Check outputs."
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 React9 from "react";
2570
+ import * as React8 from "react";
2708
2571
  import { jsx as jsx12 } from "react/jsx-runtime";
2709
- var ChatThreadsContext = React9.createContext(
2572
+ var ChatThreadsContext = React8.createContext(
2710
2573
  null
2711
2574
  );
2712
2575
  function useChatThreads() {
2713
- const value = React9.useContext(ChatThreadsContext);
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 = React9.useMemo(
2622
+ const adapter = React8.useMemo(
2760
2623
  () => providedAdapter ?? createMemoryThreadsAdapter(),
2761
2624
  [providedAdapter]
2762
2625
  );
2763
- const [threads, setThreads] = React9.useState([]);
2764
- const [uncontrolledId, setUncontrolledId] = React9.useState(
2626
+ const [threads, setThreads] = React8.useState([]);
2627
+ const [uncontrolledId, setUncontrolledId] = React8.useState(
2765
2628
  defaultActiveThreadId
2766
2629
  );
2767
- const [isLoading, setIsLoading] = React9.useState(true);
2630
+ const [isLoading, setIsLoading] = React8.useState(true);
2768
2631
  const isControlled = controlledId !== void 0;
2769
2632
  const activeThreadId = isControlled ? controlledId : uncontrolledId;
2770
- const setActiveThreadId = React9.useCallback(
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
- React9.useEffect(() => {
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 = React9.useCallback(
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 = React9.useCallback(
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 = React9.useCallback(
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 = React9.useRef(threads);
2680
+ const threadsRef = React8.useRef(threads);
2818
2681
  threadsRef.current = threads;
2819
- const updateThreadMessages = React9.useCallback(
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 = React9.useMemo(
2696
+ const activeThread = React8.useMemo(
2834
2697
  () => threads.find((t) => t.id === activeThreadId),
2835
2698
  [threads, activeThreadId]
2836
2699
  );
2837
- const value = React9.useMemo(
2700
+ const value = React8.useMemo(
2838
2701
  () => ({
2839
2702
  threads,
2840
2703
  activeThreadId,