@tangle-network/ui 11.11.3 → 11.11.5

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 (36) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/README.md +9 -0
  3. package/dist/{chat-BUJhNpx2.js → chat-DXidmE_w.js} +8 -8
  4. package/dist/chat.d.ts +1 -1
  5. package/dist/chat.js +1 -1
  6. package/dist/{document-editor-pane-LyanNypc.js → document-editor-pane-DrjsLZ3a.js} +1 -1
  7. package/dist/editor.js +1 -1
  8. package/dist/{files-DgPc3vI2.js → files-DDpeW_nO.js} +2 -2
  9. package/dist/files.js +1 -1
  10. package/dist/hooks.js +1 -1
  11. package/dist/{index-CUhfHT_V.d.ts → index-D-9c3r-Y.d.ts} +3 -3
  12. package/dist/index.d.ts +6 -5
  13. package/dist/index.js +8 -8
  14. package/dist/{index-Cq-EJzqW.d.ts → markdown-C0atSabr.d.ts} +4 -3
  15. package/dist/{markdown-BGqicV82.js → markdown-PywkQXWk.js} +25 -4
  16. package/dist/markdown.d.ts +2 -2
  17. package/dist/markdown.js +2 -2
  18. package/dist/{openui-artifact-renderer-C3bmqfjX.js → openui-artifact-renderer-DjLPuaP9.js} +8 -7
  19. package/dist/{openui-artifact-renderer-D3E5bIAI.d.ts → openui-artifact-renderer-fkBQaoLO.d.ts} +3 -1
  20. package/dist/openui-schema.d.ts +2 -2
  21. package/dist/openui.d.ts +2 -2
  22. package/dist/openui.js +1 -1
  23. package/dist/{run-group-CxNskmHd.js → run-group-COUIsZ_x.js} +2 -2
  24. package/dist/run.js +2 -2
  25. package/dist/{schema-BFKgCGH-.d.ts → schema-DAstk-J4.d.ts} +1 -1
  26. package/dist/sdk-hooks.js +1 -1
  27. package/dist/{tool-call-feed-Djt2q11V.js → tool-call-feed-DNADpFyJ.js} +1 -1
  28. package/dist/{use-sse-stream-BVgO1QBN.js → use-sse-stream-OOPpkt_E.js} +1 -1
  29. package/package.json +4 -2
  30. package/src/chat/user-message.test.tsx +9 -3
  31. package/src/chat/user-message.tsx +7 -5
  32. package/src/markdown/index.ts +1 -1
  33. package/src/markdown/markdown.test.tsx +57 -1
  34. package/src/markdown/markdown.tsx +40 -4
  35. package/src/openui/openui-artifact-renderer.tsx +15 -7
  36. package/src/openui/schema.test.tsx +40 -1
package/CHANGELOG.md CHANGED
@@ -1,5 +1,17 @@
1
1
  # @tangle-network/ui
2
2
 
3
+ ## 11.11.5
4
+
5
+ ### Patch Changes
6
+
7
+ - 688868d: Add sanitized heading IDs and URL transform forwarding for Markdown rendered in OpenUI artifacts.
8
+
9
+ ## 11.11.4
10
+
11
+ ### Patch Changes
12
+
13
+ - 720de9a: Normalize the shared neutral palette and regenerate standalone chart tokens so charts follow the palette. Make user message cards wrap in narrow layouts.
14
+
3
15
  ## 11.11.3
4
16
 
5
17
  ### Patch Changes
package/README.md CHANGED
@@ -95,6 +95,15 @@ Both validators return `{ ok: true, value }` with a typed renderer node, or `{ o
95
95
  They reject unknown node types, hidden fields, malformed cells, and unsupported nested children.
96
96
  The renderer reports an unsupported saved node at its path instead of silently omitting it.
97
97
 
98
+ ### Markdown and OpenUI links
99
+
100
+ `Markdown` adds GitHub-style heading IDs before sanitising the rendered document.
101
+ The existing sanitizer keeps its `user-content-` prefix to prevent DOM clobbering.
102
+ For a link into another Markdown file, use `getSanitizedMarkdownHeadingIdFromRawFragment` with raw fragment text, without a leading `#` or sanitizer prefix.
103
+ `Markdown` applies the same mapping to local `#fragment` links.
104
+ Custom URL transforms still pass through ReactMarkdown's safe protocol check.
105
+ `OpenUIArtifactRenderer` forwards its `urlTransform` prop to nested Markdown nodes.
106
+
98
107
  ## Optional peers
99
108
 
100
109
  `@tiptap/core`, `@tiptap/react`, `@tiptap/starter-kit`, `@tiptap/extension-collaboration`, `@tiptap/extension-collaboration-caret`, `@hocuspocus/provider` and `yjs` back the `./editor` entry. The entry reaches every one of them through a dynamic `import()`, and gets a loud error that names the missing packages only when it renders an editor. `./editor` splits the cost three ways, so each surface costs only the peers it uses:
@@ -3,9 +3,9 @@ import { t as cn } from "./utils-C_uf36nf.js";
3
3
  import { r as getToolDisplayMetadata } from "./tool-display-BAuAVa43.js";
4
4
  import { n as useRunCollapseState, r as useRunGroups, t as useAutoScroll } from "./use-auto-scroll-C5Pjeqon.js";
5
5
  import { n as ToolCallStep, t as ToolCallGroup } from "./tool-call-step-DNebqhmX.js";
6
- import { t as Markdown } from "./markdown-BGqicV82.js";
7
- import { n as InlineThinkingItem, t as RunGroup } from "./run-group-CxNskmHd.js";
8
- import { t as OpenUIArtifactRenderer } from "./openui-artifact-renderer-C3bmqfjX.js";
6
+ import { t as Markdown } from "./markdown-PywkQXWk.js";
7
+ import { n as InlineThinkingItem, t as RunGroup } from "./run-group-COUIsZ_x.js";
8
+ import { t as OpenUIArtifactRenderer } from "./openui-artifact-renderer-DjLPuaP9.js";
9
9
  import { memo, useEffect, useMemo, useRef, useState } from "react";
10
10
  import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
11
11
  import { AlertTriangle, ArrowDown, CheckCircle2, CircleDot, FileText, Info } from "lucide-react";
@@ -17,8 +17,8 @@ function formatTime$1(date) {
17
17
  });
18
18
  }
