From 2c351726ae21a73ac0549500783d5a4de6394214 Mon Sep 17 00:00:00 2001 From: 0x1f99d Date: Wed, 11 Mar 2026 03:46:24 +1100 Subject: [PATCH] fix(contracts): align terminal restart input type across IPC, WS, and server (#597) --- apps/server/src/terminal/Layers/Manager.test.ts | 13 ++++++++++++- apps/server/src/terminal/Layers/Manager.ts | 6 ++++-- apps/server/src/terminal/Services/Manager.ts | 3 ++- packages/contracts/src/ipc.ts | 3 ++- packages/contracts/src/terminal.ts | 3 ++- 5 files changed, 22 insertions(+), 6 deletions(-) diff --git a/apps/server/src/terminal/Layers/Manager.test.ts b/apps/server/src/terminal/Layers/Manager.test.ts index 0d45bfcb294b9c7d24db8cd73f9845c98398ac1c..825bcbded39e6c6399085629221ea4a95acb1969 100644 --- a/apps/server/src/terminal/Layers/Manager.test.ts +++ b/apps/server/src/terminal/Layers/Manager.test.ts @@ -6,6 +6,7 @@ import { DEFAULT_TERMINAL_ID, type TerminalEvent, type TerminalOpenInput, + type TerminalRestartInput, } from "@t3tools/contracts"; import { afterEach, describe, expect, it } from "vitest"; @@ -134,6 +135,16 @@ function openInput(overrides: Partial = {}): TerminalOpenInpu }; } +function restartInput(overrides: Partial = {}): TerminalRestartInput { + return { + threadId: "thread-1", + cwd: process.cwd(), + cols: 100, + rows: 24, + ...overrides, + }; +} + function historyLogName(threadId: string): string { return `terminal_${Encoding.encodeBase64Url(threadId)}.log`; } @@ -361,7 +372,7 @@ describe("TerminalManager", () => { firstProcess.emitData("before restart\n"); await waitFor(() => fs.existsSync(historyLogPath(logsDir))); - const snapshot = await manager.restart(openInput()); + const snapshot = await manager.restart(restartInput()); expect(snapshot.history).toBe(""); expect(snapshot.status).toBe("running"); expect(ptyAdapter.spawnInputs).toHaveLength(2); diff --git a/apps/server/src/terminal/Layers/Manager.ts b/apps/server/src/terminal/Layers/Manager.ts index 771c56b287e83bfc907daece15e37f55e1e682ef..f84e7b5930d292d5a7ec83c84affa4dd3df4706d 100644 --- a/apps/server/src/terminal/Layers/Manager.ts +++ b/apps/server/src/terminal/Layers/Manager.ts @@ -8,6 +8,7 @@ import { TerminalCloseInput, TerminalOpenInput, TerminalResizeInput, + TerminalRestartInput, TerminalWriteInput, type TerminalEvent, type TerminalSessionSnapshot, @@ -37,6 +38,7 @@ const DEFAULT_OPEN_ROWS = 30; const TERMINAL_ENV_BLOCKLIST = new Set(["PORT", "ELECTRON_RENDERER_PORT", "ELECTRON_RUN_AS_NODE"]); const decodeTerminalOpenInput = Schema.decodeUnknownSync(TerminalOpenInput); +const decodeTerminalRestartInput = Schema.decodeUnknownSync(TerminalRestartInput); const decodeTerminalWriteInput = Schema.decodeUnknownSync(TerminalWriteInput); const decodeTerminalResizeInput = Schema.decodeUnknownSync(TerminalResizeInput); const decodeTerminalClearInput = Schema.decodeUnknownSync(TerminalClearInput); @@ -478,8 +480,8 @@ export class TerminalManagerRuntime extends EventEmitter }); } - async restart(raw: TerminalOpenInput): Promise { - const input = decodeTerminalOpenInput(raw); + async restart(raw: TerminalRestartInput): Promise { + const input = decodeTerminalRestartInput(raw); return this.runWithThreadLock(input.threadId, async () => { await this.assertValidCwd(input.cwd); diff --git a/apps/server/src/terminal/Services/Manager.ts b/apps/server/src/terminal/Services/Manager.ts index 9cff3239919ad6b336a4ba9d2c776773d56b7c84..8d8398c7adb57e603ffe2881259aec482c62ba8e 100644 --- a/apps/server/src/terminal/Services/Manager.ts +++ b/apps/server/src/terminal/Services/Manager.ts @@ -12,6 +12,7 @@ import { TerminalEvent, TerminalOpenInput, TerminalResizeInput, + TerminalRestartInput, TerminalSessionSnapshot, TerminalSessionStatus, TerminalWriteInput, @@ -88,7 +89,7 @@ export interface TerminalManagerShape { * Always resets history before spawning the new process. */ readonly restart: ( - input: TerminalOpenInput, + input: TerminalRestartInput, ) => Effect.Effect; /** diff --git a/packages/contracts/src/ipc.ts b/packages/contracts/src/ipc.ts index 4c93970fcc34a5d9c1197d3cecd146e782bf6bc8..b69bacdd4f274d782d4012e6988400a8ccee5728 100644 --- a/packages/contracts/src/ipc.ts +++ b/packages/contracts/src/ipc.ts @@ -31,6 +31,7 @@ import type { TerminalEvent, TerminalOpenInput, TerminalResizeInput, + TerminalRestartInput, TerminalSessionSnapshot, TerminalWriteInput, } from "./terminal"; @@ -118,7 +119,7 @@ export interface NativeApi { write: (input: TerminalWriteInput) => Promise; resize: (input: TerminalResizeInput) => Promise; clear: (input: TerminalClearInput) => Promise; - restart: (input: TerminalOpenInput) => Promise; + restart: (input: TerminalRestartInput) => Promise; close: (input: TerminalCloseInput) => Promise; onEvent: (callback: (event: TerminalEvent) => void) => () => void; }; diff --git a/packages/contracts/src/terminal.ts b/packages/contracts/src/terminal.ts index e7c20242b1f00450c243f7bd1c704c31735da37c..b0493d95c2aba9d3ee30b24b9f5b64fd02fa1aba 100644 --- a/packages/contracts/src/terminal.ts +++ b/packages/contracts/src/terminal.ts @@ -60,12 +60,13 @@ export const TerminalClearInput = TerminalSessionInput; export type TerminalClearInput = Schema.Codec.Encoded; export const TerminalRestartInput = Schema.Struct({ - ...TerminalThreadInput.fields, + ...TerminalSessionInput.fields, cwd: TrimmedNonEmptyStringSchema, cols: TerminalColsSchema, rows: TerminalRowsSchema, env: Schema.optional(TerminalEnvSchema), }); +export type TerminalRestartInput = Schema.Codec.Encoded; export const TerminalCloseInput = Schema.Struct({ ...TerminalThreadInput.fields, -- 2.54.0