@xinghunm/ai-chat 1.0.2 → 1.1.1

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
@@ -47,7 +47,7 @@ module.exports = __toCommonJS(src_exports);
47
47
 
48
48
  // src/components/ai-chat/index.tsx
49
49
  var import_styled17 = __toESM(require("@emotion/styled"));
50
- var import_compass_ui4 = require("@xinghunm/compass-ui");
50
+ var import_compass_ui5 = require("@xinghunm/compass-ui");
51
51
 
52
52
  // src/components/ai-chat-provider/index.tsx
53
53
  var import_react2 = require("react");
@@ -68,6 +68,7 @@ var DEFAULT_AI_CHAT_LABELS = {
68
68
  sendButton: "Send",
69
69
  stopButton: "Stop",
70
70
  retryButton: "Retry",
71
+ scrollToLatest: "Jump to latest",
71
72
  placeholder: "Ask something...",
72
73
  modeLabelAsk: "Ask",
73
74
  modeLabelPlan: "Plan",
@@ -89,7 +90,10 @@ var DEFAULT_AI_CHAT_LABELS = {
89
90
  questionnaireSubmitting: "Submitting...",
90
91
  questionnaireSubmitted: "Selection submitted. Waiting for the plan to continue...",
91
92
  questionnaireValidationPrefix: "Please complete:",
92
- questionnaireSubmitFailed: "Failed to submit. Please try again."
93
+ questionnaireSubmitFailed: "Failed to submit. Please try again.",
94
+ questionnaireMultiSelectHint: "Multiple choice",
95
+ questionnaireOtherOptionLabel: "Other",
96
+ questionnaireOtherPlaceholder: "Other"
93
97
  };
94
98
 
95
99
  // src/store/chat-store.ts
@@ -1534,29 +1538,120 @@ var Value = import_styled3.default.span`
1534
1538
  // src/components/chat-thread/components/questionnaire-card.tsx
1535
1539
  var import_react7 = require("react");
1536
1540
  var import_styled4 = __toESM(require("@emotion/styled"));
1537
- var import_jsx_runtime5 = require("@emotion/react/jsx-runtime");
1541
+ var import_compass_ui = require("@xinghunm/compass-ui");
1542
+
1543
+ // src/components/chat-thread/components/questionnaire-card-helpers.ts
1538
1544
  var OTHER_OPTION_VALUE = "__other__";
1539
- var DEFAULT_QUESTIONNAIRE_CARD_LABELS = {
1540
- submitting: "Submitting...",
1541
- submitted: "Selection submitted. Waiting for the plan to continue...",
1542
- validationPrefix: "Please complete:",
1543
- submitFailed: "Failed to submit. Please try again."
1544
- };
1545
- var createInitialAnswers = (questionnaire) => ({
1546
- ...questionnaire.answers ?? {}
1547
- });
1545
+ var getQuestionnaireQuestion = (questionnaire) => questionnaire.question;
1548
1546
  var getMultiSelectAnswerValues = (answer) => Array.isArray(answer) ? answer : [];
1549
- var getSingleSelectDraftState = (question, answer) => {
1547
+ var getQuestionOptionValues = (question) => new Set(question.options.map((option) => option.value));
1548
+ var extractSingleSelectOtherDraft = (question, answer) => {
1549
+ if (typeof answer !== "string") {
1550
+ return "";
1551
+ }
1552
+ return getQuestionOptionValues(question).has(answer) ? "" : answer;
1553
+ };
1554
+ var extractMultiSelectOtherDraft = (question, answer) => {
1555
+ if (!Array.isArray(answer)) {
1556
+ return "";
1557
+ }
1558
+ const optionValues = getQuestionOptionValues(question);
1559
+ const customValue = answer.find(
1560
+ (value) => typeof value === "string" && value !== OTHER_OPTION_VALUE && !optionValues.has(value)
1561
+ );
1562
+ return typeof customValue === "string" ? customValue : "";
1563
+ };
1564
+ var createInitialAnswers = (questionnaire) => {
1565
+ const initialAnswers = {};
1566
+ const question = getQuestionnaireQuestion(questionnaire);
1567
+ if (!question) {
1568
+ return initialAnswers;
1569
+ }
1570
+ const answer = questionnaire.answers?.[question.id];
1571
+ switch (question.kind) {
1572
+ case "single_select": {
1573
+ if (typeof answer !== "string") {
1574
+ break;
1575
+ }
1576
+ if (getQuestionOptionValues(question).has(answer)) {
1577
+ initialAnswers[question.id] = answer;
1578
+ break;
1579
+ }
1580
+ if (question.allowOther) {
1581
+ initialAnswers[question.id] = OTHER_OPTION_VALUE;
1582
+ }
1583
+ break;
1584
+ }
1585
+ case "multi_select": {
1586
+ if (!Array.isArray(answer)) {
1587
+ break;
1588
+ }
1589
+ const optionValues = getQuestionOptionValues(question);
1590
+ const selectedValues = [];
1591
+ let hasOtherValue = false;
1592
+ for (const value of answer) {
1593
+ if (typeof value !== "string") {
1594
+ continue;
1595
+ }
1596
+ if (optionValues.has(value)) {
1597
+ selectedValues.push(value);
1598
+ continue;
1599
+ }
1600
+ if (question.allowOther && !hasOtherValue) {
1601
+ selectedValues.push(OTHER_OPTION_VALUE);
1602
+ hasOtherValue = true;
1603
+ }
1604
+ }
1605
+ initialAnswers[question.id] = selectedValues;
1606
+ break;
1607
+ }
1608
+ default:
1609
+ initialAnswers[question.id] = answer;
1610
+ }
1611
+ return initialAnswers;
1612
+ };
1613
+ var createInitialOtherDrafts = (questionnaire) => {
1614
+ const drafts = {};
1615
+ const question = getQuestionnaireQuestion(questionnaire);
1616
+ if (!question) {
1617
+ return drafts;
1618
+ }
1619
+ const answer = questionnaire.answers?.[question.id];
1620
+ switch (question.kind) {
1621
+ case "single_select":
1622
+ if (question.allowOther) {
1623
+ drafts[question.id] = extractSingleSelectOtherDraft(question, answer);
1624
+ }
1625
+ break;
1626
+ case "multi_select":
1627
+ if (question.allowOther) {
1628
+ drafts[question.id] = extractMultiSelectOtherDraft(question, answer);
1629
+ }
1630
+ break;
1631
+ default:
1632
+ break;
1633
+ }
1634
+ return drafts;
1635
+ };
1636
+ var getMultiSelectDraftState = (question, answer, otherDraft) => {
1637
+ const answerValues = getMultiSelectAnswerValues(answer);
1638
+ return {
1639
+ selectedValues: answerValues,
1640
+ otherValue: otherDraft,
1641
+ hasOtherSelected: question.allowOther === true && answerValues.includes(OTHER_OPTION_VALUE)
1642
+ };
1643
+ };
1644
+ var getSingleSelectDraftState = (question, answer, otherDraft) => {
1550
1645
  if (typeof answer !== "string") {
1551
1646
  return {
1552
1647
  selectedValue: void 0,
1553
- otherValue: ""
1648
+ otherValue: otherDraft
1554
1649
  };
1555
1650
  }
1556
- const matchesOption = question.options.some((option) => option.value === answer);
1651
+ const matchesOption = answer !== OTHER_OPTION_VALUE && question.options.some((option) => option.value === answer);
1557
1652
  return {
1558
1653
  selectedValue: matchesOption ? answer : question.allowOther ? OTHER_OPTION_VALUE : void 0,
1559
- otherValue: matchesOption ? "" : answer
1654
+ otherValue: otherDraft
1560
1655
  };
1561
1656
  };
1562
1657
  var updateAnswerValue = (current, questionId, value) => ({
@@ -1568,6 +1663,17 @@ var toggleMultiSelectAnswer = (current, questionId, optionValue) => {
1568
1663
  const nextValues = currentValues.includes(optionValue) ? currentValues.filter((value) => value !== optionValue) : [...currentValues, optionValue];
1569
1664
  return updateAnswerValue(current, questionId, nextValues);
1570
1665
  };
1666
+ var toggleMultiSelectOtherAnswer = (current, question) => {
1667
+ const currentValues = getMultiSelectAnswerValues(current[question.id]);
1668
+ if (currentValues.includes(OTHER_OPTION_VALUE)) {
1669
+ return updateAnswerValue(
1670
+ current,
1671
+ question.id,
1672
+ currentValues.filter((value) => value !== OTHER_OPTION_VALUE)
1673
+ );
1674
+ }
1675
+ return updateAnswerValue(current, question.id, [...currentValues, OTHER_OPTION_VALUE]);
1676
+ };
1571
1677
  var getTextInputValue = (answer) => typeof answer === "string" ? String(answer) : "";
1572
1678
  var getNumberInputValue = (answer) => typeof answer === "number" || typeof answer === "string" ? String(answer) : "";
1573
1679
  var getOptionChoiceLabel = (index) => {
@@ -1576,20 +1682,49 @@ var getOptionChoiceLabel = (index) => {
1576
1682
  }
1577
1683
  return String(index + 1);
1578
1684
  };
1579
- var isMissingRequiredAnswer = (question, answers) => {
1580
- const answer = answers[question.id];
1685
+ var normalizeQuestionAnswer = (question, answer, otherDraft = "") => {
1686
+ if (answer === void 0) {
1687
+ return void 0;
1688
+ }
1581
1689
  switch (question.kind) {
1582
- case "boolean":
1583
- return typeof answer !== "boolean";
1584
1690
  case "multi_select":
1585
- return !Array.isArray(answer) || answer.length === 0;
1586
- case "number":
1587
- return typeof answer !== "number" || Number.isNaN(answer);
1588
- case "text":
1691
+ if (!Array.isArray(answer)) {
1692
+ return void 0;
1693
+ }
1694
+ return (() => {
1695
+ const optionValues = getQuestionOptionValues(question);
1696
+ const normalizedOtherDraft = otherDraft.trim();
1697
+ const normalizedValues = answer.flatMap((value) => {
1698
+ if (typeof value !== "string") {
1699
+ return [];
1700
+ }
1701
+ if (optionValues.has(value)) {
1702
+ return [value];
1703
+ }
1704
+ if (!question.allowOther || value !== OTHER_OPTION_VALUE) {
1705
+ return [];
1706
+ }
1707
+ return normalizedOtherDraft === "" ? [] : [normalizedOtherDraft];
1708
+ });
1709
+ return normalizedValues.length > 0 ? normalizedValues : void 0;
1710
+ })();
1589
1711
  case "single_select":
1590
- return typeof answer !== "string" || answer.trim() === "";
1712
+ if (answer === OTHER_OPTION_VALUE) {
1713
+ const normalizedOtherDraft = otherDraft.trim();
1714
+ return normalizedOtherDraft === "" ? void 0 : normalizedOtherDraft;
1715
+ }
1716
+ if (typeof answer !== "string" || answer.trim() === "") {
1717
+ return void 0;
1718
+ }
1719
+ return getQuestionOptionValues(question).has(answer) ? answer : void 0;
1720
+ case "text":
1721
+ return typeof answer === "string" && answer.trim() !== "" ? answer : void 0;
1722
+ case "number":
1723
+ return typeof answer === "number" && !Number.isNaN(answer) ? answer : void 0;
1724
+ case "boolean":
1725
+ return typeof answer === "boolean" ? answer : void 0;
1591
1726
  default:
1592
- return true;
1727
+ return answer;
1593
1728
  }
1594
1729
  };
1595
1730
  var formatQuestionAnswer = (question, answer) => {
@@ -1617,80 +1752,221 @@ var formatQuestionAnswer = (question, answer) => {
1617
1752
  return String(answer);
1618
1753
  }
1619
1754
  };
1620
- var normalizeQuestionAnswer = (question, answer) => {
1755
+ var buildQuestionSubmissionDetail = (question, answer) => {
1621
1756
  if (answer === void 0) {
1622
1757
  return void 0;
1623
1758
  }
1624
1759
  switch (question.kind) {
1625
- case "multi_select":
1626
- return Array.isArray(answer) && answer.length > 0 ? answer : void 0;
1627
- case "single_select":
1628
- case "text":
1629
- return typeof answer === "string" && answer.trim() !== "" ? answer : void 0;
1630
- case "number":
1631
- return typeof answer === "number" && !Number.isNaN(answer) ? answer : void 0;
1632
- case "boolean":
1633
- return typeof answer === "boolean" ? answer : void 0;
1760
+ case "single_select": {
1761
+ if (typeof answer !== "string") {
1762
+ return void 0;
1763
+ }
1764
+ const optionValues = getQuestionOptionValues(question);
1765
+ const trimmedAnswer = answer.trim();
1766
+ return {
1767
+ questionId: question.id,
1768
+ kind: question.kind,
1769
+ value: answer,
1770
+ selectedOptionValues: optionValues.has(answer) ? [answer] : [],
1771
+ otherValue: optionValues.has(answer) || trimmedAnswer === "" ? void 0 : trimmedAnswer
1772
+ };
1773
+ }
1774
+ case "multi_select": {
1775
+ if (!Array.isArray(answer)) {
1776
+ return void 0;
1777
+ }
1778
+ const optionValues = getQuestionOptionValues(question);
1779
+ const selectedOptionValues = answer.filter(
1780
+ (value) => typeof value === "string" && optionValues.has(value)
1781
+ );
1782
+ const otherValue = answer.find(
1783
+ (value) => typeof value === "string" && !optionValues.has(value)
1784
+ );
1785
+ return {
1786
+ questionId: question.id,
1787
+ kind: question.kind,
1788
+ value: answer,
1789
+ selectedOptionValues,
1790
+ otherValue: otherValue?.trim() ? otherValue.trim() : void 0
1791
+ };
1792
+ }
1634
1793
  default:
1635
- return answer;
1794
+ return {
1795
+ questionId: question.id,
1796
+ kind: question.kind,
1797
+ value: answer
1798
+ };
1636
1799
  }
1637
1800
  };
1801
+ var getMissingRequiredQuestions = (questionnaire, answers, otherDrafts) => {
1802
+ const question = getQuestionnaireQuestion(questionnaire);
1803
+ if (!question || !question.required) {
1804
+ return [];
1805
+ }
1806
+ return normalizeQuestionAnswer(question, answers[question.id], otherDrafts[question.id]) === void 0 ? [question] : [];
1807
+ };
1808
+ var prepareQuestionnaireSubmission = (questionnaire, answers, otherDrafts) => {
1809
+ const question = getQuestionnaireQuestion(questionnaire);
1810
+ if (!question) {
1811
+ return {
1812
+ normalizedAnswers: {},
1813
+ submissionDetails: void 0,
1814
+ content: questionnaire.title ?? "Questionnaire responses"
1815
+ };
1816
+ }
1817
+ const value = normalizeQuestionAnswer(question, answers[question.id], otherDrafts[question.id]);
1818
+ const normalizedAnswers = value === void 0 ? {} : { [question.id]: value };
1819
+ const detail = buildQuestionSubmissionDetail(question, normalizedAnswers[question.id]);
1820
+ const submissionDetails = detail === void 0 ? void 0 : { [question.id]: detail };
1821
+ return {
1822
+ normalizedAnswers,
1823
+ submissionDetails,
1824
+ content: [
1825
+ questionnaire.title ?? "Questionnaire responses",
1826
+ ...normalizedAnswers[question.id] === void 0 ? [] : [
1827
+ `- ${question.label}: ${formatQuestionAnswer(question, normalizedAnswers[question.id])}`
1828
+ ]
1829
+ ].join("\n")
1830
+ };
1831
+ };
1832
+ var getQuestionnaireStateKey = (questionnaire) => JSON.stringify([
1833
+ questionnaire.questionnaireId,
1834
+ questionnaire.blockKey,
1835
+ questionnaire.question,
1836
+ questionnaire.status,
1837
+ questionnaire.statusMessage
1838
+ ]);
1839
+
1840
+ // src/components/chat-thread/components/questionnaire-card.tsx
1841
+ var import_jsx_runtime5 = require("@emotion/react/jsx-runtime");
1842
+ var DEFAULT_QUESTIONNAIRE_CARD_LABELS = {
1843
+ submitting: "Submitting...",
1844
+ submitted: "Selection submitted. Waiting for the plan to continue...",
1845
+ validationPrefix: "Please complete:",
1846
+ submitFailed: "Failed to submit. Please try again.",
1847
+ multiSelectHint: "Multiple choice",
1848
+ otherOptionLabel: "Other",
1849
+ otherPlaceholder: "Other"
1850
+ };
1851
+ var stopInputClickPropagation = (event) => {
1852
+ event.stopPropagation();
1853
+ };
1854
+ var stopInputKeyPropagation = (event) => {
1855
+ event.stopPropagation();
1856
+ };
1857
+ var OptionChoice = ({
1858
+ questionId,
1859
+ optionLabel,
1860
+ index,
1861
+ isSelected,
1862
+ isInteractionLocked,
1863
+ onClick,
1864
+ inlineInput,
1865
+ tone = "default"
1866
+ }) => /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
1867
+ OptionChoiceItem,
1868
+ {
1869
+ role: "button",
1870
+ tabIndex: isInteractionLocked ? -1 : 0,
1871
+ "aria-pressed": isSelected,
1872
+ "data-selected": isSelected,
1873
+ "data-tone": tone,
1874
+ "data-testid": `question-option-${questionId}-${index}`,
1875
+ onClick: (event) => {
1876
+ if (isInteractionLocked) {
1877
+ return;
1878
+ }
1879
+ if (event.target instanceof HTMLElement && event.target.closest("input")) {
1880
+ return;
1881
+ }
1882
+ onClick();
1883
+ },
1884
+ onKeyDown: (event) => {
1885
+ if (isInteractionLocked) {
1886
+ return;
1887
+ }
1888
+ if (event.key !== "Enter" && event.key !== " ") {
1889
+ return;
1890
+ }
1891
+ event.preventDefault();
1892
+ onClick();
1893
+ },
1894
+ children: [
1895
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(OptionChoiceMarker, { "data-selected": isSelected, children: getOptionChoiceLabel(index) }),
1896
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(OptionChoiceContent, { children: [
1897
+ inlineInput ? null : /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(OptionChoiceLabel, { children: optionLabel }),
1898
+ inlineInput
1899
+ ] })
1900
+ ]
1901
+ }
1902
+ );
1638
1903
  var QuestionnaireCardInner = ({
1639
1904
  questionnaire,
1640
1905
  interactive = false,
1641
1906
  onSubmit,
1642
1907
  labels
1643
1908
  }) => {
1909
+ const questionnaireRef = (0, import_react7.useRef)(questionnaire);
1910
+ const otherInputRefs = (0, import_react7.useRef)({});
1644
1911
  const [answers, setAnswers] = (0, import_react7.useState)(
1645
1912
  () => createInitialAnswers(questionnaire)
1646
1913
  );
1914
+ const [otherDrafts, setOtherDrafts] = (0, import_react7.useState)(
1915
+ () => createInitialOtherDrafts(questionnaire)
1916
+ );
1647
1917
  const [errorMessage, setErrorMessage] = (0, import_react7.useState)(null);
1648
1918
  const [isSubmitting, setIsSubmitting] = (0, import_react7.useState)(false);
1649
1919
  const [isSubmitted, setIsSubmitted] = (0, import_react7.useState)(false);
1920
+ const [pendingFocusQuestionId, setPendingFocusQuestionId] = (0, import_react7.useState)(null);
1650
1921
  const resolvedLabels = {
1651
1922
  ...DEFAULT_QUESTIONNAIRE_CARD_LABELS,
1652
1923
  ...labels
1653
1924
  };
1654
1925
  const hasExternalFailureStatus = questionnaire.status === "expired" || questionnaire.status === "failed";
1926
+ const question = getQuestionnaireQuestion(questionnaire);
1655
1927
  const visibleErrorMessage = questionnaire.statusMessage ?? errorMessage;
1656
1928
  const isInteractionLocked = !interactive || isSubmitting || isSubmitted || hasExternalFailureStatus;
1929
+ questionnaireRef.current = questionnaire;
1930
+ (0, import_react7.useEffect)(() => {
1931
+ setAnswers(createInitialAnswers(questionnaireRef.current));
1932
+ setOtherDrafts(createInitialOtherDrafts(questionnaireRef.current));
1933
+ }, [questionnaire.answers]);
1934
+ (0, import_react7.useEffect)(() => {
1935
+ if (!pendingFocusQuestionId || isInteractionLocked) {
1936
+ return;
1937
+ }
1938
+ const inputElement = otherInputRefs.current[pendingFocusQuestionId];
1939
+ if (!inputElement) {
1940
+ return;
1941
+ }
1942
+ inputElement.focus();
1943
+ setPendingFocusQuestionId(null);
1944
+ }, [isInteractionLocked, pendingFocusQuestionId]);
1657
1945
  const handleSubmit = async () => {
1658
1946
  if (isSubmitting || isSubmitted) {
1659
1947
  return;
1660
1948
  }
1661
- const missingQuestions = questionnaire.questions.filter(
1662
- (question) => question.required && isMissingRequiredAnswer(question, answers)
1663
- );
1949
+ const missingQuestions = getMissingRequiredQuestions(questionnaire, answers, otherDrafts);
1664
1950
  if (missingQuestions.length > 0) {
1665
1951
  setErrorMessage(
1666
- `${resolvedLabels.validationPrefix} ${missingQuestions.map((question) => question.label).join(", ")}`
1952
+ `${resolvedLabels.validationPrefix} ${missingQuestions.map((question2) => question2.label).join(", ")}`
1667
1953
  );
1668
1954
  return;
1669
1955
  }
1670
1956
  setErrorMessage(null);
1671
1957
  setIsSubmitting(true);
1672
- const normalizedAnswers = Object.fromEntries(
1673
- questionnaire.questions.flatMap((question) => {
1674
- const value = normalizeQuestionAnswer(question, answers[question.id]);
1675
- return value === void 0 ? [] : [[question.id, value]];
1676
- })
1958
+ const { normalizedAnswers, submissionDetails, content } = prepareQuestionnaireSubmission(
1959
+ questionnaire,
1960
+ answers,
1961
+ otherDrafts
1677
1962
  );
1678
- const contentLines = [
1679
- questionnaire.title ?? "Questionnaire responses",
1680
- ...questionnaire.questions.flatMap((question) => {
1681
- const value = normalizedAnswers[question.id];
1682
- if (value === void 0) {
1683
- return [];
1684
- }
1685
- return [`- ${question.label}: ${formatQuestionAnswer(question, value)}`];
1686
- })
1687
- ];
1688
1963
  try {
1689
1964
  await onSubmit?.({
1690
1965
  questionnaireId: questionnaire.questionnaireId,
1691
1966
  ...questionnaire.blockKey ? { blockKey: questionnaire.blockKey } : {},
1692
1967
  answers: normalizedAnswers,
1693
- content: contentLines.join("\n")
1968
+ details: submissionDetails,
1969
+ content
1694
1970
  });
1695
1971
  setIsSubmitted(true);
1696
1972
  } catch (error) {
@@ -1699,125 +1975,156 @@ var QuestionnaireCardInner = ({
1699
1975
  setIsSubmitting(false);
1700
1976
  }
1701
1977
  };
1702
- const renderQuestion = (question) => {
1703
- const renderOptionChoice = ({
1704
- questionId,
1705
- optionLabel,
1706
- index,
1707
- isSelected,
1708
- onClick,
1709
- inlineInput,
1710
- tone = "default"
1711
- }) => /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
1712
- OptionChoiceItem,
1713
- {
1714
- role: "button",
1715
- tabIndex: isInteractionLocked ? -1 : 0,
1716
- "aria-pressed": isSelected,
1717
- "data-selected": isSelected,
1718
- "data-tone": tone,
1719
- "data-testid": `question-option-${questionId}-${index}`,
1720
- onClick: (event) => {
1721
- if (isInteractionLocked) {
1722
- return;
1723
- }
1724
- if (event.target instanceof HTMLElement && event.target.closest("input")) {
1725
- return;
1726
- }
1727
- onClick();
1728
- },
1729
- onKeyDown: (event) => {
1730
- if (isInteractionLocked) {
1731
- return;
1732
- }
1733
- if (event.key !== "Enter" && event.key !== " ") {
1734
- return;
1735
- }
1736
- event.preventDefault();
1737
- onClick();
1738
- },
1739
- children: [
1740
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(OptionChoiceMarker, { "data-selected": isSelected, children: getOptionChoiceLabel(index) }),
1741
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(OptionChoiceContent, { children: [
1742
- inlineInput ? null : /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(OptionChoiceLabel, { children: optionLabel }),
1743
- inlineInput
1744
- ] })
1745
- ]
1746
- },
1747
- `${questionId}-${optionLabel}`
1748
- );
1749
- switch (question.kind) {
1750
- case "multi_select":
1751
- return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(QuestionBody, { children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(OptionList, { children: question.options.map((option, index) => {
1752
- const selectedValues = getMultiSelectAnswerValues(answers[question.id]);
1753
- const isSelected = selectedValues.includes(option.value);
1754
- return renderOptionChoice({
1755
- questionId: question.id,
1756
- optionLabel: option.label,
1757
- index,
1758
- isSelected,
1759
- onClick: () => setAnswers(
1760
- (current) => toggleMultiSelectAnswer(current, question.id, option.value)
1761
- )
1762
- });
1763
- }) }) });
1978
+ if (!question) {
1979
+ return null;
1980
+ }
1981
+ const renderQuestion = (questionToRender) => {
1982
+ switch (questionToRender.kind) {
1983
+ case "multi_select": {
1984
+ const multiSelectDraft = getMultiSelectDraftState(
1985
+ questionToRender,
1986
+ answers[questionToRender.id],
1987
+ otherDrafts[questionToRender.id] ?? ""
1988
+ );
1989
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(QuestionBody, { children: /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(OptionList, { children: [
1990
+ questionToRender.options.map((option, index) => {
1991
+ const isSelected = multiSelectDraft.selectedValues.includes(option.value);
1992
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1993
+ OptionChoice,
1994
+ {
1995
+ questionId: questionToRender.id,
1996
+ optionLabel: option.label,
1997
+ index,
1998
+ isSelected,
1999
+ isInteractionLocked,
2000
+ onClick: () => setAnswers(
2001
+ (current) => toggleMultiSelectAnswer(current, questionToRender.id, option.value)
2002
+ )
2003
+ },
2004
+ option.value
2005
+ );
2006
+ }),
2007
+ questionToRender.allowOther ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
2008
+ OptionChoice,
2009
+ {
2010
+ questionId: questionToRender.id,
2011
+ optionLabel: resolvedLabels.otherOptionLabel,
2012
+ index: questionToRender.options.length,
2013
+ isSelected: multiSelectDraft.hasOtherSelected,
2014
+ isInteractionLocked,
2015
+ tone: "other",
2016
+ onClick: () => {
2017
+ if (!multiSelectDraft.hasOtherSelected) {
2018
+ setPendingFocusQuestionId(questionToRender.id);
2019
+ }
2020
+ setAnswers((current) => toggleMultiSelectOtherAnswer(current, questionToRender));
2021
+ },
2022
+ inlineInput: multiSelectDraft.hasOtherSelected ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
2023
+ InlineOtherInput,
2024
+ {
2025
+ ref: (node) => {
2026
+ otherInputRefs.current[questionToRender.id] = node;
2027
+ },
2028
+ "data-testid": `question-input-${questionToRender.id}`,
2029
+ type: "text",
2030
+ value: multiSelectDraft.otherValue,
2031
+ placeholder: resolvedLabels.otherPlaceholder,
2032
+ readOnly: isInteractionLocked,
2033
+ onClick: stopInputClickPropagation,
2034
+ onKeyDown: stopInputKeyPropagation,
2035
+ onChange: (event) => {
2036
+ setOtherDrafts((current) => ({
2037
+ ...current,
2038
+ [questionToRender.id]: event.target.value
2039
+ }));
2040
+ }
2041
+ }
2042
+ ) : null
2043
+ },
2044
+ `${questionToRender.id}-other`
2045
+ ) : null
2046
+ ] }) });
2047
+ }
1764
2048
  case "single_select": {
1765
- const singleSelectDraft = getSingleSelectDraftState(question, answers[question.id]);
2049
+ const singleSelectDraft = getSingleSelectDraftState(
2050
+ questionToRender,
2051
+ answers[questionToRender.id],
2052
+ otherDrafts[questionToRender.id] ?? ""
2053
+ );
1766
2054
  return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(QuestionBody, { children: /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(OptionList, { children: [
1767
- question.options.map((option, index) => {
2055
+ questionToRender.options.map((option, index) => {
1768
2056
  const isSelected = singleSelectDraft.selectedValue === option.value;
1769
- return renderOptionChoice({
1770
- questionId: question.id,
1771
- optionLabel: option.label,
1772
- index,
1773
- isSelected,
1774
- onClick: () => setAnswers((current) => updateAnswerValue(current, question.id, option.value))
1775
- });
1776
- }),
1777
- question.allowOther ? renderOptionChoice({
1778
- questionId: question.id,
1779
- optionLabel: "Other",
1780
- index: question.options.length,
1781
- isSelected: singleSelectDraft.selectedValue === OTHER_OPTION_VALUE,
1782
- tone: "other",
1783
- onClick: () => setAnswers(
1784
- (current) => updateAnswerValue(current, question.id, singleSelectDraft.otherValue)
1785
- ),
1786
- inlineInput: singleSelectDraft.selectedValue === OTHER_OPTION_VALUE ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1787
- InlineOtherInput,
2057
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
2058
+ OptionChoice,
1788
2059
  {
1789
- "data-testid": `question-input-${question.id}`,
1790
- type: "text",
1791
- value: singleSelectDraft.otherValue,
1792
- placeholder: "Other",
1793
- readOnly: isInteractionLocked,
1794
- onClick: (event) => {
1795
- event.stopPropagation();
1796
- },
1797
- onKeyDown: (event) => {
1798
- event.stopPropagation();
1799
- },
1800
- onChange: (event) => {
1801
- setAnswers(
1802
- (current) => updateAnswerValue(current, question.id, event.target.value)
1803
- );
2060
+ questionId: questionToRender.id,
2061
+ optionLabel: option.label,
2062
+ index,
2063
+ isSelected,
2064
+ isInteractionLocked,
2065
+ onClick: () => setAnswers(
2066
+ (current) => updateAnswerValue(current, questionToRender.id, option.value)
2067
+ )
2068
+ },
2069
+ option.value
2070
+ );
2071
+ }),
2072
+ questionToRender.allowOther ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
2073
+ OptionChoice,
2074
+ {
2075
+ questionId: questionToRender.id,
2076
+ optionLabel: resolvedLabels.otherOptionLabel,
2077
+ index: questionToRender.options.length,
2078
+ isSelected: singleSelectDraft.selectedValue === OTHER_OPTION_VALUE,
2079
+ isInteractionLocked,
2080
+ tone: "other",
2081
+ onClick: () => {
2082
+ if (singleSelectDraft.selectedValue !== OTHER_OPTION_VALUE) {
2083
+ setPendingFocusQuestionId(questionToRender.id);
1804
2084
  }
1805
- }
1806
- ) : null
1807
- }) : null
2085
+ setAnswers(
2086
+ (current) => updateAnswerValue(current, questionToRender.id, OTHER_OPTION_VALUE)
2087
+ );
2088
+ },
2089
+ inlineInput: singleSelectDraft.selectedValue === OTHER_OPTION_VALUE ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
2090
+ InlineOtherInput,
2091
+ {
2092
+ ref: (node) => {
2093
+ otherInputRefs.current[questionToRender.id] = node;
2094
+ },
2095
+ "data-testid": `question-input-${questionToRender.id}`,
2096
+ type: "text",
2097
+ value: singleSelectDraft.otherValue,
2098
+ placeholder: resolvedLabels.otherPlaceholder,
2099
+ readOnly: isInteractionLocked,
2100
+ onClick: stopInputClickPropagation,
2101
+ onKeyDown: stopInputKeyPropagation,
2102
+ onChange: (event) => {
2103
+ setOtherDrafts((current) => ({
2104
+ ...current,
2105
+ [questionToRender.id]: event.target.value
2106
+ }));
2107
+ }
2108
+ }
2109
+ ) : null
2110
+ },
2111
+ `${questionToRender.id}-other`
2112
+ ) : null
1808
2113
  ] }) });
1809
2114
  }
1810
2115
  case "text":
1811
2116
  return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(QuestionBody, { children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1812
2117
  TextInput,
1813
2118
  {
1814
- "data-testid": `question-input-${question.id}`,
2119
+ "data-testid": `question-input-${questionToRender.id}`,
1815
2120
  type: "text",
1816
- value: getTextInputValue(answers[question.id]),
1817
- placeholder: question.placeholder,
2121
+ value: getTextInputValue(answers[questionToRender.id]),
2122
+ placeholder: questionToRender.placeholder,
1818
2123
  readOnly: isInteractionLocked,
1819
2124
  onChange: (event) => {
1820
- setAnswers((current) => updateAnswerValue(current, question.id, event.target.value));
2125
+ setAnswers(
2126
+ (current) => updateAnswerValue(current, questionToRender.id, event.target.value)
2127
+ );
1821
2128
  }
1822
2129
  }
1823
2130
  ) });
@@ -1826,55 +2133,63 @@ var QuestionnaireCardInner = ({
1826
2133
  /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1827
2134
  TextInput,
1828
2135
  {
1829
- "data-testid": `question-input-${question.id}`,
2136
+ "data-testid": `question-input-${questionToRender.id}`,
1830
2137
  type: "number",
1831
- value: getNumberInputValue(answers[question.id]),
1832
- placeholder: question.placeholder,
2138
+ value: getNumberInputValue(answers[questionToRender.id]),
2139
+ placeholder: questionToRender.placeholder,
1833
2140
  readOnly: isInteractionLocked,
1834
2141
  onChange: (event) => {
1835
2142
  setAnswers(
1836
2143
  (current) => updateAnswerValue(
1837
2144
  current,
1838
- question.id,
2145
+ questionToRender.id,
1839
2146
  event.target.value === "" ? void 0 : Number(event.target.value)
1840
2147
  )
1841
2148
  );
1842
2149
  }
1843
2150
  }
1844
2151
  ),
1845
- question.unit ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Unit, { children: question.unit }) : null
2152
+ questionToRender.unit ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Unit, { children: questionToRender.unit }) : null
1846
2153
  ] }) });
1847
2154
  case "boolean":
1848
2155
  return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(QuestionBody, { children: /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(OptionList, { children: [
1849
- renderOptionChoice({
1850
- questionId: question.id,
1851
- optionLabel: question.trueLabel ?? "Yes",
1852
- index: 0,
1853
- isSelected: answers[question.id] === true,
1854
- onClick: () => setAnswers((current) => updateAnswerValue(current, question.id, true))
1855
- }),
1856
- renderOptionChoice({
1857
- questionId: question.id,
1858
- optionLabel: question.falseLabel ?? "No",
1859
- index: 1,
1860
- isSelected: answers[question.id] === false,
1861
- onClick: () => setAnswers((current) => updateAnswerValue(current, question.id, false))
1862
- })
2156
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
2157
+ OptionChoice,
2158
+ {
2159
+ questionId: questionToRender.id,
2160
+ optionLabel: questionToRender.trueLabel ?? "Yes",
2161
+ index: 0,
2162
+ isSelected: answers[questionToRender.id] === true,
2163
+ isInteractionLocked,
2164
+ onClick: () => setAnswers((current) => updateAnswerValue(current, questionToRender.id, true))
2165
+ }
2166
+ ),
2167
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
2168
+ OptionChoice,
2169
+ {
2170
+ questionId: questionToRender.id,
2171
+ optionLabel: questionToRender.falseLabel ?? "No",
2172
+ index: 1,
2173
+ isSelected: answers[questionToRender.id] === false,
2174
+ isInteractionLocked,
2175
+ onClick: () => setAnswers((current) => updateAnswerValue(current, questionToRender.id, false))
2176
+ }
2177
+ )
1863
2178
  ] }) });
1864
2179
  default:
1865
2180
  return null;
1866
2181
  }
1867
2182
  };
1868
2183
  return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(Card4, { "data-testid": "questionnaire-card", children: [
1869
- questionnaire.title ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Title3, { children: questionnaire.title }) : null,
1870
2184
  questionnaire.description ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Description, { children: questionnaire.description }) : null,
1871
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(QuestionList, { children: questionnaire.questions.map((question) => /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(QuestionCard, { children: [
2185
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(QuestionList, { children: /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(QuestionCard, { children: [
1872
2186
  /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(QuestionLabel, { children: [
1873
2187
  question.label,
1874
2188
  question.required ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Required, { children: "*" }) : null
1875
2189
  ] }),
2190
+ question.kind === "multi_select" ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(QuestionHint, { children: resolvedLabels.multiSelectHint }) : null,
1876
2191
  renderQuestion(question)
1877
- ] }, question.id)) }),
2192
+ ] }, question.id) }),
1878
2193
  visibleErrorMessage ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(ErrorMessage, { "data-testid": "questionnaire-error", children: visibleErrorMessage }) : null,
1879
2194
  isSubmitted ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(SuccessMessage, { "data-testid": "questionnaire-success", children: resolvedLabels.submitted }) : interactive && !hasExternalFailureStatus ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1880
2195
  SubmitButton,
@@ -1890,12 +2205,6 @@ var QuestionnaireCardInner = ({
1890
2205
  ) : null
1891
2206
  ] });
1892
2207
  };
1893
- var getQuestionnaireStateKey = (questionnaire) => JSON.stringify([
1894
- questionnaire.questionnaireId,
1895
- questionnaire.questions,
1896
- questionnaire.status,
1897
- questionnaire.statusMessage
1898
- ]);
1899
2208
  var QuestionnaireCard = (props) => /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(QuestionnaireCardInner, { ...props }, getQuestionnaireStateKey(props.questionnaire));
1900
2209
  var Card4 = import_styled4.default.section`
1901
2210
  display: grid;
@@ -1905,11 +2214,6 @@ var Card4 = import_styled4.default.section`
1905
2214
  border: 1px solid rgba(255, 255, 255, 0.08);
1906
2215
  background: rgba(255, 255, 255, 0.03);
1907
2216
  `;
1908
- var Title3 = import_styled4.default.strong`
1909
- color: rgba(255, 255, 255, 0.94);
1910
- font-size: 16px;
1911
- line-height: 1.4;
1912
- `;
1913
2217
  var Description = import_styled4.default.p`
1914
2218
  margin: 0;
1915
2219
  color: rgba(255, 255, 255, 0.72);
@@ -1928,13 +2232,18 @@ var QuestionCard = import_styled4.default.div`
1928
2232
  `;
1929
2233
  var QuestionLabel = import_styled4.default.div`
1930
2234
  color: rgba(255, 255, 255, 0.9);
1931
- font-size: 13px;
2235
+ font-size: 14px;
1932
2236
  font-weight: 600;
1933
2237
  `;
1934
2238
  var Required = import_styled4.default.span`
1935
2239
  margin-left: 4px;
1936
2240
  color: rgba(255, 122, 122, 0.9);
1937
2241
  `;
2242
+ var QuestionHint = import_styled4.default.div`
2243
+ color: rgba(132, 180, 255, 0.9);
2244
+ font-size: 12px;
2245
+ line-height: 1.4;
2246
+ `;
1938
2247
  var QuestionBody = import_styled4.default.div`
1939
2248
  display: grid;
1940
2249
  gap: 10px;
@@ -1952,7 +2261,7 @@ var OptionChoiceItem = import_styled4.default.div`
1952
2261
  border: 1px solid rgba(255, 255, 255, 0.1);
1953
2262
  border-radius: 14px;
1954
2263
  background: rgba(255, 255, 255, 0.03);
1955
- padding: 12px 14px;
2264
+ padding: 2px 12px;
1956
2265
  color: rgba(255, 255, 255, 0.9);
1957
2266
  cursor: pointer;
1958
2267
  transition:
@@ -2003,8 +2312,11 @@ var OptionChoiceMarker = import_styled4.default.span`
2003
2312
  }
