mirror of
https://github.com/DayuanJiang/next-ai-draw-io.git
synced 2026-10-11 20:19:51 +08:00
refactor: simpler streaming preview and small AI SDK cleanups
- useChat throttles streamed message updates (experimental_throttle, 150 ms), replacing the two hand-written 150 ms timers of the display_diagram and edit_diagram previews (94 lines less). The preview now only runs while the input streams; once it is complete the tool handler takes over, so a queued preview can no longer redraw an edit the handler rejected and rolled back. Measured on a streamed 60-cell diagram: 41 redraws at least 97 ms apart, before 37 with gaps down to 48 ms - The diagram check endpoint uses streamText with Output.object instead of the deprecated streamObject, and returns its fixed result as a plain text response; new route test - Import createGateway/gateway from ai and drop the direct @ai-sdk/gateway dependency - The per-request message structure logs only print with DEBUG_LLM_PAYLOAD=true - Remove an empty onFinish callback
This commit is contained in:
@@ -0,0 +1,74 @@
|
||||
// @vitest-environment node
|
||||
import { simulateReadableStream } from "ai"
|
||||
import { MockLanguageModelV3 } from "ai/test"
|
||||
import { afterEach, describe, expect, it, vi } from "vitest"
|
||||
import { POST as validateDiagram } from "@/app/api/validate-diagram/route"
|
||||
|
||||
const RESULT = {
|
||||
valid: false,
|
||||
issues: [
|
||||
{
|
||||
type: "overlap",
|
||||
severity: "critical",
|
||||
description: "Box A covers box B",
|
||||
},
|
||||
],
|
||||
suggestions: ["Move box B to the right"],
|
||||
}
|
||||
|
||||
// A vision model that answers with the JSON in a few text chunks
|
||||
vi.mock("@/lib/ai-providers", () => ({
|
||||
getValidationModel: () =>
|
||||
new MockLanguageModelV3({
|
||||
doStream: (async () => {
|
||||
const json = JSON.stringify(RESULT)
|
||||
return {
|
||||
stream: simulateReadableStream({
|
||||
chunks: [
|
||||
{ type: "text-start", id: "t" },
|
||||
...[json.slice(0, 20), json.slice(20)].map(
|
||||
(delta) => ({ type: "text-delta", id: "t", delta }),
|
||||
),
|
||||
{ type: "text-end", id: "t" },
|
||||
{
|
||||
type: "finish",
|
||||
finishReason: { unified: "stop", raw: "stop" },
|
||||
usage: {
|
||||
inputTokens: { total: 1 },
|
||||
outputTokens: { total: 1 },
|
||||
},
|
||||
},
|
||||
],
|
||||
}),
|
||||
}
|
||||
}) as any,
|
||||
}),
|
||||
}))
|
||||
|
||||
const post = () =>
|
||||
new Request("http://localhost/api/validate-diagram", {
|
||||
method: "POST",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
body: JSON.stringify({ imageData: "data:image/png;base64,AAAA" }),
|
||||
})
|
||||
|
||||
afterEach(() => {
|
||||
delete process.env.ENABLE_VLM_VALIDATION
|
||||
})
|
||||
|
||||
describe("POST /api/validate-diagram", () => {
|
||||
it("streams the model's result as JSON text for useObject", async () => {
|
||||
const res = await validateDiagram(post())
|
||||
expect(JSON.parse(await res.text())).toEqual(RESULT)
|
||||
})
|
||||
|
||||
it("answers valid when the check is turned off", async () => {
|
||||
process.env.ENABLE_VLM_VALIDATION = "false"
|
||||
const res = await validateDiagram(post())
|
||||
expect(JSON.parse(await res.text())).toEqual({
|
||||
valid: true,
|
||||
issues: [],
|
||||
suggestions: [],
|
||||
})
|
||||
})
|
||||
})
|
||||
Reference in New Issue
Block a user