diff --git a/src/renderer/src/lib/structured-agent-session-empty-chat-reuse.test.ts b/src/renderer/src/lib/structured-agent-session-empty-chat-reuse.test.ts index 5ca6ee99f6c..67b3671e105 100644 --- a/src/renderer/src/lib/structured-agent-session-empty-chat-reuse.test.ts +++ b/src/renderer/src/lib/structured-agent-session-empty-chat-reuse.test.ts @@ -113,10 +113,8 @@ import { clearNativeChatDraftCacheForTests, writeNativeChatDraftCache } from '@/components/native-chat/native-chat-draft-cache' -import { - structuredAgentSessionPaneKey, - structuredAgentSessionTabId -} from '../../../shared/structured-agent-session-projection' +import { structuredAgentSessionTabId } from '../../../shared/structured-agent-session-projection' +import { structuredAgentSessionDraftScopeKey } from '@/components/native-chat/native-chat-composer-draft-store' import { adoptAgentSessionLaunchVerdict } from './agent-session-launch-plan' import { beginStructuredAgentSessionProvisionalLaunch, @@ -279,8 +277,8 @@ describe('a second "new chat" with no text', () => { it('opens a new chat when the idle chat has a typed draft', async () => { pick('plus-pick-1') await publishIdle(first.sessionId) - const tabId = structuredAgentSessionTabId(first.sessionId) - writeNativeChatDraftCache(structuredAgentSessionPaneKey(tabId, first.sessionId), 'half a q') + // Under the conversation's key, which the composer and every hand-back write. + writeNativeChatDraftCache(structuredAgentSessionDraftScopeKey(first.sessionId), 'half a q') expect(pick('plus-pick-2').sessionId).toBe(second.sessionId) }) @@ -288,8 +286,7 @@ describe('a second "new chat" with no text', () => { it('opens a new chat when the idle chat has an image in its composer', async () => { pick('plus-pick-1') await publishIdle(first.sessionId) - const tabId = structuredAgentSessionTabId(first.sessionId) - appendNativeChatAttachmentCache(structuredAgentSessionPaneKey(tabId, first.sessionId), [ + appendNativeChatAttachmentCache(structuredAgentSessionDraftScopeKey(first.sessionId), [ { id: 'shot', path: '/tmp/shot.png' } ]) @@ -484,6 +481,15 @@ describe('a "new chat" with text', () => { ) }) + it('leaves a starting chat whose draft holds text, given back or typed, to its user', () => { + mocks.launch.mockImplementation(() => new Promise(() => undefined)) + const blank = pick('plus-pick-1') + writeNativeChatDraftCache(structuredAgentSessionDraftScopeKey(blank.sessionId), 'my words') + + expect(pick('notes-send', { prompt: 'review notes' }).sessionId).toBe(second.sessionId) + expect(readOutbox(blank.sessionId)).toEqual([]) + }) + it('takes an empty chat still starting, as before', () => { mocks.launch.mockImplementation(() => new Promise(() => undefined)) const blank = pick('plus-pick-1') diff --git a/src/renderer/src/lib/structured-agent-session-launch-different-request.test.ts b/src/renderer/src/lib/structured-agent-session-launch-different-request.test.ts index 253a91c85bf..338e5ec8ad6 100644 --- a/src/renderer/src/lib/structured-agent-session-launch-different-request.test.ts +++ b/src/renderer/src/lib/structured-agent-session-launch-different-request.test.ts @@ -67,10 +67,7 @@ import { readNativeChatDraftCache, writeNativeChatDraftCache } from '@/components/native-chat/native-chat-draft-cache' -import { - structuredAgentSessionPaneKey, - structuredAgentSessionTabId -} from '../../../shared/structured-agent-session-projection' +import { structuredAgentSessionDraftScopeKey } from '@/components/native-chat/native-chat-composer-draft-store' import { StructuredAgentSessionCreateRefusalError } from '@/lib/launch-structured-agent-session' import { getStructuredAgentSessionLaunchLifecycle, @@ -520,10 +517,8 @@ describe('an empty chat still starting', () => { it('leaves a chat its user is typing into to them, and opens a new chat for the notes', async () => { const blank = startStructuredAgentLaunch(WORKTREE_ID, 'codex', { requestId: 'plus-pick' }) - const paneKey = structuredAgentSessionPaneKey( - structuredAgentSessionTabId(blank.sessionId), - blank.sessionId - ) + // The conversation's draft, which its composer writes. + const paneKey = structuredAgentSessionDraftScopeKey(blank.sessionId) writeNativeChatDraftCache(paneKey, 'half a question') const notes = startStructuredAgentLaunch(WORKTREE_ID, 'codex', notesSend) diff --git a/src/renderer/src/lib/structured-agent-session-launch-empty-chat.ts b/src/renderer/src/lib/structured-agent-session-launch-empty-chat.ts index 1d11c7b03d4..2f8b15d91ef 100644 --- a/src/renderer/src/lib/structured-agent-session-launch-empty-chat.ts +++ b/src/renderer/src/lib/structured-agent-session-launch-empty-chat.ts @@ -1,19 +1,19 @@ -import { - structuredAgentSessionPaneKey, - structuredAgentSessionTabId -} from '../../../shared/structured-agent-session-projection' import { getStructuredAgentSessionOutbox } from '@/components/native-chat/structured-agent-session-outbox-storage' import { readNativeChatDraftCache } from '@/components/native-chat/native-chat-draft-cache' // The draft store, not the composer hook: the launch must not load the composer (a store cycle). -import { readNativeChatComposerDraft } from '@/components/native-chat/native-chat-composer-draft-store' +import { + readNativeChatComposerDraft, + structuredAgentSessionDraftScopeKey +} from '@/components/native-chat/native-chat-composer-draft-store' -/** A starting chat is empty until its user sends into it or puts text or images in its composer; - * after that it is theirs, and another request never goes into it. */ +/** A starting chat is empty until its user sends into it or puts text or images in its draft (typed, + * or given back); after that it is theirs, and another request never goes into it. Read by the + * conversation's key, which the composer and every hand-back write. */ export function isStructuredLaunchChatEmpty(sessionId: string): boolean { - const paneKey = structuredAgentSessionPaneKey(structuredAgentSessionTabId(sessionId), sessionId) + const scopeKey = structuredAgentSessionDraftScopeKey(sessionId) return ( getStructuredAgentSessionOutbox(sessionId).length === 0 && - readNativeChatDraftCache(paneKey).trim() === '' && - readNativeChatComposerDraft(paneKey).images.length === 0 + readNativeChatDraftCache(scopeKey).trim() === '' && + readNativeChatComposerDraft(scopeKey).images.length === 0 ) }