Release v0.51.302 — Release JR (stage-brick — mobile/iOS brick + large-session perf hotfixes) (#3754)
Some checks failed
Release & Docker / release (push) Has been cancelled
Some checks failed
Release & Docker / release (push) Has been cancelled
* fix(ui): stop hidden toast from intercepting clicks on mobile (#3735) The .toast container kept pointer-events:auto while hidden (opacity:0), so its fixed padding sat over mobile profile action buttons and ate their clicks. Set pointer-events:none when hidden; restore auto on .toast.show. Co-authored-by: timlawrenz <timlawrenz@users.noreply.github.com> * fix(sessions): rename saves on blur so iOS Safari rename works (#3729) iOS Safari has no Enter key; the keyboard 'Done' button fires blur, and the old onblur=cancel discarded the rename. Flip blur to save (Escape still cancels) for session rename and project create/rename, with a _finishDone guard to prevent a double-fire between blur and the API callback. Co-authored-by: reinocheong <reinocheong@users.noreply.github.com> * perf(session): skip fuzzy dedup matching for giant merge payloads (#3730) Large tool/log payloads made _matching_visible_duplicate() casefold+regex-tokenize multi-megabyte contents on every visible key, so /api/session took 10s+ and blocked /api/sessions for ~19s. Keep loose normalization lazy+cached and skip substring/fuzzy matching for non-exact payloads >200KB; exact visible-key matches still short-circuit. Co-authored-by: alvistar <alvistar@users.noreply.github.com> * docs(changelog): stamp v0.51.302 — Release JR (stage-brick brick/perf hotfixes #3735 #3729 #3730) --------- Co-authored-by: nesquena-hermes <[email protected]> Co-authored-by: timlawrenz <timlawrenz@users.noreply.github.com> Co-authored-by: reinocheong <reinocheong@users.noreply.github.com> Co-authored-by: alvistar <alvistar@users.noreply.github.com>
This commit is contained in:
@@ -4040,7 +4040,6 @@ def _session_message_visible_key(msg: dict):
|
||||
|
||||
def _build_visible_duplicate_lookup(visible_keys: set[tuple]) -> dict:
|
||||
by_role = {}
|
||||
loose_by_key = {}
|
||||
for key in visible_keys:
|
||||
try:
|
||||
role = key[0]
|
||||
@@ -4050,8 +4049,10 @@ def _build_visible_duplicate_lookup(visible_keys: set[tuple]) -> dict:
|
||||
if not content:
|
||||
continue
|
||||
by_role.setdefault(role, []).append(key)
|
||||
loose_by_key[key] = _loose_session_message_content(content)
|
||||
return {"keys": visible_keys, "by_role": by_role, "loose_by_key": loose_by_key}
|
||||
# Keep loose_by_key lazy. Some transcripts contain multi-megabyte tool
|
||||
# outputs; eagerly casefolding + regex-tokenizing every visible key on every
|
||||
# duplicate probe made /api/session take 10s+ and blocked /api/sessions.
|
||||
return {"keys": visible_keys, "by_role": by_role, "loose_by_key": {}}
|
||||
|
||||
|
||||
def _matching_visible_duplicate(visible_key: tuple, visible_keys: set[tuple], lookup: dict | None = None):
|
||||
@@ -4064,16 +4065,28 @@ def _matching_visible_duplicate(visible_key: tuple, visible_keys: set[tuple], lo
|
||||
if lookup is None:
|
||||
lookup = _build_visible_duplicate_lookup(visible_keys)
|
||||
loose_content = None
|
||||
loose_by_key = lookup.setdefault("loose_by_key", {})
|
||||
for existing_key in lookup.get("by_role", {}).get(role, []):
|
||||
existing_role = existing_key[0]
|
||||
existing_content = existing_key[1] if len(existing_key) > 1 else ""
|
||||
if role != existing_role or not existing_content:
|
||||
continue
|
||||
# Exact visible-key equality was checked above. For very large payloads
|
||||
# (tool logs / request dumps), Python-in substring and fuzzy-token
|
||||
# comparisons are both expensive and low-value; doing them repeatedly
|
||||
# made session loading block the whole WebUI for many seconds. Keep
|
||||
# fuzzy matching for normal chat-sized text, but do exact-only matching
|
||||
# for giant payloads.
|
||||
if max(len(content), len(existing_content)) > 200_000:
|
||||
continue
|
||||
if content in existing_content or existing_content in content:
|
||||
return existing_key
|
||||
if loose_content is None:
|
||||
loose_content = _loose_session_message_content(content)
|
||||
loose_existing = lookup.get("loose_by_key", {}).get(existing_key, "")
|
||||
loose_existing = loose_by_key.get(existing_key)
|
||||
if loose_existing is None:
|
||||
loose_existing = _loose_session_message_content(existing_content)
|
||||
loose_by_key[existing_key] = loose_existing
|
||||
if loose_content and loose_existing and (
|
||||
loose_content in loose_existing or loose_existing in loose_content
|
||||
):
|
||||
|
||||
Reference in New Issue
Block a user