From c7c71ec9d1e91c77bb722143d1e106934d6d8854 Mon Sep 17 00:00:00 2001 From: m3taversal Date: Mon, 23 Mar 2026 16:59:23 +0000 Subject: [PATCH] epimetheus: fix double research message + add decisions/ to KB retrieval MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 1. handle_research gets silent=True param. RESEARCH: tag triggers use silent mode — archives tweets but posts no follow-up message. Prevents "Queued N tweets" after Opus already responded. 2. KB retrieval now searches decisions/ directory alongside domains/, core/, foundations/. Decision records (Robin Hanson proposal, etc.) are now findable by the bot. Pentagon-Agent: Epimetheus <3D35839A-7722-4740-B93D-51157F7D5E70> --- telegram/bot.py | 41 ++++++++++++++++++++++------------------ telegram/kb_retrieval.py | 1 + 2 files changed, 24 insertions(+), 18 deletions(-) diff --git a/telegram/bot.py b/telegram/bot.py index 5a4a2eb..494173c 100644 --- a/telegram/bot.py +++ b/telegram/bot.py @@ -276,22 +276,28 @@ def _format_conversation_history(chat_id: int, user_id: int) -> str: RESEARCH_PATTERN = re.compile(r'/research(?:@\w+)?\s+(.+)', re.IGNORECASE) -async def handle_research(msg, query: str, user): - """Handle a research request — search X and archive results as sources.""" +async def handle_research(msg, query: str, user, silent: bool = False): + """Handle a research request — search X and archive results as sources. + + If silent=True, archive only — no messages posted. Used when triggered + by RESEARCH: tag after Opus already responded. + """ username = user.username if user else "unknown" - if not check_research_rate_limit(user.id if user else 0): + if not silent and not check_research_rate_limit(user.id if user else 0): remaining = get_research_remaining(user.id if user else 0) await msg.reply_text(f"Research limit reached (3/day). Resets at midnight UTC. {remaining} remaining.") return - await msg.chat.send_action("typing") + if not silent: + await msg.chat.send_action("typing") logger.info("Research: searching X for '%s'", query) tweets = await search_tweets(query, max_results=15, min_engagement=0) logger.info("Research: got %d tweets for '%s'", len(tweets), query) if not tweets: - await msg.reply_text(f"No recent tweets found for '{query}'.") + if not silent: + await msg.reply_text(f"No recent tweets found for '{query}'.") return # Archive all tweets as ONE source file per research query @@ -343,18 +349,17 @@ Submitted by @{username} via Telegram /research command. except Exception as e: logger.warning("Research archive failed: %s", e) - record_research_usage(user.id if user else 0) - remaining = get_research_remaining(user.id if user else 0) - - # Summary of what was found - top_authors = list(set(t["author"] for t in tweets[:5])) - await msg.reply_text( - f"Queued {archived} tweets about '{query}' for extraction. " - f"Top voices: @{', @'.join(top_authors[:3])}. " - f"Results will appear in the KB within ~30 minutes. " - f"({remaining} research requests remaining today.)" - ) - logger.info("Research: @%s queried '%s', archived %d tweets", username, query, archived) + if not silent: + record_research_usage(user.id if user else 0) + remaining = get_research_remaining(user.id if user else 0) + top_authors = list(set(t["author"] for t in tweets[:5])) + await msg.reply_text( + f"Queued {archived} tweets about '{query}' for extraction. " + f"Top voices: @{', @'.join(top_authors[:3])}. " + f"Results will appear in the KB within ~30 minutes. " + f"({remaining} research requests remaining today.)" + ) + logger.info("Research: @%s queried '%s', archived %d tweets (silent=%s)", username, query, archived, silent) # ─── Message Handlers ─────────────────────────────────────────────────── @@ -644,7 +649,7 @@ IMPORTANT: Two special tags you can append at the end of your response (after yo display_response = re.sub(r'\nRESEARCH:\s+.+$', '', display_response, flags=re.MULTILINE).rstrip() if not research_context: # Only fire if Haiku didn't already search for query in research_lines: - asyncio.get_event_loop().create_task(handle_research(msg, query.strip(), user)) + asyncio.get_event_loop().create_task(handle_research(msg, query.strip(), user, silent=True)) logger.info("Auto-research triggered: %s", query[:80]) # Post response (without LEARNING lines) diff --git a/telegram/kb_retrieval.py b/telegram/kb_retrieval.py index 866c862..b4149ae 100644 --- a/telegram/kb_retrieval.py +++ b/telegram/kb_retrieval.py @@ -185,6 +185,7 @@ class KBIndex: self.repo_dir / "domains", self.repo_dir / "core", self.repo_dir / "foundations", + self.repo_dir / "decisions", ] for claim_dir in claim_dirs: if not claim_dir.exists():