diff --git a/.changeset/narrow-agent-manager-terminal.md b/.changeset/narrow-agent-manager-terminal.md new file mode 100644 index 00000000000..5091714bdb5 --- /dev/null +++ b/.changeset/narrow-agent-manager-terminal.md @@ -0,0 +1,5 @@ +--- +"kilo-code": patch +--- + +Keep Agent Manager terminals aligned and correctly wrapped when the terminal panel is narrow. diff --git a/packages/client/src/generated-effect/client.ts b/packages/client/src/generated-effect/client.ts index 024c9782806..5eac8611d0e 100644 --- a/packages/client/src/generated-effect/client.ts +++ b/packages/client/src/generated-effect/client.ts @@ -531,6 +531,7 @@ type Endpoint14_1Input = { readonly cwd?: Endpoint14_1Request["payload"]["cwd"] readonly title?: Endpoint14_1Request["payload"]["title"] readonly env?: Endpoint14_1Request["payload"]["env"] + readonly size?: Endpoint14_1Request["payload"]["size"] } const Endpoint14_1 = (raw: RawClient["server.pty"]) => (input?: Endpoint14_1Input) => raw["pty.create"]({ @@ -541,6 +542,7 @@ const Endpoint14_1 = (raw: RawClient["server.pty"]) => (input?: Endpoint14_1Inpu cwd: input?.["cwd"], title: input?.["title"], env: input?.["env"], + size: input?.["size"], }, }).pipe(Effect.mapError(mapClientError)) diff --git a/packages/client/src/generated/client.ts b/packages/client/src/generated/client.ts index 5f6943c53e6..b17a7ebd9fe 100644 --- a/packages/client/src/generated/client.ts +++ b/packages/client/src/generated/client.ts @@ -840,6 +840,7 @@ export function make(options: ClientOptions) { cwd: input?.["cwd"], title: input?.["title"], env: input?.["env"], + size: input?.["size"], }, successStatus: 200, declaredStatuses: [400, 401], diff --git a/packages/client/src/generated/types.ts b/packages/client/src/generated/types.ts index 9d918786679..a96ecb5d5ee 100644 --- a/packages/client/src/generated/types.ts +++ b/packages/client/src/generated/types.ts @@ -2632,6 +2632,7 @@ export type PtysCreateInput = { readonly cwd?: string readonly title?: string readonly env?: { readonly [x: string]: string } + readonly size?: { readonly rows: number; readonly cols: number } }["command"] readonly args?: { readonly command?: string @@ -2639,6 +2640,7 @@ export type PtysCreateInput = { readonly cwd?: string readonly title?: string readonly env?: { readonly [x: string]: string } + readonly size?: { readonly rows: number; readonly cols: number } }["args"] readonly cwd?: { readonly command?: string @@ -2646,6 +2648,7 @@ export type PtysCreateInput = { readonly cwd?: string readonly title?: string readonly env?: { readonly [x: string]: string } + readonly size?: { readonly rows: number; readonly cols: number } }["cwd"] readonly title?: { readonly command?: string @@ -2653,6 +2656,7 @@ export type PtysCreateInput = { readonly cwd?: string readonly title?: string readonly env?: { readonly [x: string]: string } + readonly size?: { readonly rows: number; readonly cols: number } }["title"] readonly env?: { readonly command?: string @@ -2660,7 +2664,16 @@ export type PtysCreateInput = { readonly cwd?: string readonly title?: string readonly env?: { readonly [x: string]: string } + readonly size?: { readonly rows: number; readonly cols: number } }["env"] + readonly size?: { + readonly command?: string + readonly args?: ReadonlyArray + readonly cwd?: string + readonly title?: string + readonly env?: { readonly [x: string]: string } + readonly size?: { readonly rows: number; readonly cols: number } + }["size"] } export type PtysCreateOutput = { diff --git a/packages/core/src/pty.ts b/packages/core/src/pty.ts index 44d95cb5085..97f41bcd54b 100644 --- a/packages/core/src/pty.ts +++ b/packages/core/src/pty.ts @@ -214,7 +214,17 @@ const layer = Layer.effect( } yield* Effect.logInfo("creating session", { id, cmd: command, args, cwd }) const { spawn } = yield* Effect.promise(() => pty()) - const proc = yield* Effect.sync(() => spawn(command, args, { name: "xterm-256color", cwd, env })) + // kilocode_change start - spawn with initial terminal dimensions + const proc = yield* Effect.sync(() => + spawn(command, args, { + name: "xterm-256color", + cwd, + env, + cols: input.size?.cols, + rows: input.size?.rows, + }), + ) + // kilocode_change end const info: Info = { id, title: input.title || `Terminal ${id.slice(-4)}`, diff --git a/packages/kilo-vscode/src/agent-manager/terminal-manager.ts b/packages/kilo-vscode/src/agent-manager/terminal-manager.ts index 40b98a58e14..26677dc2d3e 100644 --- a/packages/kilo-vscode/src/agent-manager/terminal-manager.ts +++ b/packages/kilo-vscode/src/agent-manager/terminal-manager.ts @@ -51,6 +51,7 @@ interface Entry { export class TerminalManager { private readonly entries = new Map() private readonly restarts = new Map>() + private readonly pending = new Map() constructor(private readonly deps: TerminalManagerDeps) {} @@ -67,7 +68,14 @@ export class TerminalManager { worktreeId: string | null cwd: string title: string + cols?: number + rows?: number }): Promise<{ terminalId: string; worktreeId: string | null; title: string; wsUrl: string }> { + const initial = + this.pending.get(params.terminalId) ?? + (params.cols !== undefined && params.rows !== undefined ? { cols: params.cols, rows: params.rows } : undefined) + this.pending.delete(params.terminalId) + const client = this.deps.getClient() const { data, error } = await client.pty.create({ directory: params.cwd, @@ -76,6 +84,7 @@ export class TerminalManager { // xterm's DOM renderer cannot draw the Unicode sextant glyphs used by // Kilo's modern wordmark, so use the compatible logo in embedded tabs. env, + size: initial, }) if (error || !data) { const err = error instanceof Error ? error.message : String(error ?? "unknown error") @@ -89,15 +98,39 @@ export class TerminalManager { title: data.title ?? params.title, } this.entries.set(params.terminalId, entry) + // If a resize arrived while pty.create was in flight that differed from `initial`, apply it now. + const latest = this.pending.get(params.terminalId) + if (latest && (latest.cols !== initial?.cols || latest.rows !== initial?.rows)) { + this.pending.delete(params.terminalId) + const { error: resizeErr } = await client.pty.update({ + directory: entry.cwd, + ptyID: entry.ptyID, + size: latest, + }) + if (resizeErr) { + const err = resizeErr instanceof Error ? resizeErr.message : String(resizeErr) + this.deps.log(`Initial terminal resize failed (${params.terminalId}): ${err}`) + } + } const wsUrl = this.deps.buildWsUrl(entry.ptyID, entry.cwd) this.deps.log(`Terminal created: ${params.terminalId} -> pty ${entry.ptyID} cwd=${entry.cwd}`) 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) return + if (!entry) { + this.pending.set(terminalId, { cols, rows }) + return + } + this.pending.delete(terminalId) const client = this.deps.getClient() const { error } = await client.pty.update({ directory: entry.cwd, @@ -126,6 +159,7 @@ export class TerminalManager { * failed delete would be silently logged as a successful close and * the server-side PTY would linger until `kilo serve` exits. */ async close(terminalId: string): Promise { + this.pending.delete(terminalId) const entry = this.entries.get(terminalId) if (!entry) return this.entries.delete(terminalId) @@ -187,6 +221,7 @@ export class TerminalManager { * is sampled mid-shutdown. */ async dispose(): Promise { + this.pending.clear() const snapshot = [...this.entries.values()] if (snapshot.length === 0) { this.entries.clear() diff --git a/packages/kilo-vscode/src/agent-manager/terminal-routing.ts b/packages/kilo-vscode/src/agent-manager/terminal-routing.ts index 95fe5c86328..7a4a74520f8 100644 --- a/packages/kilo-vscode/src/agent-manager/terminal-routing.ts +++ b/packages/kilo-vscode/src/agent-manager/terminal-routing.ts @@ -88,7 +88,7 @@ export class TerminalRouter { handle(m: AgentManagerInMessage): boolean { if (!isTerminalMessage(m)) return false if (m.type === "agentManager.terminal.create") { - void this.handleCreate(m.createId, m.placement, m.worktreeId) + void this.handleCreate(m.createId, m.placement, m.worktreeId, m.cols, m.rows) return true } if (m.type === "agentManager.terminal.close") { @@ -132,7 +132,13 @@ export class TerminalRouter { return manager.dispose() } - private async handleCreate(createId: string, placement: TerminalPlacement, worktreeId: string | null): Promise { + private async handleCreate( + createId: string, + placement: TerminalPlacement, + worktreeId: string | null, + cols?: number, + rows?: number, + ): Promise { const generation = this.generation const manager = this.manager const cwd = this.resolveCwd(worktreeId) @@ -155,7 +161,7 @@ export class TerminalRouter { // Join the shared backend connection instead of racing its synchronous // client accessor when this is the first Kilo action in the window. await this.deps.getClientAsync() - const created = await manager.create({ terminalId: createId, worktreeId, cwd, title }) + const created = await manager.create({ terminalId: createId, worktreeId, cwd, title, cols, rows }) if (generation !== this.generation) { await manager.close(created.terminalId) return diff --git a/packages/kilo-vscode/src/agent-manager/types.ts b/packages/kilo-vscode/src/agent-manager/types.ts index 7064f16d224..7e6792f10b2 100644 --- a/packages/kilo-vscode/src/agent-manager/types.ts +++ b/packages/kilo-vscode/src/agent-manager/types.ts @@ -946,6 +946,8 @@ interface TerminalCreateIn { placement: TerminalPlacement /** null for LOCAL, worktree id otherwise */ worktreeId: string | null + cols?: number + rows?: number } interface TerminalCloseIn { diff --git a/packages/kilo-vscode/tests/unit/agent-manager-terminal-layout.test.ts b/packages/kilo-vscode/tests/unit/agent-manager-terminal-layout.test.ts index 185e7770c80..dc1cdfcce85 100644 --- a/packages/kilo-vscode/tests/unit/agent-manager-terminal-layout.test.ts +++ b/packages/kilo-vscode/tests/unit/agent-manager-terminal-layout.test.ts @@ -39,6 +39,29 @@ test("does not refit hidden terminal buffers during resize", () => { expect(callback!.indexOf("if (!props.active) return")).toBeLessThan(callback!.indexOf("fit.fit()")) }) +test("keeps raw PTY line endings and initializes Unicode widths before attaching", () => { + expect(terminal).toContain("convertEol: false") + expect(terminal).toContain('term.unicode.activeVersion = "15-graphemes"') + expect(terminal.indexOf("term.loadAddon(new UnicodeGraphemesAddon())")).toBeLessThan( + terminal.indexOf("open(props.wsUrl)"), + ) +}) + +test("fits and forces the initial PTY dimensions before socket attach", () => { + expect(terminal).toContain("const syncSize = (force = false)") + expect(terminal).toContain("if (props.active) syncSize(true)") + expect(terminal.indexOf("fitNow()\n open(props.wsUrl)")).toBeGreaterThan(-1) +}) + +test("re-sends dimensions when an optimistic terminal receives its PTY", () => { + const created = terminal.match( + /if \(message\.terminalId === props\.terminalId && !ws\) \{([\s\S]*?)\n \}/, + )?.[1] + expect(created).toBeDefined() + expect(created).toContain("fitNow()") + expect(created!.indexOf("fitNow()")).toBeLessThan(created!.indexOf("open(message.wsUrl)")) +}) + test("clamps the restored inspector width to the shared layout bounds", () => { expect(clampPanelWidth(undefined, 1200)).toBe(600) expect(clampPanelWidth(500, 1200)).toBe(500) diff --git a/packages/kilo-vscode/tests/unit/agent-manager-terminal-routing.test.ts b/packages/kilo-vscode/tests/unit/agent-manager-terminal-routing.test.ts index 709a704b8f6..6950d692e5e 100644 --- a/packages/kilo-vscode/tests/unit/agent-manager-terminal-routing.test.ts +++ b/packages/kilo-vscode/tests/unit/agent-manager-terminal-routing.test.ts @@ -343,4 +343,62 @@ describe("Agent Manager terminal routing", () => { }) await router.dispose() }) + + it("applies initial create dimensions and queues resize messages before creation settles", async () => { + const creates: Array> = [] + const updates: Array<{ ptyID: string; size?: { cols: number; rows: number } }> = [] + let createResolver: ((value: { data: { id: string; title: string } }) => void) | undefined + const client = { + pty: { + create: (params: Record) => + new Promise<{ data: { id: string; title: string } }>((resolve) => { + creates.push(params) + createResolver = resolve + }), + remove: async () => ({ data: true }), + update: async (params: { ptyID: string; size?: { cols: number; rows: number } }) => { + updates.push(params) + return { data: true } + }, + }, + } as unknown as KiloClient + const router = new TerminalRouter({ + getClient: () => client, + getClientAsync: async () => client, + getServerConfig: () => ({ baseUrl: "http://127.0.0.1:4096", password: "secret" }), + getRoot: () => "/workspace", + getWorktreePath: () => undefined, + getProjectId: () => "prj-1", + log: () => undefined, + post: () => undefined, + getTerminalFont: () => font, + }) + + router.handle({ + type: "agentManager.terminal.create", + createId: "queued", + placement: "side", + worktreeId: null, + cols: 60, + rows: 20, + }) + await wait() + expect(creates).toHaveLength(1) + expect(creates[0]?.size).toEqual({ cols: 60, rows: 20 }) + + // Send a resize before pty.create settles (optimistic side terminal layout) + router.handle({ + type: "agentManager.terminal.resize", + terminalId: "queued", + cols: 55, + rows: 18, + }) + await wait() + expect(updates).toHaveLength(0) + + createResolver?.({ data: { id: "pty-queued", title: "Terminal 1" } }) + await wait() + expect(updates).toEqual([{ directory: "/workspace", ptyID: "pty-queued", size: { cols: 55, rows: 18 } }]) + await router.dispose() + }) }) diff --git a/packages/kilo-vscode/webview-ui/agent-manager/terminal/TerminalTab.tsx b/packages/kilo-vscode/webview-ui/agent-manager/terminal/TerminalTab.tsx index 08556c737b0..bdf6ae8318b 100644 --- a/packages/kilo-vscode/webview-ui/agent-manager/terminal/TerminalTab.tsx +++ b/packages/kilo-vscode/webview-ui/agent-manager/terminal/TerminalTab.tsx @@ -152,7 +152,10 @@ export const TerminalTab: Component = (props) => { onMount(() => { const term = new Terminal({ - convertEol: true, + // PTY output already contains terminal line endings. Converting LF to + // CRLF here corrupts raw PTY output and is especially visible when a + // narrow terminal wraps and redraws the prompt. + convertEol: false, cursorBlink: true, cursorInactiveStyle: "outline", fontFamily: props.font.fontFamily, @@ -164,17 +167,11 @@ export const TerminalTab: Component = (props) => { const fit = new FitAddon() term.loadAddon(fit) term.open(host) - // Fit on the next frame — `host` might still have 0px dimensions - // during the initial layout pass otherwise. - requestAnimationFrame(() => { - try { - fit.fit() - } catch (err) { - // Host still detached at mount time. ResizeObserver will retry - // once layout kicks in. Logged so regressions don't hide. - log("initial fit() threw", err) - } - }) + // Unicode width must be configured before the first PTY bytes are parsed. + // Loading it later can leave already-wrapped graphemes with stale cell + // widths, which moves the cursor in narrow terminals. + term.loadAddon(new UnicodeGraphemesAddon()) + term.unicode.activeVersion = "15-graphemes" // Pass Agent Manager hotkeys through to the parent key handler so // ⌘T / ⌘⇧T / ⌘W / terminal cycling / ⌘⌥← still work while focused. @@ -356,11 +353,9 @@ export const TerminalTab: Component = (props) => { } const disposeData = term.onData(send) const disposeBinary = term.onBinary(send) - open(props.wsUrl) - // These addons are not needed to paint the initial prompt. Defer them - // until after the first frame so their startup work, especially the - // Unicode 15 width tables, does not delay the shell connection. + // until after the first frame so their startup work does not delay the + // shell connection. const loadAddons = () => { deferred = undefined if (closed) return @@ -375,16 +370,8 @@ export const TerminalTab: Component = (props) => { ) // OSC 52 clipboard support for shell programs such as tmux and neovim. term.loadAddon(new ClipboardAddon()) - // Use grapheme-aware width tables for newer emoji and ZWJ sequences. - term.loadAddon(new UnicodeGraphemesAddon()) - term.unicode.activeVersion = "15-graphemes" term.refresh(0, Math.max(0, term.rows - 1)) } - frame = requestAnimationFrame(() => { - frame = undefined - deferred = requestAnimationFrame(loadAddons) - }) - const restarted = (url: string) => { open(url) } @@ -395,10 +382,12 @@ export const TerminalTab: Component = (props) => { let resizeTimer: ReturnType | undefined let lastCols = term.cols let lastRows = term.rows - const syncSize = () => { - if (term.cols === lastCols && term.rows === lastRows) return + let synced = false + const syncSize = (force = false) => { + if (!force && synced && term.cols === lastCols && term.rows === lastRows) return lastCols = term.cols lastRows = term.rows + synced = true vscode.postMessage({ type: "agentManager.terminal.resize", terminalId: props.terminalId, @@ -406,6 +395,16 @@ export const TerminalTab: Component = (props) => { rows: term.rows, }) } + const fitNow = () => { + try { + fit.fit() + if (props.active) syncSize(true) + } catch (err) { + // Host still detached at mount time. ResizeObserver will retry + // once layout kicks in. Logged so regressions don't hide. + log("fit() threw", err) + } + } const ro = new ResizeObserver(() => { if (!props.active) return try { @@ -422,6 +421,16 @@ export const TerminalTab: Component = (props) => { resizeTimer = setTimeout(syncSize, RESIZE_DEBOUNCE_MS) }) ro.observe(host) + // Wait for the first committed layout before attaching the socket. This + // prevents the shell from emitting its first prompt at xterm's default + // 80 columns, which is most visible in a narrow side panel. + frame = requestAnimationFrame(() => { + frame = undefined + if (closed) return + fitNow() + open(props.wsUrl) + deferred = requestAnimationFrame(loadAddons) + }) // ---- Repaint recovery ---- // @@ -452,7 +461,7 @@ export const TerminalTab: Component = (props) => { if (!isRenderable()) return try { fit.fit() - syncSize() + syncSize(!synced) } catch (err) { // Layout not settled yet; ResizeObserver retries on next change. log("repaint fit() threw", err) @@ -485,6 +494,9 @@ export const TerminalTab: Component = (props) => { if (message.terminalId === props.terminalId && !ws) { term.options.fontFamily = message.font.fontFamily term.options.fontSize = message.font.fontSize + // Optimistic side terminals can fit before their backend PTY exists; + // force the first resize again once the created response arrives. + fitNow() scheduleRepaint() open(message.wsUrl) } 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 5b5442218b3..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,10 +628,32 @@ 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, + font: TerminalFont, +): { cols: number; rows: number } | undefined { + if (typeof document === "undefined") return undefined + const selector = + placement === "side" + ? ".am-side-terminal-layer, .am-side-terminal, .am-diff-panel-wrapper" + : ".am-terminal-layer, .am-detail-stack" + const host = document.querySelector(selector) as HTMLElement | null + const rect = host?.getBoundingClientRect() + if (!rect || rect.width <= 0 || rect.height <= 0) return undefined + const cellWidth = font.fontSize > 0 ? font.fontSize * 0.6 : 7.2 + const cellHeight = font.fontSize > 0 ? font.fontSize * 1.2 : 14.4 + const availableWidth = Math.max(0, rect.width - 30) + const availableHeight = Math.max(0, rect.height - 16) + return { + cols: Math.max(10, Math.floor(availableWidth / cellWidth)), + rows: Math.max(3, Math.floor(availableHeight / cellHeight)), + } +} + export function createTerminalHandlers(deps: TerminalHandlerDeps) { const activate = (id: string) => { deps.state.setActiveId(id) @@ -645,11 +667,15 @@ export function createTerminalHandlers(deps: TerminalHandlerDeps) { const requestNew = () => { const sel = deps.getSelection() if (sel === null) return + const font = deps.getFont() + const dims = measureInitialDimensions("tab", font) deps.postMessage({ type: "agentManager.terminal.create", createId: newId(), placement: "tab", worktreeId: sel === deps.LOCAL ? null : sel, + cols: dims?.cols, + rows: dims?.rows, }) } @@ -659,12 +685,14 @@ export function createTerminalHandlers(deps: TerminalHandlerDeps) { // project-namespaced state key and must not leak into the message. const sel = deps.getSelection() const id = newId() + const font = deps.getFont() + const dims = measureInitialDimensions("side", font) deps.state.beginSide(key, id) deps.state.add(key === deps.LOCAL ? null : key, { id, title: "Terminal", wsUrl: "", - font: deps.getFont(), + font, placement: "side", }) deps.state.setSideActive(key, id) @@ -674,6 +702,8 @@ export function createTerminalHandlers(deps: TerminalHandlerDeps) { createId: id, placement: "side", worktreeId: sel === null || sel === deps.LOCAL ? null : sel, + cols: dims?.cols, + rows: dims?.rows, }) } diff --git a/packages/kilo-vscode/webview-ui/src/types/messages/webview-messages.ts b/packages/kilo-vscode/webview-ui/src/types/messages/webview-messages.ts index 72549d7da51..98de565b812 100644 --- a/packages/kilo-vscode/webview-ui/src/types/messages/webview-messages.ts +++ b/packages/kilo-vscode/webview-ui/src/types/messages/webview-messages.ts @@ -813,6 +813,8 @@ export interface AgentManagerTerminalCreateRequest { createId: string placement: TerminalPlacement worktreeId: string | null + cols?: number + rows?: number } // Close a terminal tab diff --git a/packages/opencode/test/server/httpapi-pty.test.ts b/packages/opencode/test/server/httpapi-pty.test.ts index 084ce9f713d..13f5bce2c9b 100644 --- a/packages/opencode/test/server/httpapi-pty.test.ts +++ b/packages/opencode/test/server/httpapi-pty.test.ts @@ -81,11 +81,18 @@ describe("pty HttpApi bridge", () => { expect(list.status).toBe(200) expect(await list.json()).toEqual([]) + // kilocode_change start - test initial spawn dimensions const created = await app().request(PtyPaths.create, { method: "POST", headers: { ...headers, "content-type": "application/json" }, - body: JSON.stringify({ command: "/usr/bin/env", args: ["sh", "-c", "sleep 5"], title: "demo" }), + body: JSON.stringify({ + command: "/usr/bin/env", + args: ["sh", "-c", "sleep 5"], + title: "demo", + size: { cols: 50, rows: 20 }, + }), }) + // kilocode_change end expect(created.status).toBe(200) const info = await created.json() diff --git a/packages/schema/src/pty.ts b/packages/schema/src/pty.ts index 1ed58393e93..34903b9bc2b 100644 --- a/packages/schema/src/pty.ts +++ b/packages/schema/src/pty.ts @@ -45,6 +45,14 @@ export const CreateInput = Schema.Struct({ cwd: optional(Schema.String), title: optional(Schema.String), env: optional(Schema.Record(Schema.String, Schema.String)), + // kilocode_change start - spawn with initial terminal dimensions + size: optional( + Schema.Struct({ + rows: PositiveInt, + cols: PositiveInt, + }), + ), + // kilocode_change end }) export interface CreateInput extends Schema.Schema.Type {} diff --git a/packages/sdk/js/src/v2/gen/sdk.gen.ts b/packages/sdk/js/src/v2/gen/sdk.gen.ts index dab2fa1ccfb..965b7b43c24 100644 --- a/packages/sdk/js/src/v2/gen/sdk.gen.ts +++ b/packages/sdk/js/src/v2/gen/sdk.gen.ts @@ -3428,6 +3428,10 @@ export class Pty extends HeyApiClient { env?: { [key: string]: string } + size?: { + rows: number + cols: number + } }, options?: Options, ) { @@ -3443,6 +3447,7 @@ export class Pty extends HeyApiClient { { in: "body", key: "cwd" }, { in: "body", key: "title" }, { in: "body", key: "env" }, + { in: "body", key: "size" }, ], }, ], @@ -4430,6 +4435,8 @@ export class Session2 extends HeyApiClient { directory?: string workspace?: string messageID?: string + file?: string + full?: "true" | "false" }, options?: Options, ) { @@ -4442,6 +4449,8 @@ export class Session2 extends HeyApiClient { { in: "query", key: "directory" }, { in: "query", key: "workspace" }, { in: "query", key: "messageID" }, + { in: "query", key: "file" }, + { in: "query", key: "full" }, ], }, ], @@ -10831,6 +10840,10 @@ export class Pty2 extends HeyApiClient { env?: { [key: string]: string } + size?: { + rows: number + cols: number + } }, options?: Options, ) { @@ -10845,6 +10858,7 @@ export class Pty2 extends HeyApiClient { { in: "body", key: "cwd" }, { in: "body", key: "title" }, { in: "body", key: "env" }, + { in: "body", key: "size" }, ], }, ], diff --git a/packages/sdk/js/src/v2/gen/types.gen.ts b/packages/sdk/js/src/v2/gen/types.gen.ts index 42ab093ccad..ebdab8111c3 100644 --- a/packages/sdk/js/src/v2/gen/types.gen.ts +++ b/packages/sdk/js/src/v2/gen/types.gen.ts @@ -465,6 +465,8 @@ export type IndexingWarning = { export type SnapshotFileDiff = { file?: string patch?: string + before?: string + after?: string additions: number deletions: number status?: "added" | "deleted" | "modified" @@ -2888,11 +2890,11 @@ export type WorktreeResetInput = { export type WorktreeDiffItem = { file?: string patch?: string + before: string + after: string additions: number deletions: number status?: "added" | "deleted" | "modified" - before: string - after: string tracked: boolean generatedLike: boolean summarized: boolean @@ -12326,6 +12328,10 @@ export type PtyCreateData = { env?: { [key: string]: string } + size?: { + rows: number + cols: number + } } path?: never query?: { @@ -13177,6 +13183,8 @@ export type SessionDiffData = { directory?: string workspace?: string messageID?: string + file?: string + full?: "true" | "false" } url: "/session/{sessionID}/diff" } @@ -20244,6 +20252,10 @@ export type V2PtyCreateData = { env?: { [key: string]: string } + size?: { + rows: number + cols: number + } } path?: never query?: { diff --git a/packages/sdk/openapi.json b/packages/sdk/openapi.json index a770f7f8185..6165344b853 100644 --- a/packages/sdk/openapi.json +++ b/packages/sdk/openapi.json @@ -4539,6 +4539,21 @@ "additionalProperties": { "type": "string" } + }, + "size": { + "type": "object", + "properties": { + "rows": { + "type": "integer", + "exclusiveMinimum": 0 + }, + "cols": { + "type": "integer", + "exclusiveMinimum": 0 + } + }, + "required": ["rows", "cols"], + "additionalProperties": false } }, "additionalProperties": false @@ -6587,6 +6602,23 @@ "pattern": "^msg" }, "required": false + }, + { + "name": "file", + "in": "query", + "schema": { + "type": "string" + }, + "required": false + }, + { + "name": "full", + "in": "query", + "schema": { + "type": "string", + "enum": ["true", "false"] + }, + "required": false } ], "responses": { @@ -24318,6 +24350,21 @@ "additionalProperties": { "type": "string" } + }, + "size": { + "type": "object", + "properties": { + "rows": { + "type": "integer", + "exclusiveMinimum": 0 + }, + "cols": { + "type": "integer", + "exclusiveMinimum": 0 + } + }, + "required": ["rows", "cols"], + "additionalProperties": false } }, "additionalProperties": false @@ -27026,6 +27073,12 @@ "patch": { "type": "string" }, + "before": { + "type": "string" + }, + "after": { + "type": "string" + }, "additions": { "type": "number" }, @@ -34498,6 +34551,12 @@ "patch": { "type": "string" }, + "before": { + "type": "string" + }, + "after": { + "type": "string" + }, "additions": { "type": "number" }, @@ -34508,12 +34567,6 @@ "type": "string", "enum": ["added", "deleted", "modified"] }, - "before": { - "type": "string" - }, - "after": { - "type": "string" - }, "tracked": { "type": "boolean" }, @@ -34527,7 +34580,7 @@ "type": "string" } }, - "required": ["additions", "deletions", "before", "after", "tracked", "generatedLike", "summarized", "stamp"], + "required": ["before", "after", "additions", "deletions", "tracked", "generatedLike", "summarized", "stamp"], "additionalProperties": false }, "SnapshotSummaryFileDiff": {