From 5a39e69164af9a57eaf334a7b0e50d8c579ac7e1 Mon Sep 17 00:00:00 2001 From: Keith Guerin Date: Fri, 27 Mar 2026 20:58:51 -0700 Subject: [PATCH] feat(core): track shell cursor visibility in output events --- .../core/src/services/executionLifecycleService.ts | 1 + .../core/src/services/shellExecutionService.test.ts | 10 ++++++---- packages/core/src/services/shellExecutionService.ts | 13 ++++++++++++- 3 files changed, 19 insertions(+), 5 deletions(-) diff --git a/packages/core/src/services/executionLifecycleService.ts b/packages/core/src/services/executionLifecycleService.ts index 5efe26c375..d5c6b86a14 100644 --- a/packages/core/src/services/executionLifecycleService.ts +++ b/packages/core/src/services/executionLifecycleService.ts @@ -36,6 +36,7 @@ export type ExecutionOutputEvent = | { type: 'data'; chunk: string | AnsiOutput; + isCursorHidden?: boolean; } | { type: 'binary_detected'; diff --git a/packages/core/src/services/shellExecutionService.test.ts b/packages/core/src/services/shellExecutionService.test.ts index 465d79fe4b..afafe42fc7 100644 --- a/packages/core/src/services/shellExecutionService.test.ts +++ b/packages/core/src/services/shellExecutionService.test.ts @@ -299,10 +299,12 @@ describe('ShellExecutionService', () => { expect(result.output.trim()).toBe('file1.txt'); expect(handle.pid).toBe(12345); - expect(onOutputEventMock).toHaveBeenCalledWith({ - type: 'data', - chunk: createExpectedAnsiOutput('file1.txt'), - }); + expect(onOutputEventMock).toHaveBeenCalledWith( + expect.objectContaining({ + type: 'data', + chunk: createExpectedAnsiOutput('file1.txt'), + }), + ); }); it('should strip ANSI color codes from output', async () => { diff --git a/packages/core/src/services/shellExecutionService.ts b/packages/core/src/services/shellExecutionService.ts index 6184354a2a..78c2fc803e 100644 --- a/packages/core/src/services/shellExecutionService.ts +++ b/packages/core/src/services/shellExecutionService.ts @@ -952,9 +952,13 @@ export class ShellExecutionService { if (output !== finalOutput) { output = finalOutput; + // eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-type-assertion + const isCursorHidden = (headlessTerminal as any)._core?.coreService + ?.isCursorHidden as boolean | undefined; const event: ShellOutputEvent = { type: 'data', chunk: finalOutput, + isCursorHidden, }; onOutputEvent(event); ExecutionLifecycleService.emitEvent(ptyPid, event); @@ -1303,7 +1307,14 @@ export class ShellExecutionService { startLine, endLine, ); - const event: ShellOutputEvent = { type: 'data', chunk: bufferData }; + // eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-type-assertion + const isCursorHidden = (activePty.headlessTerminal as any)._core + ?.coreService?.isCursorHidden as boolean | undefined; + const event: ShellOutputEvent = { + type: 'data', + chunk: bufferData, + isCursorHidden, + }; ExecutionLifecycleService.emitEvent(pid, event); } }