diff --git a/src/renderer/src/runtime/sync-runtime-graph.test.ts b/src/renderer/src/runtime/sync-runtime-graph.test.ts index f406974bd77..76872153159 100644 --- a/src/renderer/src/runtime/sync-runtime-graph.test.ts +++ b/src/renderer/src/runtime/sync-runtime-graph.test.ts @@ -726,6 +726,38 @@ describe('buildMobileSessionTabSnapshots', () => { ]) }) + it('withholds a launch draft seeded for a different agent than the tab runs', () => { + // The seed is keyed by tab id, which survives an agent switch. Desktop's + // consumer declines on mismatch; publishing anyway would prefill the new + // agent's mobile chat with the previous agent's link. + const leafId = '11111111-1111-4111-8111-111111111111' + const state = makeState({ + tabsByWorktree: { + 'wt-1': [{ id: 'term-1', title: 'Terminal 1', launchAgent: 'codex' }] + } as unknown as AppState['tabsByWorktree'], + terminalLayoutsByTabId: { + 'term-1': { + root: { type: 'leaf', leafId }, + activeLeafId: leafId, + expandedLeafId: null, + ptyIdsByLeafId: { [leafId]: 'pty-1' } + } + } as unknown as AppState['terminalLayoutsByTabId'], + nativeChatLaunchDraftByTabId: { + 'term-1': { + tabId: 'term-1', + agent: 'claude', + text: 'https://github.com/o/r/issues/12', + createdAt: 1 + } + } + }) + + const snapshot = buildMobileSessionTabSnapshots(state)[0] + + expect(snapshot?.tabs[0]).not.toHaveProperty('launchDraft') + }) + it('preserves source-control diff metadata for mobile file tabs', () => { const diffId = 'wt-1::diff::unstaged::src/app.ts' const state = makeState({ diff --git a/src/renderer/src/runtime/sync-runtime-graph.ts b/src/renderer/src/runtime/sync-runtime-graph.ts index d4afaec979b..33cb27ed74a 100644 --- a/src/renderer/src/runtime/sync-runtime-graph.ts +++ b/src/renderer/src/runtime/sync-runtime-graph.ts @@ -1367,9 +1367,12 @@ function buildMobileTerminalSurfaceTabs( : undefined const savedPtyIdsByLeafId = sanitizedSavedLayout?.ptyIdsByLeafId ?? {} const terminalTheme = resolveMobileTerminalTheme(state, systemPrefersDark) - const launchDraftText = state.nativeChatLaunchDraftByTabId?.[terminal.id]?.text.trim() - ? state.nativeChatLaunchDraftByTabId[terminal.id].text - : null + // Agent-matched like the desktop consumer: a pane whose agent changed keeps its + // tab id, so an unmatched seed would prefill the new agent's chat with stale text. + const seededLaunchDraft = state.nativeChatLaunchDraftByTabId?.[terminal.id] + const launchDraftEntry = + seededLaunchDraft && seededLaunchDraft.agent === terminal.launchAgent ? seededLaunchDraft : null + const launchDraftText = launchDraftEntry?.text.trim() ? launchDraftEntry.text : null const container = registered?.getContainer() const firstChild = container?.firstElementChild const liveLayoutRoot = serializePaneTree(