@vapi-network/cli 0.9.0 → 0.9.4

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/cli.js CHANGED
@@ -10116,11 +10116,9 @@ var init_call = __esm({
10116
10116
  }
10117
10117
  });
10118
10118
 
10119
- // src/cli.ts
10120
- import { spawn as spawn3 } from "node:child_process";
10121
- import { stat as stat16 } from "node:fs/promises";
10122
- import { join as join28 } from "node:path";
10123
- import { createInterface as createInterface3 } from "node:readline/promises";
10119
+ // src/update-check.ts
10120
+ import { lookup } from "node:dns/promises";
10121
+ import { mkdir as mkdir21, readFile as readFile29, writeFile as writeFile12 } from "node:fs/promises";
10124
10122
 
10125
10123
  // ../../node_modules/.pnpm/zod@4.5.4/node_modules/zod/v4/classic/external.js
10126
10124
  var external_exports = {};
@@ -28988,365 +28986,6 @@ function date4(params) {
28988
28986
  return _coercedDate(ZodDate, params);
28989
28987
  }
28990
28988
 
28991
- // ../core/src/marketplace-contracts.ts
28992
- var MARKETPLACE_DISCOVERY_PROTOCOL = "vapi.marketplace.discovery/1";
28993
- var MARKETPLACE_RANKING_VERSION = "marketplace-ranking-v1";
28994
- var MARKETPLACE_KINDS = ["api", "service_offer", "open_request"];
28995
- var MARKETPLACE_EXECUTION_METHODS = [
28996
- "GET",
28997
- "HEAD",
28998
- "POST",
28999
- "PUT",
29000
- "PATCH",
29001
- "DELETE"
29002
- ];
29003
- var marketplaceExecutionMethodSchema = external_exports.enum(MARKETPLACE_EXECUTION_METHODS);
29004
- var marketplaceKindSchema = external_exports.enum(MARKETPLACE_KINDS);
29005
- var EXECUTION_MODES = ["direct", "gateway"];
29006
- var executionModeSchema = external_exports.enum(EXECUTION_MODES);
29007
- var PROVENANCES = ["indexed", "self_listed", "partner"];
29008
- var provenanceSchema = external_exports.enum(PROVENANCES);
29009
- var FIRST_PARTY_PROVENANCES = ["self_listed", "partner"];
29010
- var firstPartyProvenanceSchema = external_exports.enum(FIRST_PARTY_PROVENANCES);
29011
- var LISTING_GROUPS = ["vapi", "added", "partner", "external"];
29012
- var listingGroupSchema = external_exports.enum(LISTING_GROUPS);
29013
- var listingFeeSchema = external_exports.looseObject({
29014
- bps: external_exports.number().int().min(0),
29015
- label: external_exports.string()
29016
- });
29017
- var LISTING_VERIFICATIONS = ["none", "requested", "verified"];
29018
- var listingVerificationSchema = external_exports.enum(LISTING_VERIFICATIONS);
29019
- var listingVerificationFieldSchema = listingVerificationSchema.default("none").catch("none");
29020
- var listingLivenessSchema = external_exports.looseObject({
29021
- uptime7d: external_exports.number().min(0).max(1),
29022
- latencyP50Ms: external_exports.number().nonnegative().nullable(),
29023
- latencyP95Ms: external_exports.number().nonnegative().nullable(),
29024
- checks7d: external_exports.number().int().nonnegative()
29025
- });
29026
- var listingConformanceSchema = external_exports.looseObject({
29027
- declaredVersion: external_exports.union([external_exports.literal(1), external_exports.literal(2)]).nullable(),
29028
- versionConformant: external_exports.boolean(),
29029
- offerTransport: external_exports.enum(["body", "header", "both"]),
29030
- issues: external_exports.array(external_exports.string())
29031
- });
29032
- var listingIdentitySchema = external_exports.looseObject({
29033
- erc8004Id: external_exports.string().trim().min(1),
29034
- reputation: external_exports.looseObject({
29035
- score: external_exports.number().finite(),
29036
- count: external_exports.number().int().nonnegative()
29037
- }).optional().catch(void 0)
29038
- });
29039
- var listingDisclosureShape = {
29040
- group: listingGroupSchema.optional(),
29041
- fee: listingFeeSchema.optional(),
29042
- verification: listingVerificationFieldSchema,
29043
- liveness: listingLivenessSchema.optional().catch(void 0),
29044
- conformance: listingConformanceSchema.optional().catch(void 0),
29045
- identity: listingIdentitySchema.optional().catch(void 0)
29046
- };
29047
- var marketplaceBadgeCodeSchema = external_exports.enum([
29048
- "live_x402",
29049
- "partner",
29050
- "payout_wallet_confirmed",
29051
- "vapi_verified",
29052
- "external_catalog",
29053
- "approved_vendor"
29054
- ]);
29055
- var marketplaceBadgeSchema = external_exports.looseObject({
29056
- code: marketplaceBadgeCodeSchema,
29057
- label: external_exports.string().trim().min(1).max(80)
29058
- });
29059
- var marketplacePublicFactSchema = external_exports.looseObject({
29060
- label: external_exports.string().trim().min(1).max(80),
29061
- value: external_exports.string().trim().min(1).max(160)
29062
- });
29063
- var marketplaceHrefSchema = external_exports.union([
29064
- external_exports.string().trim().min(1).max(2048).regex(/^\/(?!\/)/),
29065
- external_exports.url().max(2048).regex(/^https:\/\//)
29066
- ]);
29067
- var marketplaceCardSchema = external_exports.looseObject({
29068
- title: external_exports.string().trim().min(1).max(160),
29069
- summary: external_exports.string().trim().min(1).max(1e3),
29070
- byline: external_exports.string().trim().min(1).max(160).optional(),
29071
- bylineHref: marketplaceHrefSchema.optional(),
29072
- badges: external_exports.array(marketplaceBadgeSchema).max(8),
29073
- facts: external_exports.array(marketplacePublicFactSchema).max(12)
29074
- });
29075
- var marketplaceHitBase = {
29076
- ref: external_exports.string().trim().min(1).max(512),
29077
- card: marketplaceCardSchema,
29078
- ...listingDisclosureShape
29079
- };
29080
- var invokeApiActionSchema = external_exports.looseObject({
29081
- type: external_exports.literal("invoke_api"),
29082
- href: marketplaceHrefSchema
29083
- });
29084
- var firstPartyApiMarketplaceHitSchema = external_exports.looseObject({
29085
- ...marketplaceHitBase,
29086
- kind: external_exports.literal("api"),
29087
- provenance: firstPartyProvenanceSchema,
29088
- execution: external_exports.looseObject({
29089
- mode: executionModeSchema
29090
- }),
29091
- action: invokeApiActionSchema
29092
- });
29093
- var mirroredApiMarketplaceHitSchema = external_exports.looseObject({
29094
- ...marketplaceHitBase,
29095
- kind: external_exports.literal("api"),
29096
- provenance: external_exports.literal("indexed"),
29097
- execution: external_exports.looseObject({
29098
- mode: external_exports.literal("direct"),
29099
- url: external_exports.url().max(2048).regex(/^https:\/\/(?![^/?#]*@)/),
29100
- method: marketplaceExecutionMethodSchema.nullable(),
29101
- network: external_exports.string().trim().max(160).regex(/^eip155:[1-9]\d*$/)
29102
- }),
29103
- action: invokeApiActionSchema
29104
- });
29105
- var apiMarketplaceHitSchema = external_exports.discriminatedUnion("provenance", [
29106
- firstPartyApiMarketplaceHitSchema,
29107
- mirroredApiMarketplaceHitSchema
29108
- ]);
29109
- var serviceOfferMarketplaceHitSchema = external_exports.looseObject({
29110
- ...marketplaceHitBase,
29111
- kind: external_exports.literal("service_offer"),
29112
- action: external_exports.looseObject({
29113
- type: external_exports.literal("start_engagement"),
29114
- href: marketplaceHrefSchema
29115
- })
29116
- });
29117
- var openRequestMarketplaceHitSchema = external_exports.looseObject({
29118
- ...marketplaceHitBase,
29119
- kind: external_exports.literal("open_request"),
29120
- action: external_exports.looseObject({
29121
- type: external_exports.literal("propose_to_request"),
29122
- href: marketplaceHrefSchema
29123
- })
29124
- });
29125
- var marketplaceHitSchema = external_exports.union([
29126
- apiMarketplaceHitSchema,
29127
- serviceOfferMarketplaceHitSchema,
29128
- openRequestMarketplaceHitSchema
29129
- ]);
29130
- var marketplaceDiscoveryInputSchema = external_exports.strictObject({
29131
- q: external_exports.string().trim().max(200).optional(),
29132
- kinds: external_exports.array(marketplaceKindSchema).min(1).max(MARKETPLACE_KINDS.length).optional(),
29133
- network: external_exports.string().trim().min(1).max(160).optional(),
29134
- cursor: external_exports.string().trim().min(1).max(4096).optional(),
29135
- limit: external_exports.number().int().min(1).max(50).optional(),
29136
- includeUnverified: external_exports.boolean().optional()
29137
- }).superRefine((input2, context) => {
29138
- if (input2.kinds && new Set(input2.kinds).size !== input2.kinds.length) {
29139
- context.addIssue({
29140
- code: "custom",
29141
- path: ["kinds"],
29142
- message: "Marketplace kinds must be unique"
29143
- });
29144
- }
29145
- });
29146
- function isMirroredHit(hit) {
29147
- return hit.kind === "api" && hit.provenance === "indexed";
29148
- }
29149
- var marketplaceDiscoveryPageSchema = external_exports.looseObject({
29150
- protocol: external_exports.literal(MARKETPLACE_DISCOVERY_PROTOCOL),
29151
- items: external_exports.array(marketplaceHitSchema),
29152
- nextCursor: external_exports.string().min(1).max(4096).nullable(),
29153
- unavailableKinds: external_exports.array(marketplaceKindSchema).max(MARKETPLACE_KINDS.length),
29154
- rankingVersion: external_exports.literal(MARKETPLACE_RANKING_VERSION)
29155
- });
29156
-
29157
- // ../core/src/call-contracts-wire.ts
29158
- var CALLABLE_CATEGORIES = ["ai", "data", "crypto", "compute", "search"];
29159
- var callableCategorySchema = external_exports.enum(CALLABLE_CATEGORIES);
29160
- var DISCOVERY_CATEGORIES = [...CALLABLE_CATEGORIES, "other"];
29161
- var discoveryCategorySchema = external_exports.enum(DISCOVERY_CATEGORIES);
29162
- var CALLABLE_CATEGORY_SET = new Set(CALLABLE_CATEGORIES);
29163
- var serviceTierSchema = external_exports.enum(["listed", "verified", "partner"]);
29164
- var discoveryEndpointSchema = external_exports.looseObject({
29165
- name: external_exports.string(),
29166
- method: external_exports.string(),
29167
- url: external_exports.url(),
29168
- price: external_exports.string(),
29169
- description: external_exports.string(),
29170
- operationId: external_exports.string().trim().min(1).optional(),
29171
- requestContentType: external_exports.string().trim().min(1).optional(),
29172
- requestSchema: external_exports.json().optional(),
29173
- responseContentType: external_exports.string().trim().min(1).optional(),
29174
- pathTemplate: external_exports.string().trim().min(1).optional(),
29175
- pathParameters: external_exports.array(external_exports.string().trim().min(1)).optional(),
29176
- payment: external_exports.looseObject({
29177
- scheme: external_exports.literal("exact"),
29178
- network: external_exports.string().regex(/^eip155:\d+$/),
29179
- asset: external_exports.string().regex(/^0x[0-9a-fA-F]{40}$/),
29180
- payTo: external_exports.string().regex(/^0x[0-9a-fA-F]{40}$/),
29181
- checkedAt: external_exports.iso.datetime()
29182
- }).optional()
29183
- });
29184
- var serviceSummarySchema = external_exports.looseObject({
29185
- id: external_exports.string(),
29186
- name: external_exports.string(),
29187
- description: external_exports.string(),
29188
- category: discoveryCategorySchema,
29189
- tier: serviceTierSchema,
29190
- ...listingDisclosureShape,
29191
- verified: external_exports.boolean(),
29192
- wrapped: external_exports.boolean(),
29193
- price: external_exports.string(),
29194
- networks: external_exports.array(external_exports.string()),
29195
- endpoints: external_exports.array(discoveryEndpointSchema)
29196
- });
29197
- var searchServicesResponseSchema = external_exports.looseObject({
29198
- services: external_exports.array(serviceSummarySchema)
29199
- });
29200
- var discoveryResponseSchema = searchServicesResponseSchema;
29201
-
29202
- // ../core/src/call-contracts.ts
29203
- var DiscoveryCatalogError = class extends Error {
29204
- name = "DiscoveryCatalogError";
29205
- code;
29206
- serviceId;
29207
- constructor(code, message, serviceId) {
29208
- super(message);
29209
- this.code = code;
29210
- this.serviceId = serviceId;
29211
- }
29212
- };
29213
- function parseDiscovery(raw) {
29214
- const parsed = discoveryResponseSchema.safeParse(raw);
29215
- if (!parsed.success) {
29216
- const malformedUrl = parsed.error.issues.find(
29217
- (issue2) => issue2.path.at(-1) === "url" && issue2.path.includes("endpoints")
29218
- );
29219
- if (malformedUrl) {
29220
- const serviceIndex = pathIndexAfter(malformedUrl.path, "services");
29221
- const serviceId = rawServiceId(raw, serviceIndex);
29222
- throw new DiscoveryCatalogError(
29223
- "malformed_url",
29224
- `Service ${JSON.stringify(serviceId ?? "unknown")} has a malformed endpoint URL.`,
29225
- serviceId
29226
- );
29227
- }
29228
- throw new DiscoveryCatalogError("invalid_discovery", "Discovery response is malformed.");
29229
- }
29230
- for (const service of parsed.data.services) {
29231
- buildTargets(service);
29232
- }
29233
- const resolveListing = (serviceId, endpointName) => {
29234
- const service = parsed.data.services.find((candidate) => candidate.id === serviceId);
29235
- if (!service) {
29236
- throw new DiscoveryCatalogError(
29237
- "service_not_found",
29238
- `No payable endpoint found for service ${JSON.stringify(serviceId)}.`,
29239
- serviceId
29240
- );
29241
- }
29242
- return { service, endpoint: resolveTarget(service, endpointName) };
29243
- };
29244
- return {
29245
- services: parsed.data.services,
29246
- resolve: (serviceId, endpointName) => resolveListing(serviceId, endpointName).endpoint,
29247
- resolveListing
29248
- };
29249
- }
29250
- function resolveTarget(service, endpointName) {
29251
- const { targets, targetsByName } = buildTargets(service);
29252
- if (endpointName !== void 0) {
29253
- const selected = targetsByName.get(endpointName.trim());
29254
- if (!selected) {
29255
- throw new DiscoveryCatalogError(
29256
- "endpoint_not_found",
29257
- `Service ${JSON.stringify(service.id)} has no endpoint ${JSON.stringify(endpointName)}. Available endpoints: ${[...targetsByName.keys()].join(", ")}.`,
29258
- service.id
29259
- );
29260
- }
29261
- return { ...selected };
29262
- }
29263
- if (targets.size !== 1) {
29264
- throw new DiscoveryCatalogError(
29265
- "ambiguous_default",
29266
- `Service ${JSON.stringify(service.id)} has ${targets.size} distinct payable endpoints. Choose one with endpoint: ${[...targetsByName.keys()].join(", ")}.`,
29267
- service.id
29268
- );
29269
- }
29270
- return targets.values().next().value;
29271
- }
29272
- function buildTargets(service) {
29273
- if (service.endpoints.length === 0) {
29274
- throw new DiscoveryCatalogError(
29275
- "no_endpoint",
29276
- `Service ${JSON.stringify(service.id)} has no payable endpoint.`,
29277
- service.id
29278
- );
29279
- }
29280
- const namedEndpoints = [...service.endpoints].sort(
29281
- (left, right) => compareNames(left.name.trim(), right.name.trim())
29282
- );
29283
- const names = /* @__PURE__ */ new Set();
29284
- const targets = /* @__PURE__ */ new Map();
29285
- const targetsByName = /* @__PURE__ */ new Map();
29286
- for (const endpoint of namedEndpoints) {
29287
- const name = endpoint.name.trim();
29288
- if (!name) {
29289
- throw new DiscoveryCatalogError(
29290
- "invalid_endpoint_name",
29291
- `Service ${JSON.stringify(service.id)} has a blank endpoint name.`,
29292
- service.id
29293
- );
29294
- }
29295
- if (names.has(name)) {
29296
- throw new DiscoveryCatalogError(
29297
- "duplicate_endpoint_name",
29298
- `Service ${JSON.stringify(service.id)} has duplicate endpoint name ${JSON.stringify(name)}.`,
29299
- service.id
29300
- );
29301
- }
29302
- names.add(name);
29303
- const method = endpoint.method.trim().toUpperCase();
29304
- if (!method) {
29305
- throw new DiscoveryCatalogError(
29306
- "blank_method",
29307
- `Service ${JSON.stringify(service.id)} has a blank endpoint method.`,
29308
- service.id
29309
- );
29310
- }
29311
- const url2 = new URL(endpoint.url);
29312
- if (url2.protocol !== "http:" && url2.protocol !== "https:") {
29313
- throw new DiscoveryCatalogError(
29314
- "malformed_url",
29315
- `Service ${JSON.stringify(service.id)} has a non-HTTP endpoint URL.`,
29316
- service.id
29317
- );
29318
- }
29319
- const transportKey = `${method}\0${endpoint.url}`;
29320
- const normalized = { ...endpoint, name, method };
29321
- targetsByName.set(name, normalized);
29322
- if (!targets.has(transportKey)) targets.set(transportKey, normalized);
29323
- }
29324
- return { targets, targetsByName };
29325
- }
29326
- function compareNames(left, right) {
29327
- return left < right ? -1 : left > right ? 1 : 0;
29328
- }
29329
- function pathIndexAfter(path, key2) {
29330
- const keyIndex = path.indexOf(key2);
29331
- const candidate = path[keyIndex + 1];
29332
- return typeof candidate === "number" ? candidate : void 0;
29333
- }
29334
- function rawServiceId(raw, serviceIndex) {
29335
- if (serviceIndex === void 0 || typeof raw !== "object" || raw === null) {
29336
- return void 0;
29337
- }
29338
- const services = Reflect.get(raw, "services");
29339
- if (!Array.isArray(services)) {
29340
- return void 0;
29341
- }
29342
- const service = services[serviceIndex];
29343
- if (typeof service !== "object" || service === null) {
29344
- return void 0;
29345
- }
29346
- const id2 = Reflect.get(service, "id");
29347
- return typeof id2 === "string" ? id2 : void 0;
29348
- }
29349
-
29350
28989
  // ../../node_modules/.pnpm/viem@2.56.1_typescript@6.0.3_zod@4.5.4/node_modules/viem/_esm/index.js
29351
28990
  init_exports();
29352
28991
 
@@ -39623,6 +39262,7 @@ var ARC_MAINNET_CAIP2 = "eip155:5042";
39623
39262
  var ARC_TESTNET_CAIP2 = "eip155:5042002";
39624
39263
  var SOLANA_MAINNET_CAIP2 = "solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdpKuc147dw2N9d";
39625
39264
  var X402_SOLANA_MAINNET_CAIP2 = "solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp";
39265
+ var SOLANA_DEVNET_CAIP2 = "solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1";
39626
39266
  var SOLANA_MAINNET_USDC = "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v";
39627
39267
  function canonicalIdentity(usdc, eip712Domain) {
39628
39268
  return Object.freeze({
@@ -39666,375 +39306,194 @@ var BROWSER_ENABLED_X402_NETWORK_CONFIG = Object.freeze({
39666
39306
  [ARC_TESTNET_CAIP2]: browserNetwork(arcTestnetUsdc)
39667
39307
  });
39668
39308
 
39669
- // ../core/src/net-guard.ts
39670
- import { lookup as dnsLookup } from "node:dns/promises";
39671
- import { request as httpRequest } from "node:http";
39672
- import { request as httpsRequest } from "node:https";
39673
- import { isIP } from "node:net";
39674
- import { Readable } from "node:stream";
39675
- var defaultLookup = async (hostname3) => {
39676
- const addresses = await dnsLookup(hostname3, { all: true });
39677
- return addresses.map(({ address: address4 }) => address4);
39309
+ // ../core/src/marketplace-contracts.ts
39310
+ var MARKETPLACE_DISCOVERY_PROTOCOL = "vapi.marketplace.discovery/1";
39311
+ var MARKETPLACE_RANKING_VERSION = "marketplace-ranking-v1";
39312
+ var MARKETPLACE_KINDS = ["api", "service_offer", "open_request"];
39313
+ var MARKETPLACE_EXECUTION_METHODS = [
39314
+ "GET",
39315
+ "HEAD",
39316
+ "POST",
39317
+ "PUT",
39318
+ "PATCH",
39319
+ "DELETE"
39320
+ ];
39321
+ var marketplaceExecutionMethodSchema = external_exports.enum(MARKETPLACE_EXECUTION_METHODS);
39322
+ var marketplaceKindSchema = external_exports.enum(MARKETPLACE_KINDS);
39323
+ var EXECUTION_MODES = ["direct", "gateway"];
39324
+ var executionModeSchema = external_exports.enum(EXECUTION_MODES);
39325
+ var PROVENANCES = ["indexed", "self_listed", "partner"];
39326
+ var provenanceSchema = external_exports.enum(PROVENANCES);
39327
+ var FIRST_PARTY_PROVENANCES = ["self_listed", "partner"];
39328
+ var firstPartyProvenanceSchema = external_exports.enum(FIRST_PARTY_PROVENANCES);
39329
+ var LISTING_GROUPS = ["vapi", "added", "partner", "external"];
39330
+ var listingGroupSchema = external_exports.enum(LISTING_GROUPS);
39331
+ var listingFeeSchema = external_exports.looseObject({
39332
+ bps: external_exports.number().int().min(0),
39333
+ label: external_exports.string()
39334
+ });
39335
+ var LISTING_VERIFICATIONS = ["none", "requested", "verified"];
39336
+ var listingVerificationSchema = external_exports.enum(LISTING_VERIFICATIONS);
39337
+ var listingVerificationFieldSchema = listingVerificationSchema.default("none").catch("none");
39338
+ var listingLivenessSchema = external_exports.looseObject({
39339
+ uptime7d: external_exports.number().min(0).max(1),
39340
+ latencyP50Ms: external_exports.number().nonnegative().nullable(),
39341
+ latencyP95Ms: external_exports.number().nonnegative().nullable(),
39342
+ checks7d: external_exports.number().int().nonnegative()
39343
+ });
39344
+ var listingConformanceSchema = external_exports.looseObject({
39345
+ declaredVersion: external_exports.union([external_exports.literal(1), external_exports.literal(2)]).nullable(),
39346
+ versionConformant: external_exports.boolean(),
39347
+ offerTransport: external_exports.enum(["body", "header", "both"]),
39348
+ issues: external_exports.array(external_exports.string())
39349
+ });
39350
+ var listingIdentitySchema = external_exports.looseObject({
39351
+ erc8004Id: external_exports.string().trim().min(1),
39352
+ reputation: external_exports.looseObject({
39353
+ score: external_exports.number().finite(),
39354
+ count: external_exports.number().int().nonnegative()
39355
+ }).optional().catch(void 0)
39356
+ });
39357
+ var listingDisclosureShape = {
39358
+ // Presentation metadata must not make an otherwise executable row vanish
39359
+ // when the registry adds a new group or changes the fee display shape.
39360
+ group: listingGroupSchema.optional().catch(void 0),
39361
+ fee: listingFeeSchema.optional().catch(void 0),
39362
+ verification: listingVerificationFieldSchema,
39363
+ liveness: listingLivenessSchema.optional().catch(void 0),
39364
+ conformance: listingConformanceSchema.optional().catch(void 0),
39365
+ identity: listingIdentitySchema.optional().catch(void 0)
39678
39366
  };
39679
- async function assertPublicUrl(url2, options) {
39680
- if (url2.username || url2.password) {
39681
- throw guardError(url2);
39682
- }
39683
- if (url2.protocol !== "http:" && url2.protocol !== "https:") {
39684
- throw guardError(url2);
39685
- }
39686
- if (options.allowPrivateNetwork) {
39687
- return;
39688
- }
39689
- const hostname3 = normalizeHostname(url2.hostname);
39690
- const lowercaseHostname = hostname3.toLowerCase();
39691
- if (!lowercaseHostname || lowercaseHostname === "localhost" || lowercaseHostname.endsWith(".localhost") || lowercaseHostname.endsWith(".local") || lowercaseHostname.endsWith(".internal")) {
39692
- throw guardError(url2);
39693
- }
39694
- if (isIP(hostname3)) {
39695
- if (isNonPublicAddress(hostname3)) {
39696
- throw guardError(url2);
39697
- }
39698
- return;
39699
- }
39700
- let addresses;
39701
- try {
39702
- addresses = await withTimeout2(
39703
- (options.lookup ?? defaultLookup)(hostname3),
39704
- options.timeoutMs ?? 5e3
39705
- );
39706
- } catch {
39707
- throw guardError(url2);
39708
- }
39709
- if (addresses.length === 0 || addresses.some(isNonPublicAddress)) {
39710
- throw guardError(url2);
39711
- }
39712
- }
39713
- function createPublicFetch(options) {
39714
- const lookupFn = options.lookup ?? defaultLookup;
39715
- return (async (input2, init) => {
39716
- const url2 = new URL(input2 instanceof Request ? input2.url : input2);
39717
- await assertPublicUrl(url2, {
39718
- allowPrivateNetwork: options.allowPrivateNetwork,
39719
- lookup: lookupFn,
39720
- timeoutMs: 5e3
39721
- });
39722
- const normalized = new Request(input2, init);
39723
- const bytes = normalized.body ? Buffer.from(await normalized.arrayBuffer()) : null;
39724
- return await new Promise((resolve2, reject) => {
39725
- const requestOptions2 = {
39726
- method: normalized.method,
39727
- headers: Object.fromEntries(normalized.headers),
39728
- signal: normalized.signal,
39729
- ...options.allowPrivateNetwork ? {} : { lookup: pinnedLookup(lookupFn) }
39730
- };
39731
- const onResponse = (incoming) => {
39732
- try {
39733
- const headers = new Headers();
39734
- for (const [name, value] of Object.entries(incoming.headers)) {
39735
- if (Array.isArray(value)) {
39736
- for (const item of value) headers.append(name, item);
39737
- } else if (value !== void 0) {
39738
- headers.set(name, value);
39739
- }
39740
- }
39741
- const status = incoming.statusCode ?? 500;
39742
- const bodyForbidden = normalized.method === "HEAD" || [204, 205, 304].includes(status);
39743
- if (bodyForbidden) incoming.resume();
39744
- const response = new Response(
39745
- bodyForbidden ? null : Readable.toWeb(incoming),
39746
- { status, statusText: incoming.statusMessage, headers }
39747
- );
39748
- Object.defineProperty(response, "url", { value: url2.toString() });
39749
- resolve2(response);
39750
- } catch (error61) {
39751
- incoming.destroy();
39752
- reject(error61);
39753
- }
39754
- };
39755
- const request = url2.protocol === "https:" ? httpsRequest(url2, requestOptions2, onResponse) : httpRequest(url2, requestOptions2, onResponse);
39756
- request.on("error", reject);
39757
- if (bytes) request.write(bytes);
39758
- request.end();
39759
- });
39760
- });
39761
- }
39762
- function pinnedLookup(lookup) {
39763
- return (hostname3, dnsOptions, callback) => {
39764
- void lookup(normalizeHostname(hostname3)).then((addresses) => {
39765
- if (addresses.length === 0 || addresses.some(isNonPublicAddress)) {
39766
- callback(guardError(new URL(`https://${hostname3}`)), "");
39767
- return;
39768
- }
39769
- const address4 = addresses[0];
39770
- const family = isIP(address4);
39771
- callback(
39772
- null,
39773
- dnsOptions.all ? [{ address: address4, family }] : address4,
39774
- dnsOptions.all ? void 0 : family
39775
- );
39776
- }).catch(
39777
- (error61) => callback(error61 instanceof Error ? error61 : new Error("DNS lookup failed."), "")
39778
- );
39779
- };
39780
- }
39781
- async function withTimeout2(operation, timeoutMs) {
39782
- let timeout;
39783
- try {
39784
- return await Promise.race([
39785
- operation,
39786
- new Promise((_resolve, reject) => {
39787
- timeout = setTimeout(() => reject(new Error("DNS lookup timed out.")), timeoutMs);
39788
- })
39789
- ]);
39790
- } finally {
39791
- if (timeout) clearTimeout(timeout);
39792
- }
39793
- }
39794
- function normalizeHostname(hostname3) {
39795
- const unbracketed = hostname3.startsWith("[") && hostname3.endsWith("]") ? hostname3.slice(1, -1) : hostname3;
39796
- return unbracketed.endsWith(".") ? unbracketed.slice(0, -1) : unbracketed;
39797
- }
39798
- function isNonPublicAddress(address4) {
39799
- const normalized = normalizeHostname(address4);
39800
- const version5 = isIP(normalized);
39801
- if (version5 === 4) {
39802
- return isNonPublicIpv4(parseIpv4(normalized));
39803
- }
39804
- if (version5 === 6) {
39805
- return isNonPublicIpv6(parseIpv6(normalized));
39806
- }
39807
- return true;
39808
- }
39809
- function parseIpv4(address4) {
39810
- const octets = address4.split(".").map(Number);
39811
- return [octets[0], octets[1], octets[2], octets[3]];
39812
- }
39813
- function isNonPublicIpv4([first, second, third]) {
39814
- return first === 0 || first === 10 || first === 100 && second >= 64 && second <= 127 || first === 127 || first === 169 && second === 254 || first === 172 && second >= 16 && second <= 31 || first === 192 && second === 0 && (third === 0 || third === 2) || first === 192 && second === 168 || first === 198 && second >= 18 && second <= 19 || first === 198 && second === 51 && third === 100 || first === 203 && second === 0 && third === 113 || first >= 224;
39815
- }
39816
- function parseIpv6(address4) {
39817
- let normalized = address4.toLowerCase();
39818
- const lastColon = normalized.lastIndexOf(":");
39819
- const dottedTail = normalized.slice(lastColon + 1);
39820
- if (dottedTail.includes(".")) {
39821
- const [first, second, third, fourth] = parseIpv4(dottedTail);
39822
- normalized = `${normalized.slice(0, lastColon + 1)}${(first << 8 | second).toString(16)}:${(third << 8 | fourth).toString(16)}`;
39823
- }
39824
- const halves = normalized.split("::");
39825
- const left = halves[0] ? halves[0].split(":").map(parseHex) : [];
39826
- const right = halves[1] ? halves[1].split(":").map(parseHex) : [];
39827
- const omittedCount = 8 - left.length - right.length;
39828
- return halves.length === 2 ? [...left, ...Array.from({ length: omittedCount }, () => 0), ...right] : left;
39829
- }
39830
- function parseHex(value) {
39831
- return Number.parseInt(value, 16);
39832
- }
39833
- function isNonPublicIpv6(hextets) {
39834
- if (hextets.slice(0, 5).every((hextet) => hextet === 0) && hextets[5] === 65535) {
39835
- const embeddedIpv4 = [
39836
- hextets[6] >> 8,
39837
- hextets[6] & 255,
39838
- hextets[7] >> 8,
39839
- hextets[7] & 255
39840
- ];
39841
- return isNonPublicIpv4(embeddedIpv4);
39842
- }
39843
- if (hextets.slice(0, 6).every((hextet) => hextet === 0)) {
39844
- const compatibleIpv4 = [
39845
- hextets[6] >> 8,
39846
- hextets[6] & 255,
39847
- hextets[7] >> 8,
39848
- hextets[7] & 255
39849
- ];
39850
- if (isNonPublicIpv4(compatibleIpv4)) return true;
39851
- }
39852
- const isUnspecified = hextets.every((hextet) => hextet === 0);
39853
- const isLoopback = hextets.slice(0, 7).every((hextet) => hextet === 0) && hextets[7] === 1;
39854
- const first = hextets[0];
39855
- const isUniqueLocal = first >= 64512 && first <= 65023;
39856
- const isLinkLocal = first >= 65152 && first <= 65215;
39857
- const isSiteLocal = first >= 65216 && first <= 65279;
39858
- const isMulticast = first >= 65280;
39859
- const isDocumentation = first === 8193 && hextets[1] === 3512;
39860
- return isUnspecified || isLoopback || isUniqueLocal || isLinkLocal || isSiteLocal || isMulticast || isDocumentation;
39861
- }
39862
- function guardError(url2) {
39863
- return new Error(
39864
- `URL hostname ${JSON.stringify(url2.hostname)} is not allowed; private or internal destinations require allowPrivateNetwork true in the vAPI config.`
39865
- );
39866
- }
39867
-
39868
- // ../core/src/networks.ts
39869
- var USDC_DECIMALS = 6;
39870
- var DEFAULT_ARC_GAS_HEADROOM_ATOMIC = 50000n;
39871
- var NETWORKS = {
39872
- [BASE_MAINNET_CAIP2]: {
39873
- family: "evm",
39874
- chainId: 8453,
39875
- name: "Base mainnet",
39876
- usdc: CANONICAL_X402_USDC_NETWORKS[BASE_MAINNET_CAIP2].usdc,
39877
- gasToken: "ETH",
39878
- rpcEnv: "BASE_RPC_URL",
39879
- publicRpcUrl: "https://mainnet.base.org",
39880
- explorerUrl: "https://basescan.org"
39881
- },
39882
- [ARC_MAINNET_CAIP2]: {
39883
- family: "evm",
39884
- chainId: 5042,
39885
- name: "Arc mainnet",
39886
- usdc: CANONICAL_X402_USDC_NETWORKS[ARC_MAINNET_CAIP2].usdc,
39887
- gasToken: "USDC",
39888
- rpcEnv: "ARC_RPC_URL",
39889
- publicRpcUrl: "https://rpc.mainnet.arc.io",
39890
- explorerUrl: "https://explorer.arc.io"
39891
- },
39892
- [ARC_TESTNET_CAIP2]: {
39893
- family: "evm",
39894
- chainId: 5042002,
39895
- name: "Arc testnet",
39896
- usdc: CANONICAL_X402_USDC_NETWORKS[ARC_TESTNET_CAIP2].usdc,
39897
- gasToken: "USDC",
39898
- rpcEnv: "ARC_TESTNET_RPC_URL"
39899
- },
39900
- [SOLANA_MAINNET_CAIP2]: {
39901
- family: "svm",
39902
- name: "Solana mainnet",
39903
- usdc: SOLANA_MAINNET_USDC,
39904
- gasToken: "SOL",
39905
- rpcEnv: "SOLANA_RPC_URL",
39906
- publicRpcUrl: "https://api.mainnet-beta.solana.com"
39907
- },
39908
- [X402_SOLANA_MAINNET_CAIP2]: {
39909
- family: "svm",
39910
- name: "Solana mainnet",
39911
- usdc: SOLANA_MAINNET_USDC,
39912
- gasToken: "SOL",
39913
- rpcEnv: "SOLANA_RPC_URL",
39914
- publicRpcUrl: "https://api.mainnet-beta.solana.com"
39915
- }
39367
+ var marketplaceBadgeCodeSchema = external_exports.enum([
39368
+ "live_x402",
39369
+ "mpp",
39370
+ "partner",
39371
+ "payout_wallet_confirmed",
39372
+ "vapi_verified",
39373
+ "external_catalog",
39374
+ "approved_vendor",
39375
+ "unverified"
39376
+ ]);
39377
+ var marketplaceBadgeSchema = external_exports.looseObject({
39378
+ code: marketplaceBadgeCodeSchema,
39379
+ label: external_exports.string().trim().min(1).max(80)
39380
+ });
39381
+ var marketplacePublicFactSchema = external_exports.looseObject({
39382
+ label: external_exports.string().trim().min(1).max(80),
39383
+ value: external_exports.string().trim().min(1).max(160)
39384
+ });
39385
+ var marketplaceHrefSchema = external_exports.union([
39386
+ external_exports.string().trim().min(1).max(2048).regex(/^\/(?!\/)/),
39387
+ external_exports.url().max(2048).regex(/^https:\/\//)
39388
+ ]);
39389
+ var marketplaceCardSchema = external_exports.looseObject({
39390
+ title: external_exports.string().trim().min(1).max(160),
39391
+ summary: external_exports.string().trim().min(1).max(1e3),
39392
+ byline: external_exports.string().trim().min(1).max(160).optional(),
39393
+ bylineHref: marketplaceHrefSchema.optional(),
39394
+ badges: external_exports.preprocess(
39395
+ (badges) => Array.isArray(badges) ? badges.flatMap((badge) => {
39396
+ const parsed = marketplaceBadgeSchema.safeParse(badge);
39397
+ return parsed.success ? [parsed.data] : [];
39398
+ }) : badges,
39399
+ external_exports.array(marketplaceBadgeSchema).max(8)
39400
+ ),
39401
+ facts: external_exports.array(marketplacePublicFactSchema).max(12)
39402
+ });
39403
+ var marketplaceHitBase = {
39404
+ ref: external_exports.string().trim().min(1).max(512),
39405
+ card: marketplaceCardSchema,
39406
+ ...listingDisclosureShape
39916
39407
  };
39917
- function parseEip155ChainId(network) {
39918
- const match = /^eip155:(\d+)$/.exec(network);
39919
- if (!match) {
39920
- throw new Error(`Unsupported network ${network}; expected eip155:<chainId>.`);
39921
- }
39922
- const chainId = Number(match[1]);
39923
- if (!Number.isSafeInteger(chainId) || chainId <= 0) {
39924
- throw new Error(`Invalid EVM chain ID in network ${network}.`);
39925
- }
39926
- return chainId;
39927
- }
39928
- function isSolanaNetwork(network) {
39929
- return network === SOLANA_MAINNET_CAIP2 || network === X402_SOLANA_MAINNET_CAIP2;
39930
- }
39931
- function usesUsdcGas(network) {
39932
- try {
39933
- return getNetworkDefinition(network).gasToken === "USDC";
39934
- } catch {
39935
- return false;
39936
- }
39937
- }
39938
- function explorerTransactionUrl(network, hash5) {
39939
- try {
39940
- const explorerUrl = getNetworkDefinition(network).explorerUrl;
39941
- return explorerUrl ? `${explorerUrl}/tx/${hash5}` : void 0;
39942
- } catch {
39943
- return void 0;
39944
- }
39945
- }
39946
- function explorerAddressUrl(network, address4) {
39947
- try {
39948
- const explorerUrl = getNetworkDefinition(network).explorerUrl;
39949
- return explorerUrl ? `${explorerUrl}/address/${address4}` : void 0;
39950
- } catch {
39951
- return void 0;
39952
- }
39953
- }
39954
- function areSamePaymentNetwork(left, right) {
39955
- return left === right || isSolanaNetwork(left) && isSolanaNetwork(right);
39956
- }
39957
- function isSupportedPaymentNetwork(network) {
39958
- if (isSolanaNetwork(network)) return true;
39959
- try {
39960
- parseEip155ChainId(network);
39961
- return true;
39962
- } catch {
39963
- return false;
39964
- }
39965
- }
39966
- function configuredNetworkFor(networks, network) {
39967
- const configured = networks[network];
39968
- if (configured) return configured;
39969
- if (network === X402_SOLANA_MAINNET_CAIP2) return networks[SOLANA_MAINNET_CAIP2];
39970
- if (network === SOLANA_MAINNET_CAIP2) return networks[X402_SOLANA_MAINNET_CAIP2];
39971
- return void 0;
39972
- }
39973
- function getNetworkDefinition(network) {
39974
- const known = NETWORKS[network];
39975
- if (known) {
39976
- return known;
39977
- }
39978
- const chainId = parseEip155ChainId(network);
39979
- return {
39980
- family: "evm",
39981
- chainId,
39982
- name: network,
39983
- usdc: getAddress("0x0000000000000000000000000000000000000000"),
39984
- gasToken: "ETH",
39985
- rpcEnv: ""
39986
- };
39987
- }
39988
- function requireRpcUrl(network, configured) {
39989
- const definition = getNetworkDefinition(network);
39990
- const envUrl = definition.rpcEnv ? process.env[definition.rpcEnv]?.trim() : void 0;
39991
- const rpcUrl = envUrl || configured.rpcUrl.trim();
39992
- if (rpcUrl) {
39993
- return rpcUrl;
39994
- }
39995
- if (network === ARC_TESTNET_CAIP2) {
39996
- throw new Error(
39997
- "Arc testnet RPC is required. Set ARC_TESTNET_RPC_URL or add rpcUrl for eip155:5042002 in config.json."
39998
- );
39999
- }
40000
- throw new Error(`RPC URL is required for ${network}.`);
40001
- }
40002
- function createChain(network, rpcUrl) {
40003
- const definition = getNetworkDefinition(network);
40004
- if (definition.family !== "evm" || definition.chainId === void 0) {
40005
- throw new Error(`Network ${network} is not an EVM chain.`);
39408
+ var invokeApiActionSchema = external_exports.looseObject({
39409
+ type: external_exports.literal("invoke_api"),
39410
+ href: marketplaceHrefSchema
39411
+ });
39412
+ var firstPartyApiMarketplaceHitSchema = external_exports.looseObject({
39413
+ ...marketplaceHitBase,
39414
+ kind: external_exports.literal("api"),
39415
+ provenance: firstPartyProvenanceSchema,
39416
+ execution: external_exports.looseObject({
39417
+ mode: executionModeSchema
39418
+ }),
39419
+ action: invokeApiActionSchema
39420
+ });
39421
+ var mirroredApiMarketplaceHitSchema = external_exports.looseObject({
39422
+ ...marketplaceHitBase,
39423
+ kind: external_exports.literal("api"),
39424
+ provenance: external_exports.literal("indexed"),
39425
+ execution: external_exports.looseObject({
39426
+ mode: external_exports.literal("direct"),
39427
+ url: external_exports.url().max(2048).regex(/^https:\/\/(?![^/?#]*@)/),
39428
+ method: marketplaceExecutionMethodSchema.nullable(),
39429
+ network: external_exports.string().trim().max(160).transform((network) => {
39430
+ if (network === "solana") return X402_SOLANA_MAINNET_CAIP2;
39431
+ if (network === "solana-devnet") return SOLANA_DEVNET_CAIP2;
39432
+ return network;
39433
+ }).pipe(
39434
+ external_exports.union([
39435
+ external_exports.string().regex(/^[-a-z0-9]{3,8}:[-_a-zA-Z0-9]{1,32}$/),
39436
+ // Persisted mainnet configs also use the full genesis hash.
39437
+ external_exports.literal(SOLANA_MAINNET_CAIP2)
39438
+ ])
39439
+ )
39440
+ }),
39441
+ action: invokeApiActionSchema
39442
+ });
39443
+ var apiMarketplaceHitSchema = external_exports.discriminatedUnion("provenance", [
39444
+ firstPartyApiMarketplaceHitSchema,
39445
+ mirroredApiMarketplaceHitSchema
39446
+ ]);
39447
+ var serviceOfferMarketplaceHitSchema = external_exports.looseObject({
39448
+ ...marketplaceHitBase,
39449
+ kind: external_exports.literal("service_offer"),
39450
+ action: external_exports.looseObject({
39451
+ type: external_exports.literal("start_engagement"),
39452
+ href: marketplaceHrefSchema
39453
+ })
39454
+ });
39455
+ var openRequestMarketplaceHitSchema = external_exports.looseObject({
39456
+ ...marketplaceHitBase,
39457
+ kind: external_exports.literal("open_request"),
39458
+ action: external_exports.looseObject({
39459
+ type: external_exports.literal("propose_to_request"),
39460
+ href: marketplaceHrefSchema
39461
+ })
39462
+ });
39463
+ var marketplaceHitSchema = external_exports.union([
39464
+ apiMarketplaceHitSchema,
39465
+ serviceOfferMarketplaceHitSchema,
39466
+ openRequestMarketplaceHitSchema
39467
+ ]);
39468
+ var marketplaceDiscoveryInputSchema = external_exports.strictObject({
39469
+ q: external_exports.string().trim().max(200).optional(),
39470
+ kinds: external_exports.array(marketplaceKindSchema).min(1).max(MARKETPLACE_KINDS.length).optional(),
39471
+ network: external_exports.string().trim().min(1).max(160).optional(),
39472
+ cursor: external_exports.string().trim().min(1).max(4096).optional(),
39473
+ limit: external_exports.number().int().min(1).max(50).optional(),
39474
+ includeUnverified: external_exports.boolean().optional()
39475
+ }).superRefine((input2, context) => {
39476
+ if (input2.kinds && new Set(input2.kinds).size !== input2.kinds.length) {
39477
+ context.addIssue({
39478
+ code: "custom",
39479
+ path: ["kinds"],
39480
+ message: "Marketplace kinds must be unique"
39481
+ });
40006
39482
  }
40007
- return defineChain({
40008
- id: definition.chainId,
40009
- name: definition.name,
40010
- nativeCurrency: definition.gasToken === "USDC" ? { name: "USDC", symbol: "USDC", decimals: USDC_DECIMALS } : { name: "Ether", symbol: "ETH", decimals: 18 },
40011
- rpcUrls: {
40012
- default: { http: [rpcUrl] }
40013
- },
40014
- ...definition.explorerUrl ? {
40015
- blockExplorers: {
40016
- default: { name: `${definition.name} explorer`, url: definition.explorerUrl }
40017
- }
40018
- } : {}
40019
- });
40020
- }
40021
- function createNetworkPublicClient(network, configured, options = {}) {
40022
- const rpcUrl = requireRpcUrl(network, configured);
40023
- return createPublicClient({
40024
- chain: createChain(network, rpcUrl),
40025
- transport: createNetworkHttpTransport(rpcUrl, options)
40026
- });
40027
- }
40028
- function createNetworkHttpTransport(rpcUrl, options = {}) {
40029
- const fetchFn = options.fetch ?? createPublicFetch({
40030
- allowPrivateNetwork: options.allowPrivateNetwork ?? false,
40031
- ...options.lookup ? { lookup: options.lookup } : {}
40032
- });
40033
- return http(rpcUrl, { fetchFn, fetchOptions: { redirect: "manual" } });
40034
- }
40035
- function formatUsdc(amountAtomic2) {
40036
- return formatUnits(amountAtomic2, USDC_DECIMALS);
39483
+ });
39484
+ function isMirroredHit(hit) {
39485
+ return hit.kind === "api" && hit.provenance === "indexed";
40037
39486
  }
39487
+ var marketplaceDiscoveryEnvelopeSchema = external_exports.looseObject({
39488
+ protocol: external_exports.literal(MARKETPLACE_DISCOVERY_PROTOCOL),
39489
+ items: external_exports.array(external_exports.unknown()),
39490
+ nextCursor: external_exports.string().min(1).max(4096).nullable(),
39491
+ unavailableKinds: external_exports.array(marketplaceKindSchema).max(MARKETPLACE_KINDS.length),
39492
+ rankingVersion: external_exports.literal(MARKETPLACE_RANKING_VERSION)
39493
+ });
39494
+ var marketplaceDiscoveryPageSchema = marketplaceDiscoveryEnvelopeSchema.extend({
39495
+ items: external_exports.array(marketplaceHitSchema)
39496
+ });
40038
39497
 
40039
39498
  // ../../node_modules/.pnpm/@solana+errors@5.5.1_typescript@6.0.3/node_modules/@solana/errors/dist/index.node.mjs
40040
39499
  var SOLANA_ERROR__BLOCK_HEIGHT_EXCEEDED = 1;
@@ -45016,16 +44475,16 @@ var DEFAULT_COMPUTE_UNIT_PRICE_MICROLAMPORTS = 1;
45016
44475
  var DEFAULT_COMPUTE_UNIT_LIMIT = 2e4;
45017
44476
  var MAX_MEMO_BYTES = 256;
45018
44477
  var SOLANA_MAINNET_CAIP22 = "solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp";
45019
- var SOLANA_DEVNET_CAIP2 = "solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1";
44478
+ var SOLANA_DEVNET_CAIP22 = "solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1";
45020
44479
  var SOLANA_TESTNET_CAIP2 = "solana:4uhcVJyU9pJkvQyS88uRDiswHXSCkY3z";
45021
44480
  var V1_TO_V2_NETWORK_MAP = {
45022
44481
  solana: SOLANA_MAINNET_CAIP22,
45023
- "solana-devnet": SOLANA_DEVNET_CAIP2,
44482
+ "solana-devnet": SOLANA_DEVNET_CAIP22,
45024
44483
  "solana-testnet": SOLANA_TESTNET_CAIP2
45025
44484
  };
45026
44485
  function normalizeNetwork(network) {
45027
44486
  if (network.includes(":")) {
45028
- const supported = [SOLANA_MAINNET_CAIP22, SOLANA_DEVNET_CAIP2, SOLANA_TESTNET_CAIP2];
44487
+ const supported = [SOLANA_MAINNET_CAIP22, SOLANA_DEVNET_CAIP22, SOLANA_TESTNET_CAIP2];
45029
44488
  if (!supported.includes(network)) {
45030
44489
  throw new Error(`Unsupported SVM network: ${network}`);
45031
44490
  }
@@ -45073,7 +44532,7 @@ var DEFAULT_ASSETS = {
45073
44532
  tokenProgram: TOKEN_2022_PROGRAM_ADDRESS2
45074
44533
  }
45075
44534
  ],
45076
- [SOLANA_DEVNET_CAIP2]: [
44535
+ [SOLANA_DEVNET_CAIP22]: [
45077
44536
  {
45078
44537
  asset: USDC_DEVNET_ADDRESS,
45079
44538
  decimals: 6,
@@ -45128,7 +44587,7 @@ var findDefaultAsset = (asset, network) => {
45128
44587
  function createRpcClient(network, customRpcUrl) {
45129
44588
  const caip2Network = normalizeNetwork(network);
45130
44589
  switch (caip2Network) {
45131
- case SOLANA_DEVNET_CAIP2: {
44590
+ case SOLANA_DEVNET_CAIP22: {
45132
44591
  const url2 = customRpcUrl || DEVNET_RPC_URL;
45133
44592
  return createSolanaRpc(devnet(url2));
45134
44593
  }
@@ -45326,6 +44785,376 @@ var ExactSvmScheme = class {
45326
44785
  var addressEncoder = getAddressEncoder();
45327
44786
  var compiledMessageDecoder = getCompiledTransactionMessageDecoder();
45328
44787
 
44788
+ // ../core/src/net-guard.ts
44789
+ import { lookup as dnsLookup } from "node:dns/promises";
44790
+ import { request as httpRequest } from "node:http";
44791
+ import { request as httpsRequest } from "node:https";
44792
+ import { isIP } from "node:net";
44793
+ import { Readable } from "node:stream";
44794
+ var defaultLookup = async (hostname3) => {
44795
+ const addresses = await dnsLookup(hostname3, { all: true });
44796
+ return addresses.map(({ address: address4 }) => address4);
44797
+ };
44798
+ async function assertPublicUrl(url2, options) {
44799
+ if (url2.username || url2.password) {
44800
+ throw guardError(url2);
44801
+ }
44802
+ if (url2.protocol !== "http:" && url2.protocol !== "https:") {
44803
+ throw guardError(url2);
44804
+ }
44805
+ if (options.allowPrivateNetwork) {
44806
+ return;
44807
+ }
44808
+ const hostname3 = normalizeHostname(url2.hostname);
44809
+ const lowercaseHostname = hostname3.toLowerCase();
44810
+ if (!lowercaseHostname || lowercaseHostname === "localhost" || lowercaseHostname.endsWith(".localhost") || lowercaseHostname.endsWith(".local") || lowercaseHostname.endsWith(".internal")) {
44811
+ throw guardError(url2);
44812
+ }
44813
+ if (isIP(hostname3)) {
44814
+ if (isNonPublicAddress(hostname3)) {
44815
+ throw guardError(url2);
44816
+ }
44817
+ return;
44818
+ }
44819
+ let addresses;
44820
+ try {
44821
+ addresses = await withTimeout2(
44822
+ (options.lookup ?? defaultLookup)(hostname3),
44823
+ options.timeoutMs ?? 5e3
44824
+ );
44825
+ } catch {
44826
+ throw guardError(url2);
44827
+ }
44828
+ if (addresses.length === 0 || addresses.some(isNonPublicAddress)) {
44829
+ throw guardError(url2);
44830
+ }
44831
+ }
44832
+ function createPublicFetch(options) {
44833
+ const lookupFn = options.lookup ?? defaultLookup;
44834
+ return (async (input2, init) => {
44835
+ const url2 = new URL(input2 instanceof Request ? input2.url : input2);
44836
+ await assertPublicUrl(url2, {
44837
+ allowPrivateNetwork: options.allowPrivateNetwork,
44838
+ lookup: lookupFn,
44839
+ timeoutMs: 5e3
44840
+ });
44841
+ const normalized = new Request(input2, init);
44842
+ const bytes = normalized.body ? Buffer.from(await normalized.arrayBuffer()) : null;
44843
+ return await new Promise((resolve2, reject) => {
44844
+ const requestOptions2 = {
44845
+ method: normalized.method,
44846
+ headers: Object.fromEntries(normalized.headers),
44847
+ signal: normalized.signal,
44848
+ ...options.allowPrivateNetwork ? {} : { lookup: pinnedLookup(lookupFn) }
44849
+ };
44850
+ const onResponse = (incoming) => {
44851
+ try {
44852
+ const headers = new Headers();
44853
+ for (const [name, value] of Object.entries(incoming.headers)) {
44854
+ if (Array.isArray(value)) {
44855
+ for (const item of value) headers.append(name, item);
44856
+ } else if (value !== void 0) {
44857
+ headers.set(name, value);
44858
+ }
44859
+ }
44860
+ const status = incoming.statusCode ?? 500;
44861
+ const bodyForbidden = normalized.method === "HEAD" || [204, 205, 304].includes(status);
44862
+ if (bodyForbidden) incoming.resume();
44863
+ const response = new Response(
44864
+ bodyForbidden ? null : Readable.toWeb(incoming),
44865
+ { status, statusText: incoming.statusMessage, headers }
44866
+ );
44867
+ Object.defineProperty(response, "url", { value: url2.toString() });
44868
+ resolve2(response);
44869
+ } catch (error61) {
44870
+ incoming.destroy();
44871
+ reject(error61);
44872
+ }
44873
+ };
44874
+ const request = url2.protocol === "https:" ? httpsRequest(url2, requestOptions2, onResponse) : httpRequest(url2, requestOptions2, onResponse);
44875
+ request.on("error", reject);
44876
+ if (bytes) request.write(bytes);
44877
+ request.end();
44878
+ });
44879
+ });
44880
+ }
44881
+ function pinnedLookup(lookup2) {
44882
+ return (hostname3, dnsOptions, callback) => {
44883
+ void lookup2(normalizeHostname(hostname3)).then((addresses) => {
44884
+ if (addresses.length === 0 || addresses.some(isNonPublicAddress)) {
44885
+ callback(guardError(new URL(`https://${hostname3}`)), "");
44886
+ return;
44887
+ }
44888
+ const address4 = addresses[0];
44889
+ const family = isIP(address4);
44890
+ callback(
44891
+ null,
44892
+ dnsOptions.all ? [{ address: address4, family }] : address4,
44893
+ dnsOptions.all ? void 0 : family
44894
+ );
44895
+ }).catch(
44896
+ (error61) => callback(error61 instanceof Error ? error61 : new Error("DNS lookup failed."), "")
44897
+ );
44898
+ };
44899
+ }
44900
+ async function withTimeout2(operation, timeoutMs) {
44901
+ let timeout;
44902
+ try {
44903
+ return await Promise.race([
44904
+ operation,
44905
+ new Promise((_resolve, reject) => {
44906
+ timeout = setTimeout(() => reject(new Error("DNS lookup timed out.")), timeoutMs);
44907
+ })
44908
+ ]);
44909
+ } finally {
44910
+ if (timeout) clearTimeout(timeout);
44911
+ }
44912
+ }
44913
+ function normalizeHostname(hostname3) {
44914
+ const unbracketed = hostname3.startsWith("[") && hostname3.endsWith("]") ? hostname3.slice(1, -1) : hostname3;
44915
+ return unbracketed.endsWith(".") ? unbracketed.slice(0, -1) : unbracketed;
44916
+ }
44917
+ function isNonPublicAddress(address4) {
44918
+ const normalized = normalizeHostname(address4);
44919
+ const version5 = isIP(normalized);
44920
+ if (version5 === 4) {
44921
+ return isNonPublicIpv4(parseIpv4(normalized));
44922
+ }
44923
+ if (version5 === 6) {
44924
+ return isNonPublicIpv6(parseIpv6(normalized));
44925
+ }
44926
+ return true;
44927
+ }
44928
+ function parseIpv4(address4) {
44929
+ const octets = address4.split(".").map(Number);
44930
+ return [octets[0], octets[1], octets[2], octets[3]];
44931
+ }
44932
+ function isNonPublicIpv4([first, second, third]) {
44933
+ return first === 0 || first === 10 || first === 100 && second >= 64 && second <= 127 || first === 127 || first === 169 && second === 254 || first === 172 && second >= 16 && second <= 31 || first === 192 && second === 0 && (third === 0 || third === 2) || first === 192 && second === 168 || first === 198 && second >= 18 && second <= 19 || first === 198 && second === 51 && third === 100 || first === 203 && second === 0 && third === 113 || first >= 224;
44934
+ }
44935
+ function parseIpv6(address4) {
44936
+ let normalized = address4.toLowerCase();
44937
+ const lastColon = normalized.lastIndexOf(":");
44938
+ const dottedTail = normalized.slice(lastColon + 1);
44939
+ if (dottedTail.includes(".")) {
44940
+ const [first, second, third, fourth] = parseIpv4(dottedTail);
44941
+ normalized = `${normalized.slice(0, lastColon + 1)}${(first << 8 | second).toString(16)}:${(third << 8 | fourth).toString(16)}`;
44942
+ }
44943
+ const halves = normalized.split("::");
44944
+ const left = halves[0] ? halves[0].split(":").map(parseHex) : [];
44945
+ const right = halves[1] ? halves[1].split(":").map(parseHex) : [];
44946
+ const omittedCount = 8 - left.length - right.length;
44947
+ return halves.length === 2 ? [...left, ...Array.from({ length: omittedCount }, () => 0), ...right] : left;
44948
+ }
44949
+ function parseHex(value) {
44950
+ return Number.parseInt(value, 16);
44951
+ }
44952
+ function isNonPublicIpv6(hextets) {
44953
+ if (hextets.slice(0, 5).every((hextet) => hextet === 0) && hextets[5] === 65535) {
44954
+ const embeddedIpv4 = [
44955
+ hextets[6] >> 8,
44956
+ hextets[6] & 255,
44957
+ hextets[7] >> 8,
44958
+ hextets[7] & 255
44959
+ ];
44960
+ return isNonPublicIpv4(embeddedIpv4);
44961
+ }
44962
+ if (hextets.slice(0, 6).every((hextet) => hextet === 0)) {
44963
+ const compatibleIpv4 = [
44964
+ hextets[6] >> 8,
44965
+ hextets[6] & 255,
44966
+ hextets[7] >> 8,
44967
+ hextets[7] & 255
44968
+ ];
44969
+ if (isNonPublicIpv4(compatibleIpv4)) return true;
44970
+ }
44971
+ const isUnspecified = hextets.every((hextet) => hextet === 0);
44972
+ const isLoopback = hextets.slice(0, 7).every((hextet) => hextet === 0) && hextets[7] === 1;
44973
+ const first = hextets[0];
44974
+ const isUniqueLocal = first >= 64512 && first <= 65023;
44975
+ const isLinkLocal = first >= 65152 && first <= 65215;
44976
+ const isSiteLocal = first >= 65216 && first <= 65279;
44977
+ const isMulticast = first >= 65280;
44978
+ const isDocumentation = first === 8193 && hextets[1] === 3512;
44979
+ return isUnspecified || isLoopback || isUniqueLocal || isLinkLocal || isSiteLocal || isMulticast || isDocumentation;
44980
+ }
44981
+ function guardError(url2) {
44982
+ return new Error(
44983
+ `URL hostname ${JSON.stringify(url2.hostname)} is not allowed; private or internal destinations require allowPrivateNetwork true in the vAPI config.`
44984
+ );
44985
+ }
44986
+
44987
+ // ../core/src/networks.ts
44988
+ var USDC_DECIMALS = 6;
44989
+ var DEFAULT_ARC_GAS_HEADROOM_ATOMIC = 50000n;
44990
+ var NETWORKS2 = {
44991
+ [BASE_MAINNET_CAIP2]: {
44992
+ family: "evm",
44993
+ chainId: 8453,
44994
+ name: "Base mainnet",
44995
+ usdc: CANONICAL_X402_USDC_NETWORKS[BASE_MAINNET_CAIP2].usdc,
44996
+ gasToken: "ETH",
44997
+ rpcEnv: "BASE_RPC_URL",
44998
+ publicRpcUrl: "https://mainnet.base.org",
44999
+ explorerUrl: "https://basescan.org"
45000
+ },
45001
+ [ARC_MAINNET_CAIP2]: {
45002
+ family: "evm",
45003
+ chainId: 5042,
45004
+ name: "Arc mainnet",
45005
+ usdc: CANONICAL_X402_USDC_NETWORKS[ARC_MAINNET_CAIP2].usdc,
45006
+ gasToken: "USDC",
45007
+ rpcEnv: "ARC_RPC_URL",
45008
+ publicRpcUrl: "https://rpc.mainnet.arc.io",
45009
+ explorerUrl: "https://explorer.arc.io"
45010
+ },
45011
+ [ARC_TESTNET_CAIP2]: {
45012
+ family: "evm",
45013
+ chainId: 5042002,
45014
+ name: "Arc testnet",
45015
+ usdc: CANONICAL_X402_USDC_NETWORKS[ARC_TESTNET_CAIP2].usdc,
45016
+ gasToken: "USDC",
45017
+ rpcEnv: "ARC_TESTNET_RPC_URL"
45018
+ },
45019
+ [SOLANA_MAINNET_CAIP2]: {
45020
+ family: "svm",
45021
+ name: "Solana mainnet",
45022
+ usdc: SOLANA_MAINNET_USDC,
45023
+ gasToken: "SOL",
45024
+ rpcEnv: "SOLANA_RPC_URL",
45025
+ publicRpcUrl: "https://api.mainnet-beta.solana.com"
45026
+ },
45027
+ [X402_SOLANA_MAINNET_CAIP2]: {
45028
+ family: "svm",
45029
+ name: "Solana mainnet",
45030
+ usdc: SOLANA_MAINNET_USDC,
45031
+ gasToken: "SOL",
45032
+ rpcEnv: "SOLANA_RPC_URL",
45033
+ publicRpcUrl: "https://api.mainnet-beta.solana.com"
45034
+ }
45035
+ };
45036
+ function parseEip155ChainId(network) {
45037
+ const match = /^eip155:(\d+)$/.exec(network);
45038
+ if (!match) {
45039
+ throw new Error(`Unsupported network ${network}; expected eip155:<chainId>.`);
45040
+ }
45041
+ const chainId = Number(match[1]);
45042
+ if (!Number.isSafeInteger(chainId) || chainId <= 0) {
45043
+ throw new Error(`Invalid EVM chain ID in network ${network}.`);
45044
+ }
45045
+ return chainId;
45046
+ }
45047
+ function isSolanaNetwork(network) {
45048
+ return network === SOLANA_MAINNET_CAIP2 || network === X402_SOLANA_MAINNET_CAIP2;
45049
+ }
45050
+ function usesUsdcGas(network) {
45051
+ try {
45052
+ return getNetworkDefinition(network).gasToken === "USDC";
45053
+ } catch {
45054
+ return false;
45055
+ }
45056
+ }
45057
+ function explorerTransactionUrl(network, hash5) {
45058
+ try {
45059
+ const explorerUrl = getNetworkDefinition(network).explorerUrl;
45060
+ return explorerUrl ? `${explorerUrl}/tx/${hash5}` : void 0;
45061
+ } catch {
45062
+ return void 0;
45063
+ }
45064
+ }
45065
+ function explorerAddressUrl(network, address4) {
45066
+ try {
45067
+ const explorerUrl = getNetworkDefinition(network).explorerUrl;
45068
+ return explorerUrl ? `${explorerUrl}/address/${address4}` : void 0;
45069
+ } catch {
45070
+ return void 0;
45071
+ }
45072
+ }
45073
+ function areSamePaymentNetwork(left, right) {
45074
+ return left === right || isSolanaNetwork(left) && isSolanaNetwork(right);
45075
+ }
45076
+ function isSupportedPaymentNetwork(network) {
45077
+ if (isSolanaNetwork(network)) return true;
45078
+ try {
45079
+ parseEip155ChainId(network);
45080
+ return true;
45081
+ } catch {
45082
+ return false;
45083
+ }
45084
+ }
45085
+ function configuredNetworkFor(networks, network) {
45086
+ const configured = networks[network];
45087
+ if (configured) return configured;
45088
+ if (network === X402_SOLANA_MAINNET_CAIP2) return networks[SOLANA_MAINNET_CAIP2];
45089
+ if (network === SOLANA_MAINNET_CAIP2) return networks[X402_SOLANA_MAINNET_CAIP2];
45090
+ return void 0;
45091
+ }
45092
+ function getNetworkDefinition(network) {
45093
+ const known = NETWORKS2[network];
45094
+ if (known) {
45095
+ return known;
45096
+ }
45097
+ const chainId = parseEip155ChainId(network);
45098
+ return {
45099
+ family: "evm",
45100
+ chainId,
45101
+ name: network,
45102
+ usdc: getAddress("0x0000000000000000000000000000000000000000"),
45103
+ gasToken: "ETH",
45104
+ rpcEnv: ""
45105
+ };
45106
+ }
45107
+ function requireRpcUrl(network, configured) {
45108
+ const definition = getNetworkDefinition(network);
45109
+ const envUrl = definition.rpcEnv ? process.env[definition.rpcEnv]?.trim() : void 0;
45110
+ const rpcUrl = envUrl || configured.rpcUrl.trim();
45111
+ if (rpcUrl) {
45112
+ return rpcUrl;
45113
+ }
45114
+ if (network === ARC_TESTNET_CAIP2) {
45115
+ throw new Error(
45116
+ "Arc testnet RPC is required. Set ARC_TESTNET_RPC_URL or add rpcUrl for eip155:5042002 in config.json."
45117
+ );
45118
+ }
45119
+ throw new Error(`RPC URL is required for ${network}.`);
45120
+ }
45121
+ function createChain(network, rpcUrl) {
45122
+ const definition = getNetworkDefinition(network);
45123
+ if (definition.family !== "evm" || definition.chainId === void 0) {
45124
+ throw new Error(`Network ${network} is not an EVM chain.`);
45125
+ }
45126
+ return defineChain({
45127
+ id: definition.chainId,
45128
+ name: definition.name,
45129
+ nativeCurrency: definition.gasToken === "USDC" ? { name: "USDC", symbol: "USDC", decimals: USDC_DECIMALS } : { name: "Ether", symbol: "ETH", decimals: 18 },
45130
+ rpcUrls: {
45131
+ default: { http: [rpcUrl] }
45132
+ },
45133
+ ...definition.explorerUrl ? {
45134
+ blockExplorers: {
45135
+ default: { name: `${definition.name} explorer`, url: definition.explorerUrl }
45136
+ }
45137
+ } : {}
45138
+ });
45139
+ }
45140
+ function createNetworkPublicClient(network, configured, options = {}) {
45141
+ const rpcUrl = requireRpcUrl(network, configured);
45142
+ return createPublicClient({
45143
+ chain: createChain(network, rpcUrl),
45144
+ transport: createNetworkHttpTransport(rpcUrl, options)
45145
+ });
45146
+ }
45147
+ function createNetworkHttpTransport(rpcUrl, options = {}) {
45148
+ const fetchFn = options.fetch ?? createPublicFetch({
45149
+ allowPrivateNetwork: options.allowPrivateNetwork ?? false,
45150
+ ...options.lookup ? { lookup: options.lookup } : {}
45151
+ });
45152
+ return http(rpcUrl, { fetchFn, fetchOptions: { redirect: "manual" } });
45153
+ }
45154
+ function formatUsdc(amountAtomic2) {
45155
+ return formatUnits(amountAtomic2, USDC_DECIMALS);
45156
+ }
45157
+
45329
45158
  // ../core/src/x402.ts
45330
45159
  var MAX_CHALLENGE_BYTES = 1048576;
45331
45160
  var MAX_UINT256 = (1n << 256n) - 1n;
@@ -46185,6 +46014,242 @@ function isRecord2(value) {
46185
46014
  return typeof value === "object" && value !== null && !Array.isArray(value);
46186
46015
  }
46187
46016
 
46017
+ // ../core/src/call-contracts-wire.ts
46018
+ var CALLABLE_CATEGORIES = ["ai", "data", "crypto", "compute", "search"];
46019
+ var callableCategorySchema = external_exports.enum(CALLABLE_CATEGORIES);
46020
+ var DISCOVERY_CATEGORIES = [...CALLABLE_CATEGORIES, "other"];
46021
+ var discoveryCategorySchema = external_exports.string().trim().min(1);
46022
+ var CALLABLE_CATEGORY_SET = new Set(CALLABLE_CATEGORIES);
46023
+ var serviceTierSchema = external_exports.string().trim().min(1);
46024
+ var discoveryEndpointSchema = external_exports.looseObject({
46025
+ name: external_exports.string(),
46026
+ method: external_exports.string(),
46027
+ url: external_exports.url(),
46028
+ price: external_exports.string(),
46029
+ description: external_exports.string(),
46030
+ operationId: external_exports.string().trim().min(1).optional(),
46031
+ requestContentType: external_exports.string().trim().min(1).optional(),
46032
+ requestSchema: external_exports.json().optional(),
46033
+ responseContentType: external_exports.string().trim().min(1).optional(),
46034
+ pathTemplate: external_exports.string().trim().min(1).optional(),
46035
+ pathParameters: external_exports.array(external_exports.string().trim().min(1)).optional(),
46036
+ payment: external_exports.union([
46037
+ external_exports.looseObject({
46038
+ scheme: external_exports.literal("exact"),
46039
+ network: external_exports.string().regex(/^eip155:\d+$/),
46040
+ asset: external_exports.string().regex(/^0x[0-9a-fA-F]{40}$/),
46041
+ payTo: external_exports.string().regex(/^0x[0-9a-fA-F]{40}$/),
46042
+ checkedAt: external_exports.iso.datetime()
46043
+ }),
46044
+ external_exports.looseObject({
46045
+ scheme: external_exports.literal("exact"),
46046
+ network: external_exports.union([
46047
+ external_exports.string().regex(/^solana:[-_a-zA-Z0-9]{1,32}$/),
46048
+ external_exports.literal(SOLANA_MAINNET_CAIP2)
46049
+ ]),
46050
+ asset: external_exports.string().refine(isSolanaAddress, "Expected a Solana base58 address."),
46051
+ payTo: external_exports.string().refine(isSolanaAddress, "Expected a Solana base58 address."),
46052
+ checkedAt: external_exports.iso.datetime()
46053
+ }),
46054
+ external_exports.looseObject({
46055
+ protocol: external_exports.literal("mpp"),
46056
+ intent: external_exports.enum(["charge", "authorize", "subscription"]).nullable(),
46057
+ method: external_exports.string().trim().min(1).max(40).nullable(),
46058
+ checkedAt: external_exports.iso.datetime(),
46059
+ // Keep common x402 properties readable on the union while making it
46060
+ // impossible for MPP metadata to masquerade as executable x402 terms.
46061
+ network: external_exports.never().optional(),
46062
+ payTo: external_exports.never().optional()
46063
+ }),
46064
+ external_exports.looseObject({
46065
+ // Future payment protocols remain visible to callers so the payment
46066
+ // layer can refuse them explicitly instead of discovery losing the row.
46067
+ protocol: external_exports.string().trim().min(1).max(40),
46068
+ checkedAt: external_exports.iso.datetime(),
46069
+ network: external_exports.never().optional(),
46070
+ payTo: external_exports.never().optional()
46071
+ })
46072
+ ]).optional()
46073
+ });
46074
+ var serviceSummarySchema = external_exports.looseObject({
46075
+ id: external_exports.string(),
46076
+ name: external_exports.string(),
46077
+ description: external_exports.string(),
46078
+ category: discoveryCategorySchema,
46079
+ tier: serviceTierSchema,
46080
+ ...listingDisclosureShape,
46081
+ verified: external_exports.boolean(),
46082
+ wrapped: external_exports.boolean(),
46083
+ price: external_exports.string(),
46084
+ networks: external_exports.array(external_exports.string()),
46085
+ endpoints: external_exports.array(discoveryEndpointSchema)
46086
+ });
46087
+ var searchServicesResponseSchema = external_exports.looseObject({
46088
+ services: external_exports.array(serviceSummarySchema)
46089
+ });
46090
+ var discoveryResponseSchema = searchServicesResponseSchema;
46091
+
46092
+ // ../core/src/call-contracts.ts
46093
+ var DiscoveryCatalogError = class extends Error {
46094
+ constructor(code, message, serviceId, paymentNetworks) {
46095
+ super(message);
46096
+ this.paymentNetworks = paymentNetworks;
46097
+ this.code = code;
46098
+ this.serviceId = serviceId;
46099
+ }
46100
+ paymentNetworks;
46101
+ name = "DiscoveryCatalogError";
46102
+ code;
46103
+ serviceId;
46104
+ };
46105
+ function isDiscoveryCatalogError(error61) {
46106
+ if (!(error61 instanceof Error) || error61.name !== "DiscoveryCatalogError" || !("code" in error61) || typeof error61.code !== "string") {
46107
+ return false;
46108
+ }
46109
+ const networks = Reflect.get(error61, "paymentNetworks");
46110
+ return networks === void 0 || Array.isArray(networks) && networks.every((network) => typeof network === "string");
46111
+ }
46112
+ function parseDiscovery(raw) {
46113
+ const parsed = discoveryResponseSchema.safeParse(raw);
46114
+ if (!parsed.success) {
46115
+ const malformedUrl = parsed.error.issues.find(
46116
+ (issue2) => issue2.path.at(-1) === "url" && issue2.path.includes("endpoints")
46117
+ );
46118
+ if (malformedUrl) {
46119
+ const serviceIndex = pathIndexAfter(malformedUrl.path, "services");
46120
+ const serviceId = rawServiceId(raw, serviceIndex);
46121
+ throw new DiscoveryCatalogError(
46122
+ "malformed_url",
46123
+ `Service ${JSON.stringify(serviceId ?? "unknown")} has a malformed endpoint URL.`,
46124
+ serviceId
46125
+ );
46126
+ }
46127
+ throw new DiscoveryCatalogError("invalid_discovery", "Discovery response is malformed.");
46128
+ }
46129
+ for (const service of parsed.data.services) {
46130
+ buildTargets(service);
46131
+ }
46132
+ const resolveListing = (serviceId, endpointName) => {
46133
+ const service = parsed.data.services.find((candidate) => candidate.id === serviceId);
46134
+ if (!service) {
46135
+ throw new DiscoveryCatalogError(
46136
+ "service_not_found",
46137
+ `No payable endpoint found for service ${JSON.stringify(serviceId)}.`,
46138
+ serviceId
46139
+ );
46140
+ }
46141
+ return { service, endpoint: resolveTarget(service, endpointName) };
46142
+ };
46143
+ return {
46144
+ services: parsed.data.services,
46145
+ resolve: (serviceId, endpointName) => resolveListing(serviceId, endpointName).endpoint,
46146
+ resolveListing
46147
+ };
46148
+ }
46149
+ function resolveTarget(service, endpointName) {
46150
+ const { targets, targetsByName } = buildTargets(service);
46151
+ if (endpointName !== void 0) {
46152
+ const selected = targetsByName.get(endpointName.trim());
46153
+ if (!selected) {
46154
+ throw new DiscoveryCatalogError(
46155
+ "endpoint_not_found",
46156
+ `Service ${JSON.stringify(service.id)} has no endpoint ${JSON.stringify(endpointName)}. Available endpoints: ${[...targetsByName.keys()].join(", ")}.`,
46157
+ service.id
46158
+ );
46159
+ }
46160
+ return { ...selected };
46161
+ }
46162
+ if (targets.size !== 1) {
46163
+ const paymentNetworks = service.endpoints.flatMap(
46164
+ (endpoint) => typeof endpoint.payment?.network === "string" ? [endpoint.payment.network] : []
46165
+ );
46166
+ throw new DiscoveryCatalogError(
46167
+ "ambiguous_default",
46168
+ `Service ${JSON.stringify(service.id)} has ${targets.size} distinct payable endpoints. Choose one with endpoint: ${[...targetsByName.keys()].join(", ")}.`,
46169
+ service.id,
46170
+ paymentNetworks.length === service.endpoints.length ? paymentNetworks : void 0
46171
+ );
46172
+ }
46173
+ return targets.values().next().value;
46174
+ }
46175
+ function buildTargets(service) {
46176
+ if (service.endpoints.length === 0) {
46177
+ throw new DiscoveryCatalogError(
46178
+ "no_endpoint",
46179
+ `Service ${JSON.stringify(service.id)} has no payable endpoint.`,
46180
+ service.id
46181
+ );
46182
+ }
46183
+ const namedEndpoints = [...service.endpoints].sort(
46184
+ (left, right) => compareNames(left.name.trim(), right.name.trim())
46185
+ );
46186
+ const names = /* @__PURE__ */ new Set();
46187
+ const targets = /* @__PURE__ */ new Map();
46188
+ const targetsByName = /* @__PURE__ */ new Map();
46189
+ for (const endpoint of namedEndpoints) {
46190
+ const name = endpoint.name.trim();
46191
+ if (!name) {
46192
+ throw new DiscoveryCatalogError(
46193
+ "invalid_endpoint_name",
46194
+ `Service ${JSON.stringify(service.id)} has a blank endpoint name.`,
46195
+ service.id
46196
+ );
46197
+ }
46198
+ if (names.has(name)) {
46199
+ throw new DiscoveryCatalogError(
46200
+ "duplicate_endpoint_name",
46201
+ `Service ${JSON.stringify(service.id)} has duplicate endpoint name ${JSON.stringify(name)}.`,
46202
+ service.id
46203
+ );
46204
+ }
46205
+ names.add(name);
46206
+ const method = endpoint.method.trim().toUpperCase();
46207
+ if (!method) {
46208
+ throw new DiscoveryCatalogError(
46209
+ "blank_method",
46210
+ `Service ${JSON.stringify(service.id)} has a blank endpoint method.`,
46211
+ service.id
46212
+ );
46213
+ }
46214
+ const url2 = new URL(endpoint.url);
46215
+ if (url2.protocol !== "http:" && url2.protocol !== "https:") {
46216
+ throw new DiscoveryCatalogError(
46217
+ "malformed_url",
46218
+ `Service ${JSON.stringify(service.id)} has a non-HTTP endpoint URL.`,
46219
+ service.id
46220
+ );
46221
+ }
46222
+ const transportKey = `${method}\0${endpoint.url}`;
46223
+ const normalized = { ...endpoint, name, method };
46224
+ targetsByName.set(name, normalized);
46225
+ if (!targets.has(transportKey)) targets.set(transportKey, normalized);
46226
+ }
46227
+ return { targets, targetsByName };
46228
+ }
46229
+ function compareNames(left, right) {
46230
+ return left < right ? -1 : left > right ? 1 : 0;
46231
+ }
46232
+ function pathIndexAfter(path, key2) {
46233
+ const keyIndex = path.indexOf(key2);
46234
+ const candidate = path[keyIndex + 1];
46235
+ return typeof candidate === "number" ? candidate : void 0;
46236
+ }
46237
+ function rawServiceId(raw, serviceIndex) {
46238
+ if (serviceIndex === void 0 || typeof raw !== "object" || raw === null) {
46239
+ return void 0;
46240
+ }
46241
+ const services = Reflect.get(raw, "services");
46242
+ if (!Array.isArray(services)) {
46243
+ return void 0;
46244
+ }
46245
+ const service = services[serviceIndex];
46246
+ if (typeof service !== "object" || service === null) {
46247
+ return void 0;
46248
+ }
46249
+ const id2 = Reflect.get(service, "id");
46250
+ return typeof id2 === "string" ? id2 : void 0;
46251
+ }
46252
+
46188
46253
  // ../core/src/sweep.ts
46189
46254
  var ERC20_ABI = [
46190
46255
  {
@@ -47033,7 +47098,7 @@ var configSchema = external_exports.object({
47033
47098
  }
47034
47099
  for (const [network, configured] of Object.entries(config2.networks)) {
47035
47100
  if (isSolanaNetwork(network)) {
47036
- if (configured.usdc !== NETWORKS[SOLANA_MAINNET_CAIP2].usdc) {
47101
+ if (configured.usdc !== NETWORKS2[SOLANA_MAINNET_CAIP2].usdc) {
47037
47102
  context.addIssue({
47038
47103
  code: "custom",
47039
47104
  path: ["networks", network, "usdc"],
@@ -47044,7 +47109,7 @@ var configSchema = external_exports.object({
47044
47109
  }
47045
47110
  try {
47046
47111
  const usdc = getAddress(configured.usdc);
47047
- if ((network === ARC_MAINNET_CAIP2 || network === ARC_TESTNET_CAIP2) && usdc !== getAddress(NETWORKS[network].usdc)) {
47112
+ if ((network === ARC_MAINNET_CAIP2 || network === ARC_TESTNET_CAIP2) && usdc !== getAddress(NETWORKS2[network].usdc)) {
47048
47113
  context.addIssue({
47049
47114
  code: "custom",
47050
47115
  path: ["networks", network, "usdc"],
@@ -47071,7 +47136,8 @@ function getVapiPaths(directory = process.env.VAPI_HOME?.trim() || join2(homedir
47071
47136
  keystore: join2(directory, "keystore.json"),
47072
47137
  receipts: join2(directory, "receipts.jsonl"),
47073
47138
  searches: join2(directory, "searches.jsonl"),
47074
- ledger: join2(directory, "spend-ledger.json")
47139
+ ledger: join2(directory, "spend-ledger.json"),
47140
+ updateCheck: join2(directory, "update-check.json")
47075
47141
  };
47076
47142
  }
47077
47143
  var getAgentCashPaths = getVapiPaths;
@@ -47196,15 +47262,15 @@ function getDefaultConfig(source = process.env, options = {}) {
47196
47262
  const tasksEscrowFactoryOverrides = tasksFactoryOverridesFromEnv(source);
47197
47263
  if (requested.has("base") || requested.has(BASE_MAINNET_CAIP2)) {
47198
47264
  networks[BASE_MAINNET_CAIP2] = {
47199
- rpcUrl: source.BASE_RPC_URL?.trim() || NETWORKS[BASE_MAINNET_CAIP2].publicRpcUrl,
47200
- usdc: NETWORKS[BASE_MAINNET_CAIP2].usdc
47265
+ rpcUrl: source.BASE_RPC_URL?.trim() || NETWORKS2[BASE_MAINNET_CAIP2].publicRpcUrl,
47266
+ usdc: NETWORKS2[BASE_MAINNET_CAIP2].usdc
47201
47267
  };
47202
47268
  }
47203
47269
  const arcMainnetRpcUrl = source.ARC_RPC_URL?.trim();
47204
47270
  if (arcMainnetRpcUrl || requested.has("arc") || requested.has(ARC_MAINNET_CAIP2)) {
47205
47271
  networks[ARC_MAINNET_CAIP2] = {
47206
- rpcUrl: arcMainnetRpcUrl || NETWORKS[ARC_MAINNET_CAIP2].publicRpcUrl,
47207
- usdc: NETWORKS[ARC_MAINNET_CAIP2].usdc
47272
+ rpcUrl: arcMainnetRpcUrl || NETWORKS2[ARC_MAINNET_CAIP2].publicRpcUrl,
47273
+ usdc: NETWORKS2[ARC_MAINNET_CAIP2].usdc
47208
47274
  };
47209
47275
  }
47210
47276
  const arcTestnetRpcUrl = source.ARC_TESTNET_RPC_URL?.trim();
@@ -47216,14 +47282,14 @@ function getDefaultConfig(source = process.env, options = {}) {
47216
47282
  }
47217
47283
  networks[ARC_TESTNET_CAIP2] = {
47218
47284
  rpcUrl: arcTestnetRpcUrl,
47219
- usdc: NETWORKS[ARC_TESTNET_CAIP2].usdc
47285
+ usdc: NETWORKS2[ARC_TESTNET_CAIP2].usdc
47220
47286
  };
47221
47287
  }
47222
47288
  const solanaRpcUrl = source.SOLANA_RPC_URL?.trim();
47223
47289
  if (solanaRpcUrl || requested.has("solana") || requested.has(SOLANA_MAINNET_CAIP2)) {
47224
47290
  networks[SOLANA_MAINNET_CAIP2] = {
47225
- rpcUrl: solanaRpcUrl || NETWORKS[SOLANA_MAINNET_CAIP2].publicRpcUrl,
47226
- usdc: NETWORKS[SOLANA_MAINNET_CAIP2].usdc
47291
+ rpcUrl: solanaRpcUrl || NETWORKS2[SOLANA_MAINNET_CAIP2].publicRpcUrl,
47292
+ usdc: NETWORKS2[SOLANA_MAINNET_CAIP2].usdc
47227
47293
  };
47228
47294
  }
47229
47295
  return {
@@ -47281,21 +47347,21 @@ Run vapi init to write the new URLs to ${path}.`
47281
47347
  if (arcMainnetRpcUrl) {
47282
47348
  const existing = config2.networks[ARC_MAINNET_CAIP2];
47283
47349
  config2.networks[ARC_MAINNET_CAIP2] = {
47284
- ...existing ?? { usdc: NETWORKS[ARC_MAINNET_CAIP2].usdc },
47350
+ ...existing ?? { usdc: NETWORKS2[ARC_MAINNET_CAIP2].usdc },
47285
47351
  rpcUrl: arcMainnetRpcUrl
47286
47352
  };
47287
47353
  }
47288
47354
  if (arcTestnetRpcUrl) {
47289
47355
  const existing = config2.networks[ARC_TESTNET_CAIP2];
47290
47356
  config2.networks[ARC_TESTNET_CAIP2] = {
47291
- ...existing ?? { usdc: NETWORKS[ARC_TESTNET_CAIP2].usdc },
47357
+ ...existing ?? { usdc: NETWORKS2[ARC_TESTNET_CAIP2].usdc },
47292
47358
  rpcUrl: arcTestnetRpcUrl
47293
47359
  };
47294
47360
  }
47295
47361
  if (solanaRpcUrl) {
47296
47362
  config2.networks[SOLANA_MAINNET_CAIP2] = {
47297
47363
  rpcUrl: solanaRpcUrl,
47298
- usdc: config2.networks[SOLANA_MAINNET_CAIP2]?.usdc ?? NETWORKS[SOLANA_MAINNET_CAIP2].usdc
47364
+ usdc: config2.networks[SOLANA_MAINNET_CAIP2]?.usdc ?? NETWORKS2[SOLANA_MAINNET_CAIP2].usdc
47299
47365
  };
47300
47366
  }
47301
47367
  if (registryUrl) {
@@ -47308,7 +47374,7 @@ Run vapi init to write the new URLs to ${path}.`
47308
47374
  for (const [network, configured] of Object.entries(config2.networks)) {
47309
47375
  configured.rpcUrl = configured.rpcUrl.trim();
47310
47376
  configured.usdc = configured.usdc.trim();
47311
- if (isSolanaNetwork(network) && configured.usdc !== NETWORKS[SOLANA_MAINNET_CAIP2].usdc) {
47377
+ if (isSolanaNetwork(network) && configured.usdc !== NETWORKS2[SOLANA_MAINNET_CAIP2].usdc) {
47312
47378
  throw new Error(`Network ${network} must use canonical Solana mainnet USDC.`);
47313
47379
  }
47314
47380
  if (!configured.rpcUrl) delete config2.networks[network];
@@ -47364,14 +47430,14 @@ async function enableDefaultNetwork(network, path = getVapiPaths().config, sourc
47364
47430
  const config2 = await loadConfig(path, source);
47365
47431
  if (network === "solana") {
47366
47432
  config2.networks[SOLANA_MAINNET_CAIP2] = {
47367
- rpcUrl: source.SOLANA_RPC_URL?.trim() || NETWORKS[SOLANA_MAINNET_CAIP2].publicRpcUrl,
47368
- usdc: NETWORKS[SOLANA_MAINNET_CAIP2].usdc
47433
+ rpcUrl: source.SOLANA_RPC_URL?.trim() || NETWORKS2[SOLANA_MAINNET_CAIP2].publicRpcUrl,
47434
+ usdc: NETWORKS2[SOLANA_MAINNET_CAIP2].usdc
47369
47435
  };
47370
47436
  } else {
47371
47437
  const existing = config2.networks[ARC_MAINNET_CAIP2];
47372
47438
  config2.networks[ARC_MAINNET_CAIP2] = {
47373
- ...existing ?? { usdc: NETWORKS[ARC_MAINNET_CAIP2].usdc },
47374
- rpcUrl: source.ARC_RPC_URL?.trim() || NETWORKS[ARC_MAINNET_CAIP2].publicRpcUrl
47439
+ ...existing ?? { usdc: NETWORKS2[ARC_MAINNET_CAIP2].usdc },
47440
+ rpcUrl: source.ARC_RPC_URL?.trim() || NETWORKS2[ARC_MAINNET_CAIP2].publicRpcUrl
47375
47441
  };
47376
47442
  }
47377
47443
  await writeConfigFile(path, config2);
@@ -70335,7 +70401,7 @@ function windowsDataProtectionStore(platform2, run, env, installed) {
70335
70401
  };
70336
70402
  }
70337
70403
  function libsecretStore(platform2, run, installed) {
70338
- const lookup = async (name) => {
70404
+ const lookup2 = async (name) => {
70339
70405
  const result = await run(SECRET_TOOL_BINARY, [
70340
70406
  "lookup",
70341
70407
  "service",
@@ -70354,9 +70420,9 @@ function libsecretStore(platform2, run, installed) {
70354
70420
  available: installed(SECRET_TOOL_BINARY),
70355
70421
  platform: platform2,
70356
70422
  description: "the libsecret keyring",
70357
- get: lookup,
70423
+ get: lookup2,
70358
70424
  async has(name) {
70359
- return await lookup(name) !== void 0;
70425
+ return await lookup2(name) !== void 0;
70360
70426
  },
70361
70427
  async set(name, passphrase) {
70362
70428
  requirePassphrase(passphrase);
@@ -70378,7 +70444,7 @@ function libsecretStore(platform2, run, installed) {
70378
70444
  requireSuccess(result, `store the passphrase of ${name} in the secret service`);
70379
70445
  },
70380
70446
  async remove(name) {
70381
- const existed = await lookup(name) !== void 0;
70447
+ const existed = await lookup2(name) !== void 0;
70382
70448
  const result = await run(SECRET_TOOL_BINARY, [
70383
70449
  "clear",
70384
70450
  "service",
@@ -71441,6 +71507,8 @@ var VAULT_KEY_ACCOUNT = "vault-key";
71441
71507
  var VAULT_SESSION_ACCOUNT = "vault-session";
71442
71508
  var DEVICE_KEY_LENGTH = 32;
71443
71509
  var DEFAULT_SESSION_HOURS = 8;
71510
+ var RESTORE_GAP_LIMIT = 5;
71511
+ var MAX_RESTORE_ACCOUNTS = 1e4;
71444
71512
  var BASE64_PATTERN = /^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$/u;
71445
71513
  var deviceKeyOperations = Promise.resolve();
71446
71514
  var sessionSchema = external_exports.object({
@@ -71590,26 +71658,41 @@ async function restoreVault(args) {
71590
71658
  throw new VaultError("corrupt", "That recovery phrase is not valid.", { cause: error61 });
71591
71659
  }
71592
71660
  let seed;
71593
- let discoveredAccounts = 0;
71661
+ if (args.accountCount !== void 0 && (!Number.isSafeInteger(args.accountCount) || args.accountCount < 1 || args.accountCount > MAX_RESTORE_ACCOUNTS)) {
71662
+ throw new VaultError(
71663
+ "corrupt",
71664
+ `Account count must be a positive integer no greater than ${MAX_RESTORE_ACCOUNTS}.`
71665
+ );
71666
+ }
71667
+ let discoveredAccounts = args.accountCount ?? 0;
71668
+ let scannedAddresses = 0;
71594
71669
  try {
71595
71670
  seed = phraseToSeed(phrase);
71596
71671
  } catch (error61) {
71597
71672
  throw asVaultError2(error61, "Unable to derive an account while restoring the vault.");
71598
71673
  }
71599
71674
  try {
71600
- for (let index2 = 0; ; index2 += 1) {
71675
+ for (let index2 = 0, emptyRun = 0; args.accountCount === void 0; index2 += 1) {
71601
71676
  let address4;
71602
71677
  try {
71603
71678
  address4 = privateKeyToAccount(deriveEvmPrivateKey(seed, `m/44'/60'/0'/0/${index2}`)).address;
71604
71679
  } catch (error61) {
71605
71680
  throw asVaultError2(error61, "Unable to derive an account while restoring the vault.");
71606
71681
  }
71607
- if (!await args.probe(address4)) break;
71608
- discoveredAccounts += 1;
71682
+ const funded = await args.probe(address4);
71683
+ scannedAddresses += 1;
71684
+ if (funded) {
71685
+ discoveredAccounts = index2 + 1;
71686
+ emptyRun = 0;
71687
+ } else {
71688
+ emptyRun += 1;
71689
+ if (emptyRun === RESTORE_GAP_LIMIT) break;
71690
+ }
71609
71691
  }
71610
71692
  } finally {
71611
71693
  seed.fill(0);
71612
71694
  }
71695
+ args.onScanComplete?.(scannedAddresses);
71613
71696
  let vault;
71614
71697
  try {
71615
71698
  vault = await createVault({ path: args.path, key: args.key, phrase, now: args.now });
@@ -72098,6 +72181,26 @@ var WalletStore = class _WalletStore {
72098
72181
  }
72099
72182
  );
72100
72183
  }
72184
+ /** Checks a cached signer's current vault session without decrypting its account again. */
72185
+ async assertSigningAuthority(name) {
72186
+ const stored = await this.readVaultUnlocked();
72187
+ if (!stored?.protected || !stored.accounts.some((account) => account.name === name)) return;
72188
+ try {
72189
+ const key2 = await unlockProtectedVault({
72190
+ path: this.vaultPath,
72191
+ secrets: this.secrets,
72192
+ env: this.environment,
72193
+ now: () => this.now()
72194
+ });
72195
+ key2.fill(0);
72196
+ } catch (error61) {
72197
+ this.dropVaultCache();
72198
+ if (error61 instanceof VaultError && error61.code === "password_required") {
72199
+ throw new KeystoreError(VAULT_LOCKED_MESSAGE, { cause: error61 });
72200
+ }
72201
+ throw error61;
72202
+ }
72203
+ }
72101
72204
  /** Returns one wallet's vault signer, migrating its legacy keystore if needed. */
72102
72205
  async unlock(name, passphrase) {
72103
72206
  const wallet = this.resolve({ name });
@@ -77484,7 +77587,7 @@ function createRunBudget(args) {
77484
77587
  import { mkdir as mkdir15, writeFile as writeFile8 } from "node:fs/promises";
77485
77588
  import { arch, platform, release } from "node:os";
77486
77589
  import { join as join13 } from "node:path";
77487
- var VAPI_CLIENT_VERSION = "0.9.0";
77590
+ var VAPI_CLIENT_VERSION = "0.9.4";
77488
77591
  async function createSupportReport(options) {
77489
77592
  const message = options.message.trim();
77490
77593
  if (!message) throw new Error("Support report message must not be empty.");
@@ -77757,7 +77860,7 @@ async function completeX402Payment(args) {
77757
77860
  let paidAttempt;
77758
77861
  const requestStarted = nowMs();
77759
77862
  try {
77760
- paidAttempt = await args.send(paidRequest);
77863
+ paidAttempt = await args.send(paidRequest, quote);
77761
77864
  } catch (error61) {
77762
77865
  if (trace) trace.phases.requestMs = elapsed(nowMs, requestStarted);
77763
77866
  throw settlementUnknown(
@@ -77775,7 +77878,7 @@ async function completeX402Payment(args) {
77775
77878
  const settleStarted = nowMs();
77776
77879
  const settlement = parseSettlementResponse(paidResponse.headers);
77777
77880
  const settlementOutcome = classifySettlement(settlement);
77778
- const receiptSettlement = sanitizeReceiptValue(settlement, receiptSecrets);
77881
+ const receiptSettlement = sanitizeReturnedValue(settlement, receiptSecrets);
77779
77882
  if (trace) {
77780
77883
  const transaction2 = settlementTransaction(receiptSettlement);
77781
77884
  const explorerUrl = transaction2 ? explorerTransactionUrl(quote.accepted.network, transaction2) : void 0;
@@ -77852,6 +77955,7 @@ async function completeX402Payment(args) {
77852
77955
  trace.phases.requestMs = (trace.phases.requestMs ?? 0) + elapsed(nowMs, bodyStarted);
77853
77956
  }
77854
77957
  }
77958
+ body = sanitizeReturnedValue(body, receiptSecrets);
77855
77959
  }
77856
77960
  const result = {
77857
77961
  response: paidResponse,
@@ -77860,7 +77964,11 @@ async function completeX402Payment(args) {
77860
77964
  quote,
77861
77965
  payer,
77862
77966
  ...payment.paymentId ? { paymentId: payment.paymentId } : {},
77863
- settlement,
77967
+ paymentProof: sanitizeReturnedValue(
77968
+ paidResponse.headers.get("x-vapi-payment-proof"),
77969
+ receiptSecrets
77970
+ ),
77971
+ settlement: receiptSettlement,
77864
77972
  settlementOutcome
77865
77973
  };
77866
77974
  if (settlementOutcome === "succeeded" && args.ceilingSweep) {
@@ -77997,19 +78105,70 @@ function sanitizeThrownError(error61, secrets) {
77997
78105
  }
77998
78106
  return new Error(message, cause === void 0 ? void 0 : { cause });
77999
78107
  }
78000
- function sanitizeReceiptValue(value, secrets, depth = 0) {
78108
+ function sanitizeReturnedValue(value, secrets) {
78001
78109
  if (typeof value === "string") return redactKnownSecrets(value, secrets);
78002
- if (value === null || typeof value !== "object") return value;
78003
- if (depth >= 16) return "[redacted nested settlement value]";
78004
- if (Array.isArray(value)) {
78005
- return value.map((item) => sanitizeReceiptValue(item, secrets, depth + 1));
78110
+ if (!isPlainReturnedContainer(value)) return value;
78111
+ const nodes = /* @__PURE__ */ new WeakMap();
78112
+ const ordered = [];
78113
+ const nodeFor = (source) => {
78114
+ const existing = nodes.get(source);
78115
+ if (existing) return existing;
78116
+ const copy = Array.isArray(source) ? new Array(source.length) : Object.create(Object.getPrototypeOf(source));
78117
+ const node2 = { source, copy, parents: /* @__PURE__ */ new Set(), changed: false };
78118
+ nodes.set(source, node2);
78119
+ ordered.push(node2);
78120
+ return node2;
78121
+ };
78122
+ const root = nodeFor(value);
78123
+ for (let index2 = 0; index2 < ordered.length; index2 += 1) {
78124
+ const node2 = ordered[index2];
78125
+ for (const [key2, item] of Object.entries(node2.source)) {
78126
+ const safeKey = Array.isArray(node2.source) ? key2 : redactKnownSecrets(key2, secrets);
78127
+ if (safeKey !== key2) node2.changed = true;
78128
+ if (typeof item === "string") {
78129
+ const safeItem = redactKnownSecrets(item, secrets);
78130
+ defineReturnedProperty(node2.copy, safeKey, safeItem);
78131
+ if (safeItem !== item) node2.changed = true;
78132
+ } else if (isPlainReturnedContainer(item)) {
78133
+ const child = nodeFor(item);
78134
+ child.parents.add(node2);
78135
+ defineReturnedProperty(node2.copy, safeKey, child.copy);
78136
+ } else {
78137
+ defineReturnedProperty(node2.copy, safeKey, item);
78138
+ }
78139
+ }
78006
78140
  }
78007
- return Object.fromEntries(
78008
- Object.entries(value).map(([key2, item]) => [
78009
- redactKnownSecrets(key2, secrets),
78010
- sanitizeReceiptValue(item, secrets, depth + 1)
78011
- ])
78012
- );
78141
+ const changed = ordered.filter((node2) => node2.changed);
78142
+ for (let index2 = 0; index2 < changed.length; index2 += 1) {
78143
+ for (const parent of changed[index2].parents) {
78144
+ if (parent.changed) continue;
78145
+ parent.changed = true;
78146
+ changed.push(parent);
78147
+ }
78148
+ }
78149
+ for (const node2 of ordered) {
78150
+ for (const [key2, item] of Object.entries(node2.source)) {
78151
+ if (!isPlainReturnedContainer(item)) continue;
78152
+ const safeKey = Array.isArray(node2.source) ? key2 : redactKnownSecrets(key2, secrets);
78153
+ const child = nodes.get(item);
78154
+ defineReturnedProperty(node2.copy, safeKey, child.changed ? child.copy : item);
78155
+ }
78156
+ }
78157
+ return root.changed ? root.copy : value;
78158
+ }
78159
+ function defineReturnedProperty(target, key2, value) {
78160
+ Object.defineProperty(target, key2, {
78161
+ value,
78162
+ enumerable: true,
78163
+ configurable: true,
78164
+ writable: true
78165
+ });
78166
+ }
78167
+ function isPlainReturnedContainer(value) {
78168
+ if (Array.isArray(value)) return true;
78169
+ if (value === null || typeof value !== "object") return false;
78170
+ const prototype = Object.getPrototypeOf(value);
78171
+ return prototype === Object.prototype || prototype === null;
78013
78172
  }
78014
78173
  function redactKnownSecrets(value, secrets) {
78015
78174
  let redacted = value;
@@ -78044,9 +78203,7 @@ function possibleSettlement(quote, payment, payer, receipt) {
78044
78203
  payTo: quote.accepted.payTo,
78045
78204
  payer,
78046
78205
  ...payment.paymentId ? { paymentId: payment.paymentId } : {},
78047
- ...isSvmPaymentRequirements(quote.accepted) ? {
78048
- authorizationTransaction: "transaction" in payment.payload.payload ? payment.payload.payload.transaction : ""
78049
- } : "authorization" in payment.payload.payload ? {
78206
+ ...isSvmPaymentRequirements(quote.accepted) ? {} : "authorization" in payment.payload.payload ? {
78050
78207
  authorizationNonce: payment.payload.payload.authorization.nonce,
78051
78208
  authorizationExpiresAt: payment.payload.payload.authorization.validBefore
78052
78209
  } : {},
@@ -78424,13 +78581,22 @@ async function sendRouterChat(deps, routerBaseUrl, routerKey, request, keyUsed)
78424
78581
  }
78425
78582
  const body = await responseText(response);
78426
78583
  if (!response.ok) {
78427
- if (response.status === 429 || body.includes("Budget has been exceeded") || body.includes("ExceededBudget")) {
78584
+ if (/budget (?:has been )?exceeded|exceededbudget/iu.test(body)) {
78428
78585
  throw new RouterClientError(
78429
78586
  "budget_exhausted",
78430
78587
  "The Router key has no remaining budget.",
78431
78588
  response.status
78432
78589
  );
78433
78590
  }
78591
+ if (response.status === 429) {
78592
+ const retryAfter = response.headers.get("retry-after")?.trim();
78593
+ const retrySeconds = retryAfter !== void 0 && /^\d+$/u.test(retryAfter) ? Number(retryAfter) : void 0;
78594
+ throw new RouterClientError(
78595
+ "rate_limited",
78596
+ `The vAPI Router is rate limited. ${retrySeconds !== void 0 && Number.isFinite(retrySeconds) ? `Retry after ${retrySeconds} seconds.` : "Wait and retry shortly."}`,
78597
+ response.status
78598
+ );
78599
+ }
78434
78600
  if (response.status === 401) {
78435
78601
  throw new RouterClientError(
78436
78602
  "no_router_key",
@@ -78997,6 +79163,7 @@ var missingTasksChain = {
78997
79163
 
78998
79164
  // ../core/src/tasks/types.ts
78999
79165
  var uuidSchema = external_exports.uuid();
79166
+ var profileIdSchema = external_exports.string().min(1).max(64).regex(/^[A-Za-z0-9_-]+$/);
79000
79167
  var isoDateTimeSchema = external_exports.iso.datetime();
79001
79168
  var addressSchema5 = external_exports.string().regex(/^0x[0-9a-fA-F]{40}$/).transform((value) => value.toLowerCase());
79002
79169
  var bytes32Schema = external_exports.string().regex(/^0x[0-9a-fA-F]{64}$/).transform((value) => value.toLowerCase());
@@ -79334,7 +79501,7 @@ var deliveryResponseSchema = external_exports.looseObject({
79334
79501
  version: external_exports.number().int().positive(),
79335
79502
  manifest: manifestResponseSchema,
79336
79503
  manifestHash: bytes32Schema,
79337
- submittedByProfileId: uuidSchema,
79504
+ submittedByProfileId: profileIdSchema,
79338
79505
  createdAt: isoDateTimeSchema
79339
79506
  });
79340
79507
  var orderDeliveryResponseSchema = external_exports.looseObject({
@@ -79440,7 +79607,7 @@ var reviewResponseSchema = external_exports.looseObject({
79440
79607
  id: uuidSchema,
79441
79608
  workOrderId: uuidSchema,
79442
79609
  clientAddress: addressSchema5,
79443
- vendorProfileId: uuidSchema,
79610
+ vendorProfileId: profileIdSchema,
79444
79611
  rating: external_exports.number().int().min(1).max(5),
79445
79612
  body: external_exports.string(),
79446
79613
  subRatings: external_exports.json().nullable(),
@@ -79983,12 +80150,15 @@ function createTasksClient(options) {
79983
80150
  const parsed2 = serverErrorSchema.safeParse(errorBody);
79984
80151
  const server = parsed2.success ? parsed2.data : void 0;
79985
80152
  const nested = typeof server?.error === "object" ? server.error : void 0;
79986
- const message = (typeof server?.error === "string" ? server.error : nested?.message) || server?.message || response.statusText || `HTTP ${response.status}`;
80153
+ const serverCode = nested?.code ?? server?.code;
80154
+ const serverMessage = (typeof server?.error === "string" ? server.error : nested?.message) || server?.message;
80155
+ const fallback = response.statusText || `HTTP ${response.status}`;
80156
+ const message = response.status === 401 || response.status === 403 ? serverCode ?? fallback : serverMessage || (errorBody === void 0 && raw.trim() ? raw.replace(/\s+/gu, " ").trim().slice(0, 300) : fallback);
79987
80157
  throw new TasksClientError(
79988
80158
  "http",
79989
80159
  message,
79990
80160
  response.status,
79991
- nested?.code ?? server?.code,
80161
+ serverCode,
79992
80162
  response.headers.get("Retry-After") ?? void 0
79993
80163
  );
79994
80164
  }
@@ -80391,9 +80561,10 @@ function safeTasksChainError(cause, broadcast, authorizationExposed, txHash) {
80391
80561
  let message = "Task chain operation failed.";
80392
80562
  if (cause instanceof TasksValidationError || cause instanceof TasksChainError)
80393
80563
  message = cause.message;
80394
- else if (cause instanceof TasksClientError)
80395
- message = `Tasks service request failed${cause.status === void 0 ? "" : ` (status ${cause.status})`}.`;
80396
- else if (cause instanceof Error) {
80564
+ else if (cause instanceof TasksClientError) {
80565
+ const code = cause.serverCode ?? (cause.status ? `http_${cause.status}` : cause.code);
80566
+ message = cause.status === 401 || cause.status === 403 ? `${code} (status ${cause.status})` : `${code}: ${cause.message}`;
80567
+ } else if (cause instanceof Error) {
80397
80568
  const short = "shortMessage" in cause && typeof cause.shortMessage === "string" ? cause.shortMessage : void 0;
80398
80569
  let statusCode;
80399
80570
  const seen = /* @__PURE__ */ new Set();
@@ -81201,6 +81372,44 @@ function createTasksChain(options) {
81201
81372
  return idempotencyKey;
81202
81373
  });
81203
81374
  }
81375
+ async function prepareOrResume(prepare, expected, idempotencyKey, kind, steps, authorizationExposed = false, beforeSign) {
81376
+ let prepared;
81377
+ let resumedFromServer = false;
81378
+ try {
81379
+ prepared = await prepare();
81380
+ } catch (error61) {
81381
+ if (!uncertainPreparation(error61)) throw error61;
81382
+ const fresh = await order(expected.milestone.workOrderId);
81383
+ const matches = fresh.milestones.filter((item) => item.id === expected.milestone.id);
81384
+ if (matches.length !== 1 || matches[0].workOrderId !== fresh.id)
81385
+ throw new TasksValidationError("The task milestone does not match its parent order.");
81386
+ const selected = matches[0];
81387
+ const operation = selected.chainOperation;
81388
+ if (expected.verb === "deliver" && selected.delivery && !operation)
81389
+ throw new TasksValidationError(
81390
+ "The server recorded this delivery but has no chain operation for it; open the task in the console to continue."
81391
+ );
81392
+ if (!operation || operation.kind !== kind || !(typeof steps === "string" ? [steps] : steps).includes(operation.step) || !["prepared", "submitted", "confirmed"].includes(operation.state))
81393
+ throw error61;
81394
+ if (expected.verb === "deliver" && selected.delivery && selected.delivery.manifestHash !== expected.manifestHash)
81395
+ throw new TasksValidationError(
81396
+ "The server recorded a different delivery manifest; refusing to continue."
81397
+ );
81398
+ prepared = {
81399
+ operation,
81400
+ milestone: { id: selected.id, workOrderId: selected.workOrderId }
81401
+ };
81402
+ resumedFromServer = true;
81403
+ }
81404
+ const result = await execute(
81405
+ prepared,
81406
+ expected,
81407
+ idempotencyKey,
81408
+ authorizationExposed,
81409
+ beforeSign
81410
+ );
81411
+ return resumedFromServer ? { ...result, resumedFromServer: true } : result;
81412
+ }
81204
81413
  async function verifyReceipt(operation, expected, hash5) {
81205
81414
  const rpc = rpcFor(expected.deployment.chainId);
81206
81415
  const receipt = await rpc.waitForTransactionReceipt({ hash: hash5, confirmations });
@@ -81242,6 +81451,7 @@ function createTasksChain(options) {
81242
81451
  throw new TasksValidationError(
81243
81452
  "The RPC transaction input does not match the verified task plan."
81244
81453
  );
81454
+ return receipt.blockNumber.toString();
81245
81455
  }
81246
81456
  async function retryConflict(call2) {
81247
81457
  let waited = 0;
@@ -81269,6 +81479,7 @@ function createTasksChain(options) {
81269
81479
  current = { ...initial, operation: live };
81270
81480
  let broadcast = current.operation.state === "submitted";
81271
81481
  let txHash = current.operation.transactionHash ?? void 0;
81482
+ let blockNumber;
81272
81483
  const operationId = initial.operation.id;
81273
81484
  function checkTransition(previous, next) {
81274
81485
  if (previous !== next && !(previous === "approve-usdc" && next === afterApproval))
@@ -81304,7 +81515,7 @@ function createTasksChain(options) {
81304
81515
  if (!operation.transactionHash)
81305
81516
  throw new TasksValidationError("The confirmed task operation has no transaction hash.");
81306
81517
  if (!checkpoint) {
81307
- await verifyReceipt(operation, expected, operation.transactionHash);
81518
+ blockNumber = await verifyReceipt(operation, expected, operation.transactionHash);
81308
81519
  await pending.complete(operation.id, operation.step, current);
81309
81520
  }
81310
81521
  const fresh = await order(expected.milestone.workOrderId);
@@ -81313,7 +81524,12 @@ function createTasksChain(options) {
81313
81524
  );
81314
81525
  if (!resultMilestone)
81315
81526
  throw new TasksValidationError("The reconciled task milestone is unavailable.");
81316
- return { txHash: operation.transactionHash, operation, milestone: resultMilestone };
81527
+ return {
81528
+ txHash: operation.transactionHash,
81529
+ operation,
81530
+ milestone: resultMilestone,
81531
+ blockNumber
81532
+ };
81317
81533
  }
81318
81534
  const rpc = rpcFor(expected.deployment.chainId);
81319
81535
  if (operation.state === "prepared") {
@@ -81509,7 +81725,7 @@ function createTasksChain(options) {
81509
81725
  }
81510
81726
  if (operation.state !== "submitted" || !operation.transactionHash)
81511
81727
  throw new TasksValidationError("The task operation has no submitted transaction.");
81512
- await verifyReceipt(operation, expected, operation.transactionHash);
81728
+ blockNumber = await verifyReceipt(operation, expected, operation.transactionHash);
81513
81729
  const reconciled = await retryConflict(
81514
81730
  () => client.reconcileOperation(
81515
81731
  operation.id,
@@ -81532,6 +81748,7 @@ function createTasksChain(options) {
81532
81748
  if (reconciled.operation.state !== "confirmed" && !(operation.step === "approve-usdc" && reconciled.operation.state === "prepared" && reconciled.operation.step === afterApproval))
81533
81749
  throw new TasksValidationError("The task transaction was not reconciled.");
81534
81750
  await pending.complete(operation.id, operation.step, reconciled);
81751
+ if (reconciled.operation.step !== operation.step) blockNumber = void 0;
81535
81752
  current = reconciled;
81536
81753
  }
81537
81754
  throw new TasksValidationError("The task operation exceeded its allowed step transitions.");
@@ -81566,14 +81783,16 @@ function createTasksChain(options) {
81566
81783
  );
81567
81784
  const prepareKey = await preparation(input2, verb, { evidenceHash: input2.evidenceHash });
81568
81785
  const call2 = verb === "dispute" ? client.disputeEscrow.bind(client) : client.counterEvidenceEscrow.bind(client);
81569
- return await execute(
81570
- await call2(
81786
+ return await prepareOrResume(
81787
+ () => call2(
81571
81788
  input2.escrowId,
81572
81789
  { evidenceHash: input2.evidenceHash },
81573
81790
  { idempotencyKey: prepareKey }
81574
81791
  ),
81575
81792
  { ...expected, evidenceHash: input2.evidenceHash },
81576
81793
  prepareKey,
81794
+ verb === "dispute" ? "escrow-dispute" : "escrow-counter-evidence",
81795
+ expected.steps,
81577
81796
  exposed,
81578
81797
  input2.beforeSign
81579
81798
  );
@@ -81593,11 +81812,34 @@ function createTasksChain(options) {
81593
81812
  await options.bindings.put(binding);
81594
81813
  },
81595
81814
  createEscrow: (input2) => safe(async () => {
81596
- const workOrder = await order(input2.orderId);
81815
+ let workOrder = await order(input2.orderId);
81597
81816
  const ready = await deployment();
81598
- const prepared = await client.createEscrow(input2.orderId, {
81599
- idempotencyKey: input2.idempotencyKey
81600
- });
81817
+ let prepared;
81818
+ let resumedFromServer = false;
81819
+ try {
81820
+ prepared = await client.createEscrow(input2.orderId, {
81821
+ idempotencyKey: input2.idempotencyKey
81822
+ });
81823
+ } catch (error61) {
81824
+ if (!uncertainPreparation(error61)) throw error61;
81825
+ const fresh = await order(input2.orderId);
81826
+ const candidates = fresh.milestones.filter((item) => {
81827
+ const previous = workOrder.milestones.find((prior) => prior.id === item.id);
81828
+ const operation = item.chainOperation;
81829
+ return item.workOrderId === input2.orderId && previous && operation && operation.kind === "escrow-create" && operation.step === "create-escrow" && (previous.escrowState === null || previous.chainOperation?.id === operation.id);
81830
+ });
81831
+ if (candidates.length !== 1) throw error61;
81832
+ const selected2 = candidates[0];
81833
+ prepared = {
81834
+ operation: selected2.chainOperation,
81835
+ milestone: {
81836
+ id: selected2.id,
81837
+ workOrderId: selected2.workOrderId
81838
+ }
81839
+ };
81840
+ workOrder = fresh;
81841
+ resumedFromServer = true;
81842
+ }
81601
81843
  const selected = workOrder.milestones.find((item) => item.id === prepared.milestone.id);
81602
81844
  if (!selected || selected.workOrderId !== input2.orderId)
81603
81845
  throw new TasksValidationError(
@@ -81607,11 +81849,12 @@ function createTasksChain(options) {
81607
81849
  { escrowId: selected.id, idempotencyKey: input2.idempotencyKey },
81608
81850
  "createEscrow"
81609
81851
  );
81610
- return await execute(
81852
+ const result = await execute(
81611
81853
  prepared,
81612
81854
  await expectation(selected, ready, "createEscrow", ["create-escrow"], input2.counterparty),
81613
81855
  prepareKey
81614
81856
  );
81857
+ return resumedFromServer ? { ...result, resumedFromServer: true } : result;
81615
81858
  }),
81616
81859
  async fund(input2) {
81617
81860
  let exposed = true;
@@ -81699,10 +81942,14 @@ function createTasksChain(options) {
81699
81942
  }
81700
81943
  exposed = true;
81701
81944
  await pending.markExposure(selected.id);
81702
- const prepared = await client.fundEscrow(input2.escrowId, body, {
81703
- idempotencyKey: prepareKey
81704
- });
81705
- return await execute(prepared, expected, prepareKey, exposed);
81945
+ return await prepareOrResume(
81946
+ () => client.fundEscrow(input2.escrowId, body, { idempotencyKey: prepareKey }),
81947
+ expected,
81948
+ prepareKey,
81949
+ "escrow-funding",
81950
+ expected.steps,
81951
+ exposed
81952
+ );
81706
81953
  } catch (cause) {
81707
81954
  throw chainError(cause, false, exposed);
81708
81955
  }
@@ -81727,22 +81974,26 @@ function createTasksChain(options) {
81727
81974
  manifest: frozen.manifest,
81728
81975
  note: input2.note
81729
81976
  });
81730
- const prepared = await client.deliverEscrow(
81731
- input2.escrowId,
81732
- { fileIds: frozen.manifest.files.map((file2) => file2.fileId), note: input2.note },
81733
- { idempotencyKey: prepareKey }
81734
- );
81735
- if (prepared.delivery.manifestHash !== frozen.manifestHash)
81736
- throw new TasksValidationError(
81737
- "The server task delivery manifest hash does not match the local manifest."
81738
- );
81739
- return await execute(
81740
- prepared,
81977
+ return await prepareOrResume(
81978
+ async () => {
81979
+ const prepared = await client.deliverEscrow(
81980
+ input2.escrowId,
81981
+ { fileIds: frozen.manifest.files.map((file2) => file2.fileId), note: input2.note },
81982
+ { idempotencyKey: prepareKey }
81983
+ );
81984
+ if (prepared.delivery.manifestHash !== frozen.manifestHash)
81985
+ throw new TasksValidationError(
81986
+ "The server task delivery manifest hash does not match the local manifest."
81987
+ );
81988
+ return prepared;
81989
+ },
81741
81990
  {
81742
81991
  ...expected,
81743
81992
  manifestHash: frozen.manifestHash
81744
81993
  },
81745
- prepareKey
81994
+ prepareKey,
81995
+ "escrow-delivery",
81996
+ "submit-delivery"
81746
81997
  );
81747
81998
  }),
81748
81999
  release: (input2) => safe(async () => {
@@ -81756,10 +82007,12 @@ function createTasksChain(options) {
81756
82007
  input2.counterparty
81757
82008
  );
81758
82009
  const prepareKey = await preparation(input2, "release");
81759
- return await execute(
81760
- await client.releaseEscrow(input2.escrowId, { idempotencyKey: prepareKey }),
82010
+ return await prepareOrResume(
82011
+ () => client.releaseEscrow(input2.escrowId, { idempotencyKey: prepareKey }),
81761
82012
  expected,
81762
- prepareKey
82013
+ prepareKey,
82014
+ "escrow-release",
82015
+ "release-funds"
81763
82016
  );
81764
82017
  }),
81765
82018
  refund: (input2) => safe(async () => {
@@ -81773,10 +82026,12 @@ function createTasksChain(options) {
81773
82026
  input2.counterparty
81774
82027
  );
81775
82028
  const prepareKey = await preparation(input2, "refund");
81776
- return await execute(
81777
- await client.refundEscrow(input2.escrowId, { idempotencyKey: prepareKey }),
82029
+ return await prepareOrResume(
82030
+ () => client.refundEscrow(input2.escrowId, { idempotencyKey: prepareKey }),
81778
82031
  expected,
81779
- prepareKey
82032
+ prepareKey,
82033
+ "escrow-release",
82034
+ "refund-buyer"
81780
82035
  );
81781
82036
  }),
81782
82037
  disputeFee: (input2) => safe(async () => {
@@ -81804,16 +82059,21 @@ function createTasksChain(options) {
81804
82059
  input2.counterparty
81805
82060
  );
81806
82061
  const prepareKey = await preparation(input2, "resolve-unmatched");
81807
- return execute(
81808
- await client.resolveUnmatchedEscrow(input2.escrowId, { idempotencyKey: prepareKey }),
82062
+ return prepareOrResume(
82063
+ () => client.resolveUnmatchedEscrow(input2.escrowId, { idempotencyKey: prepareKey }),
81809
82064
  expected,
81810
- prepareKey
82065
+ prepareKey,
82066
+ "escrow-unmatched-resolution",
82067
+ "resolve-unmatched-dispute"
81811
82068
  );
81812
82069
  }),
81813
82070
  signScopeMessage: (message) => safe(() => account.signMessage({ message }))
81814
82071
  };
81815
82072
  }
81816
82073
  var chainError = safeTasksChainError;
82074
+ function uncertainPreparation(error61) {
82075
+ return error61 instanceof TasksClientError && ((error61.status ?? 0) >= 400 || error61.code === "network" || error61.code === "timeout");
82076
+ }
81817
82077
  function retryDelay(header, now) {
81818
82078
  if (/^\d+(?:\.\d+)?$/u.test(header.trim())) return Math.max(1, Math.ceil(Number(header) * 1e3));
81819
82079
  const date5 = Date.parse(header);
@@ -81830,6 +82090,60 @@ function alreadySent(error61) {
81830
82090
  return error61 instanceof Error && /already known|known transaction|nonce (?:is )?too low/iu.test(error61.message);
81831
82091
  }
81832
82092
 
82093
+ // ../core/src/tasks/wait.ts
82094
+ async function waitForMilestone(client, input2) {
82095
+ const timeoutMs = input2.timeoutMs ?? 12e4;
82096
+ const intervalMs = input2.intervalMs ?? 3e3;
82097
+ if (!Number.isFinite(timeoutMs) || timeoutMs < 0)
82098
+ throw new RangeError("The milestone wait timeout must be non-negative and finite.");
82099
+ if (!Number.isFinite(intervalMs) || intervalMs <= 0)
82100
+ throw new RangeError("The milestone wait interval must be positive and finite.");
82101
+ const sleep = input2.sleep ?? ((ms) => new Promise((resolve2) => setTimeout(resolve2, ms)));
82102
+ const now = input2.now ?? (() => /* @__PURE__ */ new Date());
82103
+ const started = now().getTime();
82104
+ const deadline = started + timeoutMs;
82105
+ let polls = 0;
82106
+ let milestone;
82107
+ function result(reached) {
82108
+ return { reached, milestone, polls, elapsedMs: now().getTime() - started };
82109
+ }
82110
+ for (; ; ) {
82111
+ const remaining = deadline - now().getTime();
82112
+ if (remaining <= 0) return result(false);
82113
+ const controller = new AbortController();
82114
+ const timer = setTimeout(() => controller.abort(), remaining);
82115
+ let response;
82116
+ polls++;
82117
+ try {
82118
+ response = await client.getOrder(input2.orderId, { signal: controller.signal });
82119
+ } catch (error61) {
82120
+ if (controller.signal.aborted) return result(false);
82121
+ throw error61;
82122
+ } finally {
82123
+ clearTimeout(timer);
82124
+ }
82125
+ if (controller.signal.aborted || now().getTime() >= deadline) return result(false);
82126
+ const { workOrder } = response;
82127
+ milestone = workOrder.id === input2.orderId && workOrder.version === "work-order-view-v1" ? workOrder.milestones.find(
82128
+ (item) => item.id === input2.milestoneId && item.workOrderId === input2.orderId
82129
+ ) : void 0;
82130
+ if (milestone && reachedTarget(milestone, input2.target)) return result(true);
82131
+ await sleep(Math.min(intervalMs, deadline - now().getTime()));
82132
+ }
82133
+ }
82134
+ function reachedTarget(milestone, target) {
82135
+ switch (target) {
82136
+ case "created":
82137
+ return milestone.escrowState !== null;
82138
+ case "locked":
82139
+ return ["locked", "submitted", "disputed", "resolved"].includes(milestone.escrowState ?? "");
82140
+ case "delivered":
82141
+ return ["submitted", "disputed", "resolved"].includes(milestone.escrowState ?? "");
82142
+ case "released":
82143
+ return milestone.escrowState === "resolved";
82144
+ }
82145
+ }
82146
+
81833
82147
  // ../core/src/tasks/rpc.ts
81834
82148
  function createTasksRpcFor(config2, options = {}) {
81835
82149
  const clients = /* @__PURE__ */ new Map();
@@ -82946,7 +83260,10 @@ async function taskRequest(verb, route, operation, options) {
82946
83260
  "not_signed_in",
82947
83261
  `${verb} needs sign-in. ${options.signInHint}`
82948
83262
  );
82949
- throw new TaskOperationError(error61.serverCode ?? error61.code, error61.message);
83263
+ throw new TaskOperationError(
83264
+ error61.serverCode ?? (error61.status ? `http_${error61.status}` : error61.code),
83265
+ error61.message
83266
+ );
82950
83267
  }
82951
83268
  throw error61;
82952
83269
  }
@@ -83067,7 +83384,8 @@ function proposalTerms(id2, address4, deployment, terms) {
83067
83384
  return {
83068
83385
  version: "work-proposal-v1",
83069
83386
  workOrderId: id2,
83070
- providerAddress: address4,
83387
+ // The server lowercases addresses before canonicalizing the signed payload.
83388
+ providerAddress: address4.toLowerCase(),
83071
83389
  pricingModel: "fixed",
83072
83390
  milestones: [
83073
83391
  {
@@ -83454,6 +83772,55 @@ async function showTask(context, input2) {
83454
83772
  };
83455
83773
  }
83456
83774
  async function taskStatus(context, input2) {
83775
+ if (input2.signedIn) {
83776
+ const chainState = await taskRequest(
83777
+ "status",
83778
+ "chainState",
83779
+ async () => {
83780
+ try {
83781
+ return await context.client.chainState(input2.id);
83782
+ } catch (error61) {
83783
+ if (error61 instanceof TasksClientError && error61.status === 404) {
83784
+ if (isMissingTaskEntity(error61.serverCode, error61.message))
83785
+ throw new TaskOperationError("not_found", error61.message);
83786
+ throw new TaskOperationError(
83787
+ "not_available",
83788
+ "GET /v1/work-orders/:id/chain-state is not available on this server."
83789
+ );
83790
+ }
83791
+ throw error61;
83792
+ }
83793
+ },
83794
+ context
83795
+ );
83796
+ if (chainState.workOrderId !== input2.id)
83797
+ throw new TaskOperationError("invalid_response", "The response belongs to a different task.");
83798
+ const page = await taskRequest(
83799
+ "status",
83800
+ "events",
83801
+ async () => {
83802
+ try {
83803
+ return await context.client.events(input2.id, { wait: 0 });
83804
+ } catch (error61) {
83805
+ if (error61 instanceof TasksClientError && error61.status === 404) {
83806
+ if (isMissingTaskEntity(error61.serverCode, error61.message)) return null;
83807
+ throw new TaskOperationError(
83808
+ "not_available",
83809
+ "GET /v1/work-orders/:id/events is not available on this server."
83810
+ );
83811
+ }
83812
+ throw error61;
83813
+ }
83814
+ },
83815
+ context
83816
+ );
83817
+ return {
83818
+ task: { id: input2.id },
83819
+ chainState,
83820
+ events: page ? [...page.events].sort((a, b) => a.sequence - b.sequence) : null,
83821
+ nextAfter: page?.nextAfter ?? null
83822
+ };
83823
+ }
83457
83824
  const task = await taskRequest(
83458
83825
  "status",
83459
83826
  "publicTask",
@@ -83809,6 +84176,7 @@ var searchEventSchema = external_exports.strictObject({
83809
84176
  source: external_exports.string().min(1),
83810
84177
  latencyMs: external_exports.number().nonnegative().finite(),
83811
84178
  count: external_exports.number().int().nonnegative(),
84179
+ dropped: external_exports.number().int().nonnegative().optional(),
83812
84180
  error: external_exports.string().optional()
83813
84181
  })
83814
84182
  ),
@@ -86814,6 +87182,12 @@ function isRecord4(value) {
86814
87182
  return typeof value === "object" && value !== null && !Array.isArray(value);
86815
87183
  }
86816
87184
 
87185
+ // src/cli.ts
87186
+ import { spawn as spawn3 } from "node:child_process";
87187
+ import { stat as stat16 } from "node:fs/promises";
87188
+ import { join as join28 } from "node:path";
87189
+ import { createInterface as createInterface3 } from "node:readline/promises";
87190
+
86817
87191
  // ../core/src/member-bundle.ts
86818
87192
  var MEMBER_BUNDLE_MAX_BYTES = 32 * 1024;
86819
87193
  var REMOTE_BLOCKED_GRANTS = /* @__PURE__ */ new Set([
@@ -86880,7 +87254,7 @@ var memberBundleConfigSchema = external_exports.unknown().refine((value) => !has
86880
87254
  external_exports.strictObject({ usdc: external_exports.string() })
86881
87255
  ).refine(
86882
87256
  (networks) => Object.entries(networks).every(
86883
- ([id2, network]) => isMemberBundleNetwork(id2) && network.usdc === NETWORKS[id2].usdc
87257
+ ([id2, network]) => isMemberBundleNetwork(id2) && network.usdc === NETWORKS2[id2].usdc
86884
87258
  ),
86885
87259
  { message: "Expected the canonical USDC token of each network." }
86886
87260
  ).refine((networks) => Object.keys(networks).length === 1, {
@@ -86919,14 +87293,14 @@ function memberBundleConfig(owner, network) {
86919
87293
  return {
86920
87294
  discoveryUrl,
86921
87295
  marketplaceDiscoveryUrl,
86922
- networks: { [network]: { usdc: NETWORKS[network].usdc } }
87296
+ networks: { [network]: { usdc: NETWORKS2[network].usdc } }
86923
87297
  };
86924
87298
  }
86925
87299
  function headlessConfigFromBundle(config2) {
86926
87300
  const networks = {};
86927
87301
  for (const [id2, network] of Object.entries(config2.networks)) {
86928
87302
  if (!isMemberBundleNetwork(id2) || network === void 0) continue;
86929
- networks[id2] = { rpcUrl: NETWORKS[id2].publicRpcUrl, usdc: network.usdc };
87303
+ networks[id2] = { rpcUrl: NETWORKS2[id2].publicRpcUrl, usdc: network.usdc };
86930
87304
  }
86931
87305
  return configSchema.parse({
86932
87306
  discoveryUrl: config2.discoveryUrl,
@@ -87019,7 +87393,7 @@ function parseStoredTokens(value) {
87019
87393
  }
87020
87394
  }
87021
87395
  function isMemberBundleNetwork(id2) {
87022
- return Object.hasOwn(NETWORKS, id2) && typeof NETWORKS[id2].publicRpcUrl === "string";
87396
+ return Object.hasOwn(NETWORKS2, id2) && typeof NETWORKS2[id2].publicRpcUrl === "string";
87023
87397
  }
87024
87398
  function hasForbiddenConfigKey(value) {
87025
87399
  if (Array.isArray(value)) return value.some(hasForbiddenConfigKey);
@@ -87321,11 +87695,28 @@ async function searchMarketplace(input2, config2, fetchImpl, options = {}) {
87321
87695
  }
87322
87696
  }
87323
87697
  });
87324
- const page = marketplaceDiscoveryPageSchema.parse(await response.json());
87325
- mergedCount = page.items.length;
87698
+ const envelope = marketplaceDiscoveryEnvelopeSchema.parse(await response.json());
87699
+ const items = [];
87700
+ let dropped = 0;
87701
+ for (const [index2, rawItem] of envelope.items.entries()) {
87702
+ const parsed = marketplaceHitSchema.safeParse(rawItem);
87703
+ if (parsed.success) {
87704
+ items.push(parsed.data);
87705
+ continue;
87706
+ }
87707
+ dropped += 1;
87708
+ try {
87709
+ options.debug?.(`vAPI marketplace discovery dropped invalid row at index ${index2}.`);
87710
+ } catch {
87711
+ }
87712
+ }
87713
+ mergedCount = items.length;
87326
87714
  const attempt = attempts.at(-1);
87327
- if (attempt) attempt.count = mergedCount;
87328
- return page;
87715
+ if (attempt) {
87716
+ attempt.count = mergedCount;
87717
+ if (dropped > 0) attempt.dropped = dropped;
87718
+ }
87719
+ return { ...envelope, items };
87329
87720
  } finally {
87330
87721
  if (options.searchesPath) {
87331
87722
  await appendSearchEvent(
@@ -87451,6 +87842,34 @@ var VapiCallError = class extends Error {
87451
87842
  paymentRejection;
87452
87843
  confirmedSettlement;
87453
87844
  };
87845
+ var SOLANA_PAYMENTS_UNSUPPORTED_MESSAGE = "Solana payments are not supported in this version of vAPI yet; they arrive in a later release.";
87846
+ function isSolanaCaip2(network) {
87847
+ return network.startsWith("solana:");
87848
+ }
87849
+ function listingPaymentNetwork(endpointNetwork, serviceNetworks) {
87850
+ if (endpointNetwork !== void 0) return endpointNetwork;
87851
+ return serviceNetworks?.length && serviceNetworks.every(isSolanaCaip2) ? serviceNetworks[0] : void 0;
87852
+ }
87853
+ function assertSupportedListingNetwork(network) {
87854
+ if (network !== void 0 && isSolanaCaip2(network)) {
87855
+ throw new VapiCallError(
87856
+ "unsupported_network",
87857
+ `${SOLANA_PAYMENTS_UNSUPPORTED_MESSAGE} This listing pays on ${network}.`
87858
+ );
87859
+ }
87860
+ }
87861
+ function assertSupportedListingResolution(error61) {
87862
+ if (isDiscoveryCatalogError(error61) && error61.code === "ambiguous_default" && error61.paymentNetworks?.length && error61.paymentNetworks.every(isSolanaCaip2)) {
87863
+ assertSupportedListingNetwork(error61.paymentNetworks[0]);
87864
+ }
87865
+ }
87866
+ function payableConfig(config2, account) {
87867
+ if (account.solana !== void 0) return config2;
87868
+ const networks = Object.fromEntries(
87869
+ Object.entries(config2.networks).filter(([network]) => !isSolanaCaip2(network))
87870
+ );
87871
+ return { ...config2, networks };
87872
+ }
87454
87873
  var MAX_RESPONSE_BYTES = 1048576;
87455
87874
  var BODY_HEADER_NAMES = [
87456
87875
  "content-encoding",
@@ -87460,12 +87879,15 @@ var BODY_HEADER_NAMES = [
87460
87879
  "content-type"
87461
87880
  ];
87462
87881
  async function callService(args) {
87882
+ validateTimeoutSeconds(args.input.timeoutSeconds);
87463
87883
  const trace = createCallTrace(args);
87464
87884
  let execution;
87465
87885
  try {
87466
87886
  execution = await executeCallService(args, trace);
87467
87887
  } catch (error61) {
87468
- await recordCallError(args, error61, trace).catch(() => void 0);
87888
+ if (!(error61 instanceof VapiCallError && (error61.code === "unsupported_network" || error61.code === "unsupported_payment"))) {
87889
+ await recordCallError(args, error61, trace).catch(() => void 0);
87890
+ }
87469
87891
  throw error61;
87470
87892
  }
87471
87893
  try {
@@ -87513,10 +87935,16 @@ async function executeCallService(args, trace) {
87513
87935
  config2,
87514
87936
  fetchImpl
87515
87937
  );
87938
+ } catch (error61) {
87939
+ assertSupportedListingResolution(error61);
87940
+ throw error61;
87516
87941
  } finally {
87517
87942
  trace.phases.discoverMs = elapsed2(trace, discoverStarted);
87518
87943
  }
87519
87944
  }
87945
+ assertSupportedListingNetwork(
87946
+ listingPaymentNetwork(endpoint?.payment?.network, endpoint?.serviceNetworks)
87947
+ );
87520
87948
  const requestedNetwork = normalizeRequiredNetwork(input2.network);
87521
87949
  const listingNetwork = endpoint?.payment?.network;
87522
87950
  if (requestedNetwork && listingNetwork && !areSamePaymentNetwork(requestedNetwork, listingNetwork)) {
@@ -87571,6 +87999,8 @@ async function executeCallService(args, trace) {
87571
87999
  body: method === "GET" || method === "HEAD" ? void 0 : requestBody
87572
88000
  });
87573
88001
  const request = createRequest(headers);
88002
+ const probeTimeoutMs = input2.timeoutSeconds === void 0 ? args.timeoutMs ?? 3e4 : Math.min(input2.timeoutSeconds, 30) * 1e3;
88003
+ let requestTimeoutMs = probeTimeoutMs;
87574
88004
  const fetchWithGuardedRedirects = async (candidateRequest, followRedirects = true) => {
87575
88005
  let currentRequest = candidateRequest;
87576
88006
  let followedRedirects = 0;
@@ -87578,7 +88008,7 @@ async function executeCallService(args, trace) {
87578
88008
  const attempt = await fetchAttempt(
87579
88009
  fetchImpl,
87580
88010
  new Request(currentRequest.clone(), { redirect: "manual" }),
87581
- args.timeoutMs ?? 3e4
88011
+ requestTimeoutMs
87582
88012
  );
87583
88013
  const response = attempt.response;
87584
88014
  if (!isRedirectStatus2(response.status)) {
@@ -87732,8 +88162,13 @@ async function executeCallService(args, trace) {
87732
88162
  challenge: challengeAttempt,
87733
88163
  account,
87734
88164
  caps: args.spendCaps ?? config2.spendCaps,
87735
- config: config2,
87736
- send: async (paidRequest) => {
88165
+ config: payableConfig(config2, account),
88166
+ send: async (paidRequest, quote) => {
88167
+ requestTimeoutMs = paidRequestTimeoutMs(
88168
+ input2.timeoutSeconds,
88169
+ args.timeoutMs,
88170
+ quote.accepted.maxTimeoutSeconds
88171
+ );
87737
88172
  paidAttempt = await fetchWithGuardedRedirects(paidRequest, false);
87738
88173
  return paidAttempt;
87739
88174
  },
@@ -87772,7 +88207,7 @@ async function executeCallService(args, trace) {
87772
88207
  asset: completed.quote.accepted.asset,
87773
88208
  payTo: completed.quote.accepted.payTo,
87774
88209
  settlement: settlementWithExplorer2(completed.settlement, completed.quote.accepted.network),
87775
- proof: completed.response.headers.get("x-vapi-payment-proof")
88210
+ proof: completed.paymentProof
87776
88211
  },
87777
88212
  ...verificationFor(endpoint),
87778
88213
  ...expectedRequestFor(endpoint, completed.response.status)
@@ -87982,7 +88417,7 @@ async function resolveCallEndpoint(id2, endpointName, marketplaceHit, config2, f
87982
88417
  try {
87983
88418
  return registeredEndpoint(await resolveServiceListing(id2, config2, fetchImpl, endpointName));
87984
88419
  } catch (error61) {
87985
- if (!(error61 instanceof DiscoveryCatalogError) || error61.code !== "service_not_found") {
88420
+ if (!isDiscoveryCatalogError(error61) || error61.code !== "service_not_found") {
87986
88421
  throw error61;
87987
88422
  }
87988
88423
  const discovered = await findMarketplaceApiByRef(id2, config2, fetchImpl);
@@ -88019,9 +88454,18 @@ async function resolveCallEndpoint(id2, endpointName, marketplaceHit, config2, f
88019
88454
  );
88020
88455
  }
88021
88456
  function registeredEndpoint(listing, verification) {
88457
+ const { payment, ...endpoint } = listing.endpoint;
88458
+ if (payment && (typeof payment.protocol === "string" || typeof payment.network !== "string")) {
88459
+ throw new VapiCallError(
88460
+ "unsupported_payment",
88461
+ `Payment protocol ${payment.protocol} is not supported. This client pays x402 exact USDC endpoints only.`
88462
+ );
88463
+ }
88022
88464
  return {
88023
- ...listing.endpoint,
88465
+ ...endpoint,
88466
+ ...payment ? { payment: { network: payment.network, payTo: payment.payTo } } : {},
88024
88467
  verification: verification ?? listing.service.verification,
88468
+ serviceNetworks: listing.service.networks,
88025
88469
  registered: true,
88026
88470
  resolvedListing: true
88027
88471
  };
@@ -88181,7 +88625,7 @@ async function readResponseBody2(response) {
88181
88625
  async function fetchAttempt(fetchImpl, request, timeoutMs) {
88182
88626
  const controller = new AbortController();
88183
88627
  let rejectTimeout = null;
88184
- const timeoutError = new Error(`API request timed out after ${timeoutMs}ms.`);
88628
+ const timeoutError = new Error(`API request timed out after ${timeoutMs / 1e3} seconds.`);
88185
88629
  const timedOut = new Promise((_resolve, reject) => {
88186
88630
  rejectTimeout = reject;
88187
88631
  });
@@ -88221,6 +88665,19 @@ async function fetchAttempt(fetchImpl, request, timeoutMs) {
88221
88665
  throw error61;
88222
88666
  }
88223
88667
  }
88668
+ function validateTimeoutSeconds(timeoutSeconds) {
88669
+ if (timeoutSeconds !== void 0 && (!Number.isInteger(timeoutSeconds) || timeoutSeconds < 1 || timeoutSeconds > 300)) {
88670
+ throw new Error("call timeoutSeconds must be an integer from 1 to 300 seconds.");
88671
+ }
88672
+ }
88673
+ function paidRequestTimeoutMs(timeoutSeconds, internalTimeoutMs, offerTimeoutSeconds) {
88674
+ const usableOfferTimeout = Number.isInteger(offerTimeoutSeconds) && offerTimeoutSeconds > 0 ? offerTimeoutSeconds : void 0;
88675
+ if (timeoutSeconds !== void 0) {
88676
+ return Math.min(timeoutSeconds, usableOfferTimeout ?? timeoutSeconds) * 1e3;
88677
+ }
88678
+ if (internalTimeoutMs !== void 0) return internalTimeoutMs;
88679
+ return usableOfferTimeout === void 0 ? 12e4 : Math.min(12e4, Math.max(3e4, usableOfferTimeout * 1e3));
88680
+ }
88224
88681
  function mapX402PaymentError(error61, resumeId) {
88225
88682
  if (!(error61 instanceof X402PaymentError)) return error61;
88226
88683
  if (error61.code === "payment_rejected") {
@@ -88236,9 +88693,10 @@ function mapX402PaymentError(error61, resumeId) {
88236
88693
  });
88237
88694
  }
88238
88695
  const resume = resumeId !== void 0 && error61.possibleSettlement?.authorizationNonce ? ` Check whether it settled with \`vapi pay --resume ${resumeId}\` before paying again.` : "";
88696
+ const timeoutDetail = error61.cause instanceof Error && error61.cause.message.startsWith("API request timed out after ") ? `${error61.cause.message} ` : "";
88239
88697
  return new VapiCallError(
88240
88698
  "settlement_unknown",
88241
- `${error61.message}${resume}`,
88699
+ `${timeoutDetail}${error61.message}${resume}`,
88242
88700
  error61.possibleSettlement,
88243
88701
  { cause: error61.cause }
88244
88702
  );
@@ -88260,14 +88718,17 @@ async function inspectService(input2, config2, fetchImpl) {
88260
88718
  try {
88261
88719
  listing = await resolveServiceListing(input2.id, config2, fetchImpl, input2.endpoint);
88262
88720
  } catch (error61) {
88263
- if (input2.endpoint || !(error61 instanceof DiscoveryCatalogError) || error61.code !== "service_not_found") {
88721
+ assertSupportedListingResolution(error61);
88722
+ if (input2.endpoint || !isDiscoveryCatalogError(error61) || error61.code !== "service_not_found") {
88264
88723
  throw error61;
88265
88724
  }
88266
88725
  const hit = await findMarketplaceApiByRef(input2.id, config2, fetchImpl);
88267
88726
  if (!hit || hit.kind !== "api" || hit.provenance !== "indexed") throw error61;
88727
+ assertSupportedListingNetwork(hit.execution.network);
88268
88728
  return inspectIndexedHit(hit);
88269
88729
  }
88270
88730
  const { endpoint, service } = listing;
88731
+ assertSupportedListingNetwork(listingPaymentNetwork(endpoint.payment?.network, service.networks));
88271
88732
  return {
88272
88733
  name: endpoint.name,
88273
88734
  method: endpoint.method,
@@ -88367,13 +88828,7 @@ var inspectToolResultSchema = external_exports.object({
88367
88828
  liveness: listingLivenessSchema.optional(),
88368
88829
  conformance: listingConformanceSchema.optional(),
88369
88830
  identity: listingIdentitySchema.optional(),
88370
- payment: external_exports.object({
88371
- scheme: external_exports.literal("exact"),
88372
- network: external_exports.string(),
88373
- asset: external_exports.string(),
88374
- payTo: external_exports.string(),
88375
- checkedAt: external_exports.string()
88376
- }).nullable()
88831
+ payment: discoveryEndpointSchema.shape.payment.unwrap().nullable()
88377
88832
  });
88378
88833
  var callSearchInputSchema = external_exports.object({
88379
88834
  query: external_exports.string().trim().max(200).optional().describe("Capability, API, service, or request."),
@@ -88402,7 +88857,10 @@ var callPayInputSchema = external_exports.object({
88402
88857
  (value) => /^0x[0-9a-fA-F]{40}$/.test(value) || isSolanaAddress(value),
88403
88858
  "Expected an EVM or Solana address."
88404
88859
  ).optional(),
88405
- maxPriceUsd: external_exports.union([external_exports.number().nonnegative(), external_exports.string().regex(/^\d+(?:\.\d{1,6})?$/)]).optional()
88860
+ maxPriceUsd: external_exports.union([external_exports.number().nonnegative(), external_exports.string().regex(/^\d+(?:\.\d{1,6})?$/)]).optional(),
88861
+ timeoutSeconds: external_exports.number().int().min(1).max(300).optional().describe(
88862
+ "Seconds to wait for the paid response. Default: the provider's maxTimeoutSeconds, at most 120."
88863
+ )
88406
88864
  });
88407
88865
  var callSearch = defineAction({
88408
88866
  name: "call.search",
@@ -88665,7 +89123,7 @@ async function readResult(response, signal, secrets = []) {
88665
89123
  return {
88666
89124
  status: response.status,
88667
89125
  contentType: contentType === null ? null : redactKnownSecrets2(contentType, secrets),
88668
- body: sanitizeReturnedValue(await readResponseBody3(response, contentType, signal), secrets)
89126
+ body: sanitizeReturnedValue2(await readResponseBody3(response, contentType, signal), secrets)
88669
89127
  };
88670
89128
  }
88671
89129
  async function readResponseBody3(response, contentType, signal) {
@@ -88710,17 +89168,17 @@ function isJsonContentType2(value) {
88710
89168
  const mediaType = value?.split(";", 1)[0]?.trim().toLowerCase() ?? "";
88711
89169
  return mediaType === "application/json" || mediaType.endsWith("+json");
88712
89170
  }
88713
- function sanitizeReturnedValue(value, secrets, depth = 0) {
89171
+ function sanitizeReturnedValue2(value, secrets, depth = 0) {
88714
89172
  if (typeof value === "string") return redactKnownSecrets2(value, secrets);
88715
89173
  if (value === null || typeof value !== "object") return value;
88716
89174
  if (depth >= 16) return "[redacted nested response value]";
88717
89175
  if (Array.isArray(value)) {
88718
- return value.map((item) => sanitizeReturnedValue(item, secrets, depth + 1));
89176
+ return value.map((item) => sanitizeReturnedValue2(item, secrets, depth + 1));
88719
89177
  }
88720
89178
  return Object.fromEntries(
88721
89179
  Object.entries(value).map(([key2, item]) => [
88722
89180
  redactKnownSecrets2(key2, secrets),
88723
- sanitizeReturnedValue(item, secrets, depth + 1)
89181
+ sanitizeReturnedValue2(item, secrets, depth + 1)
88724
89182
  ])
88725
89183
  );
88726
89184
  }
@@ -92037,6 +92495,7 @@ var moneyParticipant = {
92037
92495
  "Checksummed 0x address of the other party, taken from tasks.show (the poster's clientAddress when you are the worker; the accepted proposal's providerAddress when you are the poster). The human must supply it; it is compared with the signed scope and stored as local consent. Without it tasks.sign refuses and no local party binding is created, so tasks.fund/deliver/release cannot run from this machine."
92038
92496
  ).optional()
92039
92497
  };
92498
+ var waitForIndexer = external_exports.boolean().default(true).describe("Wait up to 60 seconds for vAPI to index the chain result before returning.");
92040
92499
  var cursor = external_exports.number().int().nonnegative().max(Number.MAX_SAFE_INTEGER);
92041
92500
  function usdWithinEscrow(value, positive = false) {
92042
92501
  try {
@@ -92083,7 +92542,10 @@ var tasksPostTool = descriptor(
92083
92542
  deadline: external_exports.string(),
92084
92543
  intake: external_exports.enum(["proposals", "submissions"]).optional(),
92085
92544
  maxAwards: external_exports.number().int().min(TASK_LIMITS.maxAwardsMin).max(TASK_LIMITS.maxAwardsMax).optional(),
92086
- webhookUrl: httpsUrl.optional()
92545
+ webhookUrl: httpsUrl.optional(),
92546
+ vendor: external_exports.string().regex(/^0x[0-9a-fA-F]{40}$/u).describe(
92547
+ "Optional 0x address of a vendor to invite directly; the task is addressed to that wallet and shows up for them. Anyone may still propose."
92548
+ ).optional()
92087
92549
  }
92088
92550
  );
92089
92551
  var tasksProposeTool = descriptor(
@@ -92108,42 +92570,43 @@ var tasksAwardTool = descriptor(
92108
92570
  { ...participant, proposalId: id }
92109
92571
  );
92110
92572
  var tasksSignTool = descriptor(
92111
- "Does not move money. Sign the current counterparty scope locally after the human confirms the money direction via counterparty; a worker may also create the unfunded escrow with the local vault wallet.",
92112
- moneyParticipant
92573
+ "Signs the user's own task scope locally with the user's vault wallet after the human confirms the money direction via counterparty; a worker may also create the unfunded escrow; nothing is custodial. Does not move money. Waits up to 60 seconds for vAPI to index a created escrow by default.",
92574
+ { ...moneyParticipant, wait: waitForIndexer }
92113
92575
  );
92114
92576
  var tasksFundTool = descriptor(
92115
- "Moves money: locks the task amount in USDC escrow subject to the acting wallet's policy and daily cap. MCP cannot grant human approval; amounts above the approval threshold are refused with approval:true.",
92116
- moneyParticipant
92577
+ "Executes the user's own funding of this task from the user's vault wallet, within the spend policy the user configured; nothing is custodial. MCP cannot grant human approval; amounts above the approval threshold are refused with approval:true. Waits up to 60 seconds for vAPI to index the locked escrow by default.",
92578
+ { ...moneyParticipant, wait: waitForIndexer }
92117
92579
  );
92118
92580
  var tasksDeliverTool = descriptor(
92119
- "Does not move money. Upload local delivery files, freeze the manifest and record delivery with the local vault wallet.",
92581
+ "Does not move money. Upload local delivery files, freeze the manifest and record delivery with the local vault wallet. Waits up to 60 seconds for vAPI to index the delivery by default.",
92120
92582
  {
92121
92583
  ...moneyParticipant,
92584
+ wait: waitForIndexer,
92122
92585
  files: external_exports.array(localPath).min(TASK_LIMITS.deliveryFilesMin).max(TASK_LIMITS.deliveryFilesMax),
92123
92586
  note: external_exports.string().max(TASK_LIMITS.deliveryNoteMax).refine((value) => value.trim().length > 0)
92124
92587
  }
92125
92588
  );
92126
92589
  var tasksReleaseTool = descriptor(
92127
- "Moves money: pays the worker from escrow with the local vault wallet. Returns gross \xB7 fee \xB7 net using the deployed fee.",
92128
- moneyParticipant
92590
+ "Executes the user's own payment to the worker from task escrow with the user's vault wallet; nothing is custodial. Returns gross \xB7 fee \xB7 net using the deployed fee. Waits up to 60 seconds for vAPI to index the release by default.",
92591
+ { ...moneyParticipant, wait: waitForIndexer }
92129
92592
  );
92130
92593
  var tasksRefundTool = descriptor(
92131
- "Moves money: returns escrowed USDC to the poster with the local vault wallet. Returns gross \xB7 fee \xB7 net using the deployed fee.",
92594
+ "Executes the user's own refund of escrowed USDC to the poster with the user's vault wallet; nothing is custodial. Returns gross \xB7 fee \xB7 net using the deployed fee.",
92132
92595
  moneyParticipant
92133
92596
  );
92134
92597
  var tasksDisputeTool = descriptor(
92135
- "Moves money: approves the verified dispute fee and raises a dispute with the local vault wallet. Applies task and daily caps; MCP refuses human approval with approval:true. Accepts a precomputed evidence hash.",
92598
+ "Executes the user's own approval of the verified dispute fee and raises a dispute with the user's vault wallet; nothing is custodial. Applies task and daily caps; MCP refuses human approval with approval:true. Accepts a precomputed evidence hash.",
92136
92599
  {
92137
92600
  ...moneyParticipant,
92138
92601
  evidenceHash: external_exports.string().regex(TASK_LIMITS.disputeEvidenceHash)
92139
92602
  }
92140
92603
  );
92141
92604
  var tasksCounterEvidenceTool = descriptor(
92142
- "Moves money: approves the verified dispute fee and submits counter-evidence as the non-opener before the onchain deadline. Applies task and daily caps; MCP refuses human approval with approval:true.",
92605
+ "Executes the user's own counter-evidence submission and approval of the verified dispute fee with the user's vault wallet as the non-opener before the onchain deadline; nothing is custodial. Applies task and daily caps; MCP refuses human approval with approval:true.",
92143
92606
  { ...moneyParticipant, evidenceHash: external_exports.string().regex(TASK_LIMITS.disputeEvidenceHash) }
92144
92607
  );
92145
92608
  var tasksResolveUnmatchedTool = descriptor(
92146
- "Moves money: resolves an unmatched dispute after the onchain counter-evidence deadline when no counter-evidence was submitted.",
92609
+ "Executes the user's own resolution of an unmatched dispute with the user's vault wallet after the onchain counter-evidence deadline when no counter-evidence was submitted; nothing is custodial.",
92147
92610
  moneyParticipant
92148
92611
  );
92149
92612
  var tasksMessageTool = descriptor(
@@ -92167,8 +92630,8 @@ var tasksWatchTool = descriptor(
92167
92630
  }
92168
92631
  );
92169
92632
  var tasksStatusTool = descriptor(
92170
- "Does not move money. Read the public task card and receipt URL when settled; sign-in is not required.",
92171
- { id }
92633
+ "Does not move money. Read signed-in chain state and participant events, or the public task card without sign-in.",
92634
+ participant
92172
92635
  );
92173
92636
  var signInHint = "Call auth.link for the acting wallet.";
92174
92637
  function lazyTasksChain(factory, pending) {
@@ -92308,6 +92771,22 @@ function createTasksTools(options) {
92308
92771
  };
92309
92772
  };
92310
92773
  }
92774
+ async function waitAfterChain(ctx, orderId, milestoneId, target) {
92775
+ return await taskRequest(
92776
+ target,
92777
+ "getOrder",
92778
+ () => waitForMilestone(ctx.client, {
92779
+ orderId,
92780
+ milestoneId,
92781
+ target,
92782
+ timeoutMs: 6e4,
92783
+ intervalMs: 3e3,
92784
+ ...options.sleep === void 0 ? {} : { sleep: options.sleep },
92785
+ now
92786
+ }),
92787
+ ctx
92788
+ );
92789
+ }
92311
92790
  async function feeAction(verb, input2) {
92312
92791
  const ctx = await acting(input2.wallet);
92313
92792
  const policy = await taskPolicyForWallet({
@@ -92350,7 +92829,12 @@ function createTasksTools(options) {
92350
92829
  throw new TaskInputError("deadline must be at least 10 minutes from now.");
92351
92830
  const ctx = await acting(input2.wallet);
92352
92831
  const outcome = await postTask(ctx, {
92353
- order: { title: input2.title, description: input2.brief, policyFamily: "general-digital" },
92832
+ order: {
92833
+ title: input2.title,
92834
+ description: input2.brief,
92835
+ policyFamily: "general-digital",
92836
+ ...input2.vendor === void 0 ? {} : { invitedProviderAddress: input2.vendor }
92837
+ },
92354
92838
  amount: parseUsdToBaseUnits(input2.amountUsd),
92355
92839
  deadlineAt: new Date(postedAt.getTime() + deadlineDuration).toISOString(),
92356
92840
  ...input2.intake === void 0 ? {} : { intake: input2.intake },
@@ -92408,15 +92892,15 @@ function createTasksTools(options) {
92408
92892
  const ctx = await acting(input2.wallet);
92409
92893
  const signerAddress = (await options.session.addressesFor(ctx.selected.name)).address;
92410
92894
  try {
92411
- return taskResult(
92412
- await signTaskScope(ctx, {
92413
- id: input2.id,
92414
- counterparty: input2.counterparty,
92415
- signerAddress,
92416
- bindings: createScopeBindings(home),
92417
- signMessage: async (message) => (await unlock(ctx.selected.name)()).signMessage(message)
92418
- })
92419
- );
92895
+ const outcome = await signTaskScope(ctx, {
92896
+ id: input2.id,
92897
+ counterparty: input2.counterparty,
92898
+ signerAddress,
92899
+ bindings: createScopeBindings(home),
92900
+ signMessage: async (message) => (await unlock(ctx.selected.name)()).signMessage(message)
92901
+ });
92902
+ const wait2 = input2.wait && outcome.escrowCreation ? await waitAfterChain(ctx, input2.id, outcome.escrowCreation.milestone.id, "created") : null;
92903
+ return taskResult({ ...outcome, wait: wait2 });
92420
92904
  } catch (error61) {
92421
92905
  if (!(error61 instanceof TasksScopeCreationError)) throw error61;
92422
92906
  try {
@@ -92452,28 +92936,31 @@ function createTasksTools(options) {
92452
92936
  // Stdio has no human approval channel. Model arguments cannot grant approval.
92453
92937
  approval: { granted: false }
92454
92938
  });
92455
- return taskResult(outcome, !outcome.ok);
92939
+ const wait2 = input2.wait && outcome.ok ? await waitAfterChain(ctx, input2.id, outcome.result.milestone.id, "locked") : null;
92940
+ return taskResult({ ...outcome, wait: wait2 }, !outcome.ok);
92456
92941
  },
92457
92942
  async deliver(input2) {
92458
92943
  const files = (await Promise.all(input2.files.map(readTaskFile))).map(
92459
92944
  ({ fileName: name, bytes, contentType }) => ({ name, bytes, contentType })
92460
92945
  );
92461
- return taskResult(
92462
- await deliverTaskOperation(await acting(input2.wallet), {
92463
- id: input2.id,
92464
- ...input2.counterparty === void 0 ? {} : { counterparty: input2.counterparty },
92465
- files,
92466
- note: input2.note
92467
- })
92468
- );
92946
+ const ctx = await acting(input2.wallet);
92947
+ const outcome = await deliverTaskOperation(ctx, {
92948
+ id: input2.id,
92949
+ ...input2.counterparty === void 0 ? {} : { counterparty: input2.counterparty },
92950
+ files,
92951
+ note: input2.note
92952
+ });
92953
+ const wait2 = input2.wait ? await waitAfterChain(ctx, input2.id, outcome.result.milestone.id, "delivered") : null;
92954
+ return taskResult({ ...outcome, wait: wait2 });
92469
92955
  },
92470
92956
  async release(input2) {
92471
- return taskResult(
92472
- await releaseTaskOperation(await acting(input2.wallet), {
92473
- id: input2.id,
92474
- ...input2.counterparty === void 0 ? {} : { counterparty: input2.counterparty }
92475
- })
92476
- );
92957
+ const ctx = await acting(input2.wallet);
92958
+ const outcome = await releaseTaskOperation(ctx, {
92959
+ id: input2.id,
92960
+ ...input2.counterparty === void 0 ? {} : { counterparty: input2.counterparty }
92961
+ });
92962
+ const wait2 = input2.wait ? await waitAfterChain(ctx, input2.id, outcome.result.milestone.id, "released") : null;
92963
+ return taskResult({ ...outcome, wait: wait2 });
92477
92964
  },
92478
92965
  async refund(input2) {
92479
92966
  return taskResult(
@@ -92540,7 +93027,11 @@ function createTasksTools(options) {
92540
93027
  }
92541
93028
  },
92542
93029
  async status(input2) {
92543
- return taskResult(await taskStatus(await context(void 0, true), { id: input2.id }));
93030
+ await options.wallets?.reload();
93031
+ const publicOnly = input2.wallet === void 0 && options.session.activeName === void 0 && options.wallets !== void 0 && options.wallets.names().length === 0;
93032
+ const candidate = await context(input2.wallet, publicOnly);
93033
+ const ctx = candidate.token || publicOnly ? candidate : await context(void 0, true);
93034
+ return taskResult(await taskStatus(ctx, { id: input2.id, signedIn: Boolean(ctx.token) }));
92544
93035
  }
92545
93036
  };
92546
93037
  }
@@ -93297,6 +93788,11 @@ var statsToolResultSchema = external_exports.object({
93297
93788
  )
93298
93789
  })
93299
93790
  });
93791
+ function objectOutputSchema(schema) {
93792
+ if (!schema) return {};
93793
+ const json2 = external_exports.toJSONSchema(schema);
93794
+ return json2.type === "object" ? { outputSchema: json2 } : {};
93795
+ }
93300
93796
  var VapiMcpServer = class {
93301
93797
  #tools = /* @__PURE__ */ new Map();
93302
93798
  #onClose;
@@ -93320,7 +93816,7 @@ var VapiMcpServer = class {
93320
93816
  name,
93321
93817
  ...tool.description ? { description: tool.description } : {},
93322
93818
  inputSchema: external_exports.toJSONSchema(tool.inputSchema),
93323
- ...tool.outputSchema ? { outputSchema: external_exports.toJSONSchema(tool.outputSchema) } : {}
93819
+ ...objectOutputSchema(tool.outputSchema)
93324
93820
  }))
93325
93821
  };
93326
93822
  }
@@ -94188,7 +94684,13 @@ function toolError(error61) {
94188
94684
  {
94189
94685
  error: error61.message,
94190
94686
  code: error61.code,
94191
- ...error61.possibleSettlement ? { possibleSettlement: error61.possibleSettlement } : {},
94687
+ ...error61.possibleSettlement ? {
94688
+ possibleSettlement: Object.fromEntries(
94689
+ Object.entries(error61.possibleSettlement).filter(
94690
+ ([key2]) => key2 !== "authorizationTransaction"
94691
+ )
94692
+ )
94693
+ } : {},
94192
94694
  ...error61.paymentRejection ? { paymentRejection: error61.paymentRejection } : {},
94193
94695
  ...error61.confirmedSettlement ? { confirmedSettlement: error61.confirmedSettlement } : {}
94194
94696
  },
@@ -97682,7 +98184,7 @@ async function readProcessStdin() {
97682
98184
  }
97683
98185
 
97684
98186
  // src/version.ts
97685
- var CLI_VERSION = "0.9.0";
98187
+ var CLI_VERSION = "0.9.4";
97686
98188
 
97687
98189
  // src/status.ts
97688
98190
  async function statusCommand(argv, json2, io, dependencies) {
@@ -101184,7 +101686,7 @@ function createLocalRuntime(options) {
101184
101686
  const processCommand = options.processCommand ?? defaultProcessCommand;
101185
101687
  const ownsProcess = (handle, pid) => processCommand(pid)?.includes(runResultPath(home, handle.runId)) === true;
101186
101688
  const closeFd = options.closeFd ?? closeSync2;
101187
- const readFile29 = options.readFile ?? nodeReadFile;
101689
+ const readFile30 = options.readFile ?? nodeReadFile;
101188
101690
  const now = options.now ?? (() => /* @__PURE__ */ new Date());
101189
101691
  const openLog = options.openLog ?? ((path) => {
101190
101692
  mkdirSync2(runsDirectory(home), { recursive: true, mode: 448 });
@@ -101239,7 +101741,7 @@ function createLocalRuntime(options) {
101239
101741
  return handle;
101240
101742
  },
101241
101743
  async status(handle) {
101242
- const result = await readResultFile(readFile29, runResultPath(home, handle.runId));
101744
+ const result = await readResultFile(readFile30, runResultPath(home, handle.runId));
101243
101745
  if (result !== void 0) return result;
101244
101746
  const pid = localPid(handle);
101245
101747
  if (pid === void 0 || handle.kind !== "local") {
@@ -101342,10 +101844,10 @@ function childArguments(member, run) {
101342
101844
  ...run.drawUsd ? ["--draw", run.drawUsd] : []
101343
101845
  ];
101344
101846
  }
101345
- async function readResultFile(readFile29, path) {
101847
+ async function readResultFile(readFile30, path) {
101346
101848
  let text;
101347
101849
  try {
101348
- text = await readFile29(path, "utf8");
101850
+ text = await readFile30(path, "utf8");
101349
101851
  } catch (error61) {
101350
101852
  if (hasCode3(error61, "ENOENT")) return void 0;
101351
101853
  return { state: "failed", detail: "unreadable result file" };
@@ -102195,7 +102697,7 @@ function isMcpInstallApp(value) {
102195
102697
  function serverEntry(home, registry2) {
102196
102698
  return {
102197
102699
  command: "npx",
102198
- args: ["-y", "vapi-network", "mcp"],
102700
+ args: ["-y", "vapi-network@latest", "mcp"],
102199
102701
  env: { VAPI_HOME: home, VAPI_REGISTRY_URL: registry2 }
102200
102702
  };
102201
102703
  }
@@ -102244,7 +102746,7 @@ function tomlConfig(existing, entry) {
102244
102746
  const block = [
102245
102747
  "[mcp_servers.vapi]",
102246
102748
  'command = "npx"',
102247
- 'args = ["-y", "vapi-network", "mcp"]',
102749
+ 'args = ["-y", "vapi-network@latest", "mcp"]',
102248
102750
  `env = { VAPI_HOME = "${escapeToml(entry.env.VAPI_HOME)}", VAPI_REGISTRY_URL = "${escapeToml(entry.env.VAPI_REGISTRY_URL)}" }`,
102249
102751
  ""
102250
102752
  ].join("\n");
@@ -102411,13 +102913,13 @@ async function sendConfig(dependencies) {
102411
102913
  // src/setup.ts
102412
102914
  import { rm as rm5 } from "node:fs/promises";
102413
102915
  import { join as join26 } from "node:path";
102414
- var SETUP_ARGUMENT_ERROR = "vapi setup accepts only --no-cloud-backup; a recovery phrase is typed at the prompt, never passed on the command line.";
102916
+ var SETUP_ARGUMENT_ERROR = `vapi setup accepts only --no-cloud-backup and --accounts <n> (1-${MAX_RESTORE_ACCOUNTS}); a recovery phrase is typed at the prompt, never passed on the command line.`;
102415
102917
  var VAULT_CHOICE = "Create a new vault, or restore one from a recovery phrase? [new/restore] ";
102416
102918
  async function setupCommand(argv, json2, io, dependencies) {
102417
102919
  let parsed;
102418
102920
  try {
102419
102921
  parsed = parseArguments(argv, {
102420
- valueOptions: /* @__PURE__ */ new Set(),
102922
+ valueOptions: /* @__PURE__ */ new Set(["--accounts"]),
102421
102923
  booleanOptions: /* @__PURE__ */ new Set(["--no-cloud-backup"]),
102422
102924
  maximumPositionals: 0
102423
102925
  });
@@ -102428,6 +102930,7 @@ async function setupCommand(argv, json2, io, dependencies) {
102428
102930
  const paths = getVapiPaths();
102429
102931
  const steps = [];
102430
102932
  const humanIo = json2 ? stderrIo(io) : io;
102933
+ const accountCount = parseAccountCount(parsed.one("--accounts"));
102431
102934
  if (!await fileExists2(paths.config)) {
102432
102935
  await writeDefaultConfig(paths.config, process.env, { networks: ["base"] });
102433
102936
  steps.push("config");
@@ -102438,6 +102941,7 @@ async function setupCommand(argv, json2, io, dependencies) {
102438
102941
  let changedVault = false;
102439
102942
  let changedAccount = false;
102440
102943
  let changedLink = false;
102944
+ let scannedAddresses;
102441
102945
  if (!await fileExists2(join26(paths.directory, "vault.json"))) {
102442
102946
  const choice = await vaultChoice(dependencies);
102443
102947
  if (choice === "restore") {
@@ -102445,12 +102949,14 @@ async function setupCommand(argv, json2, io, dependencies) {
102445
102949
  throw new Error("Restoring needs a terminal to type the phrase.");
102446
102950
  }
102447
102951
  const readSecret = dependencies.prompts?.secret ?? promptForSecret;
102448
- await restoreVaultFromPhrase(
102952
+ const restored = await restoreVaultFromPhrase(
102449
102953
  await readSecret("Recovery phrase: "),
102450
102954
  config2,
102451
102955
  humanIo,
102452
- dependencies
102956
+ dependencies,
102957
+ accountCount
102453
102958
  );
102959
+ scannedAddresses = restored.scannedAddresses;
102454
102960
  store = await WalletStore.open(paths.directory, {
102455
102961
  secrets: getSecretStore(dependencies),
102456
102962
  env: dependencies.env ?? process.env,
@@ -102503,22 +103009,35 @@ async function setupCommand(argv, json2, io, dependencies) {
102503
103009
  }
102504
103010
  if (json2) {
102505
103011
  io.stdout(
102506
- JSON.stringify({ vault, account, address: address4, linked, steps, cloudBackup })
103012
+ JSON.stringify({
103013
+ vault,
103014
+ account,
103015
+ address: address4,
103016
+ linked,
103017
+ steps,
103018
+ cloudBackup,
103019
+ ...scannedAddresses === void 0 ? {} : { scannedAddresses }
103020
+ })
102507
103021
  );
102508
103022
  }
102509
103023
  }
102510
- async function restoreVaultFromPhrase(phrase, config2, io, dependencies) {
103024
+ async function restoreVaultFromPhrase(phrase, config2, io, dependencies, accountCount) {
102511
103025
  const paths = getVapiPaths();
102512
103026
  const validatedPhrase = validateRecoveryPhrase(phrase);
102513
103027
  const readBalance3 = baseUsdcBalanceReader(config2, dependencies);
102514
103028
  const key2 = await loadOrCreateDeviceKey({ secrets: getSecretStore(dependencies) });
102515
103029
  let names;
103030
+ let scannedAddresses = 0;
102516
103031
  try {
102517
103032
  const restored = await restoreVault({
102518
103033
  path: join26(paths.directory, "vault.json"),
102519
103034
  key: key2,
102520
103035
  phrase: validatedPhrase,
102521
103036
  probe: async (address4) => await readBalance3(address4) > 0n,
103037
+ ...accountCount === void 0 ? {} : { accountCount },
103038
+ onScanComplete: (count) => {
103039
+ scannedAddresses = count;
103040
+ },
102522
103041
  ...dependencies.now === void 0 ? {} : { now: dependencies.now }
102523
103042
  });
102524
103043
  names = restored.accounts().map((account) => account.name);
@@ -102530,8 +103049,25 @@ async function restoreVaultFromPhrase(phrase, config2, io, dependencies) {
102530
103049
  ...names[0] === void 0 ? {} : { wallet: names[0] },
102531
103050
  detail: `${names.length} account(s)`
102532
103051
  });
102533
- io.stdout(`Vault restored with ${names.length} account(s): ${names.join(", ")}`);
102534
- return { names };
103052
+ io.stdout(
103053
+ `Vault restored with ${names.length} account(s): ${names.join(", ")}. ${scannedAddresses} address(es) scanned.`
103054
+ );
103055
+ return { names, scannedAddresses };
103056
+ }
103057
+ function parseAccountCount(value) {
103058
+ if (value === void 0) return void 0;
103059
+ if (!/^\d+$/u.test(value)) {
103060
+ throw new UsageError(
103061
+ `--accounts must be a positive integer no greater than ${MAX_RESTORE_ACCOUNTS}.`
103062
+ );
103063
+ }
103064
+ const count = Number(value);
103065
+ if (!Number.isSafeInteger(count) || count < 1 || count > MAX_RESTORE_ACCOUNTS) {
103066
+ throw new UsageError(
103067
+ `--accounts must be a positive integer no greater than ${MAX_RESTORE_ACCOUNTS}.`
103068
+ );
103069
+ }
103070
+ return count;
102535
103071
  }
102536
103072
  async function vaultChoice(dependencies) {
102537
103073
  const answer = dependencies.prompts?.line === void 0 ? isInteractive(dependencies) ? await promptForLine(VAULT_CHOICE) : "" : await dependencies.prompts.line(VAULT_CHOICE);
@@ -102631,10 +103167,10 @@ var TASK_HELP = `Usage:
102631
103167
  vapi task propose <id> --price <usd> --duration <duration> --note <text> [--account <name>] [--json]
102632
103168
  vapi task submit <id> --proof <https-url> [--proof <https-url>...] [--file <path>...] [--account <name>] [--json]
102633
103169
  vapi task award <id> <proposalId> [--account <name>] [--json]
102634
- vapi task sign <id> [--yes] [--counterparty <0x\u2026>] [--account <name>] [--json]
102635
- vapi task fund <id> [--yes] [--counterparty <0x\u2026>] [--account <name>] [--json]
102636
- vapi task deliver <id> --files <path...> --note <text> [--counterparty <0x\u2026>] [--account <name>] [--json]
102637
- vapi task release <id> [--counterparty <0x\u2026>] [--account <name>] [--json]
103170
+ vapi task sign <id> [--yes] [--no-wait] [--timeout 120s] [--counterparty <0x\u2026>] [--account <name>] [--json]
103171
+ vapi task fund <id> [--yes] [--no-wait] [--timeout 120s] [--counterparty <0x\u2026>] [--account <name>] [--json]
103172
+ vapi task deliver <id> --files <path...> --note <text> [--no-wait] [--timeout 120s] [--counterparty <0x\u2026>] [--account <name>] [--json]
103173
+ vapi task release <id> [--no-wait] [--timeout 120s] [--counterparty <0x\u2026>] [--account <name>] [--json]
102638
103174
  vapi task refund <id> [--counterparty <0x\u2026>] [--account <name>] [--json]
102639
103175
  vapi task dispute <id> --evidence-hash <0x + 64 hex> [--yes] [--counterparty <0x\u2026>] [--account <name>] [--json]
102640
103176
  vapi task counter-evidence <id> --evidence-hash <0x + 64 hex> [--yes] [--counterparty <0x\u2026>] [--account <name>] [--json]
@@ -102657,23 +103193,25 @@ Exit codes:
102657
103193
  2 policy refusal only (JSON ok:false with reason policy.perTask or policy.perDay)
102658
103194
  3 approval needed in non-interactive mode
102659
103195
 
102660
- Fund, deliver, release, refund, dispute, counter-evidence, resolve-unmatched and watch auto-release sign with the local vault wallet. The CLI waits for two confirmations and records pending transactions for recovery. It never retries a chain mutation automatically.`;
103196
+ Fund, deliver, release, refund, dispute, counter-evidence, resolve-unmatched and watch auto-release sign with the local vault wallet. The CLI waits for two confirmations and records pending transactions for recovery. It never retries a chain mutation automatically. Sign, fund, deliver and release wait up to 120s for vAPI to index a confirmed transaction unless --no-wait is set; an indexing timeout keeps exit code 0.`;
102661
103197
  var IMPLEMENTED_VERBS = TASKS_CLIENT_VERBS;
102662
103198
  var USAGE = `Usage: vapi task <${IMPLEMENTED_VERBS.join("|")}>. Run vapi task --help.`;
102663
103199
  var TaskCommandError = class extends Error {
102664
- constructor(code, message, manifestHash) {
103200
+ constructor(code, message, manifestHash, prefixCode = false) {
102665
103201
  super(message);
102666
103202
  this.code = code;
102667
103203
  this.manifestHash = manifestHash;
103204
+ this.prefixCode = prefixCode;
102668
103205
  this.name = "TaskCommandError";
102669
103206
  }
102670
103207
  code;
102671
103208
  manifestHash;
103209
+ prefixCode;
102672
103210
  };
102673
103211
  function mapTaskError(error61) {
102674
103212
  if (error61 instanceof TaskInputError) return new UsageError(error61.message);
102675
103213
  if (error61 instanceof TaskOperationError)
102676
- return new TaskCommandError(error61.code, error61.message, error61.manifestHash);
103214
+ return new TaskCommandError(error61.code, error61.message, error61.manifestHash, true);
102677
103215
  return error61;
102678
103216
  }
102679
103217
  async function mapped(operation) {
@@ -102892,11 +103430,13 @@ async function taskCommandInner(argv, json2, io, dependencies) {
102892
103430
  "--intake",
102893
103431
  "--max-awards",
102894
103432
  "--webhook"
102895
- ] : verb === "propose" ? ["--price", "--duration", "--note"] : verb === "submit" ? ["--proof", "--file"] : verb === "thread" ? ["--after"] : verb === "deliver" ? ["--files", "--note"] : ["dispute", "counter-evidence"].includes(verb) ? ["--evidence-hash"] : verb === "watch" ? ["--until", "--timeout", "--interval"] : []
103433
+ ] : verb === "propose" ? ["--price", "--duration", "--note"] : verb === "submit" ? ["--proof", "--file"] : verb === "thread" ? ["--after"] : verb === "deliver" ? ["--files", "--note"] : ["dispute", "counter-evidence"].includes(verb) ? ["--evidence-hash"] : verb === "watch" ? ["--until", "--timeout", "--interval"] : [],
103434
+ ...["sign", "fund", "deliver", "release"].includes(verb) ? ["--timeout"] : []
102896
103435
  ]),
102897
103436
  booleanOptions: /* @__PURE__ */ new Set([
102898
103437
  ...verb === "search" ? ["--open"] : [],
102899
103438
  ...["sign", "fund", "dispute", "counter-evidence"].includes(verb) ? ["--yes"] : [],
103439
+ ...["sign", "fund", "deliver", "release"].includes(verb) ? ["--no-wait"] : [],
102900
103440
  ...verb === "watch" ? ["--auto-release"] : []
102901
103441
  ]),
102902
103442
  repeatableOptions: /* @__PURE__ */ new Set([
@@ -103052,7 +103592,7 @@ async function taskCommandInner(argv, json2, io, dependencies) {
103052
103592
  throw new UsageError("message needs text between 1 and 10000 characters.");
103053
103593
  }
103054
103594
  if (verb === "thread") cursor2 = optionalInteger(parsed.one("--after"), "--after");
103055
- const context = await taskContext(parsed, io, dependencies, verb === "status");
103595
+ const context = await taskContext(parsed, io, dependencies);
103056
103596
  if (verb === "show" || verb === "status") {
103057
103597
  if (verb === "show" && context.token) {
103058
103598
  const result = await showTask(context, { id: id2, signedIn: true });
@@ -103062,7 +103602,21 @@ async function taskCommandInner(argv, json2, io, dependencies) {
103062
103602
  ...receipts.map((receipt) => `Receipt (from escrow): ${receipt.receiptUrl}`)
103063
103603
  ]);
103064
103604
  } else {
103065
- const result = verb === "status" ? await taskStatus(context, { id: id2 }) : await showTask(context, { id: id2, signedIn: false });
103605
+ const result = verb === "status" ? await taskStatus(context, { id: id2, signedIn: Boolean(context.token) }) : await showTask(context, { id: id2, signedIn: false });
103606
+ if ("chainState" in result) {
103607
+ const milestoneLines = result.chainState.milestones.map((milestone) => {
103608
+ const ordinal = "ordinal" in milestone && typeof milestone.ordinal === "number" && Number.isFinite(milestone.ordinal) ? milestone.ordinal : milestone.milestoneId;
103609
+ const state = "state" in milestone.read ? ` ${milestone.read.state}` : "";
103610
+ const explorer = milestone.explorerUrl ? ` ${milestone.explorerUrl}` : "";
103611
+ return `milestone ${ordinal}: ${milestone.read.status}${state}${explorer}`;
103612
+ });
103613
+ const eventLines = (result.events ?? []).slice(-10).map((event) => {
103614
+ const createdAt = "createdAt" in event && typeof event.createdAt === "string" ? event.createdAt : event.at;
103615
+ return `${event.sequence} ${event.type} ${createdAt}`;
103616
+ });
103617
+ taskOutput(io, json2, context, verb, result, [...milestoneLines, ...eventLines]);
103618
+ return;
103619
+ }
103066
103620
  const task = result.task;
103067
103621
  taskOutput(
103068
103622
  io,
@@ -103106,6 +103660,11 @@ async function taskCommandInner(argv, json2, io, dependencies) {
103106
103660
  async function escrowTaskCommand(verb, id2, parsed, json2, io, dependencies, now) {
103107
103661
  taskCounterparty(parsed);
103108
103662
  if (verb === "watch") return await watchTask(id2, parsed, json2, io, dependencies, now);
103663
+ const waitsForIndex = ["sign", "fund", "deliver", "release"].includes(verb);
103664
+ const waitTimeoutText = parsed.one("--timeout") ?? "120s";
103665
+ const waitTimeoutMs = waitsForIndex ? parseTaskDuration2(waitTimeoutText, now) : void 0;
103666
+ if (waitTimeoutMs !== void 0 && waitTimeoutMs <= 0)
103667
+ throw new UsageError("--timeout must be positive.");
103109
103668
  const disputeEvidenceHash = ["dispute", "counter-evidence"].includes(verb) ? required3(parsed, "--evidence-hash") : void 0;
103110
103669
  const counterparty = taskCounterparty(parsed);
103111
103670
  if (disputeEvidenceHash !== void 0 && !TASK_LIMITS.disputeEvidenceHash.test(disputeEvidenceHash))
@@ -103155,9 +103714,24 @@ async function escrowTaskCommand(verb, id2, parsed, json2, io, dependencies, now
103155
103714
  return await account.signMessage({ message });
103156
103715
  }
103157
103716
  });
103158
- taskOutput(io, json2, displayContext, verb, result2, [
103717
+ if (!json2 && result2.escrowCreation?.resumedFromServer)
103718
+ io.stdout("The server had already prepared escrow creation; resumed from it.");
103719
+ const wait3 = result2.escrowCreation ? await waitForTaskIndex(
103720
+ context,
103721
+ dependencies,
103722
+ parsed,
103723
+ json2,
103724
+ io,
103725
+ id2,
103726
+ result2.escrowCreation,
103727
+ "created",
103728
+ "escrow creation",
103729
+ waitTimeoutText,
103730
+ waitTimeoutMs
103731
+ ) : null;
103732
+ taskOutput(io, json2, displayContext, verb, { ...result2, wait: wait3 }, [
103159
103733
  `Accepted scope for task ${id2}.`,
103160
- ...result2.escrowCreation ? ["Created the task escrow."] : []
103734
+ ...result2.escrowCreation && (wait3 === null || wait3.reached) ? ["escrow created"] : []
103161
103735
  ]);
103162
103736
  return;
103163
103737
  } catch (error61) {
@@ -103191,7 +103765,23 @@ async function escrowTaskCommand(verb, id2, parsed, json2, io, dependencies, now
103191
103765
  taskOutput(io, false, context, verb, {}, [`Prepared delivery manifest ${manifestHash}.`]);
103192
103766
  }
103193
103767
  });
103194
- taskOutput(io, json2, context, verb, outcome, [`Delivered task ${id2}.`]);
103768
+ const wait3 = await waitForTaskIndex(
103769
+ context,
103770
+ dependencies,
103771
+ parsed,
103772
+ json2,
103773
+ io,
103774
+ id2,
103775
+ outcome.result,
103776
+ "delivered",
103777
+ "delivery",
103778
+ waitTimeoutText,
103779
+ waitTimeoutMs
103780
+ );
103781
+ taskOutput(io, json2, context, verb, { ...outcome, wait: wait3 }, [
103782
+ ...wait3 === null || wait3.reached ? ["delivery recorded"] : [],
103783
+ ...outcome.result.resumedFromServer === true ? ["The server had already recorded this delivery; resumed from it."] : []
103784
+ ]);
103195
103785
  return;
103196
103786
  }
103197
103787
  const snapshot = await taskMoneySnapshot(context.client, id2, void 0, {
@@ -103254,15 +103844,82 @@ async function escrowTaskCommand(verb, id2, parsed, json2, io, dependencies, now
103254
103844
  }
103255
103845
  if (!outcome.ok && "declined" in outcome)
103256
103846
  throw new TaskCommandError("not_approved", "Not approved; nothing was signed.");
103257
- taskOutput(io, json2, context, verb, outcome, [
103258
- verb === "fund" ? `Funded task ${id2}.` : `Completed task ${verb} for ${id2}.`
103259
- ]);
103847
+ if (!json2 && outcome.result.resumedFromServer)
103848
+ io.stdout("The server had already prepared this task operation; resumed from it.");
103849
+ const wait3 = verb === "fund" ? await waitForTaskIndex(
103850
+ context,
103851
+ dependencies,
103852
+ parsed,
103853
+ json2,
103854
+ io,
103855
+ id2,
103856
+ outcome.result,
103857
+ "locked",
103858
+ "funding",
103859
+ waitTimeoutText,
103860
+ waitTimeoutMs
103861
+ ) : void 0;
103862
+ taskOutput(
103863
+ io,
103864
+ json2,
103865
+ context,
103866
+ verb,
103867
+ wait3 === void 0 ? outcome : { ...outcome, wait: wait3 },
103868
+ verb === "fund" ? wait3 === null || wait3?.reached ? ["escrow funded"] : [] : [`Completed task ${verb} for ${id2}.`]
103869
+ );
103260
103870
  return;
103261
103871
  }
103262
103872
  if (!json2) io.stdout("Policy: explicit user instruction.");
103263
103873
  const settlementInput = { id: id2, snapshot, ...counterparty === void 0 ? {} : { counterparty } };
103264
103874
  const result = verb === "release" ? await releaseTaskOperation(context, settlementInput) : verb === "refund" ? await refundTaskOperation(context, settlementInput) : await resolveUnmatchedTaskOperation(context, settlementInput);
103265
- taskOutput(io, json2, context, verb, result, [`Completed task ${verb} for ${id2}.`]);
103875
+ if (!json2 && result.result.resumedFromServer)
103876
+ io.stdout("The server had already prepared this task operation; resumed from it.");
103877
+ const wait2 = verb === "release" ? await waitForTaskIndex(
103878
+ context,
103879
+ dependencies,
103880
+ parsed,
103881
+ json2,
103882
+ io,
103883
+ id2,
103884
+ result.result,
103885
+ "released",
103886
+ "release",
103887
+ waitTimeoutText,
103888
+ waitTimeoutMs
103889
+ ) : void 0;
103890
+ taskOutput(
103891
+ io,
103892
+ json2,
103893
+ context,
103894
+ verb,
103895
+ wait2 === void 0 ? result : { ...result, wait: wait2 },
103896
+ verb === "release" ? wait2 === null || wait2?.reached ? ["funds released"] : [] : [`Completed task ${verb} for ${id2}.`]
103897
+ );
103898
+ }
103899
+ async function waitForTaskIndex(context, dependencies, parsed, json2, io, orderId, result, target, description, timeoutText, timeoutMs) {
103900
+ if (parsed.has("--no-wait")) return null;
103901
+ if (!json2)
103902
+ io.stdout(
103903
+ `confirmed on chain${result.blockNumber === void 0 ? "" : ` in block ${result.blockNumber}`}, waiting for vAPI to index\u2026`
103904
+ );
103905
+ const wait2 = await taskRequest2(
103906
+ description,
103907
+ "getOrder",
103908
+ () => waitForMilestone(context.client, {
103909
+ orderId,
103910
+ milestoneId: result.milestone.id,
103911
+ target,
103912
+ timeoutMs,
103913
+ intervalMs: 3e3,
103914
+ sleep: context.sleep,
103915
+ now: dependencies.now ?? (() => /* @__PURE__ */ new Date())
103916
+ })
103917
+ );
103918
+ if (!wait2.reached)
103919
+ io.stderr(
103920
+ `vAPI has not indexed the ${description} yet after ${timeoutText}; run vapi task status ${orderId} later.`
103921
+ );
103922
+ return wait2;
103266
103923
  }
103267
103924
  var ScopeApprovalNeeded = class extends Error {
103268
103925
  constructor(terms) {
@@ -104518,6 +105175,7 @@ async function referencedSleep(milliseconds, signal) {
104518
105175
  // src/vault.ts
104519
105176
  import { join as join27 } from "node:path";
104520
105177
  var VAULT_USAGE = "Usage: vapi vault protect|unprotect|lock|unlock|status [--json]";
105178
+ var RESTORE_USAGE = "Usage: vapi restore [--accounts <n> | --from-owner [--owner <0x\u2026>]] [--json]";
104521
105179
  var LEGACY_PASSWORD_NOTICE = "VAPI_KEYSTORE_PASSWORD is deprecated for vault passwords; use VAPI_VAULT_PASSWORD instead.";
104522
105180
  async function vaultCommand(argv, json2, io, dependencies) {
104523
105181
  const subcommand = argv[0];
@@ -104547,9 +105205,17 @@ async function restoreCommand(argv, json2, io, dependencies) {
104547
105205
  await restoreFromOwnerCommand(argv, json2, io, dependencies);
104548
105206
  return;
104549
105207
  }
104550
- if (argv.length > 0) {
104551
- throw new UsageError("Usage: vapi restore [--from-owner [--owner <0x\u2026>]] [--json]");
105208
+ let parsed;
105209
+ try {
105210
+ parsed = parseArguments(argv, {
105211
+ valueOptions: /* @__PURE__ */ new Set(["--accounts"]),
105212
+ maximumPositionals: 0
105213
+ });
105214
+ } catch (error61) {
105215
+ if (error61 instanceof UsageError) throw new UsageError(RESTORE_USAGE);
105216
+ throw error61;
104552
105217
  }
105218
+ const accountCount = parseRestoreAccountCount(parsed.one("--accounts"));
104553
105219
  const paths = getVapiPaths();
104554
105220
  const path = join27(paths.directory, "vault.json");
104555
105221
  if (await fileExists2(path)) {
@@ -104563,13 +105229,39 @@ async function restoreCommand(argv, json2, io, dependencies) {
104563
105229
  const config2 = await readConfig(paths.config, json2 ? quietIo(io) : io);
104564
105230
  const phrase = isStdinInteractive(dependencies) ? await getPrompts(dependencies).secret("Recovery phrase: ") : await (dependencies.readStdin ?? readProcessStdin3)();
104565
105231
  const restoreIo = json2 ? quietIo(io) : io;
104566
- const { names } = await restoreVaultFromPhrase(phrase.trim(), config2, restoreIo, dependencies);
105232
+ const { names, scannedAddresses } = await restoreVaultFromPhrase(
105233
+ phrase.trim(),
105234
+ config2,
105235
+ restoreIo,
105236
+ dependencies,
105237
+ accountCount
105238
+ );
104567
105239
  if (json2) {
104568
- output3(io, true, { command: "restore", vault: "restored", accounts: names }, "");
105240
+ output3(
105241
+ io,
105242
+ true,
105243
+ { command: "restore", vault: "restored", accounts: names, scannedAddresses },
105244
+ ""
105245
+ );
104569
105246
  return;
104570
105247
  }
104571
105248
  io.stdout(`Run vapi setup to link ${names[0]}.`);
104572
105249
  }
105250
+ function parseRestoreAccountCount(value) {
105251
+ if (value === void 0) return void 0;
105252
+ if (!/^\d+$/u.test(value)) {
105253
+ throw new UsageError(
105254
+ `--accounts must be a positive integer no greater than ${MAX_RESTORE_ACCOUNTS}.`
105255
+ );
105256
+ }
105257
+ const count = Number(value);
105258
+ if (!Number.isSafeInteger(count) || count < 1 || count > MAX_RESTORE_ACCOUNTS) {
105259
+ throw new UsageError(
105260
+ `--accounts must be a positive integer no greater than ${MAX_RESTORE_ACCOUNTS}.`
105261
+ );
105262
+ }
105263
+ return count;
105264
+ }
104573
105265
  async function protectCommand(argv, json2, io, dependencies) {
104574
105266
  requireNoArguments(argv);
104575
105267
  const env = getEnvironment(dependencies);
@@ -104699,8 +105391,8 @@ var HELP_HEADING = "vAPI Network";
104699
105391
  var HELP = `${HELP_HEADING}
104700
105392
 
104701
105393
  Usage:
104702
- vapi init [--networks <base,arc,solana>] [--json]
104703
- vapi setup [--no-cloud-backup] [--json]
105394
+ vapi init [--networks <base,arc>] [--json]
105395
+ vapi setup [--no-cloud-backup] [--accounts <n>] [--json]
104704
105396
  vapi accounts [--all] [--json]
104705
105397
  vapi accounts add <name> [--label <text>] [--no-link] [--json]
104706
105398
  vapi accounts import <name> [--keystore <path> | --key-file <path>] [--label <text>] [--json]
@@ -104730,7 +105422,7 @@ Usage:
104730
105422
  vapi docs read <url-or-path> [--json]
104731
105423
  vapi search [query] [--kind <kind>] [--network <caip2>] [--limit <n>] [--cursor <cursor>] [--include-unverified] [--json]
104732
105424
  vapi inspect <id> [--endpoint <name>] [--json]
104733
- vapi pay <id-or-url> [--method <method>] [--endpoint <name>] [--body <json>] [--content-type <type>] [--network <caip2>] [--expected-pay-to <address>] [--max <amount>] [--account <name>] [--json]
105425
+ vapi pay <id-or-url> [--method <method>] [--endpoint <name>] [--body <json>] [--content-type <type>] [--network <caip2>] [--expected-pay-to <address>] [--max <amount>] [--timeout <seconds>] [--account <name>] [--json]
104734
105426
  vapi pay --resume <receipt-id> [--json]
104735
105427
  vapi check <url> [--method <method>] [--json]
104736
105428
  vapi balance [--account <name>] [--json]
@@ -104776,8 +105468,8 @@ Usage:
104776
105468
  vapi task status <id> [--account <name>] [--json]
104777
105469
  vapi export-key [--network <caip2>] [--account <name>] [--json]
104778
105470
  vapi backup [--account <name>] [--cloud [off]] [--json]
104779
- vapi restore [--from-owner [--owner <0x\u2026>]] [--json]
104780
- vapi import (--phrase | --key) [--account <name>] [--networks <base,arc,solana>] [--replace] [--force] [--json]
105471
+ vapi restore [--accounts <n> | --from-owner [--owner <0x\u2026>]] [--json]
105472
+ vapi import (--phrase | --key) [--account <name>] [--networks <base,arc>] [--replace] [--force] [--json]
104781
105473
  vapi passphrase [--account <name>] [--json]
104782
105474
  vapi vault protect [--json]
104783
105475
  vapi vault unprotect [--json]
@@ -104805,6 +105497,8 @@ Every command that touches a wallet takes \`--account <name>\`, falls back to \`
104805
105497
 
104806
105498
  \`vapi search\` answers with vAPI-verified listings plus the mirrored external catalogs. \`--include-unverified\` also returns self-listed APIs that passed vAPI's automated x402 probe but were never reviewed; every result is tagged \`[verified]\`, \`[requested]\`, \`[unverified]\` or \`[external]\`.
104807
105499
 
105500
+ Solana listings remain searchable; inspect and pay return \`unsupported_network\`. Solana keys are not part of the device vault yet.
105501
+
104808
105502
  \`vapi docs\` asks the public vAPI documentation assistant; \`vapi docs search\` searches documentation excerpts and \`vapi docs read\` reads one Markdown page. They need no account, wallet or payment.
104809
105503
 
104810
105504
  \`vapi task --help\` lists task options and availability. Task exit codes: 0 ok, 1 error, 2 policy refusal (JSON ok:false with a policy. reason) or invalid usage (JSON error), 3 approval needed in non-interactive mode. Posting moves no money; the current create-order contract does not store amount, deadline, intake, max awards or webhook yet.
@@ -104817,7 +105511,7 @@ Every command that touches a wallet takes \`--account <name>\`, falls back to \`
104817
105511
 
104818
105512
  \`vapi vault protect\` adds a password to the device vault. \`vapi vault unlock\` opens it on this device for 8 hours; for unattended use, set \`VAPI_VAULT_PASSWORD\`. \`vapi unlock\` and \`vapi lock\` remain aliases for one release.
104819
105513
 
104820
- \`vapi backup\` and \`vapi export-key\` print a secret, so they run only on a real terminal, never for an agent, and ask you to type the wallet name first. \`vapi backup --cloud\` keeps an encrypted vault copy that only the owner can approve for recovery. \`vapi restore\` rebuilds the vault from the phrase and re-derives accounts until an unused address. Set \`VAPI_NO_SECRETS=1\` to switch exports off entirely. Every export and every wallet change is logged to ~/.vapi/audit.log.
105514
+ \`vapi backup\` and \`vapi export-key\` print a secret, so they run only on a real terminal, never for an agent, and ask you to type the wallet name first. \`vapi backup --cloud\` keeps an encrypted vault copy that only the owner can approve for recovery. \`vapi restore\` rebuilds the vault from the phrase and re-derives accounts until five consecutive addresses have no Base USDC, and reports the number scanned. Use \`--accounts <n>\` with restore or setup to recover a fixed count without querying balances. Set \`VAPI_NO_SECRETS=1\` to switch exports off entirely. Every export and every wallet change is logged to ~/.vapi/audit.log.
104821
105515
 
104822
105516
  \`vapi publish <url>\` lists an API you own. vAPI probes the URL \u2014 an origin, one endpoint, or an OpenAPI document \u2014 you choose which endpoints to list, and your wallet signs one line naming where the payouts go. Listing is permissionless: a listing that passed the probe goes live with \`vapi publish activate <slug>\`, and \`vapi publish verify-request <slug>\` asks for the review that puts it in the default search. Deploying the FeeSplitter that receives the payouts is a wallet transaction and stays in the console. A catalog of more than 20 endpoints is listed as several listings of up to 20, with one result line per endpoint; \`--resume\` skips every endpoint this key already lists.
104823
105517
 
@@ -105194,6 +105888,7 @@ async function runCli(argv = process.argv.slice(2), io = processIo, dependencies
105194
105888
  error: message,
105195
105889
  exitCode: code,
105196
105890
  ...error61 instanceof RuntimeError ? { code: error61.code } : {},
105891
+ ...error61 instanceof VapiCallError ? { code: error61.code } : {},
105197
105892
  ...error61 instanceof DocsError ? { code: error61.code } : {},
105198
105893
  ...error61 instanceof RemoteKeyRefusedError ? { code: error61.code } : {},
105199
105894
  ...error61 instanceof TransferError ? { code: error61.code, moneyMoved: error61.moneyMoved } : {}
@@ -105201,7 +105896,10 @@ async function runCli(argv = process.argv.slice(2), io = processIo, dependencies
105201
105896
  );
105202
105897
  }
105203
105898
  } else {
105204
- runIo.stderr(message);
105899
+ const errorCode2 = taskInvocation && error61 instanceof TaskCommandError && error61.prefixCode ? errorCodeOf(error61) : void 0;
105900
+ runIo.stderr(
105901
+ errorCode2 !== void 0 && !message.startsWith(`${errorCode2}: `) ? `${errorCode2}: ${message}` : message
105902
+ );
105205
105903
  }
105206
105904
  if (shouldAutoUploadAfterFailure(argv.filter((argument) => argument !== "--json"))) {
105207
105905
  await autoUploadBackup(io, json2, dependencies);
@@ -105602,7 +106300,7 @@ async function inspectCommand(argv, json2, io, dependencies) {
105602
106300
  );
105603
106301
  output3(io, json2, result, formatInspect(result));
105604
106302
  }
105605
- var PAY_USAGE = "Usage: vapi pay <id-or-url> [--method <method>] [--endpoint <name>] [--body <json>] [--content-type <type>] [--network <caip2>] [--expected-pay-to <address>] [--max <amount>] [--account <name>] [--json]";
106303
+ var PAY_USAGE = "Usage: vapi pay <id-or-url> [--method <method>] [--endpoint <name>] [--body <json>] [--content-type <type>] [--network <caip2>] [--expected-pay-to <address>] [--max <amount>] [--timeout <seconds>] [--account <name>] [--json]";
105606
106304
  async function payCommand(argv, json2, io, dependencies) {
105607
106305
  if (argv.includes(RESUME_OPTION)) {
105608
106306
  await payResumeCommand(argv, json2, io, dependencies);
@@ -105618,11 +106316,13 @@ async function payCommand(argv, json2, io, dependencies) {
105618
106316
  "--expected-pay-to",
105619
106317
  "--max",
105620
106318
  "--max-price-usd",
106319
+ "--timeout",
105621
106320
  WALLET_OPTION5
105622
106321
  ]),
105623
106322
  maximumPositionals: 1
105624
106323
  });
105625
106324
  const target = requiredPositional(parsed.positionals[0], "<id-or-url>", PAY_USAGE);
106325
+ const timeoutSeconds = optionalBoundedInteger(parsed.one("--timeout"), "--timeout", 1, 300);
105626
106326
  const paths = getVapiPaths();
105627
106327
  const config2 = await readConfig(paths.config, io);
105628
106328
  const wallet = await targetWallet(parsed, dependencies);
@@ -105638,7 +106338,8 @@ async function payCommand(argv, json2, io, dependencies) {
105638
106338
  ...parsed.one("--content-type") ? { contentType: parsed.one("--content-type") } : {},
105639
106339
  ...parsed.one("--network") ? { network: parsed.one("--network") } : {},
105640
106340
  ...parsed.one("--expected-pay-to") ? { expectedPayTo: parsed.one("--expected-pay-to") } : {},
105641
- ...maxPriceUsd ? { maxPriceUsd } : {}
106341
+ ...maxPriceUsd ? { maxPriceUsd } : {},
106342
+ ...timeoutSeconds === void 0 ? {} : { timeoutSeconds }
105642
106343
  };
105643
106344
  const call2 = createCallPort({
105644
106345
  config: config2,
@@ -107313,7 +108014,7 @@ function buildNextSteps(address4) {
107313
108014
  formatNextStep("Pay", "vapi pay <ref> --max 0.02"),
107314
108015
  formatNextStep(
107315
108016
  "Agent",
107316
- 'add {"command":"npx","args":["-y","vapi-network","mcp"]} to your MCP config'
108017
+ 'add {"command":"npx","args":["-y","vapi-network@latest","mcp"]} to your MCP config'
107317
108018
  )
107318
108019
  ];
107319
108020
  }
@@ -107494,6 +108195,17 @@ function optionalPositiveInteger(value, option) {
107494
108195
  if (result === 0) throw new UsageError(`${option} must be a positive integer.`);
107495
108196
  return result;
107496
108197
  }
108198
+ function optionalBoundedInteger(value, option, minimum, maximum) {
108199
+ if (value === void 0) return void 0;
108200
+ if (!/^\d+$/.test(value)) {
108201
+ throw new UsageError(`${option} must be an integer from ${minimum} to ${maximum}.`);
108202
+ }
108203
+ const parsed = Number(value);
108204
+ if (!Number.isSafeInteger(parsed) || parsed < minimum || parsed > maximum) {
108205
+ throw new UsageError(`${option} must be an integer from ${minimum} to ${maximum}.`);
108206
+ }
108207
+ return parsed;
108208
+ }
107497
108209
  function optionalUsdAmount(value, option) {
107498
108210
  if (value === void 0) return void 0;
107499
108211
  if (!/^\d+(?:\.\d{1,2})?$/.test(value)) {
@@ -107554,12 +108266,136 @@ function parseInitNetworks(value) {
107554
108266
  }
107555
108267
  for (const network of networks) {
107556
108268
  if (network !== "base" && network !== "arc" && network !== "solana") {
107557
- throw new UsageError("--networks supports base, arc and solana.");
108269
+ throw new UsageError("--networks supports base and arc; Solana vault setup is unavailable.");
107558
108270
  }
107559
108271
  }
107560
108272
  return networks;
107561
108273
  }
107562
108274
 
108275
+ // src/update-check.ts
108276
+ var CHECK_INTERVAL_MS = 24 * 60 * 60 * 1e3;
108277
+ var CHECK_TIMEOUT_MS = 1500;
108278
+ var LATEST_URL = "https://registry.npmjs.org/vapi-network/latest";
108279
+ async function runCliWithUpdateCheck(argv = process.argv.slice(2), io = {
108280
+ stdout: (message) => console.log(message),
108281
+ stderr: (message) => console.error(message)
108282
+ }, dependencies = {}, options = {}) {
108283
+ const notice = checkForUpdate({ ...options, env: options.env ?? dependencies.env, argv });
108284
+ const code = await runCli(argv, io, dependencies);
108285
+ const message = await notice;
108286
+ if (message) io.stderr(message);
108287
+ return code;
108288
+ }
108289
+ async function checkForUpdate(options = {}) {
108290
+ const env = options.env ?? process.env;
108291
+ const argv = options.argv ?? process.argv.slice(2);
108292
+ if (!(options.stderrIsTTY ?? process.stderr.isTTY) || argv.includes("--json") || argv[0] === "mcp" && argv[1] !== "install" || env.VAPI_NO_UPDATE_CHECK === "1" || env.CI !== void 0) {
108293
+ return void 0;
108294
+ }
108295
+ const controller = new AbortController();
108296
+ let timer;
108297
+ try {
108298
+ return await Promise.race([
108299
+ latestNotice(options, env, controller.signal),
108300
+ new Promise((resolve2) => {
108301
+ timer = setTimeout(() => {
108302
+ controller.abort();
108303
+ resolve2(void 0);
108304
+ }, CHECK_TIMEOUT_MS);
108305
+ })
108306
+ ]);
108307
+ } catch {
108308
+ return void 0;
108309
+ } finally {
108310
+ if (timer !== void 0) clearTimeout(timer);
108311
+ controller.abort();
108312
+ }
108313
+ }
108314
+ async function latestNotice(options, env, signal) {
108315
+ const paths = getVapiPaths(options.home ?? (env.VAPI_HOME?.trim() || void 0));
108316
+ const now = (options.nowMs ?? Date.now)();
108317
+ let cached2;
108318
+ try {
108319
+ const value = JSON.parse(await readFile29(paths.updateCheck, "utf8"));
108320
+ if (isRecord12(value) && typeof value.checkedAt === "number" && Number.isFinite(value.checkedAt) && typeof value.latest === "string" && parseVersion(value.latest)) {
108321
+ cached2 = { checkedAt: value.checkedAt, latest: value.latest };
108322
+ }
108323
+ } catch {
108324
+ }
108325
+ signal.throwIfAborted();
108326
+ let latest = cached2?.latest ?? CLI_VERSION;
108327
+ if (cached2 === void 0 || now - cached2.checkedAt >= CHECK_INTERVAL_MS || now < cached2.checkedAt) {
108328
+ await mkdir21(paths.directory, { recursive: true });
108329
+ signal.throwIfAborted();
108330
+ await writeFile12(paths.updateCheck, JSON.stringify({ checkedAt: now, latest }), { mode: 384 });
108331
+ signal.throwIfAborted();
108332
+ const fetchImpl = options.fetchImpl ?? createPublicFetch({
108333
+ allowPrivateNetwork: false,
108334
+ lookup: async (hostname3) => {
108335
+ let onAbort;
108336
+ const aborted2 = new Promise((_resolve, reject) => {
108337
+ onAbort = () => reject(signal.reason);
108338
+ signal.addEventListener("abort", onAbort, { once: true });
108339
+ });
108340
+ try {
108341
+ signal.throwIfAborted();
108342
+ const addresses = await Promise.race([lookup(hostname3, { all: true }), aborted2]);
108343
+ return addresses.map(({ address: address4 }) => address4);
108344
+ } finally {
108345
+ signal.removeEventListener("abort", onAbort);
108346
+ }
108347
+ }
108348
+ });
108349
+ const response = await fetchImpl(LATEST_URL, { signal, redirect: "error" });
108350
+ if (!response.ok) return void 0;
108351
+ const body = await response.json();
108352
+ signal.throwIfAborted();
108353
+ if (!isRecord12(body) || typeof body.version !== "string" || !parseVersion(body.version)) {
108354
+ return void 0;
108355
+ }
108356
+ latest = body.version;
108357
+ await writeFile12(paths.updateCheck, JSON.stringify({ checkedAt: now, latest }), { mode: 384 });
108358
+ }
108359
+ signal.throwIfAborted();
108360
+ return isNewerVersion(latest, CLI_VERSION) ? `vapi-network ${latest} is available (you have ${CLI_VERSION}). Update: npm i -g vapi-network@latest` : void 0;
108361
+ }
108362
+ function isRecord12(value) {
108363
+ return typeof value === "object" && value !== null && !Array.isArray(value);
108364
+ }
108365
+ function parseVersion(version5) {
108366
+ const match = /^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-([\da-zA-Z.-]+))?(?:\+[\da-zA-Z-]+(?:\.[\da-zA-Z-]+)*)?$/.exec(
108367
+ version5
108368
+ );
108369
+ if (!match) return void 0;
108370
+ const prerelease = match[4]?.split(".");
108371
+ if (prerelease?.some((part) => part === "" || /^\d+$/.test(part) && /^0\d/.test(part))) {
108372
+ return void 0;
108373
+ }
108374
+ return { core: match.slice(1, 4).map(BigInt), prerelease };
108375
+ }
108376
+ function isNewerVersion(latest, current) {
108377
+ const next = parseVersion(latest);
108378
+ const running = parseVersion(current);
108379
+ for (let index2 = 0; index2 < 3; index2 += 1) {
108380
+ if (next.core[index2] !== running.core[index2]) return next.core[index2] > running.core[index2];
108381
+ }
108382
+ if (running.prerelease === void 0) return false;
108383
+ if (next.prerelease === void 0) return true;
108384
+ for (let index2 = 0; index2 < Math.max(next.prerelease.length, running.prerelease.length); index2 += 1) {
108385
+ const a = next.prerelease[index2];
108386
+ const b = running.prerelease[index2];
108387
+ if (a === b) continue;
108388
+ if (a === void 0) return false;
108389
+ if (b === void 0) return true;
108390
+ const aNumeric = /^\d+$/.test(a);
108391
+ const bNumeric = /^\d+$/.test(b);
108392
+ if (aNumeric && bNumeric) return BigInt(a) > BigInt(b);
108393
+ if (aNumeric !== bNumeric) return !aNumeric;
108394
+ return a > b;
108395
+ }
108396
+ return false;
108397
+ }
108398
+
107563
108399
  // src/main-module.ts
107564
108400
  import { realpathSync as realpathSync2 } from "node:fs";
107565
108401
  import { pathToFileURL } from "node:url";
@@ -107576,7 +108412,7 @@ function isMainModule(entry, moduleUrl, realpath = realpathSync2) {
107576
108412
 
107577
108413
  // src/bin.ts
107578
108414
  if (isMainModule(process.argv[1], import.meta.url)) {
107579
- process.exitCode = await runCli();
108415
+ process.exitCode = await runCliWithUpdateCheck();
107580
108416
  }
107581
108417
  export {
107582
108418
  CUSTODY_NOTICE,