MCP preview after the server lost a session (it expired, or the MCP
process restarted):
- Every server state has an id, made when the state is created. The tab
notices a new id even when the version numbers happen to match, and
every push names the state it was based on, so one based on a lost state
is refused, also when it comes before the tab's first poll (the server
recovers the saved file first).
- The tab keeps the newest canvas XML, saved or not. When the server knows
nothing (no file) or exactly what the tab last saved, the canvas wins and
is saved, so edits made while the server was down are kept. Otherwise
the server's diagram (an AI write the tab missed, a cleared document
that was saved) is shown and the tab's copy goes to History.
- Late answers to an old state's push or poll are dropped; a failed push
says the server is unreachable; Download as .drawio saves the canvas.
Settings and server:
- Saved providers this version does not know stay in storage with their
keys, and sending no longer trips over them.
- The desktop "Ollama (Local)" preset with a key goes to local Ollama
again; a server model's Ollama URL variable is read; the admin panel
writes Ollama Cloud's URL for a key without one.
- Provider error texts show again in the desktop app and for EdgeOne.
- .env: a quoted value followed by a comment ending in a quote is read as
dotenv reads it; unquoted values are unchanged.
- Desktop app: the next launch opens the port where a chat was last
saved; a launch elsewhere that saves nothing does not move it, and a
page with no chats lets the next launch try the other port once.
- The Test button no longer stays busy after another tab changed the key.
- A completed append_diagram is no longer undone by an earlier failed
edit's preview; a file read once in vain is saved again once it is read
or gone.
From the first batch's review:
- The admin panel's Test of an entry without a URL now tests the server's
<P>_BASE_URL, where chat sends the entry's key; chat is unchanged (the
first fix rerouted working setups).
- The model list ends downloads that are too large, accepts answers
without a body, and keeps the "redirects are not allowed" explanation.
- A test covers the preview's History rendering.
- A session whose state expired was recovered from its auto-save file only
for the preview page; the tools built on their older copy and then
overwrote the file. They now recover it first (restoreSavedSession).
- A preview tab that missed the last AI write pushed its older diagram
over the recovered one after a restart. It now shows the recovered
diagram and keeps its own copy in History.
- An empty record of what the model has seen (after load_diagram or a
page tool on unseen changes) no longer lets one page of a multi-page
document count for all, and get_diagram counts a page only once found.
- History: a thumbnail goes only to the entry it shows, the cached image
never belongs to an older diagram, a re-serialized copy adds no entry,
and a cleared document with its own pages is kept before a restore.
- The root cell id check reads attributes one by one: rack-id="1" or id
text inside a label no longer counts.
- A compressed page counts as having cells; a saved file that could not
be read is never written over.
Found by the second PR review:
- get_diagram with a page selector, or a rejected edit's error, counted
the whole document as seen, so an edit on another page could overwrite
the user's change there. A one-page view now counts for all pages only
if the others are unchanged; otherwise the reply says to get them.
- add_page accepted shapes with the root cell ids "0" and "1" and renamed
them, breaking their edges. The check also missed ids on UserObject
wrappers and ids written with spaces around the "=".
- Root cells written over two lines were kept as an extra layer, cells
with id = "a" did not count as cells, and CDATA text before a page's
model passed the check although draw.io cannot open the page.
- Auto-save cleanup deleted the user's own files that start with mcp-.
Only names in the session id format are removed now.
- Restoring a history entry dropped edits made in the browser since the
last entry. They are added to history first.
- A session whose state expired showed a blank page, and the next change
overwrote its auto-save file. The saved file is loaded instead.
- An edit on a page export's one-page projection, made before the real
document was back, replaced the whole document.
- A late sync reply could overwrite a newer edit: each sync export is
numbered, and the server ignores replies older than the current state.
- screenshot_diagram could return another session's image after
start_session ran during its retries.
Found by the PR review, each with a test that failed first:
- get_diagram during a page export returned the one-page projection on
screen as the whole document (6 of 6 times when timed so). The preview
page no longer answers a sync while a projection shows, and syncs after
reloading, so the poll that restores the real document exports it.
- Exports are numbered on the server too: a late result of an export that
timed out was saved as the next export's file.
- In Chrome, a new_xml with a syntax error counted the <parsererror>
element as a second cell, so the web app rejected edits that auto-fix
repairs ("must contain exactly one cell").
- hasCells missed single-quoted ids, so screenshot_diagram called such a
diagram empty and auto-save never created its file.
- A literal \n directly under a <diagram> that has a model passed
validation; only text-only pages are compressed data.
- A wrapped mxCell repeating its UserObject's id took the wrapper's place
in edits, so delete and update left an empty or nested wrapper.
- Bare cells with a shape or edge id of "0" or "1" are rejected with a
clear message instead of being renamed, which broke their edges.
- DRAWIO_DATA_DIR expands ~, which JSON configs pass on as it is.
The web app will reuse the MCP server's XML engine instead of its own
copy in lib/utils.ts, so these modules now run in the browser too.
- Relative imports end in .ts, rewritten to .js by tsc
(rewriteRelativeImportExtensions); Next.js resolves them directly
- Every module uses the global DOMParser/XMLSerializer: native in the
browser, linkedom in Node via installDomPolyfill. pages.ts parsed with
linkedom but serialized with the global serializer, which throws in
the browser
- The saxes syntax check moves to xml-syntax.ts, so the browser does not
pull in linkedom; it now also rejects undeclared prefixes such as
xlink:, as the browser does
- Page decompression uses pako and atob instead of node:zlib and Buffer
- hasCells moves to pages.ts, away from the file system code
- The duplicate cell id check counts UserObject/object ids
- wrapCellsInModel drops comments and text before the first cell, which
the web app accepts today
- validateAndFixXml takes { strict: false } for diagrams with user content
- Web tests run these modules with a browser DOM (jsdom)
- saxes becomes a direct dependency of the web app
- Preview page: keep an MCP export open until the server has its result.
A poll answered before that still saw the request and started the same
export again, so a parallel page export could write the previous
page's image into its file
- Auto-save only removes its own mcp-*.drawio files, so a DRAWIO_DATA_DIR
that also holds the user's diagrams keeps them
- screenshot_diagram captures a page that has no id attribute by loading
just that page, like export_diagram
- An empty <Array as="points"/> no longer hides orphan mxPoints that
come after it
- POST /api/state refuses a push without xml, which used to wipe the
stored diagram
- Clear exportOptions when an export ends, reuse hasCells for the empty
diagram check, and reword two log lines
- Save the latest diagram of every session 1 second after each change
(AI write, browser edit, history restore) to ~/.next-ai-drawio/<id>.drawio,
keep the newest 50, flush on shutdown; DRAWIO_DATA_DIR changes the folder
and "off" disables it, like the web app's IndexedDB sessions
- start_session names the file, so a resumed conversation can reopen the
diagram with load_diagram after the MCP process restarted
- Fix PNG/SVG exports randomly timing out: a previous export's 10 second
timer cleared the export in progress, and a late reply could be taken
for the current one; exports are now numbered