Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
16 commits
Select commit Hold shift + click to select a range
9f3cf53
fix(desktop): open the agent's tab before Workspace Setup
harshithmullapudi Nov 3, 2026
9655a5e
fix(desktop): open the chat tab from the workspace create result
harshithmullapudi Nov 3, 2026
d94dce6
feat(panes): open a chat session in a new tab with panes.newTab
harshithmullapudi Nov 3, 2026
c8f81ea
feat: open a chat in a desktop tab where it is created
harshithmullapudi Nov 3, 2026
e168d58
refactor(desktop): stop adopting chat sessions that have no pane
harshithmullapudi Nov 3, 2026
5820ce9
docs: say where chat tabs come from now
harshithmullapudi Nov 3, 2026
591c589
feat(cloud): launch a cloud workspace's agent under a caller-chosen t…
harshithmullapudi Nov 3, 2026
9969468
refactor(desktop): bind a pending cloud chat by its launch terminal id
harshithmullapudi Nov 3, 2026
a79f9c3
fix(desktop): keep the floating activity popover open per workspace
harshithmullapudi Nov 3, 2026
c326a5a
fix(desktop): restore the chat scroll position after leaving a session
harshithmullapudi Nov 3, 2026
c74c248
fix(desktop): keep a promised terminal out of background adoption
harshithmullapudi Nov 4, 2026
c50b5f7
chore: align the chat-tab change with repo standards
harshithmullapudi Nov 4, 2026
9ea431a
fix(sandbox): carry the launch terminal id into sandbox.conf and host…
harshithmullapudi Nov 4, 2026
167a3d0
Merge remote-tracking branch 'origin/main' into fix/chat-tabs-from-cr…
harshithmullapudi Nov 4, 2026
7e7aeae
Merge remote-tracking branch 'origin/main' into fix/chat-tabs-from-cr…
harshithmullapudi Nov 5, 2026
985b729
fix: address review findings on chat tabs from creator
harshithmullapudi Nov 5, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import {
DEFAULT_WORKSPACE_SIDEBAR_WIDTH,
useWorkspaceSidebarStore,
} from "renderer/stores/workspace-sidebar-state";
import { WORKSPACE_SIDEBAR_ATTRIBUTE } from "./constants";
import { useAutoCollapseInNarrowWindow } from "./hooks/useAutoCollapseInNarrowWindow";
import { closeFocusedMenu } from "./utils/closeFocusedMenu";
import { getWorkspaceSidebarMaxWidth } from "./utils/getWorkspaceSidebarMaxWidth";
Expand Down Expand Up @@ -64,19 +65,21 @@ export function WorkspaceSidebarPanel({
</ResizablePanel>
);

if (!slides) {
return renderPanel(isCollapsed ? collapsedWidth : expandedWidth);
}

return (
<SidebarSlide
mode={isCollapsed ? "closed" : "open"}
width={expandedWidth}
edge="left"
alwaysMounted
onLayoutFrame={onLayoutFrame}
>
{() => renderPanel(expandedWidth)}
</SidebarSlide>
<div {...{ [WORKSPACE_SIDEBAR_ATTRIBUTE]: "" }} className="contents">
{slides ? (
<SidebarSlide
mode={isCollapsed ? "closed" : "open"}
width={expandedWidth}
edge="left"
alwaysMounted
onLayoutFrame={onLayoutFrame}
>
{() => renderPanel(expandedWidth)}
</SidebarSlide>
) : (
renderPanel(isCollapsed ? collapsedWidth : expandedWidth)
)}
</div>
);
}
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
// A pane is at least 260px wide (PANE_MIN_SIZE_CLASS_NAME in @superset/panes).
export const MIN_CENTER_WIDTH = 260;
export const WORKSPACE_SIDEBAR_ATTRIBUTE = "data-workspace-sidebar";
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
export { WORKSPACE_SIDEBAR_ATTRIBUTE } from "./constants";
export { WorkspaceSidebarPanel } from "./WorkspaceSidebarPanel";
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ import {
} from "renderer/lib/github/openPullRequestLink";
import { clearTerminalBackgroundMarker } from "renderer/lib/terminal/terminal-background-intents";
import { electronTrpcClient } from "renderer/lib/trpc-client";
import { WORKSPACE_SIDEBAR_ATTRIBUTE } from "renderer/routes/_authenticated/_dashboard/components/WorkspaceSidebarPanel";
import { usePageFavorites } from "renderer/routes/_authenticated/_dashboard/hooks/usePageFavorites";
import { usePagesList } from "renderer/routes/_authenticated/_dashboard/hooks/usePagesList";
import { pagesListInput } from "renderer/routes/_authenticated/_dashboard/utils/pagesListInput";
Expand Down Expand Up @@ -141,7 +142,6 @@ export function WorkspaceActivityMenu({
: null;
const { workspace: currentWorkspace } = useWorkspace();
const [shipView, setShipView] = useState<ShipView | null>(null);
const [popoverOpen, setPopoverOpen] = useState(false);
const triggerRef = useRef<HTMLButtonElement>(null);
const anchorNode = useActivityPanelStore(
(state) => state.anchorNodes[workspaceId],
Expand All @@ -156,6 +156,12 @@ export function WorkspaceActivityMenu({
(state) => state.hidden[workspaceId] === true,
);
const setHidden = useActivityPanelStore((state) => state.setHidden);
const popoverOpen = useActivityPanelStore(
(state) => state.floatingOpen[workspaceId] === true,
);
const setFloatingOpen = useActivityPanelStore(
(state) => state.setFloatingOpen,
);
const docked = fits && !hidden;
const floating = popoverOpen && !fits;
const open = docked || floating;
Expand Down Expand Up @@ -441,11 +447,11 @@ export function WorkspaceActivityMenu({
}, [open, workspaceId, newestPublishedAt, markSeen]);

useEffect(() => {
if (fits) setPopoverOpen(false);
}, [fits]);
if (fits) setFloatingOpen(workspaceId, false);
}, [fits, workspaceId, setFloatingOpen]);

const setFloating = (next: boolean) => {
setPopoverOpen(next);
setFloatingOpen(workspaceId, next);
if (next) {
void utils.page.listPaginated.invalidate(workspaceListInput);
return;
Expand Down Expand Up @@ -825,7 +831,11 @@ export function WorkspaceActivityMenu({
if (shipView || composing) event.preventDefault();
}}
onInteractOutside={(event) => {
if (triggerRef.current?.contains(event.target as Node))
const target = event.target as Element;
if (
triggerRef.current?.contains(target) ||
target.closest?.(`[${WORKSPACE_SIDEBAR_ATTRIBUTE}]`)
)
event.preventDefault();
}}
>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,3 +56,12 @@ test("hiding the docked card is per workspace", () => {
setHidden("ws-a", false);
expect("ws-a" in useActivityPanelStore.getState().hidden).toBe(false);
});

test("the floating popover stays open per workspace and closing removes the key", () => {
const { setFloatingOpen } = useActivityPanelStore.getState();
setFloatingOpen("ws-a", true);
expect(useActivityPanelStore.getState().floatingOpen["ws-a"]).toBe(true);
expect(useActivityPanelStore.getState().floatingOpen["ws-b"]).toBeUndefined();
setFloatingOpen("ws-a", false);
expect("ws-a" in useActivityPanelStore.getState().floatingOpen).toBe(false);
});
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ interface ActivityPanelStore {
setFits: (workspaceId: string, fits: boolean) => void;
hidden: Record<string, true>;
setHidden: (workspaceId: string, hidden: boolean) => void;
floatingOpen: Record<string, true>;
setFloatingOpen: (workspaceId: string, open: boolean) => void;
stoppedKeys: ReadonlySet<string>;
noteStopped: (key: string) => void;
forgetStopped: (keys: readonly string[]) => void;
Expand Down Expand Up @@ -51,6 +53,15 @@ export const useActivityPanelStore = create<ActivityPanelStore>()((set) => ({
const { [workspaceId]: _previous, ...rest } = state.hidden;
return { hidden: hidden ? { ...rest, [workspaceId]: true } : rest };
}),
floatingOpen: {},
setFloatingOpen: (workspaceId, open) =>
set((state) => {
if ((state.floatingOpen[workspaceId] === true) === open) return state;
const { [workspaceId]: _previous, ...rest } = state.floatingOpen;
return {
floatingOpen: open ? { ...rest, [workspaceId]: true } : rest,
};
}),
stoppedKeys: new Set(),
noteStopped: (key) =>
set((state) => ({ stoppedKeys: new Set(state.stoppedKeys).add(key) })),
Expand Down
Original file line number Diff line number Diff line change
@@ -1,37 +1,24 @@
import type { WorkspaceStore } from "@superset/panes";
import type { StoreApi } from "zustand/vanilla";
import { useAutoAdoptChatSessions } from "../../hooks/useAutoAdoptChatSessions";
import { useClearActivePaneAttention } from "../../hooks/useClearActivePaneAttention";
import type { PaneViewerData } from "../../types";

type PaneStore = StoreApi<WorkspaceStore<PaneViewerData>>;

interface WorkspaceAgentEffectsProps {
workspaceId: string;
store: PaneStore;
rightStore: PaneStore;
linkedStores: readonly PaneStore[];
isLayoutReady: boolean;
}

/**
* Agent bindings change on every hook event. Reading them here, not in the
* page, keeps an event from re-rendering the whole workspace.
*/
export function WorkspaceAgentEffects({
workspaceId,
store,
rightStore,
linkedStores,
isLayoutReady,
}: WorkspaceAgentEffectsProps) {
useClearActivePaneAttention({ store });
useClearActivePaneAttention({ store: rightStore });
useAutoAdoptChatSessions({
store,
linkedStores,
workspaceId,
isLayoutReady,
});
return null;
}

This file was deleted.

Loading
Loading