perf: slim crestodian rescue tests

This commit is contained in:
Peter Steinberger
2026-04-25 12:48:10 +01:00
parent 2b8105598e
commit 40e4a00c8e
2 changed files with 44 additions and 10 deletions

View File

@@ -1,12 +1,14 @@
import fs from "node:fs/promises";
import os from "node:os";
import path from "node:path";
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
import { afterAll, afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest";
import type { CommandContext } from "../auto-reply/reply/commands-types.js";
import type { OpenClawConfig } from "../config/types.openclaw.js";
import { extractCrestodianRescueMessage, runCrestodianRescueMessage } from "./rescue-message.js";
const originalStateDir = process.env.OPENCLAW_STATE_DIR;
let tempRoot = "";
let tempDirId = 0;
type TestConfig = Record<string, unknown>;
@@ -101,6 +103,12 @@ vi.mock("../config/model-input.js", () => ({
typeof model === "string" ? model : model?.primary,
}));
async function makeStateDir(prefix: string): Promise<string> {
const dir = path.join(tempRoot, `${prefix}${tempDirId++}`);
await fs.mkdir(dir, { recursive: true });
return dir;
}
function commandContext(overrides: Partial<CommandContext> = {}): CommandContext {
return {
surface: "whatsapp",
@@ -134,6 +142,10 @@ async function runRescue(
}
describe("Crestodian rescue message", () => {
beforeAll(async () => {
tempRoot = await fs.mkdtemp(path.join(os.tmpdir(), "crestodian-rescue-"));
});
beforeEach(() => {
mockConfig.reset();
});
@@ -146,6 +158,12 @@ describe("Crestodian rescue message", () => {
}
});
afterAll(async () => {
if (tempRoot) {
await fs.rm(tempRoot, { recursive: true, force: true });
}
});
it("recognizes the Crestodian rescue command", () => {
expect(extractCrestodianRescueMessage("/crestodian status")).toBe("status");
expect(extractCrestodianRescueMessage("/crestodian")).toBe("");
@@ -179,7 +197,7 @@ describe("Crestodian rescue message", () => {
});
it("queues and applies persistent writes through conversational approval", async () => {
const tempDir = await fs.mkdtemp(path.join(os.tmpdir(), "crestodian-rescue-"));
const tempDir = await makeStateDir("models-");
vi.stubEnv("OPENCLAW_STATE_DIR", tempDir);
const cfg: OpenClawConfig = { crestodian: { rescue: { enabled: true } } };
@@ -203,7 +221,7 @@ describe("Crestodian rescue message", () => {
});
it("queues and applies gateway restart through conversational approval", async () => {
const tempDir = await fs.mkdtemp(path.join(os.tmpdir(), "crestodian-rescue-gateway-"));
const tempDir = await makeStateDir("gateway-");
vi.stubEnv("OPENCLAW_STATE_DIR", tempDir);
const cfg: OpenClawConfig = { crestodian: { rescue: { enabled: true } } };
const deps = { runGatewayRestart: vi.fn(async () => {}) };
@@ -229,7 +247,7 @@ describe("Crestodian rescue message", () => {
});
it("queues and applies agent creation through conversational approval", async () => {
const tempDir = await fs.mkdtemp(path.join(os.tmpdir(), "crestodian-rescue-agent-"));
const tempDir = await makeStateDir("agent-");
vi.stubEnv("OPENCLAW_STATE_DIR", tempDir);
const cfg: OpenClawConfig = { crestodian: { rescue: { enabled: true } } };
const deps = { runAgentsAdd: vi.fn(async () => {}) };

View File

@@ -1,6 +1,5 @@
import { resolveAgentConfig } from "../agents/agent-scope.js";
import { resolveSandboxConfigForAgent } from "../agents/sandbox/config.js";
import type { OpenClawConfig } from "../config/types.openclaw.js";
import { normalizeAgentId } from "../routing/session-key.js";
export type CrestodianRescueDecision =
| {
@@ -33,9 +32,27 @@ function resolvePendingTtlMinutes(value: unknown): number {
return typeof value === "number" && Number.isFinite(value) && value > 0 ? value : 15;
}
function resolveAgentEntry(cfg: OpenClawConfig, agentId?: string) {
if (!agentId) {
return undefined;
}
const id = normalizeAgentId(agentId);
return cfg.agents?.list?.find(
(entry) => entry !== null && typeof entry === "object" && normalizeAgentId(entry.id) === id,
);
}
function resolveScopedExecConfig(cfg: OpenClawConfig, agentId?: string) {
const agentConfig = agentId ? resolveAgentConfig(cfg, agentId) : undefined;
return agentConfig?.tools?.exec;
return resolveAgentEntry(cfg, agentId)?.tools?.exec;
}
function resolveScopedSandboxMode(
cfg: OpenClawConfig,
agentId?: string,
): "off" | "non-main" | "all" {
return (
resolveAgentEntry(cfg, agentId)?.sandbox?.mode ?? cfg.agents?.defaults?.sandbox?.mode ?? "off"
);
}
function isYoloHostPosture(cfg: OpenClawConfig, agentId?: string): boolean {
@@ -53,8 +70,7 @@ export function resolveCrestodianRescuePolicy(
const configuredEnabled = rescue?.enabled ?? "auto";
const ownerDmOnly = rescue?.ownerDmOnly ?? true;
const pendingTtlMinutes = resolvePendingTtlMinutes(rescue?.pendingTtlMinutes);
const sandbox = resolveSandboxConfigForAgent(input.cfg, input.agentId);
const sandboxActive = sandbox.mode !== "off";
const sandboxActive = resolveScopedSandboxMode(input.cfg, input.agentId) !== "off";
const yolo = !sandboxActive && isYoloHostPosture(input.cfg, input.agentId);
const enabled = configuredEnabled === "auto" ? yolo : configuredEnabled;