import { assert, describe, it } from "@effect/vitest";import * as NetService from "@t3tools/shared/Net";import { HostProcessPlatform } from "@t3tools/shared/hostProcess";import * as Effect from "effect/Effect";import * as Layer from "effect/Layer";import * as Result from "effect/Result";import * as Sink from "effect/Sink";import * as Stream from "effect/Stream";import * as ChildProcessSpawner from "effect/unstable/process/ChildProcessSpawner"; import * as OpenCodeRuntime from "./opencodeRuntime.ts"; const encoder = new TextEncoder(); function exitedProcess(stdout: string, stderr: string, exitCode: number) { return ChildProcessSpawner.makeHandle({ pid: ChildProcessSpawner.ProcessId(123), stdout: Stream.make(encoder.encode(stdout)), stderr: Stream.make(encoder.encode(stderr)), all: Stream.empty, exitCode: Effect.yieldNow.pipe( Effect.andThen(Effect.succeed(ChildProcessSpawner.ExitCode(exitCode))), ), isRunning: Effect.succeed(false), kill: () => Effect.void, stdin: Sink.drain, getInputFd: () => Sink.drain, getOutputFd: () => Stream.empty, unref: Effect.succeed(Effect.void), });} const netService = { canListenOnHost: () => Effect.succeed(true), isPortAvailableOnLoopback: () => Effect.succeed(true), reserveLoopbackPort: () => Effect.succeed(12_345), findAvailablePort: () => Effect.succeed(12_345),} satisfies NetService.NetServiceShape; describe("OpenCodeRuntime", () => { it.effect("retains SDK status and cause without copying arbitrary response bodies", () => { const cause = { response: { status: 401 }, body: { accessToken: "sdk-secret" }, }; return Effect.gen(function* () { const result = yield* Effect.result( OpenCodeRuntime.runOpenCodeSdk("session.get", () => Promise.reject(cause)), ); assert.isTrue(Result.isFailure(result)); if (Result.isFailure(result)) { assert.instanceOf(result.failure, OpenCodeRuntime.OpenCodeRuntimeError); assert.equal(result.failure.operation, "session.get"); assert.equal(result.failure.detail, "OpenCode SDK request failed."); assert.equal(result.failure.responseStatus, 401); assert.strictEqual(result.failure.cause, cause); assert.notInclude(result.failure.detail, "sdk-secret"); assert.isFalse("body" in result.failure); } }); }); it.live("records startup output sizes without retaining process streams", () => { const stdout = "startup output with a credential sdk-secret"; const stderr = "startup failed"; const layer = Layer.mergeAll( Layer.succeed( ChildProcessSpawner.ChildProcessSpawner, ChildProcessSpawner.make(() => Effect.succeed(exitedProcess(stdout, stderr, 17))), ), Layer.succeed(NetService.NetService, netService), Layer.succeed(HostProcessPlatform, "win32"), ); return Effect.gen(function* () { const runtime = yield* OpenCodeRuntime.make; const result = yield* Effect.result( Effect.scoped( runtime.startOpenCodeServerProcess({ binaryPath: "opencode", port: 12_345, }), ), ); assert.isTrue(Result.isFailure(result)); if (Result.isFailure(result)) { assert.instanceOf(result.failure, OpenCodeRuntime.OpenCodeRuntimeError); assert.equal(result.failure.exitCode, 17); assert.equal(result.failure.argumentCount, 3); assert.equal(result.failure.stdoutBytes, encoder.encode(stdout).byteLength); assert.equal(result.failure.stderrBytes, encoder.encode(stderr).byteLength); assert.isFalse("stdout" in result.failure); assert.isFalse("stderr" in result.failure); assert.notInclude(result.failure.detail, "sdk-secret"); } }).pipe(Effect.provide(layer)); });});
import { assert, describe, it } from "@effect/vitest";
import * as NetService from "@t3tools/shared/Net";
import { HostProcessPlatform } from "@t3tools/shared/hostProcess";
import * as Effect from "effect/Effect";
import * as Layer from "effect/Layer";
import * as Result from "effect/Result";
import * as Sink from "effect/Sink";
import * as Stream from "effect/Stream";
import * as ChildProcessSpawner from "effect/unstable/process/ChildProcessSpawner";
import * as OpenCodeRuntime from "./opencodeRuntime.ts";
const encoder = new TextEncoder();
function exitedProcess(stdout: string, stderr: string, exitCode: number) {
return ChildProcessSpawner.makeHandle({
pid: ChildProcessSpawner.ProcessId(123),
stdout: Stream.make(encoder.encode(stdout)),
stderr: Stream.make(encoder.encode(stderr)),
all: Stream.empty,
exitCode: Effect.yieldNow.pipe(
Effect.andThen(Effect.succeed(ChildProcessSpawner.ExitCode(exitCode))),
),
isRunning: Effect.succeed(false),
kill: () => Effect.void,
stdin: Sink.drain,
getInputFd: () => Sink.drain,
getOutputFd: () => Stream.empty,
unref: Effect.succeed(Effect.void),
});
}
const netService = {
canListenOnHost: () => Effect.succeed(true),
isPortAvailableOnLoopback: () => Effect.succeed(true),
reserveLoopbackPort: () => Effect.succeed(12_345),
findAvailablePort: () => Effect.succeed(12_345),
} satisfies NetService.NetServiceShape;
describe("OpenCodeRuntime", () => {
it.effect("retains SDK status and cause without copying arbitrary response bodies", () => {
const cause = {
response: { status: 401 },
body: { accessToken: "sdk-secret" },
};
return Effect.gen(function* () {
const result = yield* Effect.result(
OpenCodeRuntime.runOpenCodeSdk("session.get", () => Promise.reject(cause)),
);
assert.isTrue(Result.isFailure(result));
if (Result.isFailure(result)) {
assert.instanceOf(result.failure, OpenCodeRuntime.OpenCodeRuntimeError);
assert.equal(result.failure.operation, "session.get");
assert.equal(result.failure.detail, "OpenCode SDK request failed.");
assert.equal(result.failure.responseStatus, 401);
assert.strictEqual(result.failure.cause, cause);
assert.notInclude(result.failure.detail, "sdk-secret");
assert.isFalse("body" in result.failure);
}
});
});
it.live("records startup output sizes without retaining process streams", () => {
const stdout = "startup output with a credential sdk-secret";
const stderr = "startup failed";
const layer = Layer.mergeAll(
Layer.succeed(
ChildProcessSpawner.ChildProcessSpawner,
ChildProcessSpawner.make(() => Effect.succeed(exitedProcess(stdout, stderr, 17))),
),
Layer.succeed(NetService.NetService, netService),
Layer.succeed(HostProcessPlatform, "win32"),
);
return Effect.gen(function* () {
const runtime = yield* OpenCodeRuntime.make;
const result = yield* Effect.result(
Effect.scoped(
runtime.startOpenCodeServerProcess({
binaryPath: "opencode",
port: 12_345,
}),
),
);
assert.isTrue(Result.isFailure(result));
if (Result.isFailure(result)) {
assert.instanceOf(result.failure, OpenCodeRuntime.OpenCodeRuntimeError);
assert.equal(result.failure.exitCode, 17);
assert.equal(result.failure.argumentCount, 3);
assert.equal(result.failure.stdoutBytes, encoder.encode(stdout).byteLength);
assert.equal(result.failure.stderrBytes, encoder.encode(stderr).byteLength);
assert.isFalse("stdout" in result.failure);
assert.isFalse("stderr" in result.failure);
assert.notInclude(result.failure.detail, "sdk-secret");
}
}).pipe(Effect.provide(layer));
});
});