@hex-core/components 1.9.0 → 1.10.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.
Files changed (146) hide show
  1. package/dist/_tsup-dts-rollup.d.ts +575 -18
  2. package/dist/accordion.js.map +1 -1
  3. package/dist/alert-dialog.js.map +1 -1
  4. package/dist/alert.js.map +1 -1
  5. package/dist/arc.js.map +1 -1
  6. package/dist/attachment.js.map +1 -1
  7. package/dist/audio-player.js.map +1 -1
  8. package/dist/audio-waveform.js.map +1 -1
  9. package/dist/auth-forgot-password.js.map +1 -1
  10. package/dist/auth-reset-password.js.map +1 -1
  11. package/dist/auth-sign-in-split.js.map +1 -1
  12. package/dist/auth-sign-up-card.js.map +1 -1
  13. package/dist/auth-verify-email.js.map +1 -1
  14. package/dist/auth-verify-otp.js.map +1 -1
  15. package/dist/avatar.js.map +1 -1
  16. package/dist/badge.js.map +1 -1
  17. package/dist/branch.d.ts +2 -0
  18. package/dist/branch.js +136 -0
  19. package/dist/branch.js.map +1 -0
  20. package/dist/breadcrumb.js.map +1 -1
  21. package/dist/button.js.map +1 -1
  22. package/dist/calendar.js.map +1 -1
  23. package/dist/canvas.js.map +1 -1
  24. package/dist/card.js.map +1 -1
  25. package/dist/chain-of-thought.d.ts +3 -0
  26. package/dist/chain-of-thought.js +119 -0
  27. package/dist/chain-of-thought.js.map +1 -0
  28. package/dist/checkbox.js.map +1 -1
  29. package/dist/chord.js.map +1 -1
  30. package/dist/citation.js.map +1 -1
  31. package/dist/cloze.js.map +1 -1
  32. package/dist/cluster.js.map +1 -1
  33. package/dist/code-block-copy.js.map +1 -1
  34. package/dist/code-block.js.map +1 -1
  35. package/dist/color-picker.js.map +1 -1
  36. package/dist/combobox.js.map +1 -1
  37. package/dist/command.js.map +1 -1
  38. package/dist/compare-table.js.map +1 -1
  39. package/dist/composer.js.map +1 -1
  40. package/dist/container.js.map +1 -1
  41. package/dist/context-menu.js.map +1 -1
  42. package/dist/conversation.d.ts +3 -0
  43. package/dist/conversation.js +358 -0
  44. package/dist/conversation.js.map +1 -0
  45. package/dist/data-table.js.map +1 -1
  46. package/dist/date-picker.js.map +1 -1
  47. package/dist/deck.js.map +1 -1
  48. package/dist/dendrogram.js.map +1 -1
  49. package/dist/diagram.js.map +1 -1
  50. package/dist/dialog.js.map +1 -1
  51. package/dist/drawer.js.map +1 -1
  52. package/dist/dropdown-menu.js.map +1 -1
  53. package/dist/dropzone.js.map +1 -1
  54. package/dist/empty.js.map +1 -1
  55. package/dist/error-state.js.map +1 -1
  56. package/dist/file-tree.js.map +1 -1
  57. package/dist/flashcard.js.map +1 -1
  58. package/dist/flowchart.js.map +1 -1
  59. package/dist/form.js.map +1 -1
  60. package/dist/funnel.js.map +1 -1
  61. package/dist/gantt.js.map +1 -1
  62. package/dist/grid.js.map +1 -1
  63. package/dist/hover-card.js.map +1 -1
  64. package/dist/image-occlusion.js.map +1 -1
  65. package/dist/index.d.ts +21 -0
  66. package/dist/index.js +1011 -13
  67. package/dist/index.js.map +1 -1
  68. package/dist/inline-citation.d.ts +2 -0
  69. package/dist/inline-citation.js +108 -0
  70. package/dist/inline-citation.js.map +1 -0
  71. package/dist/input-otp.js.map +1 -1
  72. package/dist/input.js.map +1 -1
  73. package/dist/label.js.map +1 -1
  74. package/dist/loading-indicator.js.map +1 -1
  75. package/dist/loading.js.map +1 -1
  76. package/dist/markdown.d.ts +1 -0
  77. package/dist/markdown.js +784 -4
  78. package/dist/markdown.js.map +1 -1
  79. package/dist/matrix.js.map +1 -1
  80. package/dist/menubar.js.map +1 -1
  81. package/dist/message-actions.js.map +1 -1
  82. package/dist/message-list.js.map +1 -1
  83. package/dist/message.js.map +1 -1
  84. package/dist/mind-map.js.map +1 -1
  85. package/dist/multi-combobox.js.map +1 -1
  86. package/dist/navigation-menu.js.map +1 -1
  87. package/dist/org-chart.js.map +1 -1
  88. package/dist/pagination.js.map +1 -1
  89. package/dist/plan.d.ts +3 -0
  90. package/dist/plan.js +183 -0
  91. package/dist/plan.js.map +1 -0
  92. package/dist/popover.js.map +1 -1
  93. package/dist/progress.js.map +1 -1
  94. package/dist/pyramid.js.map +1 -1
  95. package/dist/quiz.js.map +1 -1
  96. package/dist/radio-group.js.map +1 -1
  97. package/dist/reasoning.js.map +1 -1
  98. package/dist/resizable.js.map +1 -1
  99. package/dist/sankey.js.map +1 -1
  100. package/dist/schemas.d.ts +8 -0
  101. package/dist/schemas.js +774 -17
  102. package/dist/schemas.js.map +1 -1
  103. package/dist/scroll-area.js.map +1 -1
  104. package/dist/select.js.map +1 -1
  105. package/dist/separator.js.map +1 -1
  106. package/dist/sequence.js.map +1 -1
  107. package/dist/sheet.js.map +1 -1
  108. package/dist/shimmer.d.ts +2 -0
  109. package/dist/shimmer.js +39 -0
  110. package/dist/shimmer.js.map +1 -0
  111. package/dist/sidebar.js.map +1 -1
  112. package/dist/skeleton.js.map +1 -1
  113. package/dist/slider.js.map +1 -1
  114. package/dist/sources.d.ts +3 -0
  115. package/dist/sources.js +164 -0
  116. package/dist/sources.js.map +1 -0
  117. package/dist/spaced-repetition.js.map +1 -1
  118. package/dist/spacer.js.map +1 -1
  119. package/dist/speech-recognition.js.map +1 -1
  120. package/dist/stack.js.map +1 -1
  121. package/dist/stepper.js.map +1 -1
  122. package/dist/suggestion.js.map +1 -1
  123. package/dist/sunburst.js.map +1 -1
  124. package/dist/switch.js.map +1 -1
  125. package/dist/table.js.map +1 -1
  126. package/dist/tabs.js.map +1 -1
  127. package/dist/tag.js.map +1 -1
  128. package/dist/task.d.ts +3 -0
  129. package/dist/task.js +189 -0
  130. package/dist/task.js.map +1 -0
  131. package/dist/terminal.js +11 -0
  132. package/dist/terminal.js.map +1 -1
  133. package/dist/textarea.js.map +1 -1
  134. package/dist/time-axis.js.map +1 -1
  135. package/dist/time-picker.js.map +1 -1
  136. package/dist/timeline.js.map +1 -1
  137. package/dist/toggle-group.js.map +1 -1
  138. package/dist/toggle.js.map +1 -1
  139. package/dist/tool-call.js +5 -6
  140. package/dist/tool-call.js.map +1 -1
  141. package/dist/toolbar.js.map +1 -1
  142. package/dist/tooltip.js.map +1 -1
  143. package/dist/tree-map.js.map +1 -1
  144. package/dist/tree.js.map +1 -1
  145. package/dist/venn.js.map +1 -1
  146. package/package.json +8 -3
package/dist/index.js CHANGED
@@ -42,7 +42,11 @@ import { Command as Command$1 } from 'cmdk';
42
42
  import * as ToolbarPrimitive from '@radix-ui/react-toolbar';
43
43
  import { Drawer as Drawer$1 } from 'vaul';
44
44
  import { Panel, Group, Separator as Separator$1 } from 'react-resizable-panels';
45
- import { Streamdown } from 'streamdown';
45
+ import ReactMarkdown from 'react-markdown';
46
+ import rehypeRaw from 'rehype-raw';
47
+ import rehypeSanitize, { defaultSchema } from 'rehype-sanitize';
48
+ import remarkGfm from 'remark-gfm';
49
+ import { visit } from 'unist-util-visit';
46
50
  import { codeToHtml } from 'shiki';
