@coral-ai/chat 0.5.0 → 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 CHANGED
@@ -22,4 +22,18 @@ import { Chat } from "@coral-ai/chat";
22
22
  `ChatChunk`s, or a `ChatResponse`. A backend URL can also be supplied via the
23
23
  `api` prop or `coral.config.json`'s `chat.api`.
24
24
 
25
+ `disclaimer?: React.ReactNode` adds optional content beneath the input. By
26
+ default no disclaimer or footer space is rendered; `undefined`, `null`, and
27
+ `false` also hide it. To retain the previous built-in text, opt in explicitly:
28
+
29
+ ```tsx
30
+ <Chat api="/api/chat" disclaimer="AI makes mistakes. Check outputs." />
31
+ ```
32
+
33
+ Custom React content, such as a policy link, is also supported.
34
+
25
35
  See [coral-ai](https://github.com/mochimilk/coral-ai) for the full project.
36
+
37
+ ## Migrating to 0.6
38
+
39
+ User-message editing and `useChatContext().editMessage` have been removed. Assistant Copy/Regenerate and error Retry remain. The disclaimer is opt-in: pass `disclaimer` to render footer content; omission reserves no space. Sidecars use the true default 15px assistant font. Message rows use a 0px gap; footer buttons are small with a 2px gap.
package/dist/index.d.ts CHANGED
@@ -227,6 +227,8 @@ interface ChatProps {
227
227
  * to invoke `sendMessage(text)` on click.
228
228
  */
229
229
  promptSuggestions?: React__default.ReactNode;
230
+ /** Optional content below the input. Omit or pass null to render no footer or reserved space. */
231
+ disclaimer?: React__default.ReactNode;
230
232
  /**
231
233
  * Pass `null` to disable the chat's built-in surface motion (input slide to
232
234
  * bottom on first message). Omit / leave undefined for default motion.
@@ -550,11 +552,6 @@ interface ChatContextValue {
550
552
  * If `messageId` targets a user message, the existing assistant reply for that turn is discarded and re-generated.
551
553
  */
552
554
  regenerate: (messageId?: string) => Promise<void>;
553
- /**
554
- * Replaces the content of an existing user message and re-runs from that point.
555
- * Truncates everything after the edited message and re-invokes the handler.
556
- */
557
- editMessage: (messageId: string, newContent: string) => Promise<void>;
558
555
  scrollToBottom: () => void;
559
556
  /** Pre-binds navigator.clipboard.writeText + the onCopy prop callback. */
560
557
  handleCopy: (content: string) => void;
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
  }
@@ -675,29 +674,12 @@ var ChatCanvas = ({
675
674
  const baseMessages = messages.slice(0, userIdx + 1);
676
675
  await runHandler(userMsg.content, baseMessages, []);
677
676
  };
678
- const editMessage = async (messageId, newContent) => {
679
- const idx = messages.findIndex((m) => m.id === messageId);
680
- if (idx === -1) return;
681
- if (messages[idx].role !== "user") return;
682
- const trimmed = newContent.replace(/^[\n\r]+|[\n\r]+$/g, "");
683
- if (!trimmed.trim()) return;
684
- const editedMessage = {
685
- ...messages[idx],
686
- content: trimmed
687
- };
688
- const baseMessages = [
689
- ...messages.slice(0, idx),
690
- editedMessage
691
- ];
692
- await runHandler(trimmed, baseMessages, []);
693
- };
694
677
  return /* @__PURE__ */ jsx2(
695
678
  ChatContext.Provider,
696
679
  {
697
680
  value: {
698
681
  sendMessage,
699
682
  regenerate,
700
- editMessage,
701
683
  scrollToBottom,
702
684
  handleCopy,
703
685
  messages,
@@ -733,6 +715,7 @@ var ChatCanvas = ({
733
715
  Button2,
734
716
  {
735
717
  onClick: scrollToBottom,
718
+ "aria-label": "Scroll to bottom",
736
719
  className: styles.scrollToBottom,
737
720
  shape: "circular",
738
721
  style: {
@@ -755,15 +738,12 @@ import React5, { useEffect as useEffect4, useLayoutEffect as useLayoutEffect2, u
755
738
  import {
756
739
  Body1 as Body15,
757
740
  Button as Button4,
758
- Caption1 as Caption12,
759
741
  makeStyles as makeStyles7,
760
742
  tokens as tokens7
761
743
  } from "@fluentui/react-components";
762
744
  import {
763
745
  ArrowClockwise,
764
- Copy,
765
- Edit as EditIcon,
766
- Info
746
+ Copy
767
747
  } from "@coral-ai/bundleicons";
768
748
  import {
769
749
  CoralMarkdown
@@ -1228,7 +1208,7 @@ var Chat_TodoList_default = ChatTodoList;
1228
1208
  // src/Chat.Messages.tsx
1229
1209
  import { CoralChart } from "@coral-ai/charts";
1230
1210
  import { CheckmarkCircle20Filled } from "@fluentui/react-icons";
1231
- import { Fragment, jsx as jsx7, jsxs as jsxs7 } from "react/jsx-runtime";
1211
+ import { jsx as jsx7, jsxs as jsxs7 } from "react/jsx-runtime";
1232
1212
  function resolveBlocks(msg) {
1233
1213
  if (msg.blocks) return msg.blocks;
1234
1214
  const legacy = [];
@@ -1256,7 +1236,7 @@ var useStyles7 = makeStyles7({
1256
1236
  messageWrapper: {
1257
1237
  display: "flex",
1258
1238
  flexDirection: "column",
1259
- gap: "24px",
1239
+ gap: "0px",
1260
1240
  width: "100%",
1261
1241
  maxWidth: "768px",
1262
1242
  padding: "0 16px",
@@ -1286,51 +1266,12 @@ var useStyles7 = makeStyles7({
1286
1266
  display: "flex",
1287
1267
  justifyContent: "flex-end",
1288
1268
  marginTop: "6px",
1289
- marginRight: "-10px",
1290
1269
  opacity: 0,
1291
1270
  transition: "opacity 120ms ease-in-out"
1292
1271
  },
1293
1272
  userActions: {
1294
- display: "flex"
1295
- },
1296
- // ── Inline edit mode ──
1297
- userEditWrap: {
1298
1273
  display: "flex",
1299
- flexDirection: "column",
1300
- alignItems: "stretch",
1301
- // width: "min(640px, 80vw)",
1302
- gap: "8px"
1303
- },
1304
- userEditTextarea: {
1305
- backgroundColor: tokens7.colorNeutralBackground2,
1306
- color: tokens7.colorNeutralForeground2,
1307
- border: `1px solid ${tokens7.colorNeutralStroke1}`,
1308
- padding: "8px 12px",
1309
- borderRadius: tokens7.borderRadiusLarge,
1310
- fontFamily: tokens7.fontFamilyBase,
1311
- fontSize: tokens7.fontSizeBase300,
1312
- lineHeight: tokens7.lineHeightBase300,
1313
- resize: "none",
1314
- outline: "none",
1315
- width: "100%",
1316
- boxSizing: "border-box",
1317
- minHeight: "40px",
1318
- "&:focus": {
1319
- border: `1px solid ${tokens7.colorNeutralStroke3}`
1320
- }
1321
- },
1322
- userEditFooter: {
1323
- display: "flex",
1324
- marginTop: "8px",
1325
- // marginLeft: "12px",
1326
- color: `${tokens7.colorNeutralForeground3}`,
1327
- gap: "12px",
1328
- alignItems: "center"
1329
- },
1330
- userEditActions: {
1331
- display: "flex",
1332
- justifyContent: "flex-end",
1333
- gap: "8px"
1274
+ gap: "2px"
1334
1275
  },
1335
1276
  // ── Assistant message ──
1336
1277
  messageAssistant: {
@@ -1347,20 +1288,20 @@ var useStyles7 = makeStyles7({
1347
1288
  display: "flex",
1348
1289
  justifyContent: "space-between",
1349
1290
  marginTop: "6px",
1350
- marginLeft: "-10px",
1351
1291
  // Hover-only by default; the latest message overrides this to stay visible.
1352
1292
  opacity: 0,
1353
1293
  transition: "opacity 120ms ease-in-out"
1354
1294
  },
1355
1295
  assistantActions: {
1356
- display: "flex"
1296
+ display: "flex",
1297
+ gap: "2px"
1357
1298
  },
1358
1299
  copiedBadge: {
1359
1300
  display: "inline-flex",
1360
1301
  alignItems: "center",
1361
1302
  justifyContent: "center",
1362
- width: "32px",
1363
- height: "32px",
1303
+ width: "24px",
1304
+ height: "24px",
1364
1305
  color: tokens7.colorPaletteSeafoamForeground2
1365
1306
  },
1366
1307
  footerIconButton: {
@@ -1387,7 +1328,6 @@ var ChatMessages = ({
1387
1328
  thinkingStatus,
1388
1329
  sendMessage,
1389
1330
  regenerate,
1390
- editMessage,
1391
1331
  handleCopy,
1392
1332
  lastUserInputRef,
1393
1333
  registerMessagesContainer,
@@ -1402,55 +1342,10 @@ var ChatMessages = ({
1402
1342
  const isSidecar = surface === "panel-right";
1403
1343
  const [copiedKey, setCopiedKey] = useState5(null);
1404
1344
  const copiedTimerRef = useRef4(null);
1405
- const [editingId, setEditingId] = useState5(null);
1406
- const [editDraft, setEditDraft] = useState5("");
1407
- const editTextareaRef = useRef4(null);
1408
1345
  useEffect4(() => {
1409
1346
  registerMessagesContainer(containerRef.current);
1410
1347
  return () => registerMessagesContainer(null);
1411
1348
  }, []);
1412
- useLayoutEffect2(() => {
1413
- if (editingId && editTextareaRef.current) {
1414
- const ta = editTextareaRef.current;
1415
- ta.focus();
1416
- ta.setSelectionRange(ta.value.length, ta.value.length);
1417
- ta.style.height = "auto";
1418
- ta.style.height = `${ta.scrollHeight}px`;
1419
- }
1420
- }, [editingId]);
1421
- const startEdit = (msg) => {
1422
- if (!msg.id) return;
1423
- setEditingId(msg.id);
1424
- setEditDraft(msg.content);
1425
- };
1426
- const cancelEdit = () => {
1427
- setEditingId(null);
1428
- setEditDraft("");
1429
- };
1430
- const saveEdit = async () => {
1431
- if (!editingId) return;
1432
- const trimmed = editDraft.trim();
1433
- if (!trimmed) return;
1434
- const id = editingId;
1435
- setEditingId(null);
1436
- setEditDraft("");
1437
- await editMessage(id, trimmed);
1438
- };
1439
- const handleEditTextareaInput = (e) => {
1440
- setEditDraft(e.target.value);
1441
- const ta = e.target;
1442
- ta.style.height = "auto";
1443
- ta.style.height = `${ta.scrollHeight}px`;
1444
- };
1445
- const handleEditKeyDown = (e) => {
1446
- if (e.key === "Escape") {
1447
- e.preventDefault();
1448
- cancelEdit();
1449
- } else if (e.key === "Enter" && !e.shiftKey) {
1450
- e.preventDefault();
1451
- void saveEdit();
1452
- }
1453
- };
1454
1349
  const onCopyMerged = (content, key) => {
1455
1350
  handleCopy(content);
1456
1351
  onCopy?.(content);
@@ -1460,7 +1355,6 @@ var ChatMessages = ({
1460
1355
  };
1461
1356
  const renderUserMessage = (msg, index) => {
1462
1357
  const key = msg.id ?? `idx-${index}`;
1463
- const isEditing = !!msg.id && editingId === msg.id;
1464
1358
  const attachments = Array.isArray(msg.metadata?.attachments) ? msg.metadata.attachments : null;
1465
1359
  return /* @__PURE__ */ jsxs7("div", { className: styles.userRow, children: [
1466
1360
  attachments && /* @__PURE__ */ jsx7(
@@ -1506,73 +1400,21 @@ var ChatMessages = ({
1506
1400
  )
1507
1401
  }
1508
1402
  ),
1509
- isEditing ? /* @__PURE__ */ jsxs7("div", { className: styles.userEditWrap, children: [
1510
- /* @__PURE__ */ jsx7(
1511
- "textarea",
1512
- {
1513
- ref: editTextareaRef,
1514
- className: styles.userEditTextarea,
1515
- value: editDraft,
1516
- onChange: handleEditTextareaInput,
1517
- onKeyDown: handleEditKeyDown,
1518
- rows: 1
1519
- }
1520
- ),
1521
- /* @__PURE__ */ jsxs7("div", { className: styles.userEditFooter, children: [
1522
- /* @__PURE__ */ jsx7(
1523
- Info,
1524
- {
1525
- style: {
1526
- marginRight: "6px",
1527
- color: `${tokens7.colorNeutralForeground3}`,
1528
- fontSize: "20px",
1529
- boxSizing: "border-box",
1530
- flexShrink: 0
1531
- }
1532
- }
1533
- ),
1534
- /* @__PURE__ */ jsx7(Caption12, { children: "Editing this message will discard the current response and regenerate from here." }),
1535
- /* @__PURE__ */ jsxs7("div", { className: styles.userEditActions, children: [
1536
- /* @__PURE__ */ jsx7(Button4, { appearance: "subtle", onClick: cancelEdit, children: "Cancel" }),
1537
- /* @__PURE__ */ jsx7(
1538
- Button4,
1539
- {
1540
- appearance: "primary",
1541
- onClick: saveEdit,
1542
- disabled: !editDraft.trim(),
1543
- children: "Save"
1544
- }
1545
- )
1546
- ] })
1547
- ] })
1548
- ] }) : /* @__PURE__ */ jsxs7(Fragment, { children: [
1549
- /* @__PURE__ */ jsx7("div", { className: styles.userBubble, children: /* @__PURE__ */ jsx7(Body15, { children: msg.content.split("\n").map((line, i, arr) => /* @__PURE__ */ jsxs7(React5.Fragment, { children: [
1550
- line,
1551
- i < arr.length - 1 && /* @__PURE__ */ jsx7("br", {})
1552
- ] }, i)) }) }),
1553
- msg.id && /* @__PURE__ */ jsx7("div", { className: `${styles.userFooter} coral-user-footer`, children: /* @__PURE__ */ jsxs7("div", { className: styles.userActions, children: [
1554
- copiedKey === `user-${key}` ? /* @__PURE__ */ jsx7("span", { className: styles.copiedBadge, children: /* @__PURE__ */ jsx7(CheckmarkCircle20Filled, {}) }) : /* @__PURE__ */ jsx7(
1555
- Button4,
1556
- {
1557
- onClick: () => onCopyMerged(msg.content, `user-${key}`),
1558
- title: "Copy message",
1559
- appearance: "subtle",
1560
- className: styles.footerIconButton,
1561
- icon: /* @__PURE__ */ jsx7(Copy, {})
1562
- }
1563
- ),
1564
- /* @__PURE__ */ jsx7(
1565
- Button4,
1566
- {
1567
- onClick: () => startEdit(msg),
1568
- title: "Edit message",
1569
- appearance: "subtle",
1570
- className: styles.footerIconButton,
1571
- icon: /* @__PURE__ */ jsx7(EditIcon, {})
1572
- }
1573
- )
1574
- ] }) })
1575
- ] })
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
+ ) }) })
1576
1418
  ] }, key);
1577
1419
  };
1578
1420
  const renderAssistantMessage = (msg, index) => {
@@ -1651,6 +1493,7 @@ var ChatMessages = ({
1651
1493
  onClick: () => onCopyMerged(msg.content, `assistant-${key}`),
1652
1494
  title: "Copy response",
1653
1495
  appearance: "subtle",
1496
+ size: "small",
1654
1497
  className: styles.footerIconButton,
1655
1498
  icon: /* @__PURE__ */ jsx7(Copy, {})
1656
1499
  }
@@ -1661,6 +1504,7 @@ var ChatMessages = ({
1661
1504
  onClick: () => regenerate(msg.id),
1662
1505
  title: "Regenerate response",
1663
1506
  appearance: "subtle",
1507
+ size: "small",
1664
1508
  className: styles.footerIconButton,
1665
1509
  icon: /* @__PURE__ */ jsx7(ArrowClockwise, {})
1666
1510
  }
@@ -1674,7 +1518,7 @@ var ChatMessages = ({
1674
1518
  "div",
1675
1519
  {
1676
1520
  className: styles.messageWrapper,
1677
- style: isSidecar ? { padding: "0 8px" } : void 0,
1521
+ style: isSidecar ? { padding: "0 16px" } : void 0,
1678
1522
  children: [
1679
1523
  messages.map((msg, index) => {
1680
1524
  if (msg.role === "user") {
@@ -1728,7 +1572,7 @@ import {
1728
1572
  MenuItem
1729
1573
  } from "@fluentui/react-components";
1730
1574
  import { Add, DocumentAdd, ImageAdd } from "@coral-ai/bundleicons";
1731
- 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";
1732
1576
  var ChatAttachButton = ({
1733
1577
  types = ["files", "photos"]
1734
1578
  }) => {
@@ -1737,7 +1581,7 @@ var ChatAttachButton = ({
1737
1581
  const photoRef = useRef5(null);
1738
1582
  const showFiles = types.includes("files");
1739
1583
  const showPhotos = types.includes("photos");
1740
- return /* @__PURE__ */ jsxs8(Fragment2, { children: [
1584
+ return /* @__PURE__ */ jsxs8(Fragment, { children: [
1741
1585
  showFiles && /* @__PURE__ */ jsx8(
1742
1586
  "input",
1743
1587
  {
@@ -1812,9 +1656,6 @@ var useStyles8 = makeStyles8({
1812
1656
  boxSizing: "border-box",
1813
1657
  overflow: "hidden"
1814
1658
  },
1815
- cardFocused: {
1816
- boxShadow: tokens8.shadow28
1817
- },
1818
1659
  cardDisabled: {
1819
1660
  opacity: "0.3",
1820
1661
  pointerEvents: "none"
@@ -1990,7 +1831,7 @@ var ChatInput = forwardRef(
1990
1831
  return /* @__PURE__ */ jsx9("div", { ref: containerRef, className: styles.wrapper, style, children: /* @__PURE__ */ jsxs9(
1991
1832
  "div",
1992
1833
  {
1993
- className: `${styles.card}${isFocused ? ` ${styles.cardFocused}` : ""}${disabled ? ` ${styles.cardDisabled}` : ""}`,
1834
+ className: `${styles.card}${disabled ? ` ${styles.cardDisabled}` : ""}`,
1994
1835
  style: {
1995
1836
  border: isFocused ? `1px solid ${tokens8.colorNeutralStroke1}` : `1px solid ${tokens8.colorNeutralStroke2}`
1996
1837
  },
@@ -2064,7 +1905,7 @@ var ChatInput = forwardRef(
2064
1905
  var Chat_Input_default = ChatInput;
2065
1906
 
2066
1907
  // src/Chat.Approval.tsx
2067
- 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";
2068
1909
  import { jsx as jsx10, jsxs as jsxs10 } from "react/jsx-runtime";
2069
1910
  var useStyles9 = makeStyles9({
2070
1911
  root: {
@@ -2159,7 +2000,7 @@ var ChatApproval = ({
2159
2000
  opt.id
2160
2001
  );
2161
2002
  }) }),
2162
- 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." })
2163
2004
  ]
2164
2005
  }
2165
2006
  );
@@ -2167,7 +2008,7 @@ var ChatApproval = ({
2167
2008
  var Chat_Approval_default = ChatApproval;
2168
2009
 
2169
2010
  // src/Chat.tsx
2170
- 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";
2171
2012
  var useStyles10 = makeStyles10({
2172
2013
  emptySlot: {
2173
2014
  width: "100%",
@@ -2208,15 +2049,10 @@ var useStyles10 = makeStyles10({
2208
2049
  justifyContent: "center"
2209
2050
  }
2210
2051
  });
2211
- var remapFontSizeForSurface = (size, surface) => {
2212
- if (surface === "panel-right" && (size === void 0 || size === "default")) {
2213
- return "small";
2214
- }
2215
- return size;
2216
- };
2217
2052
  var ChatLayout = ({
2218
2053
  welcomeMessage,
2219
2054
  promptSuggestions,
2055
+ disclaimer,
2220
2056
  surfaceMotion,
2221
2057
  placeholder,
2222
2058
  disabled,
@@ -2231,13 +2067,6 @@ var ChatLayout = ({
2231
2067
  const welcomeIsFill = welcomeMessage !== void 0 && typeof welcomeMessage !== "string";
2232
2068
  const welcomeNode = typeof welcomeMessage === "string" ? /* @__PURE__ */ jsx11(Title3, { children: welcomeMessage }) : welcomeMessage;
2233
2069
  const styles = useStyles10();
2234
- const surfaceProbeRef = useRef7(null);
2235
- const [surface, setSurface] = useState7(null);
2236
- useLayoutEffect3(() => {
2237
- const el = surfaceProbeRef.current?.closest("[data-coral-surface]");
2238
- setSurface(el?.getAttribute("data-coral-surface") ?? null);
2239
- }, []);
2240
- const effectiveFontSize = remapFontSizeForSurface(fontSize, surface);
2241
2070
  const { messages, isTyping, pendingApproval, awaitingFreeformApproval } = useChatContext();
2242
2071
  const empty = messages.every((m) => m.role === "system") && !isTyping;
2243
2072
  const approvalLocksInput = pendingApproval !== null && awaitingFreeformApproval === null;
@@ -2246,11 +2075,10 @@ var ChatLayout = ({
2246
2075
  const curve = motionTokens.curveDecelerateMax;
2247
2076
  const spacerTransition = motionEnabled ? `flex-grow 300ms ${curve}` : "none";
2248
2077
  const gapTransition = motionEnabled ? `height 300ms ${curve}` : "none";
2249
- return /* @__PURE__ */ jsxs11(Fragment3, { children: [
2078
+ return /* @__PURE__ */ jsxs11(Fragment2, { children: [
2250
2079
  /* @__PURE__ */ jsx11(
2251
2080
  "div",
2252
2081
  {
2253
- ref: surfaceProbeRef,
2254
2082
  style: {
2255
2083
  flexGrow: empty && !welcomeIsFill ? 1 : 0,
2256
2084
  flexShrink: 1,
@@ -2285,7 +2113,7 @@ var ChatLayout = ({
2285
2113
  components,
2286
2114
  onCopy,
2287
2115
  onNavigate,
2288
- fontSize: effectiveFontSize,
2116
+ fontSize,
2289
2117
  fontFamily
2290
2118
  }
2291
2119
  )
@@ -2317,8 +2145,8 @@ var ChatLayout = ({
2317
2145
  }
2318
2146
  }
2319
2147
  ),
2320
- /* @__PURE__ */ jsx11(
2321
- Caption14,
2148
+ disclaimer != null && disclaimer !== false && /* @__PURE__ */ jsx11(
2149
+ Caption13,
2322
2150
  {
2323
2151
  style: {
2324
2152
  display: "flex",
@@ -2327,7 +2155,7 @@ var ChatLayout = ({
2327
2155
  height: "32px",
2328
2156
  opacity: 0.5
2329
2157
  },
2330
- children: "AI makes mistakes. Check outputs."
2158
+ children: disclaimer
2331
2159
  }
2332
2160
  )
2333
2161
  ] });
@@ -2347,6 +2175,7 @@ var Chat = ({
2347
2175
  onStop,
2348
2176
  welcomeMessage,
2349
2177
  promptSuggestions,
2178
+ disclaimer,
2350
2179
  surfaceMotion,
2351
2180
  components,
2352
2181
  onCopy,
@@ -2381,6 +2210,7 @@ var Chat = ({
2381
2210
  {
2382
2211
  welcomeMessage,
2383
2212
  promptSuggestions,
2213
+ disclaimer,
2384
2214
  surfaceMotion,
2385
2215
  placeholder,
2386
2216
  disabled,
@@ -2737,13 +2567,13 @@ function createAgentHandler(options) {
2737
2567
  }
2738
2568
 
2739
2569
  // src/Chat.Threads.tsx
2740
- import * as React9 from "react";
2570
+ import * as React8 from "react";
2741
2571
  import { jsx as jsx12 } from "react/jsx-runtime";
2742
- var ChatThreadsContext = React9.createContext(
2572
+ var ChatThreadsContext = React8.createContext(
2743
2573
  null
2744
2574
  );
2745
2575
  function useChatThreads() {
2746
- const value = React9.useContext(ChatThreadsContext);
2576
+ const value = React8.useContext(ChatThreadsContext);
2747
2577
  if (!value) {
2748
2578
  throw new Error(
2749
2579
  "useChatThreads must be used inside <ChatThreadsProvider>."
@@ -2789,25 +2619,25 @@ function ChatThreadsProvider({
2789
2619
  onActiveThreadChange,
2790
2620
  children
2791
2621
  }) {
2792
- const adapter = React9.useMemo(
2622
+ const adapter = React8.useMemo(
2793
2623
  () => providedAdapter ?? createMemoryThreadsAdapter(),
2794
2624
  [providedAdapter]
2795
2625
  );
2796
- const [threads, setThreads] = React9.useState([]);
2797
- const [uncontrolledId, setUncontrolledId] = React9.useState(
2626
+ const [threads, setThreads] = React8.useState([]);
2627
+ const [uncontrolledId, setUncontrolledId] = React8.useState(
2798
2628
  defaultActiveThreadId
2799
2629
  );
2800
- const [isLoading, setIsLoading] = React9.useState(true);
2630
+ const [isLoading, setIsLoading] = React8.useState(true);
2801
2631
  const isControlled = controlledId !== void 0;
2802
2632
  const activeThreadId = isControlled ? controlledId : uncontrolledId;
2803
- const setActiveThreadId = React9.useCallback(
2633
+ const setActiveThreadId = React8.useCallback(
2804
2634
  (id) => {
2805
2635
  if (!isControlled) setUncontrolledId(id);
2806
2636
  onActiveThreadChange?.(id);
2807
2637
  },
2808
2638
  [isControlled, onActiveThreadChange]
2809
2639
  );
2810
- React9.useEffect(() => {
2640
+ React8.useEffect(() => {
2811
2641
  let cancelled = false;
2812
2642
  (async () => {
2813
2643
  setIsLoading(true);
@@ -2820,7 +2650,7 @@ function ChatThreadsProvider({
2820
2650
  cancelled = true;
2821
2651
  };
2822
2652
  }, [adapter]);
2823
- const createThread = React9.useCallback(
2653
+ const createThread = React8.useCallback(
2824
2654
  async (initial) => {
2825
2655
  const thread = await adapter.create(initial);
2826
2656
  setThreads((prev) => [thread, ...prev.filter((t) => t.id !== thread.id)]);
@@ -2828,7 +2658,7 @@ function ChatThreadsProvider({
2828
2658
  },
2829
2659
  [adapter]
2830
2660
  );
2831
- const renameThread = React9.useCallback(
2661
+ const renameThread = React8.useCallback(
2832
2662
  async (id, newTitle) => {
2833
2663
  await adapter.rename(id, newTitle);
2834
2664
  setThreads(
@@ -2839,7 +2669,7 @@ function ChatThreadsProvider({
2839
2669
  },
2840
2670
  [adapter]
2841
2671
  );
2842
- const removeThread = React9.useCallback(
2672
+ const removeThread = React8.useCallback(
2843
2673
  async (id) => {
2844
2674
  await adapter.remove(id);
2845
2675
  setThreads((prev) => prev.filter((t) => t.id !== id));
@@ -2847,9 +2677,9 @@ function ChatThreadsProvider({
2847
2677
  },
2848
2678
  [adapter, activeThreadId, setActiveThreadId]
2849
2679
  );
2850
- const threadsRef = React9.useRef(threads);
2680
+ const threadsRef = React8.useRef(threads);
2851
2681
  threadsRef.current = threads;
2852
- const updateThreadMessages = React9.useCallback(
2682
+ const updateThreadMessages = React8.useCallback(
2853
2683
  (id, messages) => {
2854
2684
  const existing = threadsRef.current.find((t) => t.id === id);
2855
2685
  if (!existing) return;
@@ -2863,11 +2693,11 @@ function ChatThreadsProvider({
2863
2693
  },
2864
2694
  [adapter]
2865
2695
  );
2866
- const activeThread = React9.useMemo(
2696
+ const activeThread = React8.useMemo(
2867
2697
  () => threads.find((t) => t.id === activeThreadId),
2868
2698
  [threads, activeThreadId]
2869
2699
  );
2870
- const value = React9.useMemo(
2700
+ const value = React8.useMemo(
2871
2701
  () => ({
2872
2702
  threads,
2873
2703
  activeThreadId,