chore: Fix types in tests 44/N.
This commit is contained in:
@@ -8,7 +8,7 @@ import {
|
|||||||
ensureAuthProfileStore,
|
ensureAuthProfileStore,
|
||||||
resolveApiKeyForProfile,
|
resolveApiKeyForProfile,
|
||||||
} from "./auth-profiles.js";
|
} from "./auth-profiles.js";
|
||||||
import { CHUTES_TOKEN_ENDPOINT, type ChutesStoredOAuth } from "./chutes-oauth.js";
|
import { CHUTES_TOKEN_ENDPOINT } from "./chutes-oauth.js";
|
||||||
|
|
||||||
describe("auth-profiles (chutes)", () => {
|
describe("auth-profiles (chutes)", () => {
|
||||||
let envSnapshot: ReturnType<typeof captureEnv> | undefined;
|
let envSnapshot: ReturnType<typeof captureEnv> | undefined;
|
||||||
@@ -49,7 +49,7 @@ describe("auth-profiles (chutes)", () => {
|
|||||||
refresh: "rt_old",
|
refresh: "rt_old",
|
||||||
expires: Date.now() - 60_000,
|
expires: Date.now() - 60_000,
|
||||||
clientId: "cid_test",
|
clientId: "cid_test",
|
||||||
} as unknown as ChutesStoredOAuth,
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
await fs.writeFile(authProfilePath, `${JSON.stringify(store)}\n`);
|
await fs.writeFile(authProfilePath, `${JSON.stringify(store)}\n`);
|
||||||
|
|||||||
@@ -311,7 +311,8 @@ describe("exec tool backgrounding", () => {
|
|||||||
action: "poll",
|
action: "poll",
|
||||||
sessionId: sessionA,
|
sessionId: sessionA,
|
||||||
});
|
});
|
||||||
expect(pollB.details.status).toBe("failed");
|
const pollBDetails = pollB.details as { status?: string };
|
||||||
|
expect(pollBDetails.status).toBe("failed");
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -335,9 +336,9 @@ describe("exec exit codes", () => {
|
|||||||
? joinCommands(["Write-Output nope", "exit 1"])
|
? joinCommands(["Write-Output nope", "exit 1"])
|
||||||
: joinCommands(["echo nope", "exit 1"]);
|
: joinCommands(["echo nope", "exit 1"]);
|
||||||
const result = await execTool.execute("call1", { command });
|
const result = await execTool.execute("call1", { command });
|
||||||
|
const resultDetails = result.details as { status?: string; exitCode?: number | null };
|
||||||
expect(result.details.status).toBe("completed");
|
expect(resultDetails.status).toBe("completed");
|
||||||
expect(result.details.exitCode).toBe(1);
|
expect(resultDetails.exitCode).toBe(1);
|
||||||
|
|
||||||
const text = normalizeText(result.content.find((c) => c.type === "text")?.text);
|
const text = normalizeText(result.content.find((c) => c.type === "text")?.text);
|
||||||
expect(text).toContain("nope");
|
expect(text).toContain("nope");
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ test("exec falls back when PTY spawn fails", async () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
expect(result.details.status).toBe("completed");
|
expect(result.details.status).toBe("completed");
|
||||||
const text = result.content?.[0]?.text ?? "";
|
const text = result.content?.find((item) => item.type === "text")?.text ?? "";
|
||||||
expect(text).toContain("ok");
|
expect(text).toContain("ok");
|
||||||
expect(text).toContain("PTY spawn failed");
|
expect(text).toContain("PTY spawn failed");
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -14,6 +14,6 @@ test("exec supports pty output", async () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
expect(result.details.status).toBe("completed");
|
expect(result.details.status).toBe("completed");
|
||||||
const text = result.content?.[0]?.text ?? "";
|
const text = result.content?.find((item) => item.type === "text")?.text ?? "";
|
||||||
expect(text).toContain("ok");
|
expect(text).toContain("ok");
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ async function startPtySession(command: string) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
expect(result.details.status).toBe("running");
|
expect(result.details.status).toBe("running");
|
||||||
const sessionId = result.details.sessionId;
|
const sessionId = (result.details as { sessionId: string }).sessionId;
|
||||||
expect(sessionId).toBeTruthy();
|
expect(sessionId).toBeTruthy();
|
||||||
return { processTool, sessionId };
|
return { processTool, sessionId };
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,8 +17,8 @@ vi.mock("../process/supervisor/index.js", () => ({
|
|||||||
}));
|
}));
|
||||||
|
|
||||||
function createDeferred<T>() {
|
function createDeferred<T>() {
|
||||||
let resolve: (value: T) => void;
|
let resolve: (value: T) => void = () => {};
|
||||||
let reject: (error: unknown) => void;
|
let reject: (error: unknown) => void = () => {};
|
||||||
const promise = new Promise<T>((res, rej) => {
|
const promise = new Promise<T>((res, rej) => {
|
||||||
resolve = res;
|
resolve = res;
|
||||||
reject = rej;
|
reject = rej;
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import { completeSimple, getModel } from "@mariozechner/pi-ai";
|
import { completeSimple, getModel } from "@mariozechner/pi-ai";
|
||||||
|
import { Type } from "@sinclair/typebox";
|
||||||
import { describe, expect, it } from "vitest";
|
import { describe, expect, it } from "vitest";
|
||||||
import { isTruthyEnvValue } from "../infra/env.js";
|
import { isTruthyEnvValue } from "../infra/env.js";
|
||||||
|
|
||||||
@@ -57,13 +58,9 @@ describeLive("gemini live switch", () => {
|
|||||||
{
|
{
|
||||||
name: "bash",
|
name: "bash",
|
||||||
description: "Run shell command",
|
description: "Run shell command",
|
||||||
parameters: {
|
parameters: Type.Object({
|
||||||
type: "object",
|
command: Type.String(),
|
||||||
properties: {
|
}),
|
||||||
command: { type: "string" },
|
|
||||||
},
|
|
||||||
required: ["command"],
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -21,7 +21,9 @@ describe("normalizeModelCompat", () => {
|
|||||||
const model = baseModel();
|
const model = baseModel();
|
||||||
delete (model as { compat?: unknown }).compat;
|
delete (model as { compat?: unknown }).compat;
|
||||||
const normalized = normalizeModelCompat(model);
|
const normalized = normalizeModelCompat(model);
|
||||||
expect(normalized.compat?.supportsDeveloperRole).toBe(false);
|
expect(
|
||||||
|
(normalized.compat as { supportsDeveloperRole?: boolean } | undefined)?.supportsDeveloperRole,
|
||||||
|
).toBe(false);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("leaves non-zai models untouched", () => {
|
it("leaves non-zai models untouched", () => {
|
||||||
@@ -39,6 +41,8 @@ describe("normalizeModelCompat", () => {
|
|||||||
const model = baseModel();
|
const model = baseModel();
|
||||||
model.compat = { supportsDeveloperRole: false };
|
model.compat = { supportsDeveloperRole: false };
|
||||||
const normalized = normalizeModelCompat(model);
|
const normalized = normalizeModelCompat(model);
|
||||||
expect(normalized.compat?.supportsDeveloperRole).toBe(false);
|
expect(
|
||||||
|
(normalized.compat as { supportsDeveloperRole?: boolean } | undefined)?.supportsDeveloperRole,
|
||||||
|
).toBe(false);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -264,7 +264,7 @@ describe("createOllamaStreamFn", () => {
|
|||||||
try {
|
try {
|
||||||
const streamFn = createOllamaStreamFn("http://ollama-host:11434/v1/");
|
const streamFn = createOllamaStreamFn("http://ollama-host:11434/v1/");
|
||||||
const signal = new AbortController().signal;
|
const signal = new AbortController().signal;
|
||||||
const stream = streamFn(
|
const stream = await streamFn(
|
||||||
{
|
{
|
||||||
id: "qwen3:32b",
|
id: "qwen3:32b",
|
||||||
api: "ollama",
|
api: "ollama",
|
||||||
@@ -321,7 +321,7 @@ describe("createOllamaStreamFn", () => {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
const streamFn = createOllamaStreamFn("http://ollama-host:11434");
|
const streamFn = createOllamaStreamFn("http://ollama-host:11434");
|
||||||
const stream = streamFn(
|
const stream = await streamFn(
|
||||||
{
|
{
|
||||||
id: "qwen3:32b",
|
id: "qwen3:32b",
|
||||||
api: "ollama",
|
api: "ollama",
|
||||||
|
|||||||
@@ -156,7 +156,8 @@ describe("openclaw-tools: subagents (sessions_spawn model + thinking)", () => {
|
|||||||
expect(result.details).toMatchObject({
|
expect(result.details).toMatchObject({
|
||||||
status: "error",
|
status: "error",
|
||||||
});
|
});
|
||||||
expect(String(result.details?.error)).toMatch(/Invalid thinking level/i);
|
const errorDetails = result.details as { error?: unknown };
|
||||||
|
expect(String(errorDetails.error)).toMatch(/Invalid thinking level/i);
|
||||||
expect(calls).toHaveLength(0);
|
expect(calls).toHaveLength(0);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ vi.mock("node:child_process", async (importOriginal) => {
|
|||||||
stdout?: Readable;
|
stdout?: Readable;
|
||||||
stderr?: Readable;
|
stderr?: Readable;
|
||||||
on: (event: string, cb: (...args: unknown[]) => void) => void;
|
on: (event: string, cb: (...args: unknown[]) => void) => void;
|
||||||
|
emit: (event: string, ...args: unknown[]) => boolean;
|
||||||
};
|
};
|
||||||
child.stdout = new Readable({ read() {} });
|
child.stdout = new Readable({ read() {} });
|
||||||
child.stderr = new Readable({ read() {} });
|
child.stderr = new Readable({ read() {} });
|
||||||
@@ -40,8 +41,8 @@ vi.mock("node:child_process", async (importOriginal) => {
|
|||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
vi.mock("../skills.js", async (importOriginal) => {
|
vi.mock("./skills.js", async (importOriginal) => {
|
||||||
const actual = await importOriginal<typeof import("../skills.js")>();
|
const actual = await importOriginal<typeof import("./skills.js")>();
|
||||||
return {
|
return {
|
||||||
...actual,
|
...actual,
|
||||||
syncSkillsToWorkspace: vi.fn(async () => undefined),
|
syncSkillsToWorkspace: vi.fn(async () => undefined),
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ describe("buildAgentSystemPrompt uses sanitized workspace/sandbox strings", () =
|
|||||||
enabled: true,
|
enabled: true,
|
||||||
containerWorkspaceDir: "/work\u2029space",
|
containerWorkspaceDir: "/work\u2029space",
|
||||||
workspaceDir: "/host\nspace",
|
workspaceDir: "/host\nspace",
|
||||||
workspaceAccess: "read-write",
|
workspaceAccess: "rw",
|
||||||
agentWorkspaceMount: "/mnt\u2028mount",
|
agentWorkspaceMount: "/mnt\u2028mount",
|
||||||
browserNoVncUrl: "http://example.test/\nui",
|
browserNoVncUrl: "http://example.test/\nui",
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ describe("buildWorkspaceSkillStatus", () => {
|
|||||||
source: "test",
|
source: "test",
|
||||||
filePath: "/tmp/os-scoped",
|
filePath: "/tmp/os-scoped",
|
||||||
baseDir: "/tmp",
|
baseDir: "/tmp",
|
||||||
|
disableModelInvocation: false,
|
||||||
},
|
},
|
||||||
frontmatter: {},
|
frontmatter: {},
|
||||||
metadata: {
|
metadata: {
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import { describe, expect, it } from "vitest";
|
import { describe, expect, it } from "vitest";
|
||||||
import { resolveSkillsPromptForRun } from "./skills.js";
|
import { resolveSkillsPromptForRun } from "./skills.js";
|
||||||
|
import type { SkillEntry } from "./skills/types.js";
|
||||||
|
|
||||||
describe("resolveSkillsPromptForRun", () => {
|
describe("resolveSkillsPromptForRun", () => {
|
||||||
it("prefers snapshot prompt when available", () => {
|
it("prefers snapshot prompt when available", () => {
|
||||||
@@ -17,6 +18,7 @@ describe("resolveSkillsPromptForRun", () => {
|
|||||||
filePath: "/app/skills/demo-skill/SKILL.md",
|
filePath: "/app/skills/demo-skill/SKILL.md",
|
||||||
baseDir: "/app/skills/demo-skill",
|
baseDir: "/app/skills/demo-skill",
|
||||||
source: "openclaw-bundled",
|
source: "openclaw-bundled",
|
||||||
|
disableModelInvocation: false,
|
||||||
},
|
},
|
||||||
frontmatter: {},
|
frontmatter: {},
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -235,8 +235,8 @@ describe("tool-loop-detection", () => {
|
|||||||
expect(criticalResult.stuck).toBe(true);
|
expect(criticalResult.stuck).toBe(true);
|
||||||
if (criticalResult.stuck) {
|
if (criticalResult.stuck) {
|
||||||
expect(criticalResult.level).toBe("critical");
|
expect(criticalResult.level).toBe("critical");
|
||||||
|
expect(criticalResult.detector).toBe("known_poll_no_progress");
|
||||||
}
|
}
|
||||||
expect(criticalResult.detector).toBe("known_poll_no_progress");
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it("can disable specific detectors", () => {
|
it("can disable specific detectors", () => {
|
||||||
|
|||||||
@@ -33,7 +33,10 @@ describe("handleDiscordPresenceAction", () => {
|
|||||||
status: "online",
|
status: "online",
|
||||||
afk: false,
|
afk: false,
|
||||||
});
|
});
|
||||||
const payload = JSON.parse(result.content[0].text ?? "");
|
const textBlock = result.content.find((block) => block.type === "text");
|
||||||
|
const payload = JSON.parse(
|
||||||
|
(textBlock as { type: "text"; text: string } | undefined)?.text ?? "{}",
|
||||||
|
);
|
||||||
expect(payload.ok).toBe(true);
|
expect(payload.ok).toBe(true);
|
||||||
expect(payload.activities[0]).toEqual({ type: 0, name: "with fire" });
|
expect(payload.activities[0]).toEqual({ type: 0, name: "with fire" });
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -183,6 +183,7 @@ describe("image tool implicit imageModel config", () => {
|
|||||||
models: {
|
models: {
|
||||||
providers: {
|
providers: {
|
||||||
acme: {
|
acme: {
|
||||||
|
baseUrl: "https://example.com",
|
||||||
models: [
|
models: [
|
||||||
makeModelDefinition("text-1", ["text"]),
|
makeModelDefinition("text-1", ["text"]),
|
||||||
makeModelDefinition("vision-1", ["text", "image"]),
|
makeModelDefinition("vision-1", ["text", "image"]),
|
||||||
@@ -228,6 +229,7 @@ describe("image tool implicit imageModel config", () => {
|
|||||||
models: {
|
models: {
|
||||||
providers: {
|
providers: {
|
||||||
acme: {
|
acme: {
|
||||||
|
baseUrl: "https://example.com",
|
||||||
models: [makeModelDefinition("vision-1", ["text", "image"])],
|
models: [makeModelDefinition("vision-1", ["text", "image"])],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ function mockSendResult(overrides: { channel?: string; to?: string } = {}) {
|
|||||||
kind: "send",
|
kind: "send",
|
||||||
action: "send",
|
action: "send",
|
||||||
channel: overrides.channel ?? "telegram",
|
channel: overrides.channel ?? "telegram",
|
||||||
...(overrides.to ? { to: overrides.to } : {}),
|
to: overrides.to ?? "telegram:123",
|
||||||
handledBy: "plugin",
|
handledBy: "plugin",
|
||||||
payload: {},
|
payload: {},
|
||||||
dryRun: true,
|
dryRun: true,
|
||||||
|
|||||||
@@ -76,7 +76,7 @@ describe("handleTelegramAction", () => {
|
|||||||
reactMessageTelegram.mockResolvedValueOnce({
|
reactMessageTelegram.mockResolvedValueOnce({
|
||||||
ok: false,
|
ok: false,
|
||||||
warning: "Reaction unavailable: ✅",
|
warning: "Reaction unavailable: ✅",
|
||||||
});
|
} as unknown as Awaited<ReturnType<typeof reactMessageTelegram>>);
|
||||||
const result = await handleTelegramAction(defaultReactionAction, reactionConfig("minimal"));
|
const result = await handleTelegramAction(defaultReactionAction, reactionConfig("minimal"));
|
||||||
const textPayload = result.content.find((item) => item.type === "text");
|
const textPayload = result.content.find((item) => item.type === "text");
|
||||||
expect(textPayload?.type).toBe("text");
|
expect(textPayload?.type).toBe("text");
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ describe("web_fetch response size limits", () => {
|
|||||||
|
|
||||||
const tool = createWebFetchTool(baseToolConfig);
|
const tool = createWebFetchTool(baseToolConfig);
|
||||||
const result = await tool?.execute?.("call", { url: "https://example.com/stream" });
|
const result = await tool?.execute?.("call", { url: "https://example.com/stream" });
|
||||||
|
const details = result?.details as { warning?: string } | undefined;
|
||||||
expect(result?.details?.warning).toContain("Response body truncated");
|
expect(details?.warning).toContain("Response body truncated");
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user