Fix terminal snapshots reflowing after resize
Terminal snapshots now carry soft-wrap row metadata only to clients that advertise support, so restored output can resize like live output without breaking older clients.
This commit is contained in:
@@ -485,15 +485,13 @@ const ToolCallDetailPayloadSchema: z.ZodType<ToolCallDetail, z.ZodTypeDef, unkno
|
||||
}),
|
||||
]);
|
||||
|
||||
const ToolCallBasePayloadSchema = z
|
||||
.object({
|
||||
type: z.literal("tool_call"),
|
||||
callId: z.string(),
|
||||
name: z.string(),
|
||||
detail: ToolCallDetailPayloadSchema,
|
||||
metadata: z.record(z.string(), z.unknown()).optional(),
|
||||
})
|
||||
.strict();
|
||||
const ToolCallBasePayloadSchema = z.object({
|
||||
type: z.literal("tool_call"),
|
||||
callId: z.string(),
|
||||
name: z.string(),
|
||||
detail: ToolCallDetailPayloadSchema,
|
||||
metadata: z.record(z.string(), z.unknown()).optional(),
|
||||
});
|
||||
|
||||
const ToolCallRunningPayloadSchema = ToolCallBasePayloadSchema.extend({
|
||||
status: z.literal("running"),
|
||||
@@ -1808,10 +1806,8 @@ export const SubscribeTerminalRequestSchema = z.object({
|
||||
rows: z.number().int().positive(),
|
||||
cols: z.number().int().positive(),
|
||||
})
|
||||
.strict()
|
||||
.optional(),
|
||||
})
|
||||
.strict()
|
||||
.optional(),
|
||||
});
|
||||
|
||||
@@ -3540,44 +3536,45 @@ const TerminalInfoSchema = z.object({
|
||||
title: z.string().optional(),
|
||||
});
|
||||
|
||||
export const TerminalCellSchema = z
|
||||
.object({
|
||||
char: z.string(),
|
||||
fg: z.number().optional(),
|
||||
bg: z.number().optional(),
|
||||
fgMode: z.number().optional(),
|
||||
bgMode: z.number().optional(),
|
||||
bold: z.boolean().optional(),
|
||||
italic: z.boolean().optional(),
|
||||
underline: z.boolean().optional(),
|
||||
dim: z.boolean().optional(),
|
||||
inverse: z.boolean().optional(),
|
||||
strikethrough: z.boolean().optional(),
|
||||
})
|
||||
.strict();
|
||||
export const TerminalCellSchema = z.object({
|
||||
char: z.string(),
|
||||
fg: z.number().optional(),
|
||||
bg: z.number().optional(),
|
||||
fgMode: z.number().optional(),
|
||||
bgMode: z.number().optional(),
|
||||
bold: z.boolean().optional(),
|
||||
italic: z.boolean().optional(),
|
||||
underline: z.boolean().optional(),
|
||||
dim: z.boolean().optional(),
|
||||
inverse: z.boolean().optional(),
|
||||
strikethrough: z.boolean().optional(),
|
||||
});
|
||||
|
||||
export const TerminalCursorStyleSchema = z.enum(["block", "underline", "bar"]);
|
||||
|
||||
export const TerminalCursorSchema = z
|
||||
.object({
|
||||
row: z.number(),
|
||||
col: z.number(),
|
||||
hidden: z.boolean().optional(),
|
||||
style: TerminalCursorStyleSchema.optional(),
|
||||
blink: z.boolean().optional(),
|
||||
})
|
||||
.strict();
|
||||
export const TerminalCursorSchema = z.object({
|
||||
row: z.number(),
|
||||
col: z.number(),
|
||||
hidden: z.boolean().optional(),
|
||||
style: TerminalCursorStyleSchema.optional(),
|
||||
blink: z.boolean().optional(),
|
||||
});
|
||||
|
||||
export const TerminalStateSchema = z
|
||||
.object({
|
||||
rows: z.number(),
|
||||
cols: z.number(),
|
||||
grid: z.array(z.array(TerminalCellSchema)),
|
||||
scrollback: z.array(z.array(TerminalCellSchema)),
|
||||
cursor: TerminalCursorSchema,
|
||||
title: z.string().optional(),
|
||||
})
|
||||
.strict();
|
||||
export const TerminalStateSchema = z.object({
|
||||
rows: z.number(),
|
||||
cols: z.number(),
|
||||
grid: z.array(z.array(TerminalCellSchema)),
|
||||
scrollback: z.array(z.array(TerminalCellSchema)),
|
||||
cursor: TerminalCursorSchema,
|
||||
title: z.string().optional(),
|
||||
// Per-row soft-wrap flags aligned 1:1 with `grid` / `scrollback`. `true` means
|
||||
// the row continued onto the next row (xterm's GRID_LINE_WRAPPED equivalent),
|
||||
// so the client can re-wrap the logical line on resize instead of freezing it
|
||||
// at the snapshot width. Optional: only sent to clients that advertise the
|
||||
// `terminalReflowableSnapshot` capability, so old daemons/clients are unaffected.
|
||||
gridWrapped: z.array(z.boolean()).optional(),
|
||||
scrollbackWrapped: z.array(z.boolean()).optional(),
|
||||
});
|
||||
|
||||
export const ListTerminalsResponseSchema = z.object({
|
||||
type: z.literal("list_terminals_response"),
|
||||
@@ -4108,6 +4105,7 @@ export const WSHelloMessageSchema = z.object({
|
||||
pushNotifications: z.boolean().optional(),
|
||||
[CLIENT_CAPS.reasoningMergeEnum]: z.boolean().optional(),
|
||||
[CLIENT_CAPS.customModeIcons]: z.boolean().optional(),
|
||||
[CLIENT_CAPS.terminalReflowableSnapshot]: z.boolean().optional(),
|
||||
})
|
||||
.passthrough()
|
||||
.optional(),
|
||||
|
||||
Reference in New Issue
Block a user