Files
gori-agent/test/cli-config-file.test.ts
2026-08-18 18:48:47 +08:00

47 lines
2.3 KiB
TypeScript

import assert from "node:assert/strict";
import fs from "node:fs";
import os from "node:os";
import path from "node:path";
import test from "node:test";
import { parseConfig } from "../src/config.js";
import { assertOperationalConfig, loadConfigFile, writeConfigFile } from "../src/cli/config-file.js";
const config = parseConfig({
configVersion: 3,
bot: { id: "file-bot", workspace: "/tmp", persona: "", agent: { id: "node", command: process.execPath, args: ["acp"] }, permissions: { mode: "deny" } },
gateway: { platform: { type: "webhook", secret: "secret" } },
runtime: {}
});
test("runtime config loading fails closed instead of seeding example", () => {
const missing = path.join(os.tmpdir(), `gori-missing-${Date.now()}`, "config.json");
assert.throws(() => loadConfigFile(missing), /documentation only/);
});
test("config writes are atomic and mode 0600", async () => {
const dir = await fs.promises.mkdtemp(path.join(os.tmpdir(), "gori-config-write-"));
const file = path.join(dir, "config.json");
writeConfigFile(file, config);
assert.equal((await fs.promises.stat(dir)).mode & 0o777, 0o700);
assert.equal((await fs.promises.stat(file)).mode & 0o777, 0o600);
assert.equal(loadConfigFile(file).config.bot.id, "file-bot");
assert.equal((await fs.promises.readdir(dir)).some((name) => name.endsWith(".tmp")), false);
});
test("operational validation rejects placeholders, unsafe ACP args, and every credential family", () => {
assert.doesNotThrow(() => assertOperationalConfig(config));
const unsafeArgs = parseConfig({ ...config, bot: { ...config.bot, agent: { ...config.bot.agent, args: ["--yolo", "acp"] } } });
assert.throws(() => assertOperationalConfig(unsafeArgs), /exactly \['acp'\]/);
const platforms = [
{ type: "qq", appId: "QQ_APP_ID", clientSecret: "QQ_CLIENT_SECRET", botNames: ["QQ_BOT_NAME"] },
{ type: "feishu", appId: "FEISHU_APP_ID", appSecret: "FEISHU_APP_SECRET" },
{ type: "wecom", corpId: "WECOM_CORP_ID", agentId: "WECOM_AGENT_ID", secret: "WECOM_SECRET" },
{ type: "webhook", secret: "WEBHOOK_SECRET" },
{ type: "weixin", secret: "WEIXIN_SECRET" }
];
for (const platform of platforms) {
const candidate = parseConfig({ ...config, gateway: { ...config.gateway, platform } });
assert.throws(() => assertOperationalConfig(candidate), /missing or placeholder/);
}
});