2004
2313
  `;
2005
2314
  var OptionChoiceContent = import_styled4.default.span`
2006
- display: grid;
2007
- gap: 2px;
2315
+ display: flex;
2316
+ flex-direction: column;
2317
+ justify-content: center;
2318
+ gap: 4px;
2319
+ min-height: 40px;
2008
2320
  min-width: 0;
2009
2321
  flex: 1;
2010
2322
  `;
@@ -2027,8 +2339,37 @@ var TextInput = import_styled4.default.input`
2027
2339
  color: rgba(255, 255, 255, 0.34);
2028
2340
  }
2029
2341
  `;
2030
- var InlineOtherInput = (0, import_styled4.default)(TextInput)`
2342
+ var InlineOtherInput = (0, import_styled4.default)(import_compass_ui.InputField)`
2343
+ width: 100%;
2031
2344
  margin-top: 0;
2345
+
2346
+ .compass-input-field-wrapper {
2347
+ min-height: 30px;
2348
+ border: 1px solid rgba(255, 255, 255, 0.1);
2349
+ border-radius: 10px;
2350
+ background: rgba(13, 15, 21, 0.55);
2351
+ box-shadow: none;
2352
+ padding: 2px 9px;
2353
+ }
2354
+
2355
+ .compass-input-field-wrapper:hover {
2356
+ border-color: rgba(126, 160, 255, 0.28);
2357
+ }
2358
+
2359
+ .compass-input-field-wrapper:focus-within {
2360
+ border-color: rgba(126, 160, 255, 0.42);
2361
+ box-shadow: 0 0 0 1px rgba(126, 160, 255, 0.14);
2362
+ }
2363
+
2364
+ .compass-input-field-input {
2365
+ color: rgba(255, 255, 255, 0.92);
2366
+ font-size: 13px;
2367
+ line-height: 1.2;
2368
+ }
2369
+
2370
+ .compass-input-field-input::placeholder {
2371
+ color: rgba(255, 255, 255, 0.34);
2372
+ }
2032
2373
  `;
