From 29d17b9055e2993bb4b7e23bd8bf15d84f2d5792 Mon Sep 17 00:00:00 2001 From: Luke Parker <10430890+Hona@users.noreply.github.com> Date: Fri, 29 May 2026 13:47:50 +1000 Subject: [PATCH] fix(opencode): allow pid 0 in Pty.Info for Windows ConPTY (#29828) --- packages/opencode/src/pty/index.ts | 6 +++- .../opencode/test/pty/info-schema.test.ts | 33 +++++++++++++++++++ 2 files changed, 38 insertions(+), 1 deletion(-) create mode 100644 packages/opencode/test/pty/info-schema.test.ts diff --git a/packages/opencode/src/pty/index.ts b/packages/opencode/src/pty/index.ts index b5eab9ce36..9905aa4f64 100644 --- a/packages/opencode/src/pty/index.ts +++ b/packages/opencode/src/pty/index.ts @@ -60,7 +60,11 @@ export const Info = Schema.Struct({ args: Schema.Array(Schema.String), cwd: Schema.String, status: Schema.Literals(["running", "exited"]), - pid: PositiveInt, + // Windows ConPTY (@lydell/node-pty >= 1.2.0-beta.12) assigns the child pid + // asynchronously, so `proc.pid` is 0 at the synchronous spawn point and only + // resolves a tick later. `create` snapshots it immediately, so 0 is a valid + // "pid not yet assigned" value here. + pid: NonNegativeInt, }).annotate({ identifier: "Pty" }) export type Info = Types.DeepMutable> diff --git a/packages/opencode/test/pty/info-schema.test.ts b/packages/opencode/test/pty/info-schema.test.ts new file mode 100644 index 0000000000..429f29b00e --- /dev/null +++ b/packages/opencode/test/pty/info-schema.test.ts @@ -0,0 +1,33 @@ +import { describe, expect, test } from "bun:test" +import { Schema } from "effect" +import { Pty } from "../../src/pty" + +// Windows ConPTY (via @lydell/node-pty >= 1.2.0-beta.12) assigns the child pid +// asynchronously: `proc.pid` reads back as 0 at the synchronous spawn point and +// only resolves to the real pid a tick later. `Pty.create` snapshots `proc.pid` +// while building `Info`, so `Info.pid` legitimately carries 0 right after spawn. +// `Pty.Info` must be able to represent that, otherwise every `pty.create` on +// Windows fails to encode/decode and the terminal feature is unusable. +const sample = (pid: number) => ({ + id: "pty_01J5Y5H0AH4Q4NXJ6P4C3P5V2K", + title: "demo", + command: "cmd.exe", + args: [], + cwd: "C:\\", + status: "running", + pid, +}) + +describe("Pty.Info", () => { + test("accepts pid 0 (Windows ConPTY assigns the pid asynchronously)", () => { + expect(Schema.decodeUnknownSync(Pty.Info)(sample(0)).pid).toBe(0) + }) + + test("accepts a positive pid", () => { + expect(Schema.decodeUnknownSync(Pty.Info)(sample(48012)).pid).toBe(48012) + }) + + test("rejects a negative pid", () => { + expect(() => Schema.decodeUnknownSync(Pty.Info)(sample(-1))).toThrow() + }) +})