Boundary snapshots flushed the debounced writes but didn't wait for them,
so the snapshot could read the row before the edit it was meant to keep.
They now await flushAllModelWrites first. A closing window can't await,
so it sends the writes and then the snapshot straight behind them: in
the browser the worker keeps that order, and on the desktop the snapshot
can still win, leaving the edit saved but unversioned until its next
send.
The idle tracker kept one timer for all requests, so a write to any
request, from another window or sync, restarted the active one's
countdown. Each request now has its own, cleared when it fires or when
that request is captured at a boundary.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Clean merge with no conflicts or compile fixes. Regenerated bindings
differ from the merged files only in formatting, so none are included.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Restore told open editors to re-read the request before its change event
had reached the store, so header and parameter rows could keep showing
the old content. The restore RPC now returns the restored request, and
the frontend puts it in the store before calling wasUpdatedExternally,
the same way deleteModel applies its change locally once the RPC
resolves.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Conflicts were all at registration points; both sides are kept.
Main now routes every write through one connection (#642): ClientDb only
reads and writes go through `with_tx` on a WriteDb. Versioning follows:
snapshot, restore, prune and the cascade delete move to WriteDb, while the
lookups and the "has it changed" check stay on ClientDb. Callers take a
write transaction the way their neighbours do:
- The HTTP send snapshots in its own transaction from
`resolve_send_inputs`, and a failure there (including not getting the
writer) is still logged and swallowed, so the response just has no
version.
- gRPC and WebSocket connect snapshot inside the transaction that upserts
the connection.
- The snapshot and restore RPCs, on the desktop and in the browser host,
each run in a transaction.
- The request and workspace cascades live on main's WriteDb deletes.
The Request Changed dropdown moves into the response pane's
`statusLineRight` slot, since main moved the status line into the shared
pane view.
The plugin runtime's copy of the model bindings picks up `versionId`, and
`gen_rpc.ts` is regenerated.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Use an object with a null prototype so inherited property names are not
mistaken for existing fields and __proto__ remains a literal JSON key.
Cover __proto__, constructor, and toString with regression cases.
When the selected response's version no longer matches the live request, the
response header grows a "Request Changed" control with View Diff and Restore.
It follows the GraphQL editor's shape — a state-labelled dropdown button rather
than a new icon in the action row — because the label is the whole point: it
has to say *that* something is different before it offers to do anything about
it. Hidden when the two agree, and for responses recorded before versioning
existed, which have no version and never will.
The diff reuses the Git dialog's DiffViewer over YAML renderings of the two
documents, so a request diff reads like a commit diff.
Restore flushes pending edits first (the backend restores from the database, so
a debounced keystroke would otherwise land on top of it) and calls
wasUpdatedExternally afterwards, because the write came from this window and
the store's echo suppression would leave open editors showing the old content.
EditSessionTracker turns the boundaries only the frontend can see — switching
requests, losing focus, closing, falling idle for 60s — into snapshot calls. It
tracks no content of its own: content addressing already decides whether a
boundary had anything behind it, which is what keeps this a timer and two
assignments instead of a change-tracking system.
Adds a chevron on pair editor name and value inputs that opens the same options as inline autocomplete, so suggestions can be found by clicking instead of only by typing. Long values like User-Agent show a short label but insert the full string.
Row action menus move to a vertical ellipsis so the chevron only ever means "pick a value into this field".
Also restores the per-worktree Tauri config handling in run-dev.mjs, which a merge on the branch had reverted.