2033
2374
  var NumberInputRow = import_styled4.default.div`
2034
2375
  display: flex;
@@ -2337,9 +2678,7 @@ var arePlanQuestionsEqual = (previousQuestion, nextQuestion) => {
2337
2678
  return false;
2338
2679
  }
2339
2680
  };
2340
- var areQuestionnairesEqual = (previousQuestionnaire, nextQuestionnaire) => previousQuestionnaire.questionnaireId === nextQuestionnaire.questionnaireId && previousQuestionnaire.title === nextQuestionnaire.title && previousQuestionnaire.description === nextQuestionnaire.description && previousQuestionnaire.submitLabel === nextQuestionnaire.submitLabel && previousQuestionnaire.status === nextQuestionnaire.status && previousQuestionnaire.statusMessage === nextQuestionnaire.statusMessage && previousQuestionnaire.questions.length === nextQuestionnaire.questions.length && previousQuestionnaire.questions.every(
2341
- (question, index) => arePlanQuestionsEqual(question, nextQuestionnaire.questions[index])
2342
- ) && areQuestionAnswerMapsEqual(previousQuestionnaire.answers, nextQuestionnaire.answers);
2681
+ var areQuestionnairesEqual = (previousQuestionnaire, nextQuestionnaire) => previousQuestionnaire.questionnaireId === nextQuestionnaire.questionnaireId && previousQuestionnaire.title === nextQuestionnaire.title && previousQuestionnaire.description === nextQuestionnaire.description && previousQuestionnaire.submitLabel === nextQuestionnaire.submitLabel && previousQuestionnaire.status === nextQuestionnaire.status && previousQuestionnaire.statusMessage === nextQuestionnaire.statusMessage && arePlanQuestionsEqual(previousQuestionnaire.question, nextQuestionnaire.question) && areQuestionAnswerMapsEqual(previousQuestionnaire.answers, nextQuestionnaire.answers);
2343
2682
  var areMessageBlocksEqual = (previousBlocks, nextBlocks) => {
2344
2683
  if (previousBlocks === nextBlocks) {
2345
2684
  return true;
@@ -2493,7 +2832,10 @@ var ChatMessageItemView = ({
2493
2832
  submitting: labels.questionnaireSubmitting,
2494
2833
  submitted: labels.questionnaireSubmitted,
2495
2834
  validationPrefix: labels.questionnaireValidationPrefix,
2496
- submitFailed: labels.questionnaireSubmitFailed
2835
+ submitFailed: labels.questionnaireSubmitFailed,
2836
+ multiSelectHint: labels.questionnaireMultiSelectHint,
2837
+ otherOptionLabel: labels.questionnaireOtherOptionLabel,
2838
+ otherPlaceholder: labels.questionnaireOtherPlaceholder
2497
2839
  },
2498
2840
  onSubmit: canSubmitQuestionnaire ? (submission) => onQuestionnaireSubmit({
2499
2841
  ...submission,
@@ -2752,8 +3094,34 @@ var CollapseToggle = import_styled7.default.button`
2752
3094
  `;
2753
3095
  var Content = import_styled7.default.div`
