chore: Fix types in tests 31/N.

This commit is contained in:
cpojer
2026-02-17 14:33:26 +09:00
parent f2f17bafbc
commit 116f5afea3
12 changed files with 185 additions and 85 deletions

View File

@@ -3,6 +3,7 @@ import os from "node:os";
import path from "node:path";
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
import type { OpenClawConfig } from "../../config/config.js";
import type { ModelDefinitionConfig } from "../../config/types.models.js";
import { createOpenClawCodingTools } from "../pi-tools.js";
import { createHostSandboxFsBridge } from "../test-helpers/host-sandbox-fs-bridge.js";
import { __testing, createImageTool, resolveImageModelConfigForTool } from "./image-tool.js";
@@ -62,6 +63,18 @@ function createMinimaxImageConfig(): OpenClawConfig {
};
}
function makeModelDefinition(id: string, input: Array<"text" | "image">): ModelDefinitionConfig {
return {
id,
name: id,
reasoning: false,
input,
cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
contextWindow: 128_000,
maxTokens: 8_192,
};
}
async function expectImageToolExecOk(
tool: {
execute: (toolCallId: string, input: { prompt: string; image: string }) => Promise<unknown>;
@@ -171,8 +184,8 @@ describe("image tool implicit imageModel config", () => {
providers: {
acme: {
models: [
{ id: "text-1", input: ["text"] },
{ id: "vision-1", input: ["text", "image"] },
makeModelDefinition("text-1", ["text"]),
makeModelDefinition("vision-1", ["text", "image"]),
],
},
},
@@ -215,7 +228,7 @@ describe("image tool implicit imageModel config", () => {
models: {
providers: {
acme: {
models: [{ id: "vision-1", input: ["text", "image"] }],
models: [makeModelDefinition("vision-1", ["text", "image"])],
},
},
},

View File

@@ -1,4 +1,5 @@
import { beforeEach, describe, expect, it, vi } from "vitest";
import type { OpenClawConfig } from "../../config/config.js";
let backend: "builtin" | "qmd" = "builtin";
let searchImpl: () => Promise<unknown[]> = async () => [
@@ -42,6 +43,10 @@ vi.mock("../../memory/index.js", () => {
import { createMemoryGetTool, createMemorySearchTool } from "./memory-tool.js";
function asOpenClawConfig(config: Partial<OpenClawConfig>): OpenClawConfig {
return config as OpenClawConfig;
}
beforeEach(() => {
backend = "builtin";
searchImpl = async () => [
@@ -61,7 +66,10 @@ beforeEach(() => {
describe("memory search citations", () => {
it("appends source information when citations are enabled", async () => {
backend = "builtin";
const cfg = { memory: { citations: "on" }, agents: { list: [{ id: "main", default: true }] } };
const cfg = asOpenClawConfig({
memory: { citations: "on" },
agents: { list: [{ id: "main", default: true }] },
});
const tool = createMemorySearchTool({ config: cfg });
if (!tool) {
throw new Error("tool missing");
@@ -74,7 +82,10 @@ describe("memory search citations", () => {
it("leaves snippet untouched when citations are off", async () => {
backend = "builtin";
const cfg = { memory: { citations: "off" }, agents: { list: [{ id: "main", default: true }] } };
const cfg = asOpenClawConfig({
memory: { citations: "off" },
agents: { list: [{ id: "main", default: true }] },
});
const tool = createMemorySearchTool({ config: cfg });
if (!tool) {
throw new Error("tool missing");
@@ -87,10 +98,10 @@ describe("memory search citations", () => {
it("clamps decorated snippets to qmd injected budget", async () => {
backend = "qmd";
const cfg = {
const cfg = asOpenClawConfig({
memory: { citations: "on", backend: "qmd", qmd: { limits: { maxInjectedChars: 20 } } },
agents: { list: [{ id: "main", default: true }] },
};
});
const tool = createMemorySearchTool({ config: cfg });
if (!tool) {
throw new Error("tool missing");
@@ -102,10 +113,10 @@ describe("memory search citations", () => {
it("honors auto mode for direct chats", async () => {
backend = "builtin";
const cfg = {
const cfg = asOpenClawConfig({
memory: { citations: "auto" },
agents: { list: [{ id: "main", default: true }] },
};
});
const tool = createMemorySearchTool({
config: cfg,
agentSessionKey: "agent:main:discord:dm:u123",
@@ -120,10 +131,10 @@ describe("memory search citations", () => {
it("suppresses citations for auto mode in group chats", async () => {
backend = "builtin";
const cfg = {
const cfg = asOpenClawConfig({
memory: { citations: "auto" },
agents: { list: [{ id: "main", default: true }] },
};
});
const tool = createMemorySearchTool({
config: cfg,
agentSessionKey: "agent:main:discord:group:c123",

View File

@@ -11,11 +11,11 @@ import {
describe("resolveSessionToolsVisibility", () => {
it("defaults to tree when unset or invalid", () => {
expect(resolveSessionToolsVisibility({} as OpenClawConfig)).toBe("tree");
expect(resolveSessionToolsVisibility({} as unknown as OpenClawConfig)).toBe("tree");
expect(
resolveSessionToolsVisibility({
tools: { sessions: { visibility: "invalid" } },
} as OpenClawConfig),
} as unknown as OpenClawConfig),
).toBe("tree");
});
@@ -23,7 +23,7 @@ describe("resolveSessionToolsVisibility", () => {
expect(
resolveSessionToolsVisibility({
tools: { sessions: { visibility: "ALL" } },
} as OpenClawConfig),
} as unknown as OpenClawConfig),
).toBe("all");
});
});
@@ -33,7 +33,7 @@ describe("resolveEffectiveSessionToolsVisibility", () => {
const cfg = {
tools: { sessions: { visibility: "all" } },
agents: { defaults: { sandbox: { sessionToolsVisibility: "spawned" } } },
} as OpenClawConfig;
} as unknown as OpenClawConfig;
expect(resolveEffectiveSessionToolsVisibility({ cfg, sandboxed: true })).toBe("tree");
});
@@ -41,21 +41,21 @@ describe("resolveEffectiveSessionToolsVisibility", () => {
const cfg = {
tools: { sessions: { visibility: "all" } },
agents: { defaults: { sandbox: { sessionToolsVisibility: "all" } } },
} as OpenClawConfig;
} as unknown as OpenClawConfig;
expect(resolveEffectiveSessionToolsVisibility({ cfg, sandboxed: true })).toBe("all");
});
});
describe("sandbox session-tools context", () => {
it("defaults sandbox visibility clamp to spawned", () => {
expect(resolveSandboxSessionToolsVisibility({} as OpenClawConfig)).toBe("spawned");
expect(resolveSandboxSessionToolsVisibility({} as unknown as OpenClawConfig)).toBe("spawned");
});
it("restricts non-subagent sandboxed sessions to spawned visibility", () => {
const cfg = {
tools: { sessions: { visibility: "all" } },
agents: { defaults: { sandbox: { sessionToolsVisibility: "spawned" } } },
} as OpenClawConfig;
} as unknown as OpenClawConfig;
const context = resolveSandboxedSessionToolContext({
cfg,
agentSessionKey: "agent:main:main",
@@ -71,7 +71,7 @@ describe("sandbox session-tools context", () => {
const cfg = {
tools: { sessions: { visibility: "all" } },
agents: { defaults: { sandbox: { sessionToolsVisibility: "spawned" } } },
} as OpenClawConfig;
} as unknown as OpenClawConfig;
const context = resolveSandboxedSessionToolContext({
cfg,
agentSessionKey: "agent:main:subagent:abc",
@@ -85,7 +85,7 @@ describe("sandbox session-tools context", () => {
describe("createAgentToAgentPolicy", () => {
it("denies cross-agent access when disabled", () => {
const policy = createAgentToAgentPolicy({} as OpenClawConfig);
const policy = createAgentToAgentPolicy({} as unknown as OpenClawConfig);
expect(policy.enabled).toBe(false);
expect(policy.isAllowed("main", "main")).toBe(true);
expect(policy.isAllowed("main", "ops")).toBe(false);
@@ -99,7 +99,7 @@ describe("createAgentToAgentPolicy", () => {
allow: ["ops-*", "main"],
},
},
} as OpenClawConfig);
} as unknown as OpenClawConfig);
expect(policy.isAllowed("ops-a", "ops-b")).toBe(true);
expect(policy.isAllowed("main", "ops-a")).toBe(true);
@@ -113,7 +113,7 @@ describe("createSessionVisibilityGuard", () => {
action: "send",
requesterSessionKey: "agent:main:main",
visibility: "all",
a2aPolicy: createAgentToAgentPolicy({} as OpenClawConfig),
a2aPolicy: createAgentToAgentPolicy({} as unknown as OpenClawConfig),
});
expect(guard.check("agent:ops:main")).toEqual({
@@ -129,7 +129,7 @@ describe("createSessionVisibilityGuard", () => {
action: "history",
requesterSessionKey: "agent:main:main",
visibility: "self",
a2aPolicy: createAgentToAgentPolicy({} as OpenClawConfig),
a2aPolicy: createAgentToAgentPolicy({} as unknown as OpenClawConfig),
});
expect(guard.check("agent:main:main")).toEqual({ allowed: true });

View File

@@ -16,7 +16,7 @@ function redirectResponse(location: string): Response {
status: 302,
headers: makeHeaders({ location }),
body: { cancel: vi.fn() },
} as Response;
} as unknown as Response;
}
function textResponse(body: string): Response {
@@ -25,7 +25,7 @@ function textResponse(body: string): Response {
status: 200,
headers: makeHeaders({ "content-type": "text/plain" }),
text: async () => body,
} as Response;
} as unknown as Response;
}
function setMockFetch(impl?: (...args: unknown[]) => unknown) {

View File

@@ -77,7 +77,7 @@ function errorHtmlResponse(
text: async () => html,
};
}
function requestUrl(input: RequestInfo): string {
function requestUrl(input: RequestInfo | URL): string {
if (typeof input === "string") {
return input;
}
@@ -90,9 +90,9 @@ function requestUrl(input: RequestInfo): string {
return "";
}
function installMockFetch(impl: (input: RequestInfo) => Promise<Response>) {
const mockFetch = vi.fn(impl);
global.fetch = mockFetch;
function installMockFetch(impl: (input: RequestInfo | URL) => Promise<Response>) {
const mockFetch = vi.fn(async (input: RequestInfo | URL) => await impl(input));
global.fetch = mockFetch as typeof global.fetch;
return mockFetch;
}
@@ -145,7 +145,7 @@ describe("web_fetch extraction fallbacks", () => {
});
it("wraps fetched text with external content markers", async () => {
installMockFetch((input: RequestInfo) =>
installMockFetch((input: RequestInfo | URL) =>
Promise.resolve({
ok: true,
status: 200,
@@ -183,7 +183,7 @@ describe("web_fetch extraction fallbacks", () => {
it("enforces maxChars after wrapping", async () => {
const longText = "x".repeat(5_000);
installMockFetch((input: RequestInfo) =>
installMockFetch((input: RequestInfo | URL) =>
Promise.resolve({
ok: true,
status: 200,
@@ -206,7 +206,7 @@ describe("web_fetch extraction fallbacks", () => {
});
it("honors maxChars even when wrapper overhead exceeds limit", async () => {
installMockFetch((input: RequestInfo) =>
installMockFetch((input: RequestInfo | URL) =>
Promise.resolve({
ok: true,
status: 200,
@@ -232,7 +232,7 @@ describe("web_fetch extraction fallbacks", () => {
// The sanitization of these fields is verified by external-content.test.ts tests.
it("falls back to firecrawl when readability returns no content", async () => {
installMockFetch((input: RequestInfo) => {
installMockFetch((input: RequestInfo | URL) => {
const url = requestUrl(input);
if (url.includes("api.firecrawl.dev")) {
return Promise.resolve(firecrawlResponse("firecrawl content")) as Promise<Response>;
@@ -253,8 +253,11 @@ describe("web_fetch extraction fallbacks", () => {
});
it("throws when readability is disabled and firecrawl is unavailable", async () => {
installMockFetch((input: RequestInfo) =>
Promise.resolve(htmlResponse("<html><body>hi</body></html>", requestUrl(input))),
installMockFetch(
(input: RequestInfo | URL) =>
Promise.resolve(
htmlResponse("<html><body>hi</body></html>", requestUrl(input)),
) as Promise<Response>,
);
const tool = createFetchTool({
@@ -268,7 +271,7 @@ describe("web_fetch extraction fallbacks", () => {
});
it("throws when readability is empty and firecrawl fails", async () => {
installMockFetch((input: RequestInfo) => {
installMockFetch((input: RequestInfo | URL) => {
const url = requestUrl(input);
if (url.includes("api.firecrawl.dev")) {
return Promise.resolve(firecrawlError()) as Promise<Response>;
@@ -288,7 +291,7 @@ describe("web_fetch extraction fallbacks", () => {
});
it("uses firecrawl when direct fetch fails", async () => {
installMockFetch((input: RequestInfo) => {
installMockFetch((input: RequestInfo | URL) => {
const url = requestUrl(input);
if (url.includes("api.firecrawl.dev")) {
return Promise.resolve(firecrawlResponse("firecrawl fallback", url)) as Promise<Response>;
@@ -314,7 +317,7 @@ describe("web_fetch extraction fallbacks", () => {
it("wraps external content and clamps oversized maxChars", async () => {
const large = "a".repeat(80_000);
installMockFetch(
(input: RequestInfo) =>
(input: RequestInfo | URL) =>
Promise.resolve(textResponse(large, requestUrl(input))) as Promise<Response>,
);
@@ -340,8 +343,11 @@ describe("web_fetch extraction fallbacks", () => {
"<!doctype html><html><head><title>Not Found</title></head><body><h1>Not Found</h1><p>" +
long +
"</p></body></html>";
installMockFetch((input: RequestInfo) =>
Promise.resolve(errorHtmlResponse(html, 404, requestUrl(input), "Text/HTML; charset=utf-8")),
installMockFetch(
(input: RequestInfo | URL) =>
Promise.resolve(
errorHtmlResponse(html, 404, requestUrl(input), "Text/HTML; charset=utf-8"),
) as Promise<Response>,
);
const tool = createFetchTool({ firecrawl: { enabled: false } });
@@ -361,8 +367,9 @@ describe("web_fetch extraction fallbacks", () => {
it("strips HTML errors when content-type is missing", async () => {
const html =
"<!DOCTYPE HTML><html><head><title>Oops</title></head><body><h1>Oops</h1></body></html>";
installMockFetch((input: RequestInfo) =>
Promise.resolve(errorHtmlResponse(html, 500, requestUrl(input), null)),
installMockFetch(
(input: RequestInfo | URL) =>
Promise.resolve(errorHtmlResponse(html, 500, requestUrl(input), null)) as Promise<Response>,
);
const tool = createFetchTool({ firecrawl: { enabled: false } });
@@ -377,7 +384,7 @@ describe("web_fetch extraction fallbacks", () => {
});
it("wraps firecrawl error details", async () => {
installMockFetch((input: RequestInfo) => {
installMockFetch((input: RequestInfo | URL) => {
const url = requestUrl(input);
if (url.includes("api.firecrawl.dev")) {
return Promise.resolve({