mirror of
https://github.com/getpaseo/paseo.git
synced 2026-07-29 12:01:31 +00:00
fix(terminal): create PTYs at the client viewport size, not 80x24 (#2023)
New terminals were always spawned by the daemon at the hardcoded 80x24 default and only resized once the client's first resize arrived. On a slow first mount that leaves a window -- or a stuck state -- where a new terminal renders far smaller than its pane (e.g. vim in a corner). Seed the PTY with the client's measured viewport size at creation time so it is born at the right size and the race window is gone. - protocol: optional `size` on create_terminal_request. Old daemons ignore it and keep 80x24; old clients send nothing. Fully backward compatible, no capability gate. - client: a small last-measured-size cache keyed by serverId+cwd (every terminal in a workspace shares the pane) with a most-recent fallback; written on fit, read at create. - server: thread rows/cols through the controller, terminal manager, and the worker-thread boundary into the existing size-aware createTerminal. Tests: cache logic, protocol back-compat parse, controller forwarding. Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
34
packages/protocol/src/messages.create-terminal-size.test.ts
Normal file
34
packages/protocol/src/messages.create-terminal-size.test.ts
Normal file
@@ -0,0 +1,34 @@
|
||||
import { describe, expect, it } from "vitest";
|
||||
import { CreateTerminalRequestSchema } from "./messages";
|
||||
|
||||
// COMPAT(createTerminalSize): the size field is optional so old clients (which send no size)
|
||||
// still parse, and old daemons ignore it. These tests pin that contract.
|
||||
describe("CreateTerminalRequest size", () => {
|
||||
const base = {
|
||||
type: "create_terminal_request" as const,
|
||||
cwd: "/work/repo",
|
||||
requestId: "req-1",
|
||||
};
|
||||
|
||||
it("parses a request without a size (old client / back-compat)", () => {
|
||||
const parsed = CreateTerminalRequestSchema.parse({ ...base });
|
||||
expect(parsed).toEqual(base);
|
||||
});
|
||||
|
||||
it("parses a request carrying a viewport size", () => {
|
||||
const parsed = CreateTerminalRequestSchema.parse({ ...base, size: { rows: 55, cols: 136 } });
|
||||
expect(parsed.size).toEqual({ rows: 55, cols: 136 });
|
||||
});
|
||||
|
||||
it("rejects a non-positive or non-integer size", () => {
|
||||
expect(() =>
|
||||
CreateTerminalRequestSchema.parse({ ...base, size: { rows: 0, cols: 80 } }),
|
||||
).toThrow();
|
||||
expect(() =>
|
||||
CreateTerminalRequestSchema.parse({ ...base, size: { rows: 24, cols: -1 } }),
|
||||
).toThrow();
|
||||
expect(() =>
|
||||
CreateTerminalRequestSchema.parse({ ...base, size: { rows: 24.5, cols: 80 } }),
|
||||
).toThrow();
|
||||
});
|
||||
});
|
||||
@@ -1984,6 +1984,16 @@ export const CreateTerminalRequestSchema = z.object({
|
||||
agentId: z.string().optional(),
|
||||
command: z.string().optional(),
|
||||
args: z.array(z.string()).optional(),
|
||||
// COMPAT(createTerminalSize): added in v0.1.107, drop the optional gate when floor >= v0.1.107.
|
||||
// The client seeds the PTY with its measured viewport size so a new terminal isn't born at the
|
||||
// 80x24 default and then visibly reflowed. Old daemons ignore this field and start at 80x24;
|
||||
// the client's first resize corrects it as before.
|
||||
size: z
|
||||
.object({
|
||||
rows: z.number().int().positive(),
|
||||
cols: z.number().int().positive(),
|
||||
})
|
||||
.optional(),
|
||||
requestId: z.string(),
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user