@schlessera/brain-ui-react 0.4.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/LICENSE +21 -0
- package/README.md +70 -0
- package/dist/components/chat/ask-user-card.d.ts +12 -0
- package/dist/components/chat/ask-user-card.d.ts.map +1 -0
- package/dist/components/chat/ask-user-card.js +185 -0
- package/dist/components/chat/ask-user-card.js.map +1 -0
- package/dist/components/chat/brain-markdown.d.ts +35 -0
- package/dist/components/chat/brain-markdown.d.ts.map +1 -0
- package/dist/components/chat/brain-markdown.js +363 -0
- package/dist/components/chat/brain-markdown.js.map +1 -0
- package/dist/components/chat/chat-page.d.ts +2 -0
- package/dist/components/chat/chat-page.d.ts.map +1 -0
- package/dist/components/chat/chat-page.js +442 -0
- package/dist/components/chat/chat-page.js.map +1 -0
- package/dist/components/chat/command-palette.d.ts +5 -0
- package/dist/components/chat/command-palette.d.ts.map +1 -0
- package/dist/components/chat/command-palette.js +18 -0
- package/dist/components/chat/command-palette.js.map +1 -0
- package/dist/components/chat/markdown-content.d.ts +4 -0
- package/dist/components/chat/markdown-content.d.ts.map +1 -0
- package/dist/components/chat/markdown-content.js +6 -0
- package/dist/components/chat/markdown-content.js.map +1 -0
- package/dist/components/chat/message-bubble.d.ts +9 -0
- package/dist/components/chat/message-bubble.d.ts.map +1 -0
- package/dist/components/chat/message-bubble.js +129 -0
- package/dist/components/chat/message-bubble.js.map +1 -0
- package/dist/components/chat/message-share.d.ts +10 -0
- package/dist/components/chat/message-share.d.ts.map +1 -0
- package/dist/components/chat/message-share.js +65 -0
- package/dist/components/chat/message-share.js.map +1 -0
- package/dist/components/chat/renderers/claude-tools.d.ts +3 -0
- package/dist/components/chat/renderers/claude-tools.d.ts.map +1 -0
- package/dist/components/chat/renderers/claude-tools.js +38 -0
- package/dist/components/chat/renderers/claude-tools.js.map +1 -0
- package/dist/components/chat/renderers/generic.d.ts +9 -0
- package/dist/components/chat/renderers/generic.d.ts.map +1 -0
- package/dist/components/chat/renderers/generic.js +68 -0
- package/dist/components/chat/renderers/generic.js.map +1 -0
- package/dist/components/chat/renderers/index.d.ts +5 -0
- package/dist/components/chat/renderers/index.d.ts.map +1 -0
- package/dist/components/chat/renderers/index.js +17 -0
- package/dist/components/chat/renderers/index.js.map +1 -0
- package/dist/components/chat/risk-hints.d.ts +20 -0
- package/dist/components/chat/risk-hints.d.ts.map +1 -0
- package/dist/components/chat/risk-hints.js +81 -0
- package/dist/components/chat/risk-hints.js.map +1 -0
- package/dist/components/chat/session-drawer.d.ts +6 -0
- package/dist/components/chat/session-drawer.d.ts.map +1 -0
- package/dist/components/chat/session-drawer.js +96 -0
- package/dist/components/chat/session-drawer.js.map +1 -0
- package/dist/components/chat/share-block.d.ts +9 -0
- package/dist/components/chat/share-block.d.ts.map +1 -0
- package/dist/components/chat/share-block.js +70 -0
- package/dist/components/chat/share-block.js.map +1 -0
- package/dist/components/chat/tool-call-timeline.d.ts +8 -0
- package/dist/components/chat/tool-call-timeline.d.ts.map +1 -0
- package/dist/components/chat/tool-call-timeline.js +100 -0
- package/dist/components/chat/tool-call-timeline.js.map +1 -0
- package/dist/components/chat/tool-views.d.ts +116 -0
- package/dist/components/chat/tool-views.d.ts.map +1 -0
- package/dist/components/chat/tool-views.js +628 -0
- package/dist/components/chat/tool-views.js.map +1 -0
- package/dist/components/chat/welcome-state.d.ts +4 -0
- package/dist/components/chat/welcome-state.d.ts.map +1 -0
- package/dist/components/chat/welcome-state.js +10 -0
- package/dist/components/chat/welcome-state.js.map +1 -0
- package/dist/components/connectivity/connection-gate.d.ts +5 -0
- package/dist/components/connectivity/connection-gate.d.ts.map +1 -0
- package/dist/components/connectivity/connection-gate.js +42 -0
- package/dist/components/connectivity/connection-gate.js.map +1 -0
- package/dist/components/connectivity/login-screen.d.ts +9 -0
- package/dist/components/connectivity/login-screen.d.ts.map +1 -0
- package/dist/components/connectivity/login-screen.js +99 -0
- package/dist/components/connectivity/login-screen.js.map +1 -0
- package/dist/components/files/file-panel.d.ts +5 -0
- package/dist/components/files/file-panel.d.ts.map +1 -0
- package/dist/components/files/file-panel.js +46 -0
- package/dist/components/files/file-panel.js.map +1 -0
- package/dist/components/files/file-tree.d.ts +2 -0
- package/dist/components/files/file-tree.d.ts.map +1 -0
- package/dist/components/files/file-tree.js +63 -0
- package/dist/components/files/file-tree.js.map +1 -0
- package/dist/components/files/file-viewer-binary.d.ts +5 -0
- package/dist/components/files/file-viewer-binary.d.ts.map +1 -0
- package/dist/components/files/file-viewer-binary.js +20 -0
- package/dist/components/files/file-viewer-binary.js.map +1 -0
- package/dist/components/files/file-viewer-html.d.ts +4 -0
- package/dist/components/files/file-viewer-html.d.ts.map +1 -0
- package/dist/components/files/file-viewer-html.js +5 -0
- package/dist/components/files/file-viewer-html.js.map +1 -0
- package/dist/components/files/file-viewer-markdown.d.ts +4 -0
- package/dist/components/files/file-viewer-markdown.d.ts.map +1 -0
- package/dist/components/files/file-viewer-markdown.js +10 -0
- package/dist/components/files/file-viewer-markdown.js.map +1 -0
- package/dist/components/files/file-viewer-raw.d.ts +5 -0
- package/dist/components/files/file-viewer-raw.d.ts.map +1 -0
- package/dist/components/files/file-viewer-raw.js +15 -0
- package/dist/components/files/file-viewer-raw.js.map +1 -0
- package/dist/components/files/file-viewer.d.ts +2 -0
- package/dist/components/files/file-viewer.d.ts.map +1 -0
- package/dist/components/files/file-viewer.js +175 -0
- package/dist/components/files/file-viewer.js.map +1 -0
- package/dist/components/files/frontmatter-panel.d.ts +5 -0
- package/dist/components/files/frontmatter-panel.d.ts.map +1 -0
- package/dist/components/files/frontmatter-panel.js +12 -0
- package/dist/components/files/frontmatter-panel.js.map +1 -0
- package/dist/components/layout/app-shell.d.ts +5 -0
- package/dist/components/layout/app-shell.d.ts.map +1 -0
- package/dist/components/layout/app-shell.js +10 -0
- package/dist/components/layout/app-shell.js.map +1 -0
- package/dist/components/layout/mobile-tab-bar.d.ts +2 -0
- package/dist/components/layout/mobile-tab-bar.d.ts.map +1 -0
- package/dist/components/layout/mobile-tab-bar.js +16 -0
- package/dist/components/layout/mobile-tab-bar.js.map +1 -0
- package/dist/components/layout/side-rail.d.ts +2 -0
- package/dist/components/layout/side-rail.d.ts.map +1 -0
- package/dist/components/layout/side-rail.js +26 -0
- package/dist/components/layout/side-rail.js.map +1 -0
- package/dist/components/layout/slide-panel.d.ts +9 -0
- package/dist/components/layout/slide-panel.d.ts.map +1 -0
- package/dist/components/layout/slide-panel.js +18 -0
- package/dist/components/layout/slide-panel.js.map +1 -0
- package/dist/components/quick-actions/streaming-modal.d.ts +8 -0
- package/dist/components/quick-actions/streaming-modal.d.ts.map +1 -0
- package/dist/components/quick-actions/streaming-modal.js +92 -0
- package/dist/components/quick-actions/streaming-modal.js.map +1 -0
- package/dist/components/quick-actions/whatsup-modal.d.ts +5 -0
- package/dist/components/quick-actions/whatsup-modal.d.ts.map +1 -0
- package/dist/components/quick-actions/whatsup-modal.js +82 -0
- package/dist/components/quick-actions/whatsup-modal.js.map +1 -0
- package/dist/components/settings/passkey-panel.d.ts +10 -0
- package/dist/components/settings/passkey-panel.d.ts.map +1 -0
- package/dist/components/settings/passkey-panel.js +118 -0
- package/dist/components/settings/passkey-panel.js.map +1 -0
- package/dist/components/share/share-menu.d.ts +23 -0
- package/dist/components/share/share-menu.d.ts.map +1 -0
- package/dist/components/share/share-menu.js +58 -0
- package/dist/components/share/share-menu.js.map +1 -0
- package/dist/components/voice/dictation-sheet.d.ts +6 -0
- package/dist/components/voice/dictation-sheet.d.ts.map +1 -0
- package/dist/components/voice/dictation-sheet.js +91 -0
- package/dist/components/voice/dictation-sheet.js.map +1 -0
- package/dist/components/voice/mic-button.d.ts +6 -0
- package/dist/components/voice/mic-button.d.ts.map +1 -0
- package/dist/components/voice/mic-button.js +9 -0
- package/dist/components/voice/mic-button.js.map +1 -0
- package/dist/components/voice/review-card.d.ts +8 -0
- package/dist/components/voice/review-card.d.ts.map +1 -0
- package/dist/components/voice/review-card.js +8 -0
- package/dist/components/voice/review-card.js.map +1 -0
- package/dist/config.d.ts +19 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +10 -0
- package/dist/config.js.map +1 -0
- package/dist/hooks/use-vpn-status.d.ts +2 -0
- package/dist/hooks/use-vpn-status.d.ts.map +1 -0
- package/dist/hooks/use-vpn-status.js +71 -0
- package/dist/hooks/use-vpn-status.js.map +1 -0
- package/dist/hooks/use-websocket.d.ts +8 -0
- package/dist/hooks/use-websocket.d.ts.map +1 -0
- package/dist/hooks/use-websocket.js +366 -0
- package/dist/hooks/use-websocket.js.map +1 -0
- package/dist/index.d.ts +25 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +31 -0
- package/dist/index.js.map +1 -0
- package/dist/lib/api-client.d.ts +115 -0
- package/dist/lib/api-client.d.ts.map +1 -0
- package/dist/lib/api-client.js +70 -0
- package/dist/lib/api-client.js.map +1 -0
- package/dist/lib/backend.d.ts +7 -0
- package/dist/lib/backend.d.ts.map +1 -0
- package/dist/lib/backend.js +33 -0
- package/dist/lib/backend.js.map +1 -0
- package/dist/lib/frontmatter.d.ts +21 -0
- package/dist/lib/frontmatter.d.ts.map +1 -0
- package/dist/lib/frontmatter.js +88 -0
- package/dist/lib/frontmatter.js.map +1 -0
- package/dist/lib/image-attachments.d.ts +36 -0
- package/dist/lib/image-attachments.d.ts.map +1 -0
- package/dist/lib/image-attachments.js +175 -0
- package/dist/lib/image-attachments.js.map +1 -0
- package/dist/lib/passkeys.d.ts +18 -0
- package/dist/lib/passkeys.d.ts.map +1 -0
- package/dist/lib/passkeys.js +36 -0
- package/dist/lib/passkeys.js.map +1 -0
- package/dist/lib/share.d.ts +53 -0
- package/dist/lib/share.d.ts.map +1 -0
- package/dist/lib/share.js +144 -0
- package/dist/lib/share.js.map +1 -0
- package/dist/lib/strip-markdown.d.ts +10 -0
- package/dist/lib/strip-markdown.d.ts.map +1 -0
- package/dist/lib/strip-markdown.js +37 -0
- package/dist/lib/strip-markdown.js.map +1 -0
- package/dist/lib/tool-names.d.ts +17 -0
- package/dist/lib/tool-names.d.ts.map +1 -0
- package/dist/lib/tool-names.js +23 -0
- package/dist/lib/tool-names.js.map +1 -0
- package/dist/lib/utils.d.ts +3 -0
- package/dist/lib/utils.d.ts.map +1 -0
- package/dist/lib/utils.js +6 -0
- package/dist/lib/utils.js.map +1 -0
- package/dist/lib/ws-client.d.ts +26 -0
- package/dist/lib/ws-client.d.ts.map +1 -0
- package/dist/lib/ws-client.js +93 -0
- package/dist/lib/ws-client.js.map +1 -0
- package/dist/stores/chat-store.d.ts +131 -0
- package/dist/stores/chat-store.d.ts.map +1 -0
- package/dist/stores/chat-store.js +376 -0
- package/dist/stores/chat-store.js.map +1 -0
- package/dist/stores/connection-store.d.ts +11 -0
- package/dist/stores/connection-store.d.ts.map +1 -0
- package/dist/stores/connection-store.js +8 -0
- package/dist/stores/connection-store.js.map +1 -0
- package/dist/stores/file-store.d.ts +53 -0
- package/dist/stores/file-store.d.ts.map +1 -0
- package/dist/stores/file-store.js +284 -0
- package/dist/stores/file-store.js.map +1 -0
- package/dist/stores/provider-store.d.ts +24 -0
- package/dist/stores/provider-store.d.ts.map +1 -0
- package/dist/stores/provider-store.js +56 -0
- package/dist/stores/provider-store.js.map +1 -0
- package/dist/stores/ui-store.d.ts +21 -0
- package/dist/stores/ui-store.d.ts.map +1 -0
- package/dist/stores/ui-store.js +23 -0
- package/dist/stores/ui-store.js.map +1 -0
- package/dist/styles.css +2 -0
- package/dist/voice/asr-clients.d.ts +2 -0
- package/dist/voice/asr-clients.d.ts.map +1 -0
- package/dist/voice/asr-clients.js +33 -0
- package/dist/voice/asr-clients.js.map +1 -0
- package/dist/voice/asr-deepgram.d.ts +38 -0
- package/dist/voice/asr-deepgram.d.ts.map +1 -0
- package/dist/voice/asr-deepgram.js +307 -0
- package/dist/voice/asr-deepgram.js.map +1 -0
- package/dist/voice/asr-webspeech.d.ts +23 -0
- package/dist/voice/asr-webspeech.d.ts.map +1 -0
- package/dist/voice/asr-webspeech.js +93 -0
- package/dist/voice/asr-webspeech.js.map +1 -0
- package/dist/voice/use-dictation.d.ts +6 -0
- package/dist/voice/use-dictation.d.ts.map +1 -0
- package/dist/voice/use-dictation.js +174 -0
- package/dist/voice/use-dictation.js.map +1 -0
- package/dist/voice/voice-store.d.ts +26 -0
- package/dist/voice/voice-store.d.ts.map +1 -0
- package/dist/voice/voice-store.js +27 -0
- package/dist/voice/voice-store.js.map +1 -0
- package/package.json +71 -0
- package/src/components/chat/ask-user-card.tsx +451 -0
- package/src/components/chat/brain-markdown.tsx +547 -0
- package/src/components/chat/chat-page.tsx +820 -0
- package/src/components/chat/command-palette.tsx +68 -0
- package/src/components/chat/markdown-content.tsx +5 -0
- package/src/components/chat/message-bubble.tsx +362 -0
- package/src/components/chat/message-share.ts +78 -0
- package/src/components/chat/renderers/claude-tools.tsx +53 -0
- package/src/components/chat/renderers/generic.tsx +85 -0
- package/src/components/chat/renderers/index.ts +19 -0
- package/src/components/chat/risk-hints.ts +95 -0
- package/src/components/chat/session-drawer.tsx +213 -0
- package/src/components/chat/share-block.tsx +128 -0
- package/src/components/chat/tool-call-timeline.tsx +322 -0
- package/src/components/chat/tool-views.tsx +898 -0
- package/src/components/chat/welcome-state.tsx +105 -0
- package/src/components/connectivity/connection-gate.tsx +137 -0
- package/src/components/connectivity/login-screen.tsx +169 -0
- package/src/components/files/file-panel.tsx +116 -0
- package/src/components/files/file-tree.tsx +143 -0
- package/src/components/files/file-viewer-binary.tsx +63 -0
- package/src/components/files/file-viewer-html.tsx +10 -0
- package/src/components/files/file-viewer-markdown.tsx +14 -0
- package/src/components/files/file-viewer-raw.tsx +44 -0
- package/src/components/files/file-viewer.tsx +290 -0
- package/src/components/files/frontmatter-panel.tsx +78 -0
- package/src/components/layout/app-shell.tsx +25 -0
- package/src/components/layout/mobile-tab-bar.tsx +54 -0
- package/src/components/layout/side-rail.tsx +128 -0
- package/src/components/layout/slide-panel.tsx +64 -0
- package/src/components/quick-actions/streaming-modal.tsx +168 -0
- package/src/components/quick-actions/whatsup-modal.tsx +149 -0
- package/src/components/settings/passkey-panel.tsx +281 -0
- package/src/components/share/share-menu.tsx +121 -0
- package/src/components/voice/dictation-sheet.tsx +217 -0
- package/src/components/voice/mic-button.tsx +31 -0
- package/src/components/voice/review-card.tsx +66 -0
- package/src/config.ts +27 -0
- package/src/hooks/use-vpn-status.ts +75 -0
- package/src/hooks/use-websocket.ts +403 -0
- package/src/index.ts +46 -0
- package/src/lib/api-client.ts +173 -0
- package/src/lib/backend.ts +35 -0
- package/src/lib/frontmatter.ts +99 -0
- package/src/lib/image-attachments.ts +221 -0
- package/src/lib/passkeys.ts +50 -0
- package/src/lib/share.ts +167 -0
- package/src/lib/strip-markdown.ts +38 -0
- package/src/lib/tool-names.ts +27 -0
- package/src/lib/utils.ts +6 -0
- package/src/lib/ws-client.ts +109 -0
- package/src/stores/chat-store.ts +619 -0
- package/src/stores/connection-store.ts +23 -0
- package/src/stores/file-store.ts +344 -0
- package/src/stores/provider-store.ts +85 -0
- package/src/stores/ui-store.ts +48 -0
- package/src/styles.css +4 -0
- package/src/theme.css +425 -0
- package/src/voice/asr-clients.ts +45 -0
- package/src/voice/asr-deepgram.ts +325 -0
- package/src/voice/asr-webspeech.ts +135 -0
- package/src/voice/use-dictation.ts +187 -0
- package/src/voice/voice-store.ts +55 -0
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useState, useEffect } from "react";
|
|
3
|
+
import { Plus, Loader2 } from "lucide-react";
|
|
4
|
+
import { api } from "../../lib/api-client.js";
|
|
5
|
+
import { useChatStore } from "../../stores/chat-store.js";
|
|
6
|
+
import { SlidePanel } from "../layout/slide-panel.js";
|
|
7
|
+
import { cn } from "../../lib/utils.js";
|
|
8
|
+
export function SessionDrawer({ open, onClose, onResume, }) {
|
|
9
|
+
const [sessions, setSessions] = useState([]);
|
|
10
|
+
const [loading, setLoading] = useState(false);
|
|
11
|
+
const clearMessages = useChatStore((s) => s.clearMessages);
|
|
12
|
+
const currentSessionId = useChatStore((s) => s.activeSessionId);
|
|
13
|
+
const runStates = useChatStore((s) => s.runStates);
|
|
14
|
+
// A running/queued session other than the one in view is reattachable. Derive
|
|
15
|
+
// it from the live per-session run-state (kept current by the frame demux)
|
|
16
|
+
// rather than the deprecated status.activeSessionId, which multi-session
|
|
17
|
+
// servers no longer send.
|
|
18
|
+
const backgroundSessionId = Object.keys(runStates).find((id) => id !== currentSessionId) ?? null;
|
|
19
|
+
useEffect(() => {
|
|
20
|
+
if (open) {
|
|
21
|
+
setLoading(true);
|
|
22
|
+
api
|
|
23
|
+
.sessions()
|
|
24
|
+
.then((data) => setSessions(data.sessions))
|
|
25
|
+
.catch(() => setSessions([]))
|
|
26
|
+
.finally(() => setLoading(false));
|
|
27
|
+
}
|
|
28
|
+
}, [open]);
|
|
29
|
+
const groups = groupSessionsByDate(sessions);
|
|
30
|
+
return (_jsx(SlidePanel, { open: open, onClose: onClose, title: "Sessions", wide: true, children: _jsxs("div", { className: "flex h-full flex-col", children: [_jsx("div", { className: "p-4", children: _jsxs("button", { onClick: () => {
|
|
31
|
+
clearMessages();
|
|
32
|
+
onClose();
|
|
33
|
+
}, className: "flex w-full items-center justify-center gap-2 rounded-xl border-2 border-dashed border-primary/30 py-3 text-[13px] font-medium text-primary transition-all hover:border-primary/50 hover:bg-primary/5", children: [_jsx(Plus, { className: "h-4 w-4" }), "New conversation"] }) }), _jsxs("div", { className: "flex-1 overflow-y-auto px-2 pb-4", children: [backgroundSessionId && (_jsx("div", { className: "px-2 pb-2", children: _jsxs("button", { onClick: () => {
|
|
34
|
+
onResume(backgroundSessionId);
|
|
35
|
+
onClose();
|
|
36
|
+
}, className: "flex w-full items-center gap-3 rounded-lg border border-primary/30 bg-primary/5 px-3 py-2.5 text-left transition-colors hover:bg-primary/10", children: [_jsx("span", { className: "h-2 w-2 shrink-0 rounded-full bg-primary", style: { animation: "breathe 2s ease-in-out infinite" } }), _jsxs("div", { className: "min-w-0", children: [_jsx("div", { className: "truncate text-[13px] font-medium text-foreground", children: "Session running..." }), _jsx("div", { className: "text-[11px] text-primary", children: "Tap to reattach" })] })] }) })), loading ? (_jsx("div", { className: "flex items-center justify-center py-12 text-muted-foreground", children: _jsx(Loader2, { className: "h-4 w-4 animate-spin" }) })) : sessions.length === 0 && !backgroundSessionId ? (_jsx("p", { className: "py-12 text-center text-xs text-muted-foreground", children: "No sessions yet" })) : (groups.map((group) => (_jsxs("div", { children: [_jsx("div", { className: "px-3 py-2 font-[family-name:var(--font-mono)] text-[10px] font-medium uppercase tracking-widest text-muted-foreground/40", children: group.label }), group.sessions.map((session) => (_jsxs("button", { onClick: () => {
|
|
37
|
+
onResume(session.id);
|
|
38
|
+
onClose();
|
|
39
|
+
}, className: cn("w-full rounded-lg px-3 py-2.5 text-left transition-colors hover:bg-surface-raised", session.id === currentSessionId &&
|
|
40
|
+
"border-l-2 border-primary bg-primary/5"), children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx("div", { className: "min-w-0 flex-1 truncate text-[13px] font-medium text-foreground", children: session.title || "Untitled" }), _jsx(RunBadge, { state: runStates[session.id] })] }), _jsxs("div", { className: "mt-0.5 flex items-center gap-2", children: [_jsx("span", { className: "text-[11px] text-muted-foreground", children: formatRelativeTime(session.lastActiveAt) }), session.totalCostUsd != null &&
|
|
41
|
+
session.totalCostUsd > 0 && (_jsxs("span", { className: "text-[11px] text-muted-foreground/40", children: ["$", session.totalCostUsd.toFixed(2)] }))] })] }, session.id)))] }, group.label))))] })] }) }));
|
|
42
|
+
}
|
|
43
|
+
/** Live run-state pill on a session row (streaming / queued). */
|
|
44
|
+
function RunBadge({ state }) {
|
|
45
|
+
if (state !== "streaming" && state !== "queued")
|
|
46
|
+
return null;
|
|
47
|
+
const running = state === "streaming";
|
|
48
|
+
return (_jsx("span", { className: cn("shrink-0 rounded-full px-1.5 py-0.5 text-[9px] font-medium uppercase tracking-wide", running ? "bg-primary/15 text-primary" : "bg-amber-500/15 text-amber-500"), children: running ? "Running" : "Queued" }));
|
|
49
|
+
}
|
|
50
|
+
function groupSessionsByDate(sessions) {
|
|
51
|
+
const dayMs = 86400000;
|
|
52
|
+
const today = new Date();
|
|
53
|
+
today.setHours(0, 0, 0, 0);
|
|
54
|
+
const todayMs = today.getTime();
|
|
55
|
+
const yesterdayMs = todayMs - dayMs;
|
|
56
|
+
const weekAgoMs = todayMs - 7 * dayMs;
|
|
57
|
+
const groups = {
|
|
58
|
+
Today: [],
|
|
59
|
+
Yesterday: [],
|
|
60
|
+
"This week": [],
|
|
61
|
+
Earlier: [],
|
|
62
|
+
};
|
|
63
|
+
for (const s of sessions) {
|
|
64
|
+
if (s.lastActiveAt >= todayMs) {
|
|
65
|
+
groups.Today.push(s);
|
|
66
|
+
}
|
|
67
|
+
else if (s.lastActiveAt >= yesterdayMs) {
|
|
68
|
+
groups.Yesterday.push(s);
|
|
69
|
+
}
|
|
70
|
+
else if (s.lastActiveAt >= weekAgoMs) {
|
|
71
|
+
groups["This week"].push(s);
|
|
72
|
+
}
|
|
73
|
+
else {
|
|
74
|
+
groups.Earlier.push(s);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
return Object.entries(groups)
|
|
78
|
+
.filter(([, sessions]) => sessions.length > 0)
|
|
79
|
+
.map(([label, sessions]) => ({ label, sessions }));
|
|
80
|
+
}
|
|
81
|
+
function formatRelativeTime(ms) {
|
|
82
|
+
const diff = Date.now() - ms;
|
|
83
|
+
const minutes = Math.floor(diff / 60000);
|
|
84
|
+
if (minutes < 1)
|
|
85
|
+
return "just now";
|
|
86
|
+
if (minutes < 60)
|
|
87
|
+
return `${minutes}m ago`;
|
|
88
|
+
const hours = Math.floor(minutes / 60);
|
|
89
|
+
if (hours < 24)
|
|
90
|
+
return `${hours}h ago`;
|
|
91
|
+
const days = Math.floor(hours / 24);
|
|
92
|
+
if (days < 7)
|
|
93
|
+
return `${days}d ago`;
|
|
94
|
+
return new Date(ms).toLocaleDateString();
|
|
95
|
+
}
|
|
96
|
+
//# sourceMappingURL=session-drawer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session-drawer.js","sourceRoot":"","sources":["../../../src/components/chat/session-drawer.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export type ShareBlockFormat = "image" | "pdf" | "text" | "markdown" | "richtext";
|
|
2
|
+
interface ShareBlockProps {
|
|
3
|
+
body: string;
|
|
4
|
+
format?: ShareBlockFormat;
|
|
5
|
+
title?: string;
|
|
6
|
+
}
|
|
7
|
+
export declare function ShareBlock({ body, format, title }: ShareBlockProps): import("react").JSX.Element;
|
|
8
|
+
export {};
|
|
9
|
+
//# sourceMappingURL=share-block.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"share-block.d.ts","sourceRoot":"","sources":["../../../src/components/chat/share-block.tsx"],"names":[],"mappings":"AAQA,MAAM,MAAM,gBAAgB,GAAG,OAAO,GAAG,KAAK,GAAG,MAAM,GAAG,UAAU,GAAG,UAAU,CAAC;AAYlF,UAAU,eAAe;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,CAAC,EAAE,gBAAgB,CAAC;IAC1B,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,wBAAgB,UAAU,CAAC,EAAE,IAAI,EAAE,MAAgB,EAAE,KAAK,EAAE,EAAE,eAAe,+BAoC5E"}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { uiConfig } from "../../config.js";
|
|
3
|
+
import { useRef } from "react";
|
|
4
|
+
import { BrainMarkdown } from "./brain-markdown.js";
|
|
5
|
+
import { ShareMenu } from "../share/share-menu.js";
|
|
6
|
+
import { renderAndShare, shareFile, shareText, copyRichText } from "../../lib/share.js";
|
|
7
|
+
import { stripMarkdown } from "../../lib/strip-markdown.js";
|
|
8
|
+
import { Share2 } from "lucide-react";
|
|
9
|
+
const FORMAT_LABELS = {
|
|
10
|
+
image: "Share as image",
|
|
11
|
+
pdf: "Share as PDF",
|
|
12
|
+
text: "Share as plain text",
|
|
13
|
+
markdown: "Share markdown source",
|
|
14
|
+
richtext: "Copy as rich text",
|
|
15
|
+
};
|
|
16
|
+
const ORDER = ["image", "pdf", "text", "markdown", "richtext"];
|
|
17
|
+
export function ShareBlock({ body, format = "image", title }) {
|
|
18
|
+
const bodyRef = useRef(null);
|
|
19
|
+
const filename = sanitizeFilename(title ?? "share");
|
|
20
|
+
const primary = makeAction(format, body, filename, title, bodyRef);
|
|
21
|
+
const secondary = ORDER.filter((f) => f !== format).map((f) => makeAction(f, body, filename, title, bodyRef));
|
|
22
|
+
return (_jsxs("div", { className: "my-4 overflow-hidden rounded-lg border border-primary/30 bg-primary/[0.04]", children: [_jsxs("div", { className: "flex items-center justify-between gap-3 border-b border-primary/20 bg-primary/[0.06] px-3 py-2", children: [_jsxs("div", { className: "flex min-w-0 items-center gap-2 text-xs", children: [_jsx(Share2, { className: "h-3.5 w-3.5 shrink-0 text-primary/80" }), _jsx("span", { className: "truncate font-medium text-primary/90", children: title ?? "Share" }), _jsx("span", { className: "rounded-full bg-primary/15 px-2 py-0.5 text-[10px] uppercase tracking-wide text-primary/80", children: format })] }), _jsxs("div", { className: "flex items-center gap-1", children: [_jsx("button", { onClick: () => void primary.run(), className: "rounded-md bg-primary px-2.5 py-1 text-[11px] font-medium text-primary-foreground transition-opacity hover:opacity-90", children: primary.label }), _jsx(ShareMenu, { options: secondary, title: "Other formats" })] })] }), _jsx("div", { ref: bodyRef, className: "px-4 py-3", children: _jsx(BrainMarkdown, { content: body, className: "brain-prose", fileLinks: true }) })] }));
|
|
23
|
+
}
|
|
24
|
+
function makeAction(fmt, body, filename, title, bodyRef) {
|
|
25
|
+
return {
|
|
26
|
+
id: fmt,
|
|
27
|
+
label: FORMAT_LABELS[fmt],
|
|
28
|
+
run: () => runFormat(fmt, body, filename, title, bodyRef),
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
async function runFormat(fmt, body, filename, title, bodyRef) {
|
|
32
|
+
switch (fmt) {
|
|
33
|
+
case "image":
|
|
34
|
+
return renderAndShare({
|
|
35
|
+
content: body,
|
|
36
|
+
contentType: "markdown",
|
|
37
|
+
format: "png",
|
|
38
|
+
filename,
|
|
39
|
+
title: title ?? uiConfig.shareTitle,
|
|
40
|
+
});
|
|
41
|
+
case "pdf":
|
|
42
|
+
return renderAndShare({
|
|
43
|
+
content: body,
|
|
44
|
+
contentType: "markdown",
|
|
45
|
+
format: "pdf",
|
|
46
|
+
filename,
|
|
47
|
+
title: title ?? uiConfig.shareTitle,
|
|
48
|
+
});
|
|
49
|
+
case "text":
|
|
50
|
+
return shareText({ text: stripMarkdown(body), title });
|
|
51
|
+
case "markdown":
|
|
52
|
+
return shareFile(new File([body], `${filename}.md`, { type: "text/markdown" }), { title: title ?? filename });
|
|
53
|
+
case "richtext": {
|
|
54
|
+
const html = bodyRef.current?.innerHTML ?? `<pre>${escapeHtml(body)}</pre>`;
|
|
55
|
+
return copyRichText(html, stripMarkdown(body));
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
function sanitizeFilename(s) {
|
|
60
|
+
return s.replace(/[^a-z0-9_-]+/gi, "_").slice(0, 60) || "share";
|
|
61
|
+
}
|
|
62
|
+
function escapeHtml(s) {
|
|
63
|
+
return s
|
|
64
|
+
.replace(/&/g, "&")
|
|
65
|
+
.replace(/</g, "<")
|
|
66
|
+
.replace(/>/g, ">")
|
|
67
|
+
.replace(/"/g, """)
|
|
68
|
+
.replace(/'/g, "'");
|
|
69
|
+
}
|
|
70
|
+
//# sourceMappingURL=share-block.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"share-block.js","sourceRoot":"","sources":["../../../src/components/chat/share-block.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { ToolCall } from "../../stores/chat-store.js";
|
|
2
|
+
export declare function ToolCallTimeline({ toolCalls, onApproval, live, }: {
|
|
3
|
+
toolCalls: ToolCall[];
|
|
4
|
+
onApproval: (toolUseId: string, approved: boolean) => void;
|
|
5
|
+
/** Parent message still streaming — keep the timeline open while work runs. */
|
|
6
|
+
live?: boolean;
|
|
7
|
+
}): import("react").JSX.Element | null;
|
|
8
|
+
//# sourceMappingURL=tool-call-timeline.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tool-call-timeline.d.ts","sourceRoot":"","sources":["../../../src/components/chat/tool-call-timeline.tsx"],"names":[],"mappings":"AAYA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,4BAA4B,CAAC;AAgB3D,wBAAgB,gBAAgB,CAAC,EAC/B,SAAS,EACT,UAAU,EACV,IAAY,GACb,EAAE;IACD,SAAS,EAAE,QAAQ,EAAE,CAAC;IACtB,UAAU,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,OAAO,KAAK,IAAI,CAAC;IAC3D,+EAA+E;IAC/E,IAAI,CAAC,EAAE,OAAO,CAAC;CAChB,sCAwCA"}
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useState, useEffect, useRef } from "react";
|
|
3
|
+
import { Check, X, Copy, Layers, ChevronDown, ChevronRight, AlertTriangle, FileText, } from "lucide-react";
|
|
4
|
+
import { resolveToolRenderer } from "@schlessera/brain-ui-sdk/client";
|
|
5
|
+
import { cn } from "../../lib/utils.js";
|
|
6
|
+
import { motion, AnimatePresence } from "framer-motion";
|
|
7
|
+
import { getToolLabel, getTouchedFile, formatDuration } from "./tool-views.js";
|
|
8
|
+
import { registerBuiltinRenderers, GENERIC_RENDERER } from "./renderers/index.js";
|
|
9
|
+
import { riskHints } from "./risk-hints.js";
|
|
10
|
+
// Register the built-in renderer packs once. Registration is build-time; this
|
|
11
|
+
// runs on module load.
|
|
12
|
+
registerBuiltinRenderers();
|
|
13
|
+
// One backend is active per deployment (v1). The shipped default is the Claude
|
|
14
|
+
// backend; renderer resolution is backend-scoped so a future multi-backend
|
|
15
|
+
// build can thread the real id through here.
|
|
16
|
+
const BACKEND_ID = "claude";
|
|
17
|
+
export function ToolCallTimeline({ toolCalls, onApproval, live = false, }) {
|
|
18
|
+
// Collapse the whole run to a summary row once the turn is over. History
|
|
19
|
+
// messages mount collapsed; a live timeline collapses when streaming ends.
|
|
20
|
+
const [collapsed, setCollapsed] = useState(!live);
|
|
21
|
+
const prevLive = useRef(live);
|
|
22
|
+
useEffect(() => {
|
|
23
|
+
if (prevLive.current && !live)
|
|
24
|
+
setCollapsed(true);
|
|
25
|
+
prevLive.current = live;
|
|
26
|
+
}, [live]);
|
|
27
|
+
if (toolCalls.length === 0)
|
|
28
|
+
return null;
|
|
29
|
+
const hasPending = toolCalls.some((t) => t.status === "pending_approval");
|
|
30
|
+
const effectiveCollapsed = collapsed && !hasPending && !live;
|
|
31
|
+
if (effectiveCollapsed) {
|
|
32
|
+
return (_jsx(TimelineSummaryRow, { toolCalls: toolCalls, onExpand: () => setCollapsed(false) }));
|
|
33
|
+
}
|
|
34
|
+
return (_jsxs("div", { children: [!live && !hasPending && (_jsxs("button", { type: "button", onClick: () => setCollapsed(true), className: "mb-1 flex items-center gap-1.5 text-[11px] text-muted-foreground/50 transition-colors hover:text-muted-foreground", children: [_jsx(ChevronDown, { className: "h-3 w-3" }), "Hide steps"] })), _jsx("div", { className: "relative ml-1 border-l-2 border-border/40 pl-4 space-y-1.5", children: toolCalls.map((tool) => (_jsx(ToolCallEntry, { toolCall: tool, onApproval: onApproval }, tool.id))) })] }));
|
|
35
|
+
}
|
|
36
|
+
function TimelineSummaryRow({ toolCalls, onExpand, }) {
|
|
37
|
+
const steps = toolCalls.length;
|
|
38
|
+
const files = new Set(toolCalls.map(getTouchedFile).filter(Boolean)).size;
|
|
39
|
+
const errors = toolCalls.filter((t) => t.isError).length;
|
|
40
|
+
const started = Math.min(...toolCalls.map((t) => t.startedAt ?? Infinity));
|
|
41
|
+
const ended = Math.max(...toolCalls.map((t) => t.endedAt ?? -Infinity));
|
|
42
|
+
const duration = Number.isFinite(started) && ended > started
|
|
43
|
+
? formatDuration(ended - started)
|
|
44
|
+
: null;
|
|
45
|
+
return (_jsxs("button", { type: "button", onClick: onExpand, className: "flex items-center gap-2 rounded-md px-2 py-1.5 text-xs text-muted-foreground/70 transition-colors hover:text-foreground", children: [_jsx(Layers, { className: "h-3.5 w-3.5 shrink-0" }), _jsxs("span", { className: "font-[family-name:var(--font-mono)]", children: [steps, " step", steps === 1 ? "" : "s", files > 0 && ` · ${files} file${files === 1 ? "" : "s"} touched`, duration && ` · ${duration}`] }), errors > 0 && (_jsxs("span", { className: "font-[family-name:var(--font-mono)] text-destructive", children: ["\u00B7 ", errors, " failed"] })), _jsx(ChevronRight, { className: "h-3 w-3 shrink-0" })] }));
|
|
46
|
+
}
|
|
47
|
+
function ToolCallEntry({ toolCall, onApproval, }) {
|
|
48
|
+
const [expanded, setExpanded] = useState(toolCall.status === "pending_approval");
|
|
49
|
+
const prevStatus = useRef(toolCall.status);
|
|
50
|
+
// Resolve the renderer for this tool (backend-scoped exact -> global exact ->
|
|
51
|
+
// shape-sniffing predicate). Falls back to the generic renderer.
|
|
52
|
+
const renderer = resolveToolRenderer(toolCall, BACKEND_ID) ?? GENERIC_RENDERER;
|
|
53
|
+
const Icon = renderer.icon ?? FileText;
|
|
54
|
+
const isPending = toolCall.status === "pending_approval";
|
|
55
|
+
const summary = renderer.summary?.(toolCall) ?? null;
|
|
56
|
+
const meta = renderer.meta?.(toolCall) ?? null;
|
|
57
|
+
const Input = renderer.Input;
|
|
58
|
+
const Output = renderer.Output;
|
|
59
|
+
useEffect(() => {
|
|
60
|
+
if (toolCall.status === "pending_approval" &&
|
|
61
|
+
prevStatus.current !== "pending_approval") {
|
|
62
|
+
setExpanded(true);
|
|
63
|
+
}
|
|
64
|
+
else if (prevStatus.current === "pending_approval" &&
|
|
65
|
+
toolCall.status !== "pending_approval") {
|
|
66
|
+
setExpanded(false);
|
|
67
|
+
}
|
|
68
|
+
prevStatus.current = toolCall.status;
|
|
69
|
+
}, [toolCall.status]);
|
|
70
|
+
return (_jsxs("div", { className: "relative", children: [_jsx("div", { className: cn("absolute -left-[21px] top-2 h-2.5 w-2.5 rounded-full border-2 border-background", toolCall.status === "streaming" && "bg-primary animate-pulse", toolCall.status === "pending_approval" &&
|
|
71
|
+
"bg-primary", toolCall.status === "approved" && "bg-accent", toolCall.status === "denied" && "bg-destructive", toolCall.status === "complete" &&
|
|
72
|
+
(toolCall.isError ? "bg-destructive" : "bg-accent"), !["streaming", "pending_approval", "approved", "denied", "complete"].includes(toolCall.status) && "bg-muted-foreground"), style: toolCall.status === "pending_approval"
|
|
73
|
+
? { animation: "breathe 2s ease-in-out infinite" }
|
|
74
|
+
: undefined }), _jsxs("button", { onClick: () => setExpanded(!expanded), className: cn("flex w-full items-center gap-2 rounded-md px-2 py-1.5 text-xs transition-colors", toolCall.isError
|
|
75
|
+
? "text-destructive/80 hover:text-destructive"
|
|
76
|
+
: "text-muted-foreground hover:text-foreground"), children: [_jsx(Icon, { className: "h-3.5 w-3.5 shrink-0" }), _jsx("span", { className: "font-[family-name:var(--font-mono)] font-medium", children: getToolLabel(toolCall.name) }), summary && (_jsx("span", { className: cn("truncate", toolCall.isError ? "text-destructive/60" : "text-muted-foreground/70"), children: summary })), _jsxs("span", { className: "ml-auto flex shrink-0 items-center gap-2", children: [meta && (_jsx("span", { className: "font-[family-name:var(--font-mono)] text-[10px] text-muted-foreground/50", children: meta })), _jsx(StatusIndicator, { status: toolCall.status, isError: toolCall.isError })] })] }), _jsx(AnimatePresence, { children: expanded && (_jsx(motion.div, { initial: { height: 0, opacity: 0 }, animate: { height: "auto", opacity: 1 }, exit: { height: 0, opacity: 0 }, transition: { duration: 0.2, ease: "easeOut" }, className: "overflow-hidden", children: _jsxs("div", { className: cn("mt-1 rounded-lg p-3 space-y-2", isPending
|
|
77
|
+
? "border-2 border-primary/40 bg-primary/5"
|
|
78
|
+
: "border border-border-subtle bg-surface"), children: [Input && _jsx(Input, { tool: toolCall }), isPending && _jsx(RiskHints, { toolCall: toolCall }), isPending && (_jsxs("div", { className: "flex gap-2", children: [_jsxs("button", { onClick: () => onApproval(toolCall.id, true), className: "flex items-center gap-1.5 rounded-lg bg-primary px-4 py-1.5 text-xs font-medium text-primary-foreground transition-colors hover:brightness-110", children: [_jsx(Check, { className: "h-3 w-3" }), "Allow"] }), _jsxs("button", { onClick: () => onApproval(toolCall.id, false), className: "flex items-center gap-1.5 rounded-lg border border-destructive/30 px-4 py-1.5 text-xs font-medium text-destructive transition-colors hover:bg-destructive/10", children: [_jsx(X, { className: "h-3 w-3" }), "Deny"] })] })), toolCall.output && Output && (_jsxs("div", { className: "relative", children: [_jsx("button", { onClick: () => navigator.clipboard.writeText(toolCall.output), className: "absolute right-1 top-1 z-10 rounded p-1 text-muted-foreground transition-colors hover:bg-surface-raised hover:text-foreground", title: "Copy output", children: _jsx(Copy, { className: "h-3 w-3" }) }), _jsx(Output, { tool: toolCall })] }))] }) })) })] }));
|
|
79
|
+
}
|
|
80
|
+
function RiskHints({ toolCall }) {
|
|
81
|
+
const hints = riskHints(toolCall);
|
|
82
|
+
if (hints.length === 0)
|
|
83
|
+
return null;
|
|
84
|
+
return (_jsx("div", { className: "space-y-0.5 text-[11px] text-amber-400", children: hints.map((hint) => (_jsxs("div", { className: "flex items-center gap-1.5", children: [_jsx(AlertTriangle, { className: "h-3 w-3 shrink-0" }), _jsx("span", { children: hint })] }, hint))) }));
|
|
85
|
+
}
|
|
86
|
+
function StatusIndicator({ status, isError, }) {
|
|
87
|
+
switch (status) {
|
|
88
|
+
case "streaming":
|
|
89
|
+
return (_jsx("span", { className: "inline-block h-1.5 w-1.5 animate-pulse rounded-full bg-primary" }));
|
|
90
|
+
case "pending_approval":
|
|
91
|
+
return (_jsx("span", { className: "rounded bg-primary/20 px-1.5 py-0.5 text-[10px] font-medium text-primary", children: "Approval needed" }));
|
|
92
|
+
case "approved":
|
|
93
|
+
return _jsx(Check, { className: "h-3 w-3 text-accent" });
|
|
94
|
+
case "denied":
|
|
95
|
+
return _jsx(X, { className: "h-3 w-3 text-destructive" });
|
|
96
|
+
case "complete":
|
|
97
|
+
return isError ? (_jsx(X, { className: "h-3 w-3 text-destructive" })) : (_jsx(Check, { className: "h-3 w-3 text-muted-foreground/50" }));
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
//# sourceMappingURL=tool-call-timeline.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tool-call-timeline.js","sourceRoot":"","sources":["../../../src/components/chat/tool-call-timeline.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
import { Terminal } from "lucide-react";
|
|
2
|
+
import type { ToolCall } from "../../stores/chat-store.js";
|
|
3
|
+
/**
|
|
4
|
+
* Tool inputs carry absolute paths (`/data/brain/notes/foo.md`); the file
|
|
5
|
+
* panel wants repo-relative ones. Strip everything up to the brain repo root
|
|
6
|
+
* and verify the result actually looks like a repo path.
|
|
7
|
+
*/
|
|
8
|
+
export declare function toRepoRelative(path: string): string | null;
|
|
9
|
+
export declare function formatDuration(ms: number): string;
|
|
10
|
+
export declare function countLines(text: string): number;
|
|
11
|
+
export declare function getToolIcon(name: string): typeof Terminal;
|
|
12
|
+
/**
|
|
13
|
+
* Display name for a tool. In-process MCP tools stream as
|
|
14
|
+
* `mcp__<server>__<tool>`; show just the bare tool name in the timeline.
|
|
15
|
+
*/
|
|
16
|
+
export declare function getToolLabel(name: string): string;
|
|
17
|
+
/** Extract a short inline summary from tool input for at-a-glance context. */
|
|
18
|
+
export declare function getToolSummary(tool: ToolCall): string | null;
|
|
19
|
+
/** Right-side header meta: output size + wall-clock duration. */
|
|
20
|
+
export declare function getOutputMeta(tool: ToolCall): string | null;
|
|
21
|
+
/** File a tool writes to — used for the "N files touched" group summary. */
|
|
22
|
+
export declare function getTouchedFile(tool: ToolCall): string | null;
|
|
23
|
+
export declare function ToolInputView({ tool }: {
|
|
24
|
+
tool: ToolCall;
|
|
25
|
+
}): import("react").JSX.Element;
|
|
26
|
+
/** A word token, flagged when it differs from its counterpart line. */
|
|
27
|
+
type WordToken = {
|
|
28
|
+
text: string;
|
|
29
|
+
changed: boolean;
|
|
30
|
+
};
|
|
31
|
+
/** A rendered diff row. `tokens` is set only for word-refined single-line edits. */
|
|
32
|
+
type DiffRow = {
|
|
33
|
+
kind: "same" | "del" | "ins";
|
|
34
|
+
line: string;
|
|
35
|
+
tokens: WordToken[] | null;
|
|
36
|
+
};
|
|
37
|
+
/**
|
|
38
|
+
* Merge `old_string`/`new_string` into a single diff: unchanged lines appear
|
|
39
|
+
* once as neutral, deletions/insertions keep the red/green treatment. A change
|
|
40
|
+
* block that is exactly one deleted line against one inserted line gets
|
|
41
|
+
* word-level highlighting.
|
|
42
|
+
*/
|
|
43
|
+
export declare function computeDiffRows(oldStr: string, newStr: string): DiffRow[];
|
|
44
|
+
export declare function EditDiffView({ tool }: {
|
|
45
|
+
tool: ToolCall;
|
|
46
|
+
}): import("react").JSX.Element;
|
|
47
|
+
/** Longest backtick run + 1 so the fence survives content containing fences. */
|
|
48
|
+
export declare function fenceFor(content: string): string;
|
|
49
|
+
export declare function WriteFileView({ tool }: {
|
|
50
|
+
tool: ToolCall;
|
|
51
|
+
}): import("react").JSX.Element;
|
|
52
|
+
export declare function BashCommandView({ tool }: {
|
|
53
|
+
tool: ToolCall;
|
|
54
|
+
}): import("react").JSX.Element;
|
|
55
|
+
/** Generic structured input: one row per field beats raw JSON for scanning. */
|
|
56
|
+
export declare function KeyValueView({ tool }: {
|
|
57
|
+
tool: ToolCall;
|
|
58
|
+
}): import("react").JSX.Element;
|
|
59
|
+
export declare function ToolOutputView({ tool }: {
|
|
60
|
+
tool: ToolCall;
|
|
61
|
+
}): import("react").JSX.Element | null;
|
|
62
|
+
export declare function ClampedPre({ text, isError }: {
|
|
63
|
+
text: string;
|
|
64
|
+
isError?: boolean;
|
|
65
|
+
}): import("react").JSX.Element;
|
|
66
|
+
/**
|
|
67
|
+
* Compile a Grep pattern for match highlighting.
|
|
68
|
+
*
|
|
69
|
+
* We run this against every visible row during render, so it must be safe
|
|
70
|
+
* against catastrophic backtracking (ReDoS) — a synchronous `RegExp.exec` can't
|
|
71
|
+
* be interrupted, so a pattern like `(a+)+$` would freeze the UI thread. A
|
|
72
|
+
* pattern that contains no unbounded-repetition operator (`*`, `+`, `{`) cannot
|
|
73
|
+
* backtrack exponentially, so only those compile as real regexes; anything else
|
|
74
|
+
* (and any pattern that fails to compile, e.g. `c++`, `(`) is matched as an
|
|
75
|
+
* escaped literal. Both paths are linear-time. Returns null if even the literal
|
|
76
|
+
* form can't compile, so callers degrade to unhighlighted rows instead of
|
|
77
|
+
* throwing.
|
|
78
|
+
*/
|
|
79
|
+
export declare function safeSearchRegex(pattern: string | null): RegExp | null;
|
|
80
|
+
/**
|
|
81
|
+
* Split `text` into alternating non-match / match segments for a global regex.
|
|
82
|
+
* Zero-width matches are skipped (advancing lastIndex) so patterns like `a*`
|
|
83
|
+
* never spin. Purely string-in / segments-out so it's easy to unit test.
|
|
84
|
+
*/
|
|
85
|
+
export declare function splitMatches(text: string, re: RegExp): Array<{
|
|
86
|
+
text: string;
|
|
87
|
+
match: boolean;
|
|
88
|
+
}>;
|
|
89
|
+
/**
|
|
90
|
+
* Split a ripgrep-style `path:line:content` row into its linkable prefix and
|
|
91
|
+
* the content portion. Returns null when the row has no such prefix (e.g. Glob
|
|
92
|
+
* paths or an unusual format), so the caller can treat the whole line as content.
|
|
93
|
+
*/
|
|
94
|
+
export declare function splitGrepRow(line: string): {
|
|
95
|
+
prefix: string;
|
|
96
|
+
content: string;
|
|
97
|
+
} | null;
|
|
98
|
+
/** Grep/Glob results: one clickable row per line. */
|
|
99
|
+
export declare function FileRowsView({ output, pattern }: {
|
|
100
|
+
output: string;
|
|
101
|
+
pattern?: string | null;
|
|
102
|
+
}): import("react").JSX.Element;
|
|
103
|
+
/** A parsed WebSearch result: display title + destination URL. */
|
|
104
|
+
type WebResult = {
|
|
105
|
+
title: string;
|
|
106
|
+
url: string;
|
|
107
|
+
};
|
|
108
|
+
/**
|
|
109
|
+
* Tolerant parser for WebSearch output. The raw text is semi-structured, so we
|
|
110
|
+
* try a few shapes in priority order — JSON `{title,url}` objects, markdown
|
|
111
|
+
* links, then a line-scan that pairs a bare URL with nearby title text —
|
|
112
|
+
* de-duplicating by URL. Garbage input yields `[]` and never throws.
|
|
113
|
+
*/
|
|
114
|
+
export declare function parseWebSearchResults(output: string): WebResult[];
|
|
115
|
+
export {};
|
|
116
|
+
//# sourceMappingURL=tool-views.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tool-views.d.ts","sourceRoot":"","sources":["../../../src/components/chat/tool-views.tsx"],"names":[],"mappings":"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"}
|