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
Original file line number Diff line number Diff line change
Expand Up @@ -201,6 +201,7 @@ function managerFixture(options?: {
readonly restoreConnectionOnSpawn?: boolean;
readonly tempDir?: string;
readonly platform?: NodeJS.Platform;
readonly injectBridge?: boolean;
}) {
const commands: CapturedCommand[] = [];
const processes: FakeProcess[] = [];
Expand Down Expand Up @@ -259,7 +260,7 @@ function managerFixture(options?: {
readinessRetryDelay: Duration.zero,
readinessRetries: 4,
shutdownTimeout: Duration.zero,
bridge,
...(options?.injectBridge === false ? {} : { bridge }),
}).pipe(Effect.provide(Layer.merge(NodeServices.layer, spawner)));
return {
make,
Expand Down Expand Up @@ -309,11 +310,12 @@ describe("PrimeAgentDaemonManager paths and environment", () => {
});

describe("PrimeAgentDaemonManager lifecycle", () => {
it.effect("fails closed on Windows before spawning an unauthenticated named-pipe daemon", () => {
const fixture = managerFixture({ platform: "win32" });
it.effect("fails closed on Windows before loading Prime or spawning a named-pipe daemon", () => {
const fixture = managerFixture({ platform: "win32", injectBridge: false });
return Effect.gen(function* () {
const error = yield* Effect.flip(fixture.make);
expect(error).toMatchObject({
socket: fixture.paths.socket,
reason: "transport-security-unavailable",
detail: expect.stringContaining("verified per-user ACL or authenticated handshake"),
});
Expand Down
18 changes: 8 additions & 10 deletions apps/server/src/provider/prime/PrimeAgentDaemonManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -273,23 +273,21 @@ export const makePrimeAgentDaemonManager = Effect.fn("makePrimeAgentDaemonManage
const hostPlatform = yield* HostProcessPlatform;
const hostEnvironment = yield* HostProcessEnvironment;
const platform = input.platform ?? hostPlatform;
const bridge = input.bridge ?? (yield* loadPrimeAgentDaemonBridge(input.executablePath));
const paths = derivePrimeAgentDaemonPaths({ ...input, platform });
const defaultSocket = bridge.defaultDaemonSocketPath();
const socket =
paths.socket === defaultSocket
? platform === "win32"
? `${paths.socket}-pylon-private`
: paths.socket.replace(/\.sock$/, "-pylon-private.sock")
: paths.socket;
const sessionDir = paths.sessionDir;
if (platform === "win32") {
return yield* managerError(
socket,
paths.socket,
"transport-security-unavailable",
"Prime Agent daemon mode is disabled on Windows until its named pipe has a verified per-user ACL or authenticated handshake.",
);
}
const bridge = input.bridge ?? (yield* loadPrimeAgentDaemonBridge(input.executablePath));
const defaultSocket = bridge.defaultDaemonSocketPath();
const socket =
paths.socket === defaultSocket
? paths.socket.replace(/\.sock$/, "-pylon-private.sock")
: paths.socket;
const sessionDir = paths.sessionDir;
const timeoutMs = input.connectTimeoutMs ?? 10_000;
const readinessSchedule = Schedule.max([
Schedule.spaced(input.readinessRetryDelay ?? Duration.millis(50)),
Expand Down
Loading