@townco/ui 0.1.33 → 0.1.35

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (48) hide show
  1. package/dist/core/hooks/use-chat-session.d.ts +1 -1
  2. package/dist/core/schemas/chat.d.ts +1 -1
  3. package/dist/gui/components/Button.js +1 -1
  4. package/dist/gui/components/ChatEmptyState.js +1 -1
  5. package/dist/gui/components/ChatHeader.js +2 -2
  6. package/dist/gui/components/ChatInput.js +1 -1
  7. package/dist/gui/components/ChatInputCommandMenu.js +1 -1
  8. package/dist/gui/components/ChatLayout.js +1 -1
  9. package/dist/gui/components/ChatPanelTabContent.d.ts +3 -0
  10. package/dist/gui/components/ChatPanelTabContent.js +24 -5
  11. package/dist/gui/components/ChatSecondaryPanel.js +3 -3
  12. package/dist/gui/components/ChatView.js +28 -9
  13. package/dist/gui/components/Dialog.js +2 -2
  14. package/dist/gui/components/DropdownMenu.js +7 -7
  15. package/dist/gui/components/FileSystemItem.d.ts +17 -0
  16. package/dist/gui/components/FileSystemItem.js +81 -0
  17. package/dist/gui/components/FileSystemView.d.ts +14 -0
  18. package/dist/gui/components/FileSystemView.js +46 -0
  19. package/dist/gui/components/Input.js +1 -1
  20. package/dist/gui/components/Label.js +1 -1
  21. package/dist/gui/components/MarkdownRenderer.js +5 -5
  22. package/dist/gui/components/Message.d.ts +1 -1
  23. package/dist/gui/components/MessageContent.js +8 -8
  24. package/dist/gui/components/PanelTabsHeader.js +1 -1
  25. package/dist/gui/components/Reasoning.js +2 -2
  26. package/dist/gui/components/Response.js +13 -11
  27. package/dist/gui/components/Select.js +3 -3
  28. package/dist/gui/components/SourceListItem.js +1 -1
  29. package/dist/gui/components/Tabs.js +1 -1
  30. package/dist/gui/components/Task.js +2 -2
  31. package/dist/gui/components/Textarea.js +1 -1
  32. package/dist/gui/components/ThinkingBlock.js +2 -2
  33. package/dist/gui/components/TodoList.js +1 -1
  34. package/dist/gui/components/ToolCall.js +67 -70
  35. package/dist/gui/components/ToolCallList.js +1 -1
  36. package/dist/gui/components/index.d.ts +4 -0
  37. package/dist/gui/components/index.js +4 -0
  38. package/dist/gui/data/mockFileSystemData.d.ts +21 -0
  39. package/dist/gui/data/mockFileSystemData.js +127 -0
  40. package/dist/gui/types/filesystem.d.ts +27 -0
  41. package/dist/gui/types/filesystem.js +5 -0
  42. package/dist/sdk/schemas/session.d.ts +12 -12
  43. package/package.json +3 -3
  44. package/src/styles/global.css +108 -0
  45. package/dist/core/lib/logger.d.ts +0 -59
  46. package/dist/core/lib/logger.js +0 -191
  47. package/dist/tui/components/LogsPanel.d.ts +0 -5
  48. package/dist/tui/components/LogsPanel.js +0 -29
@@ -62,14 +62,14 @@ function WaitingElapsedTime({ startTime }) {
62
62
  }, []);
63
63
  const seconds = (elapsed / 1000).toFixed(1);
64
64
  const animatedDots = DOT_ANIMATIONS[dotIndex];
65
- return (_jsxs("span", { className: "text-muted-foreground text-sm", children: [thinkingWord, animatedDots, " ", seconds, "s"] }));
65
+ return (_jsxs("span", { className: "text-muted-foreground text-paragraph-sm", children: [thinkingWord, animatedDots, " ", seconds, "s"] }));
66
66
  }
67
- const messageContentVariants = cva("w-full px-4 py-3 rounded-xl text-[var(--font-size)] font-[var(--font-family)] leading-relaxed break-words transition-colors", {
67
+ const messageContentVariants = cva("w-full rounded-2xl text-[var(--font-size)] font-[var(--font-family)] leading-relaxed break-words transition-colors", {
68
68
  variants: {
69
69
  role: {
70
- user: "bg-primary text-primary-foreground shadow-sm",
71
- assistant: "text-foreground",
72
- system: "bg-card border border-border text-foreground opacity-80 text-sm",
70
+ user: "bg-secondary text-foreground px-4 py-4 text-paragraph",
71
+ assistant: "text-foreground text-paragraph-sm",
72
+ system: "bg-card border border-border text-foreground opacity-80 text-caption px-4 py-3",
73
73
  },
74
74
  variant: {
75
75
  default: "",
@@ -109,7 +109,7 @@ export const MessageContent = React.forwardRef(({ role: roleProp, variant, isStr
109
109
  // If no tool calls or they don't have positions, render old way
110
110
  if (sortedToolCalls.length === 0 ||
111
111
  !sortedToolCalls.some((tc) => tc.contentPosition !== undefined)) {
112
- return (_jsxs(_Fragment, { children: [sortedToolCalls.length > 0 && (_jsx("div", { className: "flex flex-col gap-2 mb-3", children: sortedToolCalls.map((toolCall) => (_jsx(ToolCall, { toolCall: toolCall }, toolCall.id))) })), _jsx(Response, { content: message.content, isStreaming: message.isStreaming, showEmpty: false })] }));
112
+ return (_jsxs(_Fragment, { children: [sortedToolCalls.length > 0 && (_jsx("div", { className: "flex flex-col gap-2 mb-1", children: sortedToolCalls.map((toolCall) => (_jsx(ToolCall, { toolCall: toolCall }, toolCall.id))) })), _jsx(Response, { content: message.content, isStreaming: message.isStreaming, showEmpty: false })] }));
113
113
  }
114
114
  // Render content interleaved with tool calls
115
115
  const elements = [];
@@ -124,7 +124,7 @@ export const MessageContent = React.forwardRef(({ role: roleProp, variant, isStr
124
124
  }
125
125
  }
126
126
  // Add the tool call
127
- elements.push(_jsx("div", { className: "my-2", children: _jsx(ToolCall, { toolCall: toolCall }) }, `tool-${toolCall.id}`));
127
+ elements.push(_jsx("div", { children: _jsx(ToolCall, { toolCall: toolCall }) }, `tool-${toolCall.id}`));
128
128
  currentPosition = position;
129
129
  });
130
130
  // Add remaining text after the last tool call
@@ -135,7 +135,7 @@ export const MessageContent = React.forwardRef(({ role: roleProp, variant, isStr
135
135
  }
136
136
  }
137
137
  return _jsx(_Fragment, { children: elements });
138
- })()) : (_jsx("div", { className: "whitespace-pre-wrap", children: message.content })), message.role === "assistant" && message.tokenUsage && (_jsx("div", { className: "mt-3 pt-2 border-t border-border/30 text-xs text-muted-foreground/60", children: _jsxs("span", { children: ["Context:", " ", formatTokenPercentage(message.tokenUsage.totalTokens ?? 0, currentModel ?? undefined), " ", "(", (message.tokenUsage.totalTokens ?? 0).toLocaleString(), " ", "tokens)"] }) }))] }));
138
+ })()) : (_jsx("div", { className: "whitespace-pre-wrap", children: message.content })), message.role === "assistant" && message.tokenUsage && (_jsx("div", { className: "mt-3 pt-2 border-t border-border/30 text-caption text-muted-foreground/60", children: _jsxs("span", { children: ["Context:", " ", formatTokenPercentage(message.tokenUsage.totalTokens ?? 0, currentModel ?? undefined), " ", "(", (message.tokenUsage.totalTokens ?? 0).toLocaleString(), " ", "tokens)"] }) }))] }));
139
139
  }
