@townco/ui 0.1.67 → 0.1.69
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/core/hooks/use-chat-messages.d.ts +5 -0
- package/dist/core/hooks/use-tool-calls.d.ts +5 -0
- package/dist/core/hooks/use-tool-calls.js +2 -1
- package/dist/core/schemas/chat.d.ts +10 -0
- package/dist/core/schemas/tool-call.d.ts +96 -0
- package/dist/core/schemas/tool-call.js +12 -0
- package/dist/core/utils/tool-call-state.d.ts +30 -0
- package/dist/core/utils/tool-call-state.js +73 -0
- package/dist/core/utils/tool-summary.d.ts +13 -0
- package/dist/core/utils/tool-summary.js +172 -0
- package/dist/core/utils/tool-verbiage.d.ts +28 -0
- package/dist/core/utils/tool-verbiage.js +185 -0
- package/dist/gui/components/AppSidebar.d.ts +22 -0
- package/dist/gui/components/AppSidebar.js +22 -0
- package/dist/gui/components/ChatLayout.d.ts +5 -0
- package/dist/gui/components/ChatLayout.js +239 -132
- package/dist/gui/components/ChatView.js +42 -118
- package/dist/gui/components/MessageContent.js +199 -49
- package/dist/gui/components/SessionHistory.d.ts +10 -0
- package/dist/gui/components/SessionHistory.js +101 -0
- package/dist/gui/components/SessionHistoryItem.d.ts +11 -0
- package/dist/gui/components/SessionHistoryItem.js +24 -0
- package/dist/gui/components/Sheet.d.ts +25 -0
- package/dist/gui/components/Sheet.js +36 -0
- package/dist/gui/components/Sidebar.d.ts +65 -0
- package/dist/gui/components/Sidebar.js +231 -0
- package/dist/gui/components/SidebarToggle.d.ts +3 -0
- package/dist/gui/components/SidebarToggle.js +9 -0
- package/dist/gui/components/SubAgentDetails.d.ts +13 -6
- package/dist/gui/components/SubAgentDetails.js +29 -14
- package/dist/gui/components/ToolCallList.js +3 -3
- package/dist/gui/components/ToolOperation.d.ts +11 -0
- package/dist/gui/components/ToolOperation.js +289 -0
- package/dist/gui/components/WorkProgress.d.ts +20 -0
- package/dist/gui/components/WorkProgress.js +79 -0
- package/dist/gui/components/index.d.ts +8 -1
- package/dist/gui/components/index.js +9 -1
- package/dist/gui/hooks/index.d.ts +1 -0
- package/dist/gui/hooks/index.js +1 -0
- package/dist/gui/hooks/use-mobile.d.ts +1 -0
- package/dist/gui/hooks/use-mobile.js +15 -0
- package/dist/gui/index.d.ts +1 -0
- package/dist/gui/index.js +2 -0
- package/dist/gui/lib/motion.d.ts +55 -0
- package/dist/gui/lib/motion.js +217 -0
- package/dist/sdk/schemas/session.d.ts +102 -6
- package/dist/sdk/transports/http.js +105 -37
- package/dist/sdk/transports/types.d.ts +5 -0
- package/package.json +8 -7
- package/src/styles/global.css +128 -1
- package/dist/gui/components/InvokingGroup.d.ts +0 -9
- package/dist/gui/components/InvokingGroup.js +0 -16
- package/dist/gui/components/ToolCall.d.ts +0 -8
- package/dist/gui/components/ToolCall.js +0 -226
- package/dist/gui/components/ToolCallGroup.d.ts +0 -8
- package/dist/gui/components/ToolCallGroup.js +0 -29
|
@@ -1,17 +1,20 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
import { ChevronDown,
|
|
2
|
+
import { ChevronDown, Loader2 } from "lucide-react";
|
|
3
3
|
import React, { useCallback, useEffect, useRef, useState } from "react";
|
|
4
4
|
import { useSubagentStream } from "../../core/hooks/use-subagent-stream.js";
|
|
5
|
+
import { MarkdownRenderer } from "./MarkdownRenderer.js";
|
|
5
6
|
const SCROLL_THRESHOLD = 50; // px from bottom to consider "at bottom"
|
|
6
7
|
/**
|
|
7
8
|
* SubAgentDetails component - displays streaming content from a sub-agent.
|
|
8
9
|
*
|
|
9
10
|
* This component:
|
|
10
|
-
* - Connects directly to the sub-agent's SSE endpoint
|
|
11
|
+
* - Connects directly to the sub-agent's SSE endpoint (live mode)
|
|
12
|
+
* - Or displays stored messages (replay mode)
|
|
11
13
|
* - Displays streaming text and tool calls
|
|
14
|
+
* - Renders content as markdown
|
|
12
15
|
* - Renders in a collapsible section (collapsed by default)
|
|
13
16
|
*/
|
|
14
|
-
export function SubAgentDetails({ port, sessionId, host, parentStatus, agentName, query, isExpanded: controlledIsExpanded, onExpandChange, }) {
|
|
17
|
+
export function SubAgentDetails({ port, sessionId, host, parentStatus, agentName, query, isExpanded: controlledIsExpanded, onExpandChange, storedMessages, isReplay = false, }) {
|
|
15
18
|
const [internalIsExpanded, setInternalIsExpanded] = useState(false);
|
|
16
19
|
// Use controlled state if provided, otherwise use internal state
|
|
17
20
|
const isExpanded = controlledIsExpanded ?? internalIsExpanded;
|
|
@@ -19,16 +22,28 @@ export function SubAgentDetails({ port, sessionId, host, parentStatus, agentName
|
|
|
19
22
|
const [isThinkingExpanded, setIsThinkingExpanded] = useState(false);
|
|
20
23
|
const [isNearBottom, setIsNearBottom] = useState(true);
|
|
21
24
|
const thinkingContainerRef = useRef(null);
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
25
|
+
// Only use SSE streaming if not in replay mode and port/sessionId provided
|
|
26
|
+
const shouldStream = !isReplay && port !== undefined && sessionId !== undefined;
|
|
27
|
+
const streamOptions = shouldStream
|
|
28
|
+
? {
|
|
29
|
+
port: port,
|
|
30
|
+
sessionId: sessionId,
|
|
31
|
+
...(host !== undefined ? { host } : {}),
|
|
32
|
+
}
|
|
33
|
+
: null;
|
|
34
|
+
const { messages: streamedMessages, isStreaming: hookIsStreaming, error, } = useSubagentStream(streamOptions);
|
|
35
|
+
// Use stored messages if available, otherwise use streamed messages
|
|
36
|
+
const messages = storedMessages && storedMessages.length > 0
|
|
37
|
+
? storedMessages
|
|
38
|
+
: streamedMessages;
|
|
27
39
|
// Use parent status as primary indicator, fall back to hook's streaming state
|
|
28
40
|
// Parent is "in_progress" means sub-agent is definitely still running
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
41
|
+
// In replay mode, we're never running
|
|
42
|
+
const isRunning = isReplay
|
|
43
|
+
? false
|
|
44
|
+
: parentStatus === "in_progress" ||
|
|
45
|
+
parentStatus === "pending" ||
|
|
46
|
+
hookIsStreaming;
|
|
32
47
|
// Get the current/latest message
|
|
33
48
|
const currentMessage = messages[messages.length - 1];
|
|
34
49
|
const hasContent = currentMessage &&
|
|
@@ -97,9 +112,9 @@ export function SubAgentDetails({ port, sessionId, host, parentStatus, agentName
|
|
|
97
112
|
return (_jsxs("div", { children: [!isExpanded && (_jsx("div", { className: "w-full max-w-md", children: previewText ? (_jsx("p", { className: "text-paragraph-sm text-muted-foreground/70 truncate", children: previewText })) : queryFirstLine ? (_jsx("p", { className: "text-paragraph-sm text-muted-foreground/50 truncate", children: queryFirstLine })) : null })), isExpanded && (_jsxs("div", { className: "space-y-3", children: [(agentName || query) && (_jsxs("div", { children: [_jsx("div", { className: "text-[10px] font-bold text-muted-foreground uppercase tracking-wider mb-1.5 font-sans", children: "Input" }), _jsxs("div", { className: "text-[11px] font-mono space-y-1", children: [agentName && (_jsxs("div", { children: [_jsx("span", { className: "text-muted-foreground", children: "agentName: " }), _jsx("span", { className: "text-foreground", children: agentName })] })), query && (_jsxs("div", { children: [_jsx("span", { className: "text-muted-foreground", children: "query: " }), _jsx("span", { className: "text-foreground", children: query })] }))] })] })), _jsxs("div", { children: [_jsxs("button", { type: "button", onClick: () => setIsThinkingExpanded(!isThinkingExpanded), className: "flex items-center gap-2 cursor-pointer bg-transparent border-none p-0 text-left group", children: [_jsx("div", { className: "text-[10px] font-bold text-muted-foreground uppercase tracking-wider font-sans", children: "Thinking" }), _jsx(ChevronDown, { className: `h-3 w-3 text-muted-foreground/70 transition-transform duration-200 ${isThinkingExpanded ? "rotate-180" : ""}` })] }), isThinkingExpanded && (_jsxs("div", { ref: thinkingContainerRef, className: "mt-2 rounded-md overflow-hidden bg-muted/30 border border-border/50 max-h-[200px] overflow-y-auto", children: [error && (_jsxs("div", { className: "px-2 py-2 text-[11px] text-destructive", children: ["Error: ", error] })), !error && !hasContent && isRunning && (_jsx("div", { className: "px-2 py-2 text-[11px] text-muted-foreground", children: "Waiting for sub-agent response..." })), currentMessage && (_jsxs("div", { className: "px-2 py-2 space-y-2", children: [currentMessage.contentBlocks &&
|
|
98
113
|
currentMessage.contentBlocks.length > 0
|
|
99
114
|
? // Render interleaved content blocks
|
|
100
|
-
currentMessage.contentBlocks.map((block, idx) => block.type === "text" ? (_jsx("div", { className: "text-[11px] text-foreground
|
|
101
|
-
: // Fallback to legacy content
|
|
102
|
-
currentMessage.content && (_jsx("div", { className: "text-[11px] text-foreground
|
|
115
|
+
currentMessage.contentBlocks.map((block, idx) => block.type === "text" ? (_jsx("div", { className: "text-[11px] text-foreground prose prose-sm dark:prose-invert max-w-none prose-p:my-1 prose-pre:my-1 prose-code:text-[10px]", children: _jsx(MarkdownRenderer, { content: block.text }) }, `text-${idx}`)) : (_jsx(SubagentToolCallItem, { toolCall: block.toolCall }, block.toolCall.id)))
|
|
116
|
+
: // Fallback to legacy content with markdown
|
|
117
|
+
currentMessage.content && (_jsx("div", { className: "text-[11px] text-foreground prose prose-sm dark:prose-invert max-w-none prose-p:my-1 prose-pre:my-1 prose-code:text-[10px]", children: _jsx(MarkdownRenderer, { content: currentMessage.content }) })), currentMessage.isStreaming && (_jsx("span", { className: "inline-block w-1.5 h-3 bg-primary/70 ml-0.5 animate-pulse" }))] }))] }))] }), !isRunning && currentMessage?.content && (_jsxs("div", { children: [_jsx("div", { className: "text-[10px] font-bold text-muted-foreground uppercase tracking-wider mb-1.5 font-sans", children: "Output" }), _jsx("div", { className: "text-[11px] text-foreground max-h-[200px] overflow-y-auto rounded-md bg-muted/30 border border-border/50 px-2 py-2 prose prose-sm dark:prose-invert max-w-none prose-p:my-1 prose-pre:my-1 prose-code:text-[10px]", children: _jsx(MarkdownRenderer, { content: currentMessage.content }) })] }))] }))] }));
|
|
103
118
|
}
|
|
104
119
|
/**
|
|
105
120
|
* Simple tool call display for sub-agent tool calls
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
import {
|
|
2
|
+
import { ToolOperation } from "./ToolOperation.js";
|
|
3
3
|
/**
|
|
4
4
|
* ToolCallList component - renders a list of tool calls, optionally grouped
|
|
5
5
|
*/
|
|
@@ -15,8 +15,8 @@ export function ToolCallList({ toolCalls, groupBy = "chronological", }) {
|
|
|
15
15
|
completed: toolCalls.filter((tc) => tc.status === "completed"),
|
|
16
16
|
failed: toolCalls.filter((tc) => tc.status === "failed"),
|
|
17
17
|
};
|
|
18
|
-
return (_jsxs("div", { className: "space-y-4", children: [grouped.in_progress.length > 0 && (_jsxs("div", { children: [_jsx("h4", { className: "text-[10px] font-bold text-muted-foreground uppercase tracking-wider mb-2 pl-1", children: "In Progress" }), grouped.in_progress.map((tc) => (_jsx(
|
|
18
|
+
return (_jsxs("div", { className: "space-y-4", children: [grouped.in_progress.length > 0 && (_jsxs("div", { children: [_jsx("h4", { className: "text-[10px] font-bold text-muted-foreground uppercase tracking-wider mb-2 pl-1", children: "In Progress" }), grouped.in_progress.map((tc) => (_jsx(ToolOperation, { toolCalls: [tc], isGrouped: false }, tc.id)))] })), grouped.pending.length > 0 && (_jsxs("div", { children: [_jsx("h4", { className: "text-[10px] font-bold text-muted-foreground uppercase tracking-wider mb-2 pl-1", children: "Pending" }), grouped.pending.map((tc) => (_jsx(ToolOperation, { toolCalls: [tc], isGrouped: false }, tc.id)))] })), grouped.completed.length > 0 && (_jsxs("div", { children: [_jsx("h4", { className: "text-[10px] font-bold text-muted-foreground uppercase tracking-wider mb-2 pl-1", children: "Completed" }), grouped.completed.map((tc) => (_jsx(ToolOperation, { toolCalls: [tc], isGrouped: false }, tc.id)))] })), grouped.failed.length > 0 && (_jsxs("div", { children: [_jsx("h4", { className: "text-[10px] font-bold text-zinc-400 uppercase tracking-wider mb-2 pl-1", children: "Failed" }), grouped.failed.map((tc) => (_jsx(ToolOperation, { toolCalls: [tc], isGrouped: false }, tc.id)))] }))] }));
|
|
19
19
|
}
|
|
20
20
|
// Default: chronological order
|
|
21
|
-
return (_jsx("div", { className: "space-y-2", children: toolCalls.map((tc) => (_jsx(
|
|
21
|
+
return (_jsx("div", { className: "space-y-2", children: toolCalls.map((tc) => (_jsx(ToolOperation, { toolCalls: [tc], isGrouped: false }, tc.id))) }));
|
|
22
22
|
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { ToolCall as ToolCallType } from "../../core/schemas/tool-call.js";
|
|
2
|
+
export interface ToolOperationProps {
|
|
3
|
+
toolCalls: ToolCallType[];
|
|
4
|
+
isGrouped?: boolean;
|
|
5
|
+
autoMinimize?: boolean;
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* ToolOperation component - unified display for tool calls
|
|
9
|
+
* Handles both individual and grouped tool calls with smooth transitions
|
|
10
|
+
*/
|
|
11
|
+
export declare function ToolOperation({ toolCalls, isGrouped, autoMinimize, }: ToolOperationProps): import("react/jsx-runtime").JSX.Element;
|
|
@@ -0,0 +1,289 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import JsonView from "@uiw/react-json-view";
|
|
3
|
+
import { AnimatePresence, motion, useReducedMotion } from "framer-motion";
|
|
4
|
+
import { AlertCircle, BrainCircuit, CheckSquare, ChevronDown, ChevronRight, CircleDot, Cloud, Edit, FileText, Globe, Image, Link, ListVideo, Search, Wrench, } from "lucide-react";
|
|
5
|
+
import React, { useEffect, useState } from "react";
|
|
6
|
+
import { areAllToolCallsCompleted, getGroupDisplayState, getToolCallDisplayState, getToolCallStateVerbiage, hasAnyToolCallFailed, isPreliminaryToolCall, } from "../../core/utils/tool-call-state.js";
|
|
7
|
+
import { generateSmartSummary } from "../../core/utils/tool-summary.js";
|
|
8
|
+
import { expandCollapseVariants, fadeInVariants, getDuration, getTransition, motionDuration, motionEasing, rotateVariants, shimmerTransition, standardTransition, } from "../lib/motion.js";
|
|
9
|
+
import { cn } from "../lib/utils.js";
|
|
10
|
+
import * as ChatLayout from "./ChatLayout.js";
|
|
11
|
+
import { useTheme } from "./ThemeProvider.js";
|
|
12
|
+
/**
|
|
13
|
+
* Map of icon names to Lucide components
|
|
14
|
+
*/
|
|
15
|
+
const ICON_MAP = {
|
|
16
|
+
Globe: Globe,
|
|
17
|
+
Image: Image,
|
|
18
|
+
Link: Link,
|
|
19
|
+
Cloud: Cloud,
|
|
20
|
+
CheckSquare: CheckSquare,
|
|
21
|
+
Search: Search,
|
|
22
|
+
FileText: FileText,
|
|
23
|
+
Edit: Edit,
|
|
24
|
+
Wrench: Wrench,
|
|
25
|
+
BrainCircuit: BrainCircuit,
|
|
26
|
+
CircleDot: CircleDot,
|
|
27
|
+
};
|
|
28
|
+
/**
|
|
29
|
+
* ToolOperation component - unified display for tool calls
|
|
30
|
+
* Handles both individual and grouped tool calls with smooth transitions
|
|
31
|
+
*/
|
|
32
|
+
export function ToolOperation({ toolCalls, isGrouped = false, autoMinimize = true, }) {
|
|
33
|
+
const [isExpanded, setIsExpanded] = useState(false);
|
|
34
|
+
const [isMinimized, setIsMinimized] = useState(false);
|
|
35
|
+
const [userInteracted, setUserInteracted] = useState(false);
|
|
36
|
+
const { resolvedTheme } = useTheme();
|
|
37
|
+
const shouldReduceMotion = useReducedMotion();
|
|
38
|
+
// For single tool call, extract it
|
|
39
|
+
const singleToolCall = toolCalls.length === 1 ? toolCalls[0] : null;
|
|
40
|
+
const isTodoWrite = singleToolCall?.title === "todo_write";
|
|
41
|
+
// Safely access ChatLayout context
|
|
42
|
+
const layoutContext = React.useContext(ChatLayout.Context);
|
|
43
|
+
// Determine display state
|
|
44
|
+
const displayState = isGrouped
|
|
45
|
+
? getGroupDisplayState(toolCalls)
|
|
46
|
+
: singleToolCall
|
|
47
|
+
? getToolCallDisplayState(singleToolCall)
|
|
48
|
+
: "executing";
|
|
49
|
+
const isCompleted = displayState === "completed";
|
|
50
|
+
const isFailed = displayState === "failed";
|
|
51
|
+
const isSelecting = displayState === "selecting";
|
|
52
|
+
const isActive = displayState === "executing";
|
|
53
|
+
// Auto-minimize when completed (only if user hasn't manually interacted)
|
|
54
|
+
useEffect(() => {
|
|
55
|
+
if (autoMinimize && isCompleted && !isMinimized && !userInteracted) {
|
|
56
|
+
// Small delay to show the completed state briefly
|
|
57
|
+
const timer = setTimeout(() => {
|
|
58
|
+
setIsMinimized(true);
|
|
59
|
+
setIsExpanded(false);
|
|
60
|
+
}, 500);
|
|
61
|
+
return () => clearTimeout(timer);
|
|
62
|
+
}
|
|
63
|
+
return undefined;
|
|
64
|
+
}, [autoMinimize, isCompleted, isMinimized, userInteracted]);
|
|
65
|
+
// Click handler for header
|
|
66
|
+
const handleHeaderClick = React.useCallback(() => {
|
|
67
|
+
if (isTodoWrite && layoutContext && singleToolCall) {
|
|
68
|
+
// Toggle sidepanel for TodoWrite
|
|
69
|
+
if (layoutContext.panelSize !== "hidden" &&
|
|
70
|
+
layoutContext.activeTab === "todo") {
|
|
71
|
+
layoutContext.setPanelSize("hidden");
|
|
72
|
+
}
|
|
73
|
+
else {
|
|
74
|
+
layoutContext.setPanelSize("small");
|
|
75
|
+
layoutContext.setActiveTab("todo");
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
else {
|
|
79
|
+
// Normal expand/collapse
|
|
80
|
+
setUserInteracted(true); // Mark as user-interacted to prevent auto-minimize
|
|
81
|
+
setIsExpanded(!isExpanded);
|
|
82
|
+
if (isMinimized) {
|
|
83
|
+
setIsMinimized(false);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
}, [isTodoWrite, layoutContext, isExpanded, isMinimized, singleToolCall]);
|
|
87
|
+
// Get icon for display
|
|
88
|
+
const getIcon = () => {
|
|
89
|
+
if (isGrouped) {
|
|
90
|
+
return ListVideo;
|
|
91
|
+
}
|
|
92
|
+
if (singleToolCall?.icon && ICON_MAP[singleToolCall.icon]) {
|
|
93
|
+
return ICON_MAP[singleToolCall.icon];
|
|
94
|
+
}
|
|
95
|
+
return CircleDot;
|
|
96
|
+
};
|
|
97
|
+
const IconComponent = getIcon();
|
|
98
|
+
// Get verbiage/summary
|
|
99
|
+
const getDisplayText = () => {
|
|
100
|
+
if (isGrouped) {
|
|
101
|
+
const tense = isCompleted ? "past" : "active";
|
|
102
|
+
return generateSmartSummary(toolCalls, tense);
|
|
103
|
+
}
|
|
104
|
+
if (singleToolCall) {
|
|
105
|
+
return getToolCallStateVerbiage(singleToolCall);
|
|
106
|
+
}
|
|
107
|
+
return "Tool operation";
|
|
108
|
+
};
|
|
109
|
+
const displayText = getDisplayText();
|
|
110
|
+
// For preliminary/selecting states, show simple non-expandable text
|
|
111
|
+
if (isSelecting && !isGrouped) {
|
|
112
|
+
return (_jsx(motion.div, { className: "flex flex-col my-4 rounded-md px-1 -mx-1 w-fit", animate: {
|
|
113
|
+
backgroundPosition: ["200% 0", "-200% 0"],
|
|
114
|
+
}, transition: {
|
|
115
|
+
...shimmerTransition,
|
|
116
|
+
duration: getDuration(shouldReduceMotion ?? false, 1.5),
|
|
117
|
+
}, style: {
|
|
118
|
+
backgroundImage: "linear-gradient(90deg, transparent 5%, rgba(255, 255, 255, 0.75) 25%, transparent 35%)",
|
|
119
|
+
backgroundSize: "200% 100%",
|
|
120
|
+
}, children: _jsx("span", { className: "text-paragraph-sm text-text-secondary/50", children: displayText }) }));
|
|
121
|
+
}
|
|
122
|
+
// If it's a grouped preliminary (selecting) state
|
|
123
|
+
if (isSelecting && isGrouped) {
|
|
124
|
+
return (_jsxs(motion.div, { className: "flex flex-col my-4 rounded-md px-1 -mx-1 w-fit", animate: {
|
|
125
|
+
backgroundPosition: ["200% 0", "-200% 0"],
|
|
126
|
+
}, transition: {
|
|
127
|
+
...shimmerTransition,
|
|
128
|
+
duration: getDuration(shouldReduceMotion ?? false, 1.5),
|
|
129
|
+
}, style: {
|
|
130
|
+
backgroundImage: "linear-gradient(90deg, transparent 5%, rgba(255, 255, 255, 0.75) 25%, transparent 35%)",
|
|
131
|
+
backgroundSize: "200% 100%",
|
|
132
|
+
}, children: [_jsxs("div", { className: "flex items-center gap-1.5", children: [_jsx("div", { className: "text-text-secondary/70", children: _jsx(ListVideo, { className: "h-3 w-3" }) }), _jsx("span", { className: "text-paragraph-sm text-text-secondary/70", children: "Selecting tools" }), _jsx("span", { className: "text-[10px] bg-muted px-1.5 py-0.5 rounded text-text-secondary/70", children: toolCalls.length })] }), _jsx("span", { className: "text-paragraph-sm text-text-secondary/70 pl-4.5", children: displayText })] }));
|
|
133
|
+
}
|
|
134
|
+
// Full display (for single tool call or expanded group, includes minimized state)
|
|
135
|
+
return (_jsxs(motion.div, { className: "flex flex-col my-4", initial: {
|
|
136
|
+
filter: "blur(12px)",
|
|
137
|
+
opacity: 0,
|
|
138
|
+
y: 12,
|
|
139
|
+
}, animate: {
|
|
140
|
+
filter: "blur(0px)",
|
|
141
|
+
opacity: 1,
|
|
142
|
+
y: 0,
|
|
143
|
+
}, exit: {
|
|
144
|
+
filter: "blur(12px)",
|
|
145
|
+
opacity: 0,
|
|
146
|
+
y: -12,
|
|
147
|
+
}, transition: getTransition(shouldReduceMotion ?? false, {
|
|
148
|
+
duration: 0.5,
|
|
149
|
+
ease: motionEasing.smooth,
|
|
150
|
+
}), children: [_jsxs(motion.button, { type: "button", className: "flex flex-col items-start gap-0.5 cursor-pointer bg-transparent border-none p-0 text-left group w-fit rounded-md px-1 -mx-1", onClick: handleHeaderClick, "aria-expanded": isTodoWrite ? undefined : isExpanded, animate: isActive || isSelecting
|
|
151
|
+
? {
|
|
152
|
+
backgroundPosition: ["200% 0", "-200% 0"],
|
|
153
|
+
}
|
|
154
|
+
: {}, transition: isActive || isSelecting
|
|
155
|
+
? {
|
|
156
|
+
...shimmerTransition,
|
|
157
|
+
duration: getDuration(shouldReduceMotion ?? false, 1.5),
|
|
158
|
+
}
|
|
159
|
+
: {}, style: isActive || isSelecting
|
|
160
|
+
? {
|
|
161
|
+
backgroundImage: "linear-gradient(90deg, transparent 5%, rgba(255, 255, 255, 0.75) 25%, transparent 35%)",
|
|
162
|
+
backgroundSize: "200% 100%",
|
|
163
|
+
}
|
|
164
|
+
: {}, children: [_jsxs("div", { className: "flex items-center gap-1.5", children: [_jsx("div", { className: "text-text-secondary/70 group-hover:text-text-secondary transition-colors", children: _jsx(IconComponent, { className: "h-3 w-3" }) }), _jsxs("span", { className: "text-paragraph-sm text-text-secondary/70 group-hover:text-text-secondary transition-colors", children: [isGrouped && _jsx("span", { className: "mr-1", children: "Parallel operation" }), !isGrouped && displayText] }), isGrouped && (_jsx("span", { className: "text-[10px] bg-muted px-1.5 py-0.5 rounded text-text-secondary/70", children: toolCalls.length })), isFailed && _jsx(AlertCircle, { className: "h-3 w-3 text-destructive" }), isTodoWrite ? (_jsx(ChevronRight, { className: "h-3 w-3 text-text-secondary/70 group-hover:text-text-secondary transition-colors" })) : (_jsx(motion.div, { animate: {
|
|
165
|
+
rotate: isExpanded ? 180 : 0,
|
|
166
|
+
}, transition: getTransition(shouldReduceMotion ?? false, {
|
|
167
|
+
duration: motionDuration.normal,
|
|
168
|
+
ease: motionEasing.smooth,
|
|
169
|
+
}), className: "h-3 w-3 text-text-secondary/70 group-hover:text-text-secondary transition-colors", children: _jsx(ChevronDown, { className: "h-3 w-3" }) }))] }), !isGrouped && singleToolCall?.subline && (_jsx("span", { className: "text-paragraph-sm text-text-secondary/70 pl-4.5", children: singleToolCall.subline })), isGrouped && !isExpanded && (_jsx("span", { className: "text-paragraph-sm text-text-secondary/70 pl-4.5", children: displayText }))] }), _jsx(AnimatePresence, { initial: false, children: !isTodoWrite && isExpanded && (_jsx(motion.div, { initial: "collapsed", animate: "expanded", exit: "collapsed", variants: expandCollapseVariants, transition: getTransition(shouldReduceMotion ?? false, {
|
|
170
|
+
duration: motionDuration.normal,
|
|
171
|
+
ease: motionEasing.smooth,
|
|
172
|
+
}), className: "mt-1", children: isGrouped ? (
|
|
173
|
+
// Render individual tool calls in group
|
|
174
|
+
_jsx("div", { className: "flex flex-col gap-4 mt-2", children: toolCalls.map((toolCall) => (_jsx("div", { className: "flex items-start gap-1.5", children: _jsx("div", { className: "flex-1 ml-5", children: _jsx(ToolOperationDetails, { toolCall: toolCall }) }) }, toolCall.id))) })) : (
|
|
175
|
+
// Render single tool call details
|
|
176
|
+
singleToolCall && (_jsx(ToolOperationDetails, { toolCall: singleToolCall }))) }, "expanded-content")) })] }));
|
|
177
|
+
}
|
|
178
|
+
/**
|
|
179
|
+
* Component to display detailed tool call information
|
|
180
|
+
*/
|
|
181
|
+
function ToolOperationDetails({ toolCall }) {
|
|
182
|
+
const { resolvedTheme } = useTheme();
|
|
183
|
+
// Don't show details for preliminary tool calls
|
|
184
|
+
if (isPreliminaryToolCall(toolCall)) {
|
|
185
|
+
return (_jsx("div", { className: "text-paragraph-sm text-text-secondary/70 ml-2", children: getToolCallStateVerbiage(toolCall) }));
|
|
186
|
+
}
|
|
187
|
+
// JSON View style based on theme
|
|
188
|
+
const jsonStyle = {
|
|
189
|
+
fontSize: "11px",
|
|
190
|
+
backgroundColor: "transparent",
|
|
191
|
+
fontFamily: "inherit",
|
|
192
|
+
"--w-rjv-color": resolvedTheme === "dark" ? "#fafafa" : "#09090b",
|
|
193
|
+
"--w-rjv-key-string": resolvedTheme === "dark" ? "#fafafa" : "#09090b",
|
|
194
|
+
"--w-rjv-background-color": "transparent",
|
|
195
|
+
"--w-rjv-line-color": resolvedTheme === "dark" ? "#27272a" : "#e4e4e7",
|
|
196
|
+
"--w-rjv-arrow-color": resolvedTheme === "dark" ? "#a1a1aa" : "#71717a",
|
|
197
|
+
"--w-rjv-edit-color": resolvedTheme === "dark" ? "#fafafa" : "#09090b",
|
|
198
|
+
"--w-rjv-info-color": resolvedTheme === "dark" ? "#a1a1aa" : "#71717a",
|
|
199
|
+
"--w-rjv-update-color": resolvedTheme === "dark" ? "#fafafa" : "#09090b",
|
|
200
|
+
"--w-rjv-copied-color": resolvedTheme === "dark" ? "#fafafa" : "#09090b",
|
|
201
|
+
"--w-rjv-copied-success-color": resolvedTheme === "dark" ? "#22c55e" : "#16a34a",
|
|
202
|
+
"--w-rjv-curlybraces-color": resolvedTheme === "dark" ? "#a1a1aa" : "#71717a",
|
|
203
|
+
"--w-rjv-colon-color": resolvedTheme === "dark" ? "#a1a1aa" : "#71717a",
|
|
204
|
+
"--w-rjv-brackets-color": resolvedTheme === "dark" ? "#a1a1aa" : "#71717a",
|
|
205
|
+
"--w-rjv-quotes-color": resolvedTheme === "dark" ? "#a1a1aa" : "#71717a",
|
|
206
|
+
"--w-rjv-quotes-string-color": resolvedTheme === "dark" ? "#a1a1aa" : "#71717a",
|
|
207
|
+
"--w-rjv-type-string-color": resolvedTheme === "dark" ? "#22c55e" : "#16a34a",
|
|
208
|
+
"--w-rjv-type-int-color": resolvedTheme === "dark" ? "#f59e0b" : "#d97706",
|
|
209
|
+
"--w-rjv-type-float-color": resolvedTheme === "dark" ? "#f59e0b" : "#d97706",
|
|
210
|
+
"--w-rjv-type-bigint-color": resolvedTheme === "dark" ? "#f59e0b" : "#d97706",
|
|
211
|
+
"--w-rjv-type-boolean-color": resolvedTheme === "dark" ? "#3b82f6" : "#2563eb",
|
|
212
|
+
"--w-rjv-type-date-color": resolvedTheme === "dark" ? "#ec4899" : "#db2777",
|
|
213
|
+
"--w-rjv-type-url-color": resolvedTheme === "dark" ? "#3b82f6" : "#2563eb",
|
|
214
|
+
"--w-rjv-type-null-color": resolvedTheme === "dark" ? "#ef4444" : "#dc2626",
|
|
215
|
+
"--w-rjv-type-nan-color": resolvedTheme === "dark" ? "#ef4444" : "#dc2626",
|
|
216
|
+
"--w-rjv-type-undefined-color": resolvedTheme === "dark" ? "#ef4444" : "#dc2626",
|
|
217
|
+
};
|
|
218
|
+
return (_jsxs("div", { className: "text-sm border border-border rounded-lg bg-card overflow-hidden w-full", children: [toolCall.locations && toolCall.locations.length > 0 && (_jsxs("div", { className: "p-3 border-b border-border", children: [_jsx("div", { className: "text-[10px] font-bold text-text-secondary uppercase tracking-wider mb-1.5 font-sans", children: "Files" }), _jsx("ul", { className: "space-y-1", children: toolCall.locations.map((loc) => (_jsxs("li", { className: "font-mono text-[11px] text-foreground bg-muted px-1.5 py-0.5 rounded w-fit", children: [loc.path, loc.line !== null && loc.line !== undefined && `:${loc.line}`] }, `${loc.path}:${loc.line ?? ""}`))) })] })), toolCall.rawInput && Object.keys(toolCall.rawInput).length > 0 && (_jsxs("div", { className: "p-3 border-b border-border", children: [_jsx("div", { className: "text-[10px] font-bold text-text-secondary uppercase tracking-wider mb-1.5 font-sans", children: "Input" }), _jsx("div", { className: "text-[11px] font-mono text-foreground", children: _jsx(JsonView, { value: toolCall.rawInput, collapsed: false, displayDataTypes: false, displayObjectSize: false, enableClipboard: true, style: jsonStyle }) })] })), ((toolCall.content && toolCall.content.length > 0) ||
|
|
219
|
+
toolCall.error) && (_jsxs("div", { className: "p-3 border-b border-border last:border-0", children: [_jsx("div", { className: "text-[10px] font-bold text-text-secondary uppercase tracking-wider mb-1.5 font-sans", children: "Output" }), _jsxs("div", { className: "space-y-2 text-[11px] text-foreground", children: [toolCall.content?.map((block, idx) => {
|
|
220
|
+
// Generate a stable key based on content
|
|
221
|
+
const getBlockKey = () => {
|
|
222
|
+
if (block.type === "diff" && "path" in block) {
|
|
223
|
+
return `diff-${block.path}-${idx}`;
|
|
224
|
+
}
|
|
225
|
+
if (block.type === "terminal" && "terminalId" in block) {
|
|
226
|
+
return `terminal-${block.terminalId}`;
|
|
227
|
+
}
|
|
228
|
+
if (block.type === "text" && "text" in block) {
|
|
229
|
+
return `text-${block.text.substring(0, 20)}-${idx}`;
|
|
230
|
+
}
|
|
231
|
+
if (block.type === "content" && "content" in block) {
|
|
232
|
+
const innerContent = block.content;
|
|
233
|
+
return `content-${innerContent.text?.substring(0, 20)}-${idx}`;
|
|
234
|
+
}
|
|
235
|
+
return `block-${idx}`;
|
|
236
|
+
};
|
|
237
|
+
// Helper to render text content
|
|
238
|
+
const renderTextContent = (text, key) => {
|
|
239
|
+
try {
|
|
240
|
+
const parsed = JSON.parse(text);
|
|
241
|
+
if (typeof parsed === "object" && parsed !== null) {
|
|
242
|
+
return (_jsx("div", { className: "text-[11px]", children: _jsx(JsonView, { value: parsed, collapsed: false, displayDataTypes: false, displayObjectSize: false, enableClipboard: true, style: jsonStyle }) }, key));
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
catch {
|
|
246
|
+
// Not valid JSON
|
|
247
|
+
}
|
|
248
|
+
return (_jsx("pre", { className: "whitespace-pre-wrap font-mono text-[11px] text-foreground overflow-x-auto", children: text }, key));
|
|
249
|
+
};
|
|
250
|
+
// Handle nested content blocks
|
|
251
|
+
if (block.type === "content" && "content" in block) {
|
|
252
|
+
const innerContent = block.content;
|
|
253
|
+
if (innerContent.type === "text" && innerContent.text) {
|
|
254
|
+
return renderTextContent(innerContent.text, getBlockKey());
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
// Handle direct text blocks
|
|
258
|
+
if (block.type === "text" && "text" in block) {
|
|
259
|
+
return renderTextContent(block.text, getBlockKey());
|
|
260
|
+
}
|
|
261
|
+
// Handle image blocks
|
|
262
|
+
if (block.type === "image") {
|
|
263
|
+
const alt = block.alt || "Generated image";
|
|
264
|
+
let imageSrc;
|
|
265
|
+
if ("data" in block) {
|
|
266
|
+
const mimeType = block.mimeType || "image/png";
|
|
267
|
+
imageSrc = `data:${mimeType};base64,${block.data}`;
|
|
268
|
+
}
|
|
269
|
+
else if ("url" in block) {
|
|
270
|
+
imageSrc = block.url;
|
|
271
|
+
}
|
|
272
|
+
else {
|
|
273
|
+
return null;
|
|
274
|
+
}
|
|
275
|
+
return (_jsx("div", { className: "my-2", children: _jsx("img", { src: imageSrc, alt: alt, className: "max-w-full h-auto rounded-md border border-border" }) }, getBlockKey()));
|
|
276
|
+
}
|
|
277
|
+
// Handle diff blocks
|
|
278
|
+
if (block.type === "diff" &&
|
|
279
|
+
"path" in block &&
|
|
280
|
+
"oldText" in block &&
|
|
281
|
+
"newText" in block) {
|
|
282
|
+
return (_jsxs("div", { className: "border border-border rounded bg-card", children: [_jsxs("div", { className: "bg-muted px-2 py-1 text-[10px] font-mono text-text-secondary border-b border-border", children: [block.path, "line" in block &&
|
|
283
|
+
block.line !== null &&
|
|
284
|
+
block.line !== undefined &&
|
|
285
|
+
`:${block.line}`] }), _jsxs("div", { className: "p-2 font-mono text-[11px]", children: [_jsxs("div", { className: "text-red-500 dark:text-red-400", children: ["- ", block.oldText] }), _jsxs("div", { className: "text-green-500 dark:text-green-400", children: ["+ ", block.newText] })] })] }, getBlockKey()));
|
|
286
|
+
}
|
|
287
|
+
return null;
|
|
288
|
+
}), toolCall.error && (_jsxs("div", { className: "text-destructive font-mono text-[11px] mt-2", children: ["Error: ", toolCall.error] }))] })] })), toolCall._meta?.truncationWarning && (_jsxs("div", { className: "mx-3 mt-3 mb-0 flex items-center gap-2 rounded-md bg-yellow-50 dark:bg-yellow-950/20 px-3 py-2 text-[11px] text-yellow-800 dark:text-yellow-200 border border-yellow-200 dark:border-yellow-900", children: [_jsx("span", { className: "text-yellow-600 dark:text-yellow-500", children: "\u26A0\uFE0F" }), _jsx("span", { children: toolCall._meta.truncationWarning })] })), (toolCall.tokenUsage || toolCall.startedAt) && (_jsxs("div", { className: "p-2 bg-muted/50 border-b border-border last:border-0 flex flex-wrap gap-4 text-[10px] text-text-secondary font-sans", children: [toolCall.tokenUsage && (_jsxs("div", { className: "flex gap-3", children: [toolCall.tokenUsage.inputTokens !== undefined && (_jsxs("div", { children: [_jsx("span", { className: "uppercase tracking-wide font-semibold mr-1", children: "Input:" }), toolCall.tokenUsage.inputTokens.toLocaleString()] })), toolCall.tokenUsage.outputTokens !== undefined && (_jsxs("div", { children: [_jsx("span", { className: "uppercase tracking-wide font-semibold mr-1", children: "Output:" }), toolCall.tokenUsage.outputTokens.toLocaleString()] })), toolCall.tokenUsage.totalTokens !== undefined && (_jsxs("div", { children: [_jsx("span", { className: "uppercase tracking-wide font-semibold mr-1", children: "Total:" }), toolCall.tokenUsage.totalTokens.toLocaleString()] }))] })), toolCall.startedAt && (_jsxs("div", { className: "flex gap-3 ml-auto", children: [_jsxs("span", { children: ["Started: ", new Date(toolCall.startedAt).toLocaleTimeString()] }), toolCall.completedAt && (_jsxs("span", { children: ["Completed:", " ", new Date(toolCall.completedAt).toLocaleTimeString(), " (", Math.round((toolCall.completedAt - toolCall.startedAt) / 1000), "s)"] }))] }))] }))] }));
|
|
289
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { ToolCall as ToolCallType } from "../../core/schemas/tool-call.js";
|
|
2
|
+
export interface WorkProgressProps {
|
|
3
|
+
/** Optional thinking/reasoning content */
|
|
4
|
+
thinking?: string;
|
|
5
|
+
/** Whether thinking is currently streaming */
|
|
6
|
+
isThinkingStreaming?: boolean;
|
|
7
|
+
/** Tool calls to display */
|
|
8
|
+
toolCalls?: ToolCallType[];
|
|
9
|
+
/** Display style for thinking */
|
|
10
|
+
thinkingDisplayStyle?: "collapsible" | "inline";
|
|
11
|
+
/** Whether to auto-collapse thinking when done */
|
|
12
|
+
autoCollapseThinking?: boolean;
|
|
13
|
+
/** Additional CSS class */
|
|
14
|
+
className?: string;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* WorkProgress component - coordinates display of thinking and tool execution
|
|
18
|
+
* Provides a unified view of the agent's work from thinking through execution
|
|
19
|
+
*/
|
|
20
|
+
export declare function WorkProgress({ thinking, isThinkingStreaming, toolCalls, thinkingDisplayStyle, autoCollapseThinking, className, }: WorkProgressProps): import("react/jsx-runtime").JSX.Element | null;
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import * as React from "react";
|
|
3
|
+
import { getGroupDisplayState, isPreliminaryToolCall, } from "../../core/utils/tool-call-state.js";
|
|
4
|
+
import { cn } from "../lib/utils.js";
|
|
5
|
+
import { Reasoning } from "./Reasoning.js";
|
|
6
|
+
import { ToolOperation } from "./ToolOperation.js";
|
|
7
|
+
/**
|
|
8
|
+
* WorkProgress component - coordinates display of thinking and tool execution
|
|
9
|
+
* Provides a unified view of the agent's work from thinking through execution
|
|
10
|
+
*/
|
|
11
|
+
export function WorkProgress({ thinking, isThinkingStreaming = false, toolCalls = [], thinkingDisplayStyle = "collapsible", autoCollapseThinking = true, className, }) {
|
|
12
|
+
// Group tool calls by batchId and type
|
|
13
|
+
const groupedToolCalls = React.useMemo(() => {
|
|
14
|
+
if (toolCalls.length === 0)
|
|
15
|
+
return [];
|
|
16
|
+
const result = [];
|
|
17
|
+
const batchMap = new Map();
|
|
18
|
+
let selectingGroup = [];
|
|
19
|
+
const flushSelectingGroup = () => {
|
|
20
|
+
if (selectingGroup.length > 0) {
|
|
21
|
+
if (selectingGroup.length > 1) {
|
|
22
|
+
result.push({ type: "selecting", toolCalls: selectingGroup });
|
|
23
|
+
}
|
|
24
|
+
else {
|
|
25
|
+
result.push({ type: "single", toolCall: selectingGroup[0] });
|
|
26
|
+
}
|
|
27
|
+
selectingGroup = [];
|
|
28
|
+
}
|
|
29
|
+
};
|
|
30
|
+
for (const toolCall of toolCalls) {
|
|
31
|
+
// Handle batch groups (parallel operations)
|
|
32
|
+
if (toolCall.batchId) {
|
|
33
|
+
flushSelectingGroup();
|
|
34
|
+
const existing = batchMap.get(toolCall.batchId);
|
|
35
|
+
if (existing) {
|
|
36
|
+
existing.push(toolCall);
|
|
37
|
+
}
|
|
38
|
+
else {
|
|
39
|
+
const group = [toolCall];
|
|
40
|
+
batchMap.set(toolCall.batchId, group);
|
|
41
|
+
result.push({
|
|
42
|
+
type: "batch",
|
|
43
|
+
batchId: toolCall.batchId,
|
|
44
|
+
toolCalls: group,
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
// Handle consecutive preliminary (selecting) tool calls
|
|
49
|
+
else if (isPreliminaryToolCall(toolCall)) {
|
|
50
|
+
selectingGroup.push(toolCall);
|
|
51
|
+
}
|
|
52
|
+
// Regular tool call
|
|
53
|
+
else {
|
|
54
|
+
flushSelectingGroup();
|
|
55
|
+
result.push({ type: "single", toolCall });
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
// Flush any remaining selecting group
|
|
59
|
+
flushSelectingGroup();
|
|
60
|
+
return result;
|
|
61
|
+
}, [toolCalls]);
|
|
62
|
+
const hasThinking = !!thinking;
|
|
63
|
+
const hasToolCalls = toolCalls.length > 0;
|
|
64
|
+
if (!hasThinking && !hasToolCalls) {
|
|
65
|
+
return null;
|
|
66
|
+
}
|
|
67
|
+
return (_jsxs("div", { className: cn("work-progress", className), children: [hasThinking && (_jsx(Reasoning, { content: thinking, isStreaming: isThinkingStreaming, mode: thinkingDisplayStyle, autoCollapse: autoCollapseThinking })), groupedToolCalls.map((group, index) => {
|
|
68
|
+
if (group.type === "batch") {
|
|
69
|
+
// Parallel operations group
|
|
70
|
+
return (_jsx(ToolOperation, { toolCalls: group.toolCalls, isGrouped: true, autoMinimize: true }, `batch-${group.batchId}`));
|
|
71
|
+
}
|
|
72
|
+
if (group.type === "selecting") {
|
|
73
|
+
// Multiple selecting operations
|
|
74
|
+
return (_jsx(ToolOperation, { toolCalls: group.toolCalls, isGrouped: true, autoMinimize: false }, `selecting-${index}`));
|
|
75
|
+
}
|
|
76
|
+
// Single tool call
|
|
77
|
+
return (_jsx(ToolOperation, { toolCalls: [group.toolCall], isGrouped: false, autoMinimize: true }, group.toolCall.id));
|
|
78
|
+
})] }));
|
|
79
|
+
}
|
|
@@ -2,6 +2,7 @@ export { toast } from "sonner";
|
|
|
2
2
|
export { MockFileSystemProvider, mockFileSystemData, } from "../data/mockFileSystemData.js";
|
|
3
3
|
export { mockSourceData } from "../data/mockSourceData.js";
|
|
4
4
|
export type { FileSystemData, FileSystemItem as FileSystemItemData, FileSystemItemType, FileSystemProvider, } from "../types/filesystem.js";
|
|
5
|
+
export { AppSidebar, type AppSidebarProps, } from "./AppSidebar.js";
|
|
5
6
|
export { Button, type ButtonProps, buttonVariants } from "./Button.js";
|
|
6
7
|
export { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle, } from "./Card.js";
|
|
7
8
|
export { ChatEmptyState, type ChatEmptyStateProps } from "./ChatEmptyState.js";
|
|
@@ -32,6 +33,11 @@ export { PanelTabsHeader, type PanelTabsHeaderProps, } from "./PanelTabsHeader.j
|
|
|
32
33
|
export { Reasoning, type ReasoningProps } from "./Reasoning.js";
|
|
33
34
|
export { Response, type ResponseProps } from "./Response.js";
|
|
34
35
|
export { Select, SelectContent, SelectGroup, SelectItem, SelectLabel, SelectScrollDownButton, SelectScrollUpButton, SelectSeparator, SelectTrigger, SelectValue, } from "./Select.js";
|
|
36
|
+
export { SessionHistory, type SessionHistoryProps, } from "./SessionHistory.js";
|
|
37
|
+
export { SessionHistoryItem, type SessionHistoryItemProps, } from "./SessionHistoryItem.js";
|
|
38
|
+
export { Sheet, SheetClose, SheetContent, SheetDescription, SheetFooter, SheetHeader, SheetOverlay, SheetPortal, SheetTitle, SheetTrigger, } from "./Sheet.js";
|
|
39
|
+
export { Sidebar, SidebarContent, SidebarFooter, SidebarGroup, SidebarGroupAction, SidebarGroupContent, SidebarGroupLabel, SidebarHeader, SidebarInput, SidebarInset, SidebarMenu, SidebarMenuAction, SidebarMenuBadge, SidebarMenuButton, SidebarMenuItem, SidebarMenuSkeleton, SidebarMenuSub, SidebarMenuSubButton, SidebarMenuSubItem, SidebarProvider, SidebarRail, SidebarSeparator, SidebarTrigger, useSidebar, } from "./Sidebar.js";
|
|
40
|
+
export { SidebarToggle } from "./SidebarToggle.js";
|
|
35
41
|
export { Toaster } from "./Sonner.js";
|
|
36
42
|
export { type SourceItem, SourceListItem, type SourceListItemProps, } from "./SourceListItem.js";
|
|
37
43
|
export { SubAgentDetails, type SubAgentDetailsProps, } from "./SubAgentDetails.js";
|
|
@@ -43,6 +49,7 @@ export { ThemeToggle } from "./ThemeToggle.js";
|
|
|
43
49
|
export { ThinkingBlock, type ThinkingBlockProps, } from "./ThinkingBlock.js";
|
|
44
50
|
export { TodoList, type TodoListProps } from "./TodoList.js";
|
|
45
51
|
export { type TodoItem, TodoListItem, type TodoListItemProps, } from "./TodoListItem.js";
|
|
46
|
-
export { ToolCall, type ToolCallProps } from "./ToolCall.js";
|
|
47
52
|
export { ToolCallList, type ToolCallListProps } from "./ToolCallList.js";
|
|
53
|
+
export { ToolOperation, type ToolOperationProps } from "./ToolOperation.js";
|
|
48
54
|
export { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger, } from "./Tooltip.js";
|
|
55
|
+
export { WorkProgress, type WorkProgressProps } from "./WorkProgress.js";
|
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
export { toast } from "sonner";
|
|
3
3
|
export { MockFileSystemProvider, mockFileSystemData, } from "../data/mockFileSystemData.js";
|
|
4
4
|
export { mockSourceData } from "../data/mockSourceData.js";
|
|
5
|
+
// Sidebar components
|
|
6
|
+
export { AppSidebar, } from "./AppSidebar.js";
|
|
5
7
|
export { Button, buttonVariants } from "./Button.js";
|
|
6
8
|
export { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle, } from "./Card.js";
|
|
7
9
|
export { ChatEmptyState } from "./ChatEmptyState.js";
|
|
@@ -37,6 +39,11 @@ export { PanelTabsHeader, } from "./PanelTabsHeader.js";
|
|
|
37
39
|
export { Reasoning } from "./Reasoning.js";
|
|
38
40
|
export { Response } from "./Response.js";
|
|
39
41
|
export { Select, SelectContent, SelectGroup, SelectItem, SelectLabel, SelectScrollDownButton, SelectScrollUpButton, SelectSeparator, SelectTrigger, SelectValue, } from "./Select.js";
|
|
42
|
+
export { SessionHistory, } from "./SessionHistory.js";
|
|
43
|
+
export { SessionHistoryItem, } from "./SessionHistoryItem.js";
|
|
44
|
+
export { Sheet, SheetClose, SheetContent, SheetDescription, SheetFooter, SheetHeader, SheetOverlay, SheetPortal, SheetTitle, SheetTrigger, } from "./Sheet.js";
|
|
45
|
+
export { Sidebar, SidebarContent, SidebarFooter, SidebarGroup, SidebarGroupAction, SidebarGroupContent, SidebarGroupLabel, SidebarHeader, SidebarInput, SidebarInset, SidebarMenu, SidebarMenuAction, SidebarMenuBadge, SidebarMenuButton, SidebarMenuItem, SidebarMenuSkeleton, SidebarMenuSub, SidebarMenuSubButton, SidebarMenuSubItem, SidebarProvider, SidebarRail, SidebarSeparator, SidebarTrigger, useSidebar, } from "./Sidebar.js";
|
|
46
|
+
export { SidebarToggle } from "./SidebarToggle.js";
|
|
40
47
|
export { Toaster } from "./Sonner.js";
|
|
41
48
|
// Toast components
|
|
42
49
|
export { SourceListItem, } from "./SourceListItem.js";
|
|
@@ -50,7 +57,8 @@ export { ThemeToggle } from "./ThemeToggle.js";
|
|
|
50
57
|
export { ThinkingBlock, } from "./ThinkingBlock.js";
|
|
51
58
|
export { TodoList } from "./TodoList.js";
|
|
52
59
|
export { TodoListItem, } from "./TodoListItem.js";
|
|
53
|
-
export { ToolCall } from "./ToolCall.js";
|
|
54
60
|
export { ToolCallList } from "./ToolCallList.js";
|
|
61
|
+
export { ToolOperation } from "./ToolOperation.js";
|
|
55
62
|
// Tooltip components
|
|
56
63
|
export { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger, } from "./Tooltip.js";
|
|
64
|
+
export { WorkProgress } from "./WorkProgress.js";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { useIsMobile } from "./use-mobile.js";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { useIsMobile } from "./use-mobile.js";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function useIsMobile(): boolean;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
const MOBILE_BREAKPOINT = 768;
|
|
3
|
+
export function useIsMobile() {
|
|
4
|
+
const [isMobile, setIsMobile] = React.useState(undefined);
|
|
5
|
+
React.useEffect(() => {
|
|
6
|
+
const mql = window.matchMedia(`(max-width: ${MOBILE_BREAKPOINT - 1}px)`);
|
|
7
|
+
const onChange = () => {
|
|
8
|
+
setIsMobile(window.innerWidth < MOBILE_BREAKPOINT);
|
|
9
|
+
};
|
|
10
|
+
mql.addEventListener("change", onChange);
|
|
11
|
+
setIsMobile(window.innerWidth < MOBILE_BREAKPOINT);
|
|
12
|
+
return () => mql.removeEventListener("change", onChange);
|
|
13
|
+
}, []);
|
|
14
|
+
return !!isMobile;
|
|
15
|
+
}
|
package/dist/gui/index.d.ts
CHANGED