Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
45 changes: 45 additions & 0 deletions packages/effect-acp/src/_internal/stdio.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import { assert, describe, it } from "@effect/vitest";
import * as Effect from "effect/Effect";
import * as PlatformError from "effect/PlatformError";
import { ChildProcessSpawner } from "effect/unstable/process";

import * as AcpError from "../errors.ts";
import { makeTerminationError } from "./stdio.ts";

describe("ACP child process termination", () => {
it.effect("retains the process identifier with the exit code", () =>
Effect.gen(function* () {
const error = yield* makeTerminationError({
pid: ChildProcessSpawner.ProcessId(41),
exitCode: Effect.succeed(ChildProcessSpawner.ExitCode(7)),
});

assert.instanceOf(error, AcpError.AcpProcessExitedError);
assert.equal(error.pid, 41);
assert.equal(error.code, 7);
assert.equal(error.message, "ACP process exited with code 7");
}),
);

it.effect("retains the process identifier and exact exit-status cause", () =>
Effect.gen(function* () {
const rootCause = new Error("private process diagnostics");
const cause = PlatformError.systemError({
_tag: "Unknown",
module: "ChildProcess",
method: "exitCode",
cause: rootCause,
});
const error = yield* makeTerminationError({
pid: ChildProcessSpawner.ProcessId(42),
exitCode: Effect.fail(cause),
});

assert.instanceOf(error, AcpError.AcpTransportError);
assert.equal(error.pid, 42);
assert.strictEqual(error.cause, cause);
assert.equal(error.message, "ACP transport operation read-process-exit-status failed.");
assert.notInclude(error.message, rootCause.message);
}),
);
});
10 changes: 8 additions & 2 deletions packages/effect-acp/src/_internal/stdio.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,14 +44,20 @@ export const makeInMemoryStdio = Effect.fn("makeInMemoryStdio")(function* () {
};
});

type ChildProcessTerminationHandle = Pick<
ChildProcessSpawner.ChildProcessHandle,
"exitCode" | "pid"
>;

export const makeTerminationError = (
handle: ChildProcessSpawner.ChildProcessHandle,
handle: ChildProcessTerminationHandle,
): Effect.Effect<AcpError.AcpError> =>
Effect.match(handle.exitCode, {
onFailure: (cause) =>
new AcpError.AcpTransportError({
operation: "read-process-exit-status",
pid: handle.pid,
cause,
}),
onSuccess: (code) => new AcpError.AcpProcessExitedError({ code }),
onSuccess: (code) => new AcpError.AcpProcessExitedError({ code, pid: handle.pid }),
});
2 changes: 2 additions & 0 deletions packages/effect-acp/src/errors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ export class AcpProcessExitedError extends Schema.TaggedErrorClass<AcpProcessExi
"AcpProcessExitedError",
{
code: Schema.optional(Schema.Number),
pid: Schema.optionalKey(Schema.Int),
cause: Schema.optional(Schema.Defect()),
},
) {
Expand Down Expand Up @@ -160,6 +161,7 @@ export class AcpTransportError extends Schema.TaggedErrorClass<AcpTransportError
),
method: Schema.optional(Schema.String),
detail: Schema.optional(Schema.String),
pid: Schema.optionalKey(Schema.Int),
cause: Schema.Defect(),
},
) {
Expand Down
48 changes: 48 additions & 0 deletions packages/effect-codex-app-server/src/_internal/stdio.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import { assert, describe, it } from "@effect/vitest";
import * as Effect from "effect/Effect";
import * as PlatformError from "effect/PlatformError";
import { ChildProcessSpawner } from "effect/unstable/process";

import * as CodexError from "../errors.ts";
import { makeTerminationError } from "./stdio.ts";

describe("Codex App Server child process termination", () => {
it.effect("retains the process identifier with the exit code", () =>
Effect.gen(function* () {
const error = yield* makeTerminationError({
pid: ChildProcessSpawner.ProcessId(51),
exitCode: Effect.succeed(ChildProcessSpawner.ExitCode(9)),
});

assert.instanceOf(error, CodexError.CodexAppServerProcessExitedError);
assert.equal(error.pid, 51);
assert.equal(error.code, 9);
assert.equal(error.message, "Codex App Server process exited with code 9");
}),
);

it.effect("retains the process identifier and exact exit-status cause", () =>
Effect.gen(function* () {
const rootCause = new Error("private process diagnostics");
const cause = PlatformError.systemError({
_tag: "Unknown",
module: "ChildProcess",
method: "exitCode",
cause: rootCause,
});
const error = yield* makeTerminationError({
pid: ChildProcessSpawner.ProcessId(52),
exitCode: Effect.fail(cause),
});

assert.instanceOf(error, CodexError.CodexAppServerTransportError);
assert.equal(error.pid, 52);
assert.strictEqual(error.cause, cause);
assert.equal(
error.message,
"Codex App Server transport operation 'read-process-exit-status' failed.",
);
assert.notInclude(error.message, rootCause.message);
}),
);
});
10 changes: 8 additions & 2 deletions packages/effect-codex-app-server/src/_internal/stdio.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,14 +44,20 @@ export const makeInMemoryStdio = Effect.fn("makeInMemoryStdio")(function* () {
};
});

type ChildProcessTerminationHandle = Pick<
ChildProcessSpawner.ChildProcessHandle,
"exitCode" | "pid"
>;

export const makeTerminationError = (
handle: ChildProcessSpawner.ChildProcessHandle,
handle: ChildProcessTerminationHandle,
): Effect.Effect<CodexError.CodexAppServerError> =>
Effect.match(handle.exitCode, {
onFailure: (cause) =>
new CodexError.CodexAppServerTransportError({
operation: "read-process-exit-status",
pid: handle.pid,
cause,
}),
onSuccess: (code) => new CodexError.CodexAppServerProcessExitedError({ code }),
onSuccess: (code) => new CodexError.CodexAppServerProcessExitedError({ code, pid: handle.pid }),
});
2 changes: 2 additions & 0 deletions packages/effect-codex-app-server/src/errors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,7 @@ export class CodexAppServerProcessExitedError extends Schema.TaggedErrorClass<Co
"CodexAppServerProcessExitedError",
{
code: Schema.optional(Schema.Number),
pid: Schema.optionalKey(Schema.Int),
cause: Schema.optional(Schema.Defect()),
},
) {
Expand Down Expand Up @@ -233,6 +234,7 @@ export class CodexAppServerTransportError extends Schema.TaggedErrorClass<CodexA
"CodexAppServerTransportError",
{
operation: CodexAppServerTransportOperation,
pid: Schema.optionalKey(Schema.Int),
cause: Schema.Defect(),
},
) {
Expand Down
Loading