From 06621764b2a1041f3614b8cad86d5d1e33028fd0 Mon Sep 17 00:00:00 2001 From: "dayuan.jiang" Date: Mon, 12 Oct 2026 08:17:11 +0900 Subject: [PATCH] refactor(chat): drop redesign leftovers and old-format migrations - stores/versions-store.ts, hooks/use-session-manager.ts, lib/session-storage.ts: remove the diagramHistory conversion layer, the localStorage chat migration and the empty templates store - stores/canvas-store.ts, lib/drawio/editor-bridge.ts: remove the pages list nothing read - components/chat/chat-engine.tsx: use the context's chartXMLRef and latestSvgRef instead of local copies, subscribe to one settings field, stop prefetching quota limits (lib/use-quota-manager.tsx takes the values from the 429 body), readDiagramFile delegates to the MCP loader (which now strips XML prologs and accepts ) - contexts/diagram-context.tsx: one requestTaggedExport path for thumbnails, validation, fetch and save; fetchDiagramXml replaces handleExport plus the exported resolver map - hooks/use-validate-diagram.ts and app/api/validate-diagram: plain fetch returning JSON instead of a streamed object nobody consumed - hooks/use-diagram-tool-handlers.ts: drop the DEBUG blocks; canvas vars inheritance lives in placeOnPage (lib/diagram-pages.ts) - lobby-hero, icon-button, drawio-frame: remove unreachable branches and unused props --- app/api/config/route.ts | 3 - app/api/validate-diagram/route.ts | 48 ++-- components/canvas/canvas-stage.tsx | 3 +- components/canvas/drawio-frame.tsx | 32 +-- components/chat/chat-engine.tsx | 124 ++------- components/chat/lobby-hero.tsx | 31 +-- components/workspace/icon-button.tsx | 16 +- contexts/diagram-context.tsx | 263 ++++++++---------- hooks/use-diagram-tool-handlers.ts | 91 +----- hooks/use-session-manager.ts | 22 +- hooks/use-validate-diagram.ts | 154 +++------- lib/diagram-diff.ts | 25 +- lib/diagram-pages.ts | 52 ++-- lib/drawio/editor-bridge.ts | 13 - lib/session-storage.ts | 116 +------- lib/use-quota-manager.tsx | 41 ++- packages/mcp-server/src/load-diagram.ts | 16 +- .../mcp-server/tests/load-diagram.test.ts | 34 +++ stores/canvas-store.ts | 7 - stores/versions-store.ts | 20 +- tests/e2e/settings-providers.spec.ts | 9 +- tests/e2e/workspace.spec.ts | 23 +- tests/unit/diagram-context.test.tsx | 40 ++- tests/unit/diagram-pages.test.ts | 19 +- tests/unit/redesign-helpers.test.ts | 25 +- tests/unit/use-session-manager.test.tsx | 1 - tests/unit/validate-diagram-route.test.ts | 49 ++-- 27 files changed, 411 insertions(+), 866 deletions(-) diff --git a/app/api/config/route.ts b/app/api/config/route.ts index f4b5bc4e..f4dac222 100644 --- a/app/api/config/route.ts +++ b/app/api/config/route.ts @@ -3,8 +3,5 @@ import { NextResponse } from "next/server" export async function GET() { return NextResponse.json({ accessCodeRequired: !!process.env.ACCESS_CODE_LIST, - dailyRequestLimit: Number(process.env.DAILY_REQUEST_LIMIT) || 0, - dailyTokenLimit: Number(process.env.DAILY_TOKEN_LIMIT) || 0, - tpmLimit: Number(process.env.TPM_LIMIT) || 0, }) } diff --git a/app/api/validate-diagram/route.ts b/app/api/validate-diagram/route.ts index 3fba6628..c91e6377 100644 --- a/app/api/validate-diagram/route.ts +++ b/app/api/validate-diagram/route.ts @@ -1,9 +1,9 @@ /** * API endpoint for VLM-based diagram validation. - * Accepts a PNG image and streams validation results using useObject-compatible format. + * Accepts a PNG image and answers with the validation result as JSON. */ -import { Output, streamText } from "ai" +import { generateText, Output } from "ai" import { checkAccessCode, rejectCrossSite } from "@/lib/access-code" import { getValidationModel } from "@/lib/ai-providers" import { @@ -35,13 +35,6 @@ const DEFAULT_VALID_RESULT: ValidationResult = { suggestions: [], } -/** A fixed result in the text format useObject reads */ -function createStreamingResponse(result: ValidationResult): Response { - return new Response(JSON.stringify(result), { - headers: { "Content-Type": "text/plain; charset=utf-8" }, - }) -} - export async function POST(req: Request): Promise { const crossSite = rejectCrossSite(req) if (crossSite) return crossSite @@ -53,7 +46,7 @@ export async function POST(req: Request): Promise { // Check if VLM validation is enabled (default: true) const enableValidation = process.env.ENABLE_VLM_VALIDATION !== "false" if (!enableValidation) { - return createStreamingResponse(DEFAULT_VALID_RESULT) + return Response.json(DEFAULT_VALID_RESULT) } const body: ValidateDiagramRequest = await req.json() @@ -123,7 +116,7 @@ export async function POST(req: Request): Promise { error, ) // Return valid if no vision model is configured - return createStreamingResponse(DEFAULT_VALID_RESULT) + return Response.json(DEFAULT_VALID_RESULT) } // Parse timeout with validation (minimum 1000ms, default 10000ms) @@ -133,8 +126,7 @@ export async function POST(req: Request): Promise { parseInt(process.env.VALIDATION_TIMEOUT || "10000", 10), ) || 10000 - // Stream the VLM response for useObject consumption - const result = streamText({ + const { output, totalUsage } = await generateText({ model, output: Output.object({ schema: ValidationResultSchema }), system: VALIDATION_SYSTEM_PROMPT, @@ -155,23 +147,19 @@ export async function POST(req: Request): Promise { ], maxOutputTokens: 1024, abortSignal: AbortSignal.timeout(timeout), - onFinish: ({ output, totalUsage }) => { - if (countsQuota && totalUsage) { - recordTokenUsage( - userId, - (totalUsage.inputTokens || 0) + - (totalUsage.outputTokens || 0), - ) - } - if (sessionId && output) { - console.log( - `[validate-diagram] Session ${sessionId}: valid=${output.valid}, issues=${output.issues?.length ?? 0}`, - ) - } - }, }) - - return result.toTextStreamResponse() + if (countsQuota) { + await recordTokenUsage( + userId, + (totalUsage.inputTokens || 0) + (totalUsage.outputTokens || 0), + ) + } + if (sessionId) { + console.log( + `[validate-diagram] Session ${sessionId}: valid=${output.valid}, issues=${output.issues?.length ?? 0}`, + ) + } + return Response.json(output) } catch (error) { // Log with session context if available const errorMessage = @@ -179,6 +167,6 @@ export async function POST(req: Request): Promise { console.error("[validate-diagram] Error:", errorMessage) // On error, return valid to not block the user - return createStreamingResponse(DEFAULT_VALID_RESULT) + return Response.json(DEFAULT_VALID_RESULT) } } diff --git a/components/canvas/canvas-stage.tsx b/components/canvas/canvas-stage.tsx index 2cb1617e..8b40dcb0 100644 --- a/components/canvas/canvas-stage.tsx +++ b/components/canvas/canvas-stage.tsx @@ -136,8 +136,7 @@ export function CanvasStage({ key={src} ref={drawioRef} src={src} - configCss={DRAWIO_CSS} - editorCss={DRAWIO_CSS} + css={DRAWIO_CSS} dark={isDark} onLoad={onDrawioLoad} onAutoSave={handleDiagramAutoSave} diff --git a/components/canvas/drawio-frame.tsx b/components/canvas/drawio-frame.tsx index df47a3fc..177094d8 100644 --- a/components/canvas/drawio-frame.tsx +++ b/components/canvas/drawio-frame.tsx @@ -30,10 +30,11 @@ export interface DrawioFrameHandle { interface DrawioFrameProps { src: string - /** CSS sent with the configure message (works cross-origin too) */ - configCss: string - /** CSS injected once the editor is reachable directly (same origin) */ - editorCss: string + /** + * Theme CSS: sent with the configure message (works cross-origin too) + * and, same origin, injected as a