2754
3096
  color: rgba(255, 255, 255, 0.92);
3097
+ font-size: 14px;
2755
3098
  line-height: 1.6;
2756
3099
 
3100
+ h1,
3101
+ h2,
3102
+ h3,
3103
+ h4,
3104
+ h5,
3105
+ h6 {
3106
+ margin: 0;
3107
+ line-height: 2.5;
3108
+ }
3109
+
3110
+ h1 {
3111
+ font-size: 18px;
3112
+ }
3113
+
3114
+ h2 {
3115
+ font-size: 16px;
3116
+ }
3117
+
3118
+ h3,
3119
+ h4,
3120
+ h5,
3121
+ h6 {
3122
+ font-size: 14px;
3123
+ }
3124
+
2757
3125
  p {
2758
3126
  margin: 0;
2759
3127
  }
@@ -2765,7 +3133,7 @@ var Content = import_styled7.default.div`
2765
3133
  table {
2766
3134
  width: 100%;
2767
3135
  border-collapse: collapse;
2768
- margin: 0;
3136
+ margin: 8px 0 0;
2769
3137
  overflow: hidden;
2770
3138
  border-radius: 14px;
2771
3139
  border: 1px solid rgba(255, 255, 255, 0.08);
@@ -2789,6 +3157,10 @@ var Content = import_styled7.default.div`
2789
3157
  tbody tr:last-of-type td {
2790
3158
  border-bottom: none;
2791
3159
  }