19
19
  /**
20
- * The single user message bubble — a quiet, right-aligned fill on the muted
21
- * surface (no border, no loud fill, no uppercase label). The timestamp sits
20
+ * The single user message bubble — a quiet, right-aligned card with a subtle
21
+ * semantic border (no loud fill, no uppercase label). The timestamp sits
22
22
  * beside the bubble and appears on hover, so it costs no height. Used by both
23
23
  * the run/message list (session-model `parts`) and AgentTimeline (direct
24
24
  * `content`/`timestamp`).
@@ -29,15 +29,15 @@ const UserMessage = memo(({ message: _message, parts, content, timestamp, action
29
29
  return /* @__PURE__ */ jsx("div", {
30
30
  className: "flex justify-end",
31
31
  children: /* @__PURE__ */ jsxs("div", {
32
- className: "group flex max-w-[78%] flex-col items-end gap-2",
32
+ className: "group flex min-w-0 max-w-[78%] flex-col items-end gap-2",
33
33
  children: [/* @__PURE__ */ jsxs("div", {
34
- className: "relative w-full rounded-2xl bg-muted/50 px-4 py-3",
34
+ className: "relative w-full min-w-0 rounded-2xl border border-border bg-card px-4 py-3",
35
35
  children: [timestamp ? /* @__PURE__ */ jsx("span", {
36
36
  "data-user-message-time": "",
37
37
  className: "pointer-events-none absolute right-full top-1/2 mr-3 -translate-y-1/2 whitespace-nowrap text-[var(--font-size-xs)] text-muted-foreground opacity-0 transition-opacity group-hover:opacity-100",
38
38
  children: formatTime$1(timestamp)
39
39
  }) : null, /* @__PURE__ */ jsx("div", {
40
- className: "whitespace-pre-wrap text-[var(--font-size-base)] leading-[1.5] text-foreground",
40
+ className: "break-words whitespace-pre-wrap text-[var(--font-size-base)] leading-[1.5] text-foreground",
41
41
  children: text
42
42
  })]
43
43
  }), actions ? /* @__PURE__ */ jsx("div", {
package/dist/chat.d.ts CHANGED
@@ -1,2 +1,2 @@
1
- import { _ as UserMessageProps, a as AgentTimelineMessageItem, b as ChatContainer, c as AgentTimelineTone, d as ThinkingIndicator, f as ThinkingIndicatorProps, g as UserMessage, h as MessageRole, i as AgentTimelineItem, l as AgentTimelineToolGroupItem, m as ChatMessageProps, n as AgentTimelineArtifactItem, o as AgentTimelineProps, p as ChatMessage, r as AgentTimelineCustomItem, s as AgentTimelineStatusItem, t as AgentTimeline, u as AgentTimelineToolItem, v as MessageList, x as ChatContainerProps, y as MessageListProps } from "./index-CUhfHT_V.js";
1
+ import { _ as UserMessageProps, a as AgentTimelineMessageItem, b as ChatContainer, c as AgentTimelineTone, d as ThinkingIndicator, f as ThinkingIndicatorProps, g as UserMessage, h as MessageRole, i as AgentTimelineItem, l as AgentTimelineToolGroupItem, m as ChatMessageProps, n as AgentTimelineArtifactItem, o as AgentTimelineProps, p as ChatMessage, r as AgentTimelineCustomItem, s as AgentTimelineStatusItem, t as AgentTimeline, u as AgentTimelineToolItem, v as MessageList, x as ChatContainerProps, y as MessageListProps } from "./index-D-9c3r-Y.js";
2
2
  export { AgentTimeline, type AgentTimelineArtifactItem, type AgentTimelineCustomItem, type AgentTimelineItem, type AgentTimelineMessageItem, type AgentTimelineProps, type AgentTimelineStatusItem, type AgentTimelineTone, type AgentTimelineToolGroupItem, type AgentTimelineToolItem, ChatContainer, type ChatContainerProps, ChatMessage, type ChatMessageProps, MessageList, type MessageListProps, type MessageRole, ThinkingIndicator, type ThinkingIndicatorProps, UserMessage, type UserMessageProps };
package/dist/chat.js CHANGED
@@ -1,2 +1,2 @@
1
- import { a as MessageList, i as ThinkingIndicator, n as ChatContainer, o as UserMessage, r as AgentTimeline, t as ChatMessage } from "./chat-BUJhNpx2.js";
1
+ import { a as MessageList, i as ThinkingIndicator, n as ChatContainer, o as UserMessage, r as AgentTimeline, t as ChatMessage } from "./chat-DXidmE_w.js";
2
2
  export { AgentTimeline, ChatContainer, ChatMessage, MessageList, ThinkingIndicator, UserMessage };
@@ -3,7 +3,7 @@ import { i as focusRing } from "./focus-BcE_SHqz.js";
3
3
  import { t as cn } from "./utils-C_uf36nf.js";
4
4
  import { i as TabsTrigger, n as TabsContent, r as TabsList, t as Tabs } from "./tabs-BVHR6NkO.js";
5
5
  import { t as ArtifactPane } from "./artifact-pane-DMXT9a8U.js";
6
- import { t as Markdown } from "./markdown-BGqicV82.js";
6
+ import { t as Markdown } from "./markdown-PywkQXWk.js";
7
7
  import { Suspense, createContext, lazy, useCallback, useContext, useEffect, useMemo, useRef, useState } from "react";
8
8
  import { jsx, jsxs } from "react/jsx-runtime";
9
9
  import { PencilLine, Save, Users, Wifi, WifiOff } from "lucide-react";
package/dist/editor.js CHANGED
@@ -1,2 +1,2 @@
1
- import { a as useCollaborators, c as useYjsState, d as EditorToolbar, f as EditorProvider, i as useCollaboratorPresence, l as CollaboratorsList, o as useDocumentChanges, p as useEditorContext, r as useAwareness, s as useEditorConnection, t as DocumentEditorPane, u as TiptapEditor } from "./document-editor-pane-LyanNypc.js";
1
+ import { a as useCollaborators, c as useYjsState, d as EditorToolbar, f as EditorProvider, i as useCollaboratorPresence, l as CollaboratorsList, o as useDocumentChanges, p as useEditorContext, r as useAwareness, s as useEditorConnection, t as DocumentEditorPane, u as TiptapEditor } from "./document-editor-pane-DrjsLZ3a.js";
2
2
  export { CollaboratorsList, DocumentEditorPane, EditorProvider, EditorToolbar, TiptapEditor, useAwareness, useCollaboratorPresence, useCollaborators, useDocumentChanges, useEditorConnection, useEditorContext, useYjsState };
@@ -5,7 +5,7 @@ import { t as ArtifactPane } from "./artifact-pane-DMXT9a8U.js";
5
5
  import { n as CopyButton, t as CodeBlock } from "./code-block-B36KVUSN.js";
6
6
  import { t as formatBytes } from "./format-DfcLWqMa.js";
7
7
  import { i as getFormatLabel, n as fileExtension, o as resolveFilePreviewKind, r as getCodeLanguage, t as detectFileFormat } from "./file-format-BgXbr-Ib.js";
8
- import { t as Markdown } from "./markdown-BGqicV82.js";
8
+ import { t as Markdown } from "./markdown-PywkQXWk.js";
9
9
  import { Suspense, lazy, useEffect, useMemo, useState } from "react";
10
10
  import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
11
11
  import { ChevronRight, Download, File, FileCode, FileImage, FileJson, FileSpreadsheet, FileText, Folder, FolderOpen, Music, X } from "lucide-react";
@@ -647,7 +647,7 @@ function FileTabs({ tabs, activeId, onSelect, onClose, className }) {
647
647
  //#endregion
648
648
  //#region src/files/file-artifact-pane.tsx
649
649
  const LazyDocumentEditorPane = lazy(async () => {
650
- return { default: (await import("./document-editor-pane-LyanNypc.js").then((n) => n.n)).DocumentEditorPane };
650
+ return { default: (await import("./document-editor-pane-DrjsLZ3a.js").then((n) => n.n)).DocumentEditorPane };
651
651
  });
652
652
  /**
653
653
  * FileArtifactPane — opinionated artifact frame for file previews with tabs and
package/dist/files.js CHANGED
@@ -1,3 +1,3 @@
1
1
  import { a as getSyntaxLanguage, i as getFormatLabel, n as fileExtension, o as resolveFilePreviewKind, r as getCodeLanguage, t as detectFileFormat } from "./file-format-BgXbr-Ib.js";
2
- import { a as parseCsv, c as filterFileTree, i as FilePreview, n as FileTabs, o as RichFileTree, r as CSV_PREVIEW_ROW_LIMIT, s as FileTree, t as FileArtifactPane } from "./files-DgPc3vI2.js";
2
+ import { a as parseCsv, c as filterFileTree, i as FilePreview, n as FileTabs, o as RichFileTree, r as CSV_PREVIEW_ROW_LIMIT, s as FileTree, t as FileArtifactPane } from "./files-DDpeW_nO.js";
3
3
  export { CSV_PREVIEW_ROW_LIMIT, FileArtifactPane, FilePreview, FileTabs, FileTree, RichFileTree, detectFileFormat, fileExtension, filterFileTree, getCodeLanguage, getFormatLabel, getSyntaxLanguage, parseCsv, resolveFilePreviewKind };
package/dist/hooks.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import { n as useRunCollapseState, r as useRunGroups, t as useAutoScroll } from "./use-auto-scroll-C5Pjeqon.js";
2
- import { a as useToolCallStream, i as useRealtimeSession, n as useSdkSession, o as useDropdownMenu, r as RealtimeSessionRegistry, t as useSSEStream } from "./use-sse-stream-BVgO1QBN.js";
2
+ import { a as useToolCallStream, i as useRealtimeSession, n as useSdkSession, o as useDropdownMenu, r as RealtimeSessionRegistry, t as useSSEStream } from "./use-sse-stream-OOPpkt_E.js";
3
3
  import * as React from "react";
4
4
  //#region src/hooks/use-live-time.ts
5
5
  /**
@@ -3,7 +3,7 @@ import { i as ToolPart, n as SessionPart } from "./parts-5mhy9yJ3.js";
3
3
  import { t as AgentBranding } from "./branding-26d5ARIr.js";
4
4
  import { t as CustomToolRenderer } from "./tool-display-DgmL5rIU.js";
5
5
  import { a as Run, n as GroupedMessage } from "./run-OyWmIDqu.js";
6
- import { t as OpenUIAction } from "./openui-artifact-renderer-D3E5bIAI.js";
6
+ import { t as OpenUIAction } from "./openui-artifact-renderer-fkBQaoLO.js";
7
7
  import { n as ToolCallData } from "./tool-call-feed-BeB1_4pX.js";
8
8
  import { ReactNode } from "react";
9
9
  //#region src/chat/chat-container.d.ts
@@ -87,8 +87,8 @@ interface UserMessageProps {
87
87
  actions?: ReactNode;
88
88
  }
89
89
  /**
90
- * The single user message bubble — a quiet, right-aligned fill on the muted
91
- * surface (no border, no loud fill, no uppercase label). The timestamp sits
90
+ * The single user message bubble — a quiet, right-aligned card with a subtle
91
+ * semantic border (no loud fill, no uppercase label). The timestamp sits
92
92
  * beside the bubble and appears on hover, so it costs no height. Used by both
93
93
  * the run/message list (session-model `parts`) and AgentTimeline (direct
94
94
  * `content`/`timestamp`).
package/dist/index.d.ts CHANGED
@@ -5,8 +5,9 @@ import { a as ToolState, i as ToolPart, n as SessionPart, o as ToolStatus, r as
5
5
  import { t as AgentBranding } from "./branding-26d5ARIr.js";
6
6
  import { n as DisplayVariant, r as ToolDisplayMetadata, t as CustomToolRenderer } from "./tool-display-DgmL5rIU.js";
7
7
  import { a as Run, i as MessageUser, n as GroupedMessage, o as RunStats, r as MessageRun, s as ToolCategory, t as FinalTextPart } from "./run-OyWmIDqu.js";
8
- import { _ as OpenUITableNode, a as OpenUIBadgeNode, c as OpenUIComponentNode, d as OpenUIKeyValueNode, f as OpenUIMarkdownNode, g as OpenUIStatNode, h as OpenUIStackNode, i as OpenUIArtifactRendererProps, l as OpenUIGridNode, m as OpenUISeparatorNode, n as OpenUIActionsNode, o as OpenUICardNode, p as OpenUIPrimitive, r as OpenUIArtifactRenderer, s as OpenUICodeNode, t as OpenUIAction, u as OpenUIHeadingNode, v as OpenUITextNode } from "./openui-artifact-renderer-D3E5bIAI.js";
9
- import { _ as UserMessageProps, a as AgentTimelineMessageItem, b as ChatContainer, c as AgentTimelineTone, d as ThinkingIndicator, f as ThinkingIndicatorProps, g as UserMessage, h as MessageRole, i as AgentTimelineItem, l as AgentTimelineToolGroupItem, m as ChatMessageProps, n as AgentTimelineArtifactItem, o as AgentTimelineProps, p as ChatMessage, r as AgentTimelineCustomItem, s as AgentTimelineStatusItem, t as AgentTimeline, u as AgentTimelineToolItem, v as MessageList, x as ChatContainerProps, y as MessageListProps } from "./index-CUhfHT_V.js";
8
+ import { n as MarkdownProps, r as getSanitizedMarkdownHeadingIdFromRawFragment, t as Markdown } from "./markdown-C0atSabr.js";
9
+ import { _ as OpenUITableNode, a as OpenUIBadgeNode, c as OpenUIComponentNode, d as OpenUIKeyValueNode, f as OpenUIMarkdownNode, g as OpenUIStatNode, h as OpenUIStackNode, i as OpenUIArtifactRendererProps, l as OpenUIGridNode, m as OpenUISeparatorNode, n as OpenUIActionsNode, o as OpenUICardNode, p as OpenUIPrimitive, r as OpenUIArtifactRenderer, s as OpenUICodeNode, t as OpenUIAction, u as OpenUIHeadingNode, v as OpenUITextNode } from "./openui-artifact-renderer-fkBQaoLO.js";
10
+ import { _ as UserMessageProps, a as AgentTimelineMessageItem, b as ChatContainer, c as AgentTimelineTone, d as ThinkingIndicator, f as ThinkingIndicatorProps, g as UserMessage, h as MessageRole, i as AgentTimelineItem, l as AgentTimelineToolGroupItem, m as ChatMessageProps, n as AgentTimelineArtifactItem, o as AgentTimelineProps, p as ChatMessage, r as AgentTimelineCustomItem, s as AgentTimelineStatusItem, t as AgentTimeline, u as AgentTimelineToolItem, v as MessageList, x as ChatContainerProps, y as MessageListProps } from "./index-D-9c3r-Y.js";
10
11
  import { a as parseToolEvent, i as ToolCallFeedProps, n as ToolCallData, o as ToolCallStatus, r as ToolCallFeed, s as ToolCallType, t as FeedSegment } from "./tool-call-feed-BeB1_4pX.js";
11
12
  import { n as ArtifactPaneProps, t as ArtifactPane } from "./artifact-pane-BL_DFWNl.js";
12
13
  import { C as FileNode, D as filterFileTree, E as FileTreeVisibilityOptions, S as RichFileTreeThemeVars, T as FileTreeProps, _ as parseCsv, a as getCodeLanguage, b as RichFileTreeGitStatus, c as resolveFilePreviewKind, d as FileTabData, f as FileTabs, g as FilePreviewProps, h as FilePreview, i as fileExtension, l as FileArtifactPane, m as CSV_PREVIEW_ROW_LIMIT, n as FilePreviewKind, o as getFormatLabel, p as FileTabsProps, r as detectFileFormat, s as getSyntaxLanguage, t as FileFormat, u as FileArtifactPaneProps, v as RichFileTree, w as FileTree, x as RichFileTreeProps, y as RichFileTreeGitEntry } from "./index-CyGSLGVF.js";
@@ -16,12 +17,12 @@ import { AuthUser, UseAuthOptions, UseAuthResult, createAuthFetcher, useApiKey,
16
17
  import { $ as TabsList, $t as DialogTrigger, A as TerminalInput, At as DropdownMenuSub, B as useToast, Bt as Input, C as UploadFile, Ct as DropdownMenuItem, D as DropZoneProps, Dt as DropdownMenuRadioItem, E as DropZone, Et as DropdownMenuRadioGroup, F as EmptyStateProps, Ft as AvatarFallback, G as SkeletonTable, Gt as DialogClose, H as TextShimmerProps, Ht as Textarea, I as Label, It as AvatarImage, J as SegmentedControl, Jt as DialogFooter, K as Switch, Kt as DialogContent, L as Toast, Lt as Badge, M as StatCard, Mt as DropdownMenuSubTrigger, N as StatCardProps, Nt as DropdownMenuTrigger, O as TerminalCursor, Ot as DropdownMenuSeparator, P as EmptyState, Pt as Avatar, Q as TabsContent, Qt as DialogTitle, R as ToastContainer, Rt as BadgeProps, S as SidebarDropZoneProps, St as DropdownMenuGroup, T as UploadProgressProps, Tt as DropdownMenuPortal, U as Skeleton, Ut as TextareaProps, V as TextShimmer, Vt as InputProps, W as SkeletonCard, Wt as Dialog, X as SegmentedControlProps, Xt as DialogOverlay, Y as SegmentedControlOption, Yt as DialogHeader, Z as Tabs, Zt as DialogPortal, _ as ThemeToggle, _t as SelectTrigger, a as FilterFieldProps, an as CardTitle, at as TableFooter, b as InlineCodeProps, bt as DropdownMenuCheckboxItem, c as Metric, ct as TableRow, d as MetricStripProps, dt as SelectGroup, en as Card, et as TabsTrigger, f as StatusPill, ft as SelectItem, g as PageHeaderProps, gt as SelectSeparator, h as PageHeader, ht as SelectScrollUpButton, i as FilterField, in as CardHeader, it as TableCell, j as TerminalLine, jt as DropdownMenuSubContent, k as TerminalDisplay, kt as DropdownMenuShortcut, l as MetricProps, lt as Select, m as StatusTone, mt as SelectScrollDownButton, n as LogoProps, nn as CardDescription, nt as TableBody, o as Toolbar, ot as TableHead, p as StatusPillProps, pt as SelectLabel, q as Progress, qt as DialogDescription, r as TangleKnot, rn as CardFooter, rt as TableCaption, s as ToolbarProps, st as TableHeader, t as Logo, tn as CardContent, tt as Table, u as MetricStrip, ut as SelectContent, v as useTheme, vt as SelectValue, w as UploadProgress, wt as DropdownMenuLabel, x as SidebarDropZone, xt as DropdownMenuContent, y as InlineCode, yt as DropdownMenu, z as ToastProvider, zt as badgeVariants } from "./index-CPDET_s1.js";
17
18
  import { n as CodeBlockProps, r as CopyButton, t as CodeBlock } from "./code-block-B9miUPht.js";
18
19
  import { a as InlineThinkingItemProps, c as RunRowShell, d as RunRowStatusDot, f as RunGroup, i as InlineThinkingItem, l as RunRowShellProps, n as ExpandedToolDetail, o as InlineToolItem, p as RunGroupProps, r as ExpandedToolDetailProps, s as InlineToolItemProps, t as LiveDuration, u as RunRowStatus } from "./index-DjKxO357.js";
19
- import { a as validateOpenUIJsonNode, i as validateOpenUIJsonArtifact, n as OpenUISchemaValidation, o as OPENUI_NODE_JSON_SCHEMA, r as findUnsupportedOpenUINode, s as OPENUI_NODE_TYPES, t as OpenUISchemaIssue } from "./schema-BFKgCGH-.js";
20
+ import { a as validateOpenUIJsonNode, i as validateOpenUIJsonArtifact, n as OpenUISchemaValidation, o as OPENUI_NODE_JSON_SCHEMA, r as findUnsupportedOpenUINode, s as OPENUI_NODE_TYPES, t as OpenUISchemaIssue } from "./schema-DAstk-J4.js";
20
21
  import "./openui.js";
21
- import { n as MarkdownProps, t as Markdown } from "./index-Cq-EJzqW.js";
22
+ import "./markdown.js";
22
23
  import { addMessage, addParts, clearChat, isStreamingAtom, messagesAtom, partMapAtom, updatePart } from "./stores.js";
23
24
  import "./types.js";
24
25
  import { a as focusRingInset, c as getToolCategory, d as timeAgo, f as formatBytes, g as copyText, h as truncateText, i as focusRing, l as getToolDisplayMetadata, m as formatUptime, n as focusFieldInvalid, o as cn, p as formatDuration, r as focusFieldWithin, s as TOOL_CATEGORY_ICONS, t as focusField, u as getToolErrorText } from "./index-BgUHilZm.js";
25
26
  import { a as WebSearchPreview, c as GlobResultsPreviewProps, d as WriteFilePreview, f as WriteFilePreviewProps, i as QuestionPreviewProps, l as GrepResultsPreview, m as CommandPreviewProps, n as DiffPreviewProps, o as WebSearchPreviewProps, p as CommandPreview, r as QuestionPreview, s as GlobResultsPreview, t as DiffPreview, u as GrepResultsPreviewProps } from "./index-2UntyjBb.js";
26
27
  import { a as RevealResult, i as RedactedDocumentProps, n as RedactedDocument, r as RedactedDocumentData, t as RedactedDocSegment } from "./index-COgqsFAQ.js";
27
- export { ActiveProjectActivity, ActiveSessionActivityOptions, ActiveSessionConnectionOptions, ActiveSessionConnectionState, ActiveSessionReconnectState, ActiveSessionRecord, ActiveSessionStatus, ActiveSessionTransportMode, ActiveSessionsState, AgentBranding, AgentStreamEvent, AgentTimeline, type AgentTimelineArtifactItem, type AgentTimelineCustomItem, type AgentTimelineItem, type AgentTimelineMessageItem, type AgentTimelineProps, type AgentTimelineStatusItem, type AgentTimelineTone, type AgentTimelineToolGroupItem, type AgentTimelineToolItem, AppendUserMessageOptions, ApplySdkEventOptions, ArtifactPane, type ArtifactPaneProps, AuthHeader, type AuthHeaderProps, AuthUser, AutomationStreamEvent, Avatar, AvatarFallback, AvatarImage, Badge, type BadgeProps, BeginAssistantMessageOptions, BotStreamEvent, Button, type ButtonProps, CSV_PREVIEW_ROW_LIMIT, Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle, ChatContainer, type ChatContainerProps, ChatMessage, type ChatMessageProps, CodeBlock, type CodeBlockProps, CommandPreview, type CommandPreviewProps, CompleteAssistantMessageOptions, ConnectionState, CopyButton, CustomToolRenderer, Dialog, DialogClose, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogOverlay, DialogPortal, DialogTitle, DialogTrigger, DiffPreview, type DiffPreviewProps, DisplayVariant, DropZone, type DropZoneProps, DropdownMenu, DropdownMenuCheckboxItem, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuLabel, DropdownMenuPortal, DropdownMenuRadioGroup, DropdownMenuRadioItem, DropdownMenuSeparator, DropdownMenuShortcut, DropdownMenuSub, DropdownMenuSubContent, DropdownMenuSubTrigger, DropdownMenuTrigger, EmptyState, type EmptyStateProps, ExpandedToolDetail, type ExpandedToolDetailProps, type FeedSegment, FileArtifactPane, type FileArtifactPaneProps, type FileFormat, type FileNode, FilePreview, type FilePreviewKind, type FilePreviewProps, type FileTabData, FileTabs, type FileTabsProps, FileTree, type FileTreeProps, type FileTreeVisibilityOptions, FilterField, type FilterFieldProps, FinalTextPart, GitHubLoginButton, type GitHubLoginButtonProps, GlobResultsPreview, type GlobResultsPreviewProps, GrepResultsPreview, type GrepResultsPreviewProps, GroupedMessage, InlineCode, type InlineCodeProps, InlineThinkingItem, type InlineThinkingItemProps, InlineToolItem, type InlineToolItemProps, Input, type InputProps, Label, LiveDuration, LoginLayout, type LoginLayoutProps, Logo, type LogoProps, Markdown, type MarkdownProps, MessageList, type MessageListProps, type MessageRole, MessageRun, MessageUser, Metric, type MetricProps, MetricStrip, type MetricStripProps, OPENUI_NODE_JSON_SCHEMA, OPENUI_NODE_TYPES, type OpenUIAction, type OpenUIActionsNode, OpenUIArtifactRenderer, type OpenUIArtifactRendererProps, type OpenUIBadgeNode, type OpenUICardNode, type OpenUICodeNode, type OpenUIComponentNode, type OpenUIGridNode, type OpenUIHeadingNode, type OpenUIKeyValueNode, type OpenUIMarkdownNode, type OpenUIPrimitive, type OpenUISchemaIssue, type OpenUISchemaValidation, type OpenUISeparatorNode, type OpenUIStackNode, type OpenUIStatNode, type OpenUITableNode, type OpenUITextNode, PageHeader, type PageHeaderProps, Progress, QuestionPreview, type QuestionPreviewProps, RealtimeSessionOptions, RealtimeSessionRegistry, RealtimeSessionRegistryProps, RealtimeSessionState, RealtimeSessionTarget, ReasoningPart, type RedactedDocSegment, RedactedDocument, type RedactedDocumentData, type RedactedDocumentProps, RegisterActiveSessionOptions, type RevealResult, RichFileTree, type RichFileTreeGitEntry, type RichFileTreeGitStatus, type RichFileTreeProps, type RichFileTreeThemeVars, Run, RunGroup, type RunGroupProps, RunRowShell, type RunRowShellProps, type RunRowStatus, RunRowStatusDot, RunStats, SSEEvent, SdkSessionAttachment, SdkSessionEvent, SdkSessionSeed, SegmentedControl, type SegmentedControlOption, type SegmentedControlProps, Select, SelectContent, SelectGroup, SelectItem, SelectLabel, SelectScrollDownButton, SelectScrollUpButton, SelectSeparator, SelectTrigger, SelectValue, SessionMessage, SessionPart, SessionProjectKey, type SessionUser, SidebarDropZone, type SidebarDropZoneProps, Skeleton, SkeletonCard, SkeletonTable, StatCard, type StatCardProps, StatusPill, type StatusPillProps, type StatusTone, Switch, TOOL_CATEGORY_ICONS, Table, TableBody, TableCaption, TableCell, TableFooter, TableHead, TableHeader, TableRow, Tabs, TabsContent, TabsList, TabsTrigger, TangleKnot, TaskStreamEvent, TerminalCursor, TerminalDisplay, TerminalInput, TerminalLine, TerminalStreamEvent, TextPart, TextShimmer, type TextShimmerProps, Textarea, type TextareaProps, ThemeToggle, ThinkingIndicator, type ThinkingIndicatorProps, type Toast, ToastContainer, ToastProvider, type ToolCallData, ToolCallFeed, type ToolCallFeedProps, type ToolCallStatus, type ToolCallType, ToolCategory, ToolDisplayMetadata, ToolPart, ToolState, ToolStatus, ToolTime, Toolbar, type ToolbarProps, type UploadFile, UploadProgress, type UploadProgressProps, UseAuthOptions, UseAuthResult, UseRunGroupsOptions, UseSSEStreamOptions, UseSSEStreamResult, UseSdkSessionOptions, UseSdkSessionReturn, UseToolCallStreamReturn, UserMenu, type UserMenuProps, UserMessage, type UserMessageProps, WebSearchPreview, type WebSearchPreviewProps, WriteFilePreview, type WriteFilePreviewProps, activeSessionsAtom, addMessage, addParts, badgeVariants, bumpActiveSessionActivity, buttonVariants, clearChat, cn, copyText, createAuthFetcher, detectFileFormat, fileExtension, filterFileTree, findUnsupportedOpenUINode, focusField, focusFieldInvalid, focusFieldWithin, focusRing, focusRingInset, formatBytes, formatDuration, formatUptime, getActiveSession, getAllActiveSessions, getAllProjectActivity, getCodeLanguage, getFormatLabel, getSessionsByActivity, getSessionsForNavbar, getSessionsForProject, getSyntaxLanguage, getToolCategory, getToolDisplayMetadata, getToolErrorText, getTotalRunningSessionCount, hasBackgroundRunningSessions, isStreamingAtom, messagesAtom, parseCsv, parseToolEvent, partMapAtom, registerActiveSession, resetActiveSessions, resolveFilePreviewKind, setActiveSessionAttention, setActiveSessionConnection, setActiveSessionError, setActiveSessionRunning, setForegroundActiveSession, timeAgo, truncateText, unregisterActiveSession, updateActiveSessionMeta, updatePart, useActiveSession, useActiveSessions, useActiveSessionsState, useApiKey, useAuth, useAutoScroll, useDropdownMenu, useHasBackgroundRunningSessions, useLiveTime, useNavbarSessions, useProjectActivity, useProjectSessions, useRealtimeSession, useRunCollapseState, useRunGroups, useSSEStream, useSdkSession, useSessionsByActivity, useTheme, useToast, useToolCallStream, useTotalRunningSessions, validateOpenUIJsonArtifact, validateOpenUIJsonNode };
28
+ export { ActiveProjectActivity, ActiveSessionActivityOptions, ActiveSessionConnectionOptions, ActiveSessionConnectionState, ActiveSessionReconnectState, ActiveSessionRecord, ActiveSessionStatus, ActiveSessionTransportMode, ActiveSessionsState, AgentBranding, AgentStreamEvent, AgentTimeline, type AgentTimelineArtifactItem, type AgentTimelineCustomItem, type AgentTimelineItem, type AgentTimelineMessageItem, type AgentTimelineProps, type AgentTimelineStatusItem, type AgentTimelineTone, type AgentTimelineToolGroupItem, type AgentTimelineToolItem, AppendUserMessageOptions, ApplySdkEventOptions, ArtifactPane, type ArtifactPaneProps, AuthHeader, type AuthHeaderProps, AuthUser, AutomationStreamEvent, Avatar, AvatarFallback, AvatarImage, Badge, type BadgeProps, BeginAssistantMessageOptions, BotStreamEvent, Button, type ButtonProps, CSV_PREVIEW_ROW_LIMIT, Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle, ChatContainer, type ChatContainerProps, ChatMessage, type ChatMessageProps, CodeBlock, type CodeBlockProps, CommandPreview, type CommandPreviewProps, CompleteAssistantMessageOptions, ConnectionState, CopyButton, CustomToolRenderer, Dialog, DialogClose, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogOverlay, DialogPortal, DialogTitle, DialogTrigger, DiffPreview, type DiffPreviewProps, DisplayVariant, DropZone, type DropZoneProps, DropdownMenu, DropdownMenuCheckboxItem, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuLabel, DropdownMenuPortal, DropdownMenuRadioGroup, DropdownMenuRadioItem, DropdownMenuSeparator, DropdownMenuShortcut, DropdownMenuSub, DropdownMenuSubContent, DropdownMenuSubTrigger, DropdownMenuTrigger, EmptyState, type EmptyStateProps, ExpandedToolDetail, type ExpandedToolDetailProps, type FeedSegment, FileArtifactPane, type FileArtifactPaneProps, type FileFormat, type FileNode, FilePreview, type FilePreviewKind, type FilePreviewProps, type FileTabData, FileTabs, type FileTabsProps, FileTree, type FileTreeProps, type FileTreeVisibilityOptions, FilterField, type FilterFieldProps, FinalTextPart, GitHubLoginButton, type GitHubLoginButtonProps, GlobResultsPreview, type GlobResultsPreviewProps, GrepResultsPreview, type GrepResultsPreviewProps, GroupedMessage, InlineCode, type InlineCodeProps, InlineThinkingItem, type InlineThinkingItemProps, InlineToolItem, type InlineToolItemProps, Input, type InputProps, Label, LiveDuration, LoginLayout, type LoginLayoutProps, Logo, type LogoProps, Markdown, type MarkdownProps, MessageList, type MessageListProps, type MessageRole, MessageRun, MessageUser, Metric, type MetricProps, MetricStrip, type MetricStripProps, OPENUI_NODE_JSON_SCHEMA, OPENUI_NODE_TYPES, type OpenUIAction, type OpenUIActionsNode, OpenUIArtifactRenderer, type OpenUIArtifactRendererProps, type OpenUIBadgeNode, type OpenUICardNode, type OpenUICodeNode, type OpenUIComponentNode, type OpenUIGridNode, type OpenUIHeadingNode, type OpenUIKeyValueNode, type OpenUIMarkdownNode, type OpenUIPrimitive, type OpenUISchemaIssue, type OpenUISchemaValidation, type OpenUISeparatorNode, type OpenUIStackNode, type OpenUIStatNode, type OpenUITableNode, type OpenUITextNode, PageHeader, type PageHeaderProps, Progress, QuestionPreview, type QuestionPreviewProps, RealtimeSessionOptions, RealtimeSessionRegistry, RealtimeSessionRegistryProps, RealtimeSessionState, RealtimeSessionTarget, ReasoningPart, type RedactedDocSegment, RedactedDocument, type RedactedDocumentData, type RedactedDocumentProps, RegisterActiveSessionOptions, type RevealResult, RichFileTree, type RichFileTreeGitEntry, type RichFileTreeGitStatus, type RichFileTreeProps, type RichFileTreeThemeVars, Run, RunGroup, type RunGroupProps, RunRowShell, type RunRowShellProps, type RunRowStatus, RunRowStatusDot, RunStats, SSEEvent, SdkSessionAttachment, SdkSessionEvent, SdkSessionSeed, SegmentedControl, type SegmentedControlOption, type SegmentedControlProps, Select, SelectContent, SelectGroup, SelectItem, SelectLabel, SelectScrollDownButton, SelectScrollUpButton, SelectSeparator, SelectTrigger, SelectValue, SessionMessage, SessionPart, SessionProjectKey, type SessionUser, SidebarDropZone, type SidebarDropZoneProps, Skeleton, SkeletonCard, SkeletonTable, StatCard, type StatCardProps, StatusPill, type StatusPillProps, type StatusTone, Switch, TOOL_CATEGORY_ICONS, Table, TableBody, TableCaption, TableCell, TableFooter, TableHead, TableHeader, TableRow, Tabs, TabsContent, TabsList, TabsTrigger, TangleKnot, TaskStreamEvent, TerminalCursor, TerminalDisplay, TerminalInput, TerminalLine, TerminalStreamEvent, TextPart, TextShimmer, type TextShimmerProps, Textarea, type TextareaProps, ThemeToggle, ThinkingIndicator, type ThinkingIndicatorProps, type Toast, ToastContainer, ToastProvider, type ToolCallData, ToolCallFeed, type ToolCallFeedProps, type ToolCallStatus, type ToolCallType, ToolCategory, ToolDisplayMetadata, ToolPart, ToolState, ToolStatus, ToolTime, Toolbar, type ToolbarProps, type UploadFile, UploadProgress, type UploadProgressProps, UseAuthOptions, UseAuthResult, UseRunGroupsOptions, UseSSEStreamOptions, UseSSEStreamResult, UseSdkSessionOptions, UseSdkSessionReturn, UseToolCallStreamReturn, UserMenu, type UserMenuProps, UserMessage, type UserMessageProps, WebSearchPreview, type WebSearchPreviewProps, WriteFilePreview, type WriteFilePreviewProps, activeSessionsAtom, addMessage, addParts, badgeVariants, bumpActiveSessionActivity, buttonVariants, clearChat, cn, copyText, createAuthFetcher, detectFileFormat, fileExtension, filterFileTree, findUnsupportedOpenUINode, focusField, focusFieldInvalid, focusFieldWithin, focusRing, focusRingInset, formatBytes, formatDuration, formatUptime, getActiveSession, getAllActiveSessions, getAllProjectActivity, getCodeLanguage, getFormatLabel, getSanitizedMarkdownHeadingIdFromRawFragment, getSessionsByActivity, getSessionsForNavbar, getSessionsForProject, getSyntaxLanguage, getToolCategory, getToolDisplayMetadata, getToolErrorText, getTotalRunningSessionCount, hasBackgroundRunningSessions, isStreamingAtom, messagesAtom, parseCsv, parseToolEvent, partMapAtom, registerActiveSession, resetActiveSessions, resolveFilePreviewKind, setActiveSessionAttention, setActiveSessionConnection, setActiveSessionError, setActiveSessionRunning, setForegroundActiveSession, timeAgo, truncateText, unregisterActiveSession, updateActiveSessionMeta, updatePart, useActiveSession, useActiveSessions, useActiveSessionsState, useApiKey, useAuth, useAutoScroll, useDropdownMenu, useHasBackgroundRunningSessions, useLiveTime, useNavbarSessions, useProjectActivity, useProjectSessions, useRealtimeSession, useRunCollapseState, useRunGroups, useSSEStream, useSdkSession, useSessionsByActivity, useTheme, useToast, useToolCallStream, useTotalRunningSessions, validateOpenUIJsonArtifact, validateOpenUIJsonNode };
package/dist/index.js CHANGED
@@ -15,17 +15,17 @@ import { i as truncateText, n as formatDuration, r as formatUptime, t as formatB
15
15
  import { a as GrepResultsPreview, i as GlobResultsPreview, n as QuestionPreview, o as WriteFilePreview, r as WebSearchPreview, s as CommandPreview, t as DiffPreview } from "./diff-preview-BcK3nRXb.js";
16
16
  import { a as getSyntaxLanguage, i as getFormatLabel, n as fileExtension, o as resolveFilePreviewKind, r as getCodeLanguage, t as detectFileFormat } from "./file-format-BgXbr-Ib.js";
17
17
  import { a as RunRowStatusDot, i as RunRowShell, o as ExpandedToolDetail, r as InlineToolItem } from "./tool-call-step-DNebqhmX.js";
18
- import { t as Markdown } from "./markdown-BGqicV82.js";
19
- import { n as InlineThinkingItem, t as RunGroup } from "./run-group-CxNskmHd.js";
20
- import { t as OpenUIArtifactRenderer } from "./openui-artifact-renderer-C3bmqfjX.js";
21
- import { a as MessageList, i as ThinkingIndicator, n as ChatContainer, o as UserMessage, r as AgentTimeline, t as ChatMessage } from "./chat-BUJhNpx2.js";
18
+ import { n as getSanitizedMarkdownHeadingIdFromRawFragment, t as Markdown } from "./markdown-PywkQXWk.js";
19
+ import { n as InlineThinkingItem, t as RunGroup } from "./run-group-COUIsZ_x.js";
20
+ import { t as OpenUIArtifactRenderer } from "./openui-artifact-renderer-DjLPuaP9.js";
21
+ import { a as MessageList, i as ThinkingIndicator, n as ChatContainer, o as UserMessage, r as AgentTimeline, t as ChatMessage } from "./chat-DXidmE_w.js";
22
22
  import { t as LiveDuration } from "./run-ZsIKPA6J.js";
23
- import { n as parseToolEvent, t as ToolCallFeed } from "./tool-call-feed-Djt2q11V.js";
23
+ import { n as parseToolEvent, t as ToolCallFeed } from "./tool-call-feed-DNADpFyJ.js";
24
24
  import "./openui.js";
25
- import { a as parseCsv, c as filterFileTree, i as FilePreview, n as FileTabs, o as RichFileTree, r as CSV_PREVIEW_ROW_LIMIT, s as FileTree, t as FileArtifactPane } from "./files-DgPc3vI2.js";
25
+ import { a as parseCsv, c as filterFileTree, i as FilePreview, n as FileTabs, o as RichFileTree, r as CSV_PREVIEW_ROW_LIMIT, s as FileTree, t as FileArtifactPane } from "./files-DDpeW_nO.js";
26
26
  import "./markdown.js";
27
27
  import { i as UserMenu, n as AuthHeader, r as GitHubLoginButton, t as LoginLayout } from "./auth-DOETfnd9.js";
28
- import { a as useToolCallStream, i as useRealtimeSession, n as useSdkSession, o as useDropdownMenu, r as RealtimeSessionRegistry, t as useSSEStream } from "./use-sse-stream-BVgO1QBN.js";
28
+ import { a as useToolCallStream, i as useRealtimeSession, n as useSdkSession, o as useDropdownMenu, r as RealtimeSessionRegistry, t as useSSEStream } from "./use-sse-stream-OOPpkt_E.js";
29
29
  import { C as useHasBackgroundRunningSessions, D as useSessionsByActivity, E as useProjectSessions, O as useTotalRunningSessions, S as useActiveSessionsState, T as useProjectActivity, _ as setForegroundActiveSession, a as getAllProjectActivity, b as useActiveSession, c as getSessionsForProject, d as registerActiveSession, f as resetActiveSessions, g as setActiveSessionRunning, h as setActiveSessionError, i as getAllActiveSessions, l as getTotalRunningSessionCount, m as setActiveSessionConnection, n as bumpActiveSessionActivity, o as getSessionsByActivity, p as setActiveSessionAttention, r as getActiveSession, s as getSessionsForNavbar, t as activeSessionsAtom, u as hasBackgroundRunningSessions, v as unregisterActiveSession, w as useNavbarSessions, x as useActiveSessions, y as updateActiveSessionMeta } from "./active-sessions-store-Gt1R0rFG.js";
30
30
  import { createAuthFetcher, useApiKey, useAuth, useLiveTime } from "./hooks.js";
31
31
  import { addMessage, addParts, clearChat, isStreamingAtom, messagesAtom, partMapAtom, updatePart } from "./stores.js";
@@ -33,4 +33,4 @@ import "./types.js";
33
33
  import { n as copyText, t as timeAgo } from "./utils-Bl_CZ0Qp.js";
34
34
  import "./tool-previews.js";
35
35
  import { t as RedactedDocument } from "./redaction-CGGB2ENG.js";
36
- export { AgentTimeline, ArtifactPane, AuthHeader, Avatar, AvatarFallback, AvatarImage, Badge, Button, CSV_PREVIEW_ROW_LIMIT, Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle, ChatContainer, ChatMessage, CodeBlock, CommandPreview, CopyButton, Dialog, DialogClose, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogOverlay, DialogPortal, DialogTitle, DialogTrigger, DiffPreview, DropZone, DropdownMenu, DropdownMenuCheckboxItem, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuLabel, DropdownMenuPortal, DropdownMenuRadioGroup, DropdownMenuRadioItem, DropdownMenuSeparator, DropdownMenuShortcut, DropdownMenuSub, DropdownMenuSubContent, DropdownMenuSubTrigger, DropdownMenuTrigger, EmptyState, ExpandedToolDetail, FileArtifactPane, FilePreview, FileTabs, FileTree, FilterField, GitHubLoginButton, GlobResultsPreview, GrepResultsPreview, InlineCode, InlineThinkingItem, InlineToolItem, Input, Label, LiveDuration, LoginLayout, Logo, Markdown, MessageList, Metric, MetricStrip, OPENUI_NODE_JSON_SCHEMA, OPENUI_NODE_TYPES, OpenUIArtifactRenderer, PageHeader, Progress, QuestionPreview, RealtimeSessionRegistry, RedactedDocument, RichFileTree, RunGroup, RunRowShell, RunRowStatusDot, SegmentedControl, Select, SelectContent, SelectGroup, SelectItem, SelectLabel, SelectScrollDownButton, SelectScrollUpButton, SelectSeparator, SelectTrigger, SelectValue, SidebarDropZone, Skeleton, SkeletonCard, SkeletonTable, StatCard, StatusPill, Switch, TOOL_CATEGORY_ICONS, Table, TableBody, TableCaption, TableCell, TableFooter, TableHead, TableHeader, TableRow, Tabs, TabsContent, TabsList, TabsTrigger, TangleKnot, TerminalCursor, TerminalDisplay, TerminalInput, TerminalLine, TextShimmer, Textarea, ThemeToggle, ThinkingIndicator, ToastContainer, ToastProvider, ToolCallFeed, Toolbar, UploadProgress, UserMenu, UserMessage, WebSearchPreview, WriteFilePreview, activeSessionsAtom, addMessage, addParts, badgeVariants, bumpActiveSessionActivity, buttonVariants, clearChat, cn, copyText, createAuthFetcher, detectFileFormat, fileExtension, filterFileTree, findUnsupportedOpenUINode, focusField, focusFieldInvalid, focusFieldWithin, focusRing, focusRingInset, formatBytes, formatDuration, formatUptime, getActiveSession, getAllActiveSessions, getAllProjectActivity, getCodeLanguage, getFormatLabel, getSessionsByActivity, getSessionsForNavbar, getSessionsForProject, getSyntaxLanguage, getToolCategory, getToolDisplayMetadata, getToolErrorText, getTotalRunningSessionCount, hasBackgroundRunningSessions, isStreamingAtom, messagesAtom, parseCsv, parseToolEvent, partMapAtom, registerActiveSession, resetActiveSessions, resolveFilePreviewKind, setActiveSessionAttention, setActiveSessionConnection, setActiveSessionError, setActiveSessionRunning, setForegroundActiveSession, timeAgo, truncateText, unregisterActiveSession, updateActiveSessionMeta, updatePart, useActiveSession, useActiveSessions, useActiveSessionsState, useApiKey, useAuth, useAutoScroll, useDropdownMenu, useHasBackgroundRunningSessions, useLiveTime, useNavbarSessions, useProjectActivity, useProjectSessions, useRealtimeSession, useRunCollapseState, useRunGroups, useSSEStream, useSdkSession, useSessionsByActivity, useTheme, useToast, useToolCallStream, useTotalRunningSessions, validateOpenUIJsonArtifact, validateOpenUIJsonNode };
36
+ export { AgentTimeline, ArtifactPane, AuthHeader, Avatar, AvatarFallback, AvatarImage, Badge, Button, CSV_PREVIEW_ROW_LIMIT, Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle, ChatContainer, ChatMessage, CodeBlock, CommandPreview, CopyButton, Dialog, DialogClose, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogOverlay, DialogPortal, DialogTitle, DialogTrigger, DiffPreview, DropZone, DropdownMenu, DropdownMenuCheckboxItem, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuLabel, DropdownMenuPortal, DropdownMenuRadioGroup, DropdownMenuRadioItem, DropdownMenuSeparator, DropdownMenuShortcut, DropdownMenuSub, DropdownMenuSubContent, DropdownMenuSubTrigger, DropdownMenuTrigger, EmptyState, ExpandedToolDetail, FileArtifactPane, FilePreview, FileTabs, FileTree, FilterField, GitHubLoginButton, GlobResultsPreview, GrepResultsPreview, InlineCode, InlineThinkingItem, InlineToolItem, Input, Label, LiveDuration, LoginLayout, Logo, Markdown, MessageList, Metric, MetricStrip, OPENUI_NODE_JSON_SCHEMA, OPENUI_NODE_TYPES, OpenUIArtifactRenderer, PageHeader, Progress, QuestionPreview, RealtimeSessionRegistry, RedactedDocument, RichFileTree, RunGroup, RunRowShell, RunRowStatusDot, SegmentedControl, Select, SelectContent, SelectGroup, SelectItem, SelectLabel, SelectScrollDownButton, SelectScrollUpButton, SelectSeparator, SelectTrigger, SelectValue, SidebarDropZone, Skeleton, SkeletonCard, SkeletonTable, StatCard, StatusPill, Switch, TOOL_CATEGORY_ICONS, Table, TableBody, TableCaption, TableCell, TableFooter, TableHead, TableHeader, TableRow, Tabs, TabsContent, TabsList, TabsTrigger, TangleKnot, TerminalCursor, TerminalDisplay, TerminalInput, TerminalLine, TextShimmer, Textarea, ThemeToggle, ThinkingIndicator, ToastContainer, ToastProvider, ToolCallFeed, Toolbar, UploadProgress, UserMenu, UserMessage, WebSearchPreview, WriteFilePreview, activeSessionsAtom, addMessage, addParts, badgeVariants, bumpActiveSessionActivity, buttonVariants, clearChat, cn, copyText, createAuthFetcher, detectFileFormat, fileExtension, filterFileTree, findUnsupportedOpenUINode, focusField, focusFieldInvalid, focusFieldWithin, focusRing, focusRingInset, formatBytes, formatDuration, formatUptime, getActiveSession, getAllActiveSessions, getAllProjectActivity, getCodeLanguage, getFormatLabel, getSanitizedMarkdownHeadingIdFromRawFragment, getSessionsByActivity, getSessionsForNavbar, getSessionsForProject, getSyntaxLanguage, getToolCategory, getToolDisplayMetadata, getToolErrorText, getTotalRunningSessionCount, hasBackgroundRunningSessions, isStreamingAtom, messagesAtom, parseCsv, parseToolEvent, partMapAtom, registerActiveSession, resetActiveSessions, resolveFilePreviewKind, setActiveSessionAttention, setActiveSessionConnection, setActiveSessionError, setActiveSessionRunning, setForegroundActiveSession, timeAgo, truncateText, unregisterActiveSession, updateActiveSessionMeta, updatePart, useActiveSession, useActiveSessions, useActiveSessionsState, useApiKey, useAuth, useAutoScroll, useDropdownMenu, useHasBackgroundRunningSessions, useLiveTime, useNavbarSessions, useProjectActivity, useProjectSessions, useRealtimeSession, useRunCollapseState, useRunGroups, useSSEStream, useSdkSession, useSessionsByActivity, useTheme, useToast, useToolCallStream, useTotalRunningSessions, validateOpenUIJsonArtifact, validateOpenUIJsonNode };
@@ -1,10 +1,11 @@
1
- import "./code-block-B9miUPht.js";
2
1
  import { UrlTransform } from "react-markdown";
3
2
  //#region src/markdown/markdown.d.ts
3
+ /** Converts a raw Markdown fragment to the ID rehype-sanitize emits for its heading. */
4
+ declare function getSanitizedMarkdownHeadingIdFromRawFragment(rawFragment: string): string;
4
5
  interface MarkdownProps {
5
6
  children: string;
6
7
  className?: string;
7
- /** Transform parsed link and image URLs before sanitisation. */
8
+ /** Transform parsed link and image URLs while retaining protocol safety checks. */
8
9
  urlTransform?: UrlTransform;
9
10
  }
10
11
  /**
@@ -13,4 +14,4 @@ interface MarkdownProps {
13
14
  */
14
15
  declare const Markdown: import("react").MemoExoticComponent<({ children, className, urlTransform }: MarkdownProps) => import("react").JSX.Element>;
15
16
  //#endregion
16
- export { MarkdownProps as n, Markdown as t };
17
+ export { MarkdownProps as n, getSanitizedMarkdownHeadingIdFromRawFragment as r, Markdown as t };
@@ -2,10 +2,31 @@ import { t as cn } from "./utils-C_uf36nf.js";
2
2
  import { n as CopyButton, t as CodeBlock } from "./code-block-B36KVUSN.js";
3
3
  import { memo } from "react";
4
4
  import { Fragment as Fragment$1, jsx } from "react/jsx-runtime";
5
- import ReactMarkdown from "react-markdown";
5
+ import ReactMarkdown, { defaultUrlTransform } from "react-markdown";
6
6
  import remarkGfm from "remark-gfm";
7
7
  import rehypeSanitize from "rehype-sanitize";
8
+ import rehypeSlug from "rehype-slug";
9
+ import GithubSlugger from "github-slugger";
8
10
  //#region src/markdown/markdown.tsx
11
+ const SANITIZED_HEADING_ID_PREFIX = "user-content-";
12
+ /** Converts a raw Markdown fragment to the ID rehype-sanitize emits for its heading. */
13
+ function getSanitizedMarkdownHeadingIdFromRawFragment(rawFragment) {
14
+ let decodedFragment = rawFragment;
15
+ try {
16
+ decodedFragment = decodeURIComponent(rawFragment);
17
+ } catch {}
18
+ const slugger = new GithubSlugger();
19
+ return SANITIZED_HEADING_ID_PREFIX + slugger.slug(decodedFragment);
20
+ }
21
+ function safeUrl(url) {
22
+ return defaultUrlTransform(url) ?? void 0;
23
+ }
24
+ function transformMarkdownUrl(url, key, node, urlTransform) {
25
+ const transformed = urlTransform ? urlTransform(url, key, node) : url;
26
+ if (transformed == null) return void 0;
27
+ if (key === "href" && transformed === url && url.startsWith("#")) return safeUrl("#" + getSanitizedMarkdownHeadingIdFromRawFragment(url.slice(1)));
28
+ return safeUrl(transformed);
29
+ }
9
30
  /**
10
31
  * Renders Markdown content with GFM support, XSS sanitisation, and
11
32
  * custom code block rendering via our CodeBlock component.
@@ -15,8 +36,8 @@ const Markdown = memo(({ children, className, urlTransform }) => {
15
36
  className: cn("tangle-prose max-w-none text-sm", className),
16
37
  children: /* @__PURE__ */ jsx(ReactMarkdown, {
17
38
  remarkPlugins: [remarkGfm],
18
- rehypePlugins: [rehypeSanitize],
19
- urlTransform,
39
+ rehypePlugins: [rehypeSlug, rehypeSanitize],
40
+ urlTransform: (url, key, node) => transformMarkdownUrl(url, key, node, urlTransform),
20
41
  components: {
21
42
  pre({ children: preChildren }) {
22
43
  return /* @__PURE__ */ jsx(Fragment$1, { children: preChildren });
@@ -42,4 +63,4 @@ const Markdown = memo(({ children, className, urlTransform }) => {
42
63
  });
43
64
  Markdown.displayName = "Markdown";
44
65
  //#endregion
45
- export { Markdown as t };
66
+ export { getSanitizedMarkdownHeadingIdFromRawFragment as n, Markdown as t };
@@ -1,3 +1,3 @@
1
+ import { n as MarkdownProps, r as getSanitizedMarkdownHeadingIdFromRawFragment, t as Markdown } from "./markdown-C0atSabr.js";
1
2
  import { n as CodeBlockProps, r as CopyButton, t as CodeBlock } from "./code-block-B9miUPht.js";
2
- import { n as MarkdownProps, t as Markdown } from "./index-Cq-EJzqW.js";
3
- export { CodeBlock, type CodeBlockProps, CopyButton, Markdown, type MarkdownProps };
3
+ export { CodeBlock, type CodeBlockProps, CopyButton, Markdown, type MarkdownProps, getSanitizedMarkdownHeadingIdFromRawFragment };
package/dist/markdown.js CHANGED
@@ -1,3 +1,3 @@
1
1
  import { n as CopyButton, t as CodeBlock } from "./code-block-B36KVUSN.js";
2
- import { t as Markdown } from "./markdown-BGqicV82.js";
3
- export { CodeBlock, CopyButton, Markdown };
2
+ import { n as getSanitizedMarkdownHeadingIdFromRawFragment, t as Markdown } from "./markdown-PywkQXWk.js";
3
+ export { CodeBlock, CopyButton, Markdown, getSanitizedMarkdownHeadingIdFromRawFragment };
@@ -3,7 +3,7 @@ import { t as cn } from "./utils-C_uf36nf.js";
3
3
  import { t as Button } from "./button-C87nEe2R.js";
4
4
  import { c as TableRow, d as Card, f as CardContent, g as CardTitle, h as CardHeader, i as TableCell, l as Badge, n as TableBody, o as TableHead, p as CardDescription, s as TableHeader, t as Table } from "./table-Bss73DhB.js";
5
5
  import { t as CodeBlock } from "./code-block-B36KVUSN.js";
6
- import { t as Markdown } from "./markdown-BGqicV82.js";
6
+ import { t as Markdown } from "./markdown-PywkQXWk.js";
7
7
  import { Fragment } from "react";
8
8
  import { jsx, jsxs } from "react/jsx-runtime";
9
9
  import { Minus } from "lucide-react";
@@ -53,7 +53,7 @@ function renderActions(actions, onAction) {
53
53
  }, action.id))
54
54
  });
55
55
  }
56
- function renderNode(node, onAction) {
56
+ function renderNode(node, onAction, urlTransform) {
57
57
  switch (node.type) {
58
58
  case "heading": {
59
59
  const level = node.level ?? 2;
@@ -136,6 +136,7 @@ function renderNode(node, onAction) {
136
136
  className: "rounded-[var(--radius-lg)] border border-border bg-card p-5",
137
137
  children: /* @__PURE__ */ jsx(Markdown, {
138
138
  className: "prose-sm max-w-none",
139
+ urlTransform,
139
140
  children: node.content
140
141
  })
141
142
  });
@@ -176,13 +177,13 @@ function renderNode(node, onAction) {
176
177
  if (asArray(node.children).length === 0) return null;
177
178
  return /* @__PURE__ */ jsx("div", {
178
179
  className: cn("flex", node.direction === "row" ? "flex-row" : "flex-col", GAP_STYLES[node.gap ?? "md"], ALIGN_STYLES[node.align ?? "stretch"], node.wrap && "flex-wrap"),
179
- children: asArray(node.children).map((child, index) => /* @__PURE__ */ jsx(Fragment, { children: renderNode(child, onAction) }, child.id ?? `${child.type}-${index}`))
180
+ children: asArray(node.children).map((child, index) => /* @__PURE__ */ jsx(Fragment, { children: renderNode(child, onAction, urlTransform) }, child.id ?? `${child.type}-${index}`))
180
181
  });
181
182
  case "grid":
182
183
  if (asArray(node.children).length === 0) return null;
183
184
  return /* @__PURE__ */ jsx("div", {
184
185
  className: cn("grid", GRID_STYLES[node.columns ?? 2], GAP_STYLES[node.gap ?? "md"]),
185
- children: asArray(node.children).map((child, index) => /* @__PURE__ */ jsx(Fragment, { children: renderNode(child, onAction) }, child.id ?? `${child.type}-${index}`))
186
+ children: asArray(node.children).map((child, index) => /* @__PURE__ */ jsx(Fragment, { children: renderNode(child, onAction, urlTransform) }, child.id ?? `${child.type}-${index}`))
186
187
  });
187
188
  case "card": return /* @__PURE__ */ jsxs(Card, {
188
189
  variant: "glass",
@@ -214,7 +215,7 @@ function renderNode(node, onAction) {
214
215
  }), asArray(node.actions).length > 0 && renderActions(asArray(node.actions), onAction)]
215
216
  }), asArray(node.children).length > 0 && /* @__PURE__ */ jsx(CardContent, {
216
217
  className: "space-y-4 p-4",
217
- children: asArray(node.children).map((child, index) => /* @__PURE__ */ jsx(Fragment, { children: renderNode(child, onAction) }, child.id ?? `${child.type}-${index}`))
218
+ children: asArray(node.children).map((child, index) => /* @__PURE__ */ jsx(Fragment, { children: renderNode(child, onAction, urlTransform) }, child.id ?? `${child.type}-${index}`))
218
219
  })]
219
220
  });
220
221
  }
@@ -225,7 +226,7 @@ function renderNode(node, onAction) {
225
226
  * extension surface for generated inspectors/results, not a replacement for
226
227
  * the sandbox shell.
227
228
  */
228
- function OpenUIArtifactRenderer({ schema, onAction, className }) {
229
+ function OpenUIArtifactRenderer({ schema, onAction, className, urlTransform }) {
229
230
  const issue = findUnsupportedOpenUINode(schema);
230
231
  if (issue) return /* @__PURE__ */ jsxs("div", {
231
232
  role: "alert",
@@ -254,7 +255,7 @@ function OpenUIArtifactRenderer({ schema, onAction, className }) {
254
255
  });
255
256
  return /* @__PURE__ */ jsx("div", {
256
257
  className: cn("space-y-4", className),
257
- children: nodes.map((node, index) => /* @__PURE__ */ jsx(Fragment, { children: renderNode(node, onAction) }, node.id ?? `${node.type}-${index}`))
258
+ children: nodes.map((node, index) => /* @__PURE__ */ jsx(Fragment, { children: renderNode(node, onAction, urlTransform) }, node.id ?? `${node.type}-${index}`))
258
259
  });
259
260
  }
260
261
  //#endregion
@@ -1,3 +1,4 @@
1
+ import { n as MarkdownProps } from "./markdown-C0atSabr.js";
1
2
  import { ReactNode } from "react";
2
3
  //#region src/openui/openui-artifact-renderer.d.ts
3
4
  type OpenUIPrimitive = string | number | boolean | null | undefined;
@@ -102,6 +103,7 @@ interface OpenUIArtifactRendererProps {
102
103
  schema: OpenUIComponentNode | OpenUIComponentNode[];
103
104
  onAction?: (action: OpenUIAction) => void;
104
105
  className?: string;
106
+ urlTransform?: MarkdownProps["urlTransform"];
105
107
  }
106
108
  /**
107
109
  * OpenUIArtifactRenderer — contained renderer for OpenUI-like structured
@@ -109,6 +111,6 @@ interface OpenUIArtifactRendererProps {
109
111
  * extension surface for generated inspectors/results, not a replacement for
110
112
  * the sandbox shell.
111
113
  */
112
- declare function OpenUIArtifactRenderer({ schema, onAction, className }: OpenUIArtifactRendererProps): import("react").JSX.Element;
114
+ declare function OpenUIArtifactRenderer({ schema, onAction, className, urlTransform }: OpenUIArtifactRendererProps): import("react").JSX.Element;
113
115
  //#endregion
114
116
  export { OpenUITableNode as _, OpenUIBadgeNode as a, OpenUIComponentNode as c, OpenUIKeyValueNode as d, OpenUIMarkdownNode as f, OpenUIStatNode as g, OpenUIStackNode as h, OpenUIArtifactRendererProps as i, OpenUIGridNode as l, OpenUISeparatorNode as m, OpenUIActionsNode as n, OpenUICardNode as o, OpenUIPrimitive as p, OpenUIArtifactRenderer as r, OpenUICodeNode as s, OpenUIAction as t, OpenUIHeadingNode as u, OpenUITextNode as v };
@@ -1,3 +1,3 @@
1
- import { c as OpenUIComponentNode } from "./openui-artifact-renderer-D3E5bIAI.js";
2
- import { a as validateOpenUIJsonNode, i as validateOpenUIJsonArtifact, n as OpenUISchemaValidation, o as OPENUI_NODE_JSON_SCHEMA, r as findUnsupportedOpenUINode, s as OPENUI_NODE_TYPES, t as OpenUISchemaIssue } from "./schema-BFKgCGH-.js";
1
+ import { c as OpenUIComponentNode } from "./openui-artifact-renderer-fkBQaoLO.js";
2
+ import { a as validateOpenUIJsonNode, i as validateOpenUIJsonArtifact, n as OpenUISchemaValidation, o as OPENUI_NODE_JSON_SCHEMA, r as findUnsupportedOpenUINode, s as OPENUI_NODE_TYPES, t as OpenUISchemaIssue } from "./schema-DAstk-J4.js";
3
3
  export { OPENUI_NODE_JSON_SCHEMA, OPENUI_NODE_TYPES, type OpenUIComponentNode, OpenUISchemaIssue, OpenUISchemaValidation, findUnsupportedOpenUINode, validateOpenUIJsonArtifact, validateOpenUIJsonNode };
package/dist/openui.d.ts CHANGED
@@ -1,3 +1,3 @@
1
- import { _ as OpenUITableNode, a as OpenUIBadgeNode, c as OpenUIComponentNode, d as OpenUIKeyValueNode, f as OpenUIMarkdownNode, g as OpenUIStatNode, h as OpenUIStackNode, i as OpenUIArtifactRendererProps, l as OpenUIGridNode, m as OpenUISeparatorNode, n as OpenUIActionsNode, o as OpenUICardNode, p as OpenUIPrimitive, r as OpenUIArtifactRenderer, s as OpenUICodeNode, t as OpenUIAction, u as OpenUIHeadingNode, v as OpenUITextNode } from "./openui-artifact-renderer-D3E5bIAI.js";
2
- import { a as validateOpenUIJsonNode, i as validateOpenUIJsonArtifact, n as OpenUISchemaValidation, o as OPENUI_NODE_JSON_SCHEMA, r as findUnsupportedOpenUINode, s as OPENUI_NODE_TYPES, t as OpenUISchemaIssue } from "./schema-BFKgCGH-.js";
1
+ import { _ as OpenUITableNode, a as OpenUIBadgeNode, c as OpenUIComponentNode, d as OpenUIKeyValueNode, f as OpenUIMarkdownNode, g as OpenUIStatNode, h as OpenUIStackNode, i as OpenUIArtifactRendererProps, l as OpenUIGridNode, m as OpenUISeparatorNode, n as OpenUIActionsNode, o as OpenUICardNode, p as OpenUIPrimitive, r as OpenUIArtifactRenderer, s as OpenUICodeNode, t as OpenUIAction, u as OpenUIHeadingNode, v as OpenUITextNode } from "./openui-artifact-renderer-fkBQaoLO.js";
2
+ import { a as validateOpenUIJsonNode, i as validateOpenUIJsonArtifact, n as OpenUISchemaValidation, o as OPENUI_NODE_JSON_SCHEMA, r as findUnsupportedOpenUINode, s as OPENUI_NODE_TYPES, t as OpenUISchemaIssue } from "./schema-DAstk-J4.js";
3
3
  export { OPENUI_NODE_JSON_SCHEMA, OPENUI_NODE_TYPES, type OpenUIAction, type OpenUIActionsNode, OpenUIArtifactRenderer, type OpenUIArtifactRendererProps, type OpenUIBadgeNode, type OpenUICardNode, type OpenUICodeNode, type OpenUIComponentNode, type OpenUIGridNode, type OpenUIHeadingNode, type OpenUIKeyValueNode, type OpenUIMarkdownNode, type OpenUIPrimitive, type OpenUISchemaIssue, type OpenUISchemaValidation, type OpenUISeparatorNode, type OpenUIStackNode, type OpenUIStatNode, type OpenUITableNode, type OpenUITextNode, findUnsupportedOpenUINode, validateOpenUIJsonArtifact, validateOpenUIJsonNode };
package/dist/openui.js CHANGED
@@ -1,3 +1,3 @@
1
1
  import { a as OPENUI_NODE_TYPES, i as OPENUI_NODE_JSON_SCHEMA, n as validateOpenUIJsonArtifact, r as validateOpenUIJsonNode, t as findUnsupportedOpenUINode } from "./schema-BpW9rSSG.js";
2
- import { t as OpenUIArtifactRenderer } from "./openui-artifact-renderer-C3bmqfjX.js";
2
+ import { t as OpenUIArtifactRenderer } from "./openui-artifact-renderer-DjLPuaP9.js";
3
3
  export { OPENUI_NODE_JSON_SCHEMA, OPENUI_NODE_TYPES, OpenUIArtifactRenderer, findUnsupportedOpenUINode, validateOpenUIJsonArtifact, validateOpenUIJsonNode };
@@ -2,8 +2,8 @@ import { t as cn } from "./utils-C_uf36nf.js";
2
2
  import { t as TextShimmer } from "./text-shimmer-BUUo6I-g.js";
3
3
  import { i as truncateText, n as formatDuration } from "./format-DfcLWqMa.js";
4
4
  import { i as RunRowShell, r as InlineToolItem, s as ExpandableContent } from "./tool-call-step-DNebqhmX.js";
5
- import { t as Markdown } from "./markdown-BGqicV82.js";
6
- import { t as OpenUIArtifactRenderer } from "./openui-artifact-renderer-C3bmqfjX.js";
5
+ import { t as Markdown } from "./markdown-PywkQXWk.js";
6
+ import { t as OpenUIArtifactRenderer } from "./openui-artifact-renderer-DjLPuaP9.js";
7
7
  import { memo, useEffect, useMemo, useRef, useState } from "react";
8
8
  import { jsx, jsxs } from "react/jsx-runtime";
9
9
  import { Bot, Brain, ChevronDown, ChevronRight, ClipboardList, FileEdit, FileSearch, Globe, Loader2, PencilLine, Search, Settings, Sparkles, Terminal } from "lucide-react";
package/dist/run.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import { a as RunRowStatusDot, i as RunRowShell, o as ExpandedToolDetail, r as InlineToolItem } from "./tool-call-step-DNebqhmX.js";
2
- import { n as InlineThinkingItem, t as RunGroup } from "./run-group-CxNskmHd.js";
2
+ import { n as InlineThinkingItem, t as RunGroup } from "./run-group-COUIsZ_x.js";
3
3
  import { t as LiveDuration } from "./run-ZsIKPA6J.js";
4
- import { n as parseToolEvent, t as ToolCallFeed } from "./tool-call-feed-Djt2q11V.js";
4
+ import { n as parseToolEvent, t as ToolCallFeed } from "./tool-call-feed-DNADpFyJ.js";
5
5
  export { ExpandedToolDetail, InlineThinkingItem, InlineToolItem, LiveDuration, RunGroup, RunRowShell, RunRowStatusDot, ToolCallFeed, parseToolEvent };
@@ -1,4 +1,4 @@
1
- import { c as OpenUIComponentNode } from "./openui-artifact-renderer-D3E5bIAI.js";
1
+ import { c as OpenUIComponentNode } from "./openui-artifact-renderer-fkBQaoLO.js";
2
2
  //#region src/openui/schema-data.d.ts
3
3
  declare const OPENUI_NODE_TYPES: readonly ["heading", "text", "badge", "stat", "key_value", "code", "markdown", "table", "actions", "separator", "stack", "grid", "card"];
4
4
  /**
package/dist/sdk-hooks.js CHANGED
@@ -1,3 +1,3 @@
1
1
  import { n as useRunCollapseState, r as useRunGroups, t as useAutoScroll } from "./use-auto-scroll-C5Pjeqon.js";
2
- import { a as useToolCallStream, i as useRealtimeSession, n as useSdkSession, o as useDropdownMenu, r as RealtimeSessionRegistry, t as useSSEStream } from "./use-sse-stream-BVgO1QBN.js";
2
+ import { a as useToolCallStream, i as useRealtimeSession, n as useSdkSession, o as useDropdownMenu, r as RealtimeSessionRegistry, t as useSSEStream } from "./use-sse-stream-OOPpkt_E.js";
3
3
  export { RealtimeSessionRegistry, useAutoScroll, useDropdownMenu, useRealtimeSession, useRunCollapseState, useRunGroups, useSSEStream, useSdkSession, useToolCallStream };
@@ -1,6 +1,6 @@
1
1
  import { t as cn } from "./utils-C_uf36nf.js";
2
2
  import { n as ToolCallStep, t as ToolCallGroup } from "./tool-call-step-DNebqhmX.js";
3
- import { t as Markdown } from "./markdown-BGqicV82.js";
3
+ import { t as Markdown } from "./markdown-PywkQXWk.js";
4
4
  import { jsx } from "react/jsx-runtime";
5
5
  //#region src/run/tool-call-feed.tsx
6
6
  /**
@@ -1,4 +1,4 @@
1
- import { n as parseToolEvent } from "./tool-call-feed-Djt2q11V.js";
1
+ import { n as parseToolEvent } from "./tool-call-feed-DNADpFyJ.js";
2
2
  import { _ as setForegroundActiveSession, d as registerActiveSession, g as setActiveSessionRunning, h as setActiveSessionError, m as setActiveSessionConnection, n as bumpActiveSessionActivity, p as setActiveSessionAttention, v as unregisterActiveSession, y as updateActiveSessionMeta } from "./active-sessions-store-Gt1R0rFG.js";
3
3
  import * as React from "react";
4
4
  import { createElement, useCallback, useEffect, useMemo, useRef, useState } from "react";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tangle-network/ui",
3
- "version": "11.11.3",
3
+ "version": "11.11.5",
4
4
  "description": "Generic React UI components for Tangle products — primitives, chat, run, files, editor, markdown.",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -127,11 +127,13 @@
127
127
  "@radix-ui/react-tabs": "^1.1.21",
128
128
  "class-variance-authority": "^0.7.1",
129
129
  "clsx": "^2.1.1",
130
+ "github-slugger": "^2.0.0",
130
131
  "lucide-react": "^1.48.0",
131
132
  "marked": "^18.0.14",
132
133
  "react-markdown": "^10.1.0",
133
134
  "react-syntax-highlighter": "^16.1.1",
134
135
  "rehype-sanitize": "^6.0.0",
136
+ "rehype-slug": "^6.0.0",
135
137
  "remark-gfm": "^4.0.1",
136
138
  "tailwind-merge": "^3.7.0",
137
139
  "turndown": "^7.2.4"
@@ -139,7 +141,7 @@
139
141
  "peerDependencies": {
140
142
  "@hocuspocus/provider": ">=2.15.0 <5.0.0",
141
143
  "@nanostores/react": ">=0.8.4 <3.0.0",
142
- "@tangle-network/brand": "^1.8.2",
144
+ "@tangle-network/brand": "^1.9.0",
143
145
  "@tiptap/core": ">=3.20.4 <4.0.0",
144
146
  "@tiptap/extension-collaboration": ">=3.20.4 <4.0.0",
145
147
  "@tiptap/extension-collaboration-caret": ">=3.7.0 <4.0.0",
@@ -3,13 +3,19 @@ import { describe, expect, it } from "vitest"
3
3
  import { UserMessage } from "./user-message"
4
4
 
5
5
  describe("UserMessage", () => {
6
- it("renders the text in a borderless muted bubble", () => {
6
+ it("renders the text in a bordered card that wraps in narrow panes", () => {
7
7
  const { container } = render(<UserMessage content="Run the tests." />)
8
8
  expect(screen.getByText("Run the tests.")).toBeInTheDocument()
9
9
  const bubble = container.querySelector(".rounded-2xl")
10
10
  expect(bubble).not.toBeNull()
11
- expect(bubble!.className).toContain("bg-muted/50")
12
- expect(bubble!.className).not.toMatch(/(^|\s)border(\s|$)/)
11
+ expect(bubble!.className).toContain("bg-card")
12
+ expect(bubble!.className).toContain("border-border")
13
+ expect(container.querySelector(".group")?.className).toContain(
14
+ "min-w-0",
15
+ )
16
+ expect(screen.getByText("Run the tests.").className).toContain(
17
+ "break-words",
18
+ )
13
19
  })
14
20
 
15
21
  it("keeps the timestamp beside the bubble as a hover-revealed label", () => {
@@ -17,8 +17,8 @@ function formatTime(date: Date): string {
17
17
  }
18
18
 
19
19
  /**
20
- * The single user message bubble — a quiet, right-aligned fill on the muted
21
- * surface (no border, no loud fill, no uppercase label). The timestamp sits
20
+ * The single user message bubble — a quiet, right-aligned card with a subtle
21
+ * semantic border (no loud fill, no uppercase label). The timestamp sits
22
22
  * beside the bubble and appears on hover, so it costs no height. Used by both
23
23
  * the run/message list (session-model `parts`) and AgentTimeline (direct
24
24
  * `content`/`timestamp`).
@@ -36,8 +36,10 @@ export const UserMessage = memo(
36
36
 
37
37
  return (
38
38
  <div className="flex justify-end">
39
- <div className="group flex max-w-[78%] flex-col items-end gap-2">
40
- <div className="relative w-full rounded-2xl bg-muted/50 px-4 py-3">
39
+ <div className="group flex min-w-0 max-w-[78%] flex-col items-end gap-2">
40
+ <div
41
+ className="relative w-full min-w-0 rounded-2xl border border-border bg-card px-4 py-3"
42
+ >
41
43
  {timestamp ? (
42
44
  <span
43
45
  data-user-message-time=""
@@ -46,7 +48,7 @@ export const UserMessage = memo(
46
48
  {formatTime(timestamp)}
47
49
  </span>
48
50
  ) : null}
49
- <div className="whitespace-pre-wrap text-[var(--font-size-base)] leading-[1.5] text-foreground">
51
+ <div className="break-words whitespace-pre-wrap text-[var(--font-size-base)] leading-[1.5] text-foreground">
50
52
  {text}
51
53
  </div>
52
54
  </div>
@@ -1,2 +1,2 @@
1
- export { Markdown, type MarkdownProps } from "./markdown";
1
+ export { Markdown, getSanitizedMarkdownHeadingIdFromRawFragment, type MarkdownProps } from "./markdown";
2
2
  export { CodeBlock, CopyButton, type CodeBlockProps } from "./code-block";
@@ -1,6 +1,6 @@
1
1
  import { describe, expect, it, vi } from "vitest";
2
2
  import { render, screen } from "@testing-library/react";
3
- import { Markdown } from "./markdown";
3
+ import { getSanitizedMarkdownHeadingIdFromRawFragment, Markdown } from "./markdown";
4
4
 
5
5
  describe("Markdown", () => {
6
6
  it("uses the tokenized Tangle prose class instead of host typography defaults", () => {
@@ -12,6 +12,62 @@ describe("Markdown", () => {
12
12
  expect(surface).not.toHaveClass("dark:prose-invert");
13
13
  });
14
14
 
15
+ it("adds GitHub-style Unicode and duplicate heading IDs before sanitizing them", () => {
16
+ const { container } = render(
17
+ <Markdown>{"# Duplicate\n\n## Crème brûlée\n\n# Duplicate\n\n# user-content-heading"}</Markdown>,
18
+ );
19
+
20
+ expect(container.querySelectorAll("h1, h2")).toHaveLength(4);
21
+ expect(container.querySelector("h2")).toHaveAttribute("id", "user-content-crème-brûlée");
22
+ expect(container.querySelectorAll("h1")[0]).toHaveAttribute("id", "user-content-duplicate");
23
+ expect(container.querySelectorAll("h1")[1]).toHaveAttribute("id", "user-content-duplicate-1");
24
+ expect(container.querySelectorAll("h1")[2]).toHaveAttribute(
25
+ "id",
26
+ "user-content-user-content-heading",
27
+ );
28
+ });
29
+
30
+ it("maps raw fragments exactly once to the sanitized target prefix", () => {
31
+ expect(getSanitizedMarkdownHeadingIdFromRawFragment("Cr%C3%A8me%20br%C3%BBl%C3%A9e"))
32
+ .toBe("user-content-crème-brûlée");
33
+ expect(getSanitizedMarkdownHeadingIdFromRawFragment("user-content-heading"))
34
+ .toBe("user-content-user-content-heading");
35
+ });
36
+
37
+ it("maps same-document fragments to sanitized heading IDs", () => {
38
+ render(<Markdown>{"[Jump](#Cr%C3%A8me%20br%C3%BBl%C3%A9e)\n\n# Crème brûlée"}</Markdown>);
39
+
40
+ expect(screen.getByRole("link", { name: "Jump" })).toHaveAttribute(
41
+ "href",
42
+ "#user-content-crème-brûlée",
43
+ );
44
+ });
45
+
46
+ it("keeps custom URL transforms behind ReactMarkdown protocol checks", () => {
47
+ const urlTransform = vi.fn((url: string) => url);
48
+
49
+ render(
50
+ <Markdown urlTransform={urlTransform}>
51
+ {"[External](https://example.com/docs#install)\n\n![Safe](https://example.com/image.png)\n\n![Unsafe](javascript:alert(1))"}
52
+ </Markdown>,
53
+ );
54
+
55
+ expect(screen.getByRole("link", { name: "External" })).toHaveAttribute(
56
+ "href",
57
+ "https://example.com/docs#install",
58
+ );
59
+ expect(screen.getByRole("img", { name: "Safe" })).toHaveAttribute(
60
+ "src",
61
+ "https://example.com/image.png",
62
+ );
63
+ expect(screen.getByRole("img", { name: "Unsafe" })).not.toHaveAttribute("src");
64
+ expect(urlTransform).toHaveBeenCalledWith(
65
+ "https://example.com/image.png",
66
+ "src",
67
+ expect.objectContaining({ tagName: "img" }),
68
+ );
69
+ });
70
+
15
71
  it("keeps inline code on semantic tokens", () => {
16
72
  const { container } = render(<Markdown>{"Use `token` values."}</Markdown>);
17
73
  const inlineCode = container.querySelector("code");
@@ -1,14 +1,50 @@
1
1
  import { memo } from "react";
2
- import ReactMarkdown, { type UrlTransform } from "react-markdown";
2
+ import ReactMarkdown, { defaultUrlTransform, type UrlTransform } from "react-markdown";
3
3
  import remarkGfm from "remark-gfm";
4
4
  import rehypeSanitize from "rehype-sanitize";
5
+ import rehypeSlug from "rehype-slug";
6
+ import GithubSlugger from "github-slugger";
5
7
  import { CodeBlock, CopyButton } from "./code-block";
6
8
  import { cn } from "../lib/utils";
7
9
 
10
+ const SANITIZED_HEADING_ID_PREFIX = "user-content-";
11
+
12
+ /** Converts a raw Markdown fragment to the ID rehype-sanitize emits for its heading. */
13
+ export function getSanitizedMarkdownHeadingIdFromRawFragment(rawFragment: string): string {
14
+ let decodedFragment = rawFragment;
15
+ try {
16
+ decodedFragment = decodeURIComponent(rawFragment);
17
+ } catch {
18
+ // Keep malformed percent escapes literal, as browsers do for fragment targets.
19
+ }
20
+ const slugger = new GithubSlugger();
21
+ return SANITIZED_HEADING_ID_PREFIX + slugger.slug(decodedFragment);
22
+ }
23
+
24
+ function safeUrl(url: string): string | undefined {
25
+ return defaultUrlTransform(url) ?? undefined;
26
+ }
27
+
28
+ function transformMarkdownUrl(
29
+ url: string,
30
+ key: string,
31
+ node: Parameters<UrlTransform>[2],
32
+ urlTransform?: UrlTransform,
33
+ ) {
34
+ const transformed = urlTransform ? urlTransform(url, key, node) : url;
35
+ if (transformed == null) return undefined;
36
+
37
+ if (key === "href" && transformed === url && url.startsWith("#")) {
38
+ return safeUrl("#" + getSanitizedMarkdownHeadingIdFromRawFragment(url.slice(1)));
39
+ }
40
+
41
+ return safeUrl(transformed);
42
+ }
43
+
8
44
  export interface MarkdownProps {
9
45
  children: string;
10
46
  className?: string;
11
- /** Transform parsed link and image URLs before sanitisation. */
47
+ /** Transform parsed link and image URLs while retaining protocol safety checks. */
12
48
  urlTransform?: UrlTransform;
13
49
  }
14
50
 
@@ -23,8 +59,8 @@ export const Markdown = memo(({ children, className, urlTransform }: MarkdownPro
23
59
  >
24
60
  <ReactMarkdown
25
61
  remarkPlugins={[remarkGfm]}
26
- rehypePlugins={[rehypeSanitize]}
27
- urlTransform={urlTransform}
62
+ rehypePlugins={[rehypeSlug, rehypeSanitize]}
63
+ urlTransform={(url, key, node) => transformMarkdownUrl(url, key, node, urlTransform)}
28
64
  components={{
29
65
  pre({ children: preChildren }) {
30
66
  return <>{preChildren}</>;
@@ -12,7 +12,7 @@ import {
12
12
  } from "../primitives/card";
13
13
  import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "../primitives/table";
14
14
  import { CodeBlock } from "../primitives/code-block";
15
- import { Markdown } from "../markdown/markdown";
15
+ import { Markdown, type MarkdownProps } from "../markdown/markdown";
16
16
  import { findUnsupportedOpenUINode, type OPENUI_NODE_TYPES } from "./schema";
17
17
 
18
18
  export type OpenUIPrimitive = string | number | boolean | null | undefined;
@@ -147,6 +147,7 @@ export interface OpenUIArtifactRendererProps {
147
147
  schema: OpenUIComponentNode | OpenUIComponentNode[];
148
148
  onAction?: (action: OpenUIAction) => void;
149
149
  className?: string;
150
+ urlTransform?: MarkdownProps["urlTransform"];
150
151
  }
151
152
 
152
153
  type RendererNodeTypesMatchSchema =
@@ -218,7 +219,11 @@ function renderActions(actions: OpenUIAction[], onAction?: (action: OpenUIAction
218
219
  );
219
220
  }
220
221
 
221
- function renderNode(node: OpenUIComponentNode, onAction?: (action: OpenUIAction) => void): ReactNode {
222
+ function renderNode(
223
+ node: OpenUIComponentNode,
224
+ onAction?: (action: OpenUIAction) => void,
225
+ urlTransform?: MarkdownProps["urlTransform"],
226
+ ): ReactNode {
222
227
  switch (node.type) {
223
228
  case "heading": {
224
229
  const level = node.level ?? 2;
@@ -341,7 +346,9 @@ function renderNode(node: OpenUIComponentNode, onAction?: (action: OpenUIAction)
341
346
  case "markdown":
342
347
  return (
343
348
  <div className="rounded-[var(--radius-lg)] border border-border bg-card p-5">
344
- <Markdown className="prose-sm max-w-none">{node.content}</Markdown>
349
+ <Markdown className="prose-sm max-w-none" urlTransform={urlTransform}>
350
+ {node.content}
351
+ </Markdown>
345
352
  </div>
346
353
  );
347
354
 
@@ -425,7 +432,7 @@ function renderNode(node: OpenUIComponentNode, onAction?: (action: OpenUIAction)
425
432
  >
426
433
  {asArray<OpenUIComponentNode>(node.children).map((child, index) => (
427
434
  <Fragment key={child.id ?? `${child.type}-${index}`}>
428
- {renderNode(child, onAction)}
435
+ {renderNode(child, onAction, urlTransform)}
429
436
  </Fragment>
430
437
  ))}
431
438
  </div>
@@ -439,7 +446,7 @@ function renderNode(node: OpenUIComponentNode, onAction?: (action: OpenUIAction)
439
446
  <div className={cn("grid", GRID_STYLES[node.columns ?? 2], GAP_STYLES[node.gap ?? "md"])}>
440
447
  {asArray<OpenUIComponentNode>(node.children).map((child, index) => (
441
448
  <Fragment key={child.id ?? `${child.type}-${index}`}>
442
- {renderNode(child, onAction)}
449
+ {renderNode(child, onAction, urlTransform)}
443
450
  </Fragment>
444
451
  ))}
445
452
  </div>
@@ -473,7 +480,7 @@ function renderNode(node: OpenUIComponentNode, onAction?: (action: OpenUIAction)
473
480
  <CardContent className="space-y-4 p-4">
474
481
  {asArray<OpenUIComponentNode>(node.children).map((child, index) => (
475
482
  <Fragment key={child.id ?? `${child.type}-${index}`}>
476
- {renderNode(child, onAction)}
483
+ {renderNode(child, onAction, urlTransform)}
477
484
  </Fragment>
478
485
  ))}
479
486
  </CardContent>
@@ -493,6 +500,7 @@ export function OpenUIArtifactRenderer({
493
500
  schema,
494
501
  onAction,
495
502
  className,
503
+ urlTransform,
496
504
  }: OpenUIArtifactRendererProps) {
497
505
  const issue = findUnsupportedOpenUINode(schema);
498
506
  if (issue) {
@@ -526,7 +534,7 @@ export function OpenUIArtifactRenderer({
526
534
  <div className={cn("space-y-4", className)}>
527
535
  {nodes.map((node, index) => (
528
536
  <Fragment key={node.id ?? `${node.type}-${index}`}>
529
- {renderNode(node, onAction)}
537
+ {renderNode(node, onAction, urlTransform)}
530
538
  </Fragment>
531
539
  ))}
532
540
  </div>
@@ -1,5 +1,6 @@
1
1
  import { render, screen } from "@testing-library/react";
2
- import { describe, expect, it } from "vitest";
2
+ import { describe, expect, it, vi } from "vitest";
3
+ import { getSanitizedMarkdownHeadingIdFromRawFragment } from "../markdown/markdown";
3
4
  import { OpenUIArtifactRenderer } from "./openui-artifact-renderer";
4
5
  import { OPENUI_NODE_JSON_SCHEMA, OPENUI_NODE_TYPES, validateOpenUIJsonArtifact, validateOpenUIJsonNode } from "./schema";
5
6
 
@@ -65,6 +66,44 @@ describe("OpenUI JSON contract", () => {
65
66
  expect(screen.getByText("Value")).toBeTruthy();
66
67
  });
67
68
 
69
+ it("forwards URL transforms and keeps cross-file fragments aligned with sanitized headings", () => {
70
+ const urlTransform = vi.fn((url: string, key: string) => {
71
+ if (key !== "href") return url;
72
+ const separator = url.indexOf("#");
73
+ const fragment = separator >= 0
74
+ ? "#" + getSanitizedMarkdownHeadingIdFromRawFragment(url.slice(separator + 1))
75
+ : "";
76
+ return "/app/ws-1/vault?file=campaigns%2Fpacket.md" + fragment;
77
+ });
78
+
79
+ render(
80
+ <OpenUIArtifactRenderer
81
+ schema={{
82
+ type: "card",
83
+ children: [{
84
+ type: "markdown",
85
+ content: "[Packet](campaigns/packet.md#Cr%C3%A8me%20br%C3%BBl%C3%A9e)\n\n# Crème brûlée",
86
+ }],
87
+ }}
88
+ urlTransform={urlTransform}
89
+ />,
90
+ );
91
+
92
+ expect(screen.getByRole("link", { name: "Packet" })).toHaveAttribute(
93
+ "href",
94
+ "/app/ws-1/vault?file=campaigns%2Fpacket.md#user-content-crème-brûlée",
95
+ );
96
+ expect(screen.getByRole("heading", { name: "Crème brûlée" })).toHaveAttribute(
97
+ "id",
98
+ "user-content-crème-brûlée",
99
+ );
100
+ expect(urlTransform).toHaveBeenCalledWith(
101
+ "campaigns/packet.md#Cr%C3%A8me%20br%C3%BBl%C3%A9e",
102
+ "href",
103
+ expect.objectContaining({ tagName: "a" }),
104
+ );
105
+ });
106
+
68
107
  it("shows an explicit error for an old unsupported artifact", () => {
69
108
  const oldArtifact = { type: "card", children: [{ type: "section", children: [{ type: "text", text: "hidden" }] }] };
70
109
  render(<OpenUIArtifactRenderer schema={oldArtifact as never} />);