From a4a5c66cc866795fb234d02a44fe902a148c0096 Mon Sep 17 00:00:00 2001 From: Cameron Pfiffer Date: Wed, 25 Mar 2026 11:35:46 -0700 Subject: [PATCH] fix: Correct Semble card schema to match network.cosmik.card lexicon MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The previous schema was missing required fields: - Added "type" field (required: "URL" or "NOTE") - Fixed content structure: metadata goes inside content - Removed invalid "postContent" type - Semble only supports urlContent and noteContent - Added provenance field to track source posts For posts with URLs: creates URL card with bsky.app link For posts without URLs: creates NOTE card with post text Tested with correct schema - card created successfully. 👾 Generated with [Letta Code](https://letta.com) Co-Authored-By: Letta Code --- tools/semble-researcher.py | 30 +++++++++++++++++++----------- 1 file changed, 19 insertions(+), 11 deletions(-) diff --git a/tools/semble-researcher.py b/tools/semble-researcher.py index 2685cca..5ce9f7e 100644 --- a/tools/semble-researcher.py +++ b/tools/semble-researcher.py @@ -75,20 +75,24 @@ class SembleResearcher: # Extract URLs from post urls = re.findall(r'https?://[^\s]+', text) - # Create card content if urls: - # Use first URL as the card content + # URL card - matches Semble schema content = { "$type": "network.cosmik.card#urlContent", - "url": urls[0] + "url": urls[0], + "metadata": { + "title": title or text[:80] + "..." if len(text) > 80 else text, + "description": f"Found by semble-researcher. Author: {author}", + } } + card_type = "URL" else: - # Use the post itself as content + # Note card - use post text content = { - "$type": "network.cosmik.card#postContent", - "uri": post_uri, - "cid": post_cid + "$type": "network.cosmik.card#noteContent", + "text": text } + card_type = "NOTE" # Generate title from text if not title: @@ -96,14 +100,18 @@ class SembleResearcher: record = { "$type": "network.cosmik.card", + "type": card_type, # REQUIRED field "content": content, - "metadata": { - "title": title.replace("\n", " "), - "description": f"Found by semble-researcher. Author: {author}", - }, "createdAt": datetime.now(timezone.utc).isoformat(), } + # Add provenance to track the source post + if post_uri and post_cid: + record["provenance"] = { + "$type": "network.cosmik.defs#provenance", + "via": {"uri": post_uri, "cid": post_cid} + } + resp = httpx.post( f"{PDS}/xrpc/com.atproto.repo.createRecord", headers={"Authorization": f"Bearer {self.token}"}, -- 2.51.2