3160
+ ul,
3161
+ ol {
3162
+ margin: 0 0 8px;
3163
+ }
2792
3164
  `;
2793
3165
  var ContentStack = import_styled7.default.div`
2794
3166
  display: flex;
@@ -2989,6 +3361,8 @@ var HeroSubtitle = import_styled8.default.p`
2989
3361
 
2990
3362
  // src/components/chat-thread/index.tsx
2991
3363
  var import_jsx_runtime10 = require("@emotion/react/jsx-runtime");
3364
+ var CHAT_THREAD_PINNED_THRESHOLD_PX = 32;
3365
+ var isThreadPinnedToBottom = (container) => container.scrollHeight - container.clientHeight - container.scrollTop <= CHAT_THREAD_PINNED_THRESHOLD_PX;
2992
3366
  var renderChatMessage = ({
2993
3367
  message,
2994
3368
  mode,
@@ -3062,6 +3436,7 @@ var ChatThreadView = ({
3062
3436
  streamingMessage,
3063
3437
  error,
3064
3438
  retryButtonLabel,
3439
+ scrollToLatestLabel,
3065
3440
  onRetry,
3066
3441
  onConfirmationSubmit,
3067
3442
  onQuestionnaireSubmit,
@@ -3075,9 +3450,15 @@ var ChatThreadView = ({
3075
3450
  const latestTurn = conversationTurns[conversationTurns.length - 1];
3076
3451
  const previousTurns = conversationTurns.slice(0, -1);
3077
3452
  const latestUserMessageId = latestTurn?.userMessage?.id;
3078
- const latestUserMessageRef = (0, import_react11.useRef)(null);
3453
+ const latestHistoryMessage = historyMessages[historyMessages.length - 1];
3454
+ const latestTurnRef = (0, import_react11.useRef)(null);
3079
3455
  const reservedSpaceFrameRef = (0, import_react11.useRef)(null);
3456
+ const isPinnedRef = (0, import_react11.useRef)(true);
3457
+ const lastHistoryMessageIdRef = (0, import_react11.useRef)(latestHistoryMessage?.id);
3458
+ const lastStreamingMessageIdRef = (0, import_react11.useRef)(streamingMessage?.id);
3080
3459
  const [latestTurnMinHeight, setLatestTurnMinHeight] = (0, import_react11.useState)(0);
3460
+ const [isDetached, setIsDetached] = (0, import_react11.useState)(false);
3461
+ const [pendingNewMessageCount, setPendingNewMessageCount] = (0, import_react11.useState)(0);
3081
3462
  const measureLatestTurnMinHeight = (0, import_react11.useCallback)(() => {
3082
3463
  const container = containerRef.current;
3083
3464
  if (!container)
@@ -3088,26 +3469,86 @@ var ChatThreadView = ({
3088
3469
  const nextMinHeight = Math.max(0, container.clientHeight - paddingTop - paddingBottom);
3089
3470
  setLatestTurnMinHeight((current) => current === nextMinHeight ? current : nextMinHeight);
3090
3471
  }, []);
3091
- const scrollLatestUserMessageToTop = (0, import_react11.useCallback)(() => {
3472
+ const scrollToBottom = (0, import_react11.useCallback)((force = false) => {
3092
3473
  const container = containerRef.current;
3093
- const target = latestUserMessageRef.current;
3094
- if (!container || !target)
3095
- return;
3096
- const containerRect = container.getBoundingClientRect();
3097
- const targetRect = target.getBoundingClientRect();
3098
- const nextScrollTop = Math.max(
3099
- 0,
3100
- container.scrollTop + (targetRect.top - containerRect.top) - CHAT_THREAD_SCROLL_TOP_GAP
3101
- );
3474
+ if (!container)
3475
+ return false;
3476
+ if (!force && !isPinnedRef.current)
3477
+ return false;
3478
+ const nextScrollTop = Math.max(0, container.scrollHeight - container.clientHeight);
3479
+ container.scrollTop = nextScrollTop;
3102
3480
  if (typeof container.scrollTo === "function") {
3103
3481
  container.scrollTo({
3104
3482
  top: nextScrollTop,
3105
3483
  behavior: "auto"
3106
3484
  });
3485
+ }
3486
+ return true;
3487
+ }, []);
3488
+ const markThreadPinned = (0, import_react11.useCallback)(() => {
3489
+ isPinnedRef.current = true;
3490
+ setIsDetached(false);
3491
+ setPendingNewMessageCount(0);
3492
+ }, []);
3493
+ const scrollToBottomAndPin = (0, import_react11.useCallback)(
3494
+ (force = false) => {
3495
+ const didScroll = scrollToBottom(force);
3496
+ if (!didScroll)
3497
+ return;
3498
+ markThreadPinned();
3499
+ },
3500
+ [markThreadPinned, scrollToBottom]
3501
+ );
3502
+ const handleContainerScroll = (0, import_react11.useCallback)(() => {
3503
+ const container = containerRef.current;
3504
+ if (!container)
3107
3505
  return;
3506
+ const nextPinned = isThreadPinnedToBottom(container);
3507
+ isPinnedRef.current = nextPinned;
3508
+ setIsDetached(!nextPinned);
3509
+ if (nextPinned) {
3510
+ setPendingNewMessageCount(0);
3108
3511
  }
3109
- container.scrollTop = nextScrollTop;
3110
3512
  }, []);
3513
+ (0, import_react11.useLayoutEffect)(() => {
3514
+ const nextHistoryMessageId = latestHistoryMessage?.id;
3515
+ if (lastHistoryMessageIdRef.current === nextHistoryMessageId) {
3516
+ return;
3517
+ }
3518
+ lastHistoryMessageIdRef.current = nextHistoryMessageId;
3519
+ if (!latestHistoryMessage) {
3520
+ return;
3521
+ }
3522
+ if (latestHistoryMessage.role === "user") {
3523
+ window.requestAnimationFrame(() => {
3524
+ if (!scrollToBottom(true)) {
3525
+ return;
3526
+ }
3527
+ markThreadPinned();
3528
+ });
3529
+ return;
3530
+ }
3531
+ if (!isPinnedRef.current && latestHistoryMessage.role === "assistant" && latestHistoryMessage.id !== lastStreamingMessageIdRef.current) {
3532
+ window.requestAnimationFrame(() => {
3533
+ setPendingNewMessageCount((current) => current + 1);
3534
+ });
3535
+ }
3536
+ }, [latestHistoryMessage, markThreadPinned, scrollToBottom]);
3537
+ (0, import_react11.useLayoutEffect)(() => {
3538
+ const nextStreamingMessageId = streamingMessage?.id;
3539
+ if (lastStreamingMessageIdRef.current === nextStreamingMessageId) {
3540
+ return;
3541
+ }
3542
+ lastStreamingMessageIdRef.current = nextStreamingMessageId;
3543
+ if (!streamingMessage || streamingMessage.role !== "assistant") {
3544
+ return;
3545
+ }
3546
+ if (!isPinnedRef.current) {
3547
+ window.requestAnimationFrame(() => {
3548
+ setPendingNewMessageCount((current) => current + 1);
3549
+ });
3550
+ }
3551
+ }, [streamingMessage]);
3111
3552
  (0, import_react11.useLayoutEffect)(() => {
3112
3553
  if (reservedSpaceFrameRef.current !== null) {
3113
3554
  window.cancelAnimationFrame(reservedSpaceFrameRef.current);
@@ -3117,6 +3558,7 @@ var ChatThreadView = ({
3117
3558
  reservedSpaceFrameRef.current = window.requestAnimationFrame(() => {
3118
3559
  reservedSpaceFrameRef.current = null;
3119
3560
  setLatestTurnMinHeight((current) => current === 0 ? current : 0);
3561
+ scrollToBottom();
3120
3562
  });
3121
3563
  return () => {
3122
3564
  if (reservedSpaceFrameRef.current !== null) {
@@ -3128,7 +3570,7 @@ var ChatThreadView = ({
3128
3570
  reservedSpaceFrameRef.current = window.requestAnimationFrame(() => {
3129
3571
  reservedSpaceFrameRef.current = null;
3130
3572
  measureLatestTurnMinHeight();
3131
- scrollLatestUserMessageToTop();
3573
+ scrollToBottom();
3132
3574
  });
3133
3575
  return () => {
3134
3576
  if (reservedSpaceFrameRef.current !== null) {
@@ -3136,13 +3578,18 @@ var ChatThreadView = ({
3136
3578
  reservedSpaceFrameRef.current = null;
3137
3579
  }
3138
3580
  };
3139
- }, [latestUserMessageId, measureLatestTurnMinHeight, scrollLatestUserMessageToTop]);
3581
+ }, [latestTurn, latestUserMessageId, error, measureLatestTurnMinHeight, scrollToBottom]);
3140
3582
  (0, import_react11.useLayoutEffect)(() => {
3141
- if (!latestUserMessageId)
3583
+ if (!latestTurn)
3142
3584
  return;
3143
3585
  const handleResize = () => {
3586
+ if (!latestUserMessageId) {
3587
+ setLatestTurnMinHeight((current) => current === 0 ? current : 0);
3588
+ scrollToBottom();
3589
+ return;
3590
+ }
3144
3591
  measureLatestTurnMinHeight();
3145
- scrollLatestUserMessageToTop();
3592
+ scrollToBottom();
3146
3593
  };
3147
3594
  const container = containerRef.current;
3148
3595
  let resizeObserver = null;
@@ -3157,57 +3604,101 @@ var ChatThreadView = ({
3157
3604
  resizeObserver?.disconnect();
3158
3605
  window.removeEventListener("resize", handleResize);
3159
3606
  };
3160
- }, [latestUserMessageId, measureLatestTurnMinHeight, scrollLatestUserMessageToTop]);
3161
- return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(Container, { ref: containerRef, "data-testid": "chat-thread", children: [
3162
- previousTurns.map((turn) => /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(ConversationTurn, { "data-testid": "chat-thread-turn", children: [
3163
- turn.userMessage ? /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(MessageSlot, { children: renderChatMessage({
3164
- message: turn.userMessage,
3165
- mode: activeSessionMode,
3166
- onConfirmationSubmit,
3167
- onQuestionnaireSubmit,
3168
- renderMessageBlock
3169
- }) }) : null,
3170
- turn.responseMessages.map((message) => /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(MessageSlot, { children: renderChatMessage({
3171
- message,
3172
- mode: activeSessionMode,
3173
- onConfirmationSubmit,
3174
- onQuestionnaireSubmit,
3175
- renderMessageBlock
3176
- }) }, message.id))
3177
- ] }, turn.id)),
3178
- latestTurn ? /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(
3179
- ConversationTurn,
3607
+ }, [latestTurn, latestUserMessageId, measureLatestTurnMinHeight, scrollToBottom]);
3608
+ (0, import_react11.useLayoutEffect)(() => {
3609
+ const latestTurnElement = latestTurnRef.current;
3610
+ if (!latestTurnElement || typeof ResizeObserver === "undefined") {
3611
+ return;
3612
+ }
3613
+ const observer = new ResizeObserver(() => {
3614
+ scrollToBottom();
3615
+ });
3616
+ observer.observe(latestTurnElement);
3617
+ return () => {
3618
+ observer.disconnect();
3619
+ };
3620
+ }, [latestTurn, scrollToBottom]);
3621
+ (0, import_react11.useLayoutEffect)(() => {
3622
+ const latestTurnElement = latestTurnRef.current;
3623
+ if (!latestTurnElement || typeof MutationObserver === "undefined") {
3624
+ return;
3625
+ }
3626
+ const observer = new MutationObserver(() => {
3627
+ scrollToBottom();
3628
+ });
3629
+ observer.observe(latestTurnElement, {
3630
+ childList: true,
3631
+ subtree: true,
3632
+ characterData: true
3633
+ });
3634
+ return () => {
3635
+ observer.disconnect();
3636
+ };
3637
+ }, [latestTurn, scrollToBottom]);
3638
+ return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(ThreadViewport, { children: [
3639
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(Container, { ref: containerRef, "data-testid": "chat-thread", onScroll: handleContainerScroll, children: [
3640
+ previousTurns.map((turn) => /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(ConversationTurn, { "data-testid": "chat-thread-turn", children: [
3641
+ turn.userMessage ? /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(MessageSlot, { children: renderChatMessage({
3642
+ message: turn.userMessage,
3643
+ mode: activeSessionMode,
3644
+ onConfirmationSubmit,
3645
+ onQuestionnaireSubmit,
3646
+ renderMessageBlock
3647
+ }) }) : null,
3648
+ turn.responseMessages.map((message) => /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(MessageSlot, { children: renderChatMessage({
3649
+ message,
3650
+ mode: activeSessionMode,
3651
+ onConfirmationSubmit,
3652
+ onQuestionnaireSubmit,
3653
+ renderMessageBlock
3654
+ }) }, message.id))
3655
+ ] }, turn.id)),
3656
+ latestTurn ? /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(
3657
+ ConversationTurn,
3658
+ {
3659
+ ref: latestTurnRef,
3660
+ "data-testid": "chat-thread-latest-turn",
3661
+ style: latestTurnMinHeight > 0 ? { minHeight: `${latestTurnMinHeight}px` } : void 0,
3662
+ children: [
3663
+ latestTurn.userMessage ? /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
3664
+ MessageSlot,
3665
+ {
3666
+ "data-testid": "chat-latest-user-anchor",
3667
+ style: { scrollMarginTop: `${CHAT_THREAD_SCROLL_TOP_GAP}px` },
3668
+ children: renderChatMessage({
3669
+ message: latestTurn.userMessage,
3670
+ mode: activeSessionMode,
3671
+ onConfirmationSubmit,
3672
+ onQuestionnaireSubmit,
3673
+ renderMessageBlock
3674
+ })
3675
+ }
3676
+ ) : null,
3677
+ latestTurn.responseMessages.map((message) => /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(MessageSlot, { children: renderChatMessage({
3678
+ message,
3679
+ mode: activeSessionMode,
3680
+ onConfirmationSubmit,
3681
+ onQuestionnaireSubmit,
3682
+ renderMessageBlock
3683
+ }) }, message.id)),
3684
+ error ? renderErrorState({ error, onRetry, retryButtonLabel }) : null
3685
+ ]
3686
+ }
3687
+ ) : null,
3688
+ !latestTurn && error ? renderErrorState({ error, onRetry, retryButtonLabel }) : null
3689
+ ] }),
3690
+ isDetached ? /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(ScrollToLatestOverlay, { children: /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(
3691
+ ScrollToLatestButton,
3180
3692
  {
3181
- "data-testid": "chat-thread-latest-turn",
3182
- style: latestTurnMinHeight > 0 ? { minHeight: `${latestTurnMinHeight}px` } : void 0,
3693
+ type: "button",
3694
+ "data-testid": "chat-thread-scroll-to-latest",
3695
+ onClick: () => scrollToBottomAndPin(true),
3183
3696
  children: [
3184
- latestTurn.userMessage ? /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
3185
- MessageSlot,
3186
- {
3187
- ref: latestUserMessageRef,
3188
- "data-testid": "chat-latest-user-anchor",
3189
- style: { scrollMarginTop: `${CHAT_THREAD_SCROLL_TOP_GAP}px` },
3190
- children: renderChatMessage({
3191
- message: latestTurn.userMessage,
3192
- mode: activeSessionMode,
3193
- onConfirmationSubmit,
3194
- onQuestionnaireSubmit,
3195
- renderMessageBlock
3196
- })
3197
- }
3198
- ) : null,
3199
- latestTurn.responseMessages.map((message) => /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(MessageSlot, { children: renderChatMessage({
3200
- message,
3201
- mode: activeSessionMode,
3202
- onConfirmationSubmit,
3203
- onQuestionnaireSubmit,
3204
- renderMessageBlock
3205
- }) }, message.id)),
3206
- error ? renderErrorState({ error, onRetry, retryButtonLabel }) : null
3697
+ scrollToLatestLabel,
3698
+ pendingNewMessageCount > 0 ? /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(ScrollToLatestBadge, { "data-testid": "chat-thread-scroll-to-latest-count", children: pendingNewMessageCount }) : null
3207
3699
  ]
3208
3700
  }
3209
- ) : null,
3210
- !latestTurn && error ? renderErrorState({ error, onRetry, retryButtonLabel }) : null
3701
+ ) }) : null
3211
3702
  ] });
3212
3703
  };
3213
3704
  var EMPTY_MESSAGES = [];
@@ -3295,13 +3786,21 @@ var ChatThread = () => {
3295
3786
  streamingMessage,
3296
3787
  error,
3297
3788
  retryButtonLabel: labels.retryButton,
3789
+ scrollToLatestLabel: labels.scrollToLatest,
3298
3790
  onRetry: handleRetry,
3299
3791
  onConfirmationSubmit: handleConfirmation,
3300
3792
  onQuestionnaireSubmit: handleQuestionnaireSubmit,
3301
3793
  renderMessageBlock
3302
- }
3794
+ },
3795
+ activeSessionId ?? "chat-thread-empty"
3303
3796
  );
3304
3797
  };
3798
+ var ThreadViewport = import_styled9.default.div`
3799
+ position: relative;
3800
+ display: flex;
3801
+ flex: 1;
3802
+ min-height: 0;
3803
+ `;
3305
3804
  var Container = import_styled9.default.div`