140
140
  return (_jsx("div", { ref: ref, className: cn(messageContentVariants({ role, variant }), isStreaming && "animate-pulse-subtle", className), ...props, children: content }));
141
141
  });
@@ -30,7 +30,7 @@ export const PanelTabsHeader = React.forwardRef(({ showIcons = true, visibleTabs
30
30
  const gap = variant === "compact" ? "gap-[4px]" : "gap-3";
31
31
  return (_jsx(TabsList, { ref: ref, className: cn("w-full justify-start bg-transparent p-0 h-auto", gap, className), ...props, children: tabs.map((tab) => {
32
32
  const Icon = tab.icon;
33
- return (_jsxs(TabsTrigger, { value: tab.id, className: cn("gap-2 px-3 py-1.5 rounded-lg text-sm font-medium", "data-[state=active]:bg-zinc-100 data-[state=active]:text-foreground", "data-[state=inactive]:text-muted-foreground"), children: [showIcons && Icon && _jsx(Icon, { className: "size-4" }), tab.label] }, tab.id));
33
+ return (_jsxs(TabsTrigger, { value: tab.id, className: cn("gap-2 px-3 py-1.5 rounded-lg text-paragraph-sm font-medium", "data-[state=active]:bg-zinc-100 data-[state=active]:text-foreground", "data-[state=inactive]:text-muted-foreground"), children: [showIcons && Icon && _jsx(Icon, { className: "size-4" }), tab.label] }, tab.id));
34
34
  }) }));
35
35
  });
36
36
  PanelTabsHeader.displayName = "PanelTabsHeader";
@@ -59,12 +59,12 @@ export const Reasoning = React.forwardRef(({ content, isStreaming = false, mode
59
59
  }
60
60
  // Inline mode - always visible
61
61
  if (mode === "inline") {
62
- return (_jsxs("div", { ref: ref, className: cn(reasoningContainerVariants({ variant }), "p-3", className), children: [_jsxs("div", { className: "flex items-start gap-2 mb-2", children: [_jsx("span", { className: "text-xs font-medium text-foreground opacity-60 uppercase tracking-wide", children: label }), isStreaming && (_jsx("span", { className: "inline-block w-2 h-2 bg-primary rounded-full animate-pulse" }))] }), _jsxs("div", { className: "text-sm italic text-foreground opacity-80 leading-relaxed whitespace-pre-wrap", children: [content, isStreaming && content && (_jsx("span", { className: "inline-block animate-typing text-primary", children: "..." }))] })] }));
62
+ return (_jsxs("div", { ref: ref, className: cn(reasoningContainerVariants({ variant }), "p-3", className), children: [_jsxs("div", { className: "flex items-start gap-2 mb-2", children: [_jsx("span", { className: "text-caption font-medium text-foreground opacity-60 uppercase tracking-wide", children: label }), isStreaming && (_jsx("span", { className: "inline-block w-2 h-2 bg-primary rounded-full animate-pulse" }))] }), _jsxs("div", { className: "text-paragraph-sm italic text-foreground opacity-80 leading-relaxed whitespace-pre-wrap", children: [content, isStreaming && content && (_jsx("span", { className: "inline-block animate-typing text-primary", children: "..." }))] })] }));
63
63
  }
64
64
  // Collapsible mode
65
65
  return (_jsxs("div", { ref: ref, className: cn("mb-3", className), children: [_jsxs("button", { type: "button", onClick: () => {
66
66
  setIsExpanded(!isExpanded);
67
67
  setShouldAutoCollapse(false); // Disable auto-collapse on manual interaction
68
- }, className: "w-full flex items-center justify-between p-2.5 rounded-lg bg-card border border-border hover:bg-card/80 hover:shadow-sm transition-all text-left", "aria-expanded": isExpanded, "aria-label": `${isExpanded ? "Collapse" : "Expand"} reasoning`, children: [_jsxs("div", { className: "flex items-center gap-2 flex-1 min-w-0", children: [_jsx("span", { className: "text-xs font-medium text-foreground opacity-60 uppercase tracking-wide shrink-0", children: label }), isStreaming && (_jsx("span", { className: "inline-block w-2 h-2 bg-primary rounded-full animate-pulse shrink-0" })), !isExpanded && content && (_jsxs("span", { className: "text-xs text-foreground opacity-50 truncate", children: [content.substring(0, 60), content.length > 60 && "..."] }))] }), _jsx(ChevronDown, { className: reasoningIconVariants({ expanded: isExpanded }), "aria-hidden": "true" })] }), isExpanded && (_jsx("div", { className: cn(reasoningContainerVariants({ variant }), "mt-2 p-3 animate-fadeIn"), children: _jsxs("div", { className: "text-sm italic text-foreground opacity-80 leading-relaxed whitespace-pre-wrap", children: [content, isStreaming && content && (_jsx("span", { className: "inline-block animate-typing text-primary", children: "..." }))] }) }))] }));
68
+ }, className: "w-full flex items-center justify-between p-2.5 rounded-lg bg-card border border-border hover:bg-card/80 hover:shadow-sm transition-all text-left", "aria-expanded": isExpanded, "aria-label": `${isExpanded ? "Collapse" : "Expand"} reasoning`, children: [_jsxs("div", { className: "flex items-center gap-2 flex-1 min-w-0", children: [_jsx("span", { className: "text-caption font-medium text-foreground opacity-60 uppercase tracking-wide shrink-0", children: label }), isStreaming && (_jsx("span", { className: "inline-block w-2 h-2 bg-primary rounded-full animate-pulse shrink-0" })), !isExpanded && content && (_jsxs("span", { className: "text-caption text-foreground opacity-50 truncate", children: [content.substring(0, 60), content.length > 60 && "..."] }))] }), _jsx(ChevronDown, { className: reasoningIconVariants({ expanded: isExpanded }), "aria-hidden": "true" })] }), isExpanded && (_jsx("div", { className: cn(reasoningContainerVariants({ variant }), "mt-2 p-3 animate-fadeIn"), children: _jsxs("div", { className: "text-paragraph-sm italic text-foreground opacity-80 leading-relaxed whitespace-pre-wrap", children: [content, isStreaming && content && (_jsx("span", { className: "inline-block animate-typing text-primary", children: "..." }))] }) }))] }));
69
69
  });
70
70
  Reasoning.displayName = "Reasoning";
