@iloveagents/foundry-web-ui 0.32.3 → 0.32.4
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/components/assistant-chat.js +4 -4
- package/dist/components/chat-bubble.js +1 -1
- package/dist/components/chat-context.d.ts +3 -1
- package/dist/components/chat-context.js +2 -2
- package/dist/components/chat-empty-state.js +1 -1
- package/dist/components/chat-header.js +1 -1
- package/dist/components/sidebar.js +1 -1
- package/dist/lib/ag-ui-adapter.js +2 -2
- package/dist/workbench/chat-header.js +1 -1
- package/dist/workbench/conversation-history.d.ts +3 -1
- package/dist/workbench/conversation-history.js +61 -18
- package/dist/workbench/running-chats-menu.js +1 -1
- package/dist/workbench/use-workbench-state.js +1 -1
- package/dist/workbench/welcome-intro.js +1 -1
- package/dist/workbench/workbench.js +2 -1
- package/package.json +3 -3
|
@@ -115,7 +115,7 @@ const DropZone = ({ children, centered, }) => {
|
|
|
115
115
|
: `Couldn't attach ${rejected.length} files (${rejected.join("; ")})`);
|
|
116
116
|
}
|
|
117
117
|
}, [aui, showDropError]);
|
|
118
|
-
return (_jsxs("div", { className: cn("relative flex flex-col flex-1", centered ? "
|
|
118
|
+
return (_jsxs("div", { className: cn("relative flex flex-col flex-1", centered ? "overflow-y-auto" : "overflow-hidden"), onDragEnter: handleDragEnter, onDragLeave: handleDragLeave, onDragOver: handleDragOver, onDrop: handleDrop, children: [children, isDragging && (_jsx("div", { className: cn("absolute inset-0 z-50 flex items-center justify-center pointer-events-none", "bg-background/80 backdrop-blur-sm", "border-2 border-dashed border-primary rounded-xl"), children: _jsx("p", { className: "text-lg text-primary font-medium", children: "Drop files here" }) })), dropError && (_jsx("div", { role: "alert", className: cn("absolute bottom-4 left-1/2 -translate-x-1/2 z-50 max-w-[90%]", "rounded-md border border-destructive/50 bg-background px-3 py-2", "text-sm text-destructive shadow-md pointer-events-none truncate"), children: dropError }))] }));
|
|
119
119
|
};
|
|
120
120
|
/**
|
|
121
121
|
* "Message Assistant..." named the machine and told the user nothing. The
|
|
@@ -142,11 +142,11 @@ export function ChatContent({ centerComposer = false, composerIntro, composerFoo
|
|
|
142
142
|
UserMessage,
|
|
143
143
|
EditComposer,
|
|
144
144
|
AssistantMessage,
|
|
145
|
-
} }), _jsx(ThreadPrimitive.If, { running: true, children: _jsx(LoadingIndicator, {}) })] }) })] }), !ThreadSurface && (_jsx(ThreadPrimitive.If, { empty: false, children: _jsx(ScrollToBottomButton, {}) }))] }), _jsxs("div", { className: "shrink-0 bg-background", hidden: hideComposer, children: [composerIntro && !ThreadSurface && (_jsx("div", { className: "mx-auto max-w-3xl px-4 pt-4", children: composerIntro })), _jsx(ChatComposerBannerSlot, {}), _jsx(ThreadPrimitive.If, { running: false, children: _jsx("div", { "data-chat-composer-divider": true, className: "border-t border-border" }) }), _jsx(ThreadPrimitive.If, { running: true, children: _jsx(LoadingBar, {}) }), _jsxs("div", { className: "mx-auto max-w-3xl px-4 py-4", children: [_jsx(ChatContext, {}), _jsxs(ComposerPrimitive.Root, { style: compactComposer ? { borderRadius: 16 } : undefined, className: cn(
|
|
145
|
+
} }), _jsx(ThreadPrimitive.If, { running: true, children: _jsx(LoadingIndicator, {}) })] }) })] }), !ThreadSurface && (_jsx(ThreadPrimitive.If, { empty: false, children: _jsx(ScrollToBottomButton, {}) }))] }), _jsxs("div", { className: cn("shrink-0 bg-background", centerComposer && !ThreadSurface && "my-auto"), hidden: hideComposer, children: [composerIntro && !ThreadSurface && (_jsx("div", { className: "mx-auto max-w-3xl px-4 pt-4", children: composerIntro })), _jsx(ChatComposerBannerSlot, {}), _jsx(ThreadPrimitive.If, { running: false, children: _jsx("div", { "data-chat-composer-divider": true, className: "border-t border-border" }) }), _jsx(ThreadPrimitive.If, { running: true, children: _jsx(LoadingBar, {}) }), _jsxs("div", { className: "mx-auto max-w-3xl px-4 py-4", children: [_jsx(ChatContext, { centered: centerComposer && !ThreadSurface }), _jsxs(ComposerPrimitive.Root, { style: compactComposer ? { borderRadius: 16 } : undefined, className: cn(
|
|
146
146
|
// Query container for the controls inside, so they size
|
|
147
147
|
// against the composer rather than the viewport. This one
|
|
148
148
|
// is wide, so the effort picker keeps its full label.
|
|
149
|
-
"@container", "flex flex-col gap-2", "rounded-3xl border border-input", "bg-background shadow-sm", "px-4 py-2", "focus-within:border-primary/50 focus-within:shadow-md", "transition-all duration-300"), children: [_jsx(ComposerSubmitBridge, {}), _jsx(ComposerPrimitive.Attachments, { components: composerAttachmentComponents }), _jsxs("div", { className: cn("flex items-center gap-2", compactComposer ? "flex-wrap" : "flex-wrap @md:flex-nowrap"), children: [_jsx("div", { className: cn("flex shrink-0 items-center gap-1", compactComposer ? "order-2" : "order-2 @md:order-1"), children: _jsx(ComposerAddMenu, {}) }), _jsx(ComposerInput, { autoFocus: true, placeholder: placeholder, rows: 1, className: cn("bg-transparent", compactComposer
|
|
149
|
+
"@container", "flex flex-col gap-2", "rounded-3xl border border-input", "bg-background shadow-sm", "px-4 py-2", "focus-within:border-primary/50 focus-within:shadow-md", centerComposer && "shadow-md", "transition-all duration-300"), children: [_jsx(ComposerSubmitBridge, {}), _jsx(ComposerPrimitive.Attachments, { components: composerAttachmentComponents }), _jsxs("div", { className: cn("flex items-center gap-2", compactComposer ? "flex-wrap" : "flex-wrap @md:flex-nowrap"), children: [_jsx("div", { className: cn("flex shrink-0 items-center gap-1", compactComposer ? "order-2" : "order-2 @md:order-1"), children: _jsx(ComposerAddMenu, {}) }), _jsx(ComposerInput, { autoFocus: true, placeholder: placeholder, rows: 1, className: cn("bg-transparent", compactComposer
|
|
150
150
|
? "order-1 w-full"
|
|
151
|
-
: "order-1 w-full @md:order-2 @md:w-auto @md:flex-1", "py-2 text-base sm:text-sm leading-relaxed", "text-foreground outline-none", "placeholder:text-muted-foreground", "resize-none max-h-32") }), _jsx("div", { className: cn("order-3 ml-auto flex shrink-0 items-center gap-2", !compactComposer && "@md:ml-0"), children: _jsx(ComposerActionButton, {}) })] })] }), composerFooter] })] })] })] }));
|
|
151
|
+
: "order-1 w-full @md:order-2 @md:w-auto @md:flex-1", "py-2 text-base sm:text-sm leading-relaxed", "text-foreground outline-none", "placeholder:text-muted-foreground", "resize-none max-h-32") }), _jsx("div", { className: cn("order-3 ml-auto flex shrink-0 items-center gap-2", !compactComposer && "@md:ml-0"), children: _jsx(ComposerActionButton, {}) })] })] }), !ThreadSurface && composerFooter] })] })] })] }));
|
|
152
152
|
}
|
|
@@ -106,7 +106,7 @@ export function ChatBubble() {
|
|
|
106
106
|
height: 64,
|
|
107
107
|
} })), !isOpen && (_jsxs("div", { className: "fixed z-50 group", style: { left: CHAT_BUBBLE_INSET, bottom: CHAT_BUBBLE_INSET }, children: [_jsx("button", { type: "button", onClick: openBubble, className: cn("size-10 rounded-full", "bg-primary text-primary-foreground shadow-lg", "flex items-center justify-center", "hover:bg-primary/90 transition-all duration-200", "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring"), "aria-label": "Ask the AI", children: _jsx(Sparkles, { className: "size-4" }) }), _jsx(ChatLauncherBadgeSlot, {})] })), isOpen && (_jsxs("div", { ref: panelRef, "data-chat-surface": "bubble", className: cn("fixed z-50", "rounded-2xl border border-border", "bg-background shadow-2xl", "flex flex-col overflow-hidden", "w-95 h-150"), style: dragPos
|
|
108
108
|
? { left: dragPos.x, top: dragPos.y }
|
|
109
|
-
: { left: CHAT_BUBBLE_INSET, bottom: CHAT_BUBBLE_INSET }, children: [_jsxs("div", { className: cn("flex items-center justify-between px-4 py-2.5 border-b border-border shrink-0", "cursor-grab active:cursor-grabbing select-none"), style: { touchAction: "none" }, onPointerDown: onHeaderPointerDown, onPointerMove: onHeaderPointerMove, onPointerUp: onHeaderPointerUp, onLostPointerCapture: onHeaderLostPointerCapture, children: [_jsxs("div", { className: "flex flex-col min-w-0", children: [_jsxs("div", { className: "flex items-center gap-1.5 text-sm", children: [_jsx(Sparkles, { className: "size-3.5 text-primary shrink-0" }), _jsx("span", { className: "font-semibold text-foreground truncate", children: pageLabel })] }), _jsx("span", { className: "text-xs text-muted-foreground", children: threadActive ? "Active
|
|
109
|
+
: { left: CHAT_BUBBLE_INSET, bottom: CHAT_BUBBLE_INSET }, children: [_jsxs("div", { className: cn("flex items-center justify-between px-4 py-2.5 border-b border-border shrink-0", "cursor-grab active:cursor-grabbing select-none"), style: { touchAction: "none" }, onPointerDown: onHeaderPointerDown, onPointerMove: onHeaderPointerMove, onPointerUp: onHeaderPointerUp, onLostPointerCapture: onHeaderLostPointerCapture, children: [_jsxs("div", { className: "flex flex-col min-w-0", children: [_jsxs("div", { className: "flex items-center gap-1.5 text-sm", children: [_jsx(Sparkles, { className: "size-3.5 text-primary shrink-0" }), _jsx("span", { className: "font-semibold text-foreground truncate", children: pageLabel })] }), _jsx("span", { className: "text-xs text-muted-foreground", children: threadActive ? "Active chat" : "New chat" })] }), _jsxs("div", { className: "flex items-center gap-0.5", children: [_jsx(TooltipIconButton, { tooltip: "New chat", size: "icon", className: "size-7", onClick: startNewThread, children: _jsx(SquarePen, { className: "size-3.5" }) }), _jsx(TooltipIconButton, { tooltip: "Expand chat", size: "icon", className: "size-7", onClick: expandChat, children: _jsx(Maximize2, { className: "size-3.5" }) }), _jsx(TooltipIconButton, { tooltip: "Close", size: "icon", className: "size-7", onClick: handleClose, children: _jsx(X, { className: "size-4" }) })] })] }), _jsxs(ThreadPrimitive.Root, { className: "flex flex-col flex-1 overflow-hidden", children: [_jsxs("div", { className: "relative flex-1 overflow-hidden", children: [ThreadSurface && (_jsx("div", { className: "absolute inset-0 z-10 overflow-hidden bg-background", children: _jsx(ThreadSurface, {}) })), _jsxs(ThreadPrimitive.Viewport, { className: cn("absolute inset-0 overflow-y-auto", ThreadSurface && "invisible"), "aria-hidden": ThreadSurface ? true : undefined, children: [_jsx(ThreadPrimitive.Empty, { children: _jsxs("div", { className: "flex min-h-full flex-col items-center justify-center gap-4 p-4", children: [_jsx("p", { className: "text-sm text-muted-foreground text-center", children: "Ask the agent about this page" }), _jsx(ChatHomeStartersSlot, {})] }) }), _jsx(ThreadPrimitive.If, { empty: false, children: _jsxs("div", { className: "px-4 pt-4 pb-3", children: [_jsx(ThreadPrimitive.Messages, { components: {
|
|
110
110
|
UserMessage: BubbleUserMessage,
|
|
111
111
|
AssistantMessage: BubbleAssistantMessage,
|
|
112
112
|
} }), _jsx(ThreadPrimitive.If, { running: true, children: _jsx(LoadingIndicator, {}) })] }) })] }), _jsx(ThreadPrimitive.If, { empty: false, children: !ThreadSurface && _jsx(BubbleScrollToBottomButton, {}) })] }), _jsxs("div", { className: "shrink-0 border-t border-border", hidden: hideComposer, children: [_jsx(ChatComposerBannerSlot, {}), _jsxs("div", { className: "px-3 py-3", children: [_jsx(ChatContext, {}), _jsx(ComposerPrimitive.Root, { className: cn(
|
|
@@ -1,2 +1,4 @@
|
|
|
1
1
|
/** The displayed context and the agent request use the same projection. */
|
|
2
|
-
export declare function ChatContext(
|
|
2
|
+
export declare function ChatContext({ centered }: {
|
|
3
|
+
centered?: boolean;
|
|
4
|
+
}): import("react/jsx-runtime").JSX.Element;
|
|
@@ -12,7 +12,7 @@ function readContext() {
|
|
|
12
12
|
return summarizeChatContext(useAppStore.getState().getAgentState());
|
|
13
13
|
}
|
|
14
14
|
/** The displayed context and the agent request use the same projection. */
|
|
15
|
-
export function ChatContext() {
|
|
15
|
+
export function ChatContext({ centered = false }) {
|
|
16
16
|
const [open, setOpen] = useState(false);
|
|
17
17
|
const [context, setContext] = useState(readContext);
|
|
18
18
|
const items = useAppStore((s) => s.contextItems);
|
|
@@ -74,7 +74,7 @@ export function ChatContext() {
|
|
|
74
74
|
};
|
|
75
75
|
}, []);
|
|
76
76
|
const Icon = context.field ? TextCursorInput : context.focused ? Maximize2 : FileText;
|
|
77
|
-
return (_jsxs(Popover, { open: open, onOpenChange: setOpen, children: [_jsx(PopoverTrigger, { asChild: true, children: _jsxs("button", { type: "button", "data-chat-context": true, "aria-label": `Message context: ${context.label}${detail ? `, ${detail}` : ""}${additionalCount ? `, ${additionalCount} more` : ""}`, className:
|
|
77
|
+
return (_jsxs(Popover, { open: open, onOpenChange: setOpen, children: [_jsx(PopoverTrigger, { asChild: true, children: _jsxs("button", { type: "button", "data-chat-context": true, "aria-label": `Message context: ${context.label}${detail ? `, ${detail}` : ""}${additionalCount ? `, ${additionalCount} more` : ""}`, className: `mb-2 flex min-h-9 min-w-0 items-center gap-2 rounded-lg px-2 py-1.5 text-left text-xs text-muted-foreground hover:bg-muted hover:text-foreground focus-visible:outline-2 focus-visible:outline-primary [@media(pointer:coarse)]:min-h-11 ${centered ? "mx-auto w-fit max-w-full" : "w-full"}`, children: [_jsx(Icon, { className: "size-3.5 shrink-0" }), _jsxs("span", { className: "min-w-0 flex-1 truncate", "aria-live": "polite", children: ["With ", _jsx("span", { className: "font-medium text-foreground", children: context.label }), detail && (_jsxs(_Fragment, { children: [" ", _jsx("span", { "aria-hidden": true, children: "\u203A" }), " ", _jsx("span", { className: "font-medium text-foreground", children: detail })] }))] }), additionalCount > 0 && (_jsxs("span", { className: "shrink-0 tabular-nums", "aria-hidden": true, children: ["+", additionalCount] })), _jsx(ChevronDown, { className: "size-3.5 shrink-0" })] }) }), _jsxs(PopoverContent, { align: centered ? "center" : "start", side: "top", collisionPadding: 12, "aria-label": "Context and actions", className: "w-[22rem] max-w-[calc(100vw-1.5rem)] max-h-[min(36rem,var(--radix-popover-content-available-height))] overflow-y-auto overscroll-contain space-y-3 p-3 text-sm", children: [_jsxs("div", { className: "px-2", children: [_jsx("h2", { className: "text-xs font-medium text-muted-foreground", children: "Current context" }), _jsxs("p", { className: "mt-1 break-words font-medium", children: [context.label, detail && ` › ${detail}`] })] }), _jsx("p", { className: "px-2 text-xs leading-relaxed text-muted-foreground", children: detail
|
|
78
78
|
? "This selection stays available when you move into chat."
|
|
79
79
|
: "The current page follows your navigation. Select text or a field to work more specifically." }), context.selectedText && (_jsx("blockquote", { className: "max-h-32 overflow-y-auto border-l-2 border-border pl-3 text-xs", children: context.selectedText })), !context.focused && context.label !== "Your spaces" && (_jsxs("button", { type: "button", "aria-pressed": isPinned, onClick: toggle, className: "flex min-h-9 w-full items-center gap-2 rounded-lg px-2 text-left text-sm hover:bg-muted", children: [_jsx(PinStateIcon, { pinned: isPinned, className: "size-4 shrink-0 text-muted-foreground" }), isPinned ? "Unpin this page" : "Keep this page in context"] })), _jsx(ChatContextItems, { items: items, onNavigate: () => setOpen(false) }), _jsx(ChatContextDetailsSlot, { onDismiss: () => setOpen(false) }), context.references.length > 0 && (_jsxs("div", { className: "border-t border-border px-2 pt-3 text-xs", children: [_jsx("h3", { className: "font-medium", children: "Also open" }), _jsx("ul", { className: "mt-1 space-y-1 text-muted-foreground", children: context.references.map((label, index) => (_jsx("li", { className: "truncate", children: label }, `${label}-${index}`))) })] }))] })] }));
|
|
80
80
|
}
|
|
@@ -2,5 +2,5 @@ import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-run
|
|
|
2
2
|
import { ChatHomeStartersSlot } from "./chat-slots.js";
|
|
3
3
|
/** One compact conversation home for workbench, focus and embedded chat panes. */
|
|
4
4
|
export function ChatEmptyState({ pageLabel, children, showHomeStarters = true, homeStarterPriority = 0, }) {
|
|
5
|
-
return (_jsxs("div", { "data-chat-empty-state": true, className: "flex min-h-full flex-col justify-start gap-3 px-4 pb-8 pt-3", children: [_jsx("h1", { className: "text-base leading-6 font-semibold", children: "What would you like to get done?" }), _jsx("p", { className: "max-w-sm text-sm leading-relaxed text-muted-foreground", children: pageLabel && !pageLabel.startsWith("/") ? (_jsxs(_Fragment, { children: ["Work with ", _jsx("span", { className: "font-medium text-foreground", children: pageLabel }), " or across your spaces: find information, create or edit content, and run actions."] })) : ("Find information, create or edit content, and run actions across your spaces.") }), _jsx("p", { className: "max-w-sm text-xs leading-relaxed text-muted-foreground", children: "Your
|
|
5
|
+
return (_jsxs("div", { "data-chat-empty-state": true, className: "flex min-h-full flex-col justify-start gap-3 px-4 pb-8 pt-3", children: [_jsx("h1", { className: "text-base leading-6 font-semibold", children: "What would you like to get done?" }), _jsx("p", { className: "max-w-sm text-sm leading-relaxed text-muted-foreground", children: pageLabel && !pageLabel.startsWith("/") ? (_jsxs(_Fragment, { children: ["Work with ", _jsx("span", { className: "font-medium text-foreground", children: pageLabel }), " or across your spaces: find information, create or edit content, and run actions."] })) : ("Find information, create or edit content, and run actions across your spaces.") }), _jsx("p", { className: "max-w-sm text-xs leading-relaxed text-muted-foreground", children: "Your chat continues as you browse. Select text or a field to work more specifically." }), showHomeStarters && _jsx(ChatHomeStartersSlot, { priority: homeStarterPriority }), children] }));
|
|
6
6
|
}
|
|
@@ -20,5 +20,5 @@ export const ChatHeader = () => {
|
|
|
20
20
|
const handleNewConversation = useNewConversation(isExpanded ? { navigateToChat: false, preserveNavigation: true } : undefined);
|
|
21
21
|
const toggleMobile = useSidebarStore((s) => s.toggleMobile);
|
|
22
22
|
const isSidebarOpen = useSidebarStore((s) => s.isOpen);
|
|
23
|
-
return (_jsx("div", { className: cn("shrink-0", "bg-background border-b border-border"), children: _jsxs("div", { className: "px-4 py-3 flex items-center justify-between", children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx(TooltipIconButton, { tooltip: "Open sidebar", onClick: toggleMobile, className: "md:hidden", children: _jsx(Menu, { className: "size-5" }) }), _jsx(Link, { to: "/", className: cn("flex items-center gap-2.5 hover:opacity-80 transition-opacity", isSidebarOpen && "md:hidden"), children: _jsx(AppBrand, { labelClassName: "text-sm font-semibold text-foreground" }) })] }), _jsxs("div", { className: "flex items-center gap-1", children: [_jsx(RunningChatsMenu, {}), _jsx(ThemeToggle, {}), _jsx(TooltipIconButton, { tooltip: "New
|
|
23
|
+
return (_jsx("div", { className: cn("shrink-0", "bg-background border-b border-border"), children: _jsxs("div", { className: "px-4 py-3 flex items-center justify-between", children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx(TooltipIconButton, { tooltip: "Open sidebar", onClick: toggleMobile, className: "md:hidden", children: _jsx(Menu, { className: "size-5" }) }), _jsx(Link, { to: "/", className: cn("flex items-center gap-2.5 hover:opacity-80 transition-opacity", isSidebarOpen && "md:hidden"), children: _jsx(AppBrand, { labelClassName: "text-sm font-semibold text-foreground" }) })] }), _jsxs("div", { className: "flex items-center gap-1", children: [_jsx(RunningChatsMenu, {}), _jsx(ThemeToggle, {}), _jsx(TooltipIconButton, { tooltip: "New chat", size: "icon", onClick: handleNewConversation, children: _jsx(SquarePen, { className: "size-4 text-primary" }) }), _jsx(UserMenu, {})] })] }) }));
|
|
24
24
|
};
|
|
@@ -1008,7 +1008,7 @@ function CreateActionsMenu({ group }) {
|
|
|
1008
1008
|
action.handler();
|
|
1009
1009
|
}, children: action.label }, action.id))) })] }));
|
|
1010
1010
|
}
|
|
1011
|
-
function SidebarContent({ collapsed, groups, onNewConversation, hideFooterActions, hideNewConversation, collapsedGroupsOnly, newConversationAfterGroup, newConversationLabel = "New
|
|
1011
|
+
function SidebarContent({ collapsed, groups, onNewConversation, hideFooterActions, hideNewConversation, collapsedGroupsOnly, newConversationAfterGroup, newConversationLabel = "New chat", }) {
|
|
1012
1012
|
const toggle = useSidebarStore((s) => s.toggle);
|
|
1013
1013
|
const defaultNewConversation = useNewConversation();
|
|
1014
1014
|
const handleNewConversation = onNewConversation ?? defaultNewConversation;
|
|
@@ -39,7 +39,7 @@ export class AGUIAdapterSDK {
|
|
|
39
39
|
}
|
|
40
40
|
async *run({ messages, abortSignal }) {
|
|
41
41
|
if (useChatRuns.getState().deletedThreads[this.threadId]) {
|
|
42
|
-
throw new Error("This
|
|
42
|
+
throw new Error("This chat was deleted. Start a new chat to continue.");
|
|
43
43
|
}
|
|
44
44
|
const aguiMessages = convertMessagesToAGUI(messages);
|
|
45
45
|
// App-level lifecycle: mark thread active, snapshot context, consume
|
|
@@ -78,7 +78,7 @@ export class AGUIAdapterSDK {
|
|
|
78
78
|
.filter((p) => p.type === "text")
|
|
79
79
|
.map((p) => p.text)
|
|
80
80
|
.join(" ")
|
|
81
|
-
.slice(0, 120) || "
|
|
81
|
+
.slice(0, 120) || "Chat",
|
|
82
82
|
pageLabel: useAppStore.getState().navContext.label ?? undefined,
|
|
83
83
|
contextMeta: { ...useAppStore.getState().navContext.meta },
|
|
84
84
|
stop: () => stopController.abort(),
|
|
@@ -3,7 +3,7 @@ import { TooltipIconButton } from "../index.js";
|
|
|
3
3
|
import { SquarePen, PanelLeft, MessageSquare, Menu, MessagesSquare, LoaderCircle, } from "lucide-react";
|
|
4
4
|
import { RunningChatsMenu } from "./running-chats-menu.js";
|
|
5
5
|
export function WorkbenchChatHeader({ collapsed, running, chatWidth, buttonClass, toggleNavigation, setCollapsed, showHistory, startChat, returnToChat, openHistory, chatOnly, setContentCollapsed, }) {
|
|
6
|
-
return (_jsxs(_Fragment, { children: [_jsxs("div", { "data-chat-header": true, className: `relative flex shrink-0 items-center ${collapsed ? "justify-center" : "gap-1 px-2"}`, children: [!collapsed && !chatWidth.compact && (_jsx(TooltipIconButton, { tooltip: "Open navigation", className: `${buttonClass} preview-mobile-navigation`, "aria-label": "Open navigation", onClick: toggleNavigation, children: _jsx(Menu, { size: 18 }) })), collapsed ? (_jsx(TooltipIconButton, { tooltip: running ? "AI is working — expand chat" : "Expand chat", className: buttonClass, "aria-label": running ? "AI is working — expand chat" : "Expand chat", onClick: () => setCollapsed(false), children: running ? (_jsx(LoaderCircle, { size: 18, className: "animate-spin motion-reduce:animate-none text-primary" })) : (_jsx(MessageSquare, { size: 18 })) })) : (_jsxs(_Fragment, { children: [_jsx("div", { className: "min-w-0 flex-1 px-2 py-2", children: _jsx("div", { className: "text-sm font-semibold", children: showHistory ? "
|
|
6
|
+
return (_jsxs(_Fragment, { children: [_jsxs("div", { "data-chat-header": true, className: `relative flex shrink-0 items-center ${collapsed ? "justify-center" : "gap-1 px-2"}`, children: [!collapsed && !chatWidth.compact && (_jsx(TooltipIconButton, { tooltip: "Open navigation", className: `${buttonClass} preview-mobile-navigation`, "aria-label": "Open navigation", onClick: toggleNavigation, children: _jsx(Menu, { size: 18 }) })), collapsed ? (_jsx(TooltipIconButton, { tooltip: running ? "AI is working — expand chat" : "Expand chat", className: buttonClass, "aria-label": running ? "AI is working — expand chat" : "Expand chat", onClick: () => setCollapsed(false), children: running ? (_jsx(LoaderCircle, { size: 18, className: "animate-spin motion-reduce:animate-none text-primary" })) : (_jsx(MessageSquare, { size: 18 })) })) : (_jsxs(_Fragment, { children: [_jsx("div", { className: "min-w-0 flex-1 px-2 py-2", children: _jsx("div", { className: "text-sm font-semibold", children: showHistory ? "Chats" : "Chat" }) }), _jsx(RunningChatsMenu, { onOpen: returnToChat }), _jsx(TooltipIconButton, { tooltip: "New chat", className: buttonClass, "aria-label": "New chat", onClick: startChat, children: _jsx(SquarePen, { size: 18 }) }), _jsx(TooltipIconButton, { tooltip: "Chat history", className: buttonClass, "aria-label": "Chat history", "aria-expanded": showHistory, onClick: () => (showHistory ? returnToChat() : openHistory()), children: _jsx(MessagesSquare, { size: 18 }) }), _jsx(TooltipIconButton, { tooltip: "Collapse chat", style: chatOnly || chatWidth.compact ? { display: "none" } : undefined, className: buttonClass, "aria-label": "Collapse chat", onClick: () => {
|
|
7
7
|
setContentCollapsed(false);
|
|
8
8
|
setCollapsed(true);
|
|
9
9
|
}, children: _jsx(PanelLeft, { size: 18 }) })] }))] }), collapsed && (_jsxs("div", { "data-chat-rail": true, className: "flex flex-col items-center gap-1", children: [_jsx(TooltipIconButton, { tooltip: "Open navigation", className: `${buttonClass} preview-mobile-navigation`, "aria-label": "Open navigation", onClick: toggleNavigation, children: _jsx(Menu, { size: 18 }) }), _jsx(TooltipIconButton, { tooltip: "Chat history", className: buttonClass, "aria-label": "Chat history", onClick: () => {
|
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
import type { NavGroup } from "../lib/nav-config.js";
|
|
2
2
|
/** History is a view of existing navigation targets, never a second chat runtime. */
|
|
3
|
-
export declare function ConversationHistory({ groups, workspaceId, onClose, showBack, welcome, compact, onViewAll, entityId, rootContext, }: {
|
|
3
|
+
export declare function ConversationHistory({ groups, workspaceId, onClose, showBack, welcome, compact, home, onViewAll, entityId, rootContext, }: {
|
|
4
4
|
groups: NavGroup[];
|
|
5
5
|
workspaceId: unknown;
|
|
6
6
|
onClose: () => void;
|
|
7
7
|
showBack?: boolean;
|
|
8
8
|
welcome?: boolean;
|
|
9
9
|
compact?: boolean;
|
|
10
|
+
/** The global start page shows the three newest chats below the composer. */
|
|
11
|
+
home?: boolean;
|
|
10
12
|
onViewAll?: () => void;
|
|
11
13
|
/** Current content entity. Compact homes show only an exact match unless this is the workspace root. */
|
|
12
14
|
entityId?: unknown;
|
|
@@ -6,7 +6,7 @@ import { Link } from "react-router";
|
|
|
6
6
|
import { ArrowLeft, MessageSquare, MoreHorizontal, Pin, Loader2, ChevronDown, Check, MessagesSquare, PauseCircle, Copy, } from "lucide-react";
|
|
7
7
|
import { useChatRuns, isChatRunActive } from "../lib/chat-runs-store.js";
|
|
8
8
|
/** History is a view of existing navigation targets, never a second chat runtime. */
|
|
9
|
-
export function ConversationHistory({ groups, workspaceId, onClose, showBack = true, welcome = false, compact = false, onViewAll, entityId, rootContext = false, }) {
|
|
9
|
+
export function ConversationHistory({ groups, workspaceId, onClose, showBack = true, welcome = false, compact = false, home = false, onViewAll, entityId, rootContext = false, }) {
|
|
10
10
|
const [loadingTo, setLoadingTo] = useState(null);
|
|
11
11
|
const [copiedId, setCopiedId] = useState(null);
|
|
12
12
|
const [loadError, setLoadError] = useState(null);
|
|
@@ -18,6 +18,8 @@ export function ConversationHistory({ groups, workspaceId, onClose, showBack = t
|
|
|
18
18
|
groups
|
|
19
19
|
.filter((g) => g.meta?.type === "recent-chats" || g.meta?.type === "pinned-chats")
|
|
20
20
|
.flatMap((g) => g.items);
|
|
21
|
+
const savedTargets = new Set(allItems.map((item) => item.to));
|
|
22
|
+
const hasServerTimestamps = allItems.some((item) => typeof item.meta?.updatedAt === "string");
|
|
21
23
|
const runs = useChatRuns((s) => s.runs);
|
|
22
24
|
const runFor = (item) => Object.values(runs).find((run) => (run.conversationUrl ?? `/chat/${encodeURIComponent(run.threadId)}`) === item.to);
|
|
23
25
|
const workspaceItems = all || !workspaceId
|
|
@@ -57,8 +59,26 @@ export function ConversationHistory({ groups, workspaceId, onClose, showBack = t
|
|
|
57
59
|
const run = runFor(item);
|
|
58
60
|
return run && isChatRunActive(run) ? 1 : 0;
|
|
59
61
|
};
|
|
62
|
+
if (home) {
|
|
63
|
+
// The server list can lag a just-finished run. Compare its session
|
|
64
|
+
// timestamp with server timestamps so newer chats from other tabs
|
|
65
|
+
// take priority as soon as navigation refreshes.
|
|
66
|
+
const activityAt = (item) => {
|
|
67
|
+
const updatedAt = item.meta?.updatedAt;
|
|
68
|
+
const serverAt = typeof updatedAt === "string" ? Date.parse(updatedAt) || 0 : 0;
|
|
69
|
+
const run = runFor(item);
|
|
70
|
+
const sessionAt = run && (hasServerTimestamps || !savedTargets.has(item.to))
|
|
71
|
+
? (run.finishedAt ?? run.startedAt)
|
|
72
|
+
: 0;
|
|
73
|
+
return Math.max(serverAt, sessionAt);
|
|
74
|
+
};
|
|
75
|
+
return active(b) - active(a) || activityAt(b) - activityAt(a);
|
|
76
|
+
}
|
|
60
77
|
return (active(b) - active(a) || Number(Boolean(b.meta?.pinned)) - Number(Boolean(a.meta?.pinned)));
|
|
61
78
|
});
|
|
79
|
+
const homeRecentItems = home ? items.filter((item) => !item.meta?.pinned).slice(0, 3) : [];
|
|
80
|
+
const homePinnedItems = home ? items.filter((item) => item.meta?.pinned).slice(0, 3) : [];
|
|
81
|
+
const homeHasItems = homeRecentItems.length > 0 || homePinnedItems.length > 0;
|
|
62
82
|
const visibleItems = compact ? items.slice(0, 3) : items;
|
|
63
83
|
const activeItems = visibleItems.filter((item) => {
|
|
64
84
|
const run = runFor(item);
|
|
@@ -66,22 +86,43 @@ export function ConversationHistory({ groups, workspaceId, onClose, showBack = t
|
|
|
66
86
|
});
|
|
67
87
|
const idleItems = visibleItems.filter((item) => !activeItems.includes(item));
|
|
68
88
|
const pinnedItems = idleItems.filter((item) => item.meta?.pinned);
|
|
69
|
-
const sections =
|
|
70
|
-
? [
|
|
71
|
-
|
|
72
|
-
{ label: "
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
89
|
+
const sections = home
|
|
90
|
+
? [
|
|
91
|
+
{ label: "Recent", items: homeRecentItems },
|
|
92
|
+
{ label: "Pinned", items: homePinnedItems },
|
|
93
|
+
]
|
|
94
|
+
: compact
|
|
95
|
+
? [{ label: "", items: visibleItems }]
|
|
96
|
+
: [
|
|
97
|
+
{ label: "Running", items: activeItems },
|
|
98
|
+
{ label: "Pinned", items: pinnedItems },
|
|
99
|
+
{
|
|
100
|
+
label: activeItems.length || pinnedItems.length ? "Recent chats" : "",
|
|
101
|
+
items: idleItems.filter((item) => !item.meta?.pinned),
|
|
102
|
+
},
|
|
103
|
+
];
|
|
104
|
+
return (_jsxs("section", { "data-conversation-history": true, "aria-label": home ? "Home chats" : compact ? "Recent chats" : "Chat history", className: home
|
|
105
|
+
? "w-full"
|
|
106
|
+
: compact
|
|
107
|
+
? "w-full"
|
|
108
|
+
: "mx-auto flex min-h-0 w-full max-w-3xl flex-1 flex-col px-4 pb-4", children: [welcome && (_jsxs("div", { className: "pb-6 pt-8", children: [_jsx("h1", { className: "text-xl font-semibold", children: "How can I help?" }), _jsx("p", { className: "mt-2 text-sm text-muted-foreground", children: "Start something new or continue a recent chat." })] })), showBack && (_jsxs("button", { onClick: onClose, className: "mb-4 flex items-center gap-2 py-2 text-xs text-muted-foreground hover:text-foreground", children: [_jsx(ArrowLeft, { size: 14 }), " Back to chat"] })), (!compact || items.length > 0) && (_jsxs("div", { className: home
|
|
109
|
+
? "mb-2 mt-5 flex items-center justify-between px-1"
|
|
110
|
+
: "mb-2 mt-2 flex items-center justify-between", children: [_jsx("h2", { className: compact ? "text-xs font-medium text-muted-foreground" : "text-base font-semibold", children: home ? "Your chats" : compact ? "Recent chats" : "Chat history" }), home && onViewAll && (_jsx("button", { type: "button", onClick: onViewAll, className: "rounded-md px-2 py-1 text-xs text-muted-foreground hover:bg-muted hover:text-foreground focus-visible:outline-2 focus-visible:outline-primary [@media(pointer:coarse)]:min-h-11", children: "View all" }))] })), Boolean(workspaceId) && !compact && (_jsx("div", { className: "mb-3", children: _jsxs(DropdownMenu, { children: [_jsx(DropdownMenuTrigger, { asChild: true, children: _jsxs(Button, { variant: "outline", "aria-label": "History filter", className: "w-full justify-between font-normal shadow-none", children: [_jsx("span", { className: "truncate", children: all ? "All chats" : "Last used in this workspace" }), _jsx(ChevronDown, { className: "size-4 shrink-0 text-muted-foreground", "aria-hidden": "true" })] }) }), _jsx(DropdownMenuContent, { align: "start", className: "w-[var(--radix-dropdown-menu-trigger-width)]", children: [
|
|
80
111
|
{ value: false, label: "Last used in this workspace" },
|
|
81
|
-
{ value: true, label: "All
|
|
82
|
-
].map((option) => (_jsxs(DropdownMenuItem, { role: "menuitemradio", "aria-checked": all === option.value, onSelect: () => setAll(option.value), children: [_jsx("span", { className: "flex-1", children: option.label }), all === option.value && _jsx(Check, { className: "size-4", "aria-hidden": "true" })] }, option.label))) })] }) })), !compact && (_jsx(Input, { "aria-label": "Search chats", placeholder: "Search chats", value: search, onChange: (event) => setSearch(event.target.value), className: "mb-3" })), _jsx("span", { className: "sr-only", role: "status", children: copiedId ? "Chat ID copied" : "" }), loadError && (_jsx("p", { role: "alert", className: "mb-2 text-xs text-destructive", children: loadError })), _jsxs("div", { className:
|
|
83
|
-
|
|
84
|
-
|
|
112
|
+
{ value: true, label: "All chats" },
|
|
113
|
+
].map((option) => (_jsxs(DropdownMenuItem, { role: "menuitemradio", "aria-checked": all === option.value, onSelect: () => setAll(option.value), children: [_jsx("span", { className: "flex-1", children: option.label }), all === option.value && _jsx(Check, { className: "size-4", "aria-hidden": "true" })] }, option.label))) })] }) })), !compact && (_jsx(Input, { "aria-label": "Search chats", placeholder: "Search chats", value: search, onChange: (event) => setSearch(event.target.value), className: "mb-3" })), _jsx("span", { className: "sr-only", role: "status", children: copiedId ? "Chat ID copied" : "" }), loadError && (_jsx("p", { role: "alert", className: "mb-2 text-xs text-destructive", children: loadError })), _jsxs("div", { className: home
|
|
114
|
+
? "grid grid-cols-[repeat(auto-fit,minmax(min(100%,18rem),1fr))] gap-4"
|
|
115
|
+
: "min-h-0 flex-1 overflow-y-auto", "aria-busy": Boolean(loadingTo), children: [sections
|
|
116
|
+
.filter((section) => (home ? homeHasItems : section.items.length))
|
|
117
|
+
.map((section) => (_jsxs("section", { "aria-label": section.label || "Recent chats", className: home
|
|
118
|
+
? `min-w-0 rounded-xl border border-border/70 bg-muted/10 p-3 ${section.items.length ? "" : "hidden min-[640px]:block"}`
|
|
119
|
+
: "mb-4 last:mb-0", children: [section.label && (_jsx("h3", { "data-conversation-section-label": true, className: home
|
|
120
|
+
? "px-1 pb-2 text-xs font-medium text-muted-foreground"
|
|
121
|
+
: "px-2 py-2 text-xs font-medium text-muted-foreground", children: section.label })), home && !section.items.length && (_jsx("p", { className: "px-1 py-3 text-xs text-muted-foreground", children: section.label === "Pinned"
|
|
122
|
+
? "Pin chats to keep them close."
|
|
123
|
+
: "Your latest chats will appear here." })), section.items.map((item) => item.disabled ? (_jsx("p", { className: "py-3 text-sm text-muted-foreground", children: item.label }, item.to)) : (_jsxs("div", { className: home
|
|
124
|
+
? "group flex items-center rounded-lg transition-colors hover:bg-muted/60"
|
|
125
|
+
: "group flex items-center rounded-lg hover:bg-muted", children: [_jsxs(Link, { to: item.to, onClick: (event) => {
|
|
85
126
|
if (loadingTo) {
|
|
86
127
|
event.preventDefault();
|
|
87
128
|
return;
|
|
@@ -111,7 +152,9 @@ export function ConversationHistory({ groups, workspaceId, onClose, showBack = t
|
|
|
111
152
|
}
|
|
112
153
|
setLoadingTo(null);
|
|
113
154
|
onClose();
|
|
114
|
-
}, "data-conversation-row": true, className:
|
|
155
|
+
}, "data-conversation-row": true, className: home
|
|
156
|
+
? "flex min-w-0 flex-1 items-center gap-3 rounded-lg px-2 py-2 text-left text-sm focus-visible:outline-2 focus-visible:outline-primary"
|
|
157
|
+
: "flex min-w-0 flex-1 items-center gap-2 rounded-lg px-2 py-1.5 text-sm hover:bg-muted focus-visible:outline-2 focus-visible:outline-primary", children: [loadingTo === item.to ? (_jsx(Loader2, { className: "size-4 shrink-0 animate-spin text-muted-foreground", "aria-label": "Opening chat" })) : runFor(item)?.status === "running" ? (_jsx(Loader2, { className: "size-4 shrink-0 animate-spin text-primary motion-reduce:animate-none", "aria-hidden": true })) : runFor(item)?.status === "waiting" ? (_jsx(PauseCircle, { className: "size-4 shrink-0 text-primary", "aria-hidden": true })) : item.meta?.pinned ? (_jsx(Pin, { className: "size-4 shrink-0 text-muted-foreground", "aria-label": "Pinned chat" })) : (_jsx(MessageSquare, { className: "size-4 shrink-0 text-muted-foreground" })), _jsxs("span", { className: "min-w-0 flex-1", children: [_jsx("span", { className: "block truncate", children: item.label }), " ", runFor(item) && isChatRunActive(runFor(item)) ? (_jsx("span", { className: "block text-xs text-primary", children: runFor(item)?.status === "waiting" ? "Waiting for you" : "Running" })) : ((!compact || rootContext) && (_jsx("span", { className: "block truncate text-xs text-muted-foreground", children: !all &&
|
|
115
158
|
typeof item.meta?.previewEntityName === "string" &&
|
|
116
159
|
item.meta.previewEntityName
|
|
117
160
|
? `Last at ${item.meta.previewEntityName}`
|
|
@@ -138,5 +181,5 @@ export function ConversationHistory({ groups, workspaceId, onClose, showBack = t
|
|
|
138
181
|
.catch(() => setLoadError(`Could not copy. Chat ID: ${decodeURIComponent(id)}`));
|
|
139
182
|
}, children: [_jsx(Copy, { className: "size-4" }), "Copy chat ID"] }), Boolean(item.actions?.length) && _jsx(DropdownMenuSeparator, {}), item.actions?.map((action) => (_jsxs(Fragment, { children: [action.separator && _jsx(DropdownMenuSeparator, {}), _jsxs(DropdownMenuItem, { onSelect: () => {
|
|
140
183
|
void action.handler();
|
|
141
|
-
}, className: action.destructive ? "text-destructive" : undefined, children: [_jsx(action.icon, { className: "mr-2 size-4" }), action.label] })] }, action.label)))] })] })] }, item.to)))] }, section.label))), items.length === 0 && !compact && (_jsx("p", { className: "py-3 text-sm text-muted-foreground", children: search ? "No matching chats" : "No chats yet" }))] }), compact && onViewAll && (_jsxs(Button, { variant: "ghost", size: "sm", onClick: onViewAll, className: "mt-1 h-9 w-fit gap-2 px-2 text-sm font-normal text-muted-foreground [@media(pointer:coarse)]:min-h-11", children: [_jsx(MessagesSquare, { className: "size-4", "aria-hidden": true }), "
|
|
184
|
+
}, className: action.destructive ? "text-destructive" : undefined, children: [_jsx(action.icon, { className: "mr-2 size-4" }), action.label] })] }, action.label)))] })] })] }, item.to)))] }, section.label))), items.length === 0 && !compact && (_jsx("p", { className: "py-3 text-sm text-muted-foreground", children: search ? "No matching chats" : "No chats yet" }))] }), compact && onViewAll && !home && (_jsxs(Button, { variant: "ghost", size: "sm", onClick: onViewAll, className: "mt-1 h-9 w-fit gap-2 px-2 text-sm font-normal text-muted-foreground [@media(pointer:coarse)]:min-h-11", children: [_jsx(MessagesSquare, { className: "size-4", "aria-hidden": true }), "Chat history"] }))] }));
|
|
142
185
|
}
|
|
@@ -11,7 +11,7 @@ export function RunningChatsMenu({ onOpen } = {}) {
|
|
|
11
11
|
const active = Object.values(runs).filter(isChatRunActive);
|
|
12
12
|
if (!active.length)
|
|
13
13
|
return null;
|
|
14
|
-
return (_jsxs(DropdownMenu, { children: [_jsx(DropdownMenuTrigger, { asChild: true, children: _jsxs("button", { type: "button", "aria-label": `${active.length} running
|
|
14
|
+
return (_jsxs(DropdownMenu, { children: [_jsx(DropdownMenuTrigger, { asChild: true, children: _jsxs("button", { type: "button", "aria-label": `${active.length} running chats`, className: "inline-flex items-center gap-1.5 px-2 text-xs text-primary", children: [_jsx(LoaderCircle, { className: "size-3.5 animate-spin motion-reduce:animate-none" }), _jsx("span", { children: active.length })] }) }), _jsxs(DropdownMenuContent, { align: "end", className: "max-w-80", children: [_jsx(DropdownMenuLabel, { children: "Running in this browser" }), active.map((run) => (_jsxs(DropdownMenuItem, { onSelect: () => {
|
|
15
15
|
if (!selectRetainedThread(run.threadId)) {
|
|
16
16
|
navigate(run.conversationUrl ?? `/chat/${encodeURIComponent(run.threadId)}`);
|
|
17
17
|
}
|
|
@@ -105,7 +105,7 @@ export function useWorkbenchState(chatRoute) {
|
|
|
105
105
|
const openHistory = () => {
|
|
106
106
|
setHistoryOpen(true);
|
|
107
107
|
};
|
|
108
|
-
const historyShortcut = (_jsxs(Button, { variant: "ghost", size: "sm", onClick: openHistory, className: "h-9 w-fit gap-2 px-2 text-sm font-normal text-muted-foreground [@media(pointer:coarse)]:min-h-11", children: [_jsx(MessagesSquare, { className: "size-4", "aria-hidden": true }), "
|
|
108
|
+
const historyShortcut = (_jsxs(Button, { variant: "ghost", size: "sm", onClick: openHistory, className: "h-9 w-fit gap-2 px-2 text-sm font-normal text-muted-foreground [@media(pointer:coarse)]:min-h-11", children: [_jsx(MessagesSquare, { className: "size-4", "aria-hidden": true }), "Chat history"] }));
|
|
109
109
|
const toggleNavigation = useSidebarStore((s) => s.toggleMobile);
|
|
110
110
|
useEffect(() => {
|
|
111
111
|
if (panelOpen) {
|
|
@@ -4,7 +4,7 @@ import { DropdownMenu, DropdownMenuTrigger, DropdownMenuContent, DropdownMenuIte
|
|
|
4
4
|
import { ChatHomeStartersSlot } from "../components/chat-slots.js";
|
|
5
5
|
import { Layers } from "lucide-react";
|
|
6
6
|
export function WelcomeIntro({ navGroups, historyShortcut, }) {
|
|
7
|
-
return (_jsxs("div", { className: "mb-4 text-center", children: [_jsx("h1", { className: "text-2xl font-semibold tracking-tight", children: "What would you like to get done?" }), _jsx("p", { className: "mt-2 text-sm text-muted-foreground", children: "Find information, create or edit content, and run actions across your spaces." }), _jsx("div", { className: "mx-auto mt-4 max-w-sm text-left", children: _jsx(ChatHomeStartersSlot, { priority: 10 }) }), _jsxs("div", { className: "mt-4 flex flex-wrap items-center justify-center gap-2", children: [historyShortcut, navGroups.some((group) => group.meta?.type === "spaces-workspaces" && group.createActions?.length) && (_jsx("div", { children: _jsxs(DropdownMenu, { children: [_jsx(DropdownMenuTrigger, { asChild: true, children: _jsxs(Button, { variant: "ghost", size: "sm", className: "h-9 gap-2 px-
|
|
7
|
+
return (_jsxs("div", { className: "mb-4 text-center", children: [_jsx("h1", { className: "text-2xl font-semibold tracking-tight", children: "What would you like to get done?" }), _jsx("p", { className: "mt-2 text-sm text-muted-foreground", children: "Find information, create or edit content, and run actions across your spaces." }), _jsx("div", { className: "mx-auto mt-4 max-w-sm text-left", children: _jsx(ChatHomeStartersSlot, { priority: 10 }) }), _jsxs("div", { className: "mt-4 flex flex-wrap items-center justify-center gap-2", children: [historyShortcut, navGroups.some((group) => group.meta?.type === "spaces-workspaces" && group.createActions?.length) && (_jsx("div", { children: _jsxs(DropdownMenu, { children: [_jsx(DropdownMenuTrigger, { asChild: true, children: _jsxs(Button, { variant: "ghost", size: "sm", className: "h-9 gap-2 bg-primary/10 px-3 text-sm font-medium hover:bg-primary/15 [@media(pointer:coarse)]:min-h-11", children: [_jsx(Layers, { className: "size-4", "aria-hidden": "true" }), "Create a space"] }) }), _jsx(DropdownMenuContent, { align: "center", children: navGroups
|
|
8
8
|
.filter((group) => group.meta?.type === "spaces-workspaces")
|
|
9
9
|
.flatMap((group) => group.createActions ?? [])
|
|
10
10
|
.map((action) => (_jsx(DropdownMenuItem, { onSelect: () => action.handler(), children: action.label }, action.id))) })] }) }))] })] }));
|
|
@@ -23,6 +23,7 @@ export function WorkbenchPreview({ page, chatOnly: chatRoute = false, }) {
|
|
|
23
23
|
normalizeWorkbenchPath(rootItem.to) === normalizeWorkbenchPath(currentPage));
|
|
24
24
|
const conversationHome = (_jsx(ConversationHistory, { groups: navGroups, workspaceId: workspaceId, entityId: entityId, rootContext: rootContext, onClose: returnToChat, onViewAll: openHistory, showBack: false, compact: true }));
|
|
25
25
|
const emptyChatFooter = workspaceId ? conversationHome : historyShortcut;
|
|
26
|
+
const homeRecents = !workspaceId ? (_jsx(ConversationHistory, { groups: navGroups, workspaceId: undefined, onClose: returnToChat, onViewAll: openHistory, showBack: false, compact: true, home: true })) : undefined;
|
|
26
27
|
const buttonClass = "inline-flex items-center justify-center rounded-lg p-2 text-muted-foreground hover:bg-muted hover:text-foreground focus-visible:outline-2 focus-visible:outline-primary";
|
|
27
28
|
return (_jsxs("div", { className: "workbench-preview flex min-h-0 flex-1 overflow-hidden", "data-workspace-navigation": workspaceGroups ? "true" : undefined, children: [_jsx(WorkbenchStyles, {}), _jsx(WorkbenchNavigation, { groups: staticNavigationGroups, workspace: !!workspaceGroups, onNewConversation: startChat }), _jsxs("div", { className: "flex min-h-0 min-w-0 flex-1 flex-col overflow-hidden", "data-workbench-surface": true, role: "region", "aria-label": "Workspace working area", children: [chatWidth.compact && (_jsxs("div", { className: "flex shrink-0 items-center gap-1 border-b border-border px-2 py-1", role: "group", "aria-label": "Workspace panes", children: [_jsx(Button, { variant: "ghost", size: "icon", className: "preview-mobile-navigation size-11", "aria-label": "Open navigation", onClick: toggleNavigation, children: _jsx(Menu, { className: "size-4" }) }), ["content", "chat"]
|
|
28
29
|
.filter((pane) => !chatOnly || pane === "chat")
|
|
@@ -39,5 +40,5 @@ export function WorkbenchPreview({ page, chatOnly: chatRoute = false, }) {
|
|
|
39
40
|
}, children: [_jsx(WorkbenchChatHeader, { collapsed: collapsed, running: running, chatWidth: chatWidth, buttonClass: buttonClass, toggleNavigation: toggleNavigation, setCollapsed: setCollapsed, showHistory: showHistory, startChat: startChat, returnToChat: returnToChat, openHistory: openHistory, chatOnly: chatOnly, setContentCollapsed: setContentCollapsed }), !collapsed && showHistory && (_jsx(ConversationHistory, { groups: navGroups, workspaceId: workspaceId, onClose: returnToChat, showBack: true })), !chatWidth.compact && !collapsed && !contentCollapsed && (_jsx(ChatResizeHandle, { chatWidth: chatWidth })), _jsx("div", { className: "min-h-0 flex-1 flex-col", style: {
|
|
40
41
|
display: collapsed || showHistory ? "none" : "flex",
|
|
41
42
|
paddingBottom: spaciousChat && emptyChat && !historyOpen ? "clamp(32px, 10vh, 96px)" : undefined,
|
|
42
|
-
}, children: _jsx(ChatContent, { centerComposer: spaciousChat && emptyChat && !historyOpen, composerIntro: spaciousChat && emptyChat ? (_jsx(WelcomeIntro, { navGroups: navGroups, historyShortcut: emptyChatFooter })) : undefined, compactComposer: !spaciousChat, starterSuggestions: [], emptyState: _jsx(ChatEmptyState, { pageLabel: pageLabel, showHomeStarters: !spaciousChat, children: emptyChatFooter }) }) })] }), _jsx(WorkbenchContentPane, { contentHidden: contentHidden, panelOpen: panelOpen, chatWidth: chatWidth, contentCollapsed: contentCollapsed, collapsed: collapsed, buttonClass: buttonClass, setCollapsed: setCollapsed, setContentCollapsed: setContentCollapsed, closePanel: closePanel, page: page }), contentCollapsed && !chatOnly && !chatWidth.compact && (_jsx("aside", { "aria-label": "Collapsed content", className: "flex w-11 shrink-0 flex-col items-center", style: { width: 44 }, children: _jsx("div", { className: "flex h-full w-full flex-col items-center", "data-chat-rail": true, children: _jsx("div", { className: "flex items-center justify-center", style: { height: 60 }, children: _jsx(TooltipIconButton, { tooltip: "Expand content", className: buttonClass, "aria-label": "Expand content", onClick: () => setContentCollapsed(false), children: _jsx(FileText, { size: 18 }) }) }) }) }))] })] })] }));
|
|
43
|
+
}, children: _jsx(ChatContent, { centerComposer: spaciousChat && emptyChat && !historyOpen, composerIntro: spaciousChat && emptyChat ? (_jsx(WelcomeIntro, { navGroups: navGroups, historyShortcut: workspaceId ? emptyChatFooter : null })) : undefined, composerFooter: spaciousChat && emptyChat && !historyOpen && homeRecents ? (_jsx("div", { className: "w-full", children: homeRecents })) : undefined, compactComposer: !spaciousChat, starterSuggestions: [], emptyState: _jsx(ChatEmptyState, { pageLabel: pageLabel, showHomeStarters: !spaciousChat, children: emptyChatFooter }) }) })] }), _jsx(WorkbenchContentPane, { contentHidden: contentHidden, panelOpen: panelOpen, chatWidth: chatWidth, contentCollapsed: contentCollapsed, collapsed: collapsed, buttonClass: buttonClass, setCollapsed: setCollapsed, setContentCollapsed: setContentCollapsed, closePanel: closePanel, page: page }), contentCollapsed && !chatOnly && !chatWidth.compact && (_jsx("aside", { "aria-label": "Collapsed content", className: "flex w-11 shrink-0 flex-col items-center", style: { width: 44 }, children: _jsx("div", { className: "flex h-full w-full flex-col items-center", "data-chat-rail": true, children: _jsx("div", { className: "flex items-center justify-center", style: { height: 60 }, children: _jsx(TooltipIconButton, { tooltip: "Expand content", className: buttonClass, "aria-label": "Expand content", onClick: () => setContentCollapsed(false), children: _jsx(FileText, { size: 18 }) }) }) }) }))] })] })] }));
|
|
43
44
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@iloveagents/foundry-web-ui",
|
|
3
|
-
"version": "0.32.
|
|
3
|
+
"version": "0.32.4",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"description": "React agent UI core for Foundry UI — chat, composer, AG-UI adapter for assistant-ui, tool cards, panels, sidebar, theme runtime, and UI stores.",
|
|
6
6
|
"keywords": [
|
|
@@ -80,8 +80,8 @@
|
|
|
80
80
|
"recharts": "^3.10.1",
|
|
81
81
|
"remark-gfm": "^4.0.0",
|
|
82
82
|
"tailwind-merge": "^3.5.0",
|
|
83
|
-
"@iloveagents/foundry-agent": "^0.32.
|
|
84
|
-
"@iloveagents/foundry-web-primitives": "^0.32.
|
|
83
|
+
"@iloveagents/foundry-agent": "^0.32.4",
|
|
84
|
+
"@iloveagents/foundry-web-primitives": "^0.32.4"
|
|
85
85
|
},
|
|
86
86
|
"devDependencies": {
|
|
87
87
|
"@ag-ui/client": "^0.0.52",
|