From cac24863a04779529893b4e1713bf1144fe95bea Mon Sep 17 00:00:00 2001 From: karashiiro <49822414+karashiiro@users.noreply.github.com> Date: Sun, 4 Jan 2026 16:15:34 -0800 Subject: [PATCH] Allow writing to stdout from IPC adapter --- .../adapter/src/__tests__/ipc.test.ts | 18 ++++++++------ .../adapter/src/__tests__/sdk-adapter.test.ts | 24 +++++++++++-------- backend/packages/adapter/src/ipc.ts | 5 +++- 3 files changed, 29 insertions(+), 18 deletions(-) diff --git a/backend/packages/adapter/src/__tests__/ipc.test.ts b/backend/packages/adapter/src/__tests__/ipc.test.ts index 6f7d2f9..1ba1e29 100644 --- a/backend/packages/adapter/src/__tests__/ipc.test.ts +++ b/backend/packages/adapter/src/__tests__/ipc.test.ts @@ -1,20 +1,24 @@ import { describe, expect, it, mock, spyOn, beforeEach, afterEach } from 'bun:test'; -// Mock console.log to capture emit output +// Mock process.stdout.write to capture emit output describe('IPC Layer', () => { - let originalLog: typeof console.log; + let originalWrite: typeof process.stdout.write; let logOutput: string[] = []; beforeEach(() => { - originalLog = console.log; + originalWrite = process.stdout.write.bind(process.stdout); logOutput = []; - console.log = (...args: unknown[]) => { - logOutput.push(args.map(String).join(' ')); - }; + process.stdout.write = ((chunk: string | Uint8Array) => { + if (typeof chunk === 'string') { + // Remove trailing newline for easier testing + logOutput.push(chunk.replace(/\n$/, '')); + } + return true; + }) as typeof process.stdout.write; }); afterEach(() => { - console.log = originalLog; + process.stdout.write = originalWrite; }); describe('emit', () => { diff --git a/backend/packages/adapter/src/__tests__/sdk-adapter.test.ts b/backend/packages/adapter/src/__tests__/sdk-adapter.test.ts index 66c9e95..d4209e8 100644 --- a/backend/packages/adapter/src/__tests__/sdk-adapter.test.ts +++ b/backend/packages/adapter/src/__tests__/sdk-adapter.test.ts @@ -1,24 +1,28 @@ import { describe, expect, it, beforeEach, afterEach, mock } from 'bun:test'; import { PROTOCOL_VERSION, ErrorCodes } from '@tiny-workshop/ipc-types'; -// Capture emitted messages +// Capture emitted messages via process.stdout.write let emittedMessages: unknown[] = []; -let originalLog: typeof console.log; +let originalWrite: typeof process.stdout.write; beforeEach(() => { emittedMessages = []; - originalLog = console.log; - console.log = (...args: unknown[]) => { - try { - emittedMessages.push(JSON.parse(args[0] as string)); - } catch { - // Not JSON, ignore + originalWrite = process.stdout.write.bind(process.stdout); + process.stdout.write = ((chunk: string | Uint8Array) => { + if (typeof chunk === 'string') { + try { + // Remove trailing newline and parse JSON + emittedMessages.push(JSON.parse(chunk.replace(/\n$/, ''))); + } catch { + // Not JSON, ignore + } } - }; + return true; + }) as typeof process.stdout.write; }); afterEach(() => { - console.log = originalLog; + process.stdout.write = originalWrite; }); describe('SdkAdapter', () => { diff --git a/backend/packages/adapter/src/ipc.ts b/backend/packages/adapter/src/ipc.ts index 66fc66a..2c101e1 100644 --- a/backend/packages/adapter/src/ipc.ts +++ b/backend/packages/adapter/src/ipc.ts @@ -7,9 +7,12 @@ import type { FrontendMessage, BackendMessage } from '@tiny-workshop/ipc-types'; /** * Emit a message to the frontend via stdout + * + * Uses process.stdout.write directly to bypass stdout protection. + * This is the ONLY place that should write to stdout! */ export function emit(msg: BackendMessage): void { - console.log(JSON.stringify(msg)); + process.stdout.write(JSON.stringify(msg) + '\n'); } /** -- 2.51.2