Something went wrong. Try again.
fork of prime agent with changes i want but are not upstreamable probqbly (and some fixes)
Something went wrong. Try again.
4.3 kB · 120 lines
TypeScript
at main
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121import { chmodSync, mkdtempSync, rmSync, writeFileSync } from "node:fs";import { tmpdir } from "node:os";import { join } from "node:path";import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";import { ReplKernelManager } from "../src/core/kernel/index.js";
let tempDir = "";
function writeExecutable(filePath: string, content: string): void { writeFileSync(filePath, content); chmodSync(filePath, 0o755);}
describe("ReplKernelManager startup", () => { beforeEach(() => { tempDir = mkdtempSync(join(tmpdir(), "prime-agent-repl-startup-")); });
afterEach(() => { if (tempDir) { rmSync(tempDir, { recursive: true, force: true }); tempDir = ""; } });
it("surfaces kernels that exit before ready with the stderr tail", async () => { const python = join(tempDir, "python"); writeExecutable(python, ["#!/bin/sh", 'echo "fake runtime died before ready" >&2', "exit 42", ""].join("\n")); const errorSpy = vi.spyOn(console, "error").mockImplementation(() => {}); const manager = new ReplKernelManager({ python, cwd: tempDir });
try { await expect(manager.execute("print(1)")).rejects.toThrow( /Kernel exited before ready[\s\S]*fake runtime died before ready/, ); } finally { errorSpy.mockRestore(); await manager.shutdown({ snapshot: true, drainHostRequests: true }); } });
it("completes teardown while an inherited grandchild keeps writing stderr", async () => { const python = join(tempDir, "python"); writeExecutable( python, [ "#!/bin/sh", // A busy writer inherits fd 2 and survives the kernel: its stream // never goes quiet and never EOFs. "sh -c 'while :; do echo post-mortem noise; done' >&2 &", "exit 42", "", ].join("\n"), ); const stderrLogPath = join(tempDir, "kernel-stderr.log"); const errorSpy = vi.spyOn(console, "error").mockImplementation(() => {}); const manager = new ReplKernelManager({ python, cwd: tempDir, stderrLogPath });
try { // Well under the 30s ready timeout: teardown must not wait for the // grandchild (destroying the pipe kills it with SIGPIPE). await expect(manager.execute("print(1)")).rejects.toThrow(/Kernel exited before ready/); } finally { errorSpy.mockRestore(); await manager.shutdown({ snapshot: true, drainHostRequests: true }); } }, 15000);
it("fails a runtime announcing an unexpected protocol version", async () => { const python = join(tempDir, "python"); writeExecutable( python, ["#!/bin/sh", `echo '{"event":"ready","protocol":1,"python":"3.13.0"}'`, "exec sleep 60", ""].join("\n"), ); const errorSpy = vi.spyOn(console, "error").mockImplementation(() => {}); const manager = new ReplKernelManager({ python, cwd: tempDir });
try { await expect(manager.execute("print(1)")).rejects.toThrow(/speaks protocol 1, expected 3/); } finally { errorSpy.mockRestore(); await manager.shutdown({ snapshot: true, drainHostRequests: true }); } });
it("rejects promptly when the kernel process fails to spawn", async () => { const python = join(tempDir, "does-not-exist"); const errorSpy = vi.spyOn(console, "error").mockImplementation(() => {}); const manager = new ReplKernelManager({ python, cwd: tempDir });
try { // Without prompt rejection this would ride out the 30s ready timeout. await expect(manager.start()).rejects.toThrow(/ENOENT/); } finally { errorSpy.mockRestore(); await manager.shutdown({ snapshot: true, drainHostRequests: true }); } });
it("times out a runtime that never sends ready", async () => { vi.useFakeTimers(); const python = join(tempDir, "python"); writeExecutable(python, ["#!/bin/sh", "exec sleep 120", ""].join("\n")); const errorSpy = vi.spyOn(console, "error").mockImplementation(() => {}); const manager = new ReplKernelManager({ python, cwd: tempDir });
try { const startPromise = manager.start(); const expectation = expect(startPromise).rejects.toThrow(/did not become ready within 30000ms/); await vi.advanceTimersByTimeAsync(30_000); // The failure path runs a graceful shutdown bounded by its own deadline. await vi.advanceTimersByTimeAsync(5_000); await expectation; } finally { vi.useRealTimers(); errorSpy.mockRestore(); await manager.shutdown({ snapshot: true, drainHostRequests: true }); } });});