Refactor runtime around isolated bot instances

This commit is contained in:
zenord
2026-08-16 23:45:09 +08:00
parent 914579a94c
commit f9fb4ef776
51 changed files with 2355 additions and 1459 deletions
+82
View File
@@ -0,0 +1,82 @@
import assert from "node:assert/strict";
import fs from "node:fs";
import os from "node:os";
import net from "node:net";
import path from "node:path";
import test from "node:test";
import { parseConfig } from "../src/config.js";
import { createGatewayRuntime, startServer } from "../src/server.js";
const fixture = path.resolve("test/fixtures/fake-acp-agent.mjs");
test("server mounts only selected platform and exposes non-secret identity health", { concurrency: false }, async () => {
const home = await fs.promises.mkdtemp(path.join(os.tmpdir(), "gori-server-"));
const previous = process.env.GORI_AGENT_HOME; process.env.GORI_AGENT_HOME = home;
const secret = "never-expose-this-secret";
const config = parseConfig({
configVersion: 3,
bot: { id: "route-bot", workspace: path.resolve("."), persona: "", agent: { id: "fake", command: process.execPath, args: [fixture] }, permissions: { mode: "deny" } },
gateway: { platform: { type: "webhook", secret } },
runtime: {}
});
const runtime = await createGatewayRuntime(config);
const server = runtime.app.listen(0, "127.0.0.1");
await new Promise<void>((resolve) => server.once("listening", resolve));
try {
const address = server.address(); assert.ok(address && typeof address !== "string");
const base = `http://127.0.0.1:${address.port}`;
const health = await (await fetch(`${base}/health`)).text();
assert.match(health, /"configVersion":3/); assert.match(health, /"botId":"route-bot"/); assert.match(health, /"platform":"webhook"/); assert.doesNotMatch(health, new RegExp(secret));
assert.equal((await fetch(`${base}/webhook/qq`, { method: "POST", headers: { "content-type": "application/json" }, body: "{}" })).status, 404);
assert.notEqual((await fetch(`${base}/webhook/generic`, { method: "POST", headers: { "content-type": "application/json" }, body: "{}" })).status, 404);
} finally {
await new Promise<void>((resolve, reject) => server.close((error) => error ? reject(error) : resolve()));
await runtime.shutdown();
if (previous === undefined) delete process.env.GORI_AGENT_HOME; else process.env.GORI_AGENT_HOME = previous;
}
});
test("QQ websocket mode does not mount the QQ webhook route", { concurrency: false }, async () => {
const home = await fs.promises.mkdtemp(path.join(os.tmpdir(), "gori-server-qq-"));
const previous = process.env.GORI_AGENT_HOME; process.env.GORI_AGENT_HOME = home;
const config = parseConfig({
configVersion: 3,
bot: { id: "qq-bot", workspace: path.resolve("."), persona: "", agent: { id: "fake", command: process.execPath, args: [fixture] }, permissions: { mode: "deny" } },
gateway: { platform: { type: "qq", connectionMode: "websocket", appId: "id", clientSecret: "secret", botNames: ["Bot"] } },
runtime: {}
});
const runtime = await createGatewayRuntime(config);
const server = runtime.app.listen(0, "127.0.0.1");
await new Promise<void>((resolve) => server.once("listening", resolve));
try {
const address = server.address(); assert.ok(address && typeof address !== "string");
const response = await fetch(`http://127.0.0.1:${address.port}/webhook/qq`, { method: "POST", headers: { "content-type": "application/json" }, body: "{}" });
assert.equal(response.status, 404);
} finally {
await new Promise<void>((resolve, reject) => server.close((error) => error ? reject(error) : resolve()));
await runtime.shutdown();
if (previous === undefined) delete process.env.GORI_AGENT_HOME; else process.env.GORI_AGENT_HOME = previous;
}
});
test("listen failure releases the session state lock", { concurrency: false }, async () => {
const home = await fs.promises.mkdtemp(path.join(os.tmpdir(), "gori-server-conflict-"));
const previous = process.env.GORI_AGENT_HOME; process.env.GORI_AGENT_HOME = home;
const occupied = net.createServer();
await new Promise<void>((resolve) => occupied.listen(0, "127.0.0.1", resolve));
const address = occupied.address(); assert.ok(address && typeof address !== "string");
const config = parseConfig({
configVersion: 3,
bot: { id: "conflict-bot", workspace: path.resolve("."), persona: "", agent: { id: "fake", command: process.execPath, args: [fixture] }, permissions: { mode: "deny" } },
gateway: { server: { host: "127.0.0.1", port: address.port }, platform: { type: "webhook", secret: "secret" } },
runtime: {}
});
try {
await assert.rejects(startServer(config), /EADDRINUSE/);
const runtime = await createGatewayRuntime(config);
await runtime.shutdown();
} finally {
await new Promise<void>((resolve, reject) => occupied.close((error) => error ? reject(error) : resolve()));
if (previous === undefined) delete process.env.GORI_AGENT_HOME; else process.env.GORI_AGENT_HOME = previous;
}
});