From f2853490de6cfb7fb7f908384526deef0e7dca48 Mon Sep 17 00:00:00 2001 From: Iuliia Ivashko Date: Fri, 4 Sep 2026 07:10:23 +0300 Subject: [PATCH] fix(ui): open a chat draft when a chat scratch directory is forwarded 'New session in the current directory' callers (shortcut, menu, composer) forward the current session's directory even when that session is a chat. Its managed scratch directory names no project, but it counted as an explicit project target, so a plus pressed inside a chat session opened a project draft. Chat scratch overrides now resolve to a chat draft. --- packages/ui/src/sync/session-ui-store.test.js | 26 +++++++++++++++++++ packages/ui/src/sync/session-ui-store.ts | 10 +++++-- 2 files changed, 34 insertions(+), 2 deletions(-) diff --git a/packages/ui/src/sync/session-ui-store.test.js b/packages/ui/src/sync/session-ui-store.test.js index 9e088bcf..2ec9930c 100644 --- a/packages/ui/src/sync/session-ui-store.test.js +++ b/packages/ui/src/sync/session-ui-store.test.js @@ -592,6 +592,32 @@ describe('openNewSessionDraft project binding', () => { expect(useSessionUIStore.getState().newSessionDraft.target).toBe('chat'); }); + test('a chat scratch directory forwarded as override opens a chat draft', () => { + // "New session in the current directory" callers forward the current + // session's directory even when that session is a chat; its scratch + // directory names no project. + useSessionUIStore.getState().openNewSessionDraft({ + directoryOverride: '/Users/tester/.config/openchamber/chats/ses_chat', + }); + const draft = useSessionUIStore.getState().newSessionDraft; + + expect(draft.target).toBe('chat'); + expect(draft.directoryOverride).toBeNull(); + }); + + test('a chat scratch override opens Chat even when the recorded target is a project', () => { + getDeferredSafeStorage().setItem( + DRAFT_TARGET_KEY, + JSON.stringify({ projectId: projectB.id, directory: projectB.path, target: 'project' }), + ); + + useSessionUIStore.getState().openNewSessionDraft({ + directoryOverride: '/Users/tester/.config/openchamber/chats/ses_chat', + }); + + expect(useSessionUIStore.getState().newSessionDraft.target).toBe('chat'); + }); + test('falls back to Chat when the last project target no longer exists', () => { getDeferredSafeStorage().setItem( DRAFT_TARGET_KEY, diff --git a/packages/ui/src/sync/session-ui-store.ts b/packages/ui/src/sync/session-ui-store.ts index 2f31b09a..d73613a5 100644 --- a/packages/ui/src/sync/session-ui-store.ts +++ b/packages/ui/src/sync/session-ui-store.ts @@ -1115,9 +1115,15 @@ export const useSessionUIStore = create()((set, get) => ({ const currentDirectory = normalizePath(useDirectoryStore.getState().currentDirectory ?? null) const persistedTarget = readPersistedDraftTarget() - const explicitDirectory = options?.directoryOverride !== undefined + // Callers that forward "the current session's directory" forward it for + // chat sessions too, and a chat session's scratch directory names no + // project. Treating it as an explicit project target would force a project + // draft rooted in scratch; it is a request for another chat. + const rawExplicitDirectory = options?.directoryOverride !== undefined ? normalizePath(options.directoryOverride) : null + const explicitDirectoryIsChat = rawExplicitDirectory !== null && isChatDirectoryPath(rawExplicitDirectory) + const explicitDirectory = explicitDirectoryIsChat ? null : rawExplicitDirectory const persistedProjectById = persistedTarget?.projectId ? projects.find((p) => p.id === persistedTarget.projectId) ?? null : null @@ -1138,7 +1144,7 @@ export const useSessionUIStore = create()((set, get) => ({ let target = isVSCodeRuntime() ? "project" : options?.target if (!target) { - const hasExplicitProjectTarget = options?.directoryOverride !== undefined + const hasExplicitProjectTarget = (options?.directoryOverride !== undefined && !explicitDirectoryIsChat) || (options?.selectedProjectId !== undefined && options.selectedProjectId !== CHAT_DRAFT_PROJECT_ID) || isVSCodeRuntime() target = options?.selectedProjectId === CHAT_DRAFT_PROJECT_ID