mirror of
https://github.com/langbot-app/LangBot.git
synced 2026-10-24 09:25:21 +08:00
feat: reset bot session context while retaining monitoring history
This commit is contained in:
@@ -0,0 +1,46 @@
|
||||
"""Scoped context reset markers, independent of retained monitoring history."""
|
||||
|
||||
import hashlib
|
||||
import json
|
||||
|
||||
import sqlalchemy as sa
|
||||
|
||||
from ...entity.persistence.runner_state import RunnerState
|
||||
|
||||
HOST_RESET_RUNNER = '__langbot_context_reset__'
|
||||
|
||||
|
||||
def reset_scope(workspace, bot, conversation):
|
||||
return 'host-reset:' + hashlib.sha256(json.dumps([workspace, bot, conversation]).encode()).hexdigest()
|
||||
|
||||
|
||||
async def get_reset_generation(engine, workspace, bot, conversation):
|
||||
if not all((workspace, bot, conversation)):
|
||||
return None
|
||||
async with engine.connect() as connection:
|
||||
value = (
|
||||
await connection.execute(
|
||||
sa.select(RunnerState.value_json).where(
|
||||
RunnerState.scope_key == reset_scope(workspace, bot, conversation),
|
||||
RunnerState.state_key == 'generation',
|
||||
RunnerState.runner_id == HOST_RESET_RUNNER,
|
||||
)
|
||||
)
|
||||
).scalar_one_or_none()
|
||||
return json.loads(value) if value else None
|
||||
|
||||
|
||||
def active_history_condition(transcript):
|
||||
cutoff = (
|
||||
sa.select(sa.func.max(RunnerState.created_at))
|
||||
.where(
|
||||
RunnerState.runner_id == HOST_RESET_RUNNER,
|
||||
RunnerState.state_key == 'generation',
|
||||
RunnerState.workspace_id == transcript.workspace_id,
|
||||
RunnerState.bot_id == transcript.bot_id,
|
||||
RunnerState.conversation_id == transcript.conversation_id,
|
||||
)
|
||||
.correlate(transcript)
|
||||
.scalar_subquery()
|
||||
)
|
||||
return sa.or_(cutoff.is_(None), transcript.created_at > cutoff)
|
||||
@@ -191,7 +191,9 @@ class PersistentStateStore:
|
||||
# Seed external.conversation_id from event.conversation_id if not set
|
||||
if self._check_scope_enabled('conversation', binding) and event.conversation_id:
|
||||
if 'external.conversation_id' not in snapshot['conversation']:
|
||||
snapshot['conversation']['external.conversation_id'] = event.conversation_id
|
||||
from .context_reset import get_reset_generation
|
||||
generation = await get_reset_generation(self._db_engine, event.workspace_id, event.bot_id, event.conversation_id)
|
||||
snapshot['conversation']['external.conversation_id'] = generation or event.conversation_id
|
||||
|
||||
return snapshot
|
||||
|
||||
|
||||
@@ -335,6 +335,8 @@ class TranscriptStore:
|
||||
thread_id: str | None,
|
||||
strict_thread: bool,
|
||||
) -> typing.Any:
|
||||
from .context_reset import active_history_condition
|
||||
query = query.where(active_history_condition(Transcript))
|
||||
if bot_id is not None:
|
||||
query = query.where(Transcript.bot_id == bot_id)
|
||||
if workspace_id is not None:
|
||||
|
||||
Reference in New Issue
Block a user