Release exp-v0.52.250: recognize Agent _row_id in replay merge (#7133, @ruizanthony) (#7161)

Co-authored-by: n <a@n>
This commit is contained in:
nesquena-hermesandn authored and GitHub committed 2026-08-20 01:06:11 +00:00
1 parent 43bcdcf97f
commit dc9464f62c
1 file changed
+2
+2
View File
@@ -5,6 +5,8 @@
### Fixed
- **A message you sent at the moment a reply finished no longer shows up twice (out of order) after a reload.** The Hermes Agent stamps persisted messages with a `_row_id`, but the WebUI replay-merge only recognized its other row-id aliases, so the same stored row looked new and was appended again after the settled answer. Replay now recognizes the `_row_id` alias at the shared identity chokepoint, so the row is matched to its existing turn and kept in order. Thanks @ruizanthony. (#7133)
- **Remote (SSH/Docker) workspaces no longer fail with "Path does not exist" when the WebUI host is macOS.** A macOS host resolving a target-side Linux workspace path (e.g. `terminal.cwd = /home/<user>`) ran it through the local filesystem, where macOS rewrites the synthetic `/home` firmlink to `/System/Volumes/Data/home` and then rejects the non-existent local path. Remote terminal profiles now preserve the target-side POSIX path verbatim instead of resolving it against the host filesystem — after the same containment checks (POSIX normalization rejects `..` traversal, NUL bytes, and blocked system roots, and the path must stay within `terminal.cwd`). Local workspaces still resolve and are contained exactly as before, and the fix is host-agnostic (helps a Linux host with a remote profile too). Thanks @alfred-rootson. (#7132)
- **Regenerating a response is now atomic — a concurrent message sent at the same moment can no longer be silently erased, and regeneration is no longer wrongly blocked on completed imported turns.** Starting a regeneration snapshots and validates session state under the session lock before mutating it, so a message that another tab/device sends during the same window survives (the regeneration cleanly returns a conflict instead of rolling back the winner), and completed WebUI-owned turns imported from a CLI/TUI/desktop session can be regenerated while malformed, read-only, or foreign final turns stay correctly rejected. The active-turn marker is now carried through the public projection so a mid-stream reload renders the pending prompt once instead of twice. Thanks @rodboev. (#6677)
- **Large sessions no longer replay a stale duplicate prompt (or drop a real turn) when reconciling the sidecar against the model transcript.** Matching one logical turn across the two stores relied on an O(n²) fuzzy fallback that was bounded to the first 1,000 keys for performance — but above that bound a workspace-prefixed prompt (state.db stores the model-facing `[Workspace::v1: …]` wrapper while the WebUI sidecar owns the bare text) stopped deduping, so a 1,001-key session replayed the prefixed prompt after its answer. The workspace prefix is now folded into the exact key so protocol-equivalent turns match in O(1) above the cap, and — critically — that normalization is source-aware: only the model-facing state.db key strips the wrapper, while the sidecar-owned visible key preserves literal text verbatim, so a user who genuinely types `[Workspace: …]` isn't collapsed into a different turn. Thanks @Dandandad. (#7128)