Keep explicitly reopened archived agent tabs open
This commit is contained in:
@@ -120,6 +120,7 @@ const NEW_TAB_AGENT_OPTION_ID = "__new_tab_agent__";
|
|||||||
const NEW_TAB_TERMINAL_OPTION_ID = "__new_tab_terminal__";
|
const NEW_TAB_TERMINAL_OPTION_ID = "__new_tab_terminal__";
|
||||||
type NewTabOptionId = typeof NEW_TAB_AGENT_OPTION_ID | typeof NEW_TAB_TERMINAL_OPTION_ID;
|
type NewTabOptionId = typeof NEW_TAB_AGENT_OPTION_ID | typeof NEW_TAB_TERMINAL_OPTION_ID;
|
||||||
const EMPTY_UI_TABS: WorkspaceTab[] = [];
|
const EMPTY_UI_TABS: WorkspaceTab[] = [];
|
||||||
|
const EMPTY_PINNED_AGENT_IDS = new Set<string>();
|
||||||
|
|
||||||
type WorkspaceScreenProps = {
|
type WorkspaceScreenProps = {
|
||||||
serverId: string;
|
serverId: string;
|
||||||
@@ -810,6 +811,8 @@ function WorkspaceScreenContent({
|
|||||||
const openWorkspaceTab = useWorkspaceLayoutStore((state) => state.openTab);
|
const openWorkspaceTab = useWorkspaceLayoutStore((state) => state.openTab);
|
||||||
const focusWorkspaceTab = useWorkspaceLayoutStore((state) => state.focusTab);
|
const focusWorkspaceTab = useWorkspaceLayoutStore((state) => state.focusTab);
|
||||||
const closeWorkspaceTab = useWorkspaceLayoutStore((state) => state.closeTab);
|
const closeWorkspaceTab = useWorkspaceLayoutStore((state) => state.closeTab);
|
||||||
|
const pinWorkspaceAgent = useWorkspaceLayoutStore((state) => state.pinAgent);
|
||||||
|
const unpinWorkspaceAgent = useWorkspaceLayoutStore((state) => state.unpinAgent);
|
||||||
const retargetWorkspaceTab = useWorkspaceLayoutStore((state) => state.retargetTab);
|
const retargetWorkspaceTab = useWorkspaceLayoutStore((state) => state.retargetTab);
|
||||||
const splitWorkspacePane = useWorkspaceLayoutStore((state) => state.splitPane);
|
const splitWorkspacePane = useWorkspaceLayoutStore((state) => state.splitPane);
|
||||||
const splitWorkspacePaneEmpty = useWorkspaceLayoutStore((state) => state.splitPaneEmpty);
|
const splitWorkspacePaneEmpty = useWorkspaceLayoutStore((state) => state.splitPaneEmpty);
|
||||||
@@ -817,6 +820,11 @@ function WorkspaceScreenContent({
|
|||||||
const focusWorkspacePane = useWorkspaceLayoutStore((state) => state.focusPane);
|
const focusWorkspacePane = useWorkspaceLayoutStore((state) => state.focusPane);
|
||||||
const resizeWorkspaceSplit = useWorkspaceLayoutStore((state) => state.resizeSplit);
|
const resizeWorkspaceSplit = useWorkspaceLayoutStore((state) => state.resizeSplit);
|
||||||
const reorderWorkspaceTabsInPane = useWorkspaceLayoutStore((state) => state.reorderTabsInPane);
|
const reorderWorkspaceTabsInPane = useWorkspaceLayoutStore((state) => state.reorderTabsInPane);
|
||||||
|
const pinnedAgentIds = useWorkspaceLayoutStore((state) =>
|
||||||
|
persistenceKey
|
||||||
|
? state.pinnedAgentIdsByWorkspace[persistenceKey] ?? EMPTY_PINNED_AGENT_IDS
|
||||||
|
: EMPTY_PINNED_AGENT_IDS
|
||||||
|
);
|
||||||
const pendingByDraftId = useCreateFlowStore((state) => state.pendingByDraftId);
|
const pendingByDraftId = useCreateFlowStore((state) => state.pendingByDraftId);
|
||||||
const consumedOpenIntentsRef = useRef(new Set<string>());
|
const consumedOpenIntentsRef = useRef(new Set<string>());
|
||||||
const pendingCloseTabIdsRef = useRef(new Set<string>());
|
const pendingCloseTabIdsRef = useRef(new Set<string>());
|
||||||
@@ -830,6 +838,38 @@ function WorkspaceScreenContent({
|
|||||||
}),
|
}),
|
||||||
[normalizedServerId, normalizedWorkspaceId, openIntent]
|
[normalizedServerId, normalizedWorkspaceId, openIntent]
|
||||||
);
|
);
|
||||||
|
const currentOpenIntentPinnedAgentId = useMemo(
|
||||||
|
function getCurrentOpenIntentPinnedAgentId() {
|
||||||
|
if (!openIntent || openIntent.kind !== "agent" || !hasHydratedAgents) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
if (!workspaceAgentVisibility.knownAgentIds.has(openIntent.agentId)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
if (workspaceAgentVisibility.activeAgentIds.has(openIntent.agentId)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return openIntent.agentId;
|
||||||
|
},
|
||||||
|
[hasHydratedAgents, openIntent, workspaceAgentVisibility]
|
||||||
|
);
|
||||||
|
const closeWorkspaceTabWithCleanup = useCallback(
|
||||||
|
function closeWorkspaceTabWithCleanup(input: {
|
||||||
|
tabId: string;
|
||||||
|
target?: WorkspaceTabTarget | null;
|
||||||
|
}) {
|
||||||
|
const normalizedTabId = trimNonEmpty(input.tabId);
|
||||||
|
if (!normalizedTabId || !persistenceKey) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (input.target?.kind === "agent") {
|
||||||
|
unpinWorkspaceAgent(persistenceKey, input.target.agentId);
|
||||||
|
}
|
||||||
|
closeWorkspaceTab(persistenceKey, normalizedTabId);
|
||||||
|
},
|
||||||
|
[closeWorkspaceTab, persistenceKey, unpinWorkspaceAgent]
|
||||||
|
);
|
||||||
|
|
||||||
const focusedPaneTabState = useMemo(
|
const focusedPaneTabState = useMemo(
|
||||||
() =>
|
() =>
|
||||||
@@ -930,6 +970,11 @@ function WorkspaceScreenContent({
|
|||||||
if (!currentOpenIntentKey) {
|
if (!currentOpenIntentKey) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (currentOpenIntentPinnedAgentId) {
|
||||||
|
pinWorkspaceAgent(persistenceKey, currentOpenIntentPinnedAgentId);
|
||||||
|
}
|
||||||
|
|
||||||
const intentKey = currentOpenIntentKey;
|
const intentKey = currentOpenIntentKey;
|
||||||
if (consumedOpenIntentsRef.current.has(intentKey)) {
|
if (consumedOpenIntentsRef.current.has(intentKey)) {
|
||||||
if (resolvedOpenIntentKey !== intentKey) {
|
if (resolvedOpenIntentKey !== intentKey) {
|
||||||
@@ -959,11 +1004,13 @@ function WorkspaceScreenContent({
|
|||||||
focusWorkspaceTab(persistenceKey, tabId);
|
focusWorkspaceTab(persistenceKey, tabId);
|
||||||
}
|
}
|
||||||
}, [
|
}, [
|
||||||
|
currentOpenIntentPinnedAgentId,
|
||||||
currentOpenIntentKey,
|
currentOpenIntentKey,
|
||||||
focusWorkspaceTab,
|
focusWorkspaceTab,
|
||||||
openIntent,
|
openIntent,
|
||||||
openWorkspaceDraftTab,
|
openWorkspaceDraftTab,
|
||||||
openWorkspaceTab,
|
openWorkspaceTab,
|
||||||
|
pinWorkspaceAgent,
|
||||||
persistenceKey,
|
persistenceKey,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
@@ -1029,27 +1076,32 @@ function WorkspaceScreenContent({
|
|||||||
if (
|
if (
|
||||||
canPruneAgentTabs &&
|
canPruneAgentTabs &&
|
||||||
tab.target.kind === "agent" &&
|
tab.target.kind === "agent" &&
|
||||||
|
!pinnedAgentIds.has(tab.target.agentId) &&
|
||||||
|
tab.target.agentId !== currentOpenIntentPinnedAgentId &&
|
||||||
shouldPruneWorkspaceAgentTab({
|
shouldPruneWorkspaceAgentTab({
|
||||||
agentId: tab.target.agentId,
|
agentId: tab.target.agentId,
|
||||||
agentsHydrated: hasHydratedAgents,
|
agentsHydrated: hasHydratedAgents,
|
||||||
knownAgentIds: workspaceAgentVisibility.knownAgentIds,
|
knownAgentIds: workspaceAgentVisibility.knownAgentIds,
|
||||||
|
activeAgentIds: workspaceAgentVisibility.activeAgentIds,
|
||||||
})
|
})
|
||||||
) {
|
) {
|
||||||
closeWorkspaceTab(persistenceKey, tab.tabId);
|
closeWorkspaceTabWithCleanup({ tabId: tab.tabId, target: tab.target });
|
||||||
}
|
}
|
||||||
if (
|
if (
|
||||||
canPruneTerminalTabs &&
|
canPruneTerminalTabs &&
|
||||||
tab.target.kind === "terminal" &&
|
tab.target.kind === "terminal" &&
|
||||||
!terminalIds.has(tab.target.terminalId)
|
!terminalIds.has(tab.target.terminalId)
|
||||||
) {
|
) {
|
||||||
closeWorkspaceTab(persistenceKey, tab.tabId);
|
closeWorkspaceTabWithCleanup({ tabId: tab.tabId, target: tab.target });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}, [
|
}, [
|
||||||
closeWorkspaceTab,
|
closeWorkspaceTabWithCleanup,
|
||||||
|
currentOpenIntentPinnedAgentId,
|
||||||
ensureWorkspaceTab,
|
ensureWorkspaceTab,
|
||||||
hasHydratedAgents,
|
hasHydratedAgents,
|
||||||
pendingByDraftId,
|
pendingByDraftId,
|
||||||
|
pinnedAgentIds,
|
||||||
persistenceKey,
|
persistenceKey,
|
||||||
terminals,
|
terminals,
|
||||||
terminalsQuery.isSuccess,
|
terminalsQuery.isSuccess,
|
||||||
@@ -1311,13 +1363,16 @@ function WorkspaceScreenContent({
|
|||||||
);
|
);
|
||||||
|
|
||||||
if (persistenceKey) {
|
if (persistenceKey) {
|
||||||
closeWorkspaceTab(persistenceKey, tabId);
|
closeWorkspaceTabWithCleanup({
|
||||||
|
tabId,
|
||||||
|
target: { kind: "terminal", terminalId },
|
||||||
|
});
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
[
|
[
|
||||||
closeWorkspaceTab,
|
closeWorkspaceTabWithCleanup,
|
||||||
killTerminalMutation,
|
killTerminalMutation,
|
||||||
persistenceKey,
|
persistenceKey,
|
||||||
queryClient,
|
queryClient,
|
||||||
@@ -1354,14 +1409,17 @@ function WorkspaceScreenContent({
|
|||||||
setHoveredTabKey((current) => (current === tabId ? null : current));
|
setHoveredTabKey((current) => (current === tabId ? null : current));
|
||||||
setHoveredCloseTabKey((current) => (current === tabId ? null : current));
|
setHoveredCloseTabKey((current) => (current === tabId ? null : current));
|
||||||
if (persistenceKey) {
|
if (persistenceKey) {
|
||||||
closeWorkspaceTab(persistenceKey, tabId);
|
closeWorkspaceTabWithCleanup({
|
||||||
|
tabId,
|
||||||
|
target: { kind: "agent", agentId },
|
||||||
|
});
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
[
|
[
|
||||||
archiveAgent,
|
archiveAgent,
|
||||||
closeWorkspaceTab,
|
closeWorkspaceTabWithCleanup,
|
||||||
isArchivingAgent,
|
isArchivingAgent,
|
||||||
normalizedServerId,
|
normalizedServerId,
|
||||||
persistenceKey,
|
persistenceKey,
|
||||||
@@ -1374,10 +1432,10 @@ function WorkspaceScreenContent({
|
|||||||
setHoveredTabKey((current) => (current === tabId ? null : current));
|
setHoveredTabKey((current) => (current === tabId ? null : current));
|
||||||
setHoveredCloseTabKey((current) => (current === tabId ? null : current));
|
setHoveredCloseTabKey((current) => (current === tabId ? null : current));
|
||||||
if (persistenceKey) {
|
if (persistenceKey) {
|
||||||
closeWorkspaceTab(persistenceKey, tabId);
|
closeWorkspaceTabWithCleanup({ tabId });
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
[closeWorkspaceTab, persistenceKey]
|
[closeWorkspaceTabWithCleanup, persistenceKey]
|
||||||
);
|
);
|
||||||
|
|
||||||
const handleCloseTabById = useCallback(
|
const handleCloseTabById = useCallback(
|
||||||
@@ -1503,7 +1561,10 @@ function WorkspaceScreenContent({
|
|||||||
};
|
};
|
||||||
});
|
});
|
||||||
if (persistenceKey) {
|
if (persistenceKey) {
|
||||||
closeWorkspaceTab(persistenceKey, tabId);
|
closeWorkspaceTabWithCleanup({
|
||||||
|
tabId,
|
||||||
|
target: { kind: "terminal", terminalId },
|
||||||
|
});
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.warn(`[WorkspaceScreen] Failed to close terminal tab ${logLabel}`, { terminalId, error });
|
console.warn(`[WorkspaceScreen] Failed to close terminal tab ${logLabel}`, { terminalId, error });
|
||||||
@@ -1517,7 +1578,10 @@ function WorkspaceScreenContent({
|
|||||||
try {
|
try {
|
||||||
await archiveAgent({ serverId: normalizedServerId, agentId });
|
await archiveAgent({ serverId: normalizedServerId, agentId });
|
||||||
if (persistenceKey) {
|
if (persistenceKey) {
|
||||||
closeWorkspaceTab(persistenceKey, tabId);
|
closeWorkspaceTabWithCleanup({
|
||||||
|
tabId,
|
||||||
|
target: { kind: "agent", agentId },
|
||||||
|
});
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.warn(`[WorkspaceScreen] Failed to archive agent tab ${logLabel}`, { agentId, error });
|
console.warn(`[WorkspaceScreen] Failed to archive agent tab ${logLabel}`, { agentId, error });
|
||||||
@@ -1526,7 +1590,7 @@ function WorkspaceScreenContent({
|
|||||||
|
|
||||||
for (const { tabId } of groups.otherTabs) {
|
for (const { tabId } of groups.otherTabs) {
|
||||||
if (persistenceKey) {
|
if (persistenceKey) {
|
||||||
closeWorkspaceTab(persistenceKey, tabId);
|
closeWorkspaceTabWithCleanup({ tabId });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1536,7 +1600,7 @@ function WorkspaceScreenContent({
|
|||||||
},
|
},
|
||||||
[
|
[
|
||||||
archiveAgent,
|
archiveAgent,
|
||||||
closeWorkspaceTab,
|
closeWorkspaceTabWithCleanup,
|
||||||
killTerminalMutation,
|
killTerminalMutation,
|
||||||
normalizedServerId,
|
normalizedServerId,
|
||||||
persistenceKey,
|
persistenceKey,
|
||||||
@@ -1717,7 +1781,10 @@ function WorkspaceScreenContent({
|
|||||||
|
|
||||||
if (action.id === "workspace.pane.close") {
|
if (action.id === "workspace.pane.close") {
|
||||||
for (const tabId of focusedPane.tabIds) {
|
for (const tabId of focusedPane.tabIds) {
|
||||||
closeWorkspaceTab(persistenceKey, tabId);
|
closeWorkspaceTabWithCleanup({
|
||||||
|
tabId,
|
||||||
|
target: allTabDescriptorsById.get(tabId)?.target ?? null,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -1725,7 +1792,8 @@ function WorkspaceScreenContent({
|
|||||||
return false;
|
return false;
|
||||||
},
|
},
|
||||||
[
|
[
|
||||||
closeWorkspaceTab,
|
allTabDescriptorsById,
|
||||||
|
closeWorkspaceTabWithCleanup,
|
||||||
focusWorkspacePane,
|
focusWorkspacePane,
|
||||||
handleCreateDraftSplit,
|
handleCreateDraftSplit,
|
||||||
moveWorkspaceTabToPane,
|
moveWorkspaceTabToPane,
|
||||||
|
|||||||
@@ -218,7 +218,11 @@ describe("workspace-layout-store tree transforms", () => {
|
|||||||
|
|
||||||
describe("workspace-layout-store actions", () => {
|
describe("workspace-layout-store actions", () => {
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
useWorkspaceLayoutStore.setState({ layoutByWorkspace: {} });
|
useWorkspaceLayoutStore.setState({
|
||||||
|
layoutByWorkspace: {},
|
||||||
|
splitSizesByWorkspace: {},
|
||||||
|
pinnedAgentIdsByWorkspace: {},
|
||||||
|
});
|
||||||
vi.restoreAllMocks();
|
vi.restoreAllMocks();
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -634,4 +638,40 @@ describe("workspace-layout-store actions", () => {
|
|||||||
|
|
||||||
expect(layout).toEqual(createDefaultLayout());
|
expect(layout).toEqual(createDefaultLayout());
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("keeps pinned archived agents in memory per workspace without persisting them", () => {
|
||||||
|
const workspaceKey = createWorkspaceKey();
|
||||||
|
const otherWorkspaceKey = buildWorkspaceTabPersistenceKey({
|
||||||
|
serverId: SERVER_ID,
|
||||||
|
workspaceId: "/repo/other-worktree",
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(otherWorkspaceKey).toBeTruthy();
|
||||||
|
|
||||||
|
const store = useWorkspaceLayoutStore.getState();
|
||||||
|
store.pinAgent(workspaceKey, "agent-1");
|
||||||
|
store.pinAgent(workspaceKey, "agent-1");
|
||||||
|
store.pinAgent(otherWorkspaceKey as string, "agent-2");
|
||||||
|
|
||||||
|
let state = useWorkspaceLayoutStore.getState();
|
||||||
|
expect(Array.from(state.pinnedAgentIdsByWorkspace[workspaceKey] ?? [])).toEqual(["agent-1"]);
|
||||||
|
expect(Array.from(state.pinnedAgentIdsByWorkspace[otherWorkspaceKey as string] ?? [])).toEqual([
|
||||||
|
"agent-2",
|
||||||
|
]);
|
||||||
|
|
||||||
|
store.unpinAgent(workspaceKey, "agent-1");
|
||||||
|
|
||||||
|
state = useWorkspaceLayoutStore.getState();
|
||||||
|
expect(state.pinnedAgentIdsByWorkspace[workspaceKey]).toBeUndefined();
|
||||||
|
expect(Array.from(state.pinnedAgentIdsByWorkspace[otherWorkspaceKey as string] ?? [])).toEqual([
|
||||||
|
"agent-2",
|
||||||
|
]);
|
||||||
|
|
||||||
|
const partialize = useWorkspaceLayoutStore.persist.getOptions().partialize;
|
||||||
|
expect(partialize).toBeTypeOf("function");
|
||||||
|
expect(partialize?.(state)).toEqual({
|
||||||
|
layoutByWorkspace: {},
|
||||||
|
splitSizesByWorkspace: {},
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -53,6 +53,7 @@ export type { SplitGroup, SplitNode, SplitPane, WorkspaceLayout };
|
|||||||
interface WorkspaceLayoutStore {
|
interface WorkspaceLayoutStore {
|
||||||
layoutByWorkspace: Record<string, WorkspaceLayout>;
|
layoutByWorkspace: Record<string, WorkspaceLayout>;
|
||||||
splitSizesByWorkspace: Record<string, Record<string, number[]>>;
|
splitSizesByWorkspace: Record<string, Record<string, number[]>>;
|
||||||
|
pinnedAgentIdsByWorkspace: Record<string, Set<string>>;
|
||||||
openTab: (workspaceKey: string, target: WorkspaceTabTarget) => string | null;
|
openTab: (workspaceKey: string, target: WorkspaceTabTarget) => string | null;
|
||||||
closeTab: (workspaceKey: string, tabId: string) => void;
|
closeTab: (workspaceKey: string, tabId: string) => void;
|
||||||
focusTab: (workspaceKey: string, tabId: string) => void;
|
focusTab: (workspaceKey: string, tabId: string) => void;
|
||||||
@@ -78,6 +79,8 @@ interface WorkspaceLayoutStore {
|
|||||||
focusPane: (workspaceKey: string, paneId: string) => void;
|
focusPane: (workspaceKey: string, paneId: string) => void;
|
||||||
resizeSplit: (workspaceKey: string, groupId: string, sizes: number[]) => void;
|
resizeSplit: (workspaceKey: string, groupId: string, sizes: number[]) => void;
|
||||||
reorderTabsInPane: (workspaceKey: string, paneId: string, tabIds: string[]) => void;
|
reorderTabsInPane: (workspaceKey: string, paneId: string, tabIds: string[]) => void;
|
||||||
|
pinAgent: (workspaceKey: string, agentId: string) => void;
|
||||||
|
unpinAgent: (workspaceKey: string, agentId: string) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
const MAX_TREE_DEPTH = 4;
|
const MAX_TREE_DEPTH = 4;
|
||||||
@@ -99,6 +102,7 @@ export const useWorkspaceLayoutStore = create<WorkspaceLayoutStore>()(
|
|||||||
(set, get) => ({
|
(set, get) => ({
|
||||||
layoutByWorkspace: {},
|
layoutByWorkspace: {},
|
||||||
splitSizesByWorkspace: {},
|
splitSizesByWorkspace: {},
|
||||||
|
pinnedAgentIdsByWorkspace: {},
|
||||||
openTab: (workspaceKey, target) => {
|
openTab: (workspaceKey, target) => {
|
||||||
const normalizedWorkspaceKey = trimNonEmpty(workspaceKey);
|
const normalizedWorkspaceKey = trimNonEmpty(workspaceKey);
|
||||||
const normalizedTarget = normalizeWorkspaceTabTarget(target);
|
const normalizedTarget = normalizeWorkspaceTabTarget(target);
|
||||||
@@ -385,6 +389,66 @@ export const useWorkspaceLayoutStore = create<WorkspaceLayoutStore>()(
|
|||||||
};
|
};
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
pinAgent: (workspaceKey, agentId) => {
|
||||||
|
const normalizedWorkspaceKey = trimNonEmpty(workspaceKey);
|
||||||
|
const normalizedAgentId = trimNonEmpty(agentId);
|
||||||
|
if (!normalizedWorkspaceKey || !normalizedAgentId) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
set((state) => {
|
||||||
|
const currentPinnedAgentIds =
|
||||||
|
state.pinnedAgentIdsByWorkspace[normalizedWorkspaceKey] ?? null;
|
||||||
|
if (currentPinnedAgentIds?.has(normalizedAgentId)) {
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
|
||||||
|
const nextPinnedAgentIds = new Set(currentPinnedAgentIds ?? []);
|
||||||
|
nextPinnedAgentIds.add(normalizedAgentId);
|
||||||
|
|
||||||
|
return {
|
||||||
|
pinnedAgentIdsByWorkspace: {
|
||||||
|
...state.pinnedAgentIdsByWorkspace,
|
||||||
|
[normalizedWorkspaceKey]: nextPinnedAgentIds,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
});
|
||||||
|
},
|
||||||
|
unpinAgent: (workspaceKey, agentId) => {
|
||||||
|
const normalizedWorkspaceKey = trimNonEmpty(workspaceKey);
|
||||||
|
const normalizedAgentId = trimNonEmpty(agentId);
|
||||||
|
if (!normalizedWorkspaceKey || !normalizedAgentId) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
set((state) => {
|
||||||
|
const currentPinnedAgentIds =
|
||||||
|
state.pinnedAgentIdsByWorkspace[normalizedWorkspaceKey] ?? null;
|
||||||
|
if (!currentPinnedAgentIds?.has(normalizedAgentId)) {
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (currentPinnedAgentIds.size === 1) {
|
||||||
|
const nextPinnedAgentIdsByWorkspace = {
|
||||||
|
...state.pinnedAgentIdsByWorkspace,
|
||||||
|
};
|
||||||
|
delete nextPinnedAgentIdsByWorkspace[normalizedWorkspaceKey];
|
||||||
|
return {
|
||||||
|
pinnedAgentIdsByWorkspace: nextPinnedAgentIdsByWorkspace,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
const nextPinnedAgentIds = new Set(currentPinnedAgentIds);
|
||||||
|
nextPinnedAgentIds.delete(normalizedAgentId);
|
||||||
|
|
||||||
|
return {
|
||||||
|
pinnedAgentIdsByWorkspace: {
|
||||||
|
...state.pinnedAgentIdsByWorkspace,
|
||||||
|
[normalizedWorkspaceKey]: nextPinnedAgentIds,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
});
|
||||||
|
},
|
||||||
}),
|
}),
|
||||||
{
|
{
|
||||||
name: "workspace-layout-state",
|
name: "workspace-layout-state",
|
||||||
|
|||||||
Reference in New Issue
Block a user