@@ -6,7 +6,7 @@ import { cn } from "../lib/utils.js";
6
6
  export const Response = React.forwardRef(({ content, isStreaming = false, showEmpty = true, emptyMessage = "", className, ...props }, ref) => {
7
7
  // Show empty state during streaming if no content yet
8
8
  if (!content && isStreaming && showEmpty) {
9
- return (_jsx("div", { ref: ref, className: cn("opacity-70 italic text-sm", className), ...props, children: emptyMessage }));
9
+ return (_jsx("div", { ref: ref, className: cn("opacity-70 italic text-paragraph-sm", className), ...props, children: emptyMessage }));
10
10
  }
11
11
  if (!content) {
12
12
  return null;
@@ -30,16 +30,16 @@ export const Response = React.forwardRef(({ content, isStreaming = false, showEm
30
30
  code: ({ node, ...props }) => {
31
31
  const inline = !props.className?.includes("language-");
32
32
  if (inline) {
33
- return (_jsx("code", { className: "px-1.5 py-0.5 bg-card border border-border rounded text-sm font-mono text-foreground", ...props }));
33
+ return (_jsx("code", { className: "px-1.5 py-0.5 bg-card border border-border rounded text-code text-foreground", ...props }));
34
34
  }
35
- return (_jsx("code", { className: "block p-4 bg-card border border-border rounded-md overflow-x-auto text-sm font-mono text-foreground shadow-sm", ...props }));
35
+ return (_jsx("code", { className: "block p-4 bg-card border border-border rounded-md overflow-x-auto text-code text-foreground shadow-sm", ...props }));
36
36
  },
37
37
  pre: ({ node, ...props }) => (_jsx("pre", { className: "my-4 rounded-lg", ...props })),
38
38
  // Heading styling with improved hierarchy
39
- h1: ({ node, ...props }) => (_jsx("h1", { className: "text-2xl font-bold mt-6 mb-4 text-foreground border-b border-border pb-2", ...props })),
40
- h2: ({ node, ...props }) => (_jsx("h2", { className: "text-xl font-semibold mt-5 mb-3 text-foreground border-b border-border/50 pb-1.5", ...props })),
41
- h3: ({ node, ...props }) => (_jsx("h3", { className: "text-lg font-semibold mt-4 mb-2 text-foreground", ...props })),
42
- h4: ({ node, ...props }) => (_jsx("h4", { className: "text-base font-semibold mt-3 mb-2 text-foreground", ...props })),
39
+ h1: ({ node, ...props }) => (_jsx("h1", { className: "text-heading-3 mt-6 mb-4 text-foreground border-b border-border pb-2", ...props })),
40
+ h2: ({ node, ...props }) => (_jsx("h2", { className: "text-subheading mt-5 mb-3 text-foreground border-b border-border/50 pb-1.5", ...props })),
41
+ h3: ({ node, ...props }) => (_jsx("h3", { className: "text-subheading mt-4 mb-2 text-foreground", ...props })),
42
+ h4: ({ node, ...props }) => (_jsx("h4", { className: "text-paragraph-sm font-semibold mt-3 mb-2 text-foreground", ...props })),
43
43
  // List styling
44
44
  ul: ({ node, ...props }) => {
45
45
  // Check if this is a task list by looking for checkbox inputs in children
@@ -62,9 +62,11 @@ export const Response = React.forwardRef(({ content, isStreaming = false, showEm
62
62
  grandChild.properties !== null &&
63
63
  "type" in grandChild.properties &&
64
64
  grandChild.properties.type === "checkbox"));
65
- return (_jsx("ul", { className: cn("my-2 space-y-1 text-foreground", isTaskList ? "list-none space-y-2" : "list-disc list-inside"), ...props }));
65
+ return (_jsx("ul", { className: cn("my-2 space-y-1 text-foreground", isTaskList
66
+ ? "list-none space-y-2"
67
+ : "list-disc list-outside pl-4"), ...props }));
66
68
  },
67
- ol: ({ node, ...props }) => (_jsx("ol", { className: "list-decimal list-inside my-2 space-y-1 text-foreground", ...props })),
69
+ ol: ({ node, ...props }) => (_jsx("ol", { className: "list-decimal list-outside pl-4 my-2 space-y-1 text-foreground", ...props })),
68
70
  // List item styling
69
71
  li: ({ node, ...props }) => {
70
72
  // Check if this li contains a checkbox (task list item)
@@ -79,12 +81,12 @@ export const Response = React.forwardRef(({ content, isStreaming = false, showEm
79
81
  child.properties !== null &&
80
82
  "type" in child.properties &&
81
83
  child.properties.type === "checkbox");
82
- return (_jsx("li", { className: cn("flex items-start", isTaskListItem ? "gap-2" : "ml-2"), ...props }));
84
+ return (_jsx("li", { className: cn(isTaskListItem ? "flex items-start gap-2" : ""), ...props }));
83
85
  },
84
86
  // Link styling with hover effect
85
87
  a: ({ node, ...props }) => (_jsx("a", { className: "text-primary hover:underline decoration-2 underline-offset-2 transition-all", target: "_blank", rel: "noopener noreferrer", ...props })),
86
88
  // Paragraph styling
87
- p: ({ node, ...props }) => (_jsx("p", { className: "my-2 text-foreground leading-relaxed", ...props })),
89
+ p: ({ node, ...props }) => (_jsx("p", { className: "mb-2 text-foreground leading-relaxed", ...props })),
88
90
  // Blockquote styling with enhanced visual
89
91
  blockquote: ({ node, ...props }) => (_jsx("blockquote", { className: "border-l-4 border-[primary] pl-4 italic my-4 text-foreground bg-card py-2 rounded-r-md shadow-sm", ...props })),
90
92
  // Horizontal rule
@@ -6,7 +6,7 @@ import { cn } from "../lib/utils.js";
6
6
  const Select = SelectPrimitive.Root;
7
7
  const SelectGroup = SelectPrimitive.Group;
8
8
  const SelectValue = SelectPrimitive.Value;
9
- const SelectTrigger = React.forwardRef(({ className, children, ...props }, ref) => (_jsxs(SelectPrimitive.Trigger, { ref: ref, className: cn("flex h-10 w-full items-center justify-between rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background placeholder:text-muted-foreground focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 [&>span]:line-clamp-1", className), ...props, children: [children, _jsx(SelectPrimitive.Icon, { asChild: true, children: _jsx(ChevronsUpDown, { className: "h-4 w-4 opacity-50" }) })] })));
9
+ const SelectTrigger = React.forwardRef(({ className, children, ...props }, ref) => (_jsxs(SelectPrimitive.Trigger, { ref: ref, className: cn("flex h-10 w-full items-center justify-between rounded-md border border-input bg-background px-3 py-2 text-paragraph-sm ring-offset-background placeholder:text-muted-foreground focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 [&>span]:line-clamp-1", className), ...props, children: [children, _jsx(SelectPrimitive.Icon, { asChild: true, children: _jsx(ChevronsUpDown, { className: "h-4 w-4 opacity-50" }) })] })));
10
10
  SelectTrigger.displayName = SelectPrimitive.Trigger.displayName;
11
11
  const SelectScrollUpButton = React.forwardRef(({ className, ...props }, ref) => (_jsx(SelectPrimitive.ScrollUpButton, { ref: ref, className: cn("flex cursor-default items-center justify-center py-1", className), ...props, children: _jsx(ChevronUp, { className: "h-4 w-4" }) })));
12
12
  SelectScrollUpButton.displayName = SelectPrimitive.ScrollUpButton.displayName;
@@ -17,9 +17,9 @@ const SelectContent = React.forwardRef(({ className, children, position = "poppe
17
17
  "data-[side=bottom]:translate-y-1 data-[side=left]:-translate-x-1 data-[side=right]:translate-x-1 data-[side=top]:-translate-y-1", className), position: position, ...props, children: [_jsx(SelectScrollUpButton, {}), _jsx(SelectPrimitive.Viewport, { className: cn("p-1", position === "popper" &&
18
18
  "h-[var(--radix-select-trigger-height)] w-full min-w-[var(--radix-select-trigger-width)]"), children: children }), _jsx(SelectScrollDownButton, {})] }) })));
19
19
  SelectContent.displayName = SelectPrimitive.Content.displayName;
20
- const SelectLabel = React.forwardRef(({ className, ...props }, ref) => (_jsx(SelectPrimitive.Label, { ref: ref, className: cn("py-1.5 pl-8 pr-2 text-sm font-semibold", className), ...props })));
20
+ const SelectLabel = React.forwardRef(({ className, ...props }, ref) => (_jsx(SelectPrimitive.Label, { ref: ref, className: cn("py-1.5 pl-8 pr-2 text-paragraph-sm font-semibold", className), ...props })));
21
21
  SelectLabel.displayName = SelectPrimitive.Label.displayName;
22
- const SelectItem = React.forwardRef(({ className, children, ...props }, ref) => (_jsxs(SelectPrimitive.Item, { ref: ref, className: cn("relative flex w-full cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50", className), ...props, children: [_jsx("span", { className: "absolute left-2 flex h-3.5 w-3.5 items-center justify-center", children: _jsx(SelectPrimitive.ItemIndicator, { children: _jsx(Check, { className: "h-4 w-4" }) }) }), _jsx(SelectPrimitive.ItemText, { children: children })] })));
22
+ const SelectItem = React.forwardRef(({ className, children, ...props }, ref) => (_jsxs(SelectPrimitive.Item, { ref: ref, className: cn("relative flex w-full cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-paragraph-sm outline-none focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50", className), ...props, children: [_jsx("span", { className: "absolute left-2 flex h-3.5 w-3.5 items-center justify-center", children: _jsx(SelectPrimitive.ItemIndicator, { children: _jsx(Check, { className: "h-4 w-4" }) }) }), _jsx(SelectPrimitive.ItemText, { children: children })] })));
23
23
  SelectItem.displayName = SelectPrimitive.Item.displayName;
24
24
  const SelectSeparator = React.forwardRef(({ className, ...props }, ref) => (_jsx(SelectPrimitive.Separator, { ref: ref, className: cn("-mx-1 my-1 h-px bg-muted", className), ...props })));
25
25
  SelectSeparator.displayName = SelectPrimitive.Separator.displayName;
@@ -2,6 +2,6 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import * as React from "react";
3
3
  import { cn } from "../lib/utils.js";
4
4
  export const SourceListItem = React.forwardRef(({ source, isSelected, className, ...props }, ref) => {
5
- return (_jsxs("button", { ref: ref, type: "button", className: cn("flex w-full text-left gap-2 items-start p-3 rounded-lg transition-colors cursor-pointer border border-transparent", "hover:bg-accent-hover hover:border-border/50", isSelected && "bg-accent-hover border-border/50", className), onClick: () => window.open(source.url, "_blank"), ...props, children: [_jsx("div", { className: "flex gap-2 items-center py-[2px] shrink-0", children: _jsx("div", { className: "relative rounded-[3px] shrink-0 size-4 overflow-hidden bg-muted", children: source.favicon ? (_jsx("img", { alt: source.sourceName, className: "size-full object-cover", src: source.favicon })) : (_jsx("div", { className: "size-full bg-muted" })) }) }), _jsxs("div", { className: "flex flex-1 flex-col gap-1 min-w-0", children: [_jsxs("div", { className: "text-xs leading-normal text-foreground", children: [_jsx("span", { className: "font-medium", children: source.sourceName }), _jsxs("span", { className: "text-muted-foreground", children: [" \u00B7 ", source.title] })] }), _jsx("p", { className: "text-xs leading-relaxed text-muted-foreground line-clamp-3", children: source.snippet })] })] }));
5
+ return (_jsxs("button", { ref: ref, type: "button", className: cn("flex w-full text-left gap-2 items-start p-3 rounded-lg transition-colors cursor-pointer border border-transparent", "hover:bg-accent-hover hover:border-border/50", isSelected && "bg-accent-hover border-border/50", className), onClick: () => window.open(source.url, "_blank"), ...props, children: [_jsx("div", { className: "flex gap-2 items-center py-[2px] shrink-0", children: _jsx("div", { className: "relative rounded-[3px] shrink-0 size-4 overflow-hidden bg-muted", children: source.favicon ? (_jsx("img", { alt: source.sourceName, className: "size-full object-cover", src: source.favicon })) : (_jsx("div", { className: "size-full bg-muted" })) }) }), _jsxs("div", { className: "flex flex-1 flex-col gap-1 min-w-0", children: [_jsxs("div", { className: "text-caption leading-normal text-foreground", children: [_jsx("span", { className: "font-medium", children: source.sourceName }), _jsxs("span", { className: "text-muted-foreground", children: [" \u00B7 ", source.title] })] }), _jsx("p", { className: "text-caption leading-relaxed text-muted-foreground line-clamp-3", children: source.snippet })] })] }));
6
6
  });
7
7
  SourceListItem.displayName = "SourceListItem";
@@ -5,7 +5,7 @@ import { cn } from "../lib/utils.js";
5
5
  const Tabs = TabsPrimitive.Root;
6
6
  const TabsList = React.forwardRef(({ className, ...props }, ref) => (_jsx(TabsPrimitive.List, { ref: ref, className: cn("inline-flex h-10 items-center rounded-md bg-muted p-1 text-muted-foreground gap-1", className), ...props })));
7
7
  TabsList.displayName = TabsPrimitive.List.displayName;
8
- const TabsTrigger = React.forwardRef(({ className, ...props }, ref) => (_jsx(TabsPrimitive.Trigger, { ref: ref, className: cn("inline-flex items-center justify-center whitespace-nowrap rounded-sm px-3 py-1.5 text-sm font-medium ring-offset-background transition-all focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 data-[state=active]:bg-background data-[state=active]:text-foreground data-[state=active]:shadow-sm", className), ...props })));
8
+ const TabsTrigger = React.forwardRef(({ className, ...props }, ref) => (_jsx(TabsPrimitive.Trigger, { ref: ref, className: cn("inline-flex items-center justify-center whitespace-nowrap rounded-sm px-3 py-1.5 text-paragraph-sm font-medium ring-offset-background transition-all focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 data-[state=active]:bg-background data-[state=active]:text-foreground data-[state=active]:shadow-sm", className), ...props })));
9
9
  TabsTrigger.displayName = TabsPrimitive.Trigger.displayName;
10
10
  const TabsContent = React.forwardRef(({ className, ...props }, ref) => (_jsx(TabsPrimitive.Content, { ref: ref, className: cn("mt-2 ring-offset-background focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2", className), ...props })));
11
11
  TabsContent.displayName = TabsPrimitive.Content.displayName;
@@ -28,10 +28,10 @@ export const Task = React.forwardRef(({ task, collapsible = true, defaultExpande
28
28
  }
29
29
  onTaskClick?.(task);
30
30
  };
31
- return (_jsxs("div", { ref: ref, className: cn("rounded-lg border border-border bg-card transition-all", "hover:shadow-sm hover:border-border/80", className), ...props, children: [_jsxs("button", { type: "button", onClick: handleClick, className: cn("w-full flex items-center gap-3 px-3 py-2.5 text-left", hasDetails && collapsible && "cursor-pointer"), disabled: !hasDetails && !collapsible, children: [_jsx(StatusIcon, { className: cn("w-4 h-4 shrink-0", getStatusColor(), task.status === "in_progress" && "animate-spin") }), _jsx("span", { className: cn("flex-1 text-sm font-[var(--font-family)]", task.status === "completed" && "line-through opacity-60", task.status === "in_progress" && "font-medium"), children: task.text }), hasDetails && collapsible && (_jsx(ChevronDown, { className: cn("w-4 h-4 text-foreground opacity-50 transition-transform duration-200 shrink-0", isExpanded && "rotate-180"), "aria-hidden": "true" }))] }), hasDetails && isExpanded && (_jsxs("div", { className: "px-3 pb-3 pt-1 border-t border-border/50 animate-fadeIn", children: [task.details && (_jsx("p", { className: "text-sm text-foreground opacity-80 leading-relaxed mb-2", children: task.details })), task.files && task.files.length > 0 && (_jsxs("div", { className: "space-y-1", children: [_jsx("span", { className: "text-xs font-medium text-foreground opacity-60 uppercase tracking-wide", children: "Files:" }), _jsx("div", { className: "space-y-1", children: task.files.map((file) => (_jsx("div", { className: "text-xs font-mono text-foreground opacity-70 bg-background px-2 py-1 rounded border border-border/50", children: file }, file))) })] }))] }))] }));
31
+ return (_jsxs("div", { ref: ref, className: cn("rounded-lg border border-border bg-card transition-all", "hover:shadow-sm hover:border-border/80", className), ...props, children: [_jsxs("button", { type: "button", onClick: handleClick, className: cn("w-full flex items-center gap-3 px-3 py-2.5 text-left", hasDetails && collapsible && "cursor-pointer"), disabled: !hasDetails && !collapsible, children: [_jsx(StatusIcon, { className: cn("w-4 h-4 shrink-0", getStatusColor(), task.status === "in_progress" && "animate-spin") }), _jsx("span", { className: cn("flex-1 text-paragraph-sm font-[var(--font-family)]", task.status === "completed" && "line-through opacity-60", task.status === "in_progress" && "font-medium"), children: task.text }), hasDetails && collapsible && (_jsx(ChevronDown, { className: cn("w-4 h-4 text-foreground opacity-50 transition-transform duration-200 shrink-0", isExpanded && "rotate-180"), "aria-hidden": "true" }))] }), hasDetails && isExpanded && (_jsxs("div", { className: "px-3 pb-3 pt-1 border-t border-border/50 animate-fadeIn", children: [task.details && (_jsx("p", { className: "text-paragraph-sm text-foreground opacity-80 leading-relaxed mb-2", children: task.details })), task.files && task.files.length > 0 && (_jsxs("div", { className: "space-y-1", children: [_jsx("span", { className: "text-caption font-medium text-foreground opacity-60 uppercase tracking-wide", children: "Files:" }), _jsx("div", { className: "space-y-1", children: task.files.map((file) => (_jsx("div", { className: "text-caption font-mono text-foreground opacity-70 bg-background px-2 py-1 rounded border border-border/50", children: file }, file))) })] }))] }))] }));
32
32
  });
33
33
  Task.displayName = "Task";
34
34
  export const TaskList = React.forwardRef(({ tasks, collapsible = true, onTaskClick, emptyMessage = "No tasks yet.", className, ...props }, ref) => {
35
- return (_jsx("div", { ref: ref, className: cn("space-y-2 max-h-96 overflow-y-auto", className), ...props, children: tasks.length === 0 ? (_jsx("p", { className: "text-sm text-foreground opacity-60 italic py-4 text-center", children: emptyMessage })) : (tasks.map((task) => (_jsx(Task, { task: task, collapsible: collapsible, ...(onTaskClick ? { onTaskClick } : {}) }, task.id)))) }));
35
+ return (_jsx("div", { ref: ref, className: cn("space-y-2 max-h-96 overflow-y-auto", className), ...props, children: tasks.length === 0 ? (_jsx("p", { className: "text-paragraph-sm text-foreground opacity-60 italic py-4 text-center", children: emptyMessage })) : (tasks.map((task) => (_jsx(Task, { task: task, collapsible: collapsible, ...(onTaskClick ? { onTaskClick } : {}) }, task.id)))) }));
36
36
  });
37
37
  TaskList.displayName = "TaskList";
@@ -2,7 +2,7 @@ import { jsx as _jsx } from "react/jsx-runtime";
2
2
  import { cva } from "class-variance-authority";
3
3
  import * as React from "react";
4
4
  import { cn } from "../lib/utils.js";
5
- const textareaVariants = cva("flex min-h-[80px] w-full rounded-md border bg-background px-3 py-2 text-sm ring-offset-background placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 resize-none", {
5
+ const textareaVariants = cva("flex min-h-[80px] w-full rounded-md border bg-background px-3 py-2 text-paragraph-sm ring-offset-background placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 resize-none", {
6
6
  variants: {
7
7
  variant: {
8
8
  default: "border-input focus-visible:ring-ring",
@@ -33,8 +33,8 @@ export function ThinkingBlock({ thinking, isStreaming, displayMode = "collapsibl
33
33
  }
34
34
  // Inline mode - always visible
35
35
  if (displayMode === "inline") {
36
- return (_jsxs("div", { className: cn(thinkingBlockVariants({ variant }), className), children: [_jsxs("div", { className: "flex items-start gap-2", children: [_jsx("span", { className: "text-xs font-medium text-foreground opacity-60 uppercase tracking-wide", children: "Thinking" }), isStreaming && (_jsx("span", { className: "inline-block w-2 h-2 bg-primary rounded-full animate-pulse" }))] }), _jsxs("div", { className: "mt-2 text-sm italic text-foreground opacity-80 leading-relaxed whitespace-pre-wrap", children: [thinking, isStreaming && thinking && (_jsx("span", { className: "inline-block animate-typing", children: "..." }))] })] }));
36
+ return (_jsxs("div", { className: cn(thinkingBlockVariants({ variant }), className), children: [_jsxs("div", { className: "flex items-start gap-2", children: [_jsx("span", { className: "text-caption font-medium text-foreground opacity-60 uppercase tracking-wide", children: "Thinking" }), isStreaming && (_jsx("span", { className: "inline-block w-2 h-2 bg-primary rounded-full animate-pulse" }))] }), _jsxs("div", { className: "mt-2 text-paragraph-sm italic text-foreground opacity-80 leading-relaxed whitespace-pre-wrap", children: [thinking, isStreaming && thinking && (_jsx("span", { className: "inline-block animate-typing", children: "..." }))] })] }));
37
37
  }
38
38
  // Collapsible mode
39
- return (_jsxs("div", { className: cn("mb-3", className), children: [_jsxs("button", { type: "button", onClick: () => setIsExpanded(!isExpanded), className: "w-full flex items-center justify-between p-2 rounded-lg bg-card border border-border hover:bg-card transition-colors text-left", children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx("span", { className: "text-xs font-medium text-foreground opacity-60 uppercase tracking-wide", children: "Thinking" }), isStreaming && (_jsx("span", { className: "inline-block w-2 h-2 bg-primary rounded-full animate-pulse" })), !isExpanded && thinking && (_jsxs("span", { className: "text-xs text-foreground opacity-50 truncate max-w-[200px]", children: [thinking.substring(0, 50), "..."] }))] }), _jsx(ChevronDown, { className: thinkingIconVariants({ expanded: isExpanded }) })] }), isExpanded && (_jsx("div", { className: cn(thinkingBlockVariants({ variant }), "mt-2"), children: _jsxs("div", { className: "text-sm italic text-foreground opacity-80 leading-relaxed whitespace-pre-wrap", children: [thinking, isStreaming && thinking && (_jsx("span", { className: "inline-block animate-typing", children: "..." }))] }) }))] }));
39
+ return (_jsxs("div", { className: cn("mb-3", className), children: [_jsxs("button", { type: "button", onClick: () => setIsExpanded(!isExpanded), className: "w-full flex items-center justify-between p-2 rounded-lg bg-card border border-border hover:bg-card transition-colors text-left", children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx("span", { className: "text-caption font-medium text-foreground opacity-60 uppercase tracking-wide", children: "Thinking" }), isStreaming && (_jsx("span", { className: "inline-block w-2 h-2 bg-primary rounded-full animate-pulse" })), !isExpanded && thinking && (_jsxs("span", { className: "text-caption text-foreground opacity-50 truncate max-w-[200px]", children: [thinking.substring(0, 50), "..."] }))] }), _jsx(ChevronDown, { className: thinkingIconVariants({ expanded: isExpanded }) })] }), isExpanded && (_jsx("div", { className: cn(thinkingBlockVariants({ variant }), "mt-2"), children: _jsxs("div", { className: "text-paragraph-sm italic text-foreground opacity-80 leading-relaxed whitespace-pre-wrap", children: [thinking, isStreaming && thinking && (_jsx("span", { className: "inline-block animate-typing", children: "..." }))] }) }))] }));
40
40
  }
@@ -6,6 +6,6 @@ export const TodoList = React.forwardRef(({ client, todos, className, ...props }
6
6
  // For now, just use prop-based todos
7
7
  // Future: Add hook to get todos from store when available
8
8
  const todosToDisplay = todos || [];
9
- return (_jsx("div", { ref: ref, className: cn("space-y-2 max-h-64 overflow-y-auto", className), ...props, children: todosToDisplay.length === 0 ? (_jsx("p", { className: "text-sm text-foreground opacity-60 italic", children: "No tasks yet." })) : (todosToDisplay.map((todo) => (_jsx(TodoListItem, { todo: todo }, todo.id)))) }));
9
+ return (_jsx("div", { ref: ref, className: cn("space-y-2 max-h-64 overflow-y-auto", className), ...props, children: todosToDisplay.length === 0 ? (_jsx("p", { className: "text-paragraph-sm text-foreground opacity-60 italic", children: "No tasks yet." })) : (todosToDisplay.map((todo) => (_jsx(TodoListItem, { todo: todo }, todo.id)))) }));
10
10
  });
11
11
  TodoList.displayName = "TodoList";
@@ -1,16 +1,7 @@
1
- import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import JsonView from "@uiw/react-json-view";
3
- import { Wrench } from "lucide-react";
3
+ import { ChevronDown, Wrench } from "lucide-react";
4
4
  import { useState } from "react";
5
- /**
6
- * Tool call status badge styles
7
- */
8
- const statusStyles = {
9
- pending: "bg-transparent text-muted-foreground",
10
- in_progress: "bg-transparent text-muted-foreground",
11
- completed: "bg-transparent text-muted-foreground",
12
- failed: "bg-transparent text-muted-foreground",
13
- };
14
5
  /**
15
6
  * Tool call kind icons (using emoji for simplicity)
16
7
  */
@@ -31,70 +22,76 @@ const _kindIcons = {
31
22
  */
32
23
  export function ToolCall({ toolCall }) {
33
24
  const [isExpanded, setIsExpanded] = useState(false);
34
- return (_jsxs("div", { className: "flex flex-col", children: [_jsxs("button", { type: "button", className: "flex items-center gap-1.5 cursor-pointer bg-transparent border-none p-0 text-left group w-fit", onClick: () => setIsExpanded(!isExpanded), "aria-expanded": isExpanded, children: [_jsxs("span", { className: `inline-flex items-center gap-1.5 px-2 py-1 text-xs font-medium rounded ${statusStyles[toolCall.status]}`, children: [_jsx(Wrench, { className: "h-3 w-3" }), _jsx("span", { children: toolCall.title }), toolCall.status === "completed" && _jsx("span", { children: "\u2713" })] }), _jsx("span", { className: "text-muted-foreground text-xs opacity-0 group-hover:opacity-100 transition-opacity", children: isExpanded ? "" : "" })] }), isExpanded && (_jsxs("div", { className: "mt-2 space-y-3 text-sm border border-border rounded-md p-3 bg-card shadow-sm max-w-full", children: [toolCall.locations && toolCall.locations.length > 0 && (_jsxs("div", { children: [_jsx("div", { className: "text-xs font-semibold text-muted-foreground uppercase tracking-wide mb-1.5", children: "Files" }), _jsx("ul", { className: "space-y-1", children: toolCall.locations.map((loc) => (_jsxs("li", { className: "font-mono text-xs text-foreground bg-muted px-2 py-1 rounded", children: [loc.path, loc.line !== null &&
25
+ return (_jsxs("div", { className: "flex flex-col my-2", children: [_jsx("button", { type: "button", className: "flex items-center gap-2 cursor-pointer bg-transparent border-none p-0 text-left group w-fit", onClick: () => setIsExpanded(!isExpanded), "aria-expanded": isExpanded, children: _jsxs("div", { className: "flex items-center gap-1.5 text-[11px] font-medium text-zinc-500", children: [_jsx("div", { className: "text-zinc-500", children: _jsx(Wrench, { className: "h-3 w-3" }) }), _jsx("span", { className: "text-paragraph-sm text-zinc-500", children: toolCall.title }), _jsx(ChevronDown, { className: `h-3 w-3 text-zinc-400 transition-transform duration-200 ${isExpanded ? "rotate-180" : ""}` })] }) }), isExpanded && (_jsxs("div", { className: "mt-2 text-sm border border-zinc-200 rounded-lg bg-zinc-50 overflow-hidden w-full", children: [toolCall.locations && toolCall.locations.length > 0 && (_jsxs("div", { className: "p-3 border-b border-zinc-200", children: [_jsx("div", { className: "text-[10px] font-bold text-zinc-400 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-zinc-700 bg-zinc-200/50 px-1.5 py-0.5 rounded w-fit", children: [loc.path, loc.line !== null &&
35
26
  loc.line !== undefined &&
36
- `:${loc.line}`] }, `${loc.path}:${loc.line ?? ""}`))) })] })), toolCall.rawInput && Object.keys(toolCall.rawInput).length > 0 && (_jsxs("div", { children: [_jsx("div", { className: "text-xs font-semibold text-muted-foreground uppercase tracking-wide mb-1.5", children: "Input" }), _jsx("div", { className: "bg-muted p-2 rounded border border-border", children: _jsx(JsonView, { value: toolCall.rawInput, collapsed: false, displayDataTypes: false, displayObjectSize: false, enableClipboard: true, style: { fontSize: "11px", backgroundColor: "transparent" } }) })] })), toolCall.content && toolCall.content.length > 0 && (_jsxs("div", { children: [_jsx("div", { className: "text-xs font-semibold text-muted-foreground uppercase tracking-wide mb-1.5", children: "Output" }), _jsx("div", { className: "space-y-2", children: toolCall.content.map((block, idx) => {
37
- // Generate a stable key based on content
38
- const getBlockKey = () => {
39
- if (block.type === "diff" && "path" in block) {
40
- return `diff-${block.path}-${idx}`;
41
- }
42
- if (block.type === "terminal" && "terminalId" in block) {
43
- return `terminal-${block.terminalId}`;
44
- }
45
- if (block.type === "text" && "text" in block) {
46
- return `text-${block.text.substring(0, 20)}-${idx}`;
47
- }
27
+ `:${loc.line}`] }, `${loc.path}:${loc.line ?? ""}`))) })] })), toolCall.rawInput && Object.keys(toolCall.rawInput).length > 0 && (_jsxs("div", { className: "p-3 border-b border-zinc-200", children: [_jsx("div", { className: "text-[10px] font-bold text-zinc-400 uppercase tracking-wider mb-1.5 font-sans", children: "Input" }), _jsx("div", { className: "text-[11px] font-mono text-zinc-700", children: _jsx(JsonView, { value: toolCall.rawInput, collapsed: false, displayDataTypes: false, displayObjectSize: false, enableClipboard: true, style: {
28
+ fontSize: "11px",
29
+ backgroundColor: "transparent",
30
+ fontFamily: "inherit",
31
+ } }) })] })), (toolCall.content && toolCall.content.length > 0) ||
32
+ toolCall.error ? (_jsxs("div", { className: "p-3 border-b border-zinc-200 last:border-0", children: [_jsx("div", { className: "text-[10px] font-bold text-zinc-400 uppercase tracking-wider mb-1.5 font-sans", children: "Output" }), _jsxs("div", { className: "space-y-2 text-[11px] text-zinc-700", children: [toolCall.content?.map((block, idx) => {
33
+ // Generate a stable key based on content
34
+ const getBlockKey = () => {
35
+ if (block.type === "diff" && "path" in block) {
36
+ return `diff-${block.path}-${idx}`;
37
+ }
38
+ if (block.type === "terminal" && "terminalId" in block) {
39
+ return `terminal-${block.terminalId}`;
40
+ }
41
+ if (block.type === "text" && "text" in block) {
42
+ return `text-${block.text.substring(0, 20)}-${idx}`;
43
+ }
44
+ if (block.type === "content" && "content" in block) {
45
+ const innerContent = block.content;
46
+ return `content-${innerContent.text?.substring(0, 20)}-${idx}`;
47
+ }
48
+ return `block-${idx}`;
49
+ };
50
+ // Helper to render text content (with JSON parsing if applicable)
51
+ const renderTextContent = (text, key) => {
52
+ // Try to parse as JSON
53
+ try {
54
+ const parsed = JSON.parse(text);
55
+ // If it's an object or array, render with JsonView
56
+ if (typeof parsed === "object" && parsed !== null) {
57
+ return (_jsx("div", { className: "text-[11px]", children: _jsx(JsonView, { value: parsed, collapsed: false, displayDataTypes: false, displayObjectSize: false, enableClipboard: true, style: {
58
+ fontSize: "11px",
59
+ backgroundColor: "transparent",
60
+ fontFamily: "inherit",
61
+ } }) }, key));
62
+ }
63
+ }
64
+ catch {
65
+ // Not valid JSON, render as plain text
66
+ }
67
+ // Render as plain text
68
+ return (_jsx("pre", { className: "whitespace-pre-wrap font-mono text-[11px] text-zinc-700 overflow-x-auto", children: text }, key));
69
+ };
70
+ // Handle nested content blocks (ACP format)
48
71
  if (block.type === "content" && "content" in block) {
49
72
  const innerContent = block.content;
50
- return `content-${innerContent.text?.substring(0, 20)}-${idx}`;
51
- }
52
- return `block-${idx}`;
53
- };
54
- // Helper to render text content (with JSON parsing if applicable)
55
- const renderTextContent = (text, key) => {
56
- // Try to parse as JSON
57
- try {
58
- const parsed = JSON.parse(text);
59
- // If it's an object or array, render with JsonView
60
- if (typeof parsed === "object" && parsed !== null) {
61
- return (_jsx("div", { className: "bg-muted p-2 rounded border border-border", children: _jsx(JsonView, { value: parsed, collapsed: false, displayDataTypes: false, displayObjectSize: false, enableClipboard: true, style: {
62
- fontSize: "11px",
63
- backgroundColor: "transparent",
64
- } }) }, key));
73
+ if (innerContent.type === "text" && innerContent.text) {
74
+ return renderTextContent(innerContent.text, getBlockKey());
65
75
  }
66
76
  }
67
- catch {
68
- // Not valid JSON, render as plain text
77
+ // Handle direct text blocks
78
+ if (block.type === "text" && "text" in block) {
79
+ return renderTextContent(block.text, getBlockKey());
80
+ }
81
+ // Handle diff blocks
82
+ if (block.type === "diff" &&
83
+ "path" in block &&
84
+ "oldText" in block &&
85
+ "newText" in block) {
86
+ return (_jsxs("div", { className: "border border-zinc-200 rounded bg-white", children: [_jsxs("div", { className: "bg-zinc-50 px-2 py-1 text-[10px] font-mono text-zinc-500 border-b border-zinc-200", children: [block.path, "line" in block &&
87
+ block.line !== null &&
88
+ block.line !== undefined &&
89
+ `:${block.line}`] }), _jsxs("div", { className: "p-2 font-mono text-[11px]", children: [_jsxs("div", { className: "text-red-600", children: ["- ", block.oldText] }), _jsxs("div", { className: "text-green-600", children: ["+ ", block.newText] })] })] }, getBlockKey()));
69
90
  }
70
- // Render as plain text
71
- return (_jsx("pre", { className: "bg-muted p-2.5 rounded border border-border text-xs overflow-x-auto font-mono text-foreground", children: text }, key));
72
- };
73
- // Handle nested content blocks (ACP format)
74
- if (block.type === "content" && "content" in block) {
75
- const innerContent = block.content;
76
- if (innerContent.type === "text" && innerContent.text) {
77
- return renderTextContent(innerContent.text, getBlockKey());
91
+ // Handle terminal blocks
92
+ if (block.type === "terminal" && "terminalId" in block) {
93
+ return (_jsxs("div", { className: "bg-zinc-900 text-zinc-100 p-2 rounded text-[11px] font-mono", children: ["Terminal: ", block.terminalId] }, getBlockKey()));
78
94
  }
79
- }
80
- // Handle direct text blocks
81
- if (block.type === "text" && "text" in block) {
82
- return renderTextContent(block.text, getBlockKey());
83
- }
84
- // Handle diff blocks
85
- if (block.type === "diff" &&
86
- "path" in block &&
87
- "oldText" in block &&
88
- "newText" in block) {
89
- return (_jsxs("div", { className: "border rounded", children: [_jsxs("div", { className: "bg-muted px-2 py-1 text-xs font-mono", children: [block.path, "line" in block &&
90
- block.line !== null &&
91
- block.line !== undefined &&
92
- `:${block.line}`] }), _jsxs("div", { className: "p-2 font-mono text-xs", children: [_jsxs("div", { className: "text-red-600", children: ["- ", block.oldText] }), _jsxs("div", { className: "text-green-600", children: ["+ ", block.newText] })] })] }, getBlockKey()));
93
- }
94
- // Handle terminal blocks
95
- if (block.type === "terminal" && "terminalId" in block) {
96
- return (_jsxs("div", { className: "bg-black text-green-400 p-2 rounded text-xs font-mono", children: ["Terminal: ", block.terminalId] }, getBlockKey()));
97
- }
98
- return null;
99
- }) })] })), toolCall.error && (_jsxs("div", { className: "bg-destructive/10 border border-destructive/20 rounded p-2.5 text-destructive", children: [_jsx("div", { className: "text-xs font-semibold text-destructive uppercase tracking-wide mb-1.5", children: "Error" }), _jsx("div", { className: "text-xs", children: toolCall.error })] })), toolCall.tokenUsage && (_jsxs("div", { className: "bg-muted border border-border rounded p-2.5", children: [_jsx("div", { className: "text-xs font-semibold text-muted-foreground uppercase tracking-wide mb-2", children: "Token Usage" }), _jsxs("div", { className: "grid grid-cols-3 gap-3 text-xs text-foreground", children: [toolCall.tokenUsage.inputTokens !== undefined && (_jsxs("div", { children: [_jsx("div", { className: "text-muted-foreground text-[10px] uppercase tracking-wide mb-0.5", children: "Input" }), _jsx("div", { className: "font-medium", children: toolCall.tokenUsage.inputTokens.toLocaleString() })] })), toolCall.tokenUsage.outputTokens !== undefined && (_jsxs("div", { children: [_jsx("div", { className: "text-muted-foreground text-[10px] uppercase tracking-wide mb-0.5", children: "Output" }), _jsx("div", { className: "font-medium", children: toolCall.tokenUsage.outputTokens.toLocaleString() })] })), toolCall.tokenUsage.totalTokens !== undefined && (_jsxs("div", { children: [_jsx("div", { className: "text-muted-foreground text-[10px] uppercase tracking-wide mb-0.5", children: "Total" }), _jsx("div", { className: "font-medium", children: toolCall.tokenUsage.totalTokens.toLocaleString() })] }))] })] })), toolCall.startedAt && (_jsxs("div", { className: "text-xs text-muted-foreground", children: ["Started: ", new Date(toolCall.startedAt).toLocaleTimeString(), toolCall.completedAt && (_jsxs(_Fragment, { children: [" ", "| Completed:", " ", new Date(toolCall.completedAt).toLocaleTimeString(), " (", Math.round((toolCall.completedAt - toolCall.startedAt) / 1000), "s)"] }))] }))] }))] }));
95
+ return null;
96
+ }), toolCall.error && (_jsxs("div", { className: "text-red-600 font-mono text-[11px] mt-2", children: ["Error: ", toolCall.error] }))] })] })) : null, (toolCall.tokenUsage || toolCall.startedAt) && (_jsxs("div", { className: "p-2 bg-zinc-100/50 border-t border-zinc-200 flex flex-wrap gap-4 text-[10px] text-zinc-500 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)"] }))] }))] }))] }))] }));
100
97
  }
