From e04947a9888fc5f847e873e2a5aa419e22e3704e Mon Sep 17 00:00:00 2001 From: Cameron Pfiffer Date: Tue, 27 Jan 2026 20:21:24 -0800 Subject: [PATCH] Poll responses/reasoning during activity hook for live updates --- data/published_messages.txt | 21 ++++ data/social_graph.json | 221 ++++++++++++++++++++++++++++-------- hooks/livestream.py | 92 ++++++++++++++- 3 files changed, 284 insertions(+), 50 deletions(-) diff --git a/data/published_messages.txt b/data/published_messages.txt index 3dd3d86..145c126 100644 --- a/data/published_messages.txt +++ b/data/published_messages.txt @@ -55,3 +55,24 @@ message-98d3b29c-e26e-42c8-a061-95fba7e22b58 message-b6d70a5f-3d3b-4576-9282-9ddd3baafd53 message-50274ebd-ce89-4e57-9eb7-c35ff9c6cd7d message-50274ebd-ce89-4e57-9eb7-c35ff9c6cd7d +message-6faa51e1-270e-4bab-9f96-e2bd35823d47 +message-4da8570e-cdaa-42b9-a7e6-0e0a47bf6aa8 +message-17ab9560-9748-4aaa-84a5-95f0571a8863 +message-4017a45c-6aa3-4c00-9c68-f5986672e0fe +message-346bae01-442e-43ed-9143-555ed6dc152e +message-346bae01-442e-43ed-9143-555ed6dc152e +message-63d77296-f3b4-47c1-bed5-e91753606c58 +message-a3f4bcc8-81b9-4c57-9920-e8f53b42bfbc +message-99c8270b-cbff-4536-b835-9ac6f062fc5c +message-0f168327-5ade-4832-8e06-cffc363827dc +message-ad64670c-b8ac-4584-b29d-3542e3da50be +message-e9a9a1af-3713-418a-94b7-009eecde689c +message-91f8c61e-3f62-4851-88d1-564719665435 +message-3d0f749d-7249-4a17-abbb-2039f27f9f9b +message-01775865-f54f-4703-98bd-ce10d7a005b3 +message-59e69388-42ff-442a-9171-8e998238ce75 +message-59e69388-42ff-442a-9171-8e998238ce75 +message-8cf83662-7d25-42b3-8591-d5e765aba5ce +message-8cf83662-7d25-42b3-8591-d5e765aba5ce +message-5c761095-9e9b-44a4-beb6-b51a9ab58fe1 +message-0609049d-234c-4455-ac91-8467416d657c diff --git a/data/social_graph.json b/data/social_graph.json index 277762d..49cda90 100644 --- a/data/social_graph.json +++ b/data/social_graph.json @@ -8,7 +8,7 @@ "i_follow", "follows_me" ], - "interactions": 5 + "interactions": 9 }, "taurean.bryant.land": { "did": "did:plc:tft77e5qkblxtneeib4lp3zk", @@ -17,7 +17,7 @@ "relationship": [ "i_follow" ], - "interactions": 3 + "interactions": 5 }, "jowynter.bsky.social": { "did": "did:plc:boia3kqcyo3qnjw5fmqknib4", @@ -27,7 +27,7 @@ "i_follow", "follows_me" ], - "interactions": 20 + "interactions": 29 }, "astral100.bsky.social": { "did": "did:plc:o5662l2bbcljebd6rl7a6rmz", @@ -36,7 +36,7 @@ "relationship": [ "i_follow" ], - "interactions": 6 + "interactions": 8 }, "funferall.bsky.social": { "did": "did:plc:gjqw6pjl2wvndjlmatxpenkz", @@ -46,7 +46,7 @@ "i_follow", "follows_me" ], - "interactions": 10 + "interactions": 14 }, "aglauros.bsky.social": { "did": "did:plc:77y2qmm33qp5h5lisgvxymgk", @@ -56,7 +56,7 @@ "i_follow", "follows_me" ], - "interactions": 6 + "interactions": 9 }, "violettan.bsky.social": { "did": "did:plc:uzlnp6za26cjnnsf3qmfcipu", @@ -113,7 +113,7 @@ "relationship": [ "i_follow" ], - "interactions": 6 + "interactions": 9 }, "herald.comind.network": { "did": "did:plc:uz2snz44gi4zgqdwecavi66r", @@ -131,7 +131,7 @@ "relationship": [ "i_follow" ], - "interactions": 1 + "interactions": 3 }, "cameron.stream": { "did": "did:plc:gfrmhdmjvxn2sjedzboeudef", @@ -141,7 +141,7 @@ "i_follow", "follows_me" ], - "interactions": 9 + "interactions": 14 }, "arianekonzepte.bsky.social": { "did": "did:plc:rzrivltdw4qog74icwtmxoed", @@ -276,7 +276,7 @@ "relationship": [ "follows_me" ], - "interactions": 4 + "interactions": 6 }, "juniperbevensee.bsky.social": { "did": "did:plc:326ht3oy5t7djhni2crrzh34", @@ -519,7 +519,7 @@ "relationship": [ "follows_me" ], - "interactions": 2 + "interactions": 3 }, "mensmachina.com": { "did": "did:plc:rckigwnqsvji73vtwbovp256", @@ -637,9 +637,144 @@ "follows_me" ], "interactions": 0 + }, + "eightbuff.com": { + "did": "did:plc:g2yztfkp5e3kvtraoanmj5p7", + "display_name": "Eight Buffalo Media Group LLC", + "first_seen": "2026-01-28T04:17:49.011030+00:00", + "relationship": [ + "follows_me" + ], + "interactions": 0 + }, + "etok.me": { + "did": "did:plc:x4ghpwpg65bkzpvqnlbfy6vp", + "display_name": "Ethan Davidson", + "first_seen": "2026-01-28T04:17:49.011076+00:00", + "relationship": [ + "follows_me" + ], + "interactions": 0 + }, + "michaelschellhorn.link": { + "did": "did:plc:3567oht23rzdzp27segkpf74", + "display_name": "ekco-thewizard.bsky.social", + "first_seen": "2026-01-28T04:17:49.011094+00:00", + "relationship": [ + "follows_me" + ], + "interactions": 0 } }, "interactions": [ + { + "type": "replied_to", + "handle": "grunk.comind.network", + "did": "did:plc:ogruxay3tt7wycqxnf5lis6s", + "timestamp": "2026-01-27T06:08:27.861282Z" + }, + { + "type": "replied_to", + "handle": "cameron.stream", + "did": "did:plc:gfrmhdmjvxn2sjedzboeudef", + "timestamp": "2026-01-27T06:06:28.671458Z" + }, + { + "type": "replied_to", + "handle": "funferall.bsky.social", + "did": "did:plc:gjqw6pjl2wvndjlmatxpenkz", + "timestamp": "2026-01-27T06:05:38.382072Z" + }, + { + "type": "replied_to", + "handle": "grunk.comind.network", + "did": "did:plc:ogruxay3tt7wycqxnf5lis6s", + "timestamp": "2026-01-27T06:05:38.334378Z" + }, + { + "type": "replied_to", + "handle": "cameron.stream", + "did": "did:plc:gfrmhdmjvxn2sjedzboeudef", + "timestamp": "2026-01-27T06:05:38.285918Z" + }, + { + "type": "replied_to", + "handle": "funferall.bsky.social", + "did": "did:plc:gjqw6pjl2wvndjlmatxpenkz", + "timestamp": "2026-01-27T06:02:13.824461Z" + }, + { + "type": "replied_to", + "handle": "grunk.comind.network", + "did": "did:plc:ogruxay3tt7wycqxnf5lis6s", + "timestamp": "2026-01-27T06:02:13.777853Z" + }, + { + "type": "replied_to", + "handle": "jowynter.bsky.social", + "did": "did:plc:boia3kqcyo3qnjw5fmqknib4", + "timestamp": "2026-01-27T06:02:13.723048Z" + }, + { + "type": "replied_to", + "handle": "astral100.bsky.social", + "did": "did:plc:o5662l2bbcljebd6rl7a6rmz", + "timestamp": "2026-01-27T06:02:13.675326Z" + }, + { + "type": "replied_to", + "handle": "3fz.org", + "did": "did:plc:27ivzcszryxp6mehutodmcxo", + "timestamp": "2026-01-27T05:50:57.057603Z" + }, + { + "type": "replied_to", + "handle": "justingarringer.bsky.social", + "did": "did:plc:epvbq4hm5oiyipp5bdzwebw5", + "timestamp": "2026-01-27T05:50:57.020080Z" + }, + { + "type": "replied_to", + "handle": "jowynter.bsky.social", + "did": "did:plc:boia3kqcyo3qnjw5fmqknib4", + "timestamp": "2026-01-27T05:50:56.973517Z" + }, + { + "type": "replied_to", + "handle": "funferall.bsky.social", + "did": "did:plc:gjqw6pjl2wvndjlmatxpenkz", + "timestamp": "2026-01-27T05:50:56.921913Z" + }, + { + "type": "replied_to", + "handle": "astral100.bsky.social", + "did": "did:plc:o5662l2bbcljebd6rl7a6rmz", + "timestamp": "2026-01-27T05:50:56.878210Z" + }, + { + "type": "replied_to", + "handle": "cameron.stream", + "did": "did:plc:gfrmhdmjvxn2sjedzboeudef", + "timestamp": "2026-01-27T05:50:56.833026Z" + }, + { + "type": "replied_to", + "handle": "void.comind.network", + "did": "did:plc:mxzuau6m53jtdsbqe6f4laov", + "timestamp": "2026-01-28T02:43:05.995061Z" + }, + { + "type": "replied_to", + "handle": "justingarringer.bsky.social", + "did": "did:plc:epvbq4hm5oiyipp5bdzwebw5", + "timestamp": "2026-01-28T02:43:05.944859Z" + }, + { + "type": "replied_to", + "handle": "taurean.bryant.land", + "did": "did:plc:tft77e5qkblxtneeib4lp3zk", + "timestamp": "2026-01-28T02:43:05.898688Z" + }, { "type": "replied_to", "handle": "jowynter.bsky.social", @@ -880,11 +1015,35 @@ "did": "did:plc:o5662l2bbcljebd6rl7a6rmz", "timestamp": "2026-01-27T05:50:56.878210Z" }, + { + "type": "replied_to", + "handle": "void.comind.network", + "did": "did:plc:mxzuau6m53jtdsbqe6f4laov", + "timestamp": "2026-01-28T04:17:37.876205Z" + }, + { + "type": "replied_to", + "handle": "astral100.bsky.social", + "did": "did:plc:o5662l2bbcljebd6rl7a6rmz", + "timestamp": "2026-01-28T04:17:17.085651Z" + }, + { + "type": "replied_to", + "handle": "justingarringer.bsky.social", + "did": "did:plc:epvbq4hm5oiyipp5bdzwebw5", + "timestamp": "2026-01-28T02:56:12.640978Z" + }, + { + "type": "replied_to", + "handle": "justingarringer.bsky.social", + "did": "did:plc:epvbq4hm5oiyipp5bdzwebw5", + "timestamp": "2026-01-28T02:46:10.150011Z" + }, { "type": "replied_to", "handle": "cameron.stream", "did": "did:plc:gfrmhdmjvxn2sjedzboeudef", - "timestamp": "2026-01-27T05:50:56.833026Z" + "timestamp": "2026-01-28T02:45:02.380013Z" }, { "type": "replied_to", @@ -1107,43 +1266,7 @@ "handle": "jowynter.bsky.social", "did": "did:plc:boia3kqcyo3qnjw5fmqknib4", "timestamp": "2026-01-27T06:02:13.723048Z" - }, - { - "type": "replied_to", - "handle": "astral100.bsky.social", - "did": "did:plc:o5662l2bbcljebd6rl7a6rmz", - "timestamp": "2026-01-27T06:02:13.675326Z" - }, - { - "type": "replied_to", - "handle": "3fz.org", - "did": "did:plc:27ivzcszryxp6mehutodmcxo", - "timestamp": "2026-01-27T05:50:57.057603Z" - }, - { - "type": "replied_to", - "handle": "justingarringer.bsky.social", - "did": "did:plc:epvbq4hm5oiyipp5bdzwebw5", - "timestamp": "2026-01-27T05:50:57.020080Z" - }, - { - "type": "replied_to", - "handle": "jowynter.bsky.social", - "did": "did:plc:boia3kqcyo3qnjw5fmqknib4", - "timestamp": "2026-01-27T05:50:56.973517Z" - }, - { - "type": "replied_to", - "handle": "funferall.bsky.social", - "did": "did:plc:gjqw6pjl2wvndjlmatxpenkz", - "timestamp": "2026-01-27T05:50:56.921913Z" - }, - { - "type": "replied_to", - "handle": "astral100.bsky.social", - "did": "did:plc:o5662l2bbcljebd6rl7a6rmz", - "timestamp": "2026-01-27T05:50:56.878210Z" } ], - "updated": "2026-01-28T02:43:39.741608+00:00" + "updated": "2026-01-28T04:17:51.240577+00:00" } \ No newline at end of file diff --git a/hooks/livestream.py b/hooks/livestream.py index e171323..d82ce2b 100755 --- a/hooks/livestream.py +++ b/hooks/livestream.py @@ -14,6 +14,7 @@ import json import os import re from datetime import datetime, timezone +from pathlib import Path import httpx from dotenv import load_dotenv @@ -97,6 +98,92 @@ def post_activity(tool_name: str, summary: str): print(f"Livestreamed: {tool_name}", file=sys.stderr) +def get_recent_messages(limit: int = 20) -> list: + """Fetch recent assistant + reasoning messages from Letta API.""" + api_key = os.environ.get("LETTA_API_KEY") + agent_id = os.environ.get("LETTA_AGENT_ID", "agent-c770d1c8-510e-4414-be36-c9ebd95a7758") + + if not api_key: + return [] + + try: + resp = httpx.get( + f"https://api.letta.com/v1/agents/{agent_id}/messages", + headers={"Authorization": f"Bearer {api_key}"}, + params={"limit": limit}, + timeout=15 + ) + if resp.status_code != 200: + return [] + + messages = resp.json() + result = [] + for msg in messages: + msg_type = msg.get("message_type") + if msg_type == "assistant_message": + content = msg.get("content", "") + if content and len(content) > 10: + result.append({"content": content, "type": msg_type, "id": msg.get("id")}) + elif msg_type == "reasoning_message": + content = msg.get("reasoning", "") + if content and len(content) > 10: + result.append({"content": content, "type": msg_type, "id": msg.get("id")}) + return result + except: + return [] + + +def publish_messages(): + """Publish any new assistant/reasoning messages.""" + published_file = Path(__file__).parent.parent / "data" / "published_messages.txt" + + try: + published_ids = set(published_file.read_text().splitlines()) + except: + published_ids = set() + + messages = get_recent_messages(limit=30) + session = get_session() + if not session: + return + + new_ids = [] + for msg in messages: + msg_id = msg.get("id", "") + if msg_id in published_ids: + continue + + content = msg.get("content", "") + msg_type = msg.get("type", "assistant_message") + if not content: + continue + + # Redact and determine collection + redacted = redact(content)[:500] + if msg_type == "reasoning_message": + collection = "network.comind.reasoning" + else: + collection = "network.comind.response" + + now = datetime.now(timezone.utc).isoformat().replace("+00:00", "Z") + record = {"$type": collection, "content": redacted, "createdAt": now} + + resp = httpx.post( + f"{PDS}/xrpc/com.atproto.repo.createRecord", + headers={"Authorization": f"Bearer {session['accessJwt']}"}, + json={"repo": DID, "collection": collection, "record": record}, + timeout=10 + ) + if resp.status_code == 200: + new_ids.append(msg_id) + print(f"Published to {collection}", file=sys.stderr) + + if new_ids: + with open(published_file, "a") as f: + for mid in new_ids: + f.write(mid + "\n") + + def main(): """Process hook input.""" try: @@ -145,9 +232,12 @@ def main(): # Apply redaction as backup safety summary = redact(summary) - # Post it + # Post activity post_activity(tool_name, summary) + # Also poll and publish any new responses/reasoning + publish_messages() + sys.exit(0) -- 2.51.2