Skip to content

Commit 67b21f5

Browse files
committed
Merge branch 'closing-processes'
2 parents b3c8fdf + c4192e0 commit 67b21f5

3 files changed

Lines changed: 34 additions & 4 deletions

File tree

src/App.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -173,6 +173,7 @@ function App() {
173173
setActiveTab: setActiveSessionTab,
174174
reorderTabs: reorderSessionTabs,
175175
incrementCounter: incrementSessionCounter,
176+
setPtyId: setSessionPtyId,
176177
removePtyId: removeSessionPtyId,
177178
setLastActiveTabId,
178179
updateTabLabel: updateSessionTabLabel,
@@ -3358,6 +3359,7 @@ function App() {
33583359
onScratchCwdChange={handleScratchCwdChange}
33593360
onClearNotification={clearNotification}
33603361
onTabTitleChange={updateSessionTabLabel}
3362+
onPtyIdReady={setSessionPtyId}
33613363
/>
33623364
</div>
33633365
</Panel>

src/components/MainPane/MainPane.tsx

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,8 @@ interface MainPaneProps {
4040
onClearNotification?: (sessionId: string) => void;
4141
onCwdChange?: (sessionId: string, cwd: string) => void;
4242
onTabTitleChange?: (sessionId: string, tabId: string, title: string) => void;
43+
/** Called when a tab's PTY is spawned (for cleanup tracking) */
44+
onPtyIdReady?: (tabId: string, ptyId: string) => void;
4345

4446
// Legacy props for backward compatibility during migration
4547
openWorktreeIds?: Set<string>;
@@ -92,6 +94,7 @@ export function MainPane({
9294
onClearNotification,
9395
onCwdChange,
9496
onTabTitleChange,
97+
onPtyIdReady,
9598
// Legacy props
9699
onWorktreeNotification,
97100
onWorktreeThinkingChange,
@@ -363,6 +366,7 @@ export function MainPane({
363366
onFocus={() => onFocus(session.id, tab.id)}
364367
onTitleChange={handleTitleChange}
365368
onClose={() => onCloseSessionTab(tab.id)}
369+
onPtyIdReady={(ptyId) => onPtyIdReady?.(tab.id, ptyId)}
366370
/>
367371
);
368372
} else {
@@ -383,6 +387,7 @@ export function MainPane({
383387
onThinkingChange={handleThinkingChange}
384388
onCwdChange={handleCwdChange}
385389
onTitleChange={handleTitleChange}
390+
onPtyIdReady={(ptyId) => onPtyIdReady?.(tab.id, ptyId)}
386391
/>
387392
);
388393
}

src/components/MainPane/MainTerminal.tsx

Lines changed: 27 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -51,9 +51,11 @@ interface MainTerminalProps {
5151
onCwdChange?: (cwd: string) => void;
5252
/** Called when terminal title changes (via OSC escape codes) */
5353
onTitleChange?: (title: string) => void;
54+
/** Called when PTY is spawned with the PTY ID (for cleanup tracking) */
55+
onPtyIdReady?: (ptyId: string) => void;
5456
}
5557

56-
export function MainTerminal({ entityId, sessionId, type = 'main', isActive, shouldAutoFocus, focusTrigger, terminalConfig, activityTimeout = 250, initialCwd, onFocus, onNotification, onThinkingChange, onCwdChange, onTitleChange }: MainTerminalProps) {
58+
export function MainTerminal({ entityId, sessionId, type = 'main', isActive, shouldAutoFocus, focusTrigger, terminalConfig, activityTimeout = 250, initialCwd, onFocus, onNotification, onThinkingChange, onCwdChange, onTitleChange, onPtyIdReady }: MainTerminalProps) {
5759
// Use sessionId for spawn if provided, otherwise fall back to entityId (for backward compatibility)
5860
const spawnId = sessionId ?? entityId;
5961
const containerRef = useRef<HTMLDivElement>(null);
@@ -220,6 +222,12 @@ export function MainTerminal({ entityId, sessionId, type = 'main', isActive, sho
220222
onTitleChangeRef.current = onTitleChange;
221223
}, [onTitleChange]);
222224

225+
// Store onPtyIdReady in ref so spawn handlers can access the latest version
226+
const onPtyIdReadyRef = useRef(onPtyIdReady);
227+
useEffect(() => {
228+
onPtyIdReadyRef.current = onPtyIdReady;
229+
}, [onPtyIdReady]);
230+
223231
// Progress indicator logic:
224232
// - Activity (output/title): start timer, reset on more activity, turn off when timer expires
225233
// - OSC 9 progress: explicit start/stop (no timeout)
@@ -470,7 +478,12 @@ export function MainTerminal({ entityId, sessionId, type = 'main', isActive, sho
470478

471479
spawnedAtRef.current = Date.now();
472480
// Pass initialCwd for scratch terminals to start in the specified directory
473-
await spawnRef.current(spawnId, type, cols, rows, type === 'scratch' ? initialCwd : undefined);
481+
const newPtyId = await spawnRef.current(spawnId, type, cols, rows, type === 'scratch' ? initialCwd : undefined);
482+
483+
// Notify parent of the PTY ID for cleanup tracking
484+
if (newPtyId && isMounted) {
485+
onPtyIdReadyRef.current?.(newPtyId);
486+
}
474487

475488
// For project type, mark as ready immediately (no startup delay like main command)
476489
if (type === 'project' && isMounted) {
@@ -543,7 +556,12 @@ export function MainTerminal({ entityId, sessionId, type = 'main', isActive, sho
543556
const cols = terminal.cols;
544557
const rows = terminal.rows;
545558
spawnedAtRef.current = Date.now();
546-
await spawn(spawnId, currentMode, cols, rows);
559+
const newPtyId = await spawn(spawnId, currentMode, cols, rows);
560+
561+
// Notify parent of the new PTY ID for cleanup tracking
562+
if (newPtyId) {
563+
onPtyIdReadyRef.current?.(newPtyId);
564+
}
547565
}, [spawn, spawnId, currentMode]);
548566

549567
// Launch shell handler for when the user wants a shell instead of the main command
@@ -571,7 +589,12 @@ export function MainTerminal({ entityId, sessionId, type = 'main', isActive, sho
571589
const cols = terminal.cols;
572590
const rows = terminal.rows;
573591
spawnedAtRef.current = Date.now();
574-
await spawn(spawnId, 'shell', cols, rows);
592+
const newPtyId = await spawn(spawnId, 'shell', cols, rows);
593+
594+
// Notify parent of the new PTY ID for cleanup tracking
595+
if (newPtyId) {
596+
onPtyIdReadyRef.current?.(newPtyId);
597+
}
575598
}, [spawn, spawnId]);
576599

577600
// Store resize function in ref to avoid dependency issues

0 commit comments

Comments
 (0)