@tangle-network/ui 11.12.0 → 11.13.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +17 -0
- package/dist/_virtual/_rolldown/runtime.js +13 -0
- package/dist/auth/auth.d.ts +53 -0
- package/dist/{auth-DOETfnd9.js → auth/auth.js} +7 -37
- package/dist/auth/login-layout.d.ts +20 -0
- package/dist/auth/login-layout.js +36 -0
- package/dist/auth.d.ts +2 -1
- package/dist/auth.js +2 -1
- package/dist/chat/agent-timeline.d.ts +83 -0
- package/dist/chat/agent-timeline.js +236 -0
- package/dist/chat/chat-container.d.ts +51 -0
- package/dist/chat/chat-container.js +309 -0
- package/dist/chat/chat-message.d.ts +22 -0
- package/dist/chat/chat-message.js +38 -0
- package/dist/chat/message-list.d.ts +32 -0
- package/dist/chat/message-list.js +37 -0
- package/dist/chat/thinking-indicator.d.ts +6 -0
- package/dist/chat/thinking-indicator.js +38 -0
- package/dist/chat/user-message.d.ts +21 -0
- package/dist/chat/user-message.js +42 -0
- package/dist/chat.d.ts +6 -1
- package/dist/chat.js +6 -1
- package/dist/editor/document-editor-pane.d.ts +37 -0
- package/dist/editor/document-editor-pane.js +199 -0
- package/dist/editor/editor-lazy.js +37 -0
- package/dist/editor/editor-loading.js +21 -0
- package/dist/editor/editor-peers.d.ts +6 -0
- package/dist/editor/editor-peers.js +155 -0
- package/dist/editor/editor-provider.d.ts +97 -0
- package/dist/editor/editor-provider.js +253 -0
- package/dist/editor/editor-toolbar.d.ts +11 -0
- package/dist/editor/editor-toolbar.js +106 -0
- package/dist/editor/markdown-conversion.js +23 -0
- package/dist/editor/markdown-document-editor.js +103 -0
- package/dist/editor/tiptap-editor.d.ts +45 -0
- package/dist/editor/tiptap-editor.js +271 -0
- package/dist/editor/use-editor.d.ts +67 -0
- package/dist/editor/use-editor.js +158 -0
- package/dist/editor.d.ts +6 -119
- package/dist/editor.js +5 -1
- package/dist/files/file-artifact-pane.d.ts +47 -0
- package/dist/files/file-artifact-pane.js +114 -0
- package/dist/files/file-format.d.ts +51 -0
- package/dist/{file-format-BgXbr-Ib.js → files/file-format.js} +1 -1
- package/dist/files/file-preview.d.ts +27 -0
- package/dist/files/file-preview.js +359 -0
- package/dist/files/file-tabs.d.ts +19 -0
- package/dist/files/file-tabs.js +48 -0
- package/dist/files/file-tree.d.ts +31 -0
- package/dist/files/file-tree.js +135 -0
- package/dist/files/rich-file-tree.d.ts +62 -0
- package/dist/files/rich-file-tree.js +122 -0
- package/dist/files.d.ts +6 -1
- package/dist/files.js +6 -2
- package/dist/hooks/use-auth.d.ts +40 -0
- package/dist/hooks/use-auth.js +91 -0
- package/dist/hooks/use-auto-scroll.d.ts +11 -0
- package/dist/hooks/use-auto-scroll.js +48 -0
- package/dist/hooks/use-dropdown-menu.d.ts +12 -0
- package/dist/hooks/use-dropdown-menu.js +31 -0
- package/dist/hooks/use-live-time.d.ts +7 -0
- package/dist/hooks/use-live-time.js +22 -0
- package/dist/hooks/use-realtime-session.d.ts +32 -0
- package/dist/hooks/use-realtime-session.js +235 -0
- package/dist/hooks/use-run-collapse-state.d.ts +13 -0
- package/dist/hooks/use-run-collapse-state.js +24 -0
- package/dist/hooks/use-run-groups.d.ts +11 -0
- package/dist/hooks/use-run-groups.js +85 -0
- package/dist/hooks/use-sdk-session.d.ts +59 -0
- package/dist/hooks/use-sdk-session.js +322 -0
- package/dist/hooks/use-sse-stream.d.ts +124 -0
- package/dist/hooks/use-sse-stream.js +229 -0
- package/dist/hooks/use-tool-call-stream.d.ts +23 -0
- package/dist/hooks/use-tool-call-stream.js +75 -0
- package/dist/hooks.d.ts +11 -49
- package/dist/hooks.js +10 -110
- package/dist/index.d.ts +99 -25
- package/dist/index.js +86 -36
- package/dist/lib/focus.d.ts +55 -0
- package/dist/{focus-BcE_SHqz.js → lib/focus.js} +1 -1
- package/dist/lib/utils.d.ts +4 -0
- package/dist/{utils-C_uf36nf.js → lib/utils.js} +1 -1
- package/dist/{code-block-B9miUPht.d.ts → markdown/code-block.d.ts} +5 -6
- package/dist/{code-block-B36KVUSN.js → markdown/code-block.js} +22 -47
- package/dist/{markdown-C0atSabr.d.ts → markdown/markdown.d.ts} +4 -5
- package/dist/{markdown-Db08KAYF.js → markdown/markdown.js} +3 -3
- package/dist/markdown.d.ts +2 -2
- package/dist/markdown.js +2 -2
- package/dist/{openui-artifact-renderer-fkBQaoLO.d.ts → openui/openui-artifact-renderer.d.ts} +20 -21
- package/dist/{openui-artifact-renderer-DG_i2lOR.js → openui/openui-artifact-renderer.js} +9 -7
- package/dist/{schema-BpW9rSSG.js → openui/schema-compiled.js} +2 -354
- package/dist/{schema-DAstk-J4.d.ts → openui/schema-data.d.ts} +3 -24
- package/dist/openui/schema-data.js +206 -0
- package/dist/openui-schema.d.ts +22 -3
- package/dist/openui-schema.js +138 -1
- package/dist/openui.d.ts +3 -2
- package/dist/openui.js +3 -2
- package/dist/{artifact-pane-BL_DFWNl.d.ts → primitives/artifact-pane.d.ts} +3 -4
- package/dist/{artifact-pane-DMXT9a8U.js → primitives/artifact-pane.js} +2 -2
- package/dist/primitives/avatar.d.ts +8 -0
- package/dist/primitives/avatar.js +25 -0
- package/dist/primitives/badge.d.ts +22 -0
- package/dist/primitives/badge.js +47 -0
- package/dist/{button-yoIv77e2.d.ts → primitives/button.d.ts} +2 -2
- package/dist/primitives/button.js +113 -0
- package/dist/primitives/card.d.ts +18 -0
- package/dist/primitives/card.js +52 -0
- package/dist/primitives/code-block.d.ts +6 -0
- package/dist/primitives/code-block.js +13 -0
- package/dist/primitives/dialog.d.ts +23 -0
- package/dist/primitives/dialog.js +59 -0
- package/dist/primitives/drop-zone.d.ts +23 -0
- package/dist/primitives/drop-zone.js +104 -0
- package/dist/primitives/dropdown-menu.d.ts +29 -0
- package/dist/{dropdown-menu-BpcLa5vF.js → primitives/dropdown-menu.js} +2 -23
- package/dist/primitives/empty-state.d.ts +11 -0
- package/dist/primitives/empty-state.js +32 -0
- package/dist/primitives/heading.d.ts +23 -0
- package/dist/primitives/heading.js +38 -0
- package/dist/primitives/input.d.ts +23 -0
- package/dist/primitives/input.js +110 -0
- package/dist/primitives/label.d.ts +6 -0
- package/dist/primitives/label.js +16 -0
- package/dist/primitives/metric-strip.d.ts +48 -0
- package/dist/primitives/metric-strip.js +52 -0
- package/dist/primitives/page-header.d.ts +25 -0
- package/dist/primitives/page-header.js +47 -0
- package/dist/primitives/page-shell.d.ts +14 -0
- package/dist/primitives/page-shell.js +17 -0
- package/dist/primitives/progress.d.ts +9 -0
- package/dist/primitives/progress.js +29 -0
- package/dist/primitives/segmented-control.d.ts +40 -0
- package/dist/primitives/segmented-control.js +57 -0
- package/dist/primitives/select.d.ts +15 -0
- package/dist/primitives/select.js +74 -0
- package/dist/primitives/sidebar-drop-zone.d.ts +21 -0
- package/dist/primitives/sidebar-drop-zone.js +88 -0
- package/dist/primitives/skeleton.d.ts +10 -0
- package/dist/primitives/skeleton.js +50 -0
- package/dist/primitives/stat-card.d.ts +16 -0
- package/dist/primitives/stat-card.js +60 -0
- package/dist/primitives/status-pill.d.ts +44 -0
- package/dist/primitives/status-pill.js +119 -0
- package/dist/primitives/switch.d.ts +6 -0
- package/dist/primitives/switch.js +16 -0
- package/dist/primitives/table.d.ts +22 -0
- package/dist/primitives/table.js +63 -0
- package/dist/primitives/tabs.d.ts +13 -0
- package/dist/{tabs-BVHR6NkO.js → primitives/tabs.js} +3 -3
- package/dist/primitives/terminal-display.d.ts +25 -0
- package/dist/primitives/terminal-display.js +109 -0
- package/dist/primitives/text-shimmer.d.ts +16 -0
- package/dist/{text-shimmer-BUUo6I-g.js → primitives/text-shimmer.js} +2 -2
- package/dist/primitives/theme-toggle.d.ts +11 -0
- package/dist/primitives/theme-toggle.js +154 -0
- package/dist/primitives/toast.d.ts +29 -0
- package/dist/primitives/toast.js +142 -0
- package/dist/primitives/toolbar.d.ts +55 -0
- package/dist/primitives/toolbar.js +37 -0
- package/dist/primitives/upload-progress.d.ts +23 -0
- package/dist/primitives/upload-progress.js +72 -0
- package/dist/primitives.d.ts +35 -5
- package/dist/primitives.js +35 -9
- package/dist/{index-COgqsFAQ.d.ts → redaction/redacted-document.d.ts} +6 -7
- package/dist/{redaction-CGGB2ENG.js → redaction/redacted-document.js} +2 -2
- package/dist/redaction.d.ts +1 -1
- package/dist/redaction.js +1 -1
- package/dist/run/expandable-content.js +41 -0
- package/dist/run/expanded-tool-detail.d.ts +12 -0
- package/dist/run/expanded-tool-detail.js +163 -0
- package/dist/run/inline-thinking-item.d.ts +11 -0
- package/dist/run/inline-thinking-item.js +60 -0
- package/dist/run/inline-tool-item.d.ts +25 -0
- package/dist/run/inline-tool-item.js +63 -0
- package/dist/run/run-group.d.ts +26 -0
- package/dist/{run-group-BWGeesgs.js → run/run-group.js} +9 -60
- package/dist/run/run-item-primitives.d.ts +5 -0
- package/dist/{run-ZsIKPA6J.js → run/run-item-primitives.js} +2 -2
- package/dist/run/run-row-shell.d.ts +53 -0
- package/dist/run/run-row-shell.js +114 -0
- package/dist/{tool-call-feed-BeB1_4pX.d.ts → run/tool-call-feed.d.ts} +7 -12
- package/dist/{tool-call-feed-BpmMLpPX.js → run/tool-call-feed.js} +4 -4
- package/dist/run/tool-call-step.d.ts +5 -0
- package/dist/run/tool-call-step.js +82 -0
- package/dist/run.d.ts +8 -2
- package/dist/run.js +7 -4
- package/dist/sdk-hooks.d.ts +8 -1
- package/dist/sdk-hooks.js +8 -2
- package/dist/stores/active-sessions-store.d.ts +83 -0
- package/dist/{active-sessions-store-Gt1R0rFG.js → stores/active-sessions-store.js} +1 -1
- package/dist/stores/chat-store.d.ts +14 -0
- package/dist/stores/chat-store.js +33 -0
- package/dist/stores.d.ts +3 -16
- package/dist/stores.js +2 -33
- package/dist/tool-previews/command-preview.d.ts +11 -0
- package/dist/tool-previews/command-preview.js +91 -0
- package/dist/tool-previews/diff-preview.d.ts +7 -0
- package/dist/tool-previews/diff-preview.js +76 -0
- package/dist/tool-previews/glob-results-preview.d.ts +7 -0
- package/dist/tool-previews/glob-results-preview.js +53 -0
- package/dist/tool-previews/grep-results-preview.d.ts +7 -0
- package/dist/tool-previews/grep-results-preview.js +99 -0
- package/dist/tool-previews/preview-primitives.js +58 -0
- package/dist/tool-previews/question-preview.d.ts +7 -0
- package/dist/tool-previews/question-preview.js +63 -0
- package/dist/tool-previews/web-search-preview.d.ts +7 -0
- package/dist/tool-previews/web-search-preview.js +78 -0
- package/dist/tool-previews/write-file-preview.d.ts +11 -0
- package/dist/tool-previews/write-file-preview.js +52 -0
- package/dist/tool-previews.d.ts +7 -1
- package/dist/tool-previews.js +7 -1
- package/dist/{branding-26d5ARIr.d.ts → types/branding.d.ts} +2 -3
- package/dist/{message-vhUI0c5G.d.ts → types/message.d.ts} +2 -3
- package/dist/{parts-5mhy9yJ3.d.ts → types/parts.d.ts} +8 -9
- package/dist/{run-OyWmIDqu.d.ts → types/run.d.ts} +9 -10
- package/dist/{tool-display-DgmL5rIU.d.ts → types/tool-display.d.ts} +5 -6
- package/dist/types.d.ts +5 -5
- package/dist/utils/copy-text.d.ts +7 -0
- package/dist/{utils-Bl_CZ0Qp.js → utils/copy-text.js} +1 -11
- package/dist/utils/format.d.ts +22 -0
- package/dist/{format-DfcLWqMa.js → utils/format.js} +1 -1
- package/dist/utils/time-ago.d.ts +3 -0
- package/dist/utils/time-ago.js +11 -0
- package/dist/utils/tool-display.d.ts +16 -0
- package/dist/{tool-display-BAuAVa43.js → utils/tool-display.js} +1 -1
- package/dist/utils.d.ts +6 -1
- package/dist/utils.js +6 -5
- package/package.json +2 -2
- package/src/files/rich-file-tree.stories.tsx +1 -1
- package/src/files/rich-file-tree.tsx +12 -9
- package/src/markdown/code-block.test.tsx +46 -2
- package/src/markdown/code-block.tsx +23 -60
- package/src/primitives/button.stories.tsx +37 -1
- package/src/primitives/button.test.tsx +230 -0
- package/src/primitives/button.tsx +62 -14
- package/src/primitives/card-anatomy.stories.tsx +51 -0
- package/src/primitives/card.test.tsx +71 -0
- package/src/primitives/card.tsx +25 -13
- package/src/primitives/heading.stories.tsx +35 -0
- package/src/primitives/heading.test.tsx +56 -0
- package/src/primitives/heading.tsx +76 -0
- package/src/primitives/index.ts +8 -0
- package/src/primitives/input.stories.tsx +28 -0
- package/src/primitives/input.test.tsx +161 -0
- package/src/primitives/input.tsx +34 -28
- package/src/primitives/page-header.stories.tsx +51 -0
- package/src/primitives/page-header.test.tsx +48 -0
- package/src/primitives/page-header.tsx +35 -35
- package/src/primitives/page-shell.stories.tsx +89 -0
- package/src/primitives/page-shell.test.tsx +24 -0
- package/src/primitives/page-shell.tsx +26 -0
- package/src/primitives/table-wrapper.stories.tsx +54 -0
- package/src/primitives/table.test.tsx +72 -0
- package/src/primitives/table.tsx +33 -12
- package/src/primitives/theme-toggle.test.tsx +167 -0
- package/src/primitives/theme-toggle.tsx +111 -39
- package/dist/active-sessions-store-nl70ZnMC.d.ts +0 -84
- package/dist/button-C87nEe2R.js +0 -78
- package/dist/chat-DDvF2oGQ.js +0 -672
- package/dist/diff-preview-BcK3nRXb.js +0 -533
- package/dist/document-editor-pane-BilJfiCo.d.ts +0 -136
- package/dist/document-editor-pane-POsq5Q0o.js +0 -1279
- package/dist/files-hywocVZz.js +0 -753
- package/dist/index-2UntyjBb.d.ts +0 -52
- package/dist/index-BgUHilZm.d.ts +0 -108
- package/dist/index-CJ8wRfiC.d.ts +0 -236
- package/dist/index-CPDET_s1.d.ts +0 -549
- package/dist/index-Cg6gYAqh.d.ts +0 -73
- package/dist/index-Cs7j8V7l.d.ts +0 -203
- package/dist/index-DjKxO357.d.ts +0 -128
- package/dist/primitives-Bx59fT-U.js +0 -1239
- package/dist/table-Bss73DhB.js +0 -146
- package/dist/tool-call-step-DNebqhmX.js +0 -434
- package/dist/use-auto-scroll-C5Pjeqon.js +0 -153
- package/dist/use-sse-stream-DjqRuDft.js +0 -884
- package/dist/use-sse-stream-Dm6R5YWz.d.ts +0 -282
|
@@ -0,0 +1,309 @@
|
|
|
1
|
+
import { focusRing } from "../lib/focus.js";
|
|
2
|
+
import { cn } from "../lib/utils.js";
|
|
3
|
+
import { getToolDisplayMetadata } from "../utils/tool-display.js";
|
|
4
|
+
import { useRunGroups } from "../hooks/use-run-groups.js";
|
|
5
|
+
import { useRunCollapseState } from "../hooks/use-run-collapse-state.js";
|
|
6
|
+
import { useAutoScroll } from "../hooks/use-auto-scroll.js";
|
|
7
|
+
import { InlineThinkingItem } from "../run/inline-thinking-item.js";
|
|
8
|
+
import { OpenUIArtifactRenderer } from "../openui/openui-artifact-renderer.js";
|
|
9
|
+
import { MessageList } from "./message-list.js";
|
|
10
|
+
import { AgentTimeline } from "./agent-timeline.js";
|
|
11
|
+
import { memo, useMemo, useRef } from "react";
|
|
12
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
13
|
+
import { ArrowDown } from "lucide-react";
|
|
14
|
+
//#region src/chat/chat-container.tsx
|
|
15
|
+
const OPENUI_NODE_TYPES = /* @__PURE__ */ new Set([
|
|
16
|
+
"heading",
|
|
17
|
+
"text",
|
|
18
|
+
"badge",
|
|
19
|
+
"stat",
|
|
20
|
+
"key_value",
|
|
21
|
+
"code",
|
|
22
|
+
"markdown",
|
|
23
|
+
"table",
|
|
24
|
+
"actions",
|
|
25
|
+
"separator",
|
|
26
|
+
"stack",
|
|
27
|
+
"grid",
|
|
28
|
+
"card"
|
|
29
|
+
]);
|
|
30
|
+
function isOpenUINode(value) {
|
|
31
|
+
return typeof value === "object" && value !== null && "type" in value && typeof value.type === "string" && OPENUI_NODE_TYPES.has(value.type);
|
|
32
|
+
}
|
|
33
|
+
function extractOpenUISchema(output) {
|
|
34
|
+
if (output == null) return null;
|
|
35
|
+
if (isOpenUINode(output)) return [output];
|
|
36
|
+
if (Array.isArray(output) && output.length > 0 && output.every(isOpenUINode)) return output;
|
|
37
|
+
if (typeof output === "object" && !Array.isArray(output)) {
|
|
38
|
+
const obj = output;
|
|
39
|
+
for (const key of [
|
|
40
|
+
"openui",
|
|
41
|
+
"schema",
|
|
42
|
+
"ui"
|
|
43
|
+
]) if (obj[key]) {
|
|
44
|
+
const inner = obj[key];
|
|
45
|
+
if (isOpenUINode(inner)) return [inner];
|
|
46
|
+
if (Array.isArray(inner) && inner.length > 0 && inner.every(isOpenUINode)) return inner;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
if (typeof output === "string") try {
|
|
50
|
+
return extractOpenUISchema(JSON.parse(output));
|
|
51
|
+
} catch {
|
|
52
|
+
return null;
|
|
53
|
+
}
|
|
54
|
+
return null;
|
|
55
|
+
}
|
|
56
|
+
function formatUnknown(value) {
|
|
57
|
+
if (value == null) return void 0;
|
|
58
|
+
if (typeof value === "string") return value;
|
|
59
|
+
try {
|
|
60
|
+
return JSON.stringify(value, null, 2);
|
|
61
|
+
} catch {
|
|
62
|
+
return String(value);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
function createdAtFromMessage(message) {
|
|
66
|
+
return message.time?.created ? new Date(message.time.created) : void 0;
|
|
67
|
+
}
|
|
68
|
+
function mapToolPartToTimelineType(part) {
|
|
69
|
+
switch (part.tool.toLowerCase().replace(/^tool:/, "")) {
|
|
70
|
+
case "bash":
|
|
71
|
+
case "shell":
|
|
72
|
+
case "command":
|
|
73
|
+
case "execute": return "bash";
|
|
74
|
+
case "write":
|
|
75
|
+
case "write_file":
|
|
76
|
+
case "create_file": return "write";
|
|
77
|
+
case "read":
|
|
78
|
+
case "read_file":
|
|
79
|
+
case "cat": return "read";
|
|
80
|
+
case "edit":
|
|
81
|
+
case "patch":
|
|
82
|
+
case "sed": return "edit";
|
|
83
|
+
case "glob":
|
|
84
|
+
case "find": return "glob";
|
|
85
|
+
case "ls": return "list";
|
|
86
|
+
case "grep":
|
|
87
|
+
case "search":
|
|
88
|
+
case "rg": return "grep";
|
|
89
|
+
case "inspect": return "inspect";
|
|
90
|
+
default: return "unknown";
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
function buildTimelineItems(messages, partMap, isStreaming, onOpenUIAction, enableOpenUI = true) {
|
|
94
|
+
const items = [];
|
|
95
|
+
let latestUserIndex = -1;
|
|
96
|
+
for (let index = messages.length - 1; index >= 0; index -= 1) if (messages[index].role === "user") {
|
|
97
|
+
latestUserIndex = index;
|
|
98
|
+
break;
|
|
99
|
+
}
|
|
100
|
+
const lastAssistantMessage = [...latestUserIndex >= 0 ? messages.slice(latestUserIndex + 1) : messages].reverse().find((message) => message.role === "assistant");
|
|
101
|
+
const toToolCall = (part) => {
|
|
102
|
+
const meta = getToolDisplayMetadata(part);
|
|
103
|
+
const start = part.state.time?.start;
|
|
104
|
+
const end = part.state.time?.end;
|
|
105
|
+
return {
|
|
106
|
+
id: part.id,
|
|
107
|
+
type: mapToolPartToTimelineType(part),
|
|
108
|
+
label: meta.title,
|
|
109
|
+
status: part.state.status === "completed" ? "success" : part.state.status === "error" ? "error" : "running",
|
|
110
|
+
detail: meta.commandSnippet ?? meta.targetPath ?? meta.description,
|
|
111
|
+
output: formatUnknown(part.state.output),
|
|
112
|
+
duration: start && end ? end - start : void 0
|
|
113
|
+
};
|
|
114
|
+
};
|
|
115
|
+
for (const message of messages) {
|
|
116
|
+
const parts = partMap[message.id] ?? [];
|
|
117
|
+
if (message.role === "user") {
|
|
118
|
+
const content = parts.filter((part) => part.type === "text").map((part) => part.text).join("\n").trim();
|
|
119
|
+
if (!content) continue;
|
|
120
|
+
items.push({
|
|
121
|
+
id: message.id,
|
|
122
|
+
kind: "message",
|
|
123
|
+
role: "user",
|
|
124
|
+
content,
|
|
125
|
+
timestamp: createdAtFromMessage(message)
|
|
126
|
+
});
|
|
127
|
+
continue;
|
|
128
|
+
}
|
|
129
|
+
const toolBuffer = [];
|
|
130
|
+
const flushToolBuffer = (index) => {
|
|
131
|
+
if (toolBuffer.length === 0) return;
|
|
132
|
+
if (toolBuffer.length === 1) items.push({
|
|
133
|
+
id: `${message.id}-tool-${toolBuffer[0].id}`,
|
|
134
|
+
kind: "tool",
|
|
135
|
+
call: toToolCall(toolBuffer[0]),
|
|
136
|
+
part: toolBuffer[0]
|
|
137
|
+
});
|
|
138
|
+
else items.push({
|
|
139
|
+
id: `${message.id}-tool-group-${index}`,
|
|
140
|
+
kind: "tool_group",
|
|
141
|
+
title: "Tool activity",
|
|
142
|
+
parts: [...toolBuffer],
|
|
143
|
+
calls: toolBuffer.map((part) => toToolCall(part))
|
|
144
|
+
});
|
|
145
|
+
if (enableOpenUI) for (const part of toolBuffer) {
|
|
146
|
+
if (part.state.status !== "completed" || !part.state.output) continue;
|
|
147
|
+
const schema = extractOpenUISchema(part.state.output);
|
|
148
|
+
if (!schema) continue;
|
|
149
|
+
items.push({
|
|
150
|
+
id: `${message.id}-openui-${part.id}`,
|
|
151
|
+
kind: "custom",
|
|
152
|
+
content: /* @__PURE__ */ jsx("div", {
|
|
153
|
+
className: "my-2 rounded-[var(--radius-lg)] border border-border bg-card p-4 shadow-[var(--shadow-card)]",
|
|
154
|
+
children: /* @__PURE__ */ jsx(OpenUIArtifactRenderer, {
|
|
155
|
+
schema,
|
|
156
|
+
onAction: onOpenUIAction
|
|
157
|
+
})
|
|
158
|
+
})
|
|
159
|
+
});
|
|
160
|
+
}
|
|
161
|
+
toolBuffer.length = 0;
|
|
162
|
+
};
|
|
163
|
+
parts.forEach((part, index) => {
|
|
164
|
+
const itemId = `${message.id}-${index}`;
|
|
165
|
+
if (part.type === "tool") {
|
|
166
|
+
toolBuffer.push(part);
|
|
167
|
+
return;
|
|
168
|
+
}
|
|
169
|
+
flushToolBuffer(index);
|
|
170
|
+
if (part.type === "text" && !part.synthetic && part.text.trim()) {
|
|
171
|
+
if (enableOpenUI) {
|
|
172
|
+
const jsonMatch = part.text.match(/```(?:json)?\s*\n([\s\S]*?)\n```/);
|
|
173
|
+
if (jsonMatch) {
|
|
174
|
+
const schema = extractOpenUISchema(jsonMatch[1]);
|
|
175
|
+
if (schema) {
|
|
176
|
+
const beforeJson = part.text.slice(0, part.text.indexOf("```")).trim();
|
|
177
|
+
if (beforeJson) items.push({
|
|
178
|
+
id: `${itemId}-text`,
|
|
179
|
+
kind: "message",
|
|
180
|
+
role: "assistant",
|
|
181
|
+
content: beforeJson,
|
|
182
|
+
timestamp: createdAtFromMessage(message)
|
|
183
|
+
});
|
|
184
|
+
items.push({
|
|
185
|
+
id: `${itemId}-openui`,
|
|
186
|
+
kind: "custom",
|
|
187
|
+
content: /* @__PURE__ */ jsx("div", {
|
|
188
|
+
className: "my-2 rounded-[var(--radius-lg)] border border-border bg-card p-4 shadow-[var(--shadow-card)]",
|
|
189
|
+
children: /* @__PURE__ */ jsx(OpenUIArtifactRenderer, {
|
|
190
|
+
schema,
|
|
191
|
+
onAction: onOpenUIAction
|
|
192
|
+
})
|
|
193
|
+
})
|
|
194
|
+
});
|
|
195
|
+
const afterJson = part.text.slice(part.text.lastIndexOf("```") + 3).trim();
|
|
196
|
+
if (afterJson) items.push({
|
|
197
|
+
id: `${itemId}-after`,
|
|
198
|
+
kind: "message",
|
|
199
|
+
role: "assistant",
|
|
200
|
+
content: afterJson,
|
|
201
|
+
timestamp: createdAtFromMessage(message)
|
|
202
|
+
});
|
|
203
|
+
return;
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
items.push({
|
|
208
|
+
id: itemId,
|
|
209
|
+
kind: "message",
|
|
210
|
+
role: "assistant",
|
|
211
|
+
content: part.text,
|
|
212
|
+
timestamp: createdAtFromMessage(message),
|
|
213
|
+
isStreaming: isStreaming && lastAssistantMessage?.id === message.id && index === parts.length - 1
|
|
214
|
+
});
|
|
215
|
+
return;
|
|
216
|
+
}
|
|
217
|
+
if (part.type === "reasoning") {
|
|
218
|
+
items.push({
|
|
219
|
+
id: itemId,
|
|
220
|
+
kind: "custom",
|
|
221
|
+
content: /* @__PURE__ */ jsx(InlineThinkingItem, {
|
|
222
|
+
part,
|
|
223
|
+
defaultOpen: isStreaming && lastAssistantMessage?.id === message.id
|
|
224
|
+
})
|
|
225
|
+
});
|
|
226
|
+
return;
|
|
227
|
+
}
|
|
228
|
+
});
|
|
229
|
+
flushToolBuffer(parts.length);
|
|
230
|
+
}
|
|
231
|
+
return {
|
|
232
|
+
items,
|
|
233
|
+
showThinking: isStreaming && latestUserIndex >= 0 && (lastAssistantMessage == null || !items.some((item) => item.kind === "message" && item.role === "assistant" && item.id.startsWith(lastAssistantMessage.id)))
|
|
234
|
+
};
|
|
235
|
+
}
|
|
236
|
+
/**
|
|
237
|
+
* Chat transcript container: message list + auto-scroll.
|
|
238
|
+
* Orchestrates useRunGroups, useRunCollapseState, and useAutoScroll.
|
|
239
|
+
*/
|
|
240
|
+
const ChatContainer = memo(({ messages, partMap, isStreaming, branding, className, renderToolDetail, presentation = "runs", onOpenUIAction, enableOpenUI = true, renderRunActions, renderUserMessageActions, renderToolActions, renderTimelineToolActions, collapseTimelineAfter }) => {
|
|
241
|
+
const scrollRef = useRef(null);
|
|
242
|
+
const groups = useRunGroups({
|
|
243
|
+
messages,
|
|
244
|
+
partMap,
|
|
245
|
+
isStreaming
|
|
246
|
+
});
|
|
247
|
+
const runs = groups.filter((g) => g.type === "run").map((g) => g.run);
|
|
248
|
+
const { isCollapsed, toggleCollapse } = useRunCollapseState(runs);
|
|
249
|
+
const { isAtBottom, scrollToBottom } = useAutoScroll(scrollRef, [
|
|
250
|
+
messages,
|
|
251
|
+
partMap,
|
|
252
|
+
isStreaming
|
|
253
|
+
]);
|
|
254
|
+
const timeline = useMemo(() => buildTimelineItems(messages, partMap, isStreaming, onOpenUIAction, enableOpenUI), [
|
|
255
|
+
messages,
|
|
256
|
+
partMap,
|
|
257
|
+
isStreaming,
|
|
258
|
+
onOpenUIAction,
|
|
259
|
+
enableOpenUI
|
|
260
|
+
]);
|
|
261
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
262
|
+
className: cn("flex h-full flex-col", className),
|
|
263
|
+
children: [/* @__PURE__ */ jsx("div", {
|
|
264
|
+
ref: scrollRef,
|
|
265
|
+
className: "flex-1 overflow-y-auto [scrollbar-gutter:stable]",
|
|
266
|
+
children: messages.length === 0 ? /* @__PURE__ */ jsx("div", {
|
|
267
|
+
className: "flex h-full items-center justify-center",
|
|
268
|
+
children: /* @__PURE__ */ jsx("div", {
|
|
269
|
+
className: "max-w-md text-center",
|
|
270
|
+
children: /* @__PURE__ */ jsx("div", {
|
|
271
|
+
className: "text-sm font-medium text-muted-foreground",
|
|
272
|
+
children: "Start a conversation."
|
|
273
|
+
})
|
|
274
|
+
})
|
|
275
|
+
}) : presentation === "timeline" ? /* @__PURE__ */ jsx("div", {
|
|
276
|
+
className: "mx-auto flex min-h-full w-full max-w-3xl flex-col justify-end",
|
|
277
|
+
children: /* @__PURE__ */ jsx(AgentTimeline, {
|
|
278
|
+
items: timeline.items,
|
|
279
|
+
isThinking: timeline.showThinking,
|
|
280
|
+
renderToolActions: renderTimelineToolActions,
|
|
281
|
+
collapseAfter: collapseTimelineAfter
|
|
282
|
+
})
|
|
283
|
+
}) : /* @__PURE__ */ jsx("div", {
|
|
284
|
+
className: "mx-auto flex min-h-full w-full max-w-3xl flex-col justify-end",
|
|
285
|
+
children: /* @__PURE__ */ jsx(MessageList, {
|
|
286
|
+
groups,
|
|
287
|
+
partMap,
|
|
288
|
+
isCollapsed,
|
|
289
|
+
onToggleCollapse: toggleCollapse,
|
|
290
|
+
branding,
|
|
291
|
+
renderToolDetail,
|
|
292
|
+
renderRunActions,
|
|
293
|
+
renderUserMessageActions,
|
|
294
|
+
renderToolActions
|
|
295
|
+
})
|
|
296
|
+
})
|
|
297
|
+
}), !isAtBottom && /* @__PURE__ */ jsx("div", {
|
|
298
|
+
className: "relative z-10 -mt-10 flex justify-center",
|
|
299
|
+
children: /* @__PURE__ */ jsxs("button", {
|
|
300
|
+
onClick: scrollToBottom,
|
|
301
|
+
className: cn("flex items-center gap-1.5 px-3 py-1.5 rounded-full", "border border-border bg-card shadow-[0_6px_16px_rgba(15,23,42,0.08)]", "text-xs text-foreground transition-colors hover:bg-accent", focusRing),
|
|
302
|
+
children: [/* @__PURE__ */ jsx(ArrowDown, { className: "w-3 h-3" }), "Scroll to bottom"]
|
|
303
|
+
})
|
|
304
|
+
})]
|
|
305
|
+
});
|
|
306
|
+
});
|
|
307
|
+
ChatContainer.displayName = "ChatContainer";
|
|
308
|
+
//#endregion
|
|
309
|
+
export { ChatContainer };
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { ReactNode } from "react";
|
|
2
|
+
//#region src/chat/chat-message.d.ts
|
|
3
|
+
export type MessageRole = "user" | "assistant" | "system";
|
|
4
|
+
export interface ChatMessageProps {
|
|
5
|
+
role: MessageRole;
|
|
6
|
+
content: string;
|
|
7
|
+
/** Inline tool call activity rendered between text chunks */
|
|
8
|
+
toolCalls?: ReactNode;
|
|
9
|
+
/** Whether the message is still streaming */
|
|
10
|
+
isStreaming?: boolean;
|
|
11
|
+
/** Timestamp */
|
|
12
|
+
timestamp?: Date;
|
|
13
|
+
className?: string;
|
|
14
|
+
/** Custom user label. Default: "You" */
|
|
15
|
+
userLabel?: string;
|
|
16
|
+
/** Custom assistant label. Default: "Agent" */
|
|
17
|
+
assistantLabel?: string;
|
|
18
|
+
/** Hide the role label row entirely */
|
|
19
|
+
hideRoleLabel?: boolean;
|
|
20
|
+
}
|
|
21
|
+
export declare function ChatMessage({ role, content, toolCalls, isStreaming, timestamp, className, userLabel, assistantLabel, hideRoleLabel }: ChatMessageProps): import("react").JSX.Element;
|
|
22
|
+
//#endregion
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { cn } from "../lib/utils.js";
|
|
2
|
+
import { Markdown } from "../markdown/markdown.js";
|
|
3
|
+
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
4
|
+
//#region src/chat/chat-message.tsx
|
|
5
|
+
function ChatMessage({ role, content, toolCalls, isStreaming, timestamp, className, userLabel = "You", assistantLabel = "Agent", hideRoleLabel }) {
|
|
6
|
+
const isUser = role === "user";
|
|
7
|
+
const isAssistant = role === "assistant";
|
|
8
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
9
|
+
className: cn("flex flex-col gap-1", isUser ? "items-end" : "items-start", className),
|
|
10
|
+
children: [!hideRoleLabel && /* @__PURE__ */ jsxs("div", {
|
|
11
|
+
className: cn("flex items-center gap-2 px-1", isUser && "flex-row-reverse"),
|
|
12
|
+
children: [/* @__PURE__ */ jsx("span", {
|
|
13
|
+
className: "font-medium text-foreground text-xs",
|
|
14
|
+
children: isUser ? userLabel : assistantLabel
|
|
15
|
+
}), timestamp && /* @__PURE__ */ jsx("span", {
|
|
16
|
+
className: "text-muted-foreground text-xs",
|
|
17
|
+
children: formatTime(timestamp)
|
|
18
|
+
})]
|
|
19
|
+
}), /* @__PURE__ */ jsxs("div", {
|
|
20
|
+
className: cn("min-w-0 max-w-[85%] space-y-1", isUser ? "rounded-[var(--radius-lg)] bg-foreground px-[var(--chat-message-px)] py-[var(--chat-message-py)] text-background" : isAssistant ? "text-foreground" : "rounded-[var(--radius-lg)] border border-border bg-card px-[var(--chat-message-px)] py-[var(--chat-message-py)]"),
|
|
21
|
+
children: [isUser ? /* @__PURE__ */ jsx("div", {
|
|
22
|
+
className: "whitespace-pre-wrap text-[var(--font-size-base)] leading-[var(--line-height-base)]",
|
|
23
|
+
children: content
|
|
24
|
+
}) : /* @__PURE__ */ jsxs(Fragment, { children: [content && /* @__PURE__ */ jsx(Markdown, {
|
|
25
|
+
className: "tangle-prose text-[var(--font-size-base)] leading-[var(--line-height-base)]",
|
|
26
|
+
children: content
|
|
27
|
+
}), isStreaming && /* @__PURE__ */ jsx("span", { className: "ml-0.5 inline-block h-4 w-2 animate-pulse rounded-sm bg-[var(--brand-cool)] align-text-bottom" })] }), toolCalls]
|
|
28
|
+
})]
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
function formatTime(date) {
|
|
32
|
+
return date.toLocaleTimeString(void 0, {
|
|
33
|
+
hour: "numeric",
|
|
34
|
+
minute: "2-digit"
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
//#endregion
|
|
38
|
+
export { ChatMessage };
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { SessionMessage } from "../types/message.js";
|
|
2
|
+
import { SessionPart, ToolPart } from "../types/parts.js";
|
|
3
|
+
import { AgentBranding } from "../types/branding.js";
|
|
4
|
+
import { CustomToolRenderer } from "../types/tool-display.js";
|
|
5
|
+
import { GroupedMessage } from "../types/run.js";
|
|
6
|
+
import { ReactNode } from "react";
|
|
7
|
+
//#region src/chat/message-list.d.ts
|
|
8
|
+
export interface MessageListProps {
|
|
9
|
+
groups: GroupedMessage[];
|
|
10
|
+
partMap: Record<string, SessionPart[]>;
|
|
11
|
+
isCollapsed: (runId: string) => boolean;
|
|
12
|
+
onToggleCollapse: (runId: string) => void;
|
|
13
|
+
branding?: AgentBranding;
|
|
14
|
+
renderToolDetail?: CustomToolRenderer;
|
|
15
|
+
renderRunActions?: (group: Extract<GroupedMessage, {
|
|
16
|
+
type: "run";
|
|
17
|
+
}>["run"]) => ReactNode;
|
|
18
|
+
renderUserMessageActions?: (message: SessionMessage, parts: SessionPart[]) => ReactNode;
|
|
19
|
+
renderToolActions?: (part: ToolPart, options: {
|
|
20
|
+
run: Extract<GroupedMessage, {
|
|
21
|
+
type: "run";
|
|
22
|
+
}>["run"];
|
|
23
|
+
messageId: string;
|
|
24
|
+
partIndex: number;
|
|
25
|
+
}) => ReactNode;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Maps GroupedMessage[] to UserMessage and RunGroup components.
|
|
29
|
+
* This is the main render list for the chat view.
|
|
30
|
+
*/
|
|
31
|
+
export declare const MessageList: import("react").MemoExoticComponent<({ groups, partMap, isCollapsed, onToggleCollapse, branding, renderToolDetail, renderRunActions, renderUserMessageActions, renderToolActions }: MessageListProps) => import("react").JSX.Element>;
|
|
32
|
+
//#endregion
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { RunGroup } from "../run/run-group.js";
|
|
2
|
+
import { UserMessage } from "./user-message.js";
|
|
3
|
+
import { memo } from "react";
|
|
4
|
+
import { jsx } from "react/jsx-runtime";
|
|
5
|
+
//#region src/chat/message-list.tsx
|
|
6
|
+
/**
|
|
7
|
+
* Maps GroupedMessage[] to UserMessage and RunGroup components.
|
|
8
|
+
* This is the main render list for the chat view.
|
|
9
|
+
*/
|
|
10
|
+
const MessageList = memo(({ groups, partMap, isCollapsed, onToggleCollapse, branding, renderToolDetail, renderRunActions, renderUserMessageActions, renderToolActions }) => {
|
|
11
|
+
return /* @__PURE__ */ jsx("div", {
|
|
12
|
+
className: "space-y-4",
|
|
13
|
+
children: groups.map((group) => {
|
|
14
|
+
if (group.type === "user") {
|
|
15
|
+
const messageParts = partMap[group.message.id] ?? [];
|
|
16
|
+
return /* @__PURE__ */ jsx(UserMessage, {
|
|
17
|
+
message: group.message,
|
|
18
|
+
parts: messageParts,
|
|
19
|
+
actions: renderUserMessageActions?.(group.message, messageParts)
|
|
20
|
+
}, group.message.id);
|
|
21
|
+
}
|
|
22
|
+
return /* @__PURE__ */ jsx(RunGroup, {
|
|
23
|
+
run: group.run,
|
|
24
|
+
partMap,
|
|
25
|
+
collapsed: isCollapsed(group.run.id),
|
|
26
|
+
onToggle: () => onToggleCollapse(group.run.id),
|
|
27
|
+
branding,
|
|
28
|
+
renderToolDetail,
|
|
29
|
+
headerActions: renderRunActions?.(group.run),
|
|
30
|
+
renderToolActions
|
|
31
|
+
}, group.run.id);
|
|
32
|
+
})
|
|
33
|
+
});
|
|
34
|
+
});
|
|
35
|
+
MessageList.displayName = "MessageList";
|
|
36
|
+
//#endregion
|
|
37
|
+
export { MessageList };
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { cn } from "../lib/utils.js";
|
|
2
|
+
import { useEffect, useState } from "react";
|
|
3
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
4
|
+
//#region src/chat/thinking-indicator.tsx
|
|
5
|
+
function ThinkingIndicator({ className }) {
|
|
6
|
+
const [elapsed, setElapsed] = useState(0);
|
|
7
|
+
useEffect(() => {
|
|
8
|
+
const interval = window.setInterval(() => setElapsed((current) => current + 1), 1e3);
|
|
9
|
+
return () => window.clearInterval(interval);
|
|
10
|
+
}, []);
|
|
11
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
12
|
+
role: "status",
|
|
13
|
+
"aria-label": "Agent is thinking",
|
|
14
|
+
className: cn("flex items-center gap-2 px-3 py-1.5", className),
|
|
15
|
+
children: [/* @__PURE__ */ jsxs("div", {
|
|
16
|
+
className: "flex gap-[3px]",
|
|
17
|
+
children: [
|
|
18
|
+
/* @__PURE__ */ jsx("span", {
|
|
19
|
+
className: "h-[var(--indicator-dot-size)] w-[var(--indicator-dot-size)] animate-bounce rounded-full bg-[var(--brand-glow)]",
|
|
20
|
+
style: { animationDelay: "0ms" }
|
|
21
|
+
}),
|
|
22
|
+
/* @__PURE__ */ jsx("span", {
|
|
23
|
+
className: "h-[var(--indicator-dot-size)] w-[var(--indicator-dot-size)] animate-bounce rounded-full bg-[var(--brand-glow)]",
|
|
24
|
+
style: { animationDelay: "150ms" }
|
|
25
|
+
}),
|
|
26
|
+
/* @__PURE__ */ jsx("span", {
|
|
27
|
+
className: "h-[var(--indicator-dot-size)] w-[var(--indicator-dot-size)] animate-bounce rounded-full bg-[var(--brand-glow)]",
|
|
28
|
+
style: { animationDelay: "300ms" }
|
|
29
|
+
})
|
|
30
|
+
]
|
|
31
|
+
}), elapsed > 3 && /* @__PURE__ */ jsxs("span", {
|
|
32
|
+
className: "text-[var(--font-size-xs)] tabular-nums text-muted-foreground",
|
|
33
|
+
children: [elapsed, "s"]
|
|
34
|
+
})]
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
//#endregion
|
|
38
|
+
export { ThinkingIndicator };
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { SessionMessage } from "../types/message.js";
|
|
2
|
+
import { SessionPart } from "../types/parts.js";
|
|
3
|
+
import { ReactNode } from "react";
|
|
4
|
+
//#region src/chat/user-message.d.ts
|
|
5
|
+
export interface UserMessageProps {
|
|
6
|
+
/** Session-model input: text is derived from these parts. */
|
|
7
|
+
message?: SessionMessage;
|
|
8
|
+
parts?: SessionPart[];
|
|
9
|
+
/** Direct-content input (e.g. AgentTimeline): explicit text + timestamp. */
|
|
10
|
+
content?: string;
|
|
11
|
+
timestamp?: Date;
|
|
12
|
+
actions?: ReactNode;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* The single user message bubble uses inverse theme colors. The timestamp sits
|
|
16
|
+
* beside the bubble and appears on hover, so it costs no height. Used by both
|
|
17
|
+
* the run/message list (session-model `parts`) and AgentTimeline (direct
|
|
18
|
+
* `content`/`timestamp`).
|
|
19
|
+
*/
|
|
20
|
+
export declare const UserMessage: import("react").MemoExoticComponent<({ message: _message, parts, content, timestamp, actions }: UserMessageProps) => import("react").JSX.Element | null>;
|
|
21
|
+
//#endregion
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { memo } from "react";
|
|
2
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
3
|
+
//#region src/chat/user-message.tsx
|
|
4
|
+
function formatTime(date) {
|
|
5
|
+
return date.toLocaleTimeString(void 0, {
|
|
6
|
+
hour: "numeric",
|
|
7
|
+
minute: "2-digit"
|
|
8
|
+
});
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* The single user message bubble uses inverse theme colors. The timestamp sits
|
|
12
|
+
* beside the bubble and appears on hover, so it costs no height. Used by both
|
|
13
|
+
* the run/message list (session-model `parts`) and AgentTimeline (direct
|
|
14
|
+
* `content`/`timestamp`).
|
|
15
|
+
*/
|
|
16
|
+
const UserMessage = memo(({ message: _message, parts, content, timestamp, actions }) => {
|
|
17
|
+
const text = content ?? (parts ?? []).filter((p) => p.type === "text").map((p) => p.text).join("\n");
|
|
18
|
+
if (!text.trim()) return null;
|
|
19
|
+
return /* @__PURE__ */ jsx("div", {
|
|
20
|
+
className: "flex justify-end",
|
|
21
|
+
children: /* @__PURE__ */ jsxs("div", {
|
|
22
|
+
className: "group flex min-w-0 max-w-[78%] flex-col items-end gap-2",
|
|
23
|
+
children: [/* @__PURE__ */ jsxs("div", {
|
|
24
|
+
className: "relative w-full min-w-0 rounded-2xl bg-foreground px-4 py-3 text-background",
|
|
25
|
+
children: [timestamp ? /* @__PURE__ */ jsx("span", {
|
|
26
|
+
"data-user-message-time": "",
|
|
27
|
+
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",
|
|
28
|
+
children: formatTime(timestamp)
|
|
29
|
+
}) : null, /* @__PURE__ */ jsx("div", {
|
|
30
|
+
className: "break-words whitespace-pre-wrap text-[var(--font-size-base)] leading-[1.5]",
|
|
31
|
+
children: text
|
|
32
|
+
})]
|
|
33
|
+
}), actions ? /* @__PURE__ */ jsx("div", {
|
|
34
|
+
className: "flex flex-wrap items-center justify-end gap-1.5 text-xs text-muted-foreground",
|
|
35
|
+
children: actions
|
|
36
|
+
}) : null]
|
|
37
|
+
})
|
|
38
|
+
});
|
|
39
|
+
});
|
|
40
|
+
UserMessage.displayName = "UserMessage";
|
|
41
|
+
//#endregion
|
|
42
|
+
export { UserMessage };
|
package/dist/chat.d.ts
CHANGED
|
@@ -1,2 +1,7 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { ChatContainer, ChatContainerProps } from "./chat/chat-container.js";
|
|
2
|
+
import { MessageList, MessageListProps } from "./chat/message-list.js";
|
|
3
|
+
import { UserMessage, UserMessageProps } from "./chat/user-message.js";
|
|
4
|
+
import { ChatMessage, ChatMessageProps, MessageRole } from "./chat/chat-message.js";
|
|
5
|
+
import { ThinkingIndicator, ThinkingIndicatorProps } from "./chat/thinking-indicator.js";
|
|
6
|
+
import { AgentTimeline, AgentTimelineArtifactItem, AgentTimelineCustomItem, AgentTimelineItem, AgentTimelineMessageItem, AgentTimelineProps, AgentTimelineStatusItem, AgentTimelineTone, AgentTimelineToolGroupItem, AgentTimelineToolItem } from "./chat/agent-timeline.js";
|
|
2
7
|
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,7 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { UserMessage } from "./chat/user-message.js";
|
|
2
|
+
import { MessageList } from "./chat/message-list.js";
|
|
3
|
+
import { ThinkingIndicator } from "./chat/thinking-indicator.js";
|
|
4
|
+
import { AgentTimeline } from "./chat/agent-timeline.js";
|
|
5
|
+
import { ChatContainer } from "./chat/chat-container.js";
|
|
6
|
+
import { ChatMessage } from "./chat/chat-message.js";
|
|
2
7
|
export { AgentTimeline, ChatContainer, ChatMessage, MessageList, ThinkingIndicator, UserMessage };
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { EditorProviderProps } from "./editor-provider.js";
|
|
2
|
+
import { ArtifactPaneProps } from "../primitives/artifact-pane.js";
|
|
3
|
+
import { ReactNode } from "react";
|
|
4
|
+
import { UrlTransform } from "react-markdown";
|
|
5
|
+
//#region src/editor/document-editor-pane.d.ts
|
|
6
|
+
export type DocumentEditorMode = "preview" | "edit";
|
|
7
|
+
export type DocumentEditorBackend = "local" | "collaborative";
|
|
8
|
+
export interface DocumentEditorPaneCollaborationConfig extends Omit<EditorProviderProps, "children"> {}
|
|
9
|
+
export interface DocumentEditorPaneProps extends Omit<ArtifactPaneProps, "children" | "tabs" | "toolbar" | "emptyState"> {
|
|
10
|
+
tabs?: ArtifactPaneProps["tabs"];
|
|
11
|
+
toolbar?: ReactNode;
|
|
12
|
+
markdown?: string;
|
|
13
|
+
/** Persisted baseline when the host controls the current markdown draft. */
|
|
14
|
+
savedMarkdown?: string;
|
|
15
|
+
/** Transform Markdown links and images through the shared URL policy. */
|
|
16
|
+
urlTransform?: UrlTransform;
|
|
17
|
+
mode?: DocumentEditorMode;
|
|
18
|
+
defaultMode?: DocumentEditorMode;
|
|
19
|
+
onModeChange?: (mode: DocumentEditorMode) => void;
|
|
20
|
+
backend?: DocumentEditorBackend;
|
|
21
|
+
placeholder?: string;
|
|
22
|
+
autoFocus?: boolean;
|
|
23
|
+
readOnly?: boolean;
|
|
24
|
+
onChange?: (markdown: string) => void;
|
|
25
|
+
onSave?: (markdown: string) => Promise<void> | void;
|
|
26
|
+
saving?: boolean;
|
|
27
|
+
saveLabel?: string;
|
|
28
|
+
previewClassName?: string;
|
|
29
|
+
editorClassName?: string;
|
|
30
|
+
collaboration?: DocumentEditorPaneCollaborationConfig;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* DocumentEditorPane — reusable markdown document surface with preview/edit
|
|
34
|
+
* modes and optional collaborative editing backed by Yjs/Hocuspocus.
|
|
35
|
+
*/
|
|
36
|
+
export declare function DocumentEditorPane({ eyebrow, title, subtitle, meta, headerActions, footer, className, contentClassName, headerClassName, hideTitleBlock, tabs, toolbar, markdown, savedMarkdown, urlTransform, mode, defaultMode, onModeChange, backend, placeholder, autoFocus, readOnly, onChange, onSave, saving, saveLabel, previewClassName, editorClassName, collaboration }: DocumentEditorPaneProps): import("react").JSX.Element;
|
|
37
|
+
//#endregion
|