Something went wrong. Try again.
WIP: A simple cli for daily tangled use cases and AI integration. This is for my personal use right now, but happy if others get mileage fro
Something went wrong. Try again.
3.3 kB · 105 lines
TypeScript
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106import type { TangledApiClient } from '../lib/api-client.js';
/** * Parse an AT-URI into its components * @param uri - AT-URI string (e.g., "at://did:plc:abc/collection/rkey") * @returns Parsed components or null if invalid */export function parseAtUri(uri: string): { did: string; collection: string; rkey?: string;} | null { // AT-URI format: at://did:method:identifier/collection[/rkey] const match = uri.match( /^at:\/\/(did:[a-z]+:[a-zA-Z0-9._:%-]+)\/([a-zA-Z0-9._-]+(?:\.[a-zA-Z0-9._-]+)*)(?:\/([a-zA-Z0-9._-]+))?$/ );
if (!match) { return null; }
const [, did, collection, rkey] = match; return { did, collection, ...(rkey && { rkey }), };}
/** * Resolve a handle to a DID using the AT Protocol identity resolution * @param handle - Handle string (e.g., "mark.bsky.social" or "@mark.bsky.social") * @param client - Authenticated API client * @returns DID string (e.g., "did:plc:abc123") * @throws Error if handle cannot be resolved */export async function resolveHandleToDid( handle: string, client: TangledApiClient): Promise<string> { // Strip leading @ if present const cleanHandle = handle.startsWith('@') ? handle.slice(1) : handle;
try { const response = await client.getAgent().com.atproto.identity.resolveHandle({ handle: cleanHandle, });
if (!response.data.did) { throw new Error(`No DID found for handle: ${cleanHandle}`); }
return response.data.did; } catch (error) { if (error instanceof Error) { throw new Error(`Failed to resolve handle '${cleanHandle}': ${error.message}`); } throw new Error(`Failed to resolve handle '${cleanHandle}': Unknown error`); }}
/** * Build a repository AT-URI from owner and repository name * @param ownerDidOrHandle - DID (e.g., "did:plc:abc") or handle (e.g., "mark.bsky.social") * @param repoName - Repository name * @param client - Authenticated API client * @returns AT-URI string (e.g., "at://did:plc:abc/sh.tangled.repo/3mef23waqwq22") * @throws Error if repository not found */export async function buildRepoAtUri( ownerDidOrHandle: string, repoName: string, client: TangledApiClient): Promise<string> { // Resolve owner to DID const isDid = ownerDidOrHandle.startsWith('did:'); const did = isDid ? ownerDidOrHandle : await resolveHandleToDid(ownerDidOrHandle, client);
try { // Query for sh.tangled.repo records const response = await client.getAgent().com.atproto.repo.listRecords({ repo: did, collection: 'sh.tangled.repo', limit: 100, // Reasonable limit for most users });
// Find the record matching the repo name const repoRecord = response.data.records.find((record) => { const recordData = record.value as { name?: string }; return recordData.name === repoName; });
if (!repoRecord) { throw new Error(`Repository '${repoName}' not found for ${ownerDidOrHandle}`); }
// Return the record's URI (which includes the correct rkey) return repoRecord.uri; } catch (error) { if (error instanceof Error) { throw new Error(`Failed to resolve repository AT-URI: ${error.message}`); } throw new Error('Failed to resolve repository AT-URI: Unknown error'); }}