47
51
  import { CodeBlockCopy } from './code-block-copy.js';
48
52
 
@@ -50,6 +54,17 @@ import { CodeBlockCopy } from './code-block-copy.js';
50
54
  function cn(...inputs) {
51
55
  return twMerge(clsx(inputs));
52
56
  }
57
+ var SAFE_URL_SCHEMES = ["http:", "https:", "mailto:"];
58
+ function safeUrl(raw) {
59
+ if (raw === void 0 || raw === "") return void 0;
60
+ let parsed;
61
+ try {
62
+ parsed = new URL(raw);
63
+ } catch {
64
+ return raw.includes(":") ? void 0 : raw;
65
+ }
66
+ return SAFE_URL_SCHEMES.some((scheme) => scheme === parsed.protocol) ? raw : void 0;
67
+ }
53
68
  var buttonVariants = cva(
54
69
  [
55
70
  "inline-flex items-center justify-center gap-[var(--gap-sm,0.5rem)] whitespace-nowrap rounded-md text-sm font-medium",
@@ -836,7 +851,7 @@ var tagVariants = cva(
836
851
  );
837
852
  function extractStringLabel(children) {
838
853
  const parts = [];
839
- const visit = (node) => {
854
+ const visit2 = (node) => {
840
855
  if (node === null || node === void 0 || typeof node === "boolean") return;
841
856
  if (typeof node === "string") {
842
857
  parts.push(node);
@@ -847,15 +862,15 @@ function extractStringLabel(children) {
847
862
  return;
848
863
  }
849
864
  if (Array.isArray(node)) {
850
- for (const item of node) visit(item);
865
+ for (const item of node) visit2(item);
851
866
  return;
852
867
  }
853
868
  if (React44.isValidElement(node)) {
854
869
  const props = node.props;
855
- visit(props.children);
870
+ visit2(props.children);
856
871
  }
857
872
  };
858
- visit(children);
873
+ visit2(children);
859
874
  const joined = parts.join(" ").replace(/\s+/g, " ").trim();
860
875
  return joined.length > 0 ? joined : null;
861
876
  }
@@ -5220,6 +5235,17 @@ function Terminal({
5220
5235
  className: cn(
5221
5236
  "overflow-hidden rounded-md border p-2",
5222
5237
  "font-mono text-sm leading-tight",
5238
+ // xterm.js mounts hidden helper elements (`<textarea>` for
5239
+ // keyboard / IME input, `.xterm-char-measure-element` for
5240
+ // sizing). Both inherit the page's foreground token, which
5241
+ // axe flags as sub-AA against the locked-dark surface even
5242
+ // though they're visually offscreen. Force their visible
5243
+ // color transparent so axe stops complaining; AT can still
5244
+ // read the textarea (xterm's intended IME path), but the
5245
+ // rendered output appears in xterm's canvas — not the
5246
+ // textarea — so AT won't see meaningful content there.
5247
+ "[&_textarea]:!text-transparent [&_textarea]:!caret-transparent",
5248
+ "[&_.xterm-char-measure-element]:!text-transparent",
5223
5249
  className
5224
5250
  )
5225
5251
  }
@@ -5612,12 +5638,11 @@ var STATE_LABEL = {
5612
5638
  };
5613
5639
  var STATE_CLASSES = {
5614
5640
  pending: "bg-muted text-muted-foreground",
5615
- // Solid primary bg + primary-foreground text in dark mode the
5616
- // previously tinted `bg-primary/15` made the badge fg/bg too close in
5617
- // hue at 10px to clear WCAG AA (was 4.41:1, fails the 4.5 floor).
5618
- // Light mode keeps the soft tint where contrast holds; dark mode uses
5619
- // the solid surface for guaranteed ≥7:1 contrast.
5620
- running: "bg-primary/15 text-primary dark:bg-primary dark:text-primary-foreground animate-pulse",
5641
+ // `text-foreground` (12:1) survives axe's mid-pulse capture; the
5642
+ // previous `text-primary` (`#7081a8` on dark `--muted`, 4.28:1) was
5643
+ // intermittently flagged below AA 4.5:1 at the 10px badge size when
5644
+ // `animate-pulse` caught the scan during a low-opacity frame.
5645
+ running: "bg-muted text-foreground font-medium animate-pulse",
5621
5646
  result: "bg-accent/30 text-accent-foreground",
5622
5647
  error: "bg-destructive/15 text-destructive"
5623
5648
  };
@@ -5879,9 +5904,368 @@ function DocGlyph() {
5879
5904
  }
5880
5905
  );
5881
5906
  }
5907
+ function InlineCitation({
5908
+ index,
5909
+ title,
5910
+ url: rawUrl,
5911
+ excerpt,
5912
+ openDelay = 200,
5913
+ className
5914
+ }) {
5915
+ const url = safeUrl(rawUrl);
5916
+ const triggerClasses = cn(
5917
+ "inline-flex select-none items-center justify-center rounded-sm bg-primary/10 px-1 py-0.5 text-[0.7em] font-mono font-semibold text-primary leading-none",
5918
+ "transition-all duration-[var(--duration-normal,200ms)] ease-out",
5919
+ "hover:bg-primary/15",
5920
+ "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-1",
5921
+ className
5922
+ );
5923
+ const trigger = url ? /* @__PURE__ */ jsxs(
5924
+ "a",
5925
+ {
5926
+ href: url,
5927
+ target: "_blank",
5928
+ rel: "noreferrer noopener external",
5929
+ className: triggerClasses,
5930
+ "aria-label": `Source ${index}: ${title}`,
5931
+ children: [
5932
+ "[",
5933
+ index,
5934
+ "]"
5935
+ ]
5936
+ }
5937
+ ) : (
5938
+ // No URL → still focusable so keyboard users can open the popover.
5939
+ // Real <button type="button"> over a styled span so the trigger
5940
+ // honors space/enter activation natively.
5941
+ /* @__PURE__ */ jsxs(
5942
+ "button",
5943
+ {
5944
+ type: "button",
5945
+ className: triggerClasses,
5946
+ "aria-label": `Source ${index}: ${title}`,
5947
+ children: [
5948
+ "[",
5949
+ index,
5950
+ "]"
5951
+ ]
5952
+ }
5953
+ )
5954
+ );
5955
+ return /* @__PURE__ */ jsxs(HoverCardPrimitive.Root, { openDelay, children: [
5956
+ /* @__PURE__ */ jsx(HoverCardPrimitive.Trigger, { asChild: true, children: /* @__PURE__ */ jsx("sup", { className: "inline-block leading-none", children: trigger }) }),
5957
+ /* @__PURE__ */ jsx(HoverCardPrimitive.Portal, { children: /* @__PURE__ */ jsx(
5958
+ HoverCardPrimitive.Content,
5959
+ {
5960
+ side: "top",
5961
+ align: "center",
5962
+ sideOffset: 4,
5963
+ className: cn(
5964
+ "z-50 max-w-xs rounded-md border border-border bg-popover p-3 text-popover-foreground shadow-md",
5965
+ "data-[state=open]:animate-in data-[state=closed]:animate-out",
5966
+ "data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0",
5967
+ "data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95"
5968
+ ),
5969
+ children: /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-1", children: [
5970
+ /* @__PURE__ */ jsxs("span", { className: "font-mono text-[10px] text-muted-foreground", children: [
5971
+ "[",
5972
+ index,
5973
+ "]"
5974
+ ] }),
5975
+ /* @__PURE__ */ jsx("span", { className: "text-sm font-medium leading-snug text-foreground", children: title }),
5976
+ excerpt ? /* @__PURE__ */ jsx("span", { className: "text-xs leading-relaxed text-muted-foreground", children: excerpt }) : null,
5977
+ url ? /* @__PURE__ */ jsx("span", { className: "truncate text-xs text-primary underline-offset-2 hover:underline", children: inferDisplayUrl(url) }) : null
5978
+ ] })
5979
+ }
5980
+ ) })
5981
+ ] });
5982
+ }
5983
+ function inferDisplayUrl(href) {
5984
+ try {
5985
+ const url = new URL(href);
5986
+ return url.hostname.replace(/^www\./, "") + url.pathname;
5987
+ } catch {
5988
+ return href;
5989
+ }
5990
+ }
5991
+ function Sources({ sources, defaultOpen = true, className }) {
5992
+ if (sources.length === 0) return null;
5993
+ const count = sources.length;
5994
+ const headerLabel = count === 1 ? "1 source" : `${count} sources`;
5995
+ return /* @__PURE__ */ jsxs(
5996
+ CollapsiblePrimitive.Root,
5997
+ {
5998
+ defaultOpen,
5999
+ className: cn(
6000
+ "overflow-hidden rounded-md border border-border bg-card text-card-foreground",
6001
+ className
6002
+ ),
6003
+ children: [
6004
+ /* @__PURE__ */ jsxs(
6005
+ CollapsiblePrimitive.Trigger,
6006
+ {
6007
+ className: cn(
6008
+ "group flex w-full items-center gap-2 px-3 py-1.5 text-left text-xs text-muted-foreground",
6009
+ "transition-all duration-[var(--duration-normal,200ms)] ease-out",
6010
+ "hover:text-foreground",
6011
+ "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2"
6012
+ ),
6013
+ children: [
6014
+ /* @__PURE__ */ jsx(DocStackGlyph, {}),
6015
+ /* @__PURE__ */ jsx("span", { className: "font-medium", children: headerLabel }),
6016
+ /* @__PURE__ */ jsx(Chevron4, {})
6017
+ ]
6018
+ }
6019
+ ),
6020
+ /* @__PURE__ */ jsx(CollapsiblePrimitive.Content, { className: "overflow-hidden border-t border-foreground/[0.06]", children: /* @__PURE__ */ jsx("div", { className: "flex flex-wrap items-center gap-1.5 p-2", children: sources.map((s, i) => /* @__PURE__ */ jsx(
6021
+ Citation,
6022
+ {
6023
+ title: s.title,
6024
+ url: safeUrl(s.url),
6025
+ page: s.page,
6026
+ index: s.index ?? i + 1
6027
+ },
6028
+ `${s.url ?? s.title}-${i}`
6029
+ )) }) })
6030
+ ]
6031
+ }
6032
+ );
6033
+ }
6034
+ function DocStackGlyph() {
6035
+ return /* @__PURE__ */ jsxs(
6036
+ "svg",
6037
+ {
6038
+ "aria-hidden": true,
6039
+ viewBox: "0 0 16 16",
6040
+ width: "12",
6041
+ height: "12",
6042
+ fill: "none",
6043
+ stroke: "currentColor",
6044
+ strokeWidth: "1.5",
6045
+ strokeLinecap: "round",
6046
+ strokeLinejoin: "round",
6047
+ className: "shrink-0",
6048
+ children: [
6049
+ /* @__PURE__ */ jsx("path", { d: "M5 3h7l1.5 1.5V13H5V3z" }),
6050
+ /* @__PURE__ */ jsx("path", { d: "M3 5v8.5L4.5 15H11" })
6051
+ ]
6052
+ }
6053
+ );
6054
+ }
6055
+ function Chevron4() {
6056
+ return /* @__PURE__ */ jsx(
6057
+ "svg",
6058
+ {
6059
+ "aria-hidden": true,
6060
+ viewBox: "0 0 16 16",
6061
+ width: "12",
6062
+ height: "12",
6063
+ fill: "none",
6064
+ stroke: "currentColor",
6065
+ strokeWidth: "1.5",
6066
+ strokeLinecap: "round",
6067
+ strokeLinejoin: "round",
6068
+ className: "ml-auto shrink-0 transition-transform duration-200 group-data-[state=open]:rotate-180",
6069
+ children: /* @__PURE__ */ jsx("path", { d: "M4 6l4 4 4-4" })
6070
+ }
6071
+ );
6072
+ }
6073
+
6074
+ // src/ai/markdown/close-unterminated.ts
6075
+ function closeUnterminated(input) {
6076
+ let working = input;
6077
+ const suffixes = [];
6078
+ if (hasUnclosedFence(working)) {
6079
+ suffixes.push("\n```\n");
6080
+ working = maskOpenFence(working);
6081
+ }
6082
+ const masked = maskEscapes(maskClosedFences(working));
6083
+ if (/<!--(?![\s\S]*-->)/.test(working)) {
6084
+ suffixes.push("-->");
6085
+ } else if (/<[a-zA-Z][^<>]*$/.test(working)) {
6086
+ suffixes.push(">");
6087
+ }
6088
+ if (/\[[^[\]]*\]\([^()]*$/.test(working)) {
6089
+ suffixes.push(")");
6090
+ } else if (/\[[^[\]]*$/.test(working)) {
6091
+ suffixes.push("]");
6092
+ }
6093
+ let backtickOdd = 0;
6094
+ for (const line of masked.split("\n")) {
6095
+ const count = (line.match(/`/g) ?? []).length;
6096
+ if (count % 2 === 1) backtickOdd++;
6097
+ }
6098
+ if (backtickOdd % 2 === 1) {
6099
+ suffixes.push("`");
6100
+ }
6101
+ const strikeMarkers = countOutsideMaskedFences(masked, /~~/g);
6102
+ if (strikeMarkers % 2 === 1) {
6103
+ suffixes.push("~~");
6104
+ }
6105
+ const { boldOdd, italicAsteriskOdd } = countBoldItalic(masked);
6106
+ if (boldOdd) suffixes.push("**");
6107
+ if (italicAsteriskOdd) suffixes.push("*");
6108
+ if (countUnderscoreItalic(masked) % 2 === 1) suffixes.push("_");
6109
+ if (suffixes.length === 0) return input;
6110
+ return input + suffixes.join("");
6111
+ }
6112
+ function hasUnclosedFence(input) {
6113
+ const fenceRe = /^[ \t]*```/gm;
6114
+ const matches = input.match(fenceRe);
6115
+ return matches !== null && matches.length % 2 === 1;
6116
+ }
6117
+ function maskOpenFence(input) {
6118
+ const fenceRe = /^[ \t]*```/gm;
6119
+ const matches = [];
6120
+ let m;
6121
+ while ((m = fenceRe.exec(input)) !== null) {
6122
+ matches.push(m);
6123
+ }
6124
+ if (matches.length % 2 !== 1) return input;
6125
+ const lastOpener = matches[matches.length - 1];
6126
+ if (!lastOpener) return input;
6127
+ const start = lastOpener.index;
6128
+ return input.slice(0, start) + input.slice(start).replace(/[^\n]/g, " ");
6129
+ }
6130
+ function maskClosedFences(input) {
6131
+ const fenceRe = /^[ \t]*```/gm;
6132
+ const indices = [];
6133
+ let m;
6134
+ while ((m = fenceRe.exec(input)) !== null) {
6135
+ indices.push(m.index);
6136
+ }
6137
+ let out = input;
6138
+ const pairCount = Math.floor(indices.length / 2);
6139
+ for (let i = 0; i < pairCount; i++) {
6140
+ const openIdx = indices[i * 2];
6141
+ const closeIdx = indices[i * 2 + 1];
6142
+ if (openIdx === void 0 || closeIdx === void 0) continue;
6143
+ const closeEnd = out.indexOf("\n", closeIdx);
6144
+ const regionEnd = closeEnd < 0 ? out.length : closeEnd;
6145
+ const before = out.slice(0, openIdx);
6146
+ const region = out.slice(openIdx, regionEnd).replace(/[^\n]/g, " ");
6147
+ const after = out.slice(regionEnd);
6148
+ out = before + region + after;
6149
+ }
6150
+ return out;
6151
+ }
6152
+ function countOutsideMaskedFences(masked, re) {
6153
+ const matches = masked.match(re);
6154
+ return matches?.length ?? 0;
6155
+ }
6156
+ var ESCAPABLE = "\\`*_~[](){}<>#+-.!|";
6157
+ function maskEscapes(input) {
6158
+ let out = "";
6159
+ let i = 0;
6160
+ while (i < input.length) {
6161
+ if (input[i] === "\\" && i + 1 < input.length && ESCAPABLE.includes(input[i + 1] ?? "")) {
6162
+ out += " ";
6163
+ i += 2;
6164
+ continue;
6165
+ }
6166
+ out += input[i];
6167
+ i++;
6168
+ }
6169
+ return out;
6170
+ }
6171
+ function countBoldItalic(masked) {
6172
+ let bold = 0;
6173
+ let italic = 0;
6174
+ let i = 0;
6175
+ while (i < masked.length) {
6176
+ const ch = masked[i];
6177
+ if (ch !== "*") {
6178
+ i++;
6179
+ continue;
6180
+ }
6181
+ let run = 0;
6182
+ while (i + run < masked.length && masked[i + run] === "*") run++;
6183
+ bold += Math.floor(run / 2);
6184
+ italic += run % 2;
6185
+ i += run;
6186
+ }
6187
+ return { boldOdd: bold % 2 === 1, italicAsteriskOdd: italic % 2 === 1 };
6188
+ }
6189
+ function countUnderscoreItalic(masked) {
6190
+ let count = 0;
6191
+ for (let i = 0; i < masked.length; i++) {
6192
+ if (masked[i] !== "_") continue;
6193
+ const prev = i === 0 ? " " : masked[i - 1];
6194
+ const next = i === masked.length - 1 ? " " : masked[i + 1];
6195
+ const prevWs = prev === void 0 || /[\s]/.test(prev);
6196
+ const nextWs = next === void 0 || /[\s]/.test(next);
6197
+ if (prevWs || nextWs) count++;
6198
+ }
6199
+ return count;
6200
+ }
6201
+ var SUPPORTED = /* @__PURE__ */ new Set(["think"]);
6202
+ function remarkAdmonitions() {
6203
+ return (tree) => {
6204
+ visit(tree, "blockquote", (node) => {
6205
+ const marker = extractMarker(node);
6206
+ if (!marker || !SUPPORTED.has(marker.type)) return;
6207
+ stripMarkerText(node, marker.length);
6208
+ node.data = node.data ?? {};
6209
+ node.data.hProperties = {
6210
+ ...node.data.hProperties ?? {},
6211
+ dataAdmonition: marker.type
6212
+ };
6213
+ });
6214
+ };
6215
+ }
6216
+ function extractMarker(bq) {
6217
+ const firstChild = bq.children[0];
6218
+ if (!firstChild || firstChild.type !== "paragraph") return null;
6219
+ const firstText = firstChild.children[0];
6220
+ if (!firstText || firstText.type !== "text") return null;
6221
+ const match = /^\[!([a-z]+)\]\s*\n?/.exec(firstText.value);
6222
+ if (!match) return null;
6223
+ const type = match[1];
6224
+ if (!type) return null;
6225
+ return { type, length: match[0].length };
6226
+ }
6227
+ function stripMarkerText(bq, length) {
6228
+ const firstChild = isParagraph(bq.children[0]) ? bq.children[0] : void 0;
6229
+ if (!firstChild) return;
6230
+ const firstText = isText(firstChild.children[0]) ? firstChild.children[0] : void 0;
6231
+ if (!firstText) return;
6232
+ const stripped = { ...firstText, value: firstText.value.slice(length) };
6233
+ if (stripped.value.length === 0) {
6234
+ firstChild.children.shift();
6235
+ } else {
6236
+ firstChild.children[0] = stripped;
6237
+ }
6238
+ }
6239
+ function isParagraph(node) {
6240
+ return node?.type === "paragraph";
6241
+ }
6242
+ function isText(node) {
6243
+ return node?.type === "text";
6244
+ }
6245
+ var SANITIZE_SCHEMA = {
6246
+ ...defaultSchema,
6247
+ tagNames: [...defaultSchema.tagNames ?? [], "tool-call", "sources"],
6248
+ attributes: {
6249
+ ...defaultSchema.attributes ?? {},
6250
+ "tool-call": ["name", "state", "args", "result"],
6251
+ sources: ["data"],
6252
+ blockquote: [
6253
+ ...(defaultSchema.attributes ?? {}).blockquote ?? [],
6254
+ "dataAdmonition"
6255
+ ]
6256
+ }
6257
+ };
6258
+ var COMPONENTS = {
6259
+ code: CodeBlockSlot,
6260
+ a: CitationOrLinkSlot,
6261
+ blockquote: ReasoningOrQuoteSlot,
6262
+ "tool-call": ToolCallSlot,
6263
+ sources: SourcesSlot
6264
+ };
5882
6265
  function Markdown({ children, className }) {
6266
+ const safe = React44.useMemo(() => closeUnterminated(children), [children]);
5883
6267
  return /* @__PURE__ */ jsx(
5884
- Streamdown,
6268
+ "div",
5885
6269
  {
5886
6270
  className: cn(
5887
6271
  "prose prose-sm max-w-none text-foreground",
@@ -5890,10 +6274,154 @@ function Markdown({ children, className }) {
5890
6274
  "prose-code:text-foreground prose-code:before:content-none prose-code:after:content-none",
5891
6275
  className
5892
6276
  ),
6277
+ children: /* @__PURE__ */ jsx(
6278
+ ReactMarkdown,
6279
+ {
6280
+ remarkPlugins: [remarkGfm, remarkAdmonitions],
6281
+ rehypePlugins: [rehypeRaw, [rehypeSanitize, SANITIZE_SCHEMA]],
6282
+ components: COMPONENTS,
6283
+ children: safe
6284
+ }
6285
+ )
6286
+ }
6287
+ );
6288
+ }
6289
+ var FOOTNOTE_RE = /^(\d+)$/;
6290
+ function CitationOrLinkSlot({
6291
+ href,
6292
+ children,
6293
+ className,
6294
+ node: _node,
6295
+ ...rest
6296
+ }) {
6297
+ const text = extractText2(children);
6298
+ const footnote = FOOTNOTE_RE.exec(text);
6299
+ if (footnote && href) {
6300
+ const index = Number(footnote[1]);
6301
+ return /* @__PURE__ */ jsx(InlineCitation, { index, url: href, title: inferCitationTitle(href) });
6302
+ }
6303
+ return /* @__PURE__ */ jsx("a", { href, className, ...rest, children });
6304
+ }
6305
+ function extractText2(children) {
6306
+ if (typeof children === "string") return children;
6307
+ if (Array.isArray(children)) return children.map(extractText2).join("");
6308
+ return "";
6309
+ }
6310
+ function inferCitationTitle(href) {
6311
+ try {
6312
+ const url = new URL(href);
6313
+ const hostname = url.hostname.replace(/^www\./, "");
6314
+ return hostname.length > 0 ? hostname : href;
6315
+ } catch {
6316
+ return href;
6317
+ }
6318
+ }
6319
+ function CodeBlockSlot({ className, children, node: _node, ...rest }) {
6320
+ const langMatch = /language-([a-zA-Z0-9-]+)/.exec(className ?? "");
6321
+ const isFenced = Boolean(langMatch) || Array.isArray(children) && children.length > 1 || String(children ?? "").includes("\n");
6322
+ if (!isFenced) {
6323
+ return /* @__PURE__ */ jsx(
6324
+ "code",
6325
+ {
6326
+ className: cn(
6327
+ "rounded bg-muted px-[0.3em] py-[0.15em] font-mono text-[0.85em]",
6328
+ className
6329
+ ),
6330
+ ...rest,
6331
+ children
6332
+ }
6333
+ );
6334
+ }
6335
+ return /* @__PURE__ */ jsx(
6336
+ "code",
6337
+ {
6338
+ className: cn("font-mono text-sm", className),
6339
+ "data-fenced": "true",
6340
+ ...rest,
6341
+ children
6342
+ }
6343
+ );
6344
+ }
6345
+ function ReasoningOrQuoteSlot({
6346
+ children,
6347
+ className,
6348
+ node: _node,
6349
+ ...rest
6350
+ }) {
6351
+ if (rest["data-admonition"] === "think") {
6352
+ return /* @__PURE__ */ jsx(Reasoning, { children });
6353
+ }
6354
+ return /* @__PURE__ */ jsx(
6355
+ "blockquote",
6356
+ {
6357
+ className: cn(
6358
+ "my-4 border-l-2 border-border pl-4 italic text-muted-foreground",
6359
+ className
6360
+ ),
6361
+ ...rest,
5893
6362
  children
5894
6363
  }
5895
6364
  );
5896
6365
  }
6366
+ var VALID_TOOL_CALL_STATES = {
6367
+ pending: true,
6368
+ running: true,
6369
+ result: true,
6370
+ error: true
6371
+ };
6372
+ function ToolCallSlot({ name, state, args, result, children, node: _node }) {
6373
+ if (!name) return /* @__PURE__ */ jsx(Fragment, { children });
6374
+ const parsedState = isToolCallState(state) ? state : "result";
6375
+ return /* @__PURE__ */ jsx(
6376
+ ToolCall,
6377
+ {
6378
+ name,
6379
+ state: parsedState,
6380
+ args: parseJson(args),
6381
+ result: parseJson(result)
6382
+ }
6383
+ );
6384
+ }
6385
+ function isToolCallState(value) {
6386
+ return typeof value === "string" && value in VALID_TOOL_CALL_STATES;
6387
+ }
6388
+ function parseJson(raw) {
6389
+ if (raw === void 0 || raw === "") return void 0;
6390
+ try {
6391
+ return JSON.parse(raw);
6392
+ } catch {
6393
+ return raw;
6394
+ }
6395
+ }
6396
+ function SourcesSlot({ data, children, node: _node }) {
6397
+ const sources = React44.useMemo(() => parseSources(data), [data]);
6398
+ if (!sources) return /* @__PURE__ */ jsx(Fragment, { children });
6399
+ return /* @__PURE__ */ jsx(Sources, { sources });
6400
+ }
6401
+ function parseSources(raw) {
6402
+ if (raw === void 0 || raw === "") return null;
6403
+ let parsed;
6404
+ try {
6405
+ parsed = JSON.parse(raw);
6406
+ } catch {
6407
+ return null;
6408
+ }
6409
+ if (!Array.isArray(parsed)) return null;
6410
+ const result = [];
6411
+ for (const item of parsed) {
6412
+ if (!item || typeof item !== "object") continue;
6413
+ if (!("title" in item) || typeof item.title !== "string") continue;
6414
+ const ref = { title: item.title };
6415
+ if ("url" in item && typeof item.url === "string") {
6416
+ const url = safeUrl(item.url);
6417
+ if (url !== void 0) ref.url = url;
6418
+ }
6419
+ if ("page" in item && typeof item.page === "number") ref.page = item.page;
6420
+ if ("index" in item && typeof item.index === "number") ref.index = item.index;
6421
+ result.push(ref);
6422
+ }
6423
+ return result;
6424
+ }
5897
6425
  var LABEL_TO_LANG = {
5898
6426
  pnpm: "bash",
5899
6427
  npm: "bash",
@@ -6208,6 +6736,476 @@ function FileIcon2(props) {
6208
6736
  }
6209
6737
  );
6210
6738
  }
6739
+ function Task({ label, steps, durationMs, defaultOpen = true, className }) {
6740
+ const summary = summarize(steps, durationMs);
6741
+ return /* @__PURE__ */ jsxs(
6742
+ CollapsiblePrimitive.Root,
6743
+ {
6744
+ defaultOpen,
6745
+ className: cn(
6746
+ "overflow-hidden rounded-md border border-border bg-card text-card-foreground",
6747
+ className
6748
+ ),
6749
+ children: [
6750
+ /* @__PURE__ */ jsxs(
6751
+ CollapsiblePrimitive.Trigger,
6752
+ {
6753
+ className: cn(
6754
+ "group flex w-full items-center gap-2 px-3 py-2 text-left",
6755
+ "transition-all duration-[var(--duration-normal,200ms)] ease-out",
6756
+ "hover:bg-muted/30",
6757
+ "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2"
6758
+ ),
6759
+ children: [
6760
+ /* @__PURE__ */ jsxs("div", { className: "flex min-w-0 flex-col gap-0.5", children: [
6761
+ label ? /* @__PURE__ */ jsx("span", { className: "text-sm font-medium text-foreground", children: label }) : null,
6762
+ /* @__PURE__ */ jsx("span", { className: "text-xs text-muted-foreground", children: summary })
6763
+ ] }),
6764
+ /* @__PURE__ */ jsx(Chevron5, {})
6765
+ ]
6766
+ }
6767
+ ),
6768
+ /* @__PURE__ */ jsx(CollapsiblePrimitive.Content, { className: "overflow-hidden border-t border-foreground/[0.06]", children: /* @__PURE__ */ jsx("ol", { className: "my-0 ml-0 flex list-none flex-col pl-0", children: steps.map((step) => /* @__PURE__ */ jsxs(
6769
+ "li",
6770
+ {
6771
+ className: "flex items-start gap-3 px-3 py-2 text-sm before:content-none last:pb-3",
6772
+ children: [
6773
+ /* @__PURE__ */ jsx(StepIcon, { state: step.state }),
6774
+ /* @__PURE__ */ jsxs("div", { className: "flex min-w-0 flex-col gap-0.5", children: [
6775
+ /* @__PURE__ */ jsx(
6776
+ "span",
6777
+ {
6778
+ className: cn(
6779
+ "leading-snug",
6780
+ step.state === "result" && "text-muted-foreground line-through decoration-muted-foreground/50",
6781
+ step.state === "running" && "text-foreground font-medium",
6782
+ step.state === "error" && "text-destructive",
6783
+ step.state === "pending" && "text-muted-foreground"
6784
+ ),
6785
+ children: step.label
6786
+ }
6787
+ ),
6788
+ step.detail ? /* @__PURE__ */ jsx("span", { className: "text-xs text-muted-foreground", children: step.detail }) : null
6789
+ ] })
6790
+ ]
6791
+ },
6792
+ step.id
6793
+ )) }) })
6794
+ ]
6795
+ }
6796
+ );
6797
+ }
6798
+ function summarize(steps, durationMs) {
6799
+ const total = steps.length;
6800
+ const done = steps.filter((s) => s.state === "result").length;
6801
+ const running = steps.some((s) => s.state === "running");
6802
+ const errored = steps.some((s) => s.state === "error");
6803
+ if (errored) return `${done} of ${total} steps \xB7 failed`;
6804
+ if (running) return `${done} of ${total} steps`;
6805
+ if (done === total && total > 0 && typeof durationMs === "number") {
6806
+ return `Done in ${formatDuration(durationMs)}`;
6807
+ }
6808
+ if (done === total && total > 0) return "Done";
6809
+ return `${done} of ${total} steps`;
6810
+ }
6811
+ function formatDuration(ms) {
6812
+ if (ms < 1e3) return `${ms}ms`;
6813
+ const seconds = ms / 1e3;
6814
+ const formatted = seconds >= 10 ? Math.round(seconds).toString() : seconds.toFixed(1);
6815
+ return `${formatted}s`;
6816
+ }
6817
+ function StepIcon({ state }) {
6818
+ const cls = "mt-0.5 shrink-0";
6819
+ if (state === "result") {
6820
+ return /* @__PURE__ */ jsxs(
6821
+ "svg",
6822
+ {
6823
+ "aria-label": "Done",
6824
+ role: "img",
6825
+ viewBox: "0 0 16 16",
6826
+ width: "14",
6827
+ height: "14",
6828
+ fill: "none",
6829
+ stroke: "currentColor",
6830
+ strokeWidth: "2",
6831
+ strokeLinecap: "round",
6832
+ strokeLinejoin: "round",
6833
+ className: cn(cls, "text-emerald-500"),
6834
+ children: [
6835
+ /* @__PURE__ */ jsx("circle", { cx: "8", cy: "8", r: "6" }),
6836
+ /* @__PURE__ */ jsx("path", { d: "M5 8.25l2.25 2.25L11 6" })
6837
+ ]
6838
+ }
6839
+ );
6840
+ }
6841
+ if (state === "running") {
6842
+ return /* @__PURE__ */ jsx(
6843
+ "svg",
6844
+ {
6845
+ "aria-label": "Running",
6846
+ role: "img",
6847
+ viewBox: "0 0 16 16",
6848
+ width: "14",
6849
+ height: "14",
6850
+ fill: "none",
6851
+ stroke: "currentColor",
6852
+ strokeWidth: "2",
6853
+ strokeLinecap: "round",
6854
+ className: cn(cls, "text-primary motion-safe:animate-spin"),
6855
+ children: /* @__PURE__ */ jsx("path", { d: "M8 1.5a6.5 6.5 0 1 1-6.5 6.5" })
6856
+ }
6857
+ );
6858
+ }
6859
+ if (state === "error") {
6860
+ return /* @__PURE__ */ jsxs(
6861
+ "svg",
6862
+ {
6863
+ "aria-label": "Error",
6864
+ role: "img",
6865
+ viewBox: "0 0 16 16",
6866
+ width: "14",
6867
+ height: "14",
6868
+ fill: "none",
6869
+ stroke: "currentColor",
6870
+ strokeWidth: "2",
6871
+ strokeLinecap: "round",
6872
+ strokeLinejoin: "round",
6873
+ className: cn(cls, "text-destructive"),
6874
+ children: [
6875
+ /* @__PURE__ */ jsx("circle", { cx: "8", cy: "8", r: "6" }),
6876
+ /* @__PURE__ */ jsx("path", { d: "M5 5l6 6M11 5l-6 6" })
6877
+ ]
6878
+ }
6879
+ );
6880
+ }
6881
+ return /* @__PURE__ */ jsx(
6882
+ "svg",
6883
+ {
6884
+ "aria-label": "Pending",
6885
+ role: "img",
6886
+ viewBox: "0 0 16 16",
6887
+ width: "14",
6888
+ height: "14",
6889
+ fill: "none",
6890
+ stroke: "currentColor",
6891
+ strokeWidth: "2",
6892
+ className: cn(cls, "text-muted-foreground"),
6893
+ children: /* @__PURE__ */ jsx("circle", { cx: "8", cy: "8", r: "6", strokeDasharray: "2 2" })
6894
+ }
6895
+ );
6896
+ }
6897
+ function Chevron5() {
6898
+ return /* @__PURE__ */ jsx(
6899
+ "svg",
6900
+ {
6901
+ "aria-hidden": true,
6902
+ viewBox: "0 0 16 16",
6903
+ width: "12",
6904
+ height: "12",
6905
+ fill: "none",
6906
+ stroke: "currentColor",
6907
+ strokeWidth: "1.5",
6908
+ strokeLinecap: "round",
6909
+ strokeLinejoin: "round",
6910
+ className: "ml-auto shrink-0 text-muted-foreground transition-transform duration-200 group-data-[state=open]:rotate-180",
6911
+ children: /* @__PURE__ */ jsx("path", { d: "M4 6l4 4 4-4" })
6912
+ }
6913
+ );
6914
+ }
6915
+ function Shimmer({
6916
+ width = "100%",
6917
+ height = "1.5rem",
6918
+ durationMs = 1500,
6919
+ label = "Loading\u2026",
6920
+ className
6921
+ }) {
6922
+ return /* @__PURE__ */ jsx(
6923
+ "div",
6924
+ {
6925
+ role: "status",
6926
+ "aria-label": label,
6927
+ "aria-live": "polite",
6928
+ className: cn(
6929
+ // `motion-safe:` gates the pulse on `prefers-reduced-motion: no-preference` —
6930
+ // users with reduce-motion get a static bar.
6931
+ "motion-safe:animate-pulse rounded-md border border-foreground/[0.06] bg-muted",
6932
+ className
6933
+ ),
6934
+ style: {
6935
+ width,
6936
+ height,
6937
+ animationDuration: `${durationMs}ms`
6938
+ }
6939
+ }
6940
+ );
6941
+ }
6942
+ function Branch({
6943
+ current,
6944
+ total,
6945
+ onCurrentChange,
6946
+ children,
6947
+ "aria-label": ariaLabel = "Response branches",
6948
+ className
6949
+ }) {
6950
+ if (total <= 0) return null;
6951
+ const interactive = typeof onCurrentChange === "function";
6952
+ const atFirst = current <= 0;
6953
+ const atLast = current >= total - 1;
6954
+ function go(delta) {
6955
+ if (!interactive) return;
6956
+ const next = current + delta;
6957
+ if (next < 0 || next > total - 1) return;
6958
+ onCurrentChange(next);
6959
+ }
6960
+ function handleKeyDown(event) {
6961
+ if (!interactive) return;
6962
+ if (event.key === "ArrowLeft") {
6963
+ event.preventDefault();
6964
+ go(-1);
6965
+ } else if (event.key === "ArrowRight") {
6966
+ event.preventDefault();
6967
+ go(1);
6968
+ }
6969
+ }
6970
+ return /* @__PURE__ */ jsxs(
6971
+ "div",
6972
+ {
6973
+ role: "group",
6974
+ "aria-label": ariaLabel,
6975
+ onKeyDown: handleKeyDown,
6976
+ className: cn("flex flex-col gap-2", className),
6977
+ children: [
6978
+ /* @__PURE__ */ jsx("div", { children }),
6979
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-end gap-1", children: [
6980
+ /* @__PURE__ */ jsx(
6981
+ "button",
6982
+ {
6983
+ type: "button",
6984
+ "aria-label": "Previous response",
6985
+ disabled: !interactive || atFirst,
6986
+ onClick: () => go(-1),
6987
+ className: cn(
6988
+ "inline-flex h-7 w-7 items-center justify-center rounded-md text-muted-foreground",
6989
+ "transition-all duration-[var(--duration-normal,200ms)] ease-out",
6990
+ "hover:bg-muted hover:text-foreground",
6991
+ "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2",
6992
+ "disabled:pointer-events-none disabled:opacity-40"
6993
+ ),
6994
+ children: /* @__PURE__ */ jsx(ChevronLeft, {})
6995
+ }
6996
+ ),
6997
+ /* @__PURE__ */ jsxs(
6998
+ "span",
6999
+ {
7000
+ "aria-live": interactive ? "polite" : void 0,
7001
+ "aria-atomic": interactive ? "true" : void 0,
7002
+ className: "select-none px-1 text-xs tabular-nums text-muted-foreground",
7003
+ children: [
7004
+ current + 1,
7005
+ " of ",
7006
+ total
7007
+ ]
7008
+ }
7009
+ ),
7010
+ /* @__PURE__ */ jsx(
7011
+ "button",
7012
+ {
7013
+ type: "button",
7014
+ "aria-label": "Next response",
7015
+ disabled: !interactive || atLast,
7016
+ onClick: () => go(1),
7017
+ className: cn(
7018
+ "inline-flex h-7 w-7 items-center justify-center rounded-md text-muted-foreground",
7019
+ "transition-all duration-[var(--duration-normal,200ms)] ease-out",
7020
+ "hover:bg-muted hover:text-foreground",
7021
+ "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2",
7022
+ "disabled:pointer-events-none disabled:opacity-40"
7023
+ ),
7024
+ children: /* @__PURE__ */ jsx(ChevronRight, {})
7025
+ }
7026
+ )
7027
+ ] })
7028
+ ]
7029
+ }
7030
+ );
7031
+ }
7032
+ function ChevronLeft() {
7033
+ return /* @__PURE__ */ jsx(
7034
+ "svg",
7035
+ {
7036
+ "aria-hidden": true,
7037
+ viewBox: "0 0 16 16",
7038
+ width: "14",
7039
+ height: "14",
7040
+ fill: "none",
7041
+ stroke: "currentColor",
7042
+ strokeWidth: "1.75",
7043
+ strokeLinecap: "round",
7044
+ strokeLinejoin: "round",
7045
+ children: /* @__PURE__ */ jsx("path", { d: "M10 4l-4 4 4 4" })
7046
+ }
7047
+ );
7048
+ }
7049
+ function ChevronRight() {
7050
+ return /* @__PURE__ */ jsx(
7051
+ "svg",
7052
+ {
7053
+ "aria-hidden": true,
7054
+ viewBox: "0 0 16 16",
7055
+ width: "14",
7056
+ height: "14",
7057
+ fill: "none",
7058
+ stroke: "currentColor",
7059
+ strokeWidth: "1.75",
7060
+ strokeLinecap: "round",
7061
+ strokeLinejoin: "round",
7062
+ children: /* @__PURE__ */ jsx("path", { d: "M6 4l4 4-4 4" })
7063
+ }
7064
+ );
7065
+ }
7066
+ function Plan({
7067
+ label,
7068
+ description,
7069
+ steps,
7070
+ onApprove,
7071
+ onCancel,
7072
+ approveLabel = "Approve",
7073
+ cancelLabel = "Cancel",
7074
+ className
7075
+ }) {
7076
+ const showFooter = typeof onApprove === "function" || typeof onCancel === "function";
7077
+ return /* @__PURE__ */ jsxs(
7078
+ "div",
7079
+ {
7080
+ className: cn(
7081
+ "overflow-hidden rounded-md border border-border bg-card",
7082
+ className
7083
+ ),
7084
+ children: [
7085
+ label || description ? /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-0.5 border-b border-foreground/[0.06] px-3 py-2", children: [
7086
+ label ? /* @__PURE__ */ jsx("span", { className: "text-sm font-medium text-foreground", children: label }) : null,
7087
+ description ? /* @__PURE__ */ jsx("span", { className: "text-xs text-muted-foreground", children: description }) : null
7088
+ ] }) : null,
7089
+ /* @__PURE__ */ jsx(
7090
+ "ol",
7091
+ {
7092
+ "aria-label": label ? `${label} steps` : "Plan steps",
7093
+ className: "my-0 ml-0 flex list-none flex-col gap-2 py-3 pr-3 pl-3",
7094
+ children: steps.map((step, index) => (
7095
+ /*
7096
+ * `before:content-none` defeats Tailwind Typography's
7097
+ * default `<li>::before` markers when this card lands
7098
+ * inside a `prose` block (assistant turn, MDX page).
7099
+ * Don't strip — the indicator handles ordinal display.
7100
+ */
7101
+ /* @__PURE__ */ jsxs(
7102
+ "li",
7103
+ {
7104
+ className: "flex items-start gap-3 text-sm before:content-none",
7105
+ children: [
7106
+ /* @__PURE__ */ jsx(
7107
+ "span",
7108
+ {
7109
+ "aria-hidden": true,
7110
+ className: cn(
7111
+ "mt-0.5 inline-flex h-5 w-5 shrink-0 items-center justify-center rounded-full",
7112
+ "border border-input bg-background text-[0.65rem] font-medium tabular-nums text-muted-foreground"
7113
+ ),
7114
+ children: index + 1
7115
+ }
7116
+ ),
7117
+ /* @__PURE__ */ jsxs("div", { className: "flex min-w-0 flex-col gap-0.5", children: [
7118
+ /* @__PURE__ */ jsx("span", { className: "leading-snug text-foreground", children: step.label }),
7119
+ step.detail ? /* @__PURE__ */ jsx("span", { className: "text-xs text-muted-foreground", children: step.detail }) : null
7120
+ ] })
7121
+ ]
7122
+ },
7123
+ step.id
7124
+ )
7125
+ ))
7126
+ }
7127
+ ),
7128
+ showFooter ? /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-end gap-2 border-t border-foreground/[0.06] bg-muted/20 px-3 py-2", children: [
7129
+ typeof onCancel === "function" ? /* @__PURE__ */ jsx(Button, { variant: "ghost", size: "sm", onClick: onCancel, children: cancelLabel }) : null,
7130
+ typeof onApprove === "function" ? /* @__PURE__ */ jsx(Button, { variant: "default", size: "sm", onClick: onApprove, children: approveLabel }) : null
7131
+ ] }) : null
7132
+ ]
7133
+ }
7134
+ );
7135
+ }
7136
+ function Conversation({
7137
+ messages,
7138
+ onSubmit,
7139
+ placeholder = "Ask anything\u2026",
7140
+ value: valueProp,
7141
+ onValueChange: onValueChangeProp,
7142
+ isStreaming = false,
7143
+ sources,
7144
+ disabled = false,
7145
+ composerActions,
7146
+ className
7147
+ }) {
7148
+ const [internalValue, setInternalValue] = React44.useState("");
7149
+ const isControlled = valueProp !== void 0;
7150
+ const value = isControlled ? valueProp : internalValue;
7151
+ const setValue = isControlled ? (next) => onValueChangeProp?.(next) : setInternalValue;
7152
+ if (typeof process !== "undefined" && process.env?.NODE_ENV !== "production" && isControlled && typeof onValueChangeProp !== "function") {
7153
+ console.warn(
7154
+ "<Conversation>: `value` was passed without `onValueChange`. The composer will be read-only \u2014 pass both props together for controlled mode, or omit both to let the component manage state internally."
7155
+ );
7156
+ }
7157
+ function handleSubmit(text) {
7158
+ onSubmit(text);
7159
+ setValue("");
7160
+ }
7161
+ return /* @__PURE__ */ jsxs("div", { className: cn("flex h-full min-h-0 flex-col gap-3", className), children: [
7162
+ /* @__PURE__ */ jsxs(MessageList, { className: "min-h-0 flex-1", children: [
7163
+ messages.map((m) => /* @__PURE__ */ jsx(Message, { role: m.role, children: m.content }, m.id)),
7164
+ isStreaming ? /* @__PURE__ */ jsx(Message, { role: "assistant", children: /* @__PURE__ */ jsx(Shimmer, { width: "60%" }) }) : null
7165
+ ] }),
7166
+ sources && sources.length > 0 ? /* @__PURE__ */ jsx(Sources, { sources }) : null,
7167
+ /* @__PURE__ */ jsx(
7168
+ Composer,
7169
+ {
7170
+ value,
7171
+ onValueChange: setValue,
7172
+ onSubmit: handleSubmit,
7173
+ disabled,
7174
+ placeholder,
7175
+ children: composerActions
7176
+ }
7177
+ )
7178
+ ] });
7179
+ }
7180
+ function ChainOfThought({
7181
+ steps,
7182
+ finalAnswer,
7183
+ label = "Chain of thought",
7184
+ defaultOpen = false,
7185
+ className
7186
+ }) {
7187
+ return /* @__PURE__ */ jsxs("div", { className: cn("flex flex-col gap-2", className), children: [
7188
+ /* @__PURE__ */ jsx(Reasoning, { label, defaultOpen, children: /* @__PURE__ */ jsx("ol", { className: "my-0 ml-0 flex list-none flex-col gap-3 pl-0", children: steps.map((step, index) => /* @__PURE__ */ jsxs(
7189
+ "li",
7190
+ {
7191
+ className: "flex flex-col gap-1 text-sm before:content-none",
7192
+ children: [
7193
+ /* @__PURE__ */ jsx(Row, { term: "Thought", value: step.thought }),
7194
+ step.action ? /* @__PURE__ */ jsx(Row, { term: "Action", value: step.action }) : null,
7195
+ step.observation ? /* @__PURE__ */ jsx(Row, { term: "Observation", value: step.observation }) : null
7196
+ ]
7197
+ },
7198
+ index
7199
+ )) }) }),
7200
+ finalAnswer ? /* @__PURE__ */ jsx("div", { children: finalAnswer }) : null
7201
+ ] });
7202
+ }
7203
+ function Row({ term, value }) {
7204
+ return /* @__PURE__ */ jsxs("div", { className: "flex gap-2", children: [
7205
+ /* @__PURE__ */ jsx("span", { className: "shrink-0 text-xs font-medium uppercase tracking-wide text-muted-foreground", children: term }),
7206
+ /* @__PURE__ */ jsx("span", { className: "min-w-0 flex-1 text-foreground", children: value })
7207
+ ] });
7208
+ }
6211
7209
  function MindMap({
6212
7210
  root,
6213
7211
  orientation = "radial",
@@ -10781,6 +11779,6 @@ function AuthVerifyOtp({
10781
11779
  ] }) });
