mirror of
https://github.com/andrewyng/openworker.git
synced 2026-09-04 16:42:35 +00:00
OpenWorker: initial import
Imported from andrewyng/aisuite@1b4bbf303e (contents of its platform/ directory, hoisted to the repo root). Development history prior to this commit lives in that repository. Co-authored-by: Devika <devikaverma11@gmail.com>
This commit is contained in:
@@ -0,0 +1,90 @@
|
||||
"""Mention-thread → session map for the Slack mention router (UX-DECISIONS §31).
|
||||
|
||||
When @ocw is tagged in a channel with no subscribed session, the router spawns a
|
||||
coworker session that OWNS that thread and replies into it. This store is the
|
||||
dedupe map: one durable record per thread, keyed by the thread target string
|
||||
(``"slack:C0123:1700….000100"``; relay: ``"slack:T…/C…:ts"``) — byte-identical to
|
||||
what the session passes to ``send_message`` and to the standing-grant target, so
|
||||
one string serves lookup, delivery, and permission.
|
||||
|
||||
The store is the durable source of truth for the thread grant: ``get_engine``
|
||||
re-derives ``permissions.task_rules`` from it on every engine rebuild, so the
|
||||
pre-approved in-thread reply survives server restarts. Deleting the session
|
||||
clears its records (same contract as subscriptions).
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import json
|
||||
import threading
|
||||
from dataclasses import asdict, dataclass
|
||||
from pathlib import Path
|
||||
from typing import Optional
|
||||
|
||||
|
||||
@dataclass
|
||||
class MentionThread:
|
||||
thread_target: str # "platform:chat_id:thread_ts" — the reply/grant target
|
||||
session_id: str
|
||||
channel: str # thread-agnostic "platform:chat_id" (debugging/cleanup)
|
||||
|
||||
|
||||
class MentionSessionStore:
|
||||
def __init__(self, path: Optional[str | Path] = None) -> None:
|
||||
self.path = Path(path) if path else None
|
||||
self._lock = threading.Lock()
|
||||
self._threads: list[MentionThread] = []
|
||||
self._load()
|
||||
|
||||
def _load(self) -> None:
|
||||
if self.path and self.path.is_file():
|
||||
data = json.loads(self.path.read_text(encoding="utf-8"))
|
||||
self._threads = [MentionThread(**raw) for raw in data.get("threads", [])]
|
||||
|
||||
def _save(self) -> None:
|
||||
if not self.path:
|
||||
return
|
||||
self.path.parent.mkdir(parents=True, exist_ok=True)
|
||||
self.path.write_text(
|
||||
json.dumps({"threads": [asdict(t) for t in self._threads]}, indent=2),
|
||||
encoding="utf-8",
|
||||
)
|
||||
|
||||
# -- mutations --------------------------------------------------------------
|
||||
def set(self, thread_target: str, session_id: str, channel: str) -> MentionThread:
|
||||
"""Upsert — a respawn over a deleted session overwrites the old mapping."""
|
||||
with self._lock:
|
||||
for t in self._threads:
|
||||
if t.thread_target == thread_target:
|
||||
t.session_id = session_id
|
||||
t.channel = channel
|
||||
self._save()
|
||||
return t
|
||||
rec = MentionThread(
|
||||
thread_target=thread_target, session_id=session_id, channel=channel
|
||||
)
|
||||
self._threads.append(rec)
|
||||
self._save()
|
||||
return rec
|
||||
|
||||
def remove_session(self, session_id: str) -> None:
|
||||
"""Drop all of a session's thread mappings (called when it is deleted)."""
|
||||
with self._lock:
|
||||
before = len(self._threads)
|
||||
self._threads = [t for t in self._threads if t.session_id != session_id]
|
||||
if len(self._threads) != before:
|
||||
self._save()
|
||||
|
||||
# -- queries ----------------------------------------------------------------
|
||||
def get(self, thread_target: str) -> Optional[str]:
|
||||
for t in self._threads:
|
||||
if t.thread_target == thread_target:
|
||||
return t.session_id
|
||||
return None
|
||||
|
||||
def targets_for(self, session_id: str) -> list[str]:
|
||||
"""Every thread this session owns — the grant re-seed set."""
|
||||
return [t.thread_target for t in self._threads if t.session_id == session_id]
|
||||
|
||||
def all(self) -> list[MentionThread]:
|
||||
return list(self._threads)
|
||||
Reference in New Issue
Block a user