3306
3805
  display: flex;
3307
3806
  flex: 1;
@@ -3309,8 +3808,7 @@ var Container = import_styled9.default.div`
3309
3808
  gap: 18px;
3310
3809
  min-height: 0;
3311
3810
  overflow: auto;
3312
- padding: 24px;
3313
- margin-bottom: 24px;
3811
+ padding: 24px 24px 88px;
3314
3812
  overscroll-behavior: contain;
3315
3813
 
3316
3814
  &::-webkit-scrollbar {
@@ -3362,6 +3860,48 @@ var RetryButton = import_styled9.default.button`
3362
3860
  background: rgba(255, 255, 255, 0.08);
3363
3861
  }
3364
3862
  `;
3863
+ var ScrollToLatestOverlay = import_styled9.default.div`
3864
+ position: absolute;
3865
+ right: 24px;
3866
+ bottom: 24px;
3867
+ left: 24px;
3868
+ display: flex;
3869
+ justify-content: center;
3870
+ pointer-events: none;
3871
+ `;
3872
+ var ScrollToLatestButton = import_styled9.default.button`
3873
+ display: inline-flex;
3874
+ align-items: center;
3875
+ gap: 8px;
3876
+ border: 1px solid rgba(255, 255, 255, 0.14);
3877
+ border-radius: 999px;
3878
+ background: rgba(17, 18, 21, 0.92);
3879
+ color: rgba(255, 255, 255, 0.9);
3880
+ font-size: 12px;
3881
+ line-height: 1;
3882
+ padding: 10px 14px;
3883
+ box-shadow: 0 10px 30px rgba(0, 0, 0, 0.28);
3884
+ cursor: pointer;
3885
+ z-index: 1;
3886
+ pointer-events: auto;
3887
+
3888
+ &:hover {
3889
+ background: rgba(28, 30, 36, 0.96);
3890
+ }
3891
+ `;
3892
+ var ScrollToLatestBadge = import_styled9.default.span`
3893
+ display: inline-flex;
3894
+ min-width: 18px;
3895
+ height: 18px;
3896
+ align-items: center;
3897
+ justify-content: center;
3898
+ padding: 0 6px;
3899
+ border-radius: 999px;
3900
+ background: rgba(109, 170, 255, 0.2);
3901
+ color: #9ac0ff;
3902
+ font-size: 11px;
3903
+ font-weight: 600;
3904
+ `;
3365
3905
 
3366
3906
  // src/components/chat-composer/index.tsx
3367
3907
  var import_react15 = require("react");
@@ -4087,7 +4627,7 @@ var CloseGlyph = import_styled10.default.span`
4087
4627
 
