























@@ -4,6 +4,17 @@ import { createTtsTool } from "./tts-tool.js";
4455let textToSpeechSpy: ReturnType<typeof vi.spyOn>;
667+function requireRecord(value: unknown, label: string): Record<string, unknown> {
8+if (!value || typeof value !== "object") {
9+throw new Error(`expected ${label}`);
10+}
11+return value as Record<string, unknown>;
12+}
13+14+function latestTextToSpeechArgs(): Record<string, unknown> {
15+return requireRecord(textToSpeechSpy.mock.calls.at(-1)?.[0], "text-to-speech args");
16+}
17+718describe("createTtsTool", () => {
819beforeEach(() => {
920vi.restoreAllMocks();
@@ -35,17 +46,14 @@ describe("createTtsTool", () => {
3546const tool = createTtsTool();
3647const result = await tool.execute("call-1", { text: "hello" });
374838-expect(result).toMatchObject({
39-content: [{ type: "text", text: "(spoken) hello" }],
40-details: {
41-audioPath: "/tmp/reply.opus",
42-provider: "test",
43-media: {
44-mediaUrl: "/tmp/reply.opus",
45-trustedLocalMedia: true,
46-audioAsVoice: true,
47-},
48-},
49+expect(result.content).toEqual([{ type: "text", text: "(spoken) hello" }]);
50+const details = requireRecord(result.details, "TTS result details");
51+expect(details.audioPath).toBe("/tmp/reply.opus");
52+expect(details.provider).toBe("test");
53+expect(requireRecord(details.media, "TTS media details")).toEqual({
54+mediaUrl: "/tmp/reply.opus",
55+trustedLocalMedia: true,
56+audioAsVoice: true,
4957});
5058expect(JSON.stringify(result.content)).not.toContain("MEDIA:");
5159});
@@ -62,14 +70,9 @@ describe("createTtsTool", () => {
6270const tool = createTtsTool();
6371const result = await tool.execute("call-1", { text: "hello", channel: "feishu" });
647265-expect(result).toMatchObject({
66-details: {
67-media: {
68-mediaUrl: "/tmp/reply.mp3",
69-audioAsVoice: true,
70-},
71-},
72-});
73+const media = requireRecord(requireRecord(result.details, "TTS result details").media, "media");
74+expect(media.mediaUrl).toBe("/tmp/reply.mp3");
75+expect(media.audioAsVoice).toBe(true);
7376});
74777578it("passes an optional timeout to speech generation", async () => {
@@ -83,13 +86,10 @@ describe("createTtsTool", () => {
8386const tool = createTtsTool();
8487const result = await tool.execute("call-1", { text: "hello", timeoutMs: 12_345 });
858886-expect(textToSpeechSpy).toHaveBeenCalledWith(
87-expect.objectContaining({
88-text: "hello",
89-timeoutMs: 12_345,
90-}),
91-);
92-expect(result.details).toMatchObject({ timeoutMs: 12_345 });
89+const args = latestTextToSpeechArgs();
90+expect(args.text).toBe("hello");
91+expect(args.timeoutMs).toBe(12_345);
92+expect(requireRecord(result.details, "TTS result details").timeoutMs).toBe(12_345);
9393});
94949595it("passes the active agent id to speech generation", async () => {
@@ -103,12 +103,9 @@ describe("createTtsTool", () => {
103103const tool = createTtsTool({ agentId: "voice-agent" });
104104await tool.execute("call-1", { text: "hello" });
105105106-expect(textToSpeechSpy).toHaveBeenCalledWith(
107-expect.objectContaining({
108-text: "hello",
109-agentId: "voice-agent",
110-}),
111-);
106+const args = latestTextToSpeechArgs();
107+expect(args.text).toBe("hello");
108+expect(args.agentId).toBe("voice-agent");
112109});
113110114111it("passes the active account id to speech generation", async () => {
@@ -122,12 +119,9 @@ describe("createTtsTool", () => {
122119const tool = createTtsTool({ agentAccountId: "feishu-main" });
123120await tool.execute("call-1", { text: "hello" });
124121125-expect(textToSpeechSpy).toHaveBeenCalledWith(
126-expect.objectContaining({
127-text: "hello",
128-accountId: "feishu-main",
129-}),
130-);
122+const args = latestTextToSpeechArgs();
123+expect(args.text).toBe("hello");
124+expect(args.accountId).toBe("feishu-main");
131125});
132126133127it("echoes longer utterances verbatim into the tool-result content", async () => {
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。