@@ -15,7 +15,7 @@ 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-sm font-semibold text-gray-700 mb-2", children: "In Progress" }), grouped.in_progress.map((tc) => (_jsx(ToolCall, { toolCall: tc }, tc.id)))] })), grouped.pending.length > 0 && (_jsxs("div", { children: [_jsx("h4", { className: "text-sm font-semibold text-gray-700 mb-2", children: "Pending" }), grouped.pending.map((tc) => (_jsx(ToolCall, { toolCall: tc }, tc.id)))] })), grouped.completed.length > 0 && (_jsxs("div", { children: [_jsx("h4", { className: "text-sm font-semibold text-gray-700 mb-2", children: "Completed" }), grouped.completed.map((tc) => (_jsx(ToolCall, { toolCall: tc }, tc.id)))] })), grouped.failed.length > 0 && (_jsxs("div", { children: [_jsx("h4", { className: "text-sm font-semibold text-gray-700 mb-2", children: "Failed" }), grouped.failed.map((tc) => (_jsx(ToolCall, { toolCall: tc }, tc.id)))] }))] }));
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-zinc-400 uppercase tracking-wider mb-2 pl-1", children: "In Progress" }), grouped.in_progress.map((tc) => (_jsx(ToolCall, { toolCall: tc }, tc.id)))] })), grouped.pending.length > 0 && (_jsxs("div", { children: [_jsx("h4", { className: "text-[10px] font-bold text-zinc-400 uppercase tracking-wider mb-2 pl-1", children: "Pending" }), grouped.pending.map((tc) => (_jsx(ToolCall, { toolCall: tc }, tc.id)))] })), grouped.completed.length > 0 && (_jsxs("div", { children: [_jsx("h4", { className: "text-[10px] font-bold text-zinc-400 uppercase tracking-wider mb-2 pl-1", children: "Completed" }), grouped.completed.map((tc) => (_jsx(ToolCall, { toolCall: tc }, 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(ToolCall, { toolCall: tc }, tc.id)))] }))] }));
19
19
  }
