@blockrun/llm 3.14.3 → 3.15.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.cts CHANGED
@@ -1855,7 +1855,7 @@ declare class VideoClient {
1855
1855
  * Submits an async job, then polls until the video is ready. Typical total
1856
1856
  * wall-time is 60-180s, but upstream status can lag several minutes behind
1857
1857
  * actual completion. If upstream runs past the budget (default 15min),
1858
- * throws without charging — the job stays claimable ~48h via poll_url.
1858
+ * throws with the existing poll URL; check billing before submitting again.
1859
1859
  *
1860
1860
  * @param prompt - Text description of the video
1861
1861
  * @param options - Optional generation parameters
@@ -2657,6 +2657,71 @@ declare class SolanaLLMClient {
2657
2657
  smartChat(prompt: string, options?: SmartChatOptions): Promise<SmartChatResponse>;
2658
2658
  /** Smart full message/tool completion paid on Solana. */
2659
2659
  smartChatCompletion(messages: ChatMessage[], options?: SmartChatCompletionOptions): Promise<SmartChatCompletionResponse>;
2660
+ /**
2661
+ * Stream a Server-Sent Events endpoint, paid on Solana.
2662
+ *
2663
+ * The Solana counterpart to `BlockrunClient.stream`, and the reason it had to
2664
+ * exist: a streaming harness cannot use this client at all without it, so
2665
+ * "BlockRun supports Solana" stopped being true the moment a caller streamed.
2666
+ * `chatCompletion` buffers the whole answer, which is the wrong shape for an
2667
+ * agent loop and for anything that shows tokens as they arrive.
2668
+ *
2669
+ * The handshake is the one the non-streaming paths use — `402`, sign an SPL
2670
+ * TransferChecked authorization locally, replay with `PAYMENT-SIGNATURE` —
2671
+ * with the same verification-phase re-sign on a stale blockhash. What differs
2672
+ * is that the paid response is not read as JSON: it is handed to the SSE
2673
+ * reader with its body untouched.
2674
+ *
2675
+ * A `200` on the first request is returned as-is and settles nothing. That is
2676
+ * the free tier (the gateway answers a `billing_mode: "free"` model without a
2677
+ * 402 at all) and it is also API-key mode, where billing is on the account
2678
+ * rather than on a wallet.
2679
+ *
2680
+ * Yields each `data:` frame parsed as JSON, and stops at `data: [DONE]`.
2681
+ * Malformed frames are skipped rather than thrown — see {@link readSseFrames}.
2682
+ *
2683
+ * @example
2684
+ * for await (const chunk of client.stream<ChatChunk>("/v1/chat/completions", {
2685
+ * model: "deepseek/deepseek-chat",
2686
+ * messages: [{ role: "user", content: "Hi" }],
2687
+ * stream: true,
2688
+ * })) {
2689
+ * process.stdout.write(chunk.choices?.[0]?.delta?.content ?? "");
2690
+ * }
2691
+ *
2692
+ * @param path - endpoint after the API root; a leading `/api` is tolerated.
2693
+ * @param body - JSON request body. Set `stream: true` yourself — this method
2694
+ * does not inject it, because the gateway prices a streaming and a
2695
+ * non-streaming request the same and silently rewriting a caller's body is
2696
+ * how you end up debugging a request you did not send.
2697
+ * @returns each decoded SSE frame, in order.
2698
+ */
2699
+ stream<T = unknown>(path: string, body?: Record<string, unknown>): AsyncGenerator<T, void, undefined>;
2700
+ /**
2701
+ * Get to a streaming response, paying for it if the gateway asks.
2702
+ *
2703
+ * Separate from {@link SolanaLLMClient.stream} because a generator cannot
2704
+ * retry cleanly around a `yield`: the stale-blockhash re-sign has to finish
2705
+ * before the first frame is handed out, and putting the loop here keeps the
2706
+ * payment decision entirely ahead of any output the caller has seen.
2707
+ *
2708
+ * @param url - resolved endpoint URL.
2709
+ * @param requestBody - the serialized body, reused verbatim on the paid retry
2710
+ * so the gateway prices and answers the same request it quoted for.
2711
+ * @returns a response whose body has not been read.
2712
+ */
2713
+ private openPaidStream;
2714
+ /**
2715
+ * Resolve an endpoint path against this client's API root.
2716
+ *
2717
+ * A leading `/api` is stripped for the same reason `BlockrunClient` strips
2718
+ * it: the documented paths are written `/api/v1/…` on the website and
2719
+ * `/v1/…` in this SDK, and a caller who copies one into the other should get
2720
+ * their request rather than a 404.
2721
+ * @param path - endpoint path, with or without a leading slash.
2722
+ * @returns the absolute URL to call.
2723
+ */
2724
+ private buildUrl;
2660
2725
  /** List available models. */
2661
2726
  listModels(): Promise<Model[]>;
2662
2727
  /**
@@ -2777,11 +2842,46 @@ declare class SolanaLLMClient {
2777
2842
  /** True if using sol.blockrun.ai. */
2778
2843
  isSolana(): boolean;
2779
2844
  private requestWithPayment;
2845
+ /**
2846
+ * Turn a `402` into a signed Solana payment payload.
2847
+ *
2848
+ * Extracted because four call sites need it — chat, the raw POST helpers, the
2849
+ * raw GET helper, and {@link SolanaLLMClient.stream} — and it had been
2850
+ * written out three times before this. That mattered more than ordinary
2851
+ * duplication: this is the code that signs a transfer of the caller's USDC,
2852
+ * so three copies meant every fix to it had to be applied three times or
2853
+ * quietly apply to two thirds of the paths.
2854
+ *
2855
+ * @param url - the request being paid for.
2856
+ * @param response - the gateway's `402`, not yet consumed.
2857
+ * @param forceFreshBlockhash - set on a re-sign after a stale-blockhash
2858
+ * rejection, so the retry cannot produce byte-identical transaction bytes.
2859
+ * @param resourceFallback - resource URL to claim when the 402 states none.
2860
+ * @returns the header value to replay with, and what it will settle for.
2861
+ * @throws PaymentError when the 402 carries no usable Solana requirements.
2862
+ */
2863
+ private signPaymentFrom402;
2780
2864
  private handlePaymentAndRetry;
2781
2865
  private requestWithPaymentRaw;
2782
2866
  private handlePaymentAndRetryRaw;
2783
2867
  private getWithPaymentRaw;
2784
2868
  private handleGetPaymentAndRetryRaw;
2869
+ /**
2870
+ * Fail a post-payment response, telling a re-signable rejection from a real one.
2871
+ *
2872
+ * A `402` here is not "pay again": it is the gateway refusing the payment we
2873
+ * just signed. Only a rejection the gateway attributes to the VERIFICATION
2874
+ * phase is safe to re-sign — anything settled, or ambiguous about which
2875
+ * phase it failed in, could already have moved USDC, and re-signing it would
2876
+ * pay twice. {@link isSafeStaleBlockhashResponse} is where that judgement
2877
+ * lives.
2878
+ * @param response - the reply to the paid request.
2879
+ * @throws SafeStaleBlockhashError when the caller should re-sign, PaymentError
2880
+ * when it should not, APIError for any other failure.
2881
+ */
2882
+ private assertPaid;
2883
+ /** Count one settled x402 payment against the session total. */
2884
+ private recordSettlement;
2785
2885
  private fetchWithTimeout;
2786
2886
  }
2787
2887
  /**
package/dist/index.d.ts CHANGED
@@ -1855,7 +1855,7 @@ declare class VideoClient {
1855
1855
  * Submits an async job, then polls until the video is ready. Typical total
1856
1856
  * wall-time is 60-180s, but upstream status can lag several minutes behind
1857
1857
  * actual completion. If upstream runs past the budget (default 15min),
1858
- * throws without charging — the job stays claimable ~48h via poll_url.
1858
+ * throws with the existing poll URL; check billing before submitting again.
1859
1859
  *
1860
1860
  * @param prompt - Text description of the video
1861
1861
  * @param options - Optional generation parameters
@@ -2657,6 +2657,71 @@ declare class SolanaLLMClient {
2657
2657
  smartChat(prompt: string, options?: SmartChatOptions): Promise<SmartChatResponse>;
2658
2658
  /** Smart full message/tool completion paid on Solana. */
2659
2659
  smartChatCompletion(messages: ChatMessage[], options?: SmartChatCompletionOptions): Promise<SmartChatCompletionResponse>;
2660
+ /**
2661
+ * Stream a Server-Sent Events endpoint, paid on Solana.
2662
+ *
2663
+ * The Solana counterpart to `BlockrunClient.stream`, and the reason it had to
2664
+ * exist: a streaming harness cannot use this client at all without it, so
2665
+ * "BlockRun supports Solana" stopped being true the moment a caller streamed.
2666
+ * `chatCompletion` buffers the whole answer, which is the wrong shape for an
2667
+ * agent loop and for anything that shows tokens as they arrive.
2668
+ *
2669
+ * The handshake is the one the non-streaming paths use — `402`, sign an SPL
2670
+ * TransferChecked authorization locally, replay with `PAYMENT-SIGNATURE` —
2671
+ * with the same verification-phase re-sign on a stale blockhash. What differs
2672
+ * is that the paid response is not read as JSON: it is handed to the SSE
2673
+ * reader with its body untouched.
2674
+ *
2675
+ * A `200` on the first request is returned as-is and settles nothing. That is
2676
+ * the free tier (the gateway answers a `billing_mode: "free"` model without a
2677
+ * 402 at all) and it is also API-key mode, where billing is on the account
2678
+ * rather than on a wallet.
2679
+ *
2680
+ * Yields each `data:` frame parsed as JSON, and stops at `data: [DONE]`.
2681
+ * Malformed frames are skipped rather than thrown — see {@link readSseFrames}.
2682
+ *
2683
+ * @example
2684
+ * for await (const chunk of client.stream<ChatChunk>("/v1/chat/completions", {
2685
+ * model: "deepseek/deepseek-chat",
2686
+ * messages: [{ role: "user", content: "Hi" }],
2687
+ * stream: true,
2688
+ * })) {
2689
+ * process.stdout.write(chunk.choices?.[0]?.delta?.content ?? "");
2690
+ * }
2691
+ *
2692
+ * @param path - endpoint after the API root; a leading `/api` is tolerated.
2693
+ * @param body - JSON request body. Set `stream: true` yourself — this method
2694
+ * does not inject it, because the gateway prices a streaming and a
2695
+ * non-streaming request the same and silently rewriting a caller's body is
2696
+ * how you end up debugging a request you did not send.
2697
+ * @returns each decoded SSE frame, in order.
2698
+ */
2699
+ stream<T = unknown>(path: string, body?: Record<string, unknown>): AsyncGenerator<T, void, undefined>;
2700
+ /**
2701
+ * Get to a streaming response, paying for it if the gateway asks.
2702
+ *
2703
+ * Separate from {@link SolanaLLMClient.stream} because a generator cannot
2704
+ * retry cleanly around a `yield`: the stale-blockhash re-sign has to finish
2705
+ * before the first frame is handed out, and putting the loop here keeps the
2706
+ * payment decision entirely ahead of any output the caller has seen.
2707
+ *
2708
+ * @param url - resolved endpoint URL.
2709
+ * @param requestBody - the serialized body, reused verbatim on the paid retry
2710
+ * so the gateway prices and answers the same request it quoted for.
2711
+ * @returns a response whose body has not been read.
2712
+ */
2713
+ private openPaidStream;
2714
+ /**
2715
+ * Resolve an endpoint path against this client's API root.
2716
+ *
2717
+ * A leading `/api` is stripped for the same reason `BlockrunClient` strips
2718
+ * it: the documented paths are written `/api/v1/…` on the website and
2719
+ * `/v1/…` in this SDK, and a caller who copies one into the other should get
2720
+ * their request rather than a 404.
2721
+ * @param path - endpoint path, with or without a leading slash.
2722
+ * @returns the absolute URL to call.
2723
+ */
2724
+ private buildUrl;
2660
2725
  /** List available models. */
2661
2726
  listModels(): Promise<Model[]>;
2662
2727
  /**
@@ -2777,11 +2842,46 @@ declare class SolanaLLMClient {
2777
2842
  /** True if using sol.blockrun.ai. */
2778
2843
  isSolana(): boolean;
2779
2844
  private requestWithPayment;
2845
+ /**
2846
+ * Turn a `402` into a signed Solana payment payload.
2847
+ *
2848
+ * Extracted because four call sites need it — chat, the raw POST helpers, the
2849
+ * raw GET helper, and {@link SolanaLLMClient.stream} — and it had been
2850
+ * written out three times before this. That mattered more than ordinary
2851
+ * duplication: this is the code that signs a transfer of the caller's USDC,
2852
+ * so three copies meant every fix to it had to be applied three times or
2853
+ * quietly apply to two thirds of the paths.
2854
+ *
2855
+ * @param url - the request being paid for.
2856
+ * @param response - the gateway's `402`, not yet consumed.
2857
+ * @param forceFreshBlockhash - set on a re-sign after a stale-blockhash
2858
+ * rejection, so the retry cannot produce byte-identical transaction bytes.
2859
+ * @param resourceFallback - resource URL to claim when the 402 states none.
2860
+ * @returns the header value to replay with, and what it will settle for.
2861
+ * @throws PaymentError when the 402 carries no usable Solana requirements.
2862
+ */
2863
+ private signPaymentFrom402;
2780
2864
  private handlePaymentAndRetry;
2781
2865
  private requestWithPaymentRaw;
2782
2866
  private handlePaymentAndRetryRaw;
2783
2867
  private getWithPaymentRaw;
2784
2868
  private handleGetPaymentAndRetryRaw;
2869
+ /**
2870
+ * Fail a post-payment response, telling a re-signable rejection from a real one.
2871
+ *
2872
+ * A `402` here is not "pay again": it is the gateway refusing the payment we
2873
+ * just signed. Only a rejection the gateway attributes to the VERIFICATION
2874
+ * phase is safe to re-sign — anything settled, or ambiguous about which
2875
+ * phase it failed in, could already have moved USDC, and re-signing it would
2876
+ * pay twice. {@link isSafeStaleBlockhashResponse} is where that judgement
2877
+ * lives.
2878
+ * @param response - the reply to the paid request.
2879
+ * @throws SafeStaleBlockhashError when the caller should re-sign, PaymentError
2880
+ * when it should not, APIError for any other failure.
2881
+ */
2882
+ private assertPaid;
2883
+ /** Count one settled x402 payment against the session total. */
2884
+ private recordSettlement;
2785
2885
  private fetchWithTimeout;
2786
2886
  }
2787
2887
  /**