Implement Manticore fully and re-theme

This commit is contained in:
2026-03-11 02:19:08 +00:00
parent da044be68c
commit cbedcd67f6
46 changed files with 3444 additions and 944 deletions

View File

@@ -1,11 +1,33 @@
from __future__ import annotations
from django.db.models import Q
from core.events.behavior import parse_payload
from core.events.manticore import (
get_behavioral_events_for_range,
get_behavioral_latest_states,
)
from core.events.shadow import (
get_shadow_behavioral_events_for_range,
get_shadow_behavioral_latest_states,
)
from core.models import Person, User
from core.models import ContactAvailabilityEvent, ContactAvailabilitySpan, Person, User
from .engine import ensure_fading_state
from .inference import now_ms
def _behavioral_state_from_kind(kind: str) -> tuple[str, float]:
normalized = str(kind or "").strip().lower()
if normalized == "presence_unavailable":
return ("unavailable", 0.95)
if normalized == "composing_abandoned":
return ("fading", 0.8)
if normalized in {
"presence_available",
"message_read",
"message_delivered",
"composing_started",
"composing_stopped",
"message_sent",
}:
return ("available", 0.75)
return ("unknown", 0.5)
def spans_for_range(
@@ -17,43 +39,98 @@ def spans_for_range(
service: str = "",
limit: int = 200,
):
qs = ContactAvailabilitySpan.objects.filter(
user=user,
person=person,
).filter(Q(start_ts__lte=end_ts) & Q(end_ts__gte=start_ts))
if service:
qs = qs.filter(service=str(service).strip().lower())
service_filter = str(service or "").strip().lower()
try:
rows = get_behavioral_events_for_range(
user_id=int(user.id),
person_id=str(person.id),
start_ts=int(start_ts),
end_ts=int(end_ts),
transport=service_filter,
)
except Exception:
rows = []
if not rows:
rows = get_shadow_behavioral_events_for_range(
user=user,
person_id=str(person.id),
start_ts=int(start_ts),
end_ts=int(end_ts),
transport=service_filter,
)
ensure_fading_state(
user=user,
person=person,
person_identifier=None,
service=(str(service or "").strip().lower() or "signal"),
at_ts=now_ms(),
)
spans = []
current = None
for row in list(rows or []):
transport = str(row.get("transport") or "").strip().lower()
if service_filter and transport != service_filter:
continue
ts = int(row.get("ts") or 0)
state, confidence = _behavioral_state_from_kind(str(row.get("kind") or ""))
if current is None or str(current.get("state")) != state:
if current is not None:
spans.append(current)
current = {
"id": 0,
"service": transport or service_filter,
"state": state,
"start_ts": ts,
"end_ts": ts,
"confidence_start": float(confidence),
"confidence_end": float(confidence),
"payload": {
"source": "manticore_behavioral",
"kind": str(row.get("kind") or "").strip().lower(),
"raw_payload": parse_payload(row.get("payload")),
},
}
continue
current["end_ts"] = max(int(current.get("end_ts") or 0), ts)
current["confidence_end"] = float(confidence)
payload = dict(current.get("payload") or {})
payload["kind"] = str(row.get("kind") or "").strip().lower()
current["payload"] = payload
return list(qs.order_by("-end_ts")[: max(1, min(int(limit or 200), 500))])
if current is not None:
spans.append(current)
return list(reversed(spans[: max(1, min(int(limit or 200), 500))]))
def latest_state_for_people(*, user: User, person_ids: list, service: str = "") -> dict:
out = {}
if not person_ids:
return out
qs = ContactAvailabilityEvent.objects.filter(user=user, person_id__in=person_ids)
if service:
qs = qs.filter(service=str(service).strip().lower())
rows = list(qs.order_by("person_id", "-ts", "-id"))
service_filter = str(service or "").strip().lower()
try:
rows = get_behavioral_latest_states(
user_id=int(user.id),
person_ids=[str(value) for value in person_ids],
transport=service_filter,
)
except Exception:
rows = []
if not rows:
rows = get_shadow_behavioral_latest_states(
user=user,
person_ids=[str(value) for value in person_ids],
transport=service_filter,
)
seen = set()
for row in rows:
person_key = str(row.person_id)
if person_key in seen:
for row in list(rows or []):
person_key = str(row.get("person_id") or "").strip()
transport = str(row.get("transport") or "").strip().lower()
if service_filter and transport != service_filter:
continue
if not person_key or person_key in seen:
continue
seen.add(person_key)
state, confidence = _behavioral_state_from_kind(str(row.get("kind") or ""))
out[person_key] = {
"state": str(row.availability_state or "unknown"),
"confidence": float(row.confidence or 0.0),
"service": str(row.service or ""),
"ts": int(row.ts or 0),
"source_kind": str(row.source_kind or ""),
"state": state,
"confidence": float(confidence),
"service": transport or service_filter,
"ts": int(row.get("ts") or 0),
"source_kind": f"behavioral:{str(row.get('kind') or '').strip().lower()}",
}
return out