UNPKG

libaskexperts

Version:

A TypeScript library to create experts based on NIP-174

160 lines (125 loc) 4.32 kB
# libaskexperts - Create Your Own Experts A TypeScript library to create experts based on [NIP-174](https://github.com/nostrband/askexperts/blob/main/NIP-174.md) (AskExperts) protocol. AskExperts is intended to be used by MCP tools as clients to find experts and ask them questions in exchange for a Lightning Network payment. ## Overview This library provides an `Expert` class that encapsulates all the logic of the NIP-174 protocol, handling Nostr events and Lightning payments. It allows you to create your own expert by implementing two callback functions: - `onAsk`: Called when a new ask is received, returns a bid if the expert wants to participate - `onQuestion`: Called when a question is received, returns an answer to the question ## Installation ```bash npm install libaskexperts ``` ## Usage ```typescript import { Expert } from 'libaskexperts'; import { generateSecretKey, getPublicKey } from 'nostr-tools'; import { nwc } from '@getalby/sdk'; // Create a wallet for generating invoices const nwcClient = new nwc.NWCClient({ nostrWalletConnectUrl: "your-nwc-string" }); // Generate expert keypair const expertPrivateKey = generateSecretKey(); const expertPublicKey = getPublicKey(expertPrivateKey); // Create an expert instance const expert = new Expert({ nwcString, expertPrivkey: expertPrivateKey, askRelays: ["wss://relay.nostr.band", "wss://relay.damus.io"], questionRelays: ["wss://relay.nostr.band", "wss://relay.damus.io"], hashtags: ["ai", "programming"], // Listen for asks with these hashtags min_bid_sats: 50, // Ignore asks with max_bid_sats less than 50 onAsk: async (ask) => { // Evaluate the ask and decide whether to bid return { content: "I can help with your programming question!", bid_sats: 100, // Charge 100 sats for an answer }; }, onQuestion: async (ask, bid, question, history) => { // Generate an answer to the question // history contains previous question-answer pairs for followups return { content: "Here's the answer to your question...", followup_sats: 50, // Allow followup questions for 50 sats }; }, bidTimeout: 600, // 10 minutes }); // Start the expert expert.start(); // To stop the expert and clean up resources expert[Symbol.dispose](); ``` ## API ### Expert Class ```typescript class Expert { constructor(params: ExpertParams); start(): void; [Symbol.dispose](): void; } ``` ### ExpertParams Interface ```typescript interface ExpertParams { nwcString: string; expertPrivkey: Uint8Array; askRelays: string[]; questionRelays: string[]; hashtags: string[]; onAsk: (ask: Ask) => Promise<Bid | undefined>; onQuestion: (ask: Ask, bid: Bid, question: Question, history?: QuestionAnswerPair[]) => Promise<Answer>; bidTimeout?: number; min_bid_sats?: number; // Minimum bid amount in satoshis that the expert will accept } ``` ### Ask Interface ```typescript interface Ask { id: string; pubkey: string; content: string; created_at: number; tags: string[][]; hashtags: string[]; // Hashtags parsed from 't' tags max_bid_sats?: number; // Maximum bid amount in satoshis } ``` ### Bid Interface ```typescript interface Bid { content: string; bid_sats: number; tags?: string[][]; } ``` ### Question Interface ```typescript interface Question { id: string; content: string; preimage: string; tags?: string[][]; } ``` ### Answer Interface ```typescript interface Answer { content: string; followup_sats?: number; // Amount to charge for followup questions tags?: string[][]; } ``` ### QuestionAnswerPair Interface ```typescript interface QuestionAnswerPair { question: Question; answer: Answer; } ``` ## Followup Questions The library supports followup questions, allowing clients to ask additional questions after receiving an answer. To enable followup questions: 1. In your `onQuestion` callback, return an `Answer` with the `followup_sats` property set to the amount you want to charge for a followup. 2. The library will automatically generate an invoice and include it in the answer. 3. When a client pays the invoice and asks a followup question, your `onQuestion` callback will be called again with the original ask, bid, the new question, and a history of previous question-answer pairs. ## License MIT