/** * LangChain tool wrapper for Nevermined payment protection using the x402 protocol. * * Wraps a LangChain.js tool implementation function to: * * 1. Extract the x402 payment token from `config.configurable.payment_token` * 2. Verify the subscriber has sufficient credits * 3. Execute the wrapped tool function * 4. Settle (burn) credits after successful execution * * Payment errors throw `PaymentRequiredError` so LangChain agents can catch and * surface them to the user. The error carries the full `X402PaymentRequired` * object for programmatic token acquisition. * * The `credits` option accepts two forms: * - **Static number**: `credits: 1` — always charges 1 credit * - **Function**: `credits: (ctx) => Math.max(1, Math.floor(ctx.result.length / 100))` — dynamic * * When `credits` is a function, it receives `{ args, result }` after tool execution. * * @example * ```typescript * import { tool } from '@langchain/core/tools' * import { z } from 'zod' * import { Payments } from '@nevermined-io/payments' * import { requiresPayment } from '@nevermined-io/payments/langchain' * * const payments = Payments.getInstance({ nvmApiKey: '...', environment: 'testing' }) * * const searchData = tool( * requiresPayment( * (args) => `Results for ${args.query}`, * { payments, planId: PLAN_ID, credits: 1 } * ), * { name: 'search_data', description: 'Search for data', schema: z.object({ query: z.string() }) } * ) * * // Invoke with payment token * const result = await searchData.invoke( * { query: 'AI trends' }, * { configurable: { payment_token: accessToken } } * ) * ``` */ import type { Payments } from '../../payments.js'; import { type X402PaymentRequired, type SettlePermissionsResult } from '../facilitator-api.js'; /** * Context passed to a dynamic credits function after tool execution. */ export interface CreditsContext { /** The tool's input arguments */ args: Record; /** The tool's return value */ result: unknown; } /** * Credits can be a static number or a function that receives * `{ args, result }` and returns the number of credits to charge. */ export type CreditsCallable = (ctx: CreditsContext) => number; /** * Options for the `requiresPayment` wrapper. */ export interface RequiresPaymentOptions { /** The Payments instance (with payments.facilitator) */ payments: Payments; /** Single plan ID to accept */ planId: string; /** * Number of credits to charge, or a function for dynamic pricing (default: 1). * * This value is sent as `maxAmount` to the facilitator. The amount actually * redeemed depends on the plan's server-side credit configuration: * * - **Fixed plans** (`plan.credits.minAmount === plan.credits.maxAmount`) * always burn `plan.credits.maxAmount` — this value is then effectively a * no-op (see nevermined-io/nvm-monorepo#1568). * - **Range plans** clamp this value into * `[plan.credits.minAmount, plan.credits.maxAmount]`. */ credits?: number | CreditsCallable; /** Optional agent identifier */ agentId?: string; /** Blockchain network in CAIP-2 format (default: 'eip155:84532' for Base Sepolia) */ network?: string; } /** * Thrown when payment verification fails or no token is provided. * * Carries the `X402PaymentRequired` object so callers can inspect * accepted plans and acquire the correct payment token. */ export declare class PaymentRequiredError extends Error { /** The x402 PaymentRequired object for programmatic token acquisition */ paymentRequired: X402PaymentRequired | undefined; constructor(message: string, paymentRequired?: X402PaymentRequired); } /** * Payment context stored in `config.configurable.payment_context` after verification. */ export interface PaymentContext { /** * Abbreviated, non-functional reference to the x402 access token — the SAME * redacted form surfaced as `nvm.payment_token` (``, or a * `…(short)` marker for a too-short token). The **full token is deliberately * not persisted here**: this object is written into * `config.configurable.payment_context`, and tracing frameworks (e.g. * LangChain) can capture `config.configurable` into span metadata, so storing * the raw credential would let it ride into any traced run opened during or * after the tool body. Settlement uses the token read from * `config.configurable.payment_token`, never this field. */ token: string; /** The payment required object */ paymentRequired: X402PaymentRequired; /** Number of credits to settle */ creditsToSettle: number; /** Whether verification was successful */ verified: boolean; /** Agent request ID for observability tracking */ agentRequestId?: string; /** Agent request context for observability */ agentRequest?: unknown; } /** * Return the most recent settlement receipt produced by {@link requiresPayment}. * * Use this after invoking a LangChain/LangGraph runnable whose tool is wrapped * with {@link requiresPayment} to recover the settlement receipt * (`creditsRedeemed`, `remainingBalance`, `transaction`, `network`, `payer`) * without threading it back through the runnable config (which LangGraph copies * per node, so the in-place write is invisible to the outer scope). * * Returns `undefined` if no settlement has happened yet in this process, or if * the most recent invocation raised before reaching the settle phase. * * @remarks * This accessor reads from a module-level slot. In multi-tenant processes (e.g. * a server handling concurrent settlements), the value reflects whichever * invocation settled most recently — there is no per-call isolation. */ export declare function lastSettlement(): SettlePermissionsResult | undefined; /** * Wraps a LangChain.js tool implementation with x402 payment verification and settlement. * * This is a higher-order function that takes the tool's implementation function and * payment options, returning a new function with the same signature that: * * 1. Extracts the payment token from `config.configurable.payment_token` * 2. Verifies the subscriber has sufficient credits * 3. Calls the original tool function * 4. Settles (burns) credits * 5. Stores `payment_context` and `payment_settlement` in `config.configurable` * * @param fn - The tool implementation function: `(args, config?) => result` * @param options - Payment configuration * @returns Wrapped function with the same signature * * @example Static credits * ```typescript * const searchData = tool( * requiresPayment( * (args) => `Results for ${args.query}`, * { payments, planId: PLAN_ID, credits: 1 } * ), * { name: 'search_data', description: 'Search', schema: z.object({ query: z.string() }) } * ) * ``` * * @example Dynamic credits * ```typescript * const summarize = tool( * requiresPayment( * (args) => `Summary of ${args.text}`, * { * payments, planId: PLAN_ID, * credits: (ctx) => Math.max(1, Math.floor(String(ctx.result).length / 100)), * } * ), * { name: 'summarize', description: 'Summarize text', schema: z.object({ text: z.string() }) } * ) * ``` */ export declare function requiresPayment, TResult>(fn: (args: TArgs, config?: unknown) => TResult | Promise, options: RequiresPaymentOptions): (args: TArgs, config?: unknown) => Promise; //# sourceMappingURL=decorator.d.ts.map