feat: add search_room_history tool for deep conversation search
Allows the bot to paginate back up to 500 messages in a room to find specific content, beyond the default 10-message context window. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
70
bot.py
70
bot.py
@@ -311,7 +311,28 @@ WEB_SEARCH_TOOLS = [{
|
||||
},
|
||||
}]
|
||||
|
||||
ALL_TOOLS = IMAGE_GEN_TOOLS + WEB_SEARCH_TOOLS + ATLASSIAN_TOOLS
|
||||
ROOM_TOOLS = [{
|
||||
"type": "function",
|
||||
"function": {
|
||||
"name": "search_room_history",
|
||||
"description": (
|
||||
"Search the current chat room's message history for specific content. "
|
||||
"Use when the user asks about something said earlier in the conversation that is beyond "
|
||||
"the recent messages visible to you, e.g. 'what did I say about X last week', "
|
||||
"'find the message where I mentioned Y', 'what was the first thing I asked today'."
|
||||
),
|
||||
"parameters": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"query": {"type": "string", "description": "Search term or phrase to look for in room messages"},
|
||||
"limit": {"type": "integer", "description": "Max messages to scan (default 200, max 500)", "default": 200},
|
||||
},
|
||||
"required": ["query"],
|
||||
},
|
||||
},
|
||||
}]
|
||||
|
||||
ALL_TOOLS = IMAGE_GEN_TOOLS + WEB_SEARCH_TOOLS + ATLASSIAN_TOOLS + ROOM_TOOLS
|
||||
|
||||
ATLASSIAN_NOT_CONNECTED_MSG = (
|
||||
"Your Atlassian account is not connected. "
|
||||
@@ -2047,6 +2068,12 @@ class Bot:
|
||||
return f"Could not reach {url}. The domain may be misspelled — ask the user to clarify."
|
||||
return result
|
||||
|
||||
# Room history search — no auth needed
|
||||
if tool_name == "search_room_history":
|
||||
return await self._search_room_history(
|
||||
room_id, args.get("query", ""), args.get("limit", 200)
|
||||
)
|
||||
|
||||
# Atlassian tools — need per-user token
|
||||
token = await self.atlassian.get_token(sender) if sender else None
|
||||
if not token:
|
||||
@@ -2080,6 +2107,47 @@ class Bot:
|
||||
else:
|
||||
return f"Unknown tool: {tool_name}"
|
||||
|
||||
async def _search_room_history(self, room_id: str, query: str, limit: int = 200) -> str:
|
||||
"""Search room message history for messages matching a query string."""
|
||||
limit = min(limit, 500)
|
||||
query_lower = query.lower()
|
||||
try:
|
||||
# Paginate through room history
|
||||
matches = []
|
||||
token = self.client.next_batch or ""
|
||||
fetched = 0
|
||||
while fetched < limit:
|
||||
batch_size = min(100, limit - fetched)
|
||||
resp = await self.client.room_messages(
|
||||
room_id, start=token, limit=batch_size
|
||||
)
|
||||
if not hasattr(resp, "chunk") or not resp.chunk:
|
||||
break
|
||||
for evt in resp.chunk:
|
||||
if not hasattr(evt, "body"):
|
||||
continue
|
||||
if query_lower in evt.body.lower():
|
||||
ts = evt.server_timestamp / 1000
|
||||
date_str = time.strftime("%Y-%m-%d %H:%M", time.gmtime(ts))
|
||||
sender_name = evt.sender.split(":")[0].lstrip("@")
|
||||
matches.append(f"[{date_str}] {sender_name}: {evt.body[:500]}")
|
||||
fetched += len(resp.chunk)
|
||||
token = resp.end
|
||||
if not token:
|
||||
break
|
||||
|
||||
if not matches:
|
||||
return f"No messages found matching '{query}' in the last {fetched} messages."
|
||||
# Return newest first (matches are in reverse chronological from pagination)
|
||||
result = f"Found {len(matches)} message(s) matching '{query}' (scanned {fetched} messages):\n\n"
|
||||
result += "\n\n---\n\n".join(matches[:20]) # cap at 20 results
|
||||
if len(matches) > 20:
|
||||
result += f"\n\n... and {len(matches) - 20} more matches."
|
||||
return result
|
||||
except Exception:
|
||||
logger.warning("Room history search failed", exc_info=True)
|
||||
return "Failed to search room history."
|
||||
|
||||
# -- Escalation patterns for model routing --
|
||||
_ESCALATION_KEYWORDS = re.compile(
|
||||
r"\b(debug|architecture|algorithm|regex|sql|refactor|optimize|migration"
|
||||
|
||||
Reference in New Issue
Block a user