refactor(session_search): halve the schema (1570->695 tok/call); teachings move into response hints
This commit is contained in:
@@ -670,6 +670,12 @@ def _scroll(
|
||||
"messages": [_shape_message(m, anchor_id=around_message_id) for m in messages],
|
||||
"messages_before": view.get("messages_before", 0),
|
||||
"messages_after": view.get("messages_after", 0),
|
||||
"hint": (
|
||||
"Scroll forward: re-call with around_message_id = the LAST message's "
|
||||
"id; backward: the FIRST message's id (the boundary message repeats "
|
||||
"as an orientation marker). messages_before/messages_after < window "
|
||||
"means you've hit that end of the session."
|
||||
),
|
||||
}
|
||||
if rebind_warning:
|
||||
response["warning"] = rebind_warning
|
||||
@@ -797,7 +803,11 @@ def _discover(
|
||||
"detail": detail,
|
||||
"results": [],
|
||||
"count": 0,
|
||||
"message": "No matching sessions found.",
|
||||
"message": (
|
||||
"No matching sessions found. FTS5 ANDs all terms by default — "
|
||||
"broaden with OR (`alpha OR beta`), exact-match with quoted "
|
||||
"phrases, exclude with NOT, or prefix-match with `deploy*`."
|
||||
),
|
||||
}
|
||||
_annotate_rebuild_status(db, _empty_payload)
|
||||
return json.dumps(_empty_payload, ensure_ascii=False)
|
||||
@@ -928,6 +938,13 @@ def _discover(
|
||||
"results": results,
|
||||
"count": len(results),
|
||||
"sessions_searched": len(seen_sessions),
|
||||
"link_hint": (
|
||||
"When referring the user to a session, write its `link` value "
|
||||
"verbatim inline mid-sentence (it renders as a titled link) — never "
|
||||
"as markdown, in backticks, on its own line, or next to the "
|
||||
"title/id/date. To read more around a compact result, scroll: "
|
||||
"session_search(session_id=..., around_message_id=match_message_id)."
|
||||
),
|
||||
}
|
||||
_annotate_rebuild_status(db, _final_payload)
|
||||
return json.dumps(_final_payload, ensure_ascii=False)
|
||||
@@ -1128,80 +1145,19 @@ def check_session_search_requirements() -> bool:
|
||||
SESSION_SEARCH_SCHEMA = {
|
||||
"name": "session_search",
|
||||
"description": (
|
||||
"Search past sessions stored in the local session DB, or scroll inside one. "
|
||||
"FTS5-backed retrieval over the SQLite message store. No LLM calls — every "
|
||||
"shape returns actual messages from the DB.\n\n"
|
||||
"SOURCE-FIRST LIMIT\n\n"
|
||||
" This tool searches Hermes conversation history only. It is not evidence "
|
||||
"about the current contents of external sources. If the user provided a "
|
||||
"direct source such as a URL, phone number/contact, app/thread, file path, "
|
||||
"account, website, or live system, inspect that original source before or "
|
||||
"instead of session_search when accessible. Use session_search as secondary "
|
||||
"context for what was previously said, not as primary proof of what the "
|
||||
"source currently contains. If the original source is inaccessible, say so "
|
||||
"and why before falling back to session history. Do not conclude 'not found' "
|
||||
"or 'no prior correspondence' from session_search alone when a direct source "
|
||||
"was provided.\n\n"
|
||||
"FOUR CALLING SHAPES\n\n"
|
||||
" 1) DISCOVERY — pass `query`:\n"
|
||||
" session_search(query=\"auth refactor\", limit=3)\n"
|
||||
" Runs FTS5, dedupes hits by session lineage, and returns the top N "
|
||||
"sessions. Adaptive detail is the default: the top-ranked result carries "
|
||||
"full context, while lower-ranked results stay compact. Pass `detail=\"full\"` "
|
||||
"to fully hydrate every result. Every result carries:\n"
|
||||
" - session_id, title, when, source\n"
|
||||
" - snippet: FTS5-highlighted match excerpt\n"
|
||||
" - detail: `full` or `compact`\n"
|
||||
" - bookend_start/bookend_end: the first/last 3 user+assistant messages "
|
||||
"for full results; empty lists for compact results\n"
|
||||
" - messages: ±5 messages around the FTS5 match for full results; only "
|
||||
"the flagged anchor message for compact results\n"
|
||||
" - match_message_id, messages_before, messages_after\n"
|
||||
" The top result's bookends + window let you reconstruct goal → match → "
|
||||
"resolution immediately. Scroll a compact result when another session looks "
|
||||
"more promising.\n\n"
|
||||
" 2) SCROLL — pass `session_id` + `around_message_id`:\n"
|
||||
" session_search(session_id=\"...\", around_message_id=12345, window=10)\n"
|
||||
" Returns a window of ±`window` messages centered on the anchor. No FTS5, "
|
||||
"no bookends — just the slice. Use after a discovery call when you need more "
|
||||
"context than the ±5 default window.\n"
|
||||
" - To scroll FORWARD: pass messages[-1].id back as around_message_id.\n"
|
||||
" - To scroll BACKWARD: pass messages[0].id back as around_message_id.\n"
|
||||
" - The boundary message appears in both windows — orientation marker.\n"
|
||||
" - When messages_before or messages_after is < window, you're at the "
|
||||
"start or end of the session.\n\n"
|
||||
" 3) READ — pass `session_id` only (no around_message_id):\n"
|
||||
" session_search(session_id=\"...\", profile=\"work\")\n"
|
||||
" Dumps the whole session by id (first 20 + last 10 messages when "
|
||||
"large). This is how you resolve an `@session:<profile>/<id>` link the "
|
||||
"user dropped into the chat: split the value on `/` into profile + id "
|
||||
"and call session_search(session_id=id, profile=profile).\n\n"
|
||||
" 4) BROWSE — no args:\n"
|
||||
" session_search()\n"
|
||||
" Returns recent sessions chronologically: titles, previews, timestamps. "
|
||||
"Use when the user asks \"what was I working on\" without naming a topic.\n\n"
|
||||
"LINKING THE USER TO A SESSION\n\n"
|
||||
" When you refer the user to a session, write its `link` value inline in "
|
||||
"your reply — every result carries one, e.g. "
|
||||
"`@session:default/20260722_204335_d62c16`. Copy it verbatim; do not "
|
||||
"reformat it as a markdown link or wrap it in backticks. Hermes renders "
|
||||
"it as a link showing the session's title, so the link IS the title: "
|
||||
"use it as a noun mid-sentence (\"that's @session:default/... — want me "
|
||||
"to pick it up?\"), never alone on its own line, and never alongside the "
|
||||
"title, id, or date spelled out — that shows the user the same session "
|
||||
"twice.\n\n"
|
||||
"FTS5 SYNTAX\n\n"
|
||||
" AND is the default — multi-word queries require all terms. Use OR explicitly "
|
||||
"for broader recall (`alpha OR beta OR gamma`), quoted phrases for exact match "
|
||||
"(`\"docker networking\"`), boolean (`python NOT java`), or prefix wildcards "
|
||||
"(`deploy*`).\n\n"
|
||||
"WHEN TO USE\n\n"
|
||||
" Reach for this on questions about Hermes conversation history itself, such "
|
||||
"as \"what did we do about X\", \"where did we leave Y\", or \"find the "
|
||||
"session where Z\". If the user provided a direct source identifier, inspect "
|
||||
"that source first when accessible; session_search can then supply historical "
|
||||
"context. The session DB carries what was said when; external tools show "
|
||||
"current source/world state."
|
||||
"Search past Hermes sessions (FTS5 over the local session DB), or read/"
|
||||
"scroll inside one. Four shapes, picked by args: `query` = discovery "
|
||||
"(top-N matching sessions, top result fully hydrated); `session_id` + "
|
||||
"`around_message_id` = scroll (window of messages around an anchor); "
|
||||
"`session_id` alone = read a whole session — how you resolve an "
|
||||
"`@session:<profile>/<id>` link (split on '/' into profile + id); no "
|
||||
"args = browse recent sessions. Results are actual DB messages, no LLM. "
|
||||
"Searches conversation history ONLY — when the user gave a direct "
|
||||
"source (URL, file, contact, live system), inspect that first; never "
|
||||
"conclude 'not found' from history alone. Use for questions about past "
|
||||
"conversations: 'what did we do about X', 'where did we leave Y'. When "
|
||||
"referring the user to a session, write its `link` value verbatim "
|
||||
"inline (it renders as a titled link)."
|
||||
),
|
||||
"parameters": {
|
||||
"type": "object",
|
||||
@@ -1228,12 +1184,9 @@ SESSION_SEARCH_SCHEMA = {
|
||||
"type": "string",
|
||||
"enum": ["newest", "oldest"],
|
||||
"description": (
|
||||
"Discovery shape only. Temporal bias on top of FTS5 ranking. Omit "
|
||||
"to keep relevance-only ordering (suitable for exploratory recall — "
|
||||
"\"what do we know about X\"). Set 'newest' for recency-shaped "
|
||||
"questions (\"where did we leave X\"). Set 'oldest' for "
|
||||
"origin-shaped questions (\"how did X start\"). Ignored in scroll "
|
||||
"and browse shapes."
|
||||
"Discovery shape only. Temporal bias on top of FTS5 ranking: omit "
|
||||
"for relevance-only (exploratory recall), 'newest' for "
|
||||
"\"where did we leave X\", 'oldest' for \"how did X start\"."
|
||||
),
|
||||
},
|
||||
"detail": {
|
||||
@@ -1258,10 +1211,9 @@ SESSION_SEARCH_SCHEMA = {
|
||||
"around_message_id": {
|
||||
"type": "integer",
|
||||
"description": (
|
||||
"Scroll shape. Message id to center the window on. From a discovery "
|
||||
"result use match_message_id, or any id seen in a prior window. To "
|
||||
"scroll forward pass the last window message's id; to scroll "
|
||||
"backward pass the first."
|
||||
"Scroll shape. Message id to center the window on — use "
|
||||
"match_message_id from a discovery result, or any id from a "
|
||||
"prior window."
|
||||
),
|
||||
},
|
||||
"window": {
|
||||
|
||||
Reference in New Issue
Block a user