From 18a19a839631a702f540faeb176252c14f542852 Mon Sep 17 00:00:00 2001 From: touch2be Date: Thu, 6 Aug 2026 15:12:57 +0200 Subject: [PATCH] fix(host): restore session project moves --- .../HostProvider.render.test.tsx | 20 +++++++++++++ src/features/host-provider/HostProvider.tsx | 29 +++++++++++++++++-- 2 files changed, 46 insertions(+), 3 deletions(-) diff --git a/src/features/host-provider/HostProvider.render.test.tsx b/src/features/host-provider/HostProvider.render.test.tsx index c247614..b7bd168 100644 --- a/src/features/host-provider/HostProvider.render.test.tsx +++ b/src/features/host-provider/HostProvider.render.test.tsx @@ -209,6 +209,26 @@ describe("HostProvider render integration", () => { act(() => actions.setSessionPinned("session-1", true)); expect(state.sessionMeta["session-1"]?.pinnedAt).toEqual(expect.any(String)); + await act(() => actions.moveSessionToProject("session-1", "/other/")); + expect(state.sessionMeta["session-1"]).toEqual( + expect.objectContaining({ + sidebarSection: "projects", + displayProjectDir: "/other", + sidebarMovedAt: expect.any(Number), + }), + ); + expect(JSON.parse(persisted.values.get(STORAGE_KEYS.SESSION_META) ?? "{}")).toEqual( + expect.objectContaining({ + "session-1": expect.objectContaining({ + sidebarSection: "projects", + displayProjectDir: "/other", + }), + }), + ); + await act(() => actions.removeSessionFromProject("session-1")); + expect(state.sessionMeta["session-1"]).toEqual( + expect.objectContaining({ sidebarSection: "chats", displayProjectDir: null }), + ); await act(() => actions.deleteSession("session-1")); expect(host.deleteSession).toHaveBeenCalledWith("session-1"); diff --git a/src/features/host-provider/HostProvider.tsx b/src/features/host-provider/HostProvider.tsx index 5ed9d27..0bfd2cb 100644 --- a/src/features/host-provider/HostProvider.tsx +++ b/src/features/host-provider/HostProvider.tsx @@ -47,7 +47,12 @@ import { getShellWorkspacePolicy } from "@/runtime/shell-policy"; import { normalizeProjectPath } from "@/lib/path"; import { defaultEnabledSkillNames, sessionSkillsKey } from "@/lib/session-skills"; import { findModel } from "@/lib/utils"; -import { makeProjectKey, shouldAutoNameSession } from "@/hooks/agent-session-utils"; +import { + createSessionProjectDetachMeta, + createSessionProjectMoveMeta, + makeProjectKey, + shouldAutoNameSession, +} from "@/hooks/agent-session-utils"; import { STORAGE_KEYS } from "@/lib/constants"; import { storageGet, storageSet } from "@/lib/persistence/storage"; import { connectionsToModelProviders } from "@/lib/models-dev"; @@ -1121,8 +1126,26 @@ function HostProviderBody({ return next; }); }, - moveSessionToProject: async () => {}, - removeSessionFromProject: async () => {}, + moveSessionToProject: async (sessionId, directory) => { + const session = sessions.find((item) => item.id === sessionId); + setSessionMeta((current) => { + const meta = createSessionProjectMoveMeta(session, current[sessionId], directory); + if (!meta) return current; + const next = { ...current, [sessionId]: { ...current[sessionId], ...meta } }; + persistSessionMetaMap(next); + return next; + }); + }, + removeSessionFromProject: async (sessionId) => { + const session = sessions.find((item) => item.id === sessionId); + setSessionMeta((current) => { + const meta = createSessionProjectDetachMeta(session, current[sessionId]); + if (!meta) return current; + const next = { ...current, [sessionId]: { ...current[sessionId], ...meta } }; + persistSessionMetaMap(next); + return next; + }); + }, setProjectPinned: (directory, pinned) => { const projectKey = makeProjectKey(activeWorkspaceId, directory); setProjectMeta((current) => {