源码快照 @ 2026-09-02 (source-only, 剔除非源码素材)
This commit is contained in:
@@ -0,0 +1,449 @@
|
||||
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");
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user