20
20
  // Default: chronological order
21
21
  return (_jsx("div", { className: "space-y-2", children: toolCalls.map((tc) => (_jsx(ToolCall, { toolCall: tc }, tc.id))) }));
@@ -1,4 +1,6 @@
1
1
  export { toast } from "sonner";
2
+ export { MockFileSystemProvider, mockFileSystemData, } from "../data/mockFileSystemData.js";
3
+ export type { FileSystemData, FileSystemItem as FileSystemItemData, FileSystemItemType, FileSystemProvider, } from "../types/filesystem.js";
2
4
  export { Button, type ButtonProps, buttonVariants } from "./Button.js";
3
5
  export { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle, } from "./Card.js";
4
6
  export { ChatEmptyState, type ChatEmptyStateProps } from "./ChatEmptyState.js";
@@ -14,6 +16,8 @@ export { ChatView, type ChatViewProps } from "./ChatView.js";
14
16
  export { Conversation, type ConversationProps } from "./Conversation.js";
15
17
  export { Dialog, DialogClose, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogOverlay, DialogPortal, DialogTitle, DialogTrigger, } from "./Dialog.js";
16
18
  export { DropdownMenu, DropdownMenuCheckboxItem, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuLabel, DropdownMenuPortal, DropdownMenuRadioGroup, DropdownMenuRadioItem, DropdownMenuSeparator, DropdownMenuShortcut, DropdownMenuSub, DropdownMenuSubContent, DropdownMenuSubTrigger, DropdownMenuTrigger, } from "./DropdownMenu.js";
