{
"schema": "rar-change-request/1.0",
"request_id": "req_17281478c9e845cbb478c5554ce0cb60",
"idempotency_key": "req_17281478c9e845cbb478c5554ce0cb60",
"operation": "create",
"resource": {
"kind": "agent",
"id": "@kody-w/thread_tracker_agent"
},
"preconditions": {
"if_none_match": "*"
},
"payload": {
"source": {
"media_type": "text/x-python",
"encoding": "utf-8",
"sha256": "sha256:dcf4d630cab0eaa9a6919e052cb14429416a1607f4e581a397a58430c7f8ad98",
"content": "\"\"\"Thread Tracker \u2014 local append-only topic routing that keeps work from getting lost.\"\"\"\n\n__manifest__ = {\n \"schema\": \"rapp-agent/1.0\",\n \"name\": \"@kody-w/thread_tracker_agent\",\n \"version\": \"1.0.0\",\n \"display_name\": \"Thread Tracker\",\n \"description\": \"Routes remarks into durable local topic threads, lists open work, and parks or closes threads without deleting their history.\",\n \"author\": \"kody-w\",\n \"tags\": [\"threads\", \"notes\", \"routing\", \"append-only\", \"offline\"],\n \"category\": \"productivity\",\n \"quality_tier\": \"community\",\n \"requires_env\": [],\n \"dependencies\": [\"@rapp/basic_agent\"],\n}\n\nfrom collections import Counter\nfrom datetime import datetime, timezone\nimport hashlib\nimport json\nimport os\nfrom pathlib import Path\nimport re\nimport threading\nimport uuid\n\ntry:\n from agents.basic_agent import BasicAgent\nexcept ImportError:\n try:\n from basic_agent import BasicAgent\n except ImportError:\n class BasicAgent:\n def __init__(self, name=None, metadata=None):\n if name is not None:\n self.name = name\n if metadata is not None:\n self.metadata = metadata\n\n def perform(self, **kwargs):\n return \"Not implemented.\"\n\n\n_LOCK = threading.RLock()\n_WORDS = re.compile(r\"[a-z0-9][a-z0-9_-]{1,}\")\n_STOP = {\n \"about\", \"after\", \"again\", \"also\", \"been\", \"being\", \"from\", \"have\",\n \"into\", \"just\", \"more\", \"that\", \"their\", \"then\", \"this\", \"what\", \"when\",\n \"where\", \"which\", \"with\", \"would\", \"your\",\n}\n\n\ndef _store():\n configured = os.environ.get(\"RAPP_THREAD_STORE\")\n if configured:\n return Path(configured).expanduser()\n return Path.home() / \".rapp\" / \"agent_data\" / \"thread_tracker.jsonl\"\n\n\ndef _now():\n return datetime.now(timezone.utc).isoformat(timespec=\"seconds\")\n\n\ndef _terms(text):\n return {\n word for word in _WORDS.findall(text.casefold())\n if word not in _STOP\n }\n\n\ndef _load():\n path = _store()\n if not path.exists():\n return []\n events = []\n previous = \"\"\n with path.open(encoding=\"utf-8\") as handle:\n for number, line in enumerate(handle, 1):\n event = json.loads(line)\n payload = {key: value for key, value in event.items() if key != \"hash\"}\n expected = hashlib.sha256(\n json.dumps(payload, sort_keys=True, separators=(\",\", \":\")).encode()\n ).hexdigest()\n if event.get(\"previous\") != previous or event.get(\"hash\") != expected:\n raise ValueError(f\"thread record is corrupt at line {number}\")\n events.append(event)\n previous = event[\"hash\"]\n return events\n\n\ndef _append(kind, payload):\n with _LOCK:\n events = _load()\n path = _store()\n path.parent.mkdir(mode=0o700, parents=True, exist_ok=True)\n if os.name != \"nt\":\n path.parent.chmod(0o700)\n event = {\n \"utc\": _now(),\n \"kind\": kind,\n \"payload\": payload,\n \"previous\": events[-1][\"hash\"] if events else \"\",\n }\n event[\"hash\"] = hashlib.sha256(\n json.dumps(event, sort_keys=True, separators=(\",\", \":\")).encode()\n ).hexdigest()\n with path.open(\"a\", encoding=\"utf-8\") as handle:\n handle.write(json.dumps(event, sort_keys=True) + \"\\n\")\n if os.name != \"nt\":\n path.chmod(0o600)\n return event\n\n\ndef _threads():\n threads = {}\n for event in _load():\n payload = event[\"payload\"]\n identifier = payload.get(\"thread\")\n if not identifier:\n continue\n item = threads.setdefault(identifier, {\n \"thread\": identifier,\n \"topic\": \"\",\n \"notes\": [],\n \"state\": \"open\",\n \"opened\": event[\"utc\"],\n \"touched\": event[\"utc\"],\n \"terms\": set(),\n })\n item[\"touched\"] = event[\"utc\"]\n if event[\"kind\"] == \"thread.opened\":\n item[\"topic\"] = payload[\"topic\"]\n item[\"terms\"].update(payload.get(\"terms\", []))\n elif event[\"kind\"] == \"thread.note\":\n item[\"notes\"].append(payload[\"note\"])\n item[\"terms\"].update(payload.get(\"terms\", []))\n elif event[\"kind\"] == \"thread.closed\":\n item[\"state\"] = \"closed\"\n item[\"reason\"] = payload.get(\"reason\", \"\")\n elif event[\"kind\"] == \"thread.parked\":\n item[\"state\"] = \"parked\"\n return threads\n\n\ndef _best_match(terms, threads, floor=2):\n candidates = []\n for item in threads.values():\n if item[\"state\"] == \"closed\":\n continue\n score = len(terms & item[\"terms\"])\n candidates.append((score, item[\"touched\"], item[\"thread\"], item))\n if not candidates:\n return None, 0\n score, _, _, item = max(candidates)\n return (item, score) if score >= floor else (None, score)\n\n\nclass ThreadTrackerAgent(BasicAgent):\n def __init__(self):\n self.name = \"ThreadTracker\"\n self.metadata = {\n \"name\": self.name,\n \"display_name\": __manifest__[\"display_name\"],\n \"description\": __manifest__[\"description\"],\n \"parameters\": {\n \"type\": \"object\",\n \"properties\": {\n \"action\": {\n \"type\": \"string\",\n \"enum\": [\n \"place\", \"open\", \"list\", \"topics\",\n \"close\", \"park\", \"show\",\n ],\n },\n \"text\": {\"type\": \"string\"},\n \"thread\": {\"type\": \"string\"},\n \"reason\": {\"type\": \"string\"},\n },\n \"required\": [\"action\"],\n },\n }\n super().__init__(self.name, self.metadata)\n\n def perform(self, **kwargs) -> str:\n action = str(kwargs.get(\"action\") or \"list\").strip().lower()\n threads = _threads()\n text = str(kwargs.get(\"text\") or \"\").strip()\n if action in (\"place\", \"open\"):\n if not text:\n return \"Provide a remark or topic.\"\n terms = _terms(text)\n match, score = (None, 0) if action == \"open\" else _best_match(\n terms, threads\n )\n if match:\n _append(\"thread.note\", {\n \"thread\": match[\"thread\"],\n \"note\": text[:1000],\n \"terms\": sorted(terms),\n })\n return (\n f\"Placed on thread {match['thread']} \"\n f\"({score} shared terms): {match['topic'][:100]}\"\n )\n identifier = uuid.uuid4().hex[:10]\n _append(\"thread.opened\", {\n \"thread\": identifier,\n \"topic\": text[:500],\n \"terms\": sorted(terms),\n })\n return f\"Opened thread {identifier}: {text[:120]}\"\n if action in (\"close\", \"park\"):\n identifier = str(kwargs.get(\"thread\") or \"\").strip()\n if identifier not in threads:\n return f\"No thread {identifier}.\"\n _append(\n \"thread.closed\" if action == \"close\" else \"thread.parked\",\n {\n \"thread\": identifier,\n \"reason\": str(kwargs.get(\"reason\") or \"\")[:500],\n },\n )\n return f\"Thread {identifier} {action}d. History was preserved.\"\n if action == \"show\":\n identifier = str(kwargs.get(\"thread\") or \"\").strip()\n item = threads.get(identifier)\n if not item:\n return f\"No thread {identifier}.\"\n safe = {**item, \"terms\": sorted(item[\"terms\"])}\n return json.dumps(safe, indent=2, sort_keys=True)\n if action == \"topics\":\n if not threads:\n return \"Nothing tracked yet.\"\n latest_day = max(item[\"touched\"][:10] for item in threads.values())\n items = [\n item for item in threads.values()\n if item[\"touched\"][:10] == latest_day\n ]\n counts = Counter()\n for item in items:\n counts.update(item[\"terms\"])\n lines = [f\"Covered on {latest_day}:\"]\n lines.extend(\n f\"[{item['state']}] {item['thread']} {item['topic'][:100]}\"\n for item in sorted(items, key=lambda value: value[\"touched\"])\n )\n recurring = [\n term for term, count in counts.most_common(8) if count > 1\n ]\n if recurring:\n lines.append(\"Recurring terms: \" + \", \".join(recurring))\n return \"\\n\".join(lines)\n active = [\n item for item in threads.values() if item[\"state\"] != \"closed\"\n ]\n if not active:\n return \"No open threads.\"\n return \"\\n\".join(\n f\"{item['thread']} [{item['state']}] \"\n f\"{len(item['notes'])} note(s): {item['topic'][:100]}\"\n for item in sorted(active, key=lambda value: value[\"touched\"])\n )\n\n\nif __name__ == \"__main__\":\n print(ThreadTrackerAgent().perform(action=\"list\"))\n"
}
},
"client": {
"name": "rapp_sdk",
"version": "1.1.0"
}
}
{ "schema": "rar-change-request/1.0", "request_id": "req_17281478c9e845cbb478c5554ce0cb60", "idempotency_key": "req_17281478c9e845cbb478c5554ce0cb60", "operation": "create", "resource": { "kind": "agent", "id": "@kody-w/thread_tracker_agent" }, "preconditions": { "if_none_match": "*" }, "payload": { "source": { "media_type": "text/x-python", "encoding": "utf-8", "sha256": "sha256:dcf4d630cab0eaa9a6919e052cb14429416a1607f4e581a397a58430c7f8ad98", "content": "\"\"\"Thread Tracker \u2014 local append-only topic routing that keeps work from getting lost.\"\"\"\n\n__manifest__ = {\n \"schema\": \"rapp-agent/1.0\",\n \"name\": \"@kody-w/thread_tracker_agent\",\n \"version\": \"1.0.0\",\n \"display_name\": \"Thread Tracker\",\n \"description\": \"Routes remarks into durable local topic threads, lists open work, and parks or closes threads without deleting their history.\",\n \"author\": \"kody-w\",\n \"tags\": [\"threads\", \"notes\", \"routing\", \"append-only\", \"offline\"],\n \"category\": \"productivity\",\n \"quality_tier\": \"community\",\n \"requires_env\": [],\n \"dependencies\": [\"@rapp/basic_agent\"],\n}\n\nfrom collections import Counter\nfrom datetime import datetime, timezone\nimport hashlib\nimport json\nimport os\nfrom pathlib import Path\nimport re\nimport threading\nimport uuid\n\ntry:\n from agents.basic_agent import BasicAgent\nexcept ImportError:\n try:\n from basic_agent import BasicAgent\n except ImportError:\n class BasicAgent:\n def __init__(self, name=None, metadata=None):\n if name is not None:\n self.name = name\n if metadata is not None:\n self.metadata = metadata\n\n def perform(self, **kwargs):\n return \"Not implemented.\"\n\n\n_LOCK = threading.RLock()\n_WORDS = re.compile(r\"[a-z0-9][a-z0-9_-]{1,}\")\n_STOP = {\n \"about\", \"after\", \"again\", \"also\", \"been\", \"being\", \"from\", \"have\",\n \"into\", \"just\", \"more\", \"that\", \"their\", \"then\", \"this\", \"what\", \"when\",\n \"where\", \"which\", \"with\", \"would\", \"your\",\n}\n\n\ndef _store():\n configured = os.environ.get(\"RAPP_THREAD_STORE\")\n if configured:\n return Path(configured).expanduser()\n return Path.home() / \".rapp\" / \"agent_data\" / \"thread_tracker.jsonl\"\n\n\ndef _now():\n return datetime.now(timezone.utc).isoformat(timespec=\"seconds\")\n\n\ndef _terms(text):\n return {\n word for word in _WORDS.findall(text.casefold())\n if word not in _STOP\n }\n\n\ndef _load():\n path = _store()\n if not path.exists():\n return []\n events = []\n previous = \"\"\n with path.open(encoding=\"utf-8\") as handle:\n for number, line in enumerate(handle, 1):\n event = json.loads(line)\n payload = {key: value for key, value in event.items() if key != \"hash\"}\n expected = hashlib.sha256(\n json.dumps(payload, sort_keys=True, separators=(\",\", \":\")).encode()\n ).hexdigest()\n if event.get(\"previous\") != previous or event.get(\"hash\") != expected:\n raise ValueError(f\"thread record is corrupt at line {number}\")\n events.append(event)\n previous = event[\"hash\"]\n return events\n\n\ndef _append(kind, payload):\n with _LOCK:\n events = _load()\n path = _store()\n path.parent.mkdir(mode=0o700, parents=True, exist_ok=True)\n if os.name != \"nt\":\n path.parent.chmod(0o700)\n event = {\n \"utc\": _now(),\n \"kind\": kind,\n \"payload\": payload,\n \"previous\": events[-1][\"hash\"] if events else \"\",\n }\n event[\"hash\"] = hashlib.sha256(\n json.dumps(event, sort_keys=True, separators=(\",\", \":\")).encode()\n ).hexdigest()\n with path.open(\"a\", encoding=\"utf-8\") as handle:\n handle.write(json.dumps(event, sort_keys=True) + \"\\n\")\n if os.name != \"nt\":\n path.chmod(0o600)\n return event\n\n\ndef _threads():\n threads = {}\n for event in _load():\n payload = event[\"payload\"]\n identifier = payload.get(\"thread\")\n if not identifier:\n continue\n item = threads.setdefault(identifier, {\n \"thread\": identifier,\n \"topic\": \"\",\n \"notes\": [],\n \"state\": \"open\",\n \"opened\": event[\"utc\"],\n \"touched\": event[\"utc\"],\n \"terms\": set(),\n })\n item[\"touched\"] = event[\"utc\"]\n if event[\"kind\"] == \"thread.opened\":\n item[\"topic\"] = payload[\"topic\"]\n item[\"terms\"].update(payload.get(\"terms\", []))\n elif event[\"kind\"] == \"thread.note\":\n item[\"notes\"].append(payload[\"note\"])\n item[\"terms\"].update(payload.get(\"terms\", []))\n elif event[\"kind\"] == \"thread.closed\":\n item[\"state\"] = \"closed\"\n item[\"reason\"] = payload.get(\"reason\", \"\")\n elif event[\"kind\"] == \"thread.parked\":\n item[\"state\"] = \"parked\"\n return threads\n\n\ndef _best_match(terms, threads, floor=2):\n candidates = []\n for item in threads.values():\n if item[\"state\"] == \"closed\":\n continue\n score = len(terms & item[\"terms\"])\n candidates.append((score, item[\"touched\"], item[\"thread\"], item))\n if not candidates:\n return None, 0\n score, _, _, item = max(candidates)\n return (item, score) if score >= floor else (None, score)\n\n\nclass ThreadTrackerAgent(BasicAgent):\n def __init__(self):\n self.name = \"ThreadTracker\"\n self.metadata = {\n \"name\": self.name,\n \"display_name\": __manifest__[\"display_name\"],\n \"description\": __manifest__[\"description\"],\n \"parameters\": {\n \"type\": \"object\",\n \"properties\": {\n \"action\": {\n \"type\": \"string\",\n \"enum\": [\n \"place\", \"open\", \"list\", \"topics\",\n \"close\", \"park\", \"show\",\n ],\n },\n \"text\": {\"type\": \"string\"},\n \"thread\": {\"type\": \"string\"},\n \"reason\": {\"type\": \"string\"},\n },\n \"required\": [\"action\"],\n },\n }\n super().__init__(self.name, self.metadata)\n\n def perform(self, **kwargs) -> str:\n action = str(kwargs.get(\"action\") or \"list\").strip().lower()\n threads = _threads()\n text = str(kwargs.get(\"text\") or \"\").strip()\n if action in (\"place\", \"open\"):\n if not text:\n return \"Provide a remark or topic.\"\n terms = _terms(text)\n match, score = (None, 0) if action == \"open\" else _best_match(\n terms, threads\n )\n if match:\n _append(\"thread.note\", {\n \"thread\": match[\"thread\"],\n \"note\": text[:1000],\n \"terms\": sorted(terms),\n })\n return (\n f\"Placed on thread {match['thread']} \"\n f\"({score} shared terms): {match['topic'][:100]}\"\n )\n identifier = uuid.uuid4().hex[:10]\n _append(\"thread.opened\", {\n \"thread\": identifier,\n \"topic\": text[:500],\n \"terms\": sorted(terms),\n })\n return f\"Opened thread {identifier}: {text[:120]}\"\n if action in (\"close\", \"park\"):\n identifier = str(kwargs.get(\"thread\") or \"\").strip()\n if identifier not in threads:\n return f\"No thread {identifier}.\"\n _append(\n \"thread.closed\" if action == \"close\" else \"thread.parked\",\n {\n \"thread\": identifier,\n \"reason\": str(kwargs.get(\"reason\") or \"\")[:500],\n },\n )\n return f\"Thread {identifier} {action}d. History was preserved.\"\n if action == \"show\":\n identifier = str(kwargs.get(\"thread\") or \"\").strip()\n item = threads.get(identifier)\n if not item:\n return f\"No thread {identifier}.\"\n safe = {**item, \"terms\": sorted(item[\"terms\"])}\n return json.dumps(safe, indent=2, sort_keys=True)\n if action == \"topics\":\n if not threads:\n return \"Nothing tracked yet.\"\n latest_day = max(item[\"touched\"][:10] for item in threads.values())\n items = [\n item for item in threads.values()\n if item[\"touched\"][:10] == latest_day\n ]\n counts = Counter()\n for item in items:\n counts.update(item[\"terms\"])\n lines = [f\"Covered on {latest_day}:\"]\n lines.extend(\n f\"[{item['state']}] {item['thread']} {item['topic'][:100]}\"\n for item in sorted(items, key=lambda value: value[\"touched\"])\n )\n recurring = [\n term for term, count in counts.most_common(8) if count > 1\n ]\n if recurring:\n lines.append(\"Recurring terms: \" + \", \".join(recurring))\n return \"\\n\".join(lines)\n active = [\n item for item in threads.values() if item[\"state\"] != \"closed\"\n ]\n if not active:\n return \"No open threads.\"\n return \"\\n\".join(\n f\"{item['thread']} [{item['state']}] \"\n f\"{len(item['notes'])} note(s): {item['topic'][:100]}\"\n for item in sorted(active, key=lambda value: value[\"touched\"])\n )\n\n\nif __name__ == \"__main__\":\n print(ThreadTrackerAgent().perform(action=\"list\"))\n" } }, "client": { "name": "rapp_sdk", "version": "1.1.0" } }