refactor(web): validate and repair diagram XML with the MCP server's engine

- Delete the web app's own copy of the XML checks and repairs from
  lib/utils.ts (1,074 lines). loadDiagram now uses the MCP server's
  validateAndFixXml without the strict checks, because the XML may hold
  the user's own diagram
- display_diagram and append_diagram prepare the model's XML with the new
  shared prepareNewDiagram, also used by the MCP create_new_diagram: wrap,
  validate strictly and auto-fix while it is still a bare model (where
  duplicate ids are renamed), then turn it into an mxfile
- The streaming preview of display_diagram no longer redraws the model's
  raw cells after the tool handler loaded the checked diagram, and drops
  a queued preview once the input is complete. That redraw lost
  auto-fixes and UserObject/object wrappers, so a linked cell lost its
  label; it also showed a second error toast
- The web repair regression tests now run against the MCP functions
- New e2e test checks the canvas content after display_diagram
- Fix the e2e upload tests, whose file input locator also matched the
  template import input
This commit is contained in:
dayuan.jiang
2026-10-04 12:44:01 +09:00
parent b7c543ca70
commit e49e9f0c47
14 changed files with 276 additions and 1303 deletions
+15 -8
View File
@@ -6,10 +6,14 @@ import type {
} from "@/components/chat/ValidationCard"
import type { ValidationResult } from "@/lib/diagram-validator"
import { formatValidationFeedback } from "@/lib/diagram-validator"
import { isMxCellXmlComplete, wrapWithMxFile } from "@/lib/utils"
import { isMxCellXmlComplete } from "@/lib/utils"
import { prepareNewDiagram } from "@/packages/mcp-server/src/new-diagram.ts"
const DEBUG = process.env.NODE_ENV === "development"
// display_diagram replaces the document with this one page
const NEW_PAGE = { pageId: "page-1", pageName: "Page-1" }
interface ToolCall {
toolCallId: string
toolName: string
@@ -173,11 +177,12 @@ NEXT STEP: Call append_diagram with the continuation XML.
const finalXml = xml
partialXmlRef.current = "" // Reset any partial from previous truncation
// Wrap raw XML with full mxfile structure for draw.io
const fullXml = wrapWithMxFile(finalXml)
// loadDiagram validates and returns error if invalid
const validationError = onDisplayChart(fullXml)
// Wrap, validate and auto-fix the model's XML like the MCP server's
// create_new_diagram, then load it
const prepared = prepareNewDiagram(finalXml, NEW_PAGE)
const validationError = prepared.ok
? onDisplayChart(prepared.xml, true)
: prepared.error
if (validationError) {
console.warn("[display_diagram] Validation error:", validationError)
@@ -545,8 +550,10 @@ Start your continuation with the NEXT character after where it stopped.`,
const finalXml = partialXmlRef.current
partialXmlRef.current = "" // Reset
const fullXml = wrapWithMxFile(finalXml)
const validationError = onDisplayChart(fullXml)
const prepared = prepareNewDiagram(finalXml, NEW_PAGE)
const validationError = prepared.ok
? onDisplayChart(prepared.xml, true)
: prepared.error
if (validationError) {
addToolOutput({