From db4740136566f17b60a6f106db7e5bb3314fc219 Mon Sep 17 00:00:00 2001 From: marius-kilocode Date: Fri, 7 Aug 2026 12:59:23 +0200 Subject: [PATCH] test(pty): add end-to-end spawn dimension test and clarify docstrings --- .../src/agent-manager/terminal-manager.ts | 8 +++- .../agent-manager/terminal/state.ts | 6 +-- .../opencode/test/server/httpapi-pty.test.ts | 43 +++++++++++++++++++ 3 files changed, 53 insertions(+), 4 deletions(-) diff --git a/packages/kilo-vscode/src/agent-manager/terminal-manager.ts b/packages/kilo-vscode/src/agent-manager/terminal-manager.ts index 5436a6bd678..26677dc2d3e 100644 --- a/packages/kilo-vscode/src/agent-manager/terminal-manager.ts +++ b/packages/kilo-vscode/src/agent-manager/terminal-manager.ts @@ -117,7 +117,13 @@ export class TerminalManager { return { terminalId: params.terminalId, worktreeId: entry.worktreeId, title: entry.title, wsUrl } } - /** Forward a resize event to the backend PTY. Missing terminals are a no-op. */ + /** + * Forward a resize event to the backend PTY. + * + * If the terminal creation is still in flight, dimensions are queued into + * `pending` and applied during PTY initialization before the WebSocket + * URL is returned. + */ async resize(terminalId: string, cols: number, rows: number): Promise { const entry = this.entries.get(terminalId) if (!entry) { diff --git a/packages/kilo-vscode/webview-ui/agent-manager/terminal/state.ts b/packages/kilo-vscode/webview-ui/agent-manager/terminal/state.ts index 0a4ece9801b..dde770b4d48 100644 --- a/packages/kilo-vscode/webview-ui/agent-manager/terminal/state.ts +++ b/packages/kilo-vscode/webview-ui/agent-manager/terminal/state.ts @@ -628,9 +628,9 @@ function newId(): string { } /** - * Build the close-terminal handler the main component wires to the - * close button. Picks the next visible tab before dropping the entry - * so focus flows naturally; notifies the extension last. + * Estimate initial terminal geometry from the current DOM container. + * Provides best-effort columns and rows so PTY spawn avoids the default + * 80-column line width before the first xterm fit pass commits. */ function measureInitialDimensions( placement: TerminalPlacement, diff --git a/packages/opencode/test/server/httpapi-pty.test.ts b/packages/opencode/test/server/httpapi-pty.test.ts index 13f5bce2c9b..e7ac432dc57 100644 --- a/packages/opencode/test/server/httpapi-pty.test.ts +++ b/packages/opencode/test/server/httpapi-pty.test.ts @@ -303,4 +303,47 @@ describe("pty HttpApi bridge", () => { expect(removed.status).toBe(200) }), ) + // kilocode_change start - test initial pty spawn dimensions + ;(process.platform === "win32" ? effectIt.live.skip : effectIt.live)( + "spawns PTY with initial terminal dimensions end-to-end", + () => + Effect.gen(function* () { + const dir = yield* tmpdirScoped({ git: true, config: { formatter: false, lsp: false } }) + const created = yield* HttpClientRequest.post(PtyPaths.create).pipe( + directoryHeader(dir), + HttpClientRequest.bodyJson({ + command: "/bin/sh", + args: ["-c", "stty size"], + title: "size-test", + size: { cols: 50, rows: 20 }, + }), + Effect.flatMap(HttpClient.execute), + ) + expect(created.status).toBe(200) + const info = yield* Schema.decodeUnknownEffect(Pty.Info)(yield* created.json) + + const socket = yield* Socket.makeWebSocket( + `${(yield* serverUrl()).replace(/^http/, "ws")}${PtyPaths.connect.replace(":ptyID", info.id)}?cursor=-1&directory=${encodeURIComponent(dir)}`, + { closeCodeIsError: () => false }, + ) + const messages = yield* Queue.unbounded() + yield* socket + .runRaw((message) => + Queue.offer(messages, typeof message === "string" ? message : new TextDecoder().decode(message)), + ) + .pipe(Effect.catch(() => Effect.void)) + .pipe(Effect.forkScoped) + + const takeUntil = (expected: string, seen = ""): Effect.Effect => + Effect.gen(function* () { + const next = seen + (yield* Queue.take(messages).pipe(Effect.timeout("5 seconds"))) + if (next.includes(expected)) return next + return yield* takeUntil(expected, next) + }) + + const output = yield* takeUntil("20 50") + expect(output).toContain("20 50") + }), + ) + // kilocode_change end })