fix assistant exports and tool calls

This commit is contained in:
ajnart committed 2026-08-14 11:32:11 +02:00
1 parent 9c64f8772d
commit 443fbe0c36
13 files changed
+728 -29

No files matched your search

@@ -2,6 +2,8 @@ import { describe, expect, test, vi } from "vitest";
import { jsonSchema, simulateReadableStream, stepCountIs, streamText, tool } from "ai";
import { MockLanguageModelV4 } from "ai/test";
import { repairAssistantToolInput } from "./assistant-tool-input-repair";
const usage = {
inputTokens: { total: 10, noCache: 10, cacheRead: 0, cacheWrite: 0 },
outputTokens: { total: 5, text: 5, reasoning: 0 },
@@ -100,4 +102,69 @@ describe("Assistant tool loop", () => {
expect(nextPrompt).toContain("homarr.svg");
expect(nextPrompt).toContain('"id":"board-1"');
});
test("repairs and executes an icon search whose streamed object is missing its closing delimiter", async () => {
const findIcons = vi.fn(() => ({
countIcons: 1,
icons: [
{
slug: "homarr-labs/dashboard-icons",
icons: [{ name: "homarr.svg", url: "https://cdn.example.com/homarr.svg" }],
},
],
}));
const model = new MockLanguageModelV4({
doStream: [
{
stream: simulateReadableStream({
chunks: [
{ type: "stream-start" as const, warnings: [] },
{
type: "tool-call" as const,
toolCallId: "icon-call",
toolName: "icon_findIcons",
input: '{"searchText":"homarr"',
},
finish("tool-calls"),
],
chunkDelayInMs: null,
}),
},
{
stream: simulateReadableStream({
chunks: [
{ type: "stream-start" as const, warnings: [] },
{ type: "text-start" as const, id: "answer" },
{ type: "text-delta" as const, id: "answer", delta: "The icon search completed." },
{ type: "text-end" as const, id: "answer" },
finish("stop"),
],
chunkDelayInMs: null,
}),
},
],
});
const result = streamText({
model,
prompt: "Find the Homarr icon.",
tools: {
icon_findIcons: tool({
inputSchema: jsonSchema({
type: "object",
properties: { searchText: { type: "string" } },
additionalProperties: false,
}),
execute: findIcons,
}),
},
experimental_repairToolCall: ({ toolCall }) => Promise.resolve(repairAssistantToolInput(toolCall)),
stopWhen: stepCountIs(2),
});
await expect(result.text).resolves.toBe("The icon search completed.");
expect(findIcons).toHaveBeenCalledWith(
{ searchText: "homarr" },
expect.objectContaining({ toolCallId: "icon-call" }),
);
});
});