From a649ba8df49dae7fc96dc90efc71bed725e91113 Mon Sep 17 00:00:00 2001 From: Bohdan Triapitsyn Date: Wed, 3 Jun 2026 14:36:59 +0300 Subject: [PATCH] fix: unblock initial new session prompts --- .../lib/worktrees/worktreeBootstrap.test.ts | 53 +++++++++++++++++++ .../ui/src/lib/worktrees/worktreeBootstrap.ts | 4 ++ packages/ui/src/sync/session-ui-store.ts | 22 ++++---- 3 files changed, 66 insertions(+), 13 deletions(-) create mode 100644 packages/ui/src/lib/worktrees/worktreeBootstrap.test.ts diff --git a/packages/ui/src/lib/worktrees/worktreeBootstrap.test.ts b/packages/ui/src/lib/worktrees/worktreeBootstrap.test.ts new file mode 100644 index 00000000..4d11ec48 --- /dev/null +++ b/packages/ui/src/lib/worktrees/worktreeBootstrap.test.ts @@ -0,0 +1,53 @@ +import { beforeEach, describe, expect, mock, test } from 'bun:test'; + +const bootstrapStatusCalls: string[] = []; +let bootstrapStatusResult = { status: 'ready' as const, error: null, updatedAt: 1 }; + +mock.module('@/contexts/runtimeAPIRegistry', () => ({ + getRegisteredRuntimeAPIs: () => ({ + git: { + worktree: { + bootstrapStatus: (directory: string) => { + bootstrapStatusCalls.push(directory); + return Promise.resolve(bootstrapStatusResult); + }, + }, + }, + }), +})); + +mock.module('@/lib/gitApiHttp', () => ({ + getGitWorktreeBootstrapStatus: (directory: string) => { + bootstrapStatusCalls.push(directory); + return Promise.resolve(bootstrapStatusResult); + }, +})); + +const { + clearWorktreeBootstrapState, + markWorktreeBootstrapPending, + waitForWorktreeBootstrap, +} = await import('./worktreeBootstrap'); + +describe('worktreeBootstrap.waitForWorktreeBootstrap', () => { + beforeEach(() => { + bootstrapStatusCalls.length = 0; + bootstrapStatusResult = { status: 'ready', error: null, updatedAt: 1 }; + clearWorktreeBootstrapState('/repo'); + clearWorktreeBootstrapState('/repo-wt'); + }); + + test('does not poll directories that were not marked pending', async () => { + await waitForWorktreeBootstrap('/repo'); + + expect(bootstrapStatusCalls).toEqual([]); + }); + + test('polls when the directory was explicitly marked pending', async () => { + markWorktreeBootstrapPending('/repo-wt'); + + await waitForWorktreeBootstrap('/repo-wt'); + + expect(bootstrapStatusCalls).toEqual(['/repo-wt']); + }); +}); diff --git a/packages/ui/src/lib/worktrees/worktreeBootstrap.ts b/packages/ui/src/lib/worktrees/worktreeBootstrap.ts index 49ad74ed..ab531afd 100644 --- a/packages/ui/src/lib/worktrees/worktreeBootstrap.ts +++ b/packages/ui/src/lib/worktrees/worktreeBootstrap.ts @@ -93,6 +93,10 @@ export const waitForWorktreeBootstrap = async (directory: string, timeoutMs = DE } const current = state.get(key); + if (!current) { + return; + } + if (current?.status === 'ready') { return; } diff --git a/packages/ui/src/sync/session-ui-store.ts b/packages/ui/src/sync/session-ui-store.ts index 04ad8849..83c8fd13 100644 --- a/packages/ui/src/sync/session-ui-store.ts +++ b/packages/ui/src/sync/session-ui-store.ts @@ -832,28 +832,24 @@ export const useSessionUIStore = create()((set, get) => ({ }) const draftSyntheticParts = draft.syntheticParts - await activateConfigForDirectory(draftDirectoryOverride ?? created.directory ?? null) - + const createdDirectory = normalizePath(draftDirectoryOverride ?? created.directory ?? null) const configState = useConfigStore.getState() - const draftAgentName = configState.currentAgentName - const effectiveDraftAgent = trimmedAgent ?? draftAgentName + void activateConfigForDirectory(createdDirectory).catch((error) => { + console.warn("Failed to activate directory after creating session:", error) + }) - if (configState.currentProviderId && configState.currentModelId) { - useSelectionStore.getState().saveSessionModelSelection(created.id, configState.currentProviderId, configState.currentModelId) - } + const effectiveDraftAgent = trimmedAgent ?? configState.currentAgentName + + useSelectionStore.getState().saveSessionModelSelection(created.id, providerID, modelID) if (effectiveDraftAgent) { useSelectionStore.getState().saveSessionAgentSelection(created.id, effectiveDraftAgent) - if (configState.currentProviderId && configState.currentModelId) { - useSelectionStore.getState().saveAgentModelForSession(created.id, effectiveDraftAgent, configState.currentProviderId, configState.currentModelId) - useSelectionStore.getState().saveAgentModelVariantForSession(created.id, effectiveDraftAgent, configState.currentProviderId, configState.currentModelId, variant) - } + useSelectionStore.getState().saveAgentModelForSession(created.id, effectiveDraftAgent, providerID, modelID) + useSelectionStore.getState().saveAgentModelVariantForSession(created.id, effectiveDraftAgent, providerID, modelID, variant) } get().initializeNewOpenChamberSession(created.id, configState.agents ?? []) - const createdDirectory = normalizePath(draftDirectoryOverride ?? created.directory ?? null) - get().closeNewSessionDraft() get().setCurrentSession(created.id, createdDirectory)