openclaw/extensions/guardian/types.test.ts

145 lines
4.9 KiB
TypeScript

import { describe, it, expect } from "vitest";
import {
resolveConfig,
parseModelRef,
resolveGuardianModelRef,
GUARDIAN_DEFAULTS,
} from "./types.js";
describe("types — resolveConfig", () => {
it("returns defaults when raw is undefined", () => {
const config = resolveConfig(undefined);
expect(config.model).toBeUndefined();
expect(config.watched_tools).toEqual(GUARDIAN_DEFAULTS.watched_tools);
expect(config.timeout_ms).toBe(GUARDIAN_DEFAULTS.timeout_ms);
expect(config.fallback_on_error).toBe(GUARDIAN_DEFAULTS.fallback_on_error);
expect(config.mode).toBe(GUARDIAN_DEFAULTS.mode);
expect(config.max_recent_turns).toBe(GUARDIAN_DEFAULTS.max_recent_turns);
expect(config.context_tools).toEqual(GUARDIAN_DEFAULTS.context_tools);
});
it("returns defaults when raw is empty", () => {
const config = resolveConfig({});
expect(config.model).toBeUndefined();
expect(config.watched_tools).toEqual(GUARDIAN_DEFAULTS.watched_tools);
});
it("resolves model string", () => {
const config = resolveConfig({ model: "kimi/moonshot-v1-8k" });
expect(config.model).toBe("kimi/moonshot-v1-8k");
});
it("resolves model as undefined for empty string", () => {
const config = resolveConfig({ model: "" });
expect(config.model).toBeUndefined();
});
it("overrides defaults with explicit values", () => {
const config = resolveConfig({
model: "openai/gpt-4o-mini",
watched_tools: ["exec"],
timeout_ms: 3000,
fallback_on_error: "block",
log_decisions: false,
mode: "audit",
max_arg_length: 200,
max_recent_turns: 2,
context_tools: ["memory_search"],
});
expect(config.model).toBe("openai/gpt-4o-mini");
expect(config.watched_tools).toEqual(["exec"]);
expect(config.timeout_ms).toBe(3000);
expect(config.fallback_on_error).toBe("block");
expect(config.log_decisions).toBe(false);
expect(config.mode).toBe("audit");
expect(config.max_arg_length).toBe(200);
expect(config.max_recent_turns).toBe(2);
expect(config.context_tools).toEqual(["memory_search"]);
});
it("uses defaults for invalid types", () => {
const config = resolveConfig({
timeout_ms: "not a number",
log_decisions: "not a boolean",
max_recent_turns: "bad",
context_tools: "not an array",
});
expect(config.timeout_ms).toBe(GUARDIAN_DEFAULTS.timeout_ms);
expect(config.log_decisions).toBe(GUARDIAN_DEFAULTS.log_decisions);
expect(config.max_recent_turns).toBe(GUARDIAN_DEFAULTS.max_recent_turns);
expect(config.context_tools).toEqual(GUARDIAN_DEFAULTS.context_tools);
});
it("normalizes fallback_on_error to allow for non-block values", () => {
const config = resolveConfig({ fallback_on_error: "invalid" });
expect(config.fallback_on_error).toBe("allow");
});
it("normalizes mode to enforce for non-audit values", () => {
const config = resolveConfig({ mode: "invalid" });
expect(config.mode).toBe("enforce");
});
});
describe("types — parseModelRef", () => {
it("parses provider/model", () => {
expect(parseModelRef("kimi/moonshot-v1-8k")).toEqual({
provider: "kimi",
modelId: "moonshot-v1-8k",
});
});
it("parses provider with complex model ids", () => {
expect(parseModelRef("ollama/llama3.1:8b")).toEqual({
provider: "ollama",
modelId: "llama3.1:8b",
});
});
it("handles model ids with slashes (nested paths)", () => {
expect(parseModelRef("openai/gpt-4o-mini")).toEqual({
provider: "openai",
modelId: "gpt-4o-mini",
});
});
it("returns undefined for invalid formats", () => {
expect(parseModelRef("")).toBeUndefined();
expect(parseModelRef("no-slash")).toBeUndefined();
expect(parseModelRef("/no-provider")).toBeUndefined();
expect(parseModelRef("no-model/")).toBeUndefined();
});
});
describe("types — resolveGuardianModelRef", () => {
it("uses plugin config model when provided", () => {
const config = resolveConfig({ model: "kimi/moonshot-v1-8k" });
const result = resolveGuardianModelRef(config, {});
expect(result).toBe("kimi/moonshot-v1-8k");
});
it("falls back to main agent model string", () => {
const config = resolveConfig({});
const result = resolveGuardianModelRef(config, {
agents: { defaults: { model: { primary: "openai/gpt-4o" } } },
});
expect(result).toBe("openai/gpt-4o");
});
it("returns undefined when no model is available", () => {
const config = resolveConfig({});
const result = resolveGuardianModelRef(config, {});
expect(result).toBeUndefined();
});
it("plugin config takes priority over main agent model", () => {
const config = resolveConfig({ model: "kimi/moonshot-v1-8k" });
const result = resolveGuardianModelRef(config, {
agents: { defaults: { model: { primary: "openai/gpt-4o" } } },
});
expect(result).toBe("kimi/moonshot-v1-8k");
});
});