Laimiao agent v2 service: agent orchestration, sessions, billing, gateway client, skills catalog, auth, config, plus tests.
94 lines
3.8 KiB
TypeScript
94 lines
3.8 KiB
TypeScript
import { describe, expect, it } from "vitest";
|
|
import { join } from "node:path";
|
|
import { loadConfig } from "../src/config.js";
|
|
import { tempRoot } from "./helpers.js";
|
|
|
|
describe("loadConfig", () => {
|
|
it("applies safe defaults", () => {
|
|
const root = tempRoot();
|
|
const config = loadConfig({ APP_ROOT: root });
|
|
expect(config.port).toBe(8100);
|
|
expect(config.billing.mode).toBe("live");
|
|
expect(config.billing.currency).toBe("credits");
|
|
expect(config.gateway.mock).toBe(false);
|
|
expect(config.gateway.pollTimeoutMs).toBe(900_000);
|
|
expect(config.llm.modelId).toBe("deepseek-chat");
|
|
expect(config.dataDir).toBe(join(root, "data"));
|
|
expect(config.mysql.host).toBe("127.0.0.1");
|
|
expect(config.mysql.database).toBe("laimiaodb");
|
|
expect(config.skillDefaults.model).toBe("gpt-image-2");
|
|
expect(config.toolConfirmation.enabled).toBe(true);
|
|
expect(config.toolConfirmation.tools).toEqual(["generate_image"]);
|
|
expect(config.toolConfirmation.timeoutMs).toBe(300_000);
|
|
expect(config.modelsFile).toBe(join(root, "data", "pi", "models.json"));
|
|
});
|
|
|
|
it("parses booleans and integers from env strings", () => {
|
|
const config = loadConfig({
|
|
APP_ROOT: tempRoot(),
|
|
PORT: "9001",
|
|
GATEWAY_MOCK: "TRUE",
|
|
BILLING_MODE: "off",
|
|
LAIMIAO_LLM_REASONING: "1",
|
|
GATEWAY_POLL_INTERVAL_MS: "250",
|
|
TOOL_CONFIRMATION_TOOLS: "generate_image, quote_image",
|
|
});
|
|
expect(config.port).toBe(9001);
|
|
expect(config.gateway.mock).toBe(true);
|
|
expect(config.billing.mode).toBe("off");
|
|
expect(config.llm.reasoning).toBe(true);
|
|
expect(config.gateway.pollIntervalMs).toBe(250);
|
|
expect(config.toolConfirmation.tools).toEqual(["generate_image", "quote_image"]);
|
|
});
|
|
|
|
it("treats an empty integer as the default", () => {
|
|
const config = loadConfig({ APP_ROOT: tempRoot(), PORT: "" });
|
|
expect(config.port).toBe(8100);
|
|
});
|
|
|
|
it("rejects invalid port and billing mode", () => {
|
|
expect(() => loadConfig({ APP_ROOT: tempRoot(), PORT: "0" })).toThrow(/PORT/);
|
|
expect(() => loadConfig({ APP_ROOT: tempRoot(), BILLING_MODE: "always" })).toThrow(/BILLING_MODE/);
|
|
});
|
|
|
|
it("rejects malformed gateway and LLM URLs", () => {
|
|
expect(() => loadConfig({ APP_ROOT: tempRoot(), GATEWAY_CN_URL: "not-a-url" })).toThrow(/GATEWAY_CN_URL/);
|
|
expect(() => loadConfig({ APP_ROOT: tempRoot(), LAIMIAO_LLM_BASE_URL: "ftp://x" })).toThrow(
|
|
/LAIMIAO_LLM_BASE_URL/,
|
|
);
|
|
});
|
|
|
|
it("enforces production security requirements", () => {
|
|
const base = {
|
|
APP_ROOT: tempRoot(),
|
|
NODE_ENV: "production",
|
|
JWT_KEY: "secret",
|
|
CORS_ORIGIN: "https://app.example.com",
|
|
FILE_FETCH_ALLOWED_HOSTS: "cdn.example.com,*.oss.example.com",
|
|
};
|
|
|
|
expect(() => loadConfig({ ...base, JWT_KEY: "" })).toThrow(/JWT_KEY/);
|
|
expect(() => loadConfig({ ...base, CORS_ORIGIN: "*" })).toThrow(/CORS_ORIGIN/);
|
|
expect(() => loadConfig({ ...base, CORS_ORIGIN: "https://app.example.com/path" })).toThrow(/CORS_ORIGIN/);
|
|
expect(() => loadConfig({ ...base, FILE_FETCH_ALLOWED_HOSTS: "" })).toThrow(/FILE_FETCH_ALLOWED_HOSTS/);
|
|
|
|
const config = loadConfig(base);
|
|
expect(config.isProduction).toBe(true);
|
|
expect(config.fileFetchAllowedHosts).toEqual(["cdn.example.com", "*.oss.example.com"]);
|
|
});
|
|
|
|
it("keeps permissive defaults outside production", () => {
|
|
const config = loadConfig({ APP_ROOT: tempRoot() });
|
|
expect(config.nodeEnv).toBe("development");
|
|
expect(config.isProduction).toBe(false);
|
|
expect(config.fileFetchAllowedHosts).toEqual([]);
|
|
});
|
|
|
|
it("resolves relative paths against APP_ROOT", () => {
|
|
const root = tempRoot();
|
|
const config = loadConfig({ APP_ROOT: root, DATA_DIR: "var/state" });
|
|
expect(config.dataDir).toBe(join(root, "var/state"));
|
|
expect(config.ledgerFile).toBe(join(root, "var/state/usage-ledger.jsonl"));
|
|
});
|
|
});
|