10782
11780
  }
10783
11781
 
10784
- export { Accordion, AccordionContent, AccordionItem, AccordionTrigger, Alert, AlertDescription, AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogOverlay, AlertDialogPortal, AlertDialogTitle, AlertDialogTrigger, AlertTitle, Arc, AspectRatio, Attachment, AudioPlayer, AudioWaveform, AuthForgotPassword, AuthResetPassword, AuthSignInSplit, AuthSignUpCard, AuthVerifyEmail, AuthVerifyOtp, Avatar, AvatarFallback, AvatarImage, Badge, Breadcrumb, BreadcrumbEllipsis, BreadcrumbItem, BreadcrumbLink, BreadcrumbList, BreadcrumbPage, BreadcrumbSeparator, Button, Calendar, Canvas, Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle, Checkbox, Chord, Citation, Cloze, Cluster, CodeBlock, CodeBlockCopy2 as CodeBlockCopy, Collapsible, CollapsibleContent2 as CollapsibleContent, CollapsibleTrigger2 as CollapsibleTrigger, ColorPicker, Combobox, Command, CommandDialog, CommandEmpty, CommandGroup, CommandInput, CommandItem, CommandList, CommandSeparator, CommandShortcut, CompareTable, Composer, Container, ContextMenu, ContextMenuCheckboxItem, ContextMenuContent, ContextMenuGroup, ContextMenuItem, ContextMenuLabel, ContextMenuPortal, ContextMenuRadioGroup, ContextMenuRadioItem, ContextMenuSeparator, ContextMenuShortcut, ContextMenuTrigger, DataTable, DatePicker, Deck, Dendrogram, Diagram, Dialog, DialogClose, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogOverlay, DialogPortal, DialogTitle, DialogTrigger, Drawer, DrawerClose, DrawerContent, DrawerDescription, DrawerFooter, DrawerHeader, DrawerOverlay, DrawerPortal, DrawerTitle, DrawerTrigger, DropdownMenu, DropdownMenuCheckboxItem, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuLabel, DropdownMenuPortal, DropdownMenuRadioGroup, DropdownMenuRadioItem, DropdownMenuSeparator, DropdownMenuShortcut, DropdownMenuSub, DropdownMenuTrigger, Dropzone, Empty, ErrorState, FileTree, Flashcard, Flowchart, Form, FormControl, FormDescription, FormField, FormItem, FormLabel, FormMessage, Funnel, Gantt, Grid, HoverCard, HoverCardContent, HoverCardTrigger, ImageOcclusion, Input, InputOTP, InputOTPGroup, InputOTPSeparator, InputOTPSlot, Label, Loading, LoadingIndicator, Markdown, Matrix, Menubar, MenubarContent, MenubarGroup, MenubarItem, MenubarLabel, MenubarMenu, MenubarPortal, MenubarRadioGroup, MenubarSeparator, MenubarShortcut, MenubarTrigger, Message, MessageActions, MessageList, MindMap, MultiCombobox, NavigationMenu, NavigationMenuContent, NavigationMenuIndicator, NavigationMenuItem, NavigationMenuLink, NavigationMenuList, NavigationMenuTrigger, NavigationMenuViewport, OrgChart, Pagination, PaginationContent, PaginationEllipsis, PaginationItem, PaginationLink, PaginationNext, PaginationPrevious, Popover, PopoverAnchor, PopoverContent, PopoverTrigger, Progress, Pyramid, Quiz, RadioGroup, RadioGroupItem, Reasoning, ResizableHandle, ResizablePanel, ResizablePanelGroup, Sankey, ScrollArea, ScrollBar, Select, SelectContent, SelectGroup, SelectItem, SelectLabel, SelectSeparator, SelectTrigger, SelectValue, Separator, Sequence, Sheet, SheetClose, SheetContent, SheetDescription, SheetFooter, SheetHeader, SheetOverlay, SheetPortal, SheetTitle, SheetTrigger, Sidebar, SidebarContent, SidebarFooter, SidebarHeader, SidebarItem, SidebarProvider, SidebarTrigger, Skeleton, Slider, SpacedRepetition, Spacer, SpeechRecognition, Stack, Stepper, Suggestion, Sunburst, Switch, Table, TableBody, TableCaption, TableCell, TableFooter, TableHead, TableHeader, TableRow, Tabs, TabsContent, TabsList, TabsTrigger, Tag, Terminal, Textarea, TimeAxis, TimePicker, Timeline, Toaster, Toggle, ToggleGroup, ToggleGroupItem, ToolCall, Toolbar, ToolbarButton, ToolbarLink, ToolbarSeparator, ToolbarToggleGroup, ToolbarToggleItem, Tooltip, TooltipContent, TooltipProvider, TooltipTrigger, Tree, TreeMap, Venn, alertVariants, attachmentVariants, badgeVariants, buttonVariants, clusterVariants, cn, containerVariants, emptyVariants, errorStateVariants, formatHslTriplet, gridVariants, hexToHslTriplet, hslToRgb, hslTripletToHex, loadingIndicatorVariants, loadingVariants, messageVariants, mockAuthAdapter, navigationMenuTriggerStyle, parseHslTriplet, rgbToHsl, spacerVariants, stackVariants, tagVariants, toggleVariants, toolbarVariants, useFormField, useSidebar };
11782
+ export { Accordion, AccordionContent, AccordionItem, AccordionTrigger, Alert, AlertDescription, AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogOverlay, AlertDialogPortal, AlertDialogTitle, AlertDialogTrigger, AlertTitle, Arc, AspectRatio, Attachment, AudioPlayer, AudioWaveform, AuthForgotPassword, AuthResetPassword, AuthSignInSplit, AuthSignUpCard, AuthVerifyEmail, AuthVerifyOtp, Avatar, AvatarFallback, AvatarImage, Badge, Branch, Breadcrumb, BreadcrumbEllipsis, BreadcrumbItem, BreadcrumbLink, BreadcrumbList, BreadcrumbPage, BreadcrumbSeparator, Button, Calendar, Canvas, Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle, ChainOfThought, Checkbox, Chord, Citation, Cloze, Cluster, CodeBlock, CodeBlockCopy2 as CodeBlockCopy, Collapsible, CollapsibleContent2 as CollapsibleContent, CollapsibleTrigger2 as CollapsibleTrigger, ColorPicker, Combobox, Command, CommandDialog, CommandEmpty, CommandGroup, CommandInput, CommandItem, CommandList, CommandSeparator, CommandShortcut, CompareTable, Composer, Container, ContextMenu, ContextMenuCheckboxItem, ContextMenuContent, ContextMenuGroup, ContextMenuItem, ContextMenuLabel, ContextMenuPortal, ContextMenuRadioGroup, ContextMenuRadioItem, ContextMenuSeparator, ContextMenuShortcut, ContextMenuTrigger, Conversation, DataTable, DatePicker, Deck, Dendrogram, Diagram, Dialog, DialogClose, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogOverlay, DialogPortal, DialogTitle, DialogTrigger, Drawer, DrawerClose, DrawerContent, DrawerDescription, DrawerFooter, DrawerHeader, DrawerOverlay, DrawerPortal, DrawerTitle, DrawerTrigger, DropdownMenu, DropdownMenuCheckboxItem, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuLabel, DropdownMenuPortal, DropdownMenuRadioGroup, DropdownMenuRadioItem, DropdownMenuSeparator, DropdownMenuShortcut, DropdownMenuSub, DropdownMenuTrigger, Dropzone, Empty, ErrorState, FileTree, Flashcard, Flowchart, Form, FormControl, FormDescription, FormField, FormItem, FormLabel, FormMessage, Funnel, Gantt, Grid, HoverCard, HoverCardContent, HoverCardTrigger, ImageOcclusion, InlineCitation, Input, InputOTP, InputOTPGroup, InputOTPSeparator, InputOTPSlot, Label, Loading, LoadingIndicator, Markdown, Matrix, Menubar, MenubarContent, MenubarGroup, MenubarItem, MenubarLabel, MenubarMenu, MenubarPortal, MenubarRadioGroup, MenubarSeparator, MenubarShortcut, MenubarTrigger, Message, MessageActions, MessageList, MindMap, MultiCombobox, NavigationMenu, NavigationMenuContent, NavigationMenuIndicator, NavigationMenuItem, NavigationMenuLink, NavigationMenuList, NavigationMenuTrigger, NavigationMenuViewport, OrgChart, Pagination, PaginationContent, PaginationEllipsis, PaginationItem, PaginationLink, PaginationNext, PaginationPrevious, Plan, Popover, PopoverAnchor, PopoverContent, PopoverTrigger, Progress, Pyramid, Quiz, RadioGroup, RadioGroupItem, Reasoning, ResizableHandle, ResizablePanel, ResizablePanelGroup, Sankey, ScrollArea, ScrollBar, Select, SelectContent, SelectGroup, SelectItem, SelectLabel, SelectSeparator, SelectTrigger, SelectValue, Separator, Sequence, Sheet, SheetClose, SheetContent, SheetDescription, SheetFooter, SheetHeader, SheetOverlay, SheetPortal, SheetTitle, SheetTrigger, Shimmer, Sidebar, SidebarContent, SidebarFooter, SidebarHeader, SidebarItem, SidebarProvider, SidebarTrigger, Skeleton, Slider, Sources, SpacedRepetition, Spacer, SpeechRecognition, Stack, Stepper, Suggestion, Sunburst, Switch, Table, TableBody, TableCaption, TableCell, TableFooter, TableHead, TableHeader, TableRow, Tabs, TabsContent, TabsList, TabsTrigger, Tag, Task, Terminal, Textarea, TimeAxis, TimePicker, Timeline, Toaster, Toggle, ToggleGroup, ToggleGroupItem, ToolCall, Toolbar, ToolbarButton, ToolbarLink, ToolbarSeparator, ToolbarToggleGroup, ToolbarToggleItem, Tooltip, TooltipContent, TooltipProvider, TooltipTrigger, Tree, TreeMap, Venn, alertVariants, attachmentVariants, badgeVariants, buttonVariants, clusterVariants, cn, containerVariants, emptyVariants, errorStateVariants, formatHslTriplet, gridVariants, hexToHslTriplet, hslToRgb, hslTripletToHex, loadingIndicatorVariants, loadingVariants, messageVariants, mockAuthAdapter, navigationMenuTriggerStyle, parseHslTriplet, rgbToHsl, spacerVariants, stackVariants, tagVariants, toggleVariants, toolbarVariants, useFormField, useSidebar };
10785
11783
  //# sourceMappingURL=index.js.map
10786
11784
  //# sourceMappingURL=index.js.map