128 lines
4.8 KiB
TypeScript
128 lines
4.8 KiB
TypeScript
import assert from "node:assert/strict";
|
|
import test from "node:test";
|
|
import os from "node:os";
|
|
import path from "node:path";
|
|
import { mkdtemp, rm, writeFile } from "node:fs/promises";
|
|
import {
|
|
getHermesBackendAvailabilityForTesting,
|
|
getHermesBackendConfigForTesting,
|
|
isHermesBackendConfiguredForTesting,
|
|
} from "../src/lib/execution/backends/hermes-config.ts";
|
|
|
|
function snapshotEnv() {
|
|
return {
|
|
BOSS_HERMES_ENABLED: process.env.BOSS_HERMES_ENABLED,
|
|
BOSS_HERMES_COMMAND: process.env.BOSS_HERMES_COMMAND,
|
|
BOSS_HERMES_ARGS: process.env.BOSS_HERMES_ARGS,
|
|
BOSS_HERMES_WORKDIR: process.env.BOSS_HERMES_WORKDIR,
|
|
BOSS_HERMES_TIMEOUT_MS: process.env.BOSS_HERMES_TIMEOUT_MS,
|
|
BOSS_HERMES_DEFAULT_MODEL: process.env.BOSS_HERMES_DEFAULT_MODEL,
|
|
BOSS_HERMES_TOOLSETS: process.env.BOSS_HERMES_TOOLSETS,
|
|
BOSS_HERMES_SKILLS: process.env.BOSS_HERMES_SKILLS,
|
|
};
|
|
}
|
|
|
|
function restoreEnv(snapshot: ReturnType<typeof snapshotEnv>) {
|
|
process.env.BOSS_HERMES_ENABLED = snapshot.BOSS_HERMES_ENABLED;
|
|
process.env.BOSS_HERMES_COMMAND = snapshot.BOSS_HERMES_COMMAND;
|
|
process.env.BOSS_HERMES_ARGS = snapshot.BOSS_HERMES_ARGS;
|
|
process.env.BOSS_HERMES_WORKDIR = snapshot.BOSS_HERMES_WORKDIR;
|
|
process.env.BOSS_HERMES_TIMEOUT_MS = snapshot.BOSS_HERMES_TIMEOUT_MS;
|
|
process.env.BOSS_HERMES_DEFAULT_MODEL = snapshot.BOSS_HERMES_DEFAULT_MODEL;
|
|
process.env.BOSS_HERMES_TOOLSETS = snapshot.BOSS_HERMES_TOOLSETS;
|
|
process.env.BOSS_HERMES_SKILLS = snapshot.BOSS_HERMES_SKILLS;
|
|
}
|
|
|
|
test("Hermes backend 在未配置时默认关闭", () => {
|
|
const previous = snapshotEnv();
|
|
|
|
delete process.env.BOSS_HERMES_ENABLED;
|
|
delete process.env.BOSS_HERMES_COMMAND;
|
|
delete process.env.BOSS_HERMES_ARGS;
|
|
delete process.env.BOSS_HERMES_WORKDIR;
|
|
delete process.env.BOSS_HERMES_TIMEOUT_MS;
|
|
delete process.env.BOSS_HERMES_DEFAULT_MODEL;
|
|
delete process.env.BOSS_HERMES_TOOLSETS;
|
|
delete process.env.BOSS_HERMES_SKILLS;
|
|
|
|
const config = getHermesBackendConfigForTesting();
|
|
|
|
assert.equal(config.enabled, false);
|
|
assert.equal(config.command, "hermes");
|
|
assert.equal(isHermesBackendConfiguredForTesting(config), false);
|
|
|
|
restoreEnv(previous);
|
|
});
|
|
|
|
test("Hermes backend 在配置完整时返回 command、args、toolsets 和 skills", () => {
|
|
const previous = snapshotEnv();
|
|
|
|
process.env.BOSS_HERMES_ENABLED = "true";
|
|
process.env.BOSS_HERMES_COMMAND = "hermes";
|
|
process.env.BOSS_HERMES_ARGS = "--profile prod";
|
|
process.env.BOSS_HERMES_WORKDIR = "/tmp/hermes";
|
|
process.env.BOSS_HERMES_TIMEOUT_MS = "39000";
|
|
process.env.BOSS_HERMES_DEFAULT_MODEL = "gpt-5.4";
|
|
process.env.BOSS_HERMES_TOOLSETS = "web,terminal";
|
|
process.env.BOSS_HERMES_SKILLS = "boss-dev,github";
|
|
|
|
const config = getHermesBackendConfigForTesting();
|
|
|
|
assert.equal(config.enabled, true);
|
|
assert.equal(config.command, "hermes");
|
|
assert.deepEqual(config.args, ["--profile", "prod"]);
|
|
assert.equal(config.cwd, "/tmp/hermes");
|
|
assert.equal(config.timeoutMs, 39000);
|
|
assert.equal(config.defaultModel, "gpt-5.4");
|
|
assert.deepEqual(config.toolsets, ["web", "terminal"]);
|
|
assert.deepEqual(config.skills, ["boss-dev", "github"]);
|
|
assert.equal(isHermesBackendConfiguredForTesting(config), true);
|
|
|
|
restoreEnv(previous);
|
|
});
|
|
|
|
test("Hermes backend availability 会在可执行命令和脚本都存在时返回 ready", async () => {
|
|
const previous = snapshotEnv();
|
|
const tempDir = await mkdtemp(path.join(os.tmpdir(), "boss-hermes-config-"));
|
|
const scriptPath = path.join(tempDir, "hermes-smoke.mjs");
|
|
await writeFile(scriptPath, "console.log('ok');\n", "utf8");
|
|
|
|
process.env.BOSS_HERMES_ENABLED = "true";
|
|
process.env.BOSS_HERMES_COMMAND = process.execPath;
|
|
process.env.BOSS_HERMES_ARGS = scriptPath;
|
|
process.env.BOSS_HERMES_WORKDIR = tempDir;
|
|
|
|
try {
|
|
const availability = await getHermesBackendAvailabilityForTesting();
|
|
|
|
assert.equal(availability.status, "ready");
|
|
assert.equal(availability.selectable, true);
|
|
assert.equal(availability.reason, "ready");
|
|
} finally {
|
|
restoreEnv(previous);
|
|
await rm(tempDir, { recursive: true, force: true });
|
|
}
|
|
});
|
|
|
|
test("Hermes backend availability 会在脚本参数不存在时返回不可选", async () => {
|
|
const previous = snapshotEnv();
|
|
const tempDir = await mkdtemp(path.join(os.tmpdir(), "boss-hermes-config-"));
|
|
const missingScript = path.join(tempDir, "missing-hermes-script.mjs");
|
|
|
|
process.env.BOSS_HERMES_ENABLED = "true";
|
|
process.env.BOSS_HERMES_COMMAND = process.execPath;
|
|
process.env.BOSS_HERMES_ARGS = missingScript;
|
|
process.env.BOSS_HERMES_WORKDIR = tempDir;
|
|
|
|
try {
|
|
const availability = await getHermesBackendAvailabilityForTesting();
|
|
|
|
assert.equal(availability.status, "misconfigured");
|
|
assert.equal(availability.selectable, false);
|
|
assert.equal(availability.reason, "script_not_found");
|
|
} finally {
|
|
restoreEnv(previous);
|
|
await rm(tempDir, { recursive: true, force: true });
|
|
}
|
|
});
|