import { describe, it } from "node:test"; import assert from "node:assert/strict"; import { mkdtemp, readFile, rm, writeFile } from "node:fs/promises"; import os from "node:os"; import path from "node:path"; import { fileURLToPath, pathToFileURL } from "node:url"; import { commandMatchesPackagedSidecar, createRuntimeManager, embeddedServerImportUrl, migrateOpenworkServerTokenStore, prepareRuntimeWorkspaceRoot, prioritizeWorkspacePaths, resetRuntimeStatesAfterFailedServerStart, resolveEvalLocalServerDelayMs, resolveOpenworkServerConfigPath, resolveOpenworkServerReuse, seedWorkspacePathsForEmbeddedServer, selectStickyOpenworkPortWorkspace, snapshotEngineState, snapshotOpenworkServerState, } from "./runtime.mjs"; describe("workspace root preparation", () => { it("reports an inaccessible Windows drive as a controlled recoverable error", async () => { const mkdirError = Object.assign(new Error("drive is unavailable"), { code: "ENOENT" }); let attemptedPath = null; await assert.rejects( prepareRuntimeWorkspaceRoot("\\\\?\\Z:\\Disconnected\\Workspace", { platform: "win32", mkdirImpl: async (workspaceRoot) => { attemptedPath = workspaceRoot; throw mkdirError; }, }), (error) => { assert.ok(error instanceof Error); assert.ok("code" in error); assert.ok("workspacePath" in error); assert.equal(error.code, "workspace_inaccessible"); assert.equal(error.workspacePath, "\\\\?\\Z:\\Disconnected\\Workspace"); assert.equal(error.cause, mkdirError); return true; }, ); assert.equal(attemptedPath, "Z:\\Disconnected\\Workspace"); }); it("returns the runtime lifecycle to idle after root preparation fails", async () => { const root = await mkdtemp(path.join(os.tmpdir(), "openwork-runtime-root-")); try { const manager = createRuntimeManager({ app: { getPath: (name) => name === "exe" ? path.join(root, "OpenWork.exe") : root, isPackaged: false, }, desktopRoot: path.dirname(fileURLToPath(import.meta.url)), listLocalWorkspacePaths: async () => [], localManagedMcpVaultKey: "test-key", workspaceMkdir: async () => { throw Object.assign(new Error("network share disconnected"), { code: "ENOENT" }); }, workspacePlatform: "win32", }); await assert.rejects( manager.engineStart("\\\\server\\share\\Workspace"), (error) => error instanceof Error && "code" in error && error.code === "workspace_inaccessible", ); const status = await manager.runtimeStatus(); assert.equal(status.lifecycleState, "idle"); assert.equal(status.engine.running, false); assert.equal(status.engine.projectDir, null); assert.equal(status.openworkServer.running, false); } finally { await rm(root, { recursive: true, force: true }); } }); }); describe("bundled OpenCode runtime", () => { it("pins the engine release containing the timestamp-based session loop repair", async () => { const constantsPath = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "../../../constants.json"); const constants = JSON.parse(await readFile(constantsPath, "utf8")); // OpenCode #40990 stops old assistant messages with lexicographically // later IDs from short-circuiting a newly appended user turn. assert.equal(constants.opencodeVersion, "v1.18.18"); }); }); describe("openwork server snapshot", () => { it("reports a running in-process server", () => { const snapshot = snapshotOpenworkServerState({ child: null, childExited: true, inProcess: true, }); assert.equal(snapshot.running, true); }); }); describe("resolveOpenworkServerReuse", () => { const healthy = { forceRestart: undefined, inProcess: true, lifecycleState: "healthy", remoteAccessEnabled: false, requestedRemoteAccess: false, currentProjectDir: "/Users/person/workspace-a", requestedProjectDir: "/Users/person/workspace-a", platform: "darwin", }; it("reuses the running server for the same workspace", () => { assert.deepEqual(resolveOpenworkServerReuse(healthy), { reuse: true, retarget: false }); }); it("retargets instead of restarting when a different workspace is requested", () => { // Regression: a workspace switch (e.g. opening Settings while another // workspace is routed) used to tear the server down here, aborting every // in-flight run in the workspace being left. assert.deepEqual( resolveOpenworkServerReuse({ ...healthy, requestedProjectDir: "/Users/person/workspace-b" }), { reuse: true, retarget: true }, ); }); it("treats case-only path differences as the same workspace on win32", () => { assert.deepEqual( resolveOpenworkServerReuse({ ...healthy, platform: "win32", currentProjectDir: "C:\\Work\\Space", requestedProjectDir: "c:\\work\\space", }), { reuse: true, retarget: false }, ); }); it("gives up the server only for an explicit restart, host rebind, or unhealthy runtime", () => { assert.deepEqual( resolveOpenworkServerReuse({ ...healthy, forceRestart: true }), { reuse: false, retarget: false }, ); assert.deepEqual( resolveOpenworkServerReuse({ ...healthy, requestedRemoteAccess: true }), { reuse: false, retarget: false }, ); assert.deepEqual( resolveOpenworkServerReuse({ ...healthy, lifecycleState: "starting" }), { reuse: false, retarget: false }, ); assert.deepEqual( resolveOpenworkServerReuse({ ...healthy, inProcess: false }), { reuse: false, retarget: false }, ); }); }); describe("prioritizeWorkspacePaths", () => { it("keeps the active runtime workspace first", () => { assert.deepEqual( prioritizeWorkspacePaths("/workspace/current", ["/workspace/other", "/workspace/current"]), ["/workspace/current", "/workspace/other"], ); }); it("dedupes equivalent paths", () => { assert.deepEqual( prioritizeWorkspacePaths("/workspace/current/../current", ["/workspace/current"]), ["/workspace/current/../current"], ); }); }); describe("seedWorkspacePathsForEmbeddedServer", () => { it("uses persisted server config instead of Electron workspace state once config exists", () => { assert.deepEqual( seedWorkspacePathsForEmbeddedServer(["/workspace/legacy"], true), [], ); }); it("seeds from Electron workspace state before server config exists", () => { assert.deepEqual( seedWorkspacePathsForEmbeddedServer(["/workspace/first"], false), ["/workspace/first"], ); }); }); describe("selectStickyOpenworkPortWorkspace", () => { it("uses the requested workspace even when server config owns workspace loading", () => { assert.equal( selectStickyOpenworkPortWorkspace(["/workspace/current"], []), "/workspace/current", ); }); it("falls back to server workspace paths when no requested path is available", () => { assert.equal( selectStickyOpenworkPortWorkspace([], ["/workspace/from-server"]), "/workspace/from-server", ); }); }); describe("resolveEvalLocalServerDelayMs", () => { it("enables only positive finite eval delays", () => { assert.equal(resolveEvalLocalServerDelayMs({ OPENWORK_EVAL_LOCAL_SERVER_DELAY_MS: "3000" }), 3000); assert.equal(resolveEvalLocalServerDelayMs({ OPENWORK_EVAL_LOCAL_SERVER_DELAY_MS: "0" }), 0); assert.equal(resolveEvalLocalServerDelayMs({ OPENWORK_EVAL_LOCAL_SERVER_DELAY_MS: "-1" }), 0); assert.equal(resolveEvalLocalServerDelayMs({ OPENWORK_EVAL_LOCAL_SERVER_DELAY_MS: "Infinity" }), 0); assert.equal(resolveEvalLocalServerDelayMs({ OPENWORK_EVAL_LOCAL_SERVER_DELAY_MS: "invalid" }), 0); }); }); describe("commandMatchesPackagedSidecar", () => { it("matches packaged opencode sidecars with platform suffixes", () => { assert.equal( commandMatchesPackagedSidecar( "/Applications/OpenWork.app/Contents/Resources/sidecars/opencode-aarch64-apple-darwin serve --hostname 127.0.0.1 --port 49174 --cors *", ["/Applications/OpenWork.app/Contents/Resources/sidecars"], ), true, ); }); it("does not match unrelated opencode processes outside sidecar directories", () => { assert.equal( commandMatchesPackagedSidecar( "/usr/local/bin/opencode serve --hostname 127.0.0.1 --port 49174", ["/Applications/OpenWork.app/Contents/Resources/sidecars"], ), false, ); }); }); describe("embeddedServerImportUrl", () => { it("returns the same file URL for unchanged metadata", async () => { const dir = await mkdtemp(path.join(os.tmpdir(), "openwork-runtime-")); try { const embeddedPath = path.join(dir, "embedded.js"); await writeFile(embeddedPath, "export const value = 1;\n"); const first = embeddedServerImportUrl(embeddedPath); const second = embeddedServerImportUrl(embeddedPath); const url = new URL(first); assert.equal(first, second); assert.equal(url.protocol, "file:"); assert.equal(fileURLToPath(url), embeddedPath); assert.ok(url.searchParams.get("mtimeMs")); assert.equal(url.searchParams.get("size"), String("export const value = 1;\n".length)); } finally { await rm(dir, { recursive: true, force: true }); } }); it("changes when the file metadata changes", async () => { const dir = await mkdtemp(path.join(os.tmpdir(), "openwork-runtime-")); try { const embeddedPath = path.join(dir, "embedded.js"); await writeFile(embeddedPath, "export const value = 1;\n"); const first = embeddedServerImportUrl(embeddedPath); await writeFile(embeddedPath, "export const value = 12;\n"); assert.notEqual(embeddedServerImportUrl(embeddedPath), first); } finally { await rm(dir, { recursive: true, force: true }); } }); it("falls back to the plain file URL if stat fails", () => { const missingPath = path.join(os.tmpdir(), "openwork-missing-embedded.js"); assert.equal(embeddedServerImportUrl(missingPath), pathToFileURL(missingPath).href); }); }); describe("resolveOpenworkServerConfigPath", () => { it("respects explicit server config path", () => { assert.equal( resolveOpenworkServerConfigPath({ OPENWORK_SERVER_CONFIG: "/tmp/openwork/server.json" }), "/tmp/openwork/server.json", ); }); it("uses XDG config home on Unix", () => { if (process.platform === "win32") return; assert.equal( resolveOpenworkServerConfigPath({ XDG_CONFIG_HOME: "/tmp/xdg" }), "/tmp/xdg/openwork/server.json", ); }); }); describe("OpenWork server credential persistence", () => { it("deterministically migrates legacy workspace credentials into one server bundle", () => { const migrated = migrateOpenworkServerTokenStore({ version: 1, workspaces: { "/workspace/z": { clientToken: "client-z", hostToken: "host-z", ownerToken: "owner-z", updatedAt: 20, }, "/workspace/a": { clientToken: "client-a", hostToken: "host-a", ownerToken: "owner-a", updatedAt: 20, }, "/workspace/old": { clientToken: "client-old", hostToken: "host-old", ownerToken: "owner-old", updatedAt: 10, }, }, }); assert.deepEqual(migrated, { version: 2, credentials: { clientToken: "client-a", hostToken: "host-a", ownerToken: "owner-a", updatedAt: 20, }, }); assert.deepEqual(migrateOpenworkServerTokenStore(migrated), migrated); }); }); describe("snapshotEngineState", () => { it("reports server-managed OpenCode liveness and pid without a child handle", () => { const snapshot = snapshotEngineState({ child: null, childExited: false, runtime: "direct", projectDir: "/workspace/current", hostname: "127.0.0.1", port: 4097, baseUrl: "http://127.0.0.1:4097", opencodeUsername: null, opencodePassword: null, opencodeBinPath: null, opencodeBinSource: null, managedByServer: true, managedPid: 12345, managedIsAlive: () => true, lastStdout: null, lastStderr: null, execution: null, }); assert.equal(snapshot.running, true); assert.equal(snapshot.managedByServer, true); assert.equal(snapshot.pid, 12345); }); }); describe("resetRuntimeStatesAfterFailedServerStart", () => { function staleServerState() { return { child: null, childExited: true, inProcess: true, remoteAccessEnabled: true, host: "127.0.0.1", port: 4141, baseUrl: "http://127.0.0.1:4141", connectUrl: null, mdnsUrl: null, lanUrl: null, clientToken: "client-token", ownerToken: "owner-token", hostToken: "host-token", managedOpencodeBinPath: "/usr/local/bin/opencode", managedOpencodeBinSource: "known-location", lastStdout: "server stdout", lastStderr: "server stderr", managedOpencodeExecution: { command: "opencode" }, }; } function staleEngineState() { return { child: null, childExited: false, runtime: "direct", projectDir: "/workspace/current", hostname: "127.0.0.1", port: 4097, baseUrl: "http://127.0.0.1:4097", opencodeUsername: "user", opencodePassword: "pass", opencodeBinPath: "/usr/local/bin/opencode", opencodeBinSource: "known-location", managedByServer: true, managedPid: 12345, managedIsAlive: () => true, lastStdout: "engine stdout", lastStderr: "engine stderr", execution: { command: "opencode" }, }; } it("clears a dead managed runtime so snapshots cannot report it running", () => { const serverState = staleServerState(); const engineState = staleEngineState(); resetRuntimeStatesAfterFailedServerStart(serverState, engineState, { manageOpencode: true }); assert.equal(serverState.inProcess, false); assert.equal(serverState.port, null); assert.equal(serverState.baseUrl, null); assert.equal(serverState.ownerToken, null); // Diagnostics survive the reset. assert.equal(serverState.lastStdout, "server stdout"); assert.equal(serverState.lastStderr, "server stderr"); assert.equal(engineState.baseUrl, null); assert.equal(engineState.managedByServer, false); assert.equal(engineState.managedPid, null); assert.equal(snapshotEngineState(engineState).running, false); // A retry via engineRestart still knows its workspace. assert.equal(engineState.projectDir, "/workspace/current"); assert.equal(engineState.lastStderr, "engine stderr"); }); it("leaves an external engine untouched when the failed start did not manage it", () => { const serverState = staleServerState(); const engineState = staleEngineState(); engineState.managedByServer = false; resetRuntimeStatesAfterFailedServerStart(serverState, engineState, { manageOpencode: false }); assert.equal(serverState.inProcess, false); assert.equal(engineState.baseUrl, "http://127.0.0.1:4097"); assert.equal(engineState.projectDir, "/workspace/current"); }); });