File size: 1,968 Bytes
0366d65
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
"""Assemble a conversation thread from individual messages.

Used by both the ``/agent`` endpoint (join a posted ``messages[]`` into a thread)
and autonomous mode (build a per-chat rolling window from the ingest feed). Pure —
no Gradio / llama / network — so it's trivially unit-testable in stub mode.
"""
from __future__ import annotations

import os

from dateutil import parser as dtparser


def format_thread(messages: list[dict]) -> str:
    """Render messages as ``"sender: text"`` lines, skipping empty bodies."""
    lines = []
    for m in messages:
        text = (m.get("text") or "").strip()
        if not text:
            continue
        sender = (m.get("sender") or "?").strip()
        lines.append(f"{sender}: {text}")
    return "\n".join(lines)


def _ts(value) -> float | None:
    try:
        return dtparser.parse(str(value)).timestamp()
    except (ValueError, TypeError, OverflowError):
        return None


def rolling_thread(
    feed: list[dict],
    chat: str,
    window: int | None = None,
    minutes: int | None = None,
) -> str:
    """Build a thread from the most recent messages of one chat in the feed.

    Keeps the last ``window`` messages for ``chat`` that fall within ``minutes`` of
    the newest one (env-tunable via AUTO_THREAD_WINDOW / AUTO_THREAD_MINUTES).
    """
    window = window or int(os.environ.get("AUTO_THREAD_WINDOW", "20"))
    minutes = minutes or int(os.environ.get("AUTO_THREAD_MINUTES", "720"))

    msgs = [m for m in feed if (m.get("chat") or "") == chat]
    if not msgs:
        return ""
    msgs = msgs[-window:]

    # Drop messages older than `minutes` before the newest (when timestamps parse).
    stamps = [(_ts(m.get("timestamp")), m) for m in msgs]
    newest = max((s for s, _ in stamps if s is not None), default=None)
    if newest is not None:
        cutoff = newest - minutes * 60
        msgs = [m for s, m in stamps if s is None or s >= cutoff]

    return format_thread(msgs)