Prompt repeatedly during quiet chat

This commit is contained in:
2026-05-12 10:01:48 -05:00
parent 0dc941a9a1
commit c65b51c61c
4 changed files with 66 additions and 4 deletions

View File

@@ -36,6 +36,9 @@ class AgentOrchestrator:
"""Initialize the orchestrator and all modes."""
self.llm_client = LLMClient()
self.loop_interval_seconds = loop_interval_seconds
self.hearthkeeper_prompt_interval = timedelta(
minutes=settings.HEARTHKEEPER_PROMPT_INTERVAL_MINUTES
)
# Initialize modes
self.hearthkeeper = HearthkeeperMode(self.llm_client)
@@ -93,7 +96,10 @@ class AgentOrchestrator:
sessions = await repo.get_active_sessions()
for session in sessions:
recent_messages = await repo.get_recent_messages(session.id, limit=1)
recent_messages = await repo.get_recent_human_messages(
session.id,
limit=1,
)
message_count = await repo.count_messages(session.id)
last_activity_at = (
recent_messages[0].timestamp if recent_messages else session.started_at
@@ -189,7 +195,7 @@ class AgentOrchestrator:
recent_messages = []
async for db_session in get_session():
repo = Repository(db_session)
recent_messages = await repo.get_messages_since(
recent_messages = await repo.get_human_messages_since(
session_id=session_id,
since=datetime.utcnow() - timedelta(minutes=1),
)
@@ -285,19 +291,32 @@ class AgentOrchestrator:
session_id=session_id,
mode="hearthkeeper",
)
session_info["last_hearthkeeper_prompt_at"] = (
datetime.utcnow() - self.hearthkeeper_prompt_interval
)
third_tick = await self._tick_session(session_id)
final_count = await self._count_response_actions(
session_id=session_id,
mode="hearthkeeper",
)
prompts_created = after_count - before_count
prompts_created_after_interval = final_count - before_count
return {
"passed": (
prompts_created == 1
and first_tick is not None
and second_tick is None
and third_tick is not None
and prompts_created_after_interval == 2
),
"session_id": session_id,
"inactive_minutes": inactive_minutes,
"prompts_created": prompts_created,
"prompts_created_after_interval": prompts_created_after_interval,
"first_tick": first_tick,
"second_tick": second_tick,
"third_tick_after_interval": third_tick,
}
async def _count_response_actions(self, session_id: str, mode: str) -> int:
@@ -323,6 +342,9 @@ class AgentOrchestrator:
"""Get background loop configuration and current session count."""
return {
"interval_seconds": self.loop_interval_seconds,
"hearthkeeper_prompt_interval_minutes": int(
self.hearthkeeper_prompt_interval.total_seconds() / 60
),
"active_session_count": len(self.active_sessions),
}
@@ -344,7 +366,7 @@ class AgentOrchestrator:
recent_messages = []
async for db_session in get_session():
repo = Repository(db_session)
recent_messages = await repo.get_messages_since(
recent_messages = await repo.get_human_messages_since(
session_id=session_id,
since=datetime.utcnow() - timedelta(minutes=1),
)
@@ -362,7 +384,13 @@ class AgentOrchestrator:
last_activity_at = self.chat_activity.last_activity_at(session_id)
last_prompt_at = session_info.get("last_hearthkeeper_prompt_at")
if last_prompt_at and last_activity_at and last_prompt_at >= last_activity_at:
if last_activity_at and last_prompt_at and last_activity_at > last_prompt_at:
session_info["last_hearthkeeper_prompt_at"] = None
last_prompt_at = None
if (
last_prompt_at
and datetime.utcnow() - last_prompt_at < self.hearthkeeper_prompt_interval
):
return None
try:

View File

@@ -55,6 +55,7 @@ class Settings(BaseSettings):
# Agent loop
AGENT_LOOP_INTERVAL_SECONDS: float = 60.0
HEARTHKEEPER_PROMPT_INTERVAL_MINUTES: int = 15
# Export
EXPORT_PATH: str = "exports"

View File

@@ -105,6 +105,22 @@ class Repository:
result = await self.session.execute(stmt)
return list(result.scalars().all())
async def get_recent_human_messages(
self, session_id: str, limit: int = 50
) -> list[ChatMessage]:
"""Get recent non-bot chat messages from a session."""
stmt = (
select(ChatMessage)
.where(
ChatMessage.session_id == session_id,
ChatMessage.is_bot.is_(False),
)
.order_by(ChatMessage.timestamp.desc())
.limit(limit)
)
result = await self.session.execute(stmt)
return list(result.scalars().all())
async def count_messages(self, session_id: str) -> int:
"""Count chat messages stored for a session."""
stmt = select(func.count()).select_from(ChatMessage).where(
@@ -128,6 +144,22 @@ class Repository:
result = await self.session.execute(stmt)
return list(result.scalars().all())
async def get_human_messages_since(
self, session_id: str, since: datetime
) -> list[ChatMessage]:
"""Get non-bot messages recorded since a specific timestamp."""
stmt = (
select(ChatMessage)
.where(
ChatMessage.session_id == session_id,
ChatMessage.is_bot.is_(False),
ChatMessage.timestamp >= since,
)
.order_by(ChatMessage.timestamp.desc())
)
result = await self.session.execute(stmt)
return list(result.scalars().all())
# Agent Action operations
async def record_action(

View File

@@ -43,6 +43,7 @@ services:
LLM_API_KEY: ${LLM_API_KEY:-}
LLM_MODEL: ${LLM_MODEL:-gpt-3.5-turbo}
AGENT_LOOP_INTERVAL_SECONDS: ${AGENT_LOOP_INTERVAL_SECONDS:-60}
HEARTHKEEPER_PROMPT_INTERVAL_MINUTES: ${HEARTHKEEPER_PROMPT_INTERVAL_MINUTES:-15}
EXPORT_PATH: /app/exports
volumes:
- ./exports:/app/exports