mirror of
https://github.com/DayuanJiang/next-ai-draw-io.git
synced 2026-10-12 04:29:51 +08:00
fix(mcp-server): review fixes for the version cards and History
The shell's version cards (shell/node-versions-source.ts): - a version's change and undo target are the state it replaced, the History entry right before its first copy, not the card before it: after a restore those differ, and undo went to the wrong version (and not where restore_version steps_back=1 goes) - a card restores the newest copy of its content, as restore_version does, so page settings the user changed (a "user" copy) are kept - a blank page after a drawing is a clear of the canvas, a version of its own; only the blank page before any drawing is hidden - numbers and changes are keyed by content, not by the first copy's id, so a version keeps them when its first copy drops out of the server's 20-entry buffer; the caches start over for another server state (the process restarted: entry ids name other content) The server's History (src/history.ts): - firstCopyIds compares each entry with the first of every group only: a bare model matches any page name, so "same content" is not transitive, and a card could show one document and restore another - the time and pages fields had no reader; pages parsed every XML once more on every write Reading History (src/http-server.ts, shell/mcp-sync-core.ts): - GET /api/state and a push's answer carry a History key (entry count, newest id, the entry on the canvas); the shell reads History again only when it changes, so a hand edit no longer downloads every entry's XML and thumbnail - a failed History read is told again at the next poll - a History list from a state the poll has not seen yet is dropped
This commit is contained in:
@@ -1197,8 +1197,6 @@ describe("GET /api/history for the version cards", () => {
|
||||
svg: "",
|
||||
xml: page("a"),
|
||||
source: null,
|
||||
time: a.time,
|
||||
pages: 1,
|
||||
firstId: a.id,
|
||||
})
|
||||
expect(d.entries[1]).toMatchObject({
|
||||
@@ -1209,6 +1207,49 @@ describe("GET /api/history for the version cards", () => {
|
||||
})
|
||||
})
|
||||
|
||||
it("gives the state a History key, which a hand edit changes once and a further one not at all", async () => {
|
||||
// The shell reads History (every entry's XML and picture) again
|
||||
// only when the key changes
|
||||
const id = "mcp-history-key"
|
||||
setState(id, page("a"))
|
||||
addHistory(id, page("a"))
|
||||
const [a] = getHistory(id)
|
||||
const first = JSON.parse(
|
||||
(await request(`/api/state?sessionId=${id}`)).body,
|
||||
)
|
||||
expect(first.historyKey).toBe(`1:${a.id}:${a.id}`)
|
||||
// A hand edit: the canvas is at no entry now, History is the same
|
||||
const push = await postJson("/api/state", {
|
||||
sessionId: id,
|
||||
xml: page("b"),
|
||||
baseVersion: first.version,
|
||||
stateId: first.stateId,
|
||||
})
|
||||
expect(push.status).toBe(200)
|
||||
expect(JSON.parse(push.body).historyKey).toBe(`1:${a.id}:null`)
|
||||
const again = await postJson("/api/state", {
|
||||
sessionId: id,
|
||||
xml: page("c"),
|
||||
baseVersion: first.version + 1,
|
||||
stateId: first.stateId,
|
||||
})
|
||||
expect(JSON.parse(again.body).historyKey).toBe(`1:${a.id}:null`)
|
||||
const polled = JSON.parse(
|
||||
(await request(`/api/state?sessionId=${id}`)).body,
|
||||
)
|
||||
expect(polled.historyKey).toBe(`1:${a.id}:null`)
|
||||
// A write keeps the edit in History: the key names the new entry
|
||||
keepInHistory(id, page("c"))
|
||||
setState(id, page("d"))
|
||||
addHistory(id, page("d"))
|
||||
const [, c, d] = getHistory(id)
|
||||
expect(c.xml).toBe(page("c"))
|
||||
const after = JSON.parse(
|
||||
(await request(`/api/state?sessionId=${id}`)).body,
|
||||
)
|
||||
expect(after.historyKey).toBe(`3:${d.id}:${d.id}`)
|
||||
})
|
||||
|
||||
it("names the entry a restored copy stands for, and marks the copy as a restore", async () => {
|
||||
const id = "mcp-history-cards-restore"
|
||||
addHistory(id, page("a"))
|
||||
|
||||
Reference in New Issue
Block a user