chore: initial commit
Laimiao agent v2 service: agent orchestration, sessions, billing, gateway client, skills catalog, auth, config, plus tests.
This commit is contained in:
commit
6ec9778d45
53 files changed
+12340
No files matched your search
@@ -0,0 +1,94 @@
|
||||
import { describe, expect, it } from "vitest";
|
||||
import { ToolConfirmationManager, type ToolConfirmationRequest } from "../src/agent/confirmations.js";
|
||||
|
||||
function request(manager: ToolConfirmationManager, toolCallId = "call-1", signal?: AbortSignal) {
|
||||
let emitted: ToolConfirmationRequest | undefined;
|
||||
const promise = manager.request(
|
||||
{
|
||||
sessionId: "s1",
|
||||
toolCallId,
|
||||
toolName: "generate_image",
|
||||
args: { prompt: "poster" },
|
||||
},
|
||||
(value) => {
|
||||
emitted = value;
|
||||
},
|
||||
signal,
|
||||
);
|
||||
return { promise, get emitted() { return emitted; } };
|
||||
}
|
||||
|
||||
describe("ToolConfirmationManager", () => {
|
||||
it("waits for approval and resolves the tool call", async () => {
|
||||
const manager = new ToolConfirmationManager(1_000);
|
||||
const pending = request(manager);
|
||||
expect(pending.emitted?.toolCallId).toBe("call-1");
|
||||
expect(pending.emitted?.expiresAt).toBeGreaterThan(Date.now());
|
||||
|
||||
expect(manager.resolve("s1", "call-1", true)).toBe(true);
|
||||
await expect(pending.promise).resolves.toEqual({ approved: true, reason: undefined });
|
||||
expect(manager.count()).toBe(0);
|
||||
});
|
||||
|
||||
it("carries confirm type/payload and resolves edited content", async () => {
|
||||
const manager = new ToolConfirmationManager(1_000);
|
||||
let emitted: ToolConfirmationRequest | undefined;
|
||||
const promise = manager.request(
|
||||
{
|
||||
sessionId: "s1",
|
||||
toolCallId: "call-content",
|
||||
toolName: "confirm_travel_content",
|
||||
confirmType: "travel_content_confirm",
|
||||
payload: { summary: "线路:测试" },
|
||||
args: {},
|
||||
},
|
||||
(value) => {
|
||||
emitted = value;
|
||||
},
|
||||
);
|
||||
expect(emitted?.confirmType).toBe("travel_content_confirm");
|
||||
expect(emitted?.payload).toEqual({ summary: "线路:测试" });
|
||||
expect(manager.resolve("s1", "call-content", { approved: true, content: "用户修改后的内容" })).toBe(true);
|
||||
await expect(promise).resolves.toEqual({ approved: true, content: "用户修改后的内容" });
|
||||
});
|
||||
|
||||
it("returns a rejection reason", async () => {
|
||||
const manager = new ToolConfirmationManager(1_000);
|
||||
const pending = request(manager);
|
||||
manager.resolve("s1", "call-1", false, "不要生成");
|
||||
await expect(pending.promise).resolves.toEqual({ approved: false, reason: "不要生成" });
|
||||
});
|
||||
|
||||
it("times out and does not leave stale entries", async () => {
|
||||
const manager = new ToolConfirmationManager(10);
|
||||
const pending = request(manager);
|
||||
await expect(pending.promise).resolves.toMatchObject({ approved: false, reason: "等待用户确认超时" });
|
||||
expect(manager.count()).toBe(0);
|
||||
});
|
||||
|
||||
it("cancels when the run is aborted", async () => {
|
||||
const manager = new ToolConfirmationManager(1_000);
|
||||
const controller = new AbortController();
|
||||
const pending = request(manager, "call-abort", controller.signal);
|
||||
controller.abort();
|
||||
await expect(pending.promise).resolves.toEqual({ approved: false, reason: "请求已中止" });
|
||||
});
|
||||
|
||||
it("clears all pending confirmations for a session", async () => {
|
||||
const manager = new ToolConfirmationManager(1_000);
|
||||
const first = request(manager, "call-1");
|
||||
const second = request(manager, "call-2");
|
||||
manager.clearSession("s1");
|
||||
await expect(first.promise).resolves.toMatchObject({ approved: false, reason: "会话已结束" });
|
||||
await expect(second.promise).resolves.toMatchObject({ approved: false, reason: "会话已结束" });
|
||||
});
|
||||
|
||||
it("rejects duplicate pending confirmations for the same tool call", async () => {
|
||||
const manager = new ToolConfirmationManager(1_000);
|
||||
const first = request(manager);
|
||||
const duplicate = request(manager);
|
||||
await expect(duplicate.promise).resolves.toMatchObject({ approved: false });
|
||||
manager.resolve("s1", "call-1", true);
|
||||
await expect(first.promise).resolves.toEqual({ approved: true, reason: undefined });
|
||||
});
|
||||
});
|
||||
Reference in new issue
Block a user