Files
laimiaoai-agent-new/tests/confirm_tools.test.ts
T
light 6ec9778d45 chore: initial commit
Laimiao agent v2 service: agent orchestration, sessions, billing,
gateway client, skills catalog, auth, config, plus tests.
2026-11-07 10:40:07 +08:00

116 lines
4.2 KiB
TypeScript

import { describe, expect, it } from "vitest";
import { createConfirmTools } from "../src/agent/confirm_tools.js";
import { ToolConfirmationManager } from "../src/agent/confirmations.js";
import type { AgentStreamEvent } from "../src/agent/service.js";
import { makeCatalog, silentLogger } from "./helpers.js";
interface TestTool {
name: string;
execute: (
toolCallId: string,
params: Record<string, unknown>,
signal?: AbortSignal,
) => Promise<{
content: Array<{ type: string; text: string }>;
details: Record<string, unknown>;
isError?: boolean;
}>;
}
async function setup() {
const catalog = await makeCatalog([]);
const manager = new ToolConfirmationManager(1_000);
const events: AgentStreamEvent[] = [];
const tools = createConfirmTools({
catalog,
confirmations: manager,
sessionId: "s1",
logger: silentLogger,
emit: (event) => events.push(event),
hasStream: true,
}) as unknown as TestTool[];
return { manager, events, tools };
}
function resultText(result: { content: Array<{ type: string; text: string }> }): unknown {
return JSON.parse(result.content[0]?.text ?? "{}");
}
describe("confirm tools", () => {
it("select mode emits options and returns the selected id", async () => {
const { manager, events, tools } = await setup();
const tool = tools.find((item) => item.name === "confirm_user");
expect(tool).toBeDefined();
const promise = tool!.execute("call-1", {
message: "请选择风格",
mode: "select",
options: [
{ id: "a", label: "A" },
{ id: "b", label: "B" },
],
});
expect(events[0]).toMatchObject({
type: "content_confirmation_required",
confirm_type: "user_confirm",
payload: { message: "请选择风格", mode: "select" },
});
expect(manager.resolve("s1", "call-1", { approved: true, content: "b" })).toBe(true);
expect(resultText(await promise)).toEqual({ approved: true, content: "b" });
expect(events[1]).toMatchObject({
type: "content_confirmation_resolved",
confirm_type: "user_confirm",
approved: true,
content: "b",
});
});
it("treats provided options as select mode", async () => {
const { manager, events, tools } = await setup();
const tool = tools.find((item) => item.name === "confirm_user")!;
const promise = tool.execute("call-options", {
message: "请选择风格",
mode: "confirm",
options: ["a", "b"],
});
expect(events[0]).toMatchObject({
type: "content_confirmation_required",
confirm_type: "user_confirm",
payload: { mode: "select" },
});
manager.resolve("s1", "call-options", { approved: true, content: "a" });
expect(resultText(await promise)).toEqual({ approved: true, content: "a" });
});
it("edit mode returns edited content", async () => {
const { manager, tools } = await setup();
const tool = tools.find((item) => item.name === "confirm_user")!;
const promise = tool.execute("call-edit", {
message: "请补充信息",
mode: "edit",
default_value: "默认内容",
});
manager.resolve("s1", "call-edit", { approved: true, content: "用户修改后的内容" });
expect(resultText(await promise)).toEqual({ approved: true, content: "用户修改后的内容" });
});
it("confirm mode clears content", async () => {
const { manager, tools } = await setup();
const tool = tools.find((item) => item.name === "confirm_user")!;
const promise = tool.execute("call-confirm", { message: "确认继续?", mode: "confirm" });
manager.resolve("s1", "call-confirm", { approved: true, content: "忽略内容" });
expect(resultText(await promise)).toEqual({ approved: true, content: "" });
});
it("rejects an option that was not offered", async () => {
const { manager, tools } = await setup();
const tool = tools.find((item) => item.name === "confirm_user")!;
const promise = tool.execute("call-invalid", {
message: "请选择",
mode: "select",
options: ["a", "b"],
});
manager.resolve("s1", "call-invalid", { approved: true, content: "c" });
expect(resultText(await promise)).toEqual({ approved: false, content: "" });
});
});