agent402-client 0.8.16 → 0.8.17

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.
Files changed (3) hide show
  1. package/README.md +1 -1
  2. package/index.js +30 -6
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -215,7 +215,7 @@ that runs as one.
215
215
 
216
216
  | Method | What |
217
217
  |---|---|
218
- | `new Agent402({ baseUrl?, fetch?, x402Client?, creditsKey?, cache?, fetchImpl?, maxPerCallUsd?, dailyLimitUsd?, maxPerHostUsd?, maxResponseBytes?, outputValidator?, respondAsync?, asyncTimeoutMs?, onProgress? })` | `fetch` is your x402- or MPP-wrapped fetch for paid tools (optional); `x402Client` is the `@x402/core` client that `fetch` wraps, so the caps are enforced on the payment that is signed (see below); `creditsKey` is a prepaid card-credits key (`a402_...`) used for paid tools when no `fetch` is given; `cache` (default `true`) memoizes deterministic results; the three USD caps set optional spending limits (see below); `maxResponseBytes` (default 32MB, `null` to disable) refuses an oversized response body before it is parsed; `outputValidator` binds a caller-supplied delivery check; `respondAsync` (default `"auto"`), `asyncTimeoutMs` (default 15 minutes) and `onProgress` control slow routes run as jobs (see above) |
218
+ | `new Agent402({ baseUrl?, fetch?, x402Client?, creditsKey?, cache?, fetchImpl?, maxPerCallUsd?, dailyLimitUsd?, maxPerHostUsd?, payNetworks?, maxResponseBytes?, outputValidator?, respondAsync?, asyncTimeoutMs?, onProgress? })` | `fetch` is your x402- or MPP-wrapped fetch for paid tools (optional); `x402Client` is the `@x402/core` client that `fetch` wraps, so the caps are enforced on the payment that is signed (see below); `payNetworks` (for example `["base"]`, the names `withNetworkPreference` takes) tells the caps which chains a pre-wrapped `fetch` without an `x402Client` pays on, so a call is counted at the dearest option on those chains (when none of a 402's options is on them, the dearest of all counts); `creditsKey` is a prepaid card-credits key (`a402_...`) used for paid tools when no `fetch` is given; `cache` (default `true`) memoizes deterministic results; the three USD caps set optional spending limits (see below); `maxResponseBytes` (default 32MB, `null` to disable) refuses an oversized response body before it is parsed; `outputValidator` binds a caller-supplied delivery check; `respondAsync` (default `"auto"`), `asyncTimeoutMs` (default 15 minutes) and `onProgress` control slow routes run as jobs (see above) |
219
219
  | `await a.find(task, { k = 5 })` | Resolve a plain-language task to the best-matching tools on **this host** (route, price, schema, example) |
220
220
  | `await a.route(task, { k?, include?, network? })` | Cross-seller Smart Order Router: rank eligible/routable seller rows from the host's current index (free, read-only; opaque results may include server-reported `executeVia`) |
221
221
  | `await a.findWorkflows(task, { k = 2 })` | Resolve a task to matching multi-tool workflow templates (skill packs) |
package/index.js CHANGED
@@ -30,7 +30,7 @@ export { AsyncJobPendingError } from "./async-job.js";
30
30
  // `User-Agent: agent402-client/<version>` - a standard header, no extra
31
31
  // network calls - so a seller can attribute traffic (and settled payments)
32
32
  // to this SDK. Product token only; nothing about the caller rides along.
33
- const VERSION = "0.8.16";
33
+ const VERSION = "0.8.17";
34
34
  const USER_AGENT = `agent402-client/${VERSION}`;
35
35
  // 32MB: about a hundred times any realistic response from this catalog (the
36
36
  // largest is a base64 image at a few MB), so it cannot break a legitimate
@@ -91,6 +91,9 @@ export class Agent402 {
91
91
  * @param {number} [opts.maxPerHostUsd] hard ceiling on rolling-24h paid spend to one seller host (USD)
92
92
  * @param {object} [opts.x402Client] the @x402/core x402Client your `fetch` wraps: the caps are then
93
93
  * enforced on the payment that is signed (see guardX402Client)
94
+ * @param {string[]} [opts.payNetworks] the chains your pre-wrapped `fetch` pays on (e.g. ["base"], the
95
+ * names withNetworkPreference takes): without an x402Client the
96
+ * caps count the dearest accept on these chains, not on every chain
94
97
  * @param {string} [opts.creditsKey] a prepaid card-credits key (a402_...) already issued (new credits are
95
98
  * not on sale) - pays wallet-only tools when no payFetch is given
96
99
  * @param {number|null} [opts.maxResponseBytes=33554432]
@@ -109,7 +112,7 @@ export class Agent402 {
109
112
  * ({ status, stage, progress, etaSeconds, ... }) while a job runs
110
113
  */
111
114
  constructor({ baseUrl = "https://agent402.tools", fetch: payFetch, cache = true, fetchImpl = undefined, tlsDistrust = true,
112
- maxPerCallUsd = null, dailyLimitUsd = null, maxPerHostUsd = null, creditsKey = null, x402Client = null,
115
+ maxPerCallUsd = null, dailyLimitUsd = null, maxPerHostUsd = null, creditsKey = null, x402Client = null, payNetworks = null,
113
116
  maxResponseBytes = DEFAULT_MAX_RESPONSE_BYTES, outputValidator = null,
114
117
  respondAsync = "auto", asyncTimeoutMs = DEFAULT_ASYNC_TIMEOUT_MS, onProgress = null } = {}) {
115
118
  this.respondAsync = respondAsync;
@@ -155,6 +158,10 @@ export class Agent402 {
155
158
  this._signCtx = new AsyncLocalStorage();
156
159
  this._guarded = false;
157
160
  if (x402Client) this.guardX402Client(x402Client);
161
+ // The chains a pre-wrapped fetch pays on, as CAIP-2 ids (null = unknown).
162
+ this._payNetworks = Array.isArray(payNetworks) && payNetworks.length
163
+ ? new Set(payNetworks.map((n) => String(NETWORK_CAIP2[String(n).trim().toLowerCase()] || String(n).trim()).toLowerCase()))
164
+ : null;
158
165
  // A response-size ceiling, enforced before parsing. See _readJson.
159
166
  this.maxResponseBytes = maxResponseBytes === null ? null : (numOrNull(maxResponseBytes) ?? DEFAULT_MAX_RESPONSE_BYTES);
160
167
  // Buyer-owned delivery policy. The callback stays entirely local and may
@@ -649,8 +656,11 @@ export class Agent402 {
649
656
  * "guarded" (the signing guard holds every signature to the caps, so the
650
657
  * cheapest known accept is what can be paid, and unknown ones are dropped
651
658
  * there), "wallet" (no guard: the wallet may sign any accept, so the dearest
652
- * one counts, and one that cannot be priced is refused here), or "credits"
653
- * (nothing is signed; the dearest known accept counts).
659
+ * one counts, among the chains in `payNetworks` when they are given, and one
660
+ * that cannot be priced is refused here), or "credits" (nothing is signed:
661
+ * the credits gate debits the route's own quote, and no accept is below it,
662
+ * since a chain premium or price floor only raises an accept, so the
663
+ * cheapest known accept counts).
654
664
  * @returns {Promise<number>} the quoted amount, or `listUsd` when there is no readable 402 */
655
665
  async _quotedUsd(send, listUsd, { slug = "", mode = "wallet" } = {}) {
656
666
  if (!this._spendCapsConfigured()) return listUsd;
@@ -658,7 +668,14 @@ export class Agent402 {
658
668
  try {
659
669
  const pre = await send();
660
670
  if (pre?.status !== 402) return listUsd;
661
- q = quoteOf(await challengeAccepts(pre));
671
+ let accepts = await challengeAccepts(pre);
672
+ if (mode === "wallet" && this._payNetworks && Array.isArray(accepts)) {
673
+ const onChains = accepts.filter((a) => this._payNetworks.has(String(a?.network || "").toLowerCase()));
674
+ // No option on the declared chains (or a name that maps to none): the
675
+ // wallet may still sign any of them, so the dearest of all counts.
676
+ if (onChains.length) accepts = onChains;
677
+ }
678
+ q = quoteOf(accepts);
662
679
  } catch (e) {
663
680
  // A redirect is refused here, before anything is reserved or signed.
664
681
  if (e instanceof PaymentRedirectError) throw e;
@@ -671,7 +688,7 @@ export class Agent402 {
671
688
  `refusing to pay for "${slug}" - ${q.max == null ? "no" : "a"} payment option it offers is in an asset this client cannot price, and a capped wallet signs only what it can price${mode === "wallet" ? " (pass your x402Client to guard signing and pay the options it can price)" : ""}`,
672
689
  { limit: "knownAsset", slug, priceUsd: null, unknownOptions: q.unknown });
673
690
  }
674
- const quoted = mode === "guarded" ? q.min : q.max;
691
+ const quoted = mode === "wallet" ? q.max : q.min;
675
692
  // Larger of the two: an understated catalog must not lower the ceiling
676
693
  // the cap is checked against.
677
694
  return Math.max(listUsd, quoted);
@@ -955,8 +972,15 @@ export const NETWORK_CAIP2 = {
955
972
  "base-sepolia": "eip155:84532",
956
973
  robinhood: "eip155:4663",
957
974
  arc: "eip155:5042",
975
+ monad: "eip155:143",
976
+ celo: "eip155:42220",
977
+ avalanche: "eip155:43114",
978
+ sei: "eip155:1329",
979
+ optimism: "eip155:10",
958
980
  solana: "solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp",
959
981
  "solana-devnet": "solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1",
982
+ stellar: "stellar:pubnet",
983
+ algorand: "algorand:wGHE2Pwdvd7S12BL5FaOP20EGYesN73ktiC1qzkkit8=",
960
984
  };
961
985
 
962
986
  export function withNetworkPreference(client, networks) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agent402-client",
3
- "version": "0.8.16",
3
+ "version": "0.8.17",
4
4
  "description": "Agent402 buyer SDK: resolve a task to a tool across 500+ pay-per-call endpoints and call it with payment handled - free via proof-of-work, or over x402 or MPP (a stock mppx fetch works) with a wallet you keep; the buy side of Agentic Finance. Caching, idempotent retries (Idempotency-Key), non-custodial, zero dependencies.",
5
5
  "type": "module",
6
6
  "main": "index.js",