mirror of
https://github.com/DayuanJiang/next-ai-draw-io.git
synced 2026-10-11 03:59:58 +08:00
fix(mcp-server): recover sessions in one place, and more fixes from the third review
- 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.
This commit is contained in:
@@ -144,7 +144,14 @@ function showNotice(text) {
|
||||
noticeTimer = setTimeout(() => el.classList.remove('open'), 8000);
|
||||
}
|
||||
|
||||
// source is 'sync' for replies to a server sync request, else 'edit'
|
||||
// Same rule as hasCells in pages.ts: a cell besides the root cells, or a
|
||||
// compressed page
|
||||
function hasCells(xml) {
|
||||
return /<(mxCell\b[^>]*\bid\s*=\s*["'](?![01]["'])|UserObject\b|object\b)|<diagram\b[^>]*>\s*[^\s<]/.test(xml || '');
|
||||
}
|
||||
|
||||
// source is 'sync' for replies to a server sync request, 'recover' for the
|
||||
// tab's copy after the server recovered the session, else 'edit'
|
||||
async function pushState(xml, svg = '', baseVersion = currentVersion, source = 'edit') {
|
||||
if (!sessionId) return;
|
||||
try {
|
||||
@@ -157,7 +164,11 @@ async function pushState(xml, svg = '', baseVersion = currentVersion, source = '
|
||||
// 409: the AI wrote a newer version; load it now
|
||||
else if (r.status === 409) {
|
||||
const d = await r.json().catch(() => ({}));
|
||||
if (d.savedToHistory) showNotice('The AI changed the diagram while you were editing. Your last change was saved in History.');
|
||||
if (d.savedToHistory) {
|
||||
showNotice(source === 'recover'
|
||||
? 'The diagram was restored from its saved file. What this tab showed before is in History.'
|
||||
: 'The AI changed the diagram while you were editing. Your last change was saved in History.');
|
||||
}
|
||||
poll();
|
||||
}
|
||||
} catch (e) { console.error('Push failed:', e); }
|
||||
@@ -174,10 +185,18 @@ async function poll() {
|
||||
const r = await fetch('/api/state?sessionId=' + encodeURIComponent(sessionId));
|
||||
if (!r.ok) return;
|
||||
const s = await r.json();
|
||||
// The server lost this session (e.g. it expired) and rebuilt it
|
||||
// with a blank diagram: push back what the browser shows.
|
||||
// The server lost this session (it expired, or the MCP process
|
||||
// restarted) and rebuilt it. Blank: push back what the browser
|
||||
// shows. From the auto-save file, which can hold an AI write this
|
||||
// tab never loaded: show that, and keep this tab's copy in History
|
||||
// (a push based on version 0 is refused and saved there).
|
||||
if (s.version < knownVersion && lastXml) {
|
||||
pushState(lastXml);
|
||||
if (!hasCells(s.xml)) {
|
||||
pushState(lastXml);
|
||||
} else {
|
||||
currentVersion = 0;
|
||||
if (s.xml !== lastXml) pushState(lastXml, '', 0, 'recover');
|
||||
}
|
||||
}
|
||||
// Load new diagram from server (before export, so we export latest).
|
||||
// While a page-targeted projection is on screen, only the restore
|
||||
|
||||
Reference in New Issue
Block a user