4088
4628
  // src/components/chat-composer/components/chat-model-control.tsx
4089
4629
  var import_styled11 = __toESM(require("@emotion/styled"));
4090
- var import_compass_ui = require("@xinghunm/compass-ui");
4630
+ var import_compass_ui2 = require("@xinghunm/compass-ui");
4091
4631
  var import_jsx_runtime12 = require("@emotion/react/jsx-runtime");
4092
4632
  var ChatModelControl = ({
4093
4633
  selectedModel,
@@ -4188,7 +4728,7 @@ var ModelReloadButton = import_styled11.default.button`
4188
4728
  var ReloadIcon = import_styled11.default.svg`
4189
4729
  flex-shrink: 0;
4190
4730
  `;
4191
- var ModelSelect = (0, import_styled11.default)(import_compass_ui.Select)`
4731
+ var ModelSelect = (0, import_styled11.default)(import_compass_ui2.Select)`
4192
4732
  && {
4193
4733
  width: auto;
4194
4734
  min-width: 0;
@@ -4209,7 +4749,7 @@ var ModelSelect = (0, import_styled11.default)(import_compass_ui.Select)`
4209
4749
 
4210
4750
  // src/components/chat-composer/components/chat-mode-control.tsx
4211
4751
  var import_styled12 = __toESM(require("@emotion/styled"));
4212
- var import_compass_ui2 = require("@xinghunm/compass-ui");
4752
+ var import_compass_ui3 = require("@xinghunm/compass-ui");
4213
4753
  var import_jsx_runtime13 = require("@emotion/react/jsx-runtime");
4214
4754
  var ChatModeControl = ({
4215
4755
  value,
@@ -4232,7 +4772,7 @@ var ChatModeControl = ({
4232
4772
  }
4233
4773
  );
4234
4774
  };
4235
- var ModeSelect = (0, import_styled12.default)(import_compass_ui2.Select)`
4775
+ var ModeSelect = (0, import_styled12.default)(import_compass_ui3.Select)`
4236
4776
  && {
4237
4777
  flex: 0 1 auto;
4238
4778
  width: auto;
@@ -4254,7 +4794,7 @@ var ModeSelect = (0, import_styled12.default)(import_compass_ui2.Select)`
4254
4794
 
4255
4795
  // src/components/chat-composer/components/chat-send-actions.tsx
4256
4796
  var import_styled13 = __toESM(require("@emotion/styled"));
4257
- var import_compass_ui3 = require("@xinghunm/compass-ui");
4797
+ var import_compass_ui4 = require("@xinghunm/compass-ui");
4258
4798
  var import_jsx_runtime14 = require("@emotion/react/jsx-runtime");
4259
4799
  var ArrowUpIcon = () => /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
4260
4800
  "svg",
@@ -4308,7 +4848,7 @@ var ChatSendActions = ({
4308
4848
  onClick: () => void onSend()
4309
4849
  }
4310
4850
  ) });
4311
- var PrimaryButton = (0, import_styled13.default)(import_compass_ui3.Button)`
4851
+ var PrimaryButton = (0, import_styled13.default)(import_compass_ui4.Button)`
4312
4852
  && {
4313
4853
  min-width: 24px;
4314
4854
  width: 24px;
@@ -4334,7 +4874,7 @@ var PrimaryButton = (0, import_styled13.default)(import_compass_ui3.Button)`
4334
4874
  }
4335
4875
  }
4336
4876
  `;
4337
- var StopButton = (0, import_styled13.default)(import_compass_ui3.Button)`
4877
+ var StopButton = (0, import_styled13.default)(import_compass_ui4.Button)`
4338
4878
  && {
4339
4879
  min-width: 24px;
4340
4880
  width: 24px;
@@ -4907,7 +5447,7 @@ var ChatConversationList = () => {
4907
5447
  };
4908
5448
  return /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(Container3, { children: [
4909
5449
  /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(Toolbar, { children: [
4910
- /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(Title4, { children: "Sessions" }),
5450
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(Title3, { children: "Sessions" }),
4911
5451
  /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(CreateButton, { type: "button", "data-testid": "chat-create-session", onClick: handleCreateSession, children: labels.newChat })
4912
5452
  ] }),
4913
5453
  /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(List2, { "data-testid": "chat-session-list", children: sessions.map((session) => /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
@@ -4936,7 +5476,7 @@ var Toolbar = import_styled16.default.div`
4936
5476
  flex-direction: column;
4937
5477
  gap: 12px;
4938
5478
  `;
4939
- var Title4 = import_styled16.default.h2`
5479
+ var Title3 = import_styled16.default.h2`
4940
5480
  margin: 0;
4941
5481
  font-size: 14px;
4942
5482
  color: var(--text-secondary);
@@ -4961,7 +5501,7 @@ var List2 = import_styled16.default.div`
4961
5501
  // src/components/ai-chat/index.tsx
4962
5502
  var import_jsx_runtime18 = require("@emotion/react/jsx-runtime");
4963
5503
  var AiChat = ({ showConversationList = false, ...providerProps }) => /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
4964
- import_compass_ui4.ConfigProvider,
5504
+ import_compass_ui5.ConfigProvider,
4965
5505
  {
4966
5506
  theme: {
4967
5507
  token: {