epimetheus: fix double research message + add decisions/ to KB retrieval

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>
This commit is contained in:
m3taversal 2026-03-23 16:59:23 +00:00
parent c59db5812f
commit c7c71ec9d1
2 changed files with 24 additions and 18 deletions

View file

@ -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)

View file

@ -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():