authorgravatar for julius0216@outlook.comJulius Marminge <julius0216@outlook.com> 2026-02-12 21:17:11-08:00
committergravatar for jmarminge@gmail.comJulius Marminge <jmarminge@gmail.com> 2026-02-12 22:20:01-08:00
log901579233cf0c846abcd9622f1443db6d3bb5834
tree8c3e04ec01a2476b890ff962826f92571eb884d4
parentd27b08bae68ac514f5f3a497bc4aa91c0cbfc101

Close terminal session when hiding terminal panel

- Attempt `api.terminal.close` when toggling an open terminal off - Fall back to sending `exit` if close is unavailable or fails - Include `api` in callback dependencies to keep behavior current

1 files changed, 16 insertions(+), 13 deletions(-)

apps/web/src/components/ChatView.tsx+16-13
...@@ -263,12 +263,23 @@ export default function ChatView() {...@@ -263,12 +263,23 @@ export default function ChatView() {
263 const toggleTerminalVisibility = useCallback(() => {263 const toggleTerminalVisibility = useCallback(() => {
264 if (!activeThreadId) return;264 if (!activeThreadId) return;
265 const isOpen = Boolean(activeThread?.terminalOpen);265 const isOpen = Boolean(activeThread?.terminalOpen);
266
267 if (isOpen && api) {
268 if (typeof api.terminal.close === "function") {
269 void api.terminal.close({ threadId: activeThreadId }).catch(() => {
270 void api.terminal.write({ threadId: activeThreadId, data: "exit\n" }).catch(() => undefined);
271 });
272 } else {
273 void api.terminal.write({ threadId: activeThreadId, data: "exit\n" }).catch(() => undefined);
274 }
275 }
276
266 dispatch({277 dispatch({
267 type: "SET_THREAD_TERMINAL_OPEN",278 type: "SET_THREAD_TERMINAL_OPEN",
268 threadId: activeThreadId,279 threadId: activeThreadId,
269 open: !isOpen,280 open: !isOpen,
270 });281 });
271 }, [activeThread?.terminalOpen, activeThreadId, dispatch]);282 }, [activeThread?.terminalOpen, activeThreadId, api, dispatch]);
272 const splitTerminal = useCallback(() => {283 const splitTerminal = useCallback(() => {
273 if (!activeThreadId) return;284 if (!activeThreadId) return;
274 dispatch({285 dispatch({
...@@ -303,21 +314,13 @@ export default function ChatView() {...@@ -303,21 +314,13 @@ export default function ChatView() {
303 (terminalId: string) => {314 (terminalId: string) => {
304 if (!activeThreadId || !api) return;315 if (!activeThreadId || !api) return;
305 const fallbackExitWrite = () =>316 const fallbackExitWrite = () =>
306 api.terminal317 api.terminal.write({ threadId: activeThreadId, terminalId, data: "exit\n" }).catch(() => undefined);
307 .write({ threadId: activeThreadId, terminalId, data: "exit\n" })
308 .catch(() => undefined);
309 const fallbackClearAndExit = () =>
310 api.terminal
311 .clear({ threadId: activeThreadId, terminalId })
312 .catch(() => undefined)
313 .then(() => fallbackExitWrite())
314 .catch(() => undefined);
315 if ("close" in api.terminal && typeof api.terminal.close === "function") {318 if ("close" in api.terminal && typeof api.terminal.close === "function") {
316 void api.terminal319 void api.terminal
317 .close({ threadId: activeThreadId, terminalId, deleteHistory: true })320 .close({ threadId: activeThreadId, terminalId })
318 .catch(() => fallbackClearAndExit());321 .catch(() => fallbackExitWrite());
319 } else {322 } else {
320 void fallbackClearAndExit();323 void fallbackExitWrite();
321 }324 }
322 dispatch({325 dispatch({
323 type: "CLOSE_THREAD_TERMINAL",326 type: "CLOSE_THREAD_TERMINAL",