From 0a413924893f56a0b34bccf9dbbe84bd5028ff13 Mon Sep 17 00:00:00 2001 From: teknium1 <127238744+teknium1@users.noreply.github.com> Date: Fri, 18 Sep 2026 00:46:33 -0700 Subject: [PATCH] fix(session_search): cap title-match discovery entries like FTS hits _title_match_result shaped its bookends and window with no max_content_len while _bookend/_hydrate_hit cap FTS hits at 1200/4000, so a session found by title could still return one 74K tool result verbatim. Same caps, same metadata. --- tests/tools/test_session_search.py | 13 +++++++++++++ tools/session_search_tool.py | 9 ++++++--- 2 files changed, 19 insertions(+), 3 deletions(-) diff --git a/tests/tools/test_session_search.py b/tests/tools/test_session_search.py index 9468c56197..6bb41d5f09 100644 --- a/tests/tools/test_session_search.py +++ b/tests/tools/test_session_search.py @@ -508,6 +508,19 @@ class TestReadShape: assert big["original_content_chars"] == 80_000 assert sum(len(m.get("content") or "") for m in result["messages"]) < 5_000 + def test_title_match_entry_caps_content_like_fts_hits(self, db): + """A session-title match is a discovery entry: bookends 1200, window 4000, same as FTS hits.""" + db.create_session("s_titled", source="cli") + db.set_session_title("s_titled", "quasar ledger reconciliation") + db.append_message("s_titled", role="user", content="reconcile the quasar ledger") + db.append_message("s_titled", role="tool", content="y" * 80_000) + db.end_session("s_titled", "cli_exit") + result = json.loads(session_search(query="quasar ledger reconciliation", db=db, detail="full")) + entry = next(r for r in result["results"] if r["matched_role"] == "session_title") + shaped = entry["bookend_start"] + entry["messages"] + entry["bookend_end"] + big = [m for m in shaped if m.get("original_content_chars") == 80_000] + assert big and all(m["content_truncated"] and len(m["content"]) <= 4001 for m in big) + # ========================================================================= # Session links — the value the agent writes to point the user at a session diff --git a/tools/session_search_tool.py b/tools/session_search_tool.py index 2589364000..f5c0e78a83 100644 --- a/tools/session_search_tool.py +++ b/tools/session_search_tool.py @@ -294,14 +294,17 @@ def _title_match_result(db, query: str, current_lineage_root: Optional[str]) -> lambda: db.get_anchored_view(session_id, anchor_id, window=5, bookend=3), {}, "get_anchored_view failed for title match %s/%s", session_id, anchor_id) title = session_meta.get("title") or title_query - def shape(key, fallback, anchor=None): - return [_shape_message(m, anchor_id=anchor) for m in (view.get(key) or fallback)] + # Same caps as FTS hits (_bookend / _hydrate_hit): a title match is a discovery entry too. + def shape(key, fallback, anchor=None, max_content_len=1200): + return [_shape_message(m, anchor_id=anchor, max_content_len=max_content_len) + for m in (view.get(key) or fallback)] return {**_discovery_entry( lineage_root, session_id=session_id, when=_format_timestamp(session_meta.get("started_at")), source=session_meta.get("source", "unknown"), model=session_meta.get("model") or "unknown", title=title, matched_role="session_title", match_message_id=anchor_id, snippet=f"Session title matched: {title}", - bookend_start=shape("bookend_start", messages[:3]), messages=shape("window", messages[:5], anchor_id), + bookend_start=shape("bookend_start", messages[:3]), + messages=shape("window", messages[:5], anchor_id, max_content_len=4000), bookend_end=shape("bookend_end", messages[-3:]), messages_before=view.get("messages_before", 0), messages_after=view.get("messages_after", max(len(messages) - 5, 0)), detail="full"), "_lineage_root": lineage_root}