Chats:
- New Chat right after an answer saves that chat once. Saves run one at
a time and read the chat on screen when their turn comes; a save
scheduled for a chat that is no longer on screen is dropped. A chat
whose id was still on its way to the URL no longer comes back after
New Chat (the next answer went into it).
- Crossing the 768 px breakpoint keeps the chat panel: a streaming answer,
unsaved messages and attachments stay. The panel gets the sizes of each
side, and a panel collapsed on desktop opens on mobile.
- The chat's export waits for its own reply: an edit's history export
still on its way no longer answers it with the older diagram, and two
file saves at once no longer swap results.
- A second edit in one answer is previewed on the first edit's result.
- Stop also ends a running screenshot check; a chat that cannot be saved
(storage full) can be left with "Continue without saving".
- Small diagrams with shapes count as diagrams; the tool card no longer
crashes on malformed operations.
Quota and providers:
- Requests that reach the server's own endpoints count toward the quota:
EdgeOne (always its own endpoint now), a private base URL whatever key
header is sent, keyless Ollama without a URL. With the quota on, a
redirect is followed only to a public address. The output cap applies
to these requests too.
- Stop records the tokens of the steps that finished; the screenshot check
counts its tokens without counting a request.
- EdgeOne configured only by AI_PROVIDER works, also in the admin Test,
which forwards the access code. Azure set up only in the admin panel
works in chat. The Test sends a Bedrock session token.
- The admin panel's Test of an entry without a URL uses the server's URL
as the server does (no private address check for it); the admin panel
no longer writes an Ollama URL.
MCP server:
- Write tools and start_session run one at a time, so two at once never
drop each other's change; a cancelled call waiting its turn is skipped.
get_diagram and export_diagram keep the session they started with.
- Export to .drawio first gets the user's latest edits from the browser.
- History thumbnails: one that arrives after the next AI write is
dropped; a sync reply keeps the image; a version that changed only page
settings is its own entry.
- A diagram over the 10 MB limit is saved without its image, or the user
is told to download it (the server now answers 413 instead of cutting
the connection).
- Labels holding text like id='1' or parent='1' are no longer read as
attributes (a layer or a parent was deleted). A broken bare
<mxGraphModel> file is refused.
- After a sync reply the tab no longer sends its autosave copy again.
Desktop and files:
- A newer switch of the same preset is not rolled back by an older one
that failed. .env values with escaped quotes are read whole.
- MCP saved files: a file that could not be read stays protected while a
folder without permission hides it, and is saved again once deleted.
- The desktop app reports "no chats" only when the count was read and no
model settings are stored.
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
- Validate and escape the mcp session id; only serve localhost Host/Origin
- Malformed URLs and session ids return errors instead of crashing the process
- Strict XML syntax check with saxes (linkedom never reports parse errors)
- autoFixXml no longer corrupts valid XML; attribute newlines serialized as entities
- Sessions stay alive while polled; browser pushes carry a base version (409 on conflict)
- Page tools respect the edit gate; UTF-8 bodies decoded correctly
- Export replies matched to requests and serialized; xml sync export handled
- UserObject/object cells addressable by id; history restored by stable id; logs off stdout
* feat(mcp): add load_diagram tool to load .drawio files into the session
Loading a file previously required the agent to read the file itself and
pass the entire XML through create_new_diagram - wasteful for large
diagrams and impossible for draw.io's compressed save format.
load_diagram takes a file path; the server reads it, decompresses any
compressed pages (base64 -> raw deflate -> URI-decode, per page), and
replaces the session document. The loaded XML is deliberately NOT marked
as seen by the edit gate: the model only supplied a path, so it must
call get_diagram once before editing.
* chore(mcp): version 0.2.3
* fix(mcp): report package.json version in the MCP handshake
The McpServer metadata version was a separate hardcoded string that
never matched the published version (stuck at 0.1.2, then 0.3.0 while
npm shipped 0.2.x). Read it from package.json at startup instead —
works from both src/ (tsx) and dist/ (published build).