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:
dayuan.jiang
2026-10-05 13:04:32 +09:00
parent 49468f9478
commit cfbf17f97e
12 changed files with 288 additions and 53 deletions
+8 -2
View File
@@ -55,13 +55,19 @@ export class Autosaver {
return this.dir ? join(this.dir, `${sessionId}.drawio`) : null
}
// Saved files that could not be read back: never written over, since
// the session then shows something else than what they hold
private unreadable = new Set<string>()
/** The session's saved diagram, or null. */
load(sessionId: string): string | null {
const path = this.pathFor(sessionId)
if (!path || !existsSync(path)) return null
try {
return readFileSync(path, "utf-8")
} catch {
} catch (error) {
log.warn(`Could not read the saved diagram ${path}: ${error}`)
this.unreadable.add(path)
return null
}
}
@@ -87,7 +93,7 @@ export class Autosaver {
const entry = this.pending.get(sessionId)
this.pending.delete(sessionId)
const path = this.pathFor(sessionId)
if (!entry || !this.dir || !path) return
if (!entry || !this.dir || !path || this.unreadable.has(path)) return
try {
const isNew = !existsSync(path)
// A blank page the browser shows before any drawing: nothing to keep