19
+ export { FileSystemItem, type FileSystemItemProps, } from "./FileSystemItem.js";
20
+ export { FileSystemView, type FileSystemViewProps, } from "./FileSystemView.js";
17
21
  export { HeightTransition } from "./HeightTransition.js";
18
22
  export { Input, type InputProps, inputVariants } from "./Input.js";
19
23
  export { Label } from "./Label.js";
@@ -1,5 +1,6 @@
1
1
  // Base UI components
2
2
  export { toast } from "sonner";
3
+ export { MockFileSystemProvider, mockFileSystemData, } from "../data/mockFileSystemData.js";
3
4
  export { Button, buttonVariants } from "./Button.js";
4
5
  export { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle, } from "./Card.js";
5
6
  export { ChatEmptyState } from "./ChatEmptyState.js";
@@ -19,6 +20,9 @@ export { Conversation } from "./Conversation.js";
19
20
  export { Dialog, DialogClose, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogOverlay, DialogPortal, DialogTitle, DialogTrigger, } from "./Dialog.js";
20
21
  // DropdownMenu components
21
22
  export { DropdownMenu, DropdownMenuCheckboxItem, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuLabel, DropdownMenuPortal, DropdownMenuRadioGroup, DropdownMenuRadioItem, DropdownMenuSeparator, DropdownMenuShortcut, DropdownMenuSub, DropdownMenuSubContent, DropdownMenuSubTrigger, DropdownMenuTrigger, } from "./DropdownMenu.js";
23
+ export { FileSystemItem, } from "./FileSystemItem.js";
24
+ // FileSystem components
25
+ export { FileSystemView, } from "./FileSystemView.js";
22
26
  // Utility components
23
27
  export { HeightTransition } from "./HeightTransition.js";
24
28
  export { Input, inputVariants } from "./Input.js";
@@ -0,0 +1,21 @@
1
+ /**
2
+ * Mock filesystem data - stub implementation
3
+ * Replace this with a real FileSystemProvider implementation later
4
+ */
5
+ import type { FileSystemItem, FileSystemProvider } from "../types/filesystem.js";
6
+ /**
7
+ * Stub filesystem data matching the Figma design
8
+ * This data can be easily replaced with real filesystem queries
9
+ */
10
+ export declare const mockFileSystemData: FileSystemItem[];
11
+ /**
12
+ * Mock FileSystemProvider implementation
13
+ * Replace this class with a real implementation that fetches from an actual filesystem
14
+ */
15
+ export declare class MockFileSystemProvider implements FileSystemProvider {
16
+ private data;
17
+ constructor(data?: FileSystemItem[]);
18
+ getRootItems(): Promise<FileSystemItem[]>;
19
+ getItemChildren(itemId: string): Promise<FileSystemItem[]>;
20
+ getItemDetails(itemId: string): Promise<FileSystemItem>;
21
+ }