@vapi-network/cli 0.9.2 → 0.9.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -9441,13 +9441,13 @@ var init_getCallError = __esm({
9441
9441
 
9442
9442
  // ../../node_modules/.pnpm/viem@2.56.1_typescript@6.0.3_zod@4.5.4/node_modules/viem/_esm/utils/promise/withResolvers.js
9443
9443
  function withResolvers() {
9444
- let resolve2 = () => void 0;
9444
+ let resolve3 = () => void 0;
9445
9445
  let reject = () => void 0;
9446
9446
  const promise2 = new Promise((resolve_, reject_) => {
9447
- resolve2 = resolve_;
9447
+ resolve3 = resolve_;
9448
9448
  reject = reject_;
9449
9449
  });
9450
- return { promise: promise2, resolve: resolve2, reject };
9450
+ return { promise: promise2, resolve: resolve3, reject };
9451
9451
  }
9452
9452
  var init_withResolvers = __esm({
9453
9453
  "../../node_modules/.pnpm/viem@2.56.1_typescript@6.0.3_zod@4.5.4/node_modules/viem/_esm/utils/promise/withResolvers.js"() {
@@ -9466,8 +9466,8 @@ function createBatchScheduler({ fn, id: id2, shouldSplitBatch, wait: wait2 = 0,
9466
9466
  if (sort && Array.isArray(data))
9467
9467
  data.sort(sort);
9468
9468
  for (let i = 0; i < scheduler.length; i++) {
9469
- const { resolve: resolve2 } = scheduler[i];
9470
- resolve2?.([data[i], data]);
9469
+ const { resolve: resolve3 } = scheduler[i];
9470
+ resolve3?.([data[i], data]);
9471
9471
  }
9472
9472
  }).catch((err) => {
9473
9473
  for (let i = 0; i < scheduler.length; i++) {
@@ -9483,16 +9483,16 @@ function createBatchScheduler({ fn, id: id2, shouldSplitBatch, wait: wait2 = 0,
9483
9483
  return {
9484
9484
  flush,
9485
9485
  async schedule(args) {
9486
- const { promise: promise2, resolve: resolve2, reject } = withResolvers();
9486
+ const { promise: promise2, resolve: resolve3, reject } = withResolvers();
9487
9487
  const split2 = shouldSplitBatch?.([...getBatchedArgs(), args]);
9488
9488
  if (split2)
9489
9489
  exec();
9490
9490
  const hasActiveScheduler = getScheduler().length > 0;
9491
9491
  if (hasActiveScheduler) {
9492
- setScheduler({ args, resolve: resolve2, reject });
9492
+ setScheduler({ args, resolve: resolve3, reject });
9493
9493
  return promise2;
9494
9494
  }
9495
- setScheduler({ args, resolve: resolve2, reject });
9495
+ setScheduler({ args, resolve: resolve3, reject });
9496
9496
  setTimeout(exec, wait2);
9497
9497
  return promise2;
9498
9498
  }
@@ -30774,7 +30774,7 @@ function observe(observerId, callbacks, fn) {
30774
30774
  // ../../node_modules/.pnpm/viem@2.56.1_typescript@6.0.3_zod@4.5.4/node_modules/viem/_esm/utils/wait.js
30775
30775
  init_utils3();
30776
30776
  async function wait(time3, { signal } = {}) {
30777
- return new Promise((resolve2, reject) => {
30777
+ return new Promise((resolve3, reject) => {
30778
30778
  if (signal?.aborted) {
30779
30779
  reject(getAbortError(signal));
30780
30780
  return;
@@ -30782,7 +30782,7 @@ async function wait(time3, { signal } = {}) {
30782
30782
  const cleanup = () => signal?.removeEventListener("abort", onAbort);
30783
30783
  const timeout = setTimeout(() => {
30784
30784
  cleanup();
30785
- resolve2();
30785
+ resolve3();
30786
30786
  }, time3);
30787
30787
  const onAbort = () => {
30788
30788
  clearTimeout(timeout);
@@ -31358,7 +31358,7 @@ init_withResolvers();
31358
31358
  // ../../node_modules/.pnpm/viem@2.56.1_typescript@6.0.3_zod@4.5.4/node_modules/viem/_esm/utils/promise/withRetry.js
31359
31359
  init_utils3();
31360
31360
  function withRetry(fn, { delay: delay_ = 100, retryCount = 2, shouldRetry: shouldRetry2 = () => true, signal } = {}) {
31361
- return new Promise((resolve2, reject) => {
31361
+ return new Promise((resolve3, reject) => {
31362
31362
  const attemptRetry = async ({ count = 0 } = {}) => {
31363
31363
  if (signal?.aborted) {
31364
31364
  reject(getAbortError(signal));
@@ -31378,7 +31378,7 @@ function withRetry(fn, { delay: delay_ = 100, retryCount = 2, shouldRetry: shoul
31378
31378
  };
31379
31379
  try {
31380
31380
  const data = await fn();
31381
- resolve2(data);
31381
+ resolve3(data);
31382
31382
  } catch (err) {
31383
31383
  if (signal?.aborted) {
31384
31384
  reject(getAbortError(signal));
@@ -31529,7 +31529,7 @@ async function sendCalls(client, parameters) {
31529
31529
  results.push({ reason, status: "rejected" });
31530
31530
  }
31531
31531
  if (experimental_fallbackDelay > 0)
31532
- await new Promise((resolve2) => setTimeout(resolve2, experimental_fallbackDelay));
31532
+ await new Promise((resolve3) => setTimeout(resolve3, experimental_fallbackDelay));
31533
31533
  }
31534
31534
  if (results.every((r) => r.status === "rejected"))
31535
31535
  throw results[0].reason;
@@ -31632,9 +31632,9 @@ async function waitForCallsStatus(client, parameters) {
31632
31632
  throwOnFailure = false
31633
31633
  } = parameters;
31634
31634
  const observerId = stringify(["waitForCallsStatus", client.uid, id2]);
31635
- const { promise: promise2, resolve: resolve2, reject } = withResolvers();
31635
+ const { promise: promise2, resolve: resolve3, reject } = withResolvers();
31636
31636
  let timer;
31637
- const unobserve = observe(observerId, { resolve: resolve2, reject }, (emit) => {
31637
+ const unobserve = observe(observerId, { resolve: resolve3, reject }, (emit) => {
31638
31638
  const unpoll = poll(async () => {
31639
31639
  const done = (fn) => {
31640
31640
  clearTimeout(timer);
@@ -32016,13 +32016,13 @@ async function isImageUri(uri) {
32016
32016
  }
32017
32017
  if (!Object.hasOwn(globalThis, "Image"))
32018
32018
  return false;
32019
- return new Promise((resolve2) => {
32019
+ return new Promise((resolve3) => {
32020
32020
  const img = new Image();
32021
32021
  img.onload = () => {
32022
- resolve2(true);
32022
+ resolve3(true);
32023
32023
  };
32024
32024
  img.onerror = () => {
32025
- resolve2(false);
32025
+ resolve3(false);
32026
32026
  };
32027
32027
  img.src = uri;
32028
32028
  });
@@ -33485,7 +33485,7 @@ init_utils3();
33485
33485
  // ../../node_modules/.pnpm/viem@2.56.1_typescript@6.0.3_zod@4.5.4/node_modules/viem/_esm/utils/promise/withTimeout.js
33486
33486
  init_utils3();
33487
33487
  function withTimeout(fn, { errorInstance = new Error("timed out"), timeout, signal }) {
33488
- return new Promise((resolve2, reject) => {
33488
+ return new Promise((resolve3, reject) => {
33489
33489
  ;
33490
33490
  (async () => {
33491
33491
  let timeoutId;
@@ -33500,7 +33500,7 @@ function withTimeout(fn, { errorInstance = new Error("timed out"), timeout, sign
33500
33500
  }
33501
33501
  }, timeout);
33502
33502
  }
33503
- resolve2(await fn({ signal: controller?.signal || null }));
33503
+ resolve3(await fn({ signal: controller?.signal || null }));
33504
33504
  } catch (err) {
33505
33505
  if (controller?.signal.aborted && isAbortError(err)) {
33506
33506
  reject(errorInstance);
@@ -37480,13 +37480,13 @@ async function waitForTransactionReceipt(client, parameters) {
37480
37480
  let retrying = false;
37481
37481
  let _unobserve;
37482
37482
  let _unwatch;
37483
- const { promise: promise2, resolve: resolve2, reject } = withResolvers();
37483
+ const { promise: promise2, resolve: resolve3, reject } = withResolvers();
37484
37484
  const timer = timeout ? setTimeout(() => {
37485
37485
  _unwatch?.();
37486
37486
  _unobserve?.();
37487
37487
  reject(new WaitForTransactionReceiptTimeoutError({ hash: hash5 }));
37488
37488
  }, timeout) : void 0;
37489
- _unobserve = observe(observerId, { onReplaced, resolve: resolve2, reject }, async (emit) => {
37489
+ _unobserve = observe(observerId, { onReplaced, resolve: resolve3, reject }, async (emit) => {
37490
37490
  receipt = await getAction(client, getTransactionReceipt, "getTransactionReceipt")({ hash: hash5 }).catch(() => void 0);
37491
37491
  if (receipt && confirmations <= 1) {
37492
37492
  clearTimeout(timer);
@@ -39356,8 +39356,10 @@ var listingIdentitySchema = external_exports.looseObject({
39356
39356
  }).optional().catch(void 0)
39357
39357
  });
39358
39358
  var listingDisclosureShape = {
39359
- group: listingGroupSchema.optional(),
39360
- fee: listingFeeSchema.optional(),
39359
+ // Presentation metadata must not make an otherwise executable row vanish
39360
+ // when the registry adds a new group or changes the fee display shape.
39361
+ group: listingGroupSchema.optional().catch(void 0),
39362
+ fee: listingFeeSchema.optional().catch(void 0),
39361
39363
  verification: listingVerificationFieldSchema,
39362
39364
  liveness: listingLivenessSchema.optional().catch(void 0),
39363
39365
  conformance: listingConformanceSchema.optional().catch(void 0),
@@ -39365,11 +39367,13 @@ var listingDisclosureShape = {
39365
39367
  };
39366
39368
  var marketplaceBadgeCodeSchema = external_exports.enum([
39367
39369
  "live_x402",
39370
+ "mpp",
39368
39371
  "partner",
39369
39372
  "payout_wallet_confirmed",
39370
39373
  "vapi_verified",
39371
39374
  "external_catalog",
39372
- "approved_vendor"
39375
+ "approved_vendor",
39376
+ "unverified"
39373
39377
  ]);
39374
39378
  var marketplaceBadgeSchema = external_exports.looseObject({
39375
39379
  code: marketplaceBadgeCodeSchema,
@@ -39388,7 +39392,13 @@ var marketplaceCardSchema = external_exports.looseObject({
39388
39392
  summary: external_exports.string().trim().min(1).max(1e3),
39389
39393
  byline: external_exports.string().trim().min(1).max(160).optional(),
39390
39394
  bylineHref: marketplaceHrefSchema.optional(),
39391
- badges: external_exports.array(marketplaceBadgeSchema).max(8),
39395
+ badges: external_exports.preprocess(
39396
+ (badges) => Array.isArray(badges) ? badges.flatMap((badge) => {
39397
+ const parsed = marketplaceBadgeSchema.safeParse(badge);
39398
+ return parsed.success ? [parsed.data] : [];
39399
+ }) : badges,
39400
+ external_exports.array(marketplaceBadgeSchema).max(8)
39401
+ ),
39392
39402
  facts: external_exports.array(marketplacePublicFactSchema).max(12)
39393
39403
  });
39394
39404
  var marketplaceHitBase = {
@@ -43435,7 +43445,7 @@ function getRpcTransportWithRequestCoalescing(transport, getDeduplicationKey) {
43435
43445
  coalescedRequest.numConsumers++;
43436
43446
  if (signal) {
43437
43447
  const responsePromise = coalescedRequest.responsePromise;
43438
- return await new Promise((resolve2, reject) => {
43448
+ return await new Promise((resolve3, reject) => {
43439
43449
  const handleAbort = (e22) => {
43440
43450
  signal.removeEventListener("abort", handleAbort);
43441
43451
  coalescedRequest.numConsumers -= 1;
@@ -43448,7 +43458,7 @@ function getRpcTransportWithRequestCoalescing(transport, getDeduplicationKey) {
43448
43458
  reject(e22.target.reason);
43449
43459
  };
43450
43460
  signal.addEventListener("abort", handleAbort);
43451
- responsePromise.then(resolve2).catch(reject).finally(() => {
43461
+ responsePromise.then(resolve3).catch(reject).finally(() => {
43452
43462
  signal.removeEventListener("abort", handleAbort);
43453
43463
  });
43454
43464
  });
@@ -44831,7 +44841,7 @@ function createPublicFetch(options) {
44831
44841
  });
44832
44842
  const normalized = new Request(input2, init);
44833
44843
  const bytes = normalized.body ? Buffer.from(await normalized.arrayBuffer()) : null;
44834
- return await new Promise((resolve2, reject) => {
44844
+ return await new Promise((resolve3, reject) => {
44835
44845
  const requestOptions2 = {
44836
44846
  method: normalized.method,
44837
44847
  headers: Object.fromEntries(normalized.headers),
@@ -44856,7 +44866,7 @@ function createPublicFetch(options) {
44856
44866
  { status, statusText: incoming.statusMessage, headers }
44857
44867
  );
44858
44868
  Object.defineProperty(response, "url", { value: url2.toString() });
44859
- resolve2(response);
44869
+ resolve3(response);
44860
44870
  } catch (error61) {
44861
44871
  incoming.destroy();
44862
44872
  reject(error61);
@@ -44869,9 +44879,9 @@ function createPublicFetch(options) {
44869
44879
  });
44870
44880
  });
44871
44881
  }
44872
- function pinnedLookup(lookup) {
44882
+ function pinnedLookup(lookup2) {
44873
44883
  return (hostname3, dnsOptions, callback) => {
44874
- void lookup(normalizeHostname(hostname3)).then((addresses) => {
44884
+ void lookup2(normalizeHostname(hostname3)).then((addresses) => {
44875
44885
  if (addresses.length === 0 || addresses.some(isNonPublicAddress)) {
44876
44886
  callback(guardError(new URL(`https://${hostname3}`)), "");
44877
44887
  return;
@@ -45625,8 +45635,8 @@ var svmFetchQueue = Promise.resolve();
45625
45635
  async function withGuardedSvmFetch(fetchImpl, operation) {
45626
45636
  const previous = svmFetchQueue;
45627
45637
  let release2;
45628
- svmFetchQueue = new Promise((resolve2) => {
45629
- release2 = resolve2;
45638
+ svmFetchQueue = new Promise((resolve3) => {
45639
+ release2 = resolve3;
45630
45640
  });
45631
45641
  await previous;
45632
45642
  const originalFetch = globalThis.fetch;
@@ -46009,9 +46019,9 @@ function isRecord2(value) {
46009
46019
  var CALLABLE_CATEGORIES = ["ai", "data", "crypto", "compute", "search"];
46010
46020
  var callableCategorySchema = external_exports.enum(CALLABLE_CATEGORIES);
46011
46021
  var DISCOVERY_CATEGORIES = [...CALLABLE_CATEGORIES, "other"];
46012
- var discoveryCategorySchema = external_exports.enum(DISCOVERY_CATEGORIES);
46022
+ var discoveryCategorySchema = external_exports.string().trim().min(1);
46013
46023
  var CALLABLE_CATEGORY_SET = new Set(CALLABLE_CATEGORIES);
46014
- var serviceTierSchema = external_exports.enum(["listed", "verified", "partner"]);
46024
+ var serviceTierSchema = external_exports.string().trim().min(1);
46015
46025
  var discoveryEndpointSchema = external_exports.looseObject({
46016
46026
  name: external_exports.string(),
46017
46027
  method: external_exports.string(),
@@ -46041,6 +46051,24 @@ var discoveryEndpointSchema = external_exports.looseObject({
46041
46051
  asset: external_exports.string().refine(isSolanaAddress, "Expected a Solana base58 address."),
46042
46052
  payTo: external_exports.string().refine(isSolanaAddress, "Expected a Solana base58 address."),
46043
46053
  checkedAt: external_exports.iso.datetime()
46054
+ }),
46055
+ external_exports.looseObject({
46056
+ protocol: external_exports.literal("mpp"),
46057
+ intent: external_exports.enum(["charge", "authorize", "subscription"]).nullable(),
46058
+ method: external_exports.string().trim().min(1).max(40).nullable(),
46059
+ checkedAt: external_exports.iso.datetime(),
46060
+ // Keep common x402 properties readable on the union while making it
46061
+ // impossible for MPP metadata to masquerade as executable x402 terms.
46062
+ network: external_exports.never().optional(),
46063
+ payTo: external_exports.never().optional()
46064
+ }),
46065
+ external_exports.looseObject({
46066
+ // Future payment protocols remain visible to callers so the payment
46067
+ // layer can refuse them explicitly instead of discovery losing the row.
46068
+ protocol: external_exports.string().trim().min(1).max(40),
46069
+ checkedAt: external_exports.iso.datetime(),
46070
+ network: external_exports.never().optional(),
46071
+ payTo: external_exports.never().optional()
46044
46072
  })
46045
46073
  ]).optional()
46046
46074
  });
@@ -46134,7 +46162,7 @@ function resolveTarget(service, endpointName) {
46134
46162
  }
46135
46163
  if (targets.size !== 1) {
46136
46164
  const paymentNetworks = service.endpoints.flatMap(
46137
- (endpoint) => endpoint.payment ? [endpoint.payment.network] : []
46165
+ (endpoint) => typeof endpoint.payment?.network === "string" ? [endpoint.payment.network] : []
46138
46166
  );
46139
46167
  throw new DiscoveryCatalogError(
46140
46168
  "ambiguous_default",
@@ -46821,7 +46849,7 @@ async function withFileLock(lockPath, fn, options = {}) {
46821
46849
  if (Date.now() >= deadline) {
46822
46850
  throw new FileLockedError(options.lockedMessage);
46823
46851
  }
46824
- await new Promise((resolve2) => setTimeout(resolve2, LOCK_RETRY_MS));
46852
+ await new Promise((resolve3) => setTimeout(resolve3, LOCK_RETRY_MS));
46825
46853
  continue;
46826
46854
  }
46827
46855
  handle = candidate;
@@ -46836,7 +46864,7 @@ async function withFileLock(lockPath, fn, options = {}) {
46836
46864
  if (Date.now() >= deadline) {
46837
46865
  throw new FileLockedError(options.lockedMessage);
46838
46866
  }
46839
- await new Promise((resolve2) => setTimeout(resolve2, LOCK_RETRY_MS));
46867
+ await new Promise((resolve3) => setTimeout(resolve3, LOCK_RETRY_MS));
46840
46868
  }
46841
46869
  }
46842
46870
  const ownedHandle = handle;
@@ -46957,7 +46985,7 @@ async function restoreRenamedLock(path, tombPath) {
46957
46985
  } catch (error61) {
46958
46986
  if (hasCode(error61, "ENOENT")) return;
46959
46987
  if (!hasCode(error61, "EEXIST")) throw error61;
46960
- await new Promise((resolve2) => setTimeout(resolve2, LOCK_RETRY_MS));
46988
+ await new Promise((resolve3) => setTimeout(resolve3, LOCK_RETRY_MS));
46961
46989
  }
46962
46990
  }
46963
46991
  }
@@ -47109,7 +47137,8 @@ function getVapiPaths(directory = process.env.VAPI_HOME?.trim() || join2(homedir
47109
47137
  keystore: join2(directory, "keystore.json"),
47110
47138
  receipts: join2(directory, "receipts.jsonl"),
47111
47139
  searches: join2(directory, "searches.jsonl"),
47112
- ledger: join2(directory, "spend-ledger.json")
47140
+ ledger: join2(directory, "spend-ledger.json"),
47141
+ updateCheck: join2(directory, "update-check.json")
47113
47142
  };
47114
47143
  }
47115
47144
  var getAgentCashPaths = getVapiPaths;
@@ -47955,7 +47984,7 @@ async function withAgentCredentialLock(wallets, clientId, operation) {
47955
47984
  if (Date.now() >= deadline) {
47956
47985
  throw httpError("Timed out waiting to update the agent credentials.");
47957
47986
  }
47958
- await new Promise((resolve2) => setTimeout(resolve2, 20));
47987
+ await new Promise((resolve3) => setTimeout(resolve3, 20));
47959
47988
  }
47960
47989
  }
47961
47990
  try {
@@ -48108,7 +48137,7 @@ function splitScopes(scope) {
48108
48137
  return scope.split(/\s+/u).filter(Boolean);
48109
48138
  }
48110
48139
  async function sleepFor(milliseconds) {
48111
- await new Promise((resolve2) => setTimeout(resolve2, milliseconds));
48140
+ await new Promise((resolve3) => setTimeout(resolve3, milliseconds));
48112
48141
  }
48113
48142
 
48114
48143
  // ../core/src/keystore.ts
@@ -69586,7 +69615,7 @@ function decryptWithKey(key2, sealed) {
69586
69615
  return Buffer.concat([decipher.update(sealed.ciphertext), decipher.final()]);
69587
69616
  }
69588
69617
  async function deriveScryptKey(passphrase, salt) {
69589
- return await new Promise((resolve2, reject) => {
69618
+ return await new Promise((resolve3, reject) => {
69590
69619
  scrypt(
69591
69620
  passphrase,
69592
69621
  salt,
@@ -69602,7 +69631,7 @@ async function deriveScryptKey(passphrase, salt) {
69602
69631
  reject(error61);
69603
69632
  return;
69604
69633
  }
69605
- resolve2(derivedKey);
69634
+ resolve3(derivedKey);
69606
69635
  }
69607
69636
  );
69608
69637
  });
@@ -69926,7 +69955,7 @@ async function promptForSecret(prompt, noTerminalHint) {
69926
69955
  stdin.setRawMode(true);
69927
69956
  stdin.resume();
69928
69957
  stdin.setEncoding("utf8");
69929
- return await new Promise((resolve2, reject) => {
69958
+ return await new Promise((resolve3, reject) => {
69930
69959
  let value = "";
69931
69960
  const cleanup = () => {
69932
69961
  stdin.off("data", onData);
@@ -69943,7 +69972,7 @@ async function promptForSecret(prompt, noTerminalHint) {
69943
69972
  }
69944
69973
  if (character === "\r" || character === "\n") {
69945
69974
  cleanup();
69946
- resolve2(value);
69975
+ resolve3(value);
69947
69976
  return;
69948
69977
  }
69949
69978
  if (character === "\x7F" || character === "\b") {
@@ -70005,7 +70034,7 @@ async function withAccountMovementLock(home, account, timeoutMs, operation, sign
70005
70034
  if (!(error61 instanceof Error && "code" in error61 && error61.code === "EEXIST")) throw error61;
70006
70035
  await removeStaleLock2(path);
70007
70036
  if (Date.now() >= deadline) throw new AccountMovementLockedError(account);
70008
- await new Promise((resolve2) => setTimeout(resolve2, 20));
70037
+ await new Promise((resolve3) => setTimeout(resolve3, 20));
70009
70038
  }
70010
70039
  }
70011
70040
  const ownedHandle = handle;
@@ -70373,7 +70402,7 @@ function windowsDataProtectionStore(platform2, run, env, installed) {
70373
70402
  };
70374
70403
  }
70375
70404
  function libsecretStore(platform2, run, installed) {
70376
- const lookup = async (name) => {
70405
+ const lookup2 = async (name) => {
70377
70406
  const result = await run(SECRET_TOOL_BINARY, [
70378
70407
  "lookup",
70379
70408
  "service",
@@ -70392,9 +70421,9 @@ function libsecretStore(platform2, run, installed) {
70392
70421
  available: installed(SECRET_TOOL_BINARY),
70393
70422
  platform: platform2,
70394
70423
  description: "the libsecret keyring",
70395
- get: lookup,
70424
+ get: lookup2,
70396
70425
  async has(name) {
70397
- return await lookup(name) !== void 0;
70426
+ return await lookup2(name) !== void 0;
70398
70427
  },
70399
70428
  async set(name, passphrase) {
70400
70429
  requirePassphrase(passphrase);
@@ -70416,7 +70445,7 @@ function libsecretStore(platform2, run, installed) {
70416
70445
  requireSuccess(result, `store the passphrase of ${name} in the secret service`);
70417
70446
  },
70418
70447
  async remove(name) {
70419
- const existed = await lookup(name) !== void 0;
70448
+ const existed = await lookup2(name) !== void 0;
70420
70449
  const result = await run(SECRET_TOOL_BINARY, [
70421
70450
  "clear",
70422
70451
  "service",
@@ -70476,14 +70505,14 @@ function requireSuccess(result, what) {
70476
70505
  function withoutTrailingNewline(value) {
70477
70506
  return value.replace(/\r?\n$/u, "");
70478
70507
  }
70479
- var spawnRunner = async (file2, args, input2) => await new Promise((resolve2) => {
70508
+ var spawnRunner = async (file2, args, input2) => await new Promise((resolve3) => {
70480
70509
  let stdout = "";
70481
70510
  let stderr2 = "";
70482
70511
  let settled = false;
70483
70512
  const finish = (outcome) => {
70484
70513
  if (settled) return;
70485
70514
  settled = true;
70486
- resolve2(outcome);
70515
+ resolve3(outcome);
70487
70516
  };
70488
70517
  const child = spawn(file2, [...args], {
70489
70518
  detached: true,
@@ -71446,7 +71475,7 @@ async function withVaultLock(path, operation) {
71446
71475
  if (Date.now() >= deadline) {
71447
71476
  throw new VaultError("corrupt", "Timed out waiting for the vault lock.");
71448
71477
  }
71449
- await new Promise((resolve2) => setTimeout(resolve2, 20));
71478
+ await new Promise((resolve3) => setTimeout(resolve3, 20));
71450
71479
  }
71451
71480
  }
71452
71481
  try {
@@ -71479,6 +71508,8 @@ var VAULT_KEY_ACCOUNT = "vault-key";
71479
71508
  var VAULT_SESSION_ACCOUNT = "vault-session";
71480
71509
  var DEVICE_KEY_LENGTH = 32;
71481
71510
  var DEFAULT_SESSION_HOURS = 8;
71511
+ var RESTORE_GAP_LIMIT = 5;
71512
+ var MAX_RESTORE_ACCOUNTS = 1e4;
71482
71513
  var BASE64_PATTERN = /^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$/u;
71483
71514
  var deviceKeyOperations = Promise.resolve();
71484
71515
  var sessionSchema = external_exports.object({
@@ -71628,26 +71659,41 @@ async function restoreVault(args) {
71628
71659
  throw new VaultError("corrupt", "That recovery phrase is not valid.", { cause: error61 });
71629
71660
  }
71630
71661
  let seed;
71631
- let discoveredAccounts = 0;
71662
+ if (args.accountCount !== void 0 && (!Number.isSafeInteger(args.accountCount) || args.accountCount < 1 || args.accountCount > MAX_RESTORE_ACCOUNTS)) {
71663
+ throw new VaultError(
71664
+ "corrupt",
71665
+ `Account count must be a positive integer no greater than ${MAX_RESTORE_ACCOUNTS}.`
71666
+ );
71667
+ }
71668
+ let discoveredAccounts = args.accountCount ?? 0;
71669
+ let scannedAddresses = 0;
71632
71670
  try {
71633
71671
  seed = phraseToSeed(phrase);
71634
71672
  } catch (error61) {
71635
71673
  throw asVaultError2(error61, "Unable to derive an account while restoring the vault.");
71636
71674
  }
71637
71675
  try {
71638
- for (let index2 = 0; ; index2 += 1) {
71676
+ for (let index2 = 0, emptyRun = 0; args.accountCount === void 0; index2 += 1) {
71639
71677
  let address4;
71640
71678
  try {
71641
71679
  address4 = privateKeyToAccount(deriveEvmPrivateKey(seed, `m/44'/60'/0'/0/${index2}`)).address;
71642
71680
  } catch (error61) {
71643
71681
  throw asVaultError2(error61, "Unable to derive an account while restoring the vault.");
71644
71682
  }
71645
- if (!await args.probe(address4)) break;
71646
- discoveredAccounts += 1;
71683
+ const funded = await args.probe(address4);
71684
+ scannedAddresses += 1;
71685
+ if (funded) {
71686
+ discoveredAccounts = index2 + 1;
71687
+ emptyRun = 0;
71688
+ } else {
71689
+ emptyRun += 1;
71690
+ if (emptyRun === RESTORE_GAP_LIMIT) break;
71691
+ }
71647
71692
  }
71648
71693
  } finally {
71649
71694
  seed.fill(0);
71650
71695
  }
71696
+ args.onScanComplete?.(scannedAddresses);
71651
71697
  let vault;
71652
71698
  try {
71653
71699
  vault = await createVault({ path: args.path, key: args.key, phrase, now: args.now });
@@ -72136,6 +72182,26 @@ var WalletStore = class _WalletStore {
72136
72182
  }
72137
72183
  );
72138
72184
  }
72185
+ /** Checks a cached signer's current vault session without decrypting its account again. */
72186
+ async assertSigningAuthority(name) {
72187
+ const stored = await this.readVaultUnlocked();
72188
+ if (!stored?.protected || !stored.accounts.some((account) => account.name === name)) return;
72189
+ try {
72190
+ const key2 = await unlockProtectedVault({
72191
+ path: this.vaultPath,
72192
+ secrets: this.secrets,
72193
+ env: this.environment,
72194
+ now: () => this.now()
72195
+ });
72196
+ key2.fill(0);
72197
+ } catch (error61) {
72198
+ this.dropVaultCache();
72199
+ if (error61 instanceof VaultError && error61.code === "password_required") {
72200
+ throw new KeystoreError(VAULT_LOCKED_MESSAGE, { cause: error61 });
72201
+ }
72202
+ throw error61;
72203
+ }
72204
+ }
72139
72205
  /** Returns one wallet's vault signer, migrating its legacy keystore if needed. */
72140
72206
  async unlock(name, passphrase) {
72141
72207
  const wallet = this.resolve({ name });
@@ -73142,7 +73208,7 @@ async function withRegistryLock(path, operation) {
73142
73208
  if (Date.now() >= deadline) {
73143
73209
  throw new KeystoreError("Timed out waiting for the wallet registry lock.");
73144
73210
  }
73145
- await new Promise((resolve2) => setTimeout(resolve2, 20));
73211
+ await new Promise((resolve3) => setTimeout(resolve3, 20));
73146
73212
  }
73147
73213
  }
73148
73214
  try {
@@ -73488,11 +73554,11 @@ function publicErrorMessage(error61, fallback, sensitiveValues = []) {
73488
73554
  return error61 instanceof Error ? message : fallback;
73489
73555
  }
73490
73556
  async function unrefSleep(milliseconds, signal) {
73491
- await new Promise((resolve2) => {
73557
+ await new Promise((resolve3) => {
73492
73558
  const finish = () => {
73493
73559
  clearTimeout(timer);
73494
73560
  signal?.removeEventListener("abort", finish);
73495
- resolve2();
73561
+ resolve3();
73496
73562
  };
73497
73563
  const timer = setTimeout(finish, milliseconds);
73498
73564
  timer.unref();
@@ -74029,7 +74095,7 @@ async function withLedgerLock(path, operation) {
74029
74095
  if (Date.now() >= deadline) {
74030
74096
  throw new Error("Timed out waiting for the spend ledger lock.");
74031
74097
  }
74032
- await new Promise((resolve2) => setTimeout(resolve2, 20));
74098
+ await new Promise((resolve3) => setTimeout(resolve3, 20));
74033
74099
  }
74034
74100
  }
74035
74101
  try {
@@ -74663,7 +74729,7 @@ async function withTransferLock(context, nonce, operation) {
74663
74729
  if (Date.now() >= deadline) {
74664
74730
  throw new Error("Timed out waiting for the transfer lock.");
74665
74731
  }
74666
- await new Promise((resolve2) => setTimeout(resolve2, 20));
74732
+ await new Promise((resolve3) => setTimeout(resolve3, 20));
74667
74733
  }
74668
74734
  }
74669
74735
  try {
@@ -76381,8 +76447,8 @@ async function sweepAllAboveCeiling(args) {
76381
76447
  }
76382
76448
  var pendingCeilingSweeps = /* @__PURE__ */ new Set();
76383
76449
  function scheduleCeilingSweep(hook) {
76384
- const task = new Promise((resolve2) => {
76385
- setTimeout(resolve2, 0);
76450
+ const task = new Promise((resolve3) => {
76451
+ setTimeout(resolve3, 0);
76386
76452
  }).then(async () => {
76387
76453
  const timeoutMs = hook.timeoutMs ?? CEILING_SWEEP_TIMEOUT_MS;
76388
76454
  const controller = new AbortController();
@@ -76422,8 +76488,8 @@ async function drainCeilingSweeps(timeoutMs = CEILING_SWEEP_TIMEOUT_MS) {
76422
76488
  try {
76423
76489
  await Promise.race([
76424
76490
  Promise.allSettled(pending),
76425
- new Promise((resolve2) => {
76426
- timeout = setTimeout(resolve2, timeoutMs);
76491
+ new Promise((resolve3) => {
76492
+ timeout = setTimeout(resolve3, timeoutMs);
76427
76493
  })
76428
76494
  ]);
76429
76495
  } finally {
@@ -77522,7 +77588,7 @@ function createRunBudget(args) {
77522
77588
  import { mkdir as mkdir15, writeFile as writeFile8 } from "node:fs/promises";
77523
77589
  import { arch, platform, release } from "node:os";
77524
77590
  import { join as join13 } from "node:path";
77525
- var VAPI_CLIENT_VERSION = "0.9.2";
77591
+ var VAPI_CLIENT_VERSION = "0.9.5";
77526
77592
  async function createSupportReport(options) {
77527
77593
  const message = options.message.trim();
77528
77594
  if (!message) throw new Error("Support report message must not be empty.");
@@ -77795,7 +77861,7 @@ async function completeX402Payment(args) {
77795
77861
  let paidAttempt;
77796
77862
  const requestStarted = nowMs();
77797
77863
  try {
77798
- paidAttempt = await args.send(paidRequest);
77864
+ paidAttempt = await args.send(paidRequest, quote);
77799
77865
  } catch (error61) {
77800
77866
  if (trace) trace.phases.requestMs = elapsed(nowMs, requestStarted);
77801
77867
  throw settlementUnknown(
@@ -77813,7 +77879,7 @@ async function completeX402Payment(args) {
77813
77879
  const settleStarted = nowMs();
77814
77880
  const settlement = parseSettlementResponse(paidResponse.headers);
77815
77881
  const settlementOutcome = classifySettlement(settlement);
77816
- const receiptSettlement = sanitizeReceiptValue(settlement, receiptSecrets);
77882
+ const receiptSettlement = sanitizeReturnedValue(settlement, receiptSecrets);
77817
77883
  if (trace) {
77818
77884
  const transaction2 = settlementTransaction(receiptSettlement);
77819
77885
  const explorerUrl = transaction2 ? explorerTransactionUrl(quote.accepted.network, transaction2) : void 0;
@@ -77890,6 +77956,7 @@ async function completeX402Payment(args) {
77890
77956
  trace.phases.requestMs = (trace.phases.requestMs ?? 0) + elapsed(nowMs, bodyStarted);
77891
77957
  }
77892
77958
  }
77959
+ body = sanitizeReturnedValue(body, receiptSecrets);
77893
77960
  }
77894
77961
  const result = {
77895
77962
  response: paidResponse,
@@ -77898,7 +77965,11 @@ async function completeX402Payment(args) {
77898
77965
  quote,
77899
77966
  payer,
77900
77967
  ...payment.paymentId ? { paymentId: payment.paymentId } : {},
77901
- settlement,
77968
+ paymentProof: sanitizeReturnedValue(
77969
+ paidResponse.headers.get("x-vapi-payment-proof"),
77970
+ receiptSecrets
77971
+ ),
77972
+ settlement: receiptSettlement,
77902
77973
  settlementOutcome
77903
77974
  };
77904
77975
  if (settlementOutcome === "succeeded" && args.ceilingSweep) {
@@ -78035,19 +78106,70 @@ function sanitizeThrownError(error61, secrets) {
78035
78106
  }
78036
78107
  return new Error(message, cause === void 0 ? void 0 : { cause });
78037
78108
  }
78038
- function sanitizeReceiptValue(value, secrets, depth = 0) {
78109
+ function sanitizeReturnedValue(value, secrets) {
78039
78110
  if (typeof value === "string") return redactKnownSecrets(value, secrets);
78040
- if (value === null || typeof value !== "object") return value;
78041
- if (depth >= 16) return "[redacted nested settlement value]";
78042
- if (Array.isArray(value)) {
78043
- return value.map((item) => sanitizeReceiptValue(item, secrets, depth + 1));
78111
+ if (!isPlainReturnedContainer(value)) return value;
78112
+ const nodes = /* @__PURE__ */ new WeakMap();
78113
+ const ordered = [];
78114
+ const nodeFor = (source) => {
78115
+ const existing = nodes.get(source);
78116
+ if (existing) return existing;
78117
+ const copy = Array.isArray(source) ? new Array(source.length) : Object.create(Object.getPrototypeOf(source));
78118
+ const node2 = { source, copy, parents: /* @__PURE__ */ new Set(), changed: false };
78119
+ nodes.set(source, node2);
78120
+ ordered.push(node2);
78121
+ return node2;
78122
+ };
78123
+ const root = nodeFor(value);
78124
+ for (let index2 = 0; index2 < ordered.length; index2 += 1) {
78125
+ const node2 = ordered[index2];
78126
+ for (const [key2, item] of Object.entries(node2.source)) {
78127
+ const safeKey = Array.isArray(node2.source) ? key2 : redactKnownSecrets(key2, secrets);
78128
+ if (safeKey !== key2) node2.changed = true;
78129
+ if (typeof item === "string") {
78130
+ const safeItem = redactKnownSecrets(item, secrets);
78131
+ defineReturnedProperty(node2.copy, safeKey, safeItem);
78132
+ if (safeItem !== item) node2.changed = true;
78133
+ } else if (isPlainReturnedContainer(item)) {
78134
+ const child = nodeFor(item);
78135
+ child.parents.add(node2);
78136
+ defineReturnedProperty(node2.copy, safeKey, child.copy);
78137
+ } else {
78138
+ defineReturnedProperty(node2.copy, safeKey, item);
78139
+ }
78140
+ }
78044
78141
  }
78045
- return Object.fromEntries(
78046
- Object.entries(value).map(([key2, item]) => [
78047
- redactKnownSecrets(key2, secrets),
78048
- sanitizeReceiptValue(item, secrets, depth + 1)
78049
- ])
78050
- );
78142
+ const changed = ordered.filter((node2) => node2.changed);
78143
+ for (let index2 = 0; index2 < changed.length; index2 += 1) {
78144
+ for (const parent of changed[index2].parents) {
78145
+ if (parent.changed) continue;
78146
+ parent.changed = true;
78147
+ changed.push(parent);
78148
+ }
78149
+ }
78150
+ for (const node2 of ordered) {
78151
+ for (const [key2, item] of Object.entries(node2.source)) {
78152
+ if (!isPlainReturnedContainer(item)) continue;
78153
+ const safeKey = Array.isArray(node2.source) ? key2 : redactKnownSecrets(key2, secrets);
78154
+ const child = nodes.get(item);
78155
+ defineReturnedProperty(node2.copy, safeKey, child.changed ? child.copy : item);
78156
+ }
78157
+ }
78158
+ return root.changed ? root.copy : value;
78159
+ }
78160
+ function defineReturnedProperty(target, key2, value) {
78161
+ Object.defineProperty(target, key2, {
78162
+ value,
78163
+ enumerable: true,
78164
+ configurable: true,
78165
+ writable: true
78166
+ });
78167
+ }
78168
+ function isPlainReturnedContainer(value) {
78169
+ if (Array.isArray(value)) return true;
78170
+ if (value === null || typeof value !== "object") return false;
78171
+ const prototype = Object.getPrototypeOf(value);
78172
+ return prototype === Object.prototype || prototype === null;
78051
78173
  }
78052
78174
  function redactKnownSecrets(value, secrets) {
78053
78175
  let redacted = value;
@@ -78082,9 +78204,7 @@ function possibleSettlement(quote, payment, payer, receipt) {
78082
78204
  payTo: quote.accepted.payTo,
78083
78205
  payer,
78084
78206
  ...payment.paymentId ? { paymentId: payment.paymentId } : {},
78085
- ...isSvmPaymentRequirements(quote.accepted) ? {
78086
- authorizationTransaction: "transaction" in payment.payload.payload ? payment.payload.payload.transaction : ""
78087
- } : "authorization" in payment.payload.payload ? {
78207
+ ...isSvmPaymentRequirements(quote.accepted) ? {} : "authorization" in payment.payload.payload ? {
78088
78208
  authorizationNonce: payment.payload.payload.authorization.nonce,
78089
78209
  authorizationExpiresAt: payment.payload.payload.authorization.validBefore
78090
78210
  } : {},
@@ -78462,13 +78582,22 @@ async function sendRouterChat(deps, routerBaseUrl, routerKey, request, keyUsed)
78462
78582
  }
78463
78583
  const body = await responseText(response);
78464
78584
  if (!response.ok) {
78465
- if (response.status === 429 || body.includes("Budget has been exceeded") || body.includes("ExceededBudget")) {
78585
+ if (/budget (?:has been )?exceeded|exceededbudget/iu.test(body)) {
78466
78586
  throw new RouterClientError(
78467
78587
  "budget_exhausted",
78468
78588
  "The Router key has no remaining budget.",
78469
78589
  response.status
78470
78590
  );
78471
78591
  }
78592
+ if (response.status === 429) {
78593
+ const retryAfter = response.headers.get("retry-after")?.trim();
78594
+ const retrySeconds = retryAfter !== void 0 && /^\d+$/u.test(retryAfter) ? Number(retryAfter) : void 0;
78595
+ throw new RouterClientError(
78596
+ "rate_limited",
78597
+ `The vAPI Router is rate limited. ${retrySeconds !== void 0 && Number.isFinite(retrySeconds) ? `Retry after ${retrySeconds} seconds.` : "Wait and retry shortly."}`,
78598
+ response.status
78599
+ );
78600
+ }
78472
78601
  if (response.status === 401) {
78473
78602
  throw new RouterClientError(
78474
78603
  "no_router_key",
@@ -81165,7 +81294,7 @@ var authorizationTypes = {
81165
81294
  function createTasksChain(options) {
81166
81295
  const { account, client, pending, rpcFor } = options;
81167
81296
  const now = options.now ?? (() => /* @__PURE__ */ new Date());
81168
- const sleep = options.sleep ?? ((ms) => new Promise((resolve2) => setTimeout(resolve2, ms)));
81297
+ const sleep = options.sleep ?? ((ms) => new Promise((resolve3) => setTimeout(resolve3, ms)));
81169
81298
  const randomBytes17 = options.randomBytes ?? cryptoRandomBytes2;
81170
81299
  const confirmations = options.confirmations ?? 2;
81171
81300
  if (!Number.isSafeInteger(confirmations) || confirmations < 1)
@@ -81970,7 +82099,7 @@ async function waitForMilestone(client, input2) {
81970
82099
  throw new RangeError("The milestone wait timeout must be non-negative and finite.");
81971
82100
  if (!Number.isFinite(intervalMs) || intervalMs <= 0)
81972
82101
  throw new RangeError("The milestone wait interval must be positive and finite.");
81973
- const sleep = input2.sleep ?? ((ms) => new Promise((resolve2) => setTimeout(resolve2, ms)));
82102
+ const sleep = input2.sleep ?? ((ms) => new Promise((resolve3) => setTimeout(resolve3, ms)));
81974
82103
  const now = input2.now ?? (() => /* @__PURE__ */ new Date());
81975
82104
  const started = now().getTime();
81976
82105
  const deadline = started + timeoutMs;
@@ -86572,10 +86701,10 @@ async function buildStatus(deps) {
86572
86701
  const timers = deps.timers ?? { setTimeout, clearTimeout };
86573
86702
  const controller = new AbortController();
86574
86703
  let timeout;
86575
- const deadline = new Promise((resolve2) => {
86704
+ const deadline = new Promise((resolve3) => {
86576
86705
  timeout = timers.setTimeout(() => {
86577
86706
  controller.abort(new Error("Status request deadline exceeded."));
86578
- resolve2();
86707
+ resolve3();
86579
86708
  }, deps.timeoutMs ?? STATUS_TIMEOUT_MS);
86580
86709
  });
86581
86710
  try {
@@ -87745,12 +87874,13 @@ var BODY_HEADER_NAMES = [
87745
87874
  "content-type"
87746
87875
  ];
87747
87876
  async function callService(args) {
87877
+ validateTimeoutSeconds(args.input.timeoutSeconds);
87748
87878
  const trace = createCallTrace(args);
87749
87879
  let execution;
87750
87880
  try {
87751
87881
  execution = await executeCallService(args, trace);
87752
87882
  } catch (error61) {
87753
- if (!(error61 instanceof VapiCallError && error61.code === "unsupported_network")) {
87883
+ if (!(error61 instanceof VapiCallError && (error61.code === "unsupported_network" || error61.code === "unsupported_payment"))) {
87754
87884
  await recordCallError(args, error61, trace).catch(() => void 0);
87755
87885
  }
87756
87886
  throw error61;
@@ -87864,6 +87994,8 @@ async function executeCallService(args, trace) {
87864
87994
  body: method === "GET" || method === "HEAD" ? void 0 : requestBody
87865
87995
  });
87866
87996
  const request = createRequest(headers);
87997
+ const probeTimeoutMs = input2.timeoutSeconds === void 0 ? args.timeoutMs ?? 3e4 : Math.min(input2.timeoutSeconds, 30) * 1e3;
87998
+ let requestTimeoutMs = probeTimeoutMs;
87867
87999
  const fetchWithGuardedRedirects = async (candidateRequest, followRedirects = true) => {
87868
88000
  let currentRequest = candidateRequest;
87869
88001
  let followedRedirects = 0;
@@ -87871,7 +88003,7 @@ async function executeCallService(args, trace) {
87871
88003
  const attempt = await fetchAttempt(
87872
88004
  fetchImpl,
87873
88005
  new Request(currentRequest.clone(), { redirect: "manual" }),
87874
- args.timeoutMs ?? 3e4
88006
+ requestTimeoutMs
87875
88007
  );
87876
88008
  const response = attempt.response;
87877
88009
  if (!isRedirectStatus2(response.status)) {
@@ -88026,7 +88158,12 @@ async function executeCallService(args, trace) {
88026
88158
  account,
88027
88159
  caps: args.spendCaps ?? config2.spendCaps,
88028
88160
  config: payableConfig(config2, account),
88029
- send: async (paidRequest) => {
88161
+ send: async (paidRequest, quote) => {
88162
+ requestTimeoutMs = paidRequestTimeoutMs(
88163
+ input2.timeoutSeconds,
88164
+ args.timeoutMs,
88165
+ quote.accepted.maxTimeoutSeconds
88166
+ );
88030
88167
  paidAttempt = await fetchWithGuardedRedirects(paidRequest, false);
88031
88168
  return paidAttempt;
88032
88169
  },
@@ -88065,7 +88202,7 @@ async function executeCallService(args, trace) {
88065
88202
  asset: completed.quote.accepted.asset,
88066
88203
  payTo: completed.quote.accepted.payTo,
88067
88204
  settlement: settlementWithExplorer2(completed.settlement, completed.quote.accepted.network),
88068
- proof: completed.response.headers.get("x-vapi-payment-proof")
88205
+ proof: completed.paymentProof
88069
88206
  },
88070
88207
  ...verificationFor(endpoint),
88071
88208
  ...expectedRequestFor(endpoint, completed.response.status)
@@ -88312,8 +88449,16 @@ async function resolveCallEndpoint(id2, endpointName, marketplaceHit, config2, f
88312
88449
  );
88313
88450
  }
88314
88451
  function registeredEndpoint(listing, verification) {
88452
+ const { payment, ...endpoint } = listing.endpoint;
88453
+ if (payment && (typeof payment.protocol === "string" || typeof payment.network !== "string")) {
88454
+ throw new VapiCallError(
88455
+ "unsupported_payment",
88456
+ `Payment protocol ${payment.protocol} is not supported. This client pays x402 exact USDC endpoints only.`
88457
+ );
88458
+ }
88315
88459
  return {
88316
- ...listing.endpoint,
88460
+ ...endpoint,
88461
+ ...payment ? { payment: { network: payment.network, payTo: payment.payTo } } : {},
88317
88462
  verification: verification ?? listing.service.verification,
88318
88463
  serviceNetworks: listing.service.networks,
88319
88464
  registered: true,
@@ -88475,7 +88620,7 @@ async function readResponseBody2(response) {
88475
88620
  async function fetchAttempt(fetchImpl, request, timeoutMs) {
88476
88621
  const controller = new AbortController();
88477
88622
  let rejectTimeout = null;
88478
- const timeoutError = new Error(`API request timed out after ${timeoutMs}ms.`);
88623
+ const timeoutError = new Error(`API request timed out after ${timeoutMs / 1e3} seconds.`);
88479
88624
  const timedOut = new Promise((_resolve, reject) => {
88480
88625
  rejectTimeout = reject;
88481
88626
  });
@@ -88515,6 +88660,19 @@ async function fetchAttempt(fetchImpl, request, timeoutMs) {
88515
88660
  throw error61;
88516
88661
  }
88517
88662
  }
88663
+ function validateTimeoutSeconds(timeoutSeconds) {
88664
+ if (timeoutSeconds !== void 0 && (!Number.isInteger(timeoutSeconds) || timeoutSeconds < 1 || timeoutSeconds > 300)) {
88665
+ throw new Error("call timeoutSeconds must be an integer from 1 to 300 seconds.");
88666
+ }
88667
+ }
88668
+ function paidRequestTimeoutMs(timeoutSeconds, internalTimeoutMs, offerTimeoutSeconds) {
88669
+ const usableOfferTimeout = Number.isInteger(offerTimeoutSeconds) && offerTimeoutSeconds > 0 ? offerTimeoutSeconds : void 0;
88670
+ if (timeoutSeconds !== void 0) {
88671
+ return Math.min(timeoutSeconds, usableOfferTimeout ?? timeoutSeconds) * 1e3;
88672
+ }
88673
+ if (internalTimeoutMs !== void 0) return internalTimeoutMs;
88674
+ return usableOfferTimeout === void 0 ? 12e4 : Math.min(12e4, Math.max(3e4, usableOfferTimeout * 1e3));
88675
+ }
88518
88676
  function mapX402PaymentError(error61, resumeId) {
88519
88677
  if (!(error61 instanceof X402PaymentError)) return error61;
88520
88678
  if (error61.code === "payment_rejected") {
@@ -88530,9 +88688,10 @@ function mapX402PaymentError(error61, resumeId) {
88530
88688
  });
88531
88689
  }
88532
88690
  const resume = resumeId !== void 0 && error61.possibleSettlement?.authorizationNonce ? ` Check whether it settled with \`vapi pay --resume ${resumeId}\` before paying again.` : "";
88691
+ const timeoutDetail = error61.cause instanceof Error && error61.cause.message.startsWith("API request timed out after ") ? `${error61.cause.message} ` : "";
88533
88692
  return new VapiCallError(
88534
88693
  "settlement_unknown",
88535
- `${error61.message}${resume}`,
88694
+ `${timeoutDetail}${error61.message}${resume}`,
88536
88695
  error61.possibleSettlement,
88537
88696
  { cause: error61.cause }
88538
88697
  );
@@ -88664,13 +88823,7 @@ var inspectToolResultSchema = external_exports.object({
88664
88823
  liveness: listingLivenessSchema.optional(),
88665
88824
  conformance: listingConformanceSchema.optional(),
88666
88825
  identity: listingIdentitySchema.optional(),
88667
- payment: external_exports.object({
88668
- scheme: external_exports.literal("exact"),
88669
- network: external_exports.string(),
88670
- asset: external_exports.string(),
88671
- payTo: external_exports.string(),
88672
- checkedAt: external_exports.string()
88673
- }).nullable()
88826
+ payment: discoveryEndpointSchema.shape.payment.unwrap().nullable()
88674
88827
  });
88675
88828
  var callSearchInputSchema = external_exports.object({
88676
88829
  query: external_exports.string().trim().max(200).optional().describe("Capability, API, service, or request."),
@@ -88699,7 +88852,10 @@ var callPayInputSchema = external_exports.object({
88699
88852
  (value) => /^0x[0-9a-fA-F]{40}$/.test(value) || isSolanaAddress(value),
88700
88853
  "Expected an EVM or Solana address."
88701
88854
  ).optional(),
88702
- maxPriceUsd: external_exports.union([external_exports.number().nonnegative(), external_exports.string().regex(/^\d+(?:\.\d{1,6})?$/)]).optional()
88855
+ maxPriceUsd: external_exports.union([external_exports.number().nonnegative(), external_exports.string().regex(/^\d+(?:\.\d{1,6})?$/)]).optional(),
88856
+ timeoutSeconds: external_exports.number().int().min(1).max(300).optional().describe(
88857
+ "Seconds to wait for the paid response. Default: the provider's maxTimeoutSeconds, at most 120."
88858
+ )
88703
88859
  });
88704
88860
  var callSearch = defineAction({
88705
88861
  name: "call.search",
@@ -88962,7 +89118,7 @@ async function readResult(response, signal, secrets = []) {
88962
89118
  return {
88963
89119
  status: response.status,
88964
89120
  contentType: contentType === null ? null : redactKnownSecrets2(contentType, secrets),
88965
- body: sanitizeReturnedValue(await readResponseBody3(response, contentType, signal), secrets)
89121
+ body: sanitizeReturnedValue2(await readResponseBody3(response, contentType, signal), secrets)
88966
89122
  };
88967
89123
  }
88968
89124
  async function readResponseBody3(response, contentType, signal) {
@@ -89007,17 +89163,17 @@ function isJsonContentType2(value) {
89007
89163
  const mediaType = value?.split(";", 1)[0]?.trim().toLowerCase() ?? "";
89008
89164
  return mediaType === "application/json" || mediaType.endsWith("+json");
89009
89165
  }
89010
- function sanitizeReturnedValue(value, secrets, depth = 0) {
89166
+ function sanitizeReturnedValue2(value, secrets, depth = 0) {
89011
89167
  if (typeof value === "string") return redactKnownSecrets2(value, secrets);
89012
89168
  if (value === null || typeof value !== "object") return value;
89013
89169
  if (depth >= 16) return "[redacted nested response value]";
89014
89170
  if (Array.isArray(value)) {
89015
- return value.map((item) => sanitizeReturnedValue(item, secrets, depth + 1));
89171
+ return value.map((item) => sanitizeReturnedValue2(item, secrets, depth + 1));
89016
89172
  }
89017
89173
  return Object.fromEntries(
89018
89174
  Object.entries(value).map(([key2, item]) => [
89019
89175
  redactKnownSecrets2(key2, secrets),
89020
- sanitizeReturnedValue(item, secrets, depth + 1)
89176
+ sanitizeReturnedValue2(item, secrets, depth + 1)
89021
89177
  ])
89022
89178
  );
89023
89179
  }
@@ -94523,7 +94679,13 @@ function toolError(error61) {
94523
94679
  {
94524
94680
  error: error61.message,
94525
94681
  code: error61.code,
94526
- ...error61.possibleSettlement ? { possibleSettlement: error61.possibleSettlement } : {},
94682
+ ...error61.possibleSettlement ? {
94683
+ possibleSettlement: Object.fromEntries(
94684
+ Object.entries(error61.possibleSettlement).filter(
94685
+ ([key2]) => key2 !== "authorizationTransaction"
94686
+ )
94687
+ )
94688
+ } : {},
94527
94689
  ...error61.paymentRejection ? { paymentRejection: error61.paymentRejection } : {},
94528
94690
  ...error61.confirmedSettlement ? { confirmedSettlement: error61.confirmedSettlement } : {}
94529
94691
  },
@@ -94705,6 +94867,9 @@ function rgbToAnsi256(red, green, blue) {
94705
94867
  import { readFile as readFile24, stat as stat14 } from "node:fs/promises";
94706
94868
  import { join as join21 } from "node:path";
94707
94869
 
94870
+ // src/dashboard.ts
94871
+ import { resolve as resolve2 } from "node:path";
94872
+
94708
94873
  // src/publish-client.ts
94709
94874
  var LISTING_CATEGORIES = ["ai", "data", "crypto", "compute", "search"];
94710
94875
  var PROBE_MODES = ["origin", "endpoint", "openapi"];
@@ -95025,7 +95190,8 @@ async function runLoginFlow(argv, json2, io, dependencies, options = {}) {
95025
95190
  booleanOptions: /* @__PURE__ */ new Set(["--publish", "--no-browser"]),
95026
95191
  maximumPositionals: 0
95027
95192
  });
95028
- const target = await targetWallet(parsed, dependencies);
95193
+ const paths = getVapiPaths(options.home);
95194
+ const target = await targetWallet(parsed, dependencies, paths.directory);
95029
95195
  const { account } = await unlockTarget(target, dependencies);
95030
95196
  const label = parsed.one("--label") ?? target.name;
95031
95197
  const scopes = [
@@ -95034,13 +95200,13 @@ async function runLoginFlow(argv, json2, io, dependencies, options = {}) {
95034
95200
  "tasks:write",
95035
95201
  ...parsed.has("--publish") ? ["call.publish"] : []
95036
95202
  ];
95037
- const config2 = await loadConfig(getVapiPaths().config, process.env, { notice: io.stderr });
95038
- const apiBase = registryBaseUrl(config2);
95203
+ const config2 = await loadConfig(paths.config, process.env, { notice: io.stderr });
95204
+ const apiBase = options.apiBase ?? registryBaseUrl(config2);
95039
95205
  const fetchImpl = dependencies.fetchImpl ?? createPublicFetch({ allowPrivateNetwork: false });
95040
95206
  const secrets = getSecretStore(dependencies);
95041
95207
  const device = await ensureDeviceName({
95042
95208
  env: getEnvironment(dependencies),
95043
- configPath: getVapiPaths().config,
95209
+ configPath: paths.config,
95044
95210
  ...dependencies.hostname === void 0 ? {} : { hostname: dependencies.hostname() }
95045
95211
  });
95046
95212
  const bearer = await trustedLinkBearer({
@@ -95294,6 +95460,87 @@ function shortAddress(address4) {
95294
95460
  return address4.length <= 12 ? address4 : `${address4.slice(0, 6)}\u2026${address4.slice(-4)}`;
95295
95461
  }
95296
95462
 
95463
+ // src/dashboard.ts
95464
+ function dashboardUrl(apiBase) {
95465
+ return `${apiBase.replace(/\/+$/u, "")}/agents`;
95466
+ }
95467
+ async function offerDashboardLink({
95468
+ name,
95469
+ json: json2,
95470
+ noLink = false,
95471
+ io,
95472
+ dependencies,
95473
+ home = getVapiPaths().directory,
95474
+ apiBase
95475
+ }) {
95476
+ const otherHome = resolve2(home) !== resolve2(getVapiPaths().directory);
95477
+ const command = `${otherHome ? `VAPI_HOME=${shellQuote(home)} ` : ""}${apiBase === void 0 ? "" : `VAPI_REGISTRY_URL=${shellQuote(apiBase)} `}vapi login --account ${name}`;
95478
+ const unlinked = {
95479
+ linked: false,
95480
+ next: [{ kind: "link", account: name, command }]
95481
+ };
95482
+ const hint = () => {
95483
+ if (!json2) io.stdout(`Run \`${command}\` to see this wallet on your dashboard.`);
95484
+ return unlinked;
95485
+ };
95486
+ try {
95487
+ const store = await WalletStore.open(home, {
95488
+ secrets: getSecretStore(dependencies),
95489
+ env: getEnvironment(dependencies)
95490
+ });
95491
+ if (store.entry(name)?.link !== void 0) return { linked: true };
95492
+ if (noLink || json2 || !isInteractive(dependencies) || activeAgentMarker(getEnvironment(dependencies)) !== void 0) {
95493
+ return hint();
95494
+ }
95495
+ const answer = (await getLinePrompt(dependencies)(`Link ${name} to your vAPI dashboard? [Y/n] `)).trim();
95496
+ if (!/^(?:y|yes)?$/iu.test(answer)) return hint();
95497
+ await runLoginFlow(["--account", name, "--label", name], false, io, dependencies, {
95498
+ home,
95499
+ ...apiBase === void 0 ? {} : { apiBase }
95500
+ });
95501
+ await store.reload();
95502
+ const link3 = store.entry(name)?.link;
95503
+ if (link3 === void 0) return hint();
95504
+ io.stdout(`See it on your dashboard: ${dashboardUrl(link3.apiBase)}`);
95505
+ return { linked: true };
95506
+ } catch (error61) {
95507
+ if (!json2) {
95508
+ io.stderr(`Link not completed: ${error61 instanceof Error ? error61.message : String(error61)}`);
95509
+ }
95510
+ return hint();
95511
+ }
95512
+ }
95513
+ async function dashboardCommand(argv, json2, io, dependencies) {
95514
+ const parsed = parseArguments(argv, {
95515
+ valueOptions: /* @__PURE__ */ new Set(["--wallet"]),
95516
+ booleanOptions: /* @__PURE__ */ new Set(["--no-browser", "--no-link"]),
95517
+ maximumPositionals: 0
95518
+ });
95519
+ const target = await targetWallet(parsed, dependencies);
95520
+ let status = { linked: true };
95521
+ if (target.entry.link === void 0) {
95522
+ if (!json2) io.stdout(`${target.name} is not linked to your vAPI dashboard yet.`);
95523
+ status = await offerDashboardLink({
95524
+ name: target.name,
95525
+ json: json2,
95526
+ noLink: parsed.has("--no-link"),
95527
+ io,
95528
+ dependencies: parsed.has("--no-browser") ? { ...dependencies, openUrl: () => false } : dependencies
95529
+ });
95530
+ }
95531
+ await target.store.reload();
95532
+ const apiBase = target.store.entry(target.name)?.link?.apiBase ?? registryBaseUrl(await readConfig(getVapiPaths().config, io));
95533
+ const url2 = dashboardUrl(apiBase);
95534
+ let opened = false;
95535
+ if (status.linked && !parsed.has("--no-browser") && (dependencies.interactive ?? Boolean(process.stdout.isTTY)) && activeAgentMarker(getEnvironment(dependencies)) === void 0) {
95536
+ opened = (dependencies.openUrl ?? openInBrowser)(url2);
95537
+ }
95538
+ io.stdout(json2 ? JSON.stringify({ account: target.name, url: url2, ...status, opened }) : url2);
95539
+ }
95540
+ function shellQuote(value) {
95541
+ return /^[a-zA-Z0-9_./-]+$/u.test(value) ? value : `'${value.replace(/'/gu, "'\\''")}'`;
95542
+ }
95543
+
95297
95544
  // src/status.ts
95298
95545
  import { stat as stat13 } from "node:fs/promises";
95299
95546
  import { homedir as homedir2 } from "node:os";
@@ -97679,10 +97926,10 @@ function apiEndpoint2(apiBase, path) {
97679
97926
  }
97680
97927
  async function sleepFor2(milliseconds, signal) {
97681
97928
  if (signal?.aborted === true) throw signal.reason;
97682
- await new Promise((resolve2, reject) => {
97929
+ await new Promise((resolve3, reject) => {
97683
97930
  const finish = () => {
97684
97931
  signal?.removeEventListener("abort", abort);
97685
- resolve2();
97932
+ resolve3();
97686
97933
  };
97687
97934
  const timeout = setTimeout(finish, milliseconds);
97688
97935
  const abort = () => {
@@ -98017,7 +98264,7 @@ async function readProcessStdin() {
98017
98264
  }
98018
98265
 
98019
98266
  // src/version.ts
98020
- var CLI_VERSION = "0.9.2";
98267
+ var CLI_VERSION = "0.9.5";
98021
98268
 
98022
98269
  // src/status.ts
98023
98270
  async function statusCommand(argv, json2, io, dependencies) {
@@ -98161,10 +98408,10 @@ async function runStatusSweep(args) {
98161
98408
  timeoutMs,
98162
98409
  ...args.warn === void 0 ? {} : { warn: args.warn }
98163
98410
  }),
98164
- new Promise((resolve2) => {
98411
+ new Promise((resolve3) => {
98165
98412
  timeout = setTimeout(() => {
98166
98413
  controller.abort();
98167
- resolve2();
98414
+ resolve3();
98168
98415
  }, timeoutMs);
98169
98416
  timeout.unref();
98170
98417
  })
@@ -98393,7 +98640,7 @@ async function siblingsFetchImpl(dependencies) {
98393
98640
  function shortAddress3(address4) {
98394
98641
  return address4.length <= 12 ? address4 : `${address4.slice(0, 6)}\u2026${address4.slice(-4)}`;
98395
98642
  }
98396
- async function accountsAddCommand(argv, json2, io, dependencies) {
98643
+ async function accountsAddCommand(argv, json2, io, dependencies, options = { link: "always" }) {
98397
98644
  const parsed = parseArguments(argv, {
98398
98645
  valueOptions: /* @__PURE__ */ new Set(["--label"]),
98399
98646
  booleanOptions: /* @__PURE__ */ new Set(["--no-link"]),
@@ -98410,6 +98657,18 @@ async function accountsAddCommand(argv, json2, io, dependencies) {
98410
98657
  });
98411
98658
  await recordAudit(dependencies, "wallet.create", { wallet: created.account });
98412
98659
  const address4 = created.address;
98660
+ if (options.link === "offer") {
98661
+ if (!json2) io.stdout(`Account ${created.account} derived: ${address4}`);
98662
+ const link3 = await offerDashboardLink({
98663
+ name: created.account,
98664
+ json: json2,
98665
+ noLink: parsed.has("--no-link"),
98666
+ io,
98667
+ dependencies
98668
+ });
98669
+ if (json2) io.stdout(JSON.stringify({ account: created.account, address: address4, ...link3 }));
98670
+ return;
98671
+ }
98413
98672
  if (parsed.has("--no-link")) {
98414
98673
  output2(
98415
98674
  io,
@@ -99225,10 +99484,10 @@ async function autoUploadBackup(io, json2, dependencies) {
99225
99484
  const timeoutMs = dependencies.cloudBackup?.uploadTimeoutMs ?? DEFAULT_UPLOAD_TIMEOUT_MS;
99226
99485
  const controller = new AbortController();
99227
99486
  let timer;
99228
- const timeout = new Promise((resolve2) => {
99487
+ const timeout = new Promise((resolve3) => {
99229
99488
  timer = setTimeout(() => {
99230
99489
  controller.abort();
99231
- resolve2({ status: "skipped", reason: "timeout" });
99490
+ resolve3({ status: "skipped", reason: "timeout" });
99232
99491
  }, timeoutMs);
99233
99492
  timer.unref();
99234
99493
  });
@@ -100452,7 +100711,7 @@ var HTTP_NOT_FOUND_PATTERN = /\b404\b/u;
100452
100711
  var OTHER_SCOPE_PATTERN = /\b(?:project|environment|service|workspace|team|token|user|account|volume|deployment|command|file|directory|module|package)s?\b/iu;
100453
100712
  var SIDECAR_SUFFIX = ".railway.json";
100454
100713
  var MINIMUM_SECRET_LENGTH = 8;
100455
- var defaultRailwayExec = (file2, args) => new Promise((resolve2, reject) => {
100714
+ var defaultRailwayExec = (file2, args) => new Promise((resolve3, reject) => {
100456
100715
  const child = spawn2(file2, [...args], {
100457
100716
  stdio: ["ignore", "pipe", "pipe"],
100458
100717
  env: process.env,
@@ -100467,7 +100726,7 @@ var defaultRailwayExec = (file2, args) => new Promise((resolve2, reject) => {
100467
100726
  stderr2 += chunk;
100468
100727
  });
100469
100728
  child.once("error", reject);
100470
- child.once("close", (code) => resolve2({ code, stdout, stderr: stderr2 }));
100729
+ child.once("close", (code) => resolve3({ code, stdout, stderr: stderr2 }));
100471
100730
  });
100472
100731
  function parseSandboxId(stdout) {
100473
100732
  const trimmed = stdout.trim();
@@ -100600,8 +100859,8 @@ function createRailwayRuntime(options) {
100600
100859
  const readyAttempts = options.readyAttempts ?? DEFAULT_RAILWAY_READY_ATTEMPTS;
100601
100860
  const readyIntervalMs = options.readyIntervalMs ?? DEFAULT_RAILWAY_READY_INTERVAL_MS;
100602
100861
  const signalDestroyTimeoutMs = options.signalDestroyTimeoutMs ?? DEFAULT_RAILWAY_SIGNAL_DESTROY_TIMEOUT_MS;
100603
- const sleep = options.sleep ?? ((milliseconds) => new Promise((resolve2) => {
100604
- setTimeout(resolve2, milliseconds);
100862
+ const sleep = options.sleep ?? ((milliseconds) => new Promise((resolve3) => {
100863
+ setTimeout(resolve3, milliseconds);
100605
100864
  }));
100606
100865
  let secrets = options.secrets;
100607
100866
  const getSecrets = () => secrets ??= secretStore();
@@ -101519,7 +101778,7 @@ function createLocalRuntime(options) {
101519
101778
  const processCommand = options.processCommand ?? defaultProcessCommand;
101520
101779
  const ownsProcess = (handle, pid) => processCommand(pid)?.includes(runResultPath(home, handle.runId)) === true;
101521
101780
  const closeFd = options.closeFd ?? closeSync2;
101522
- const readFile29 = options.readFile ?? nodeReadFile;
101781
+ const readFile30 = options.readFile ?? nodeReadFile;
101523
101782
  const now = options.now ?? (() => /* @__PURE__ */ new Date());
101524
101783
  const openLog = options.openLog ?? ((path) => {
101525
101784
  mkdirSync2(runsDirectory(home), { recursive: true, mode: 448 });
@@ -101574,7 +101833,7 @@ function createLocalRuntime(options) {
101574
101833
  return handle;
101575
101834
  },
101576
101835
  async status(handle) {
101577
- const result = await readResultFile(readFile29, runResultPath(home, handle.runId));
101836
+ const result = await readResultFile(readFile30, runResultPath(home, handle.runId));
101578
101837
  if (result !== void 0) return result;
101579
101838
  const pid = localPid(handle);
101580
101839
  if (pid === void 0 || handle.kind !== "local") {
@@ -101677,10 +101936,10 @@ function childArguments(member, run) {
101677
101936
  ...run.drawUsd ? ["--draw", run.drawUsd] : []
101678
101937
  ];
101679
101938
  }
101680
- async function readResultFile(readFile29, path) {
101939
+ async function readResultFile(readFile30, path) {
101681
101940
  let text;
101682
101941
  try {
101683
- text = await readFile29(path, "utf8");
101942
+ text = await readFile30(path, "utf8");
101684
101943
  } catch (error61) {
101685
101944
  if (hasCode3(error61, "ENOENT")) return void 0;
101686
101945
  return { state: "failed", detail: "unreadable result file" };
@@ -102454,7 +102713,7 @@ function usd(value, minimumDecimals = 0) {
102454
102713
  import { mkdir as mkdir20, readFile as readFile27, writeFile as writeFile11 } from "node:fs/promises";
102455
102714
  import { homedir as systemHomedir } from "node:os";
102456
102715
  import { dirname as dirname14, posix, win32 as win322 } from "node:path";
102457
- var MCP_INSTALL_USAGE = "Usage: vapi mcp install <claude|cursor|codex> [--home <dir>] [--registry <url>] [--json]";
102716
+ var MCP_INSTALL_USAGE = "Usage: vapi mcp install <claude|cursor|codex> [--home <dir>] [--registry <url>] [--no-link] [--json]";
102458
102717
  var APPS = /* @__PURE__ */ new Set(["claude", "cursor", "codex"]);
102459
102718
  var NEXT_STEP = {
102460
102719
  claude: 'Restart Claude Desktop, then ask it: "Search vAPI for a weather API."',
@@ -102495,6 +102754,7 @@ function mcpInstallTarget(app, context) {
102495
102754
  async function mcpInstallCommand(argv, json2, io, dependencies) {
102496
102755
  const parsed = parseArguments(argv, {
102497
102756
  valueOptions: /* @__PURE__ */ new Set(["--home", "--registry"]),
102757
+ booleanOptions: /* @__PURE__ */ new Set(["--no-link"]),
102498
102758
  maximumPositionals: 1
102499
102759
  });
102500
102760
  const appValue = parsed.positionals[0];
@@ -102516,13 +102776,39 @@ ${MCP_INSTALL_USAGE}`
102516
102776
  });
102517
102777
  const entry = serverEntry(home, registry2);
102518
102778
  const created = await writeMcpConfig(target, entry);
102779
+ const name = await unlinkedDefaultAccount(home, dependencies);
102780
+ const offerLink = (name2) => offerDashboardLink({
102781
+ name: name2,
102782
+ json: json2,
102783
+ noLink: parsed.has("--no-link"),
102784
+ io,
102785
+ dependencies,
102786
+ home,
102787
+ apiBase: parsed.one("--registry")
102788
+ });
102789
+ const link3 = json2 && name !== void 0 ? await offerLink(name) : {};
102519
102790
  output3(
102520
102791
  io,
102521
102792
  json2,
102522
- { command: "mcp install", app: appValue, path: target.path, created, home, registry: registry2 },
102793
+ { ...link3, command: "mcp install", app: appValue, path: target.path, created, home, registry: registry2 },
102523
102794
  `${created ? "Wrote" : "Updated"} ${target.path}.`
102524
102795
  );
102525
- if (!json2) io.stdout(NEXT_STEP[appValue]);
102796
+ if (!json2) {
102797
+ io.stdout(NEXT_STEP[appValue]);
102798
+ if (name !== void 0) await offerLink(name);
102799
+ }
102800
+ }
102801
+ async function unlinkedDefaultAccount(home, dependencies) {
102802
+ try {
102803
+ const store = await WalletStore.open(home, {
102804
+ secrets: getSecretStore(dependencies),
102805
+ env: getEnvironment(dependencies)
102806
+ });
102807
+ const name = store.defaultName;
102808
+ if (name !== void 0 && store.resolve({ name }).entry.link === void 0) return name;
102809
+ } catch {
102810
+ }
102811
+ return void 0;
102526
102812
  }
102527
102813
  function isMcpInstallApp(value) {
102528
102814
  return APPS.has(value);
@@ -102530,7 +102816,7 @@ function isMcpInstallApp(value) {
102530
102816
  function serverEntry(home, registry2) {
102531
102817
  return {
102532
102818
  command: "npx",
102533
- args: ["-y", "vapi-network", "mcp"],
102819
+ args: ["-y", "vapi-network@latest", "mcp"],
102534
102820
  env: { VAPI_HOME: home, VAPI_REGISTRY_URL: registry2 }
102535
102821
  };
102536
102822
  }
@@ -102579,7 +102865,7 @@ function tomlConfig(existing, entry) {
102579
102865
  const block = [
102580
102866
  "[mcp_servers.vapi]",
102581
102867
  'command = "npx"',
102582
- 'args = ["-y", "vapi-network", "mcp"]',
102868
+ 'args = ["-y", "vapi-network@latest", "mcp"]',
102583
102869
  `env = { VAPI_HOME = "${escapeToml(entry.env.VAPI_HOME)}", VAPI_REGISTRY_URL = "${escapeToml(entry.env.VAPI_REGISTRY_URL)}" }`,
102584
102870
  ""
102585
102871
  ].join("\n");
@@ -102746,13 +103032,13 @@ async function sendConfig(dependencies) {
102746
103032
  // src/setup.ts
102747
103033
  import { rm as rm5 } from "node:fs/promises";
102748
103034
  import { join as join26 } from "node:path";
102749
- 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.";
103035
+ 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.`;
102750
103036
  var VAULT_CHOICE = "Create a new vault, or restore one from a recovery phrase? [new/restore] ";
102751
103037
  async function setupCommand(argv, json2, io, dependencies) {
102752
103038
  let parsed;
102753
103039
  try {
102754
103040
  parsed = parseArguments(argv, {
102755
- valueOptions: /* @__PURE__ */ new Set(),
103041
+ valueOptions: /* @__PURE__ */ new Set(["--accounts"]),
102756
103042
  booleanOptions: /* @__PURE__ */ new Set(["--no-cloud-backup"]),
102757
103043
  maximumPositionals: 0
102758
103044
  });
@@ -102763,6 +103049,7 @@ async function setupCommand(argv, json2, io, dependencies) {
102763
103049
  const paths = getVapiPaths();
102764
103050
  const steps = [];
102765
103051
  const humanIo = json2 ? stderrIo(io) : io;
103052
+ const accountCount = parseAccountCount(parsed.one("--accounts"));
102766
103053
  if (!await fileExists2(paths.config)) {
102767
103054
  await writeDefaultConfig(paths.config, process.env, { networks: ["base"] });
102768
103055
  steps.push("config");
@@ -102773,6 +103060,7 @@ async function setupCommand(argv, json2, io, dependencies) {
102773
103060
  let changedVault = false;
102774
103061
  let changedAccount = false;
102775
103062
  let changedLink = false;
103063
+ let scannedAddresses;
102776
103064
  if (!await fileExists2(join26(paths.directory, "vault.json"))) {
102777
103065
  const choice = await vaultChoice(dependencies);
102778
103066
  if (choice === "restore") {
@@ -102780,12 +103068,14 @@ async function setupCommand(argv, json2, io, dependencies) {
102780
103068
  throw new Error("Restoring needs a terminal to type the phrase.");
102781
103069
  }
102782
103070
  const readSecret = dependencies.prompts?.secret ?? promptForSecret;
102783
- await restoreVaultFromPhrase(
103071
+ const restored = await restoreVaultFromPhrase(
102784
103072
  await readSecret("Recovery phrase: "),
102785
103073
  config2,
102786
103074
  humanIo,
102787
- dependencies
103075
+ dependencies,
103076
+ accountCount
102788
103077
  );
103078
+ scannedAddresses = restored.scannedAddresses;
102789
103079
  store = await WalletStore.open(paths.directory, {
102790
103080
  secrets: getSecretStore(dependencies),
102791
103081
  env: dependencies.env ?? process.env,
@@ -102838,22 +103128,35 @@ async function setupCommand(argv, json2, io, dependencies) {
102838
103128
  }
102839
103129
  if (json2) {
102840
103130
  io.stdout(
102841
- JSON.stringify({ vault, account, address: address4, linked, steps, cloudBackup })
103131
+ JSON.stringify({
103132
+ vault,
103133
+ account,
103134
+ address: address4,
103135
+ linked,
103136
+ steps,
103137
+ cloudBackup,
103138
+ ...scannedAddresses === void 0 ? {} : { scannedAddresses }
103139
+ })
102842
103140
  );
102843
103141
  }
102844
103142
  }
102845
- async function restoreVaultFromPhrase(phrase, config2, io, dependencies) {
103143
+ async function restoreVaultFromPhrase(phrase, config2, io, dependencies, accountCount) {
102846
103144
  const paths = getVapiPaths();
102847
103145
  const validatedPhrase = validateRecoveryPhrase(phrase);
102848
103146
  const readBalance3 = baseUsdcBalanceReader(config2, dependencies);
102849
103147
  const key2 = await loadOrCreateDeviceKey({ secrets: getSecretStore(dependencies) });
102850
103148
  let names;
103149
+ let scannedAddresses = 0;
102851
103150
  try {
102852
103151
  const restored = await restoreVault({
102853
103152
  path: join26(paths.directory, "vault.json"),
102854
103153
  key: key2,
102855
103154
  phrase: validatedPhrase,
102856
103155
  probe: async (address4) => await readBalance3(address4) > 0n,
103156
+ ...accountCount === void 0 ? {} : { accountCount },
103157
+ onScanComplete: (count) => {
103158
+ scannedAddresses = count;
103159
+ },
102857
103160
  ...dependencies.now === void 0 ? {} : { now: dependencies.now }
102858
103161
  });
102859
103162
  names = restored.accounts().map((account) => account.name);
@@ -102865,8 +103168,25 @@ async function restoreVaultFromPhrase(phrase, config2, io, dependencies) {
102865
103168
  ...names[0] === void 0 ? {} : { wallet: names[0] },
102866
103169
  detail: `${names.length} account(s)`
102867
103170
  });
102868
- io.stdout(`Vault restored with ${names.length} account(s): ${names.join(", ")}`);
102869
- return { names };
103171
+ io.stdout(
103172
+ `Vault restored with ${names.length} account(s): ${names.join(", ")}. ${scannedAddresses} address(es) scanned.`
103173
+ );
103174
+ return { names, scannedAddresses };
103175
+ }
103176
+ function parseAccountCount(value) {
103177
+ if (value === void 0) return void 0;
103178
+ if (!/^\d+$/u.test(value)) {
103179
+ throw new UsageError(
103180
+ `--accounts must be a positive integer no greater than ${MAX_RESTORE_ACCOUNTS}.`
103181
+ );
103182
+ }
103183
+ const count = Number(value);
103184
+ if (!Number.isSafeInteger(count) || count < 1 || count > MAX_RESTORE_ACCOUNTS) {
103185
+ throw new UsageError(
103186
+ `--accounts must be a positive integer no greater than ${MAX_RESTORE_ACCOUNTS}.`
103187
+ );
103188
+ }
103189
+ return count;
102870
103190
  }
102871
103191
  async function vaultChoice(dependencies) {
102872
103192
  const answer = dependencies.prompts?.line === void 0 ? isInteractive(dependencies) ? await promptForLine(VAULT_CHOICE) : "" : await dependencies.prompts.line(VAULT_CHOICE);
@@ -103158,7 +103478,7 @@ async function taskContext(parsed, io, dependencies, publicOnly = false) {
103158
103478
  pending,
103159
103479
  randomUUID: dependencies.tasks?.randomUUID ?? randomUUID6,
103160
103480
  signInHint: "Run vapi login for the acting wallet.",
103161
- sleep: dependencies.tasks?.sleep ?? ((milliseconds) => new Promise((resolve2) => setTimeout(resolve2, milliseconds)))
103481
+ sleep: dependencies.tasks?.sleep ?? ((milliseconds) => new Promise((resolve3) => setTimeout(resolve3, milliseconds)))
103162
103482
  };
103163
103483
  }
103164
103484
  async function taskRequest2(verb, route, operation) {
@@ -104958,11 +105278,11 @@ ${usage}`);
104958
105278
  }
104959
105279
  }
104960
105280
  async function referencedSleep(milliseconds, signal) {
104961
- await new Promise((resolve2) => {
105281
+ await new Promise((resolve3) => {
104962
105282
  const finish = () => {
104963
105283
  clearTimeout(timer);
104964
105284
  signal?.removeEventListener("abort", finish);
104965
- resolve2();
105285
+ resolve3();
104966
105286
  };
104967
105287
  const timer = setTimeout(finish, milliseconds);
104968
105288
  if (signal === void 0) return;
@@ -104974,6 +105294,7 @@ async function referencedSleep(milliseconds, signal) {
104974
105294
  // src/vault.ts
104975
105295
  import { join as join27 } from "node:path";
104976
105296
  var VAULT_USAGE = "Usage: vapi vault protect|unprotect|lock|unlock|status [--json]";
105297
+ var RESTORE_USAGE = "Usage: vapi restore [--accounts <n> | --from-owner [--owner <0x\u2026>]] [--json]";
104977
105298
  var LEGACY_PASSWORD_NOTICE = "VAPI_KEYSTORE_PASSWORD is deprecated for vault passwords; use VAPI_VAULT_PASSWORD instead.";
104978
105299
  async function vaultCommand(argv, json2, io, dependencies) {
104979
105300
  const subcommand = argv[0];
@@ -105003,9 +105324,17 @@ async function restoreCommand(argv, json2, io, dependencies) {
105003
105324
  await restoreFromOwnerCommand(argv, json2, io, dependencies);
105004
105325
  return;
105005
105326
  }
105006
- if (argv.length > 0) {
105007
- throw new UsageError("Usage: vapi restore [--from-owner [--owner <0x\u2026>]] [--json]");
105327
+ let parsed;
105328
+ try {
105329
+ parsed = parseArguments(argv, {
105330
+ valueOptions: /* @__PURE__ */ new Set(["--accounts"]),
105331
+ maximumPositionals: 0
105332
+ });
105333
+ } catch (error61) {
105334
+ if (error61 instanceof UsageError) throw new UsageError(RESTORE_USAGE);
105335
+ throw error61;
105008
105336
  }
105337
+ const accountCount = parseRestoreAccountCount(parsed.one("--accounts"));
105009
105338
  const paths = getVapiPaths();
105010
105339
  const path = join27(paths.directory, "vault.json");
105011
105340
  if (await fileExists2(path)) {
@@ -105019,13 +105348,39 @@ async function restoreCommand(argv, json2, io, dependencies) {
105019
105348
  const config2 = await readConfig(paths.config, json2 ? quietIo(io) : io);
105020
105349
  const phrase = isStdinInteractive(dependencies) ? await getPrompts(dependencies).secret("Recovery phrase: ") : await (dependencies.readStdin ?? readProcessStdin3)();
105021
105350
  const restoreIo = json2 ? quietIo(io) : io;
105022
- const { names } = await restoreVaultFromPhrase(phrase.trim(), config2, restoreIo, dependencies);
105351
+ const { names, scannedAddresses } = await restoreVaultFromPhrase(
105352
+ phrase.trim(),
105353
+ config2,
105354
+ restoreIo,
105355
+ dependencies,
105356
+ accountCount
105357
+ );
105023
105358
  if (json2) {
105024
- output3(io, true, { command: "restore", vault: "restored", accounts: names }, "");
105359
+ output3(
105360
+ io,
105361
+ true,
105362
+ { command: "restore", vault: "restored", accounts: names, scannedAddresses },
105363
+ ""
105364
+ );
105025
105365
  return;
105026
105366
  }
105027
105367
  io.stdout(`Run vapi setup to link ${names[0]}.`);
105028
105368
  }
105369
+ function parseRestoreAccountCount(value) {
105370
+ if (value === void 0) return void 0;
105371
+ if (!/^\d+$/u.test(value)) {
105372
+ throw new UsageError(
105373
+ `--accounts must be a positive integer no greater than ${MAX_RESTORE_ACCOUNTS}.`
105374
+ );
105375
+ }
105376
+ const count = Number(value);
105377
+ if (!Number.isSafeInteger(count) || count < 1 || count > MAX_RESTORE_ACCOUNTS) {
105378
+ throw new UsageError(
105379
+ `--accounts must be a positive integer no greater than ${MAX_RESTORE_ACCOUNTS}.`
105380
+ );
105381
+ }
105382
+ return count;
105383
+ }
105029
105384
  async function protectCommand(argv, json2, io, dependencies) {
105030
105385
  requireNoArguments(argv);
105031
105386
  const env = getEnvironment(dependencies);
@@ -105155,8 +105510,8 @@ var HELP_HEADING = "vAPI Network";
105155
105510
  var HELP = `${HELP_HEADING}
105156
105511
 
105157
105512
  Usage:
105158
- vapi init [--networks <base,arc,solana>] [--json]
105159
- vapi setup [--no-cloud-backup] [--json]
105513
+ vapi init [--networks <base,arc>] [--no-link] [--json]
105514
+ vapi setup [--no-cloud-backup] [--accounts <n>] [--json]
105160
105515
  vapi accounts [--all] [--json]
105161
105516
  vapi accounts add <name> [--label <text>] [--no-link] [--json]
105162
105517
  vapi accounts import <name> [--keystore <path> | --key-file <path>] [--label <text>] [--json]
@@ -105186,7 +105541,7 @@ Usage:
105186
105541
  vapi docs read <url-or-path> [--json]
105187
105542
  vapi search [query] [--kind <kind>] [--network <caip2>] [--limit <n>] [--cursor <cursor>] [--include-unverified] [--json]
105188
105543
  vapi inspect <id> [--endpoint <name>] [--json]
105189
- 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]
105544
+ 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]
105190
105545
  vapi pay --resume <receipt-id> [--json]
105191
105546
  vapi check <url> [--method <method>] [--json]
105192
105547
  vapi balance [--account <name>] [--json]
@@ -105202,6 +105557,7 @@ Usage:
105202
105557
  vapi agent pause <name> [--json]
105203
105558
  vapi agent resume <name> [--json]
105204
105559
  vapi agent revoke <name> [--json]
105560
+ vapi dashboard [--account <name>] [--no-browser] [--json]
105205
105561
  vapi login [--account <name>] [--label <name>] [--publish] [--no-browser] [--json]
105206
105562
  vapi logout [--account <name>] [--json]
105207
105563
  vapi whoami [--account <name>] [--json]
@@ -105232,8 +105588,8 @@ Usage:
105232
105588
  vapi task status <id> [--account <name>] [--json]
105233
105589
  vapi export-key [--network <caip2>] [--account <name>] [--json]
105234
105590
  vapi backup [--account <name>] [--cloud [off]] [--json]
105235
- vapi restore [--from-owner [--owner <0x\u2026>]] [--json]
105236
- vapi import (--phrase | --key) [--account <name>] [--networks <base,arc,solana>] [--replace] [--force] [--json]
105591
+ vapi restore [--accounts <n> | --from-owner [--owner <0x\u2026>]] [--json]
105592
+ vapi import (--phrase | --key) [--account <name>] [--networks <base,arc>] [--replace] [--force] [--json]
105237
105593
  vapi passphrase [--account <name>] [--json]
105238
105594
  vapi vault protect [--json]
105239
105595
  vapi vault unprotect [--json]
@@ -105252,15 +105608,19 @@ Usage:
105252
105608
  vapi publish list [--json]
105253
105609
  vapi claim <origin> [--account <name>] [--json]
105254
105610
  vapi mcp [--account <name>] [--json]
105255
- vapi mcp install <claude|cursor|codex> [--home <dir>] [--registry <url>] [--json]
105611
+ vapi mcp install <claude|cursor|codex> [--home <dir>] [--registry <url>] [--no-link] [--json]
105256
105612
  vapi serve [--json]
105257
105613
  vapi version [--json]
105258
105614
  vapi help [--json]
105259
105615
 
105616
+ \`vapi init\`, \`vapi wallet create\` and \`vapi mcp install\` offer to link the wallet to your vAPI dashboard. Use \`--no-link\` to skip the prompt.
105617
+
105260
105618
  Every command that touches a wallet takes \`--account <name>\`, falls back to \`VAPI_WALLET\`, then to the default account set by \`vapi accounts use\`, and names the wallet it used on its first line.
105261
105619
 
105262
105620
  \`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]\`.
105263
105621
 
105622
+ Solana listings remain searchable; inspect and pay return \`unsupported_network\`. Solana keys are not part of the device vault yet.
105623
+
105264
105624
  \`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.
105265
105625
 
105266
105626
  \`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.
@@ -105273,7 +105633,7 @@ Every command that touches a wallet takes \`--account <name>\`, falls back to \`
105273
105633
 
105274
105634
  \`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.
105275
105635
 
105276
- \`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.
105636
+ \`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.
105277
105637
 
105278
105638
  \`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.
105279
105639
 
@@ -105319,8 +105679,8 @@ var ACCOUNT_OPTION2 = "--account";
105319
105679
  var WALLET_OPTION_DEPRECATION = "--wallet is now --account; --wallet keeps working for one release.";
105320
105680
  var SOLANA_VAULT_UNAVAILABLE2 = "Solana keys are not part of the device vault yet.";
105321
105681
  var INCLUDE_UNVERIFIED_OPTION = "--include-unverified";
105322
- async function openWalletStore(dependencies) {
105323
- return await WalletStore.open(getVapiPaths().directory, {
105682
+ async function openWalletStore(dependencies, home = getVapiPaths().directory) {
105683
+ return await WalletStore.open(home, {
105324
105684
  secrets: getSecretStore(dependencies),
105325
105685
  env: getEnvironment(dependencies),
105326
105686
  ...dependencies.now === void 0 ? {} : { now: dependencies.now }
@@ -105335,8 +105695,8 @@ async function selectWallet(store, parsed, dependencies) {
105335
105695
  const address4 = await store.readAddress(resolved.name);
105336
105696
  return { store, ...resolved, ...address4 === void 0 ? {} : { address: address4 } };
105337
105697
  }
105338
- async function targetWallet(parsed, dependencies) {
105339
- return await selectWallet(await openWalletStore(dependencies), parsed, dependencies);
105698
+ async function targetWallet(parsed, dependencies, home = getVapiPaths().directory) {
105699
+ return await selectWallet(await openWalletStore(dependencies, home), parsed, dependencies);
105340
105700
  }
105341
105701
  function getSecretStore(dependencies) {
105342
105702
  return dependencies.secretStore ?? secretStore();
@@ -105515,6 +105875,10 @@ async function runCli(argv = process.argv.slice(2), io = processIo, dependencies
105515
105875
  case "agent":
105516
105876
  exitCode = await agentCommand(args.slice(1), json2, runIo, dependencies);
105517
105877
  break;
105878
+ case "dashboard":
105879
+ await dashboardCommand(args.slice(1), json2, io, dependencies);
105880
+ exitCode = 0;
105881
+ break;
105518
105882
  case "login":
105519
105883
  await loginCommand(args.slice(1), json2, io, dependencies);
105520
105884
  exitCode = 0;
@@ -105729,6 +106093,7 @@ function shouldAutoUploadAfterFailure(args) {
105729
106093
  async function initCommand(argv, json2, io, dependencies) {
105730
106094
  const parsed = parseArguments(argv, {
105731
106095
  valueOptions: /* @__PURE__ */ new Set(["--networks"]),
106096
+ booleanOptions: /* @__PURE__ */ new Set(["--no-link"]),
105732
106097
  maximumPositionals: 0
105733
106098
  });
105734
106099
  const networks = parseInitNetworks(parsed.one("--networks") ?? "base");
@@ -105776,7 +106141,14 @@ async function initCommand(argv, json2, io, dependencies) {
105776
106141
  nextSteps: buildNextSteps(account.address)
105777
106142
  };
105778
106143
  if (json2) {
105779
- io.stdout(JSON.stringify(result));
106144
+ const link3 = await offerDashboardLink({
106145
+ name: created.name,
106146
+ json: json2,
106147
+ noLink: parsed.has("--no-link"),
106148
+ io,
106149
+ dependencies
106150
+ });
106151
+ io.stdout(JSON.stringify({ ...result, ...link3 }));
105780
106152
  return;
105781
106153
  }
105782
106154
  if (configRewrites.length > 0) io.stdout(formatLegacyRegistryRewrites(configRewrites));
@@ -105797,6 +106169,13 @@ async function initCommand(argv, json2, io, dependencies) {
105797
106169
  io.stdout(formatAccounts(accounts));
105798
106170
  io.stdout("");
105799
106171
  io.stdout(result.nextSteps.join("\n"));
106172
+ await offerDashboardLink({
106173
+ name: created.name,
106174
+ json: json2,
106175
+ noLink: parsed.has("--no-link"),
106176
+ io,
106177
+ dependencies
106178
+ });
105800
106179
  }
105801
106180
  var INIT_ALREADY_DONE = "This machine already has a wallet, so vapi init created nothing.";
105802
106181
  async function reportExistingWallets(store, json2, io, dependencies) {
@@ -105832,12 +106211,11 @@ async function walletCommand(argv, json2, io, dependencies) {
105832
106211
  `Unknown wallet subcommand ${JSON.stringify(subcommand)}. ${WALLET_USAGE}`
105833
106212
  );
105834
106213
  }
105835
- await accountsCommand(
105836
- [mapped2, ...rest, ...subcommand === "create" ? ["--no-link"] : []],
105837
- json2,
105838
- io,
105839
- dependencies
105840
- );
106214
+ if (subcommand === "create") {
106215
+ await accountsAddCommand(rest, json2, io, dependencies, { link: "offer" });
106216
+ return;
106217
+ }
106218
+ await accountsCommand([mapped2, ...rest], json2, io, dependencies);
105841
106219
  }
105842
106220
  async function unlockedWallets(walletsStore, wallets, dependencies) {
105843
106221
  const secrets = getSecretStore(dependencies);
@@ -106062,7 +106440,7 @@ async function inspectCommand(argv, json2, io, dependencies) {
106062
106440
  );
106063
106441
  output3(io, json2, result, formatInspect(result));
106064
106442
  }
106065
- 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]";
106443
+ 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]";
106066
106444
  async function payCommand(argv, json2, io, dependencies) {
106067
106445
  if (argv.includes(RESUME_OPTION)) {
106068
106446
  await payResumeCommand(argv, json2, io, dependencies);
@@ -106078,11 +106456,13 @@ async function payCommand(argv, json2, io, dependencies) {
106078
106456
  "--expected-pay-to",
106079
106457
  "--max",
106080
106458
  "--max-price-usd",
106459
+ "--timeout",
106081
106460
  WALLET_OPTION5
106082
106461
  ]),
106083
106462
  maximumPositionals: 1
106084
106463
  });
106085
106464
  const target = requiredPositional(parsed.positionals[0], "<id-or-url>", PAY_USAGE);
106465
+ const timeoutSeconds = optionalBoundedInteger(parsed.one("--timeout"), "--timeout", 1, 300);
106086
106466
  const paths = getVapiPaths();
106087
106467
  const config2 = await readConfig(paths.config, io);
106088
106468
  const wallet = await targetWallet(parsed, dependencies);
@@ -106098,7 +106478,8 @@ async function payCommand(argv, json2, io, dependencies) {
106098
106478
  ...parsed.one("--content-type") ? { contentType: parsed.one("--content-type") } : {},
106099
106479
  ...parsed.one("--network") ? { network: parsed.one("--network") } : {},
106100
106480
  ...parsed.one("--expected-pay-to") ? { expectedPayTo: parsed.one("--expected-pay-to") } : {},
106101
- ...maxPriceUsd ? { maxPriceUsd } : {}
106481
+ ...maxPriceUsd ? { maxPriceUsd } : {},
106482
+ ...timeoutSeconds === void 0 ? {} : { timeoutSeconds }
106102
106483
  };
106103
106484
  const call2 = createCallPort({
106104
106485
  config: config2,
@@ -106376,8 +106757,8 @@ async function fetchNetworkStats(dependencies) {
106376
106757
  })();
106377
106758
  let timeout;
106378
106759
  try {
106379
- const timedOut = new Promise((resolve2) => {
106380
- timeout = setTimeout(() => resolve2(null), NETWORK_STATS_REQUEST_TIMEOUT_MS);
106760
+ const timedOut = new Promise((resolve3) => {
106761
+ timeout = setTimeout(() => resolve3(null), NETWORK_STATS_REQUEST_TIMEOUT_MS);
106381
106762
  });
106382
106763
  return await Promise.race([request, timedOut]);
106383
106764
  } finally {
@@ -107773,7 +108154,7 @@ function buildNextSteps(address4) {
107773
108154
  formatNextStep("Pay", "vapi pay <ref> --max 0.02"),
107774
108155
  formatNextStep(
107775
108156
  "Agent",
107776
- 'add {"command":"npx","args":["-y","vapi-network","mcp"]} to your MCP config'
108157
+ 'add {"command":"npx","args":["-y","vapi-network@latest","mcp"]} to your MCP config'
107777
108158
  )
107778
108159
  ];
107779
108160
  }
@@ -107954,6 +108335,17 @@ function optionalPositiveInteger(value, option) {
107954
108335
  if (result === 0) throw new UsageError(`${option} must be a positive integer.`);
107955
108336
  return result;
107956
108337
  }
108338
+ function optionalBoundedInteger(value, option, minimum, maximum) {
108339
+ if (value === void 0) return void 0;
108340
+ if (!/^\d+$/.test(value)) {
108341
+ throw new UsageError(`${option} must be an integer from ${minimum} to ${maximum}.`);
108342
+ }
108343
+ const parsed = Number(value);
108344
+ if (!Number.isSafeInteger(parsed) || parsed < minimum || parsed > maximum) {
108345
+ throw new UsageError(`${option} must be an integer from ${minimum} to ${maximum}.`);
108346
+ }
108347
+ return parsed;
108348
+ }
107957
108349
  function optionalUsdAmount(value, option) {
107958
108350
  if (value === void 0) return void 0;
107959
108351
  if (!/^\d+(?:\.\d{1,2})?$/.test(value)) {
@@ -108014,17 +108406,144 @@ function parseInitNetworks(value) {
108014
108406
  }
108015
108407
  for (const network of networks) {
108016
108408
  if (network !== "base" && network !== "arc" && network !== "solana") {
108017
- throw new UsageError("--networks supports base, arc and solana.");
108409
+ throw new UsageError("--networks supports base and arc; Solana vault setup is unavailable.");
108018
108410
  }
108019
108411
  }
108020
108412
  return networks;
108021
108413
  }
108414
+
108415
+ // src/update-check.ts
108416
+ import { lookup } from "node:dns/promises";
108417
+ import { mkdir as mkdir21, readFile as readFile29, writeFile as writeFile12 } from "node:fs/promises";
108418
+ var CHECK_INTERVAL_MS = 24 * 60 * 60 * 1e3;
108419
+ var CHECK_TIMEOUT_MS = 1500;
108420
+ var LATEST_URL = "https://registry.npmjs.org/vapi-network/latest";
108421
+ async function runCliWithUpdateCheck(argv = process.argv.slice(2), io = {
108422
+ stdout: (message) => console.log(message),
108423
+ stderr: (message) => console.error(message)
108424
+ }, dependencies = {}, options = {}) {
108425
+ const notice = checkForUpdate({ ...options, env: options.env ?? dependencies.env, argv });
108426
+ const code = await runCli(argv, io, dependencies);
108427
+ const message = await notice;
108428
+ if (message) io.stderr(message);
108429
+ return code;
108430
+ }
108431
+ async function checkForUpdate(options = {}) {
108432
+ const env = options.env ?? process.env;
108433
+ const argv = options.argv ?? process.argv.slice(2);
108434
+ 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) {
108435
+ return void 0;
108436
+ }
108437
+ const controller = new AbortController();
108438
+ let timer;
108439
+ try {
108440
+ return await Promise.race([
108441
+ latestNotice(options, env, controller.signal),
108442
+ new Promise((resolve3) => {
108443
+ timer = setTimeout(() => {
108444
+ controller.abort();
108445
+ resolve3(void 0);
108446
+ }, CHECK_TIMEOUT_MS);
108447
+ })
108448
+ ]);
108449
+ } catch {
108450
+ return void 0;
108451
+ } finally {
108452
+ if (timer !== void 0) clearTimeout(timer);
108453
+ controller.abort();
108454
+ }
108455
+ }
108456
+ async function latestNotice(options, env, signal) {
108457
+ const paths = getVapiPaths(options.home ?? (env.VAPI_HOME?.trim() || void 0));
108458
+ const now = (options.nowMs ?? Date.now)();
108459
+ let cached2;
108460
+ try {
108461
+ const value = JSON.parse(await readFile29(paths.updateCheck, "utf8"));
108462
+ if (isRecord12(value) && typeof value.checkedAt === "number" && Number.isFinite(value.checkedAt) && typeof value.latest === "string" && parseVersion(value.latest)) {
108463
+ cached2 = { checkedAt: value.checkedAt, latest: value.latest };
108464
+ }
108465
+ } catch {
108466
+ }
108467
+ signal.throwIfAborted();
108468
+ let latest = cached2?.latest ?? CLI_VERSION;
108469
+ if (cached2 === void 0 || now - cached2.checkedAt >= CHECK_INTERVAL_MS || now < cached2.checkedAt) {
108470
+ await mkdir21(paths.directory, { recursive: true });
108471
+ signal.throwIfAborted();
108472
+ await writeFile12(paths.updateCheck, JSON.stringify({ checkedAt: now, latest }), { mode: 384 });
108473
+ signal.throwIfAborted();
108474
+ const fetchImpl = options.fetchImpl ?? createPublicFetch({
108475
+ allowPrivateNetwork: false,
108476
+ lookup: async (hostname3) => {
108477
+ let onAbort;
108478
+ const aborted2 = new Promise((_resolve, reject) => {
108479
+ onAbort = () => reject(signal.reason);
108480
+ signal.addEventListener("abort", onAbort, { once: true });
108481
+ });
108482
+ try {
108483
+ signal.throwIfAborted();
108484
+ const addresses = await Promise.race([lookup(hostname3, { all: true }), aborted2]);
108485
+ return addresses.map(({ address: address4 }) => address4);
108486
+ } finally {
108487
+ signal.removeEventListener("abort", onAbort);
108488
+ }
108489
+ }
108490
+ });
108491
+ const response = await fetchImpl(LATEST_URL, { signal, redirect: "error" });
108492
+ if (!response.ok) return void 0;
108493
+ const body = await response.json();
108494
+ signal.throwIfAborted();
108495
+ if (!isRecord12(body) || typeof body.version !== "string" || !parseVersion(body.version)) {
108496
+ return void 0;
108497
+ }
108498
+ latest = body.version;
108499
+ await writeFile12(paths.updateCheck, JSON.stringify({ checkedAt: now, latest }), { mode: 384 });
108500
+ }
108501
+ signal.throwIfAborted();
108502
+ return isNewerVersion(latest, CLI_VERSION) ? `vapi-network ${latest} is available (you have ${CLI_VERSION}). Update: npm i -g vapi-network@latest` : void 0;
108503
+ }
108504
+ function isRecord12(value) {
108505
+ return typeof value === "object" && value !== null && !Array.isArray(value);
108506
+ }
108507
+ function parseVersion(version5) {
108508
+ const match = /^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-([\da-zA-Z.-]+))?(?:\+[\da-zA-Z-]+(?:\.[\da-zA-Z-]+)*)?$/.exec(
108509
+ version5
108510
+ );
108511
+ if (!match) return void 0;
108512
+ const prerelease = match[4]?.split(".");
108513
+ if (prerelease?.some((part) => part === "" || /^\d+$/.test(part) && /^0\d/.test(part))) {
108514
+ return void 0;
108515
+ }
108516
+ return { core: match.slice(1, 4).map(BigInt), prerelease };
108517
+ }
108518
+ function isNewerVersion(latest, current) {
108519
+ const next = parseVersion(latest);
108520
+ const running = parseVersion(current);
108521
+ for (let index2 = 0; index2 < 3; index2 += 1) {
108522
+ if (next.core[index2] !== running.core[index2]) return next.core[index2] > running.core[index2];
108523
+ }
108524
+ if (running.prerelease === void 0) return false;
108525
+ if (next.prerelease === void 0) return true;
108526
+ for (let index2 = 0; index2 < Math.max(next.prerelease.length, running.prerelease.length); index2 += 1) {
108527
+ const a = next.prerelease[index2];
108528
+ const b = running.prerelease[index2];
108529
+ if (a === b) continue;
108530
+ if (a === void 0) return false;
108531
+ if (b === void 0) return true;
108532
+ const aNumeric = /^\d+$/.test(a);
108533
+ const bNumeric = /^\d+$/.test(b);
108534
+ if (aNumeric && bNumeric) return BigInt(a) > BigInt(b);
108535
+ if (aNumeric !== bNumeric) return !aNumeric;
108536
+ return a > b;
108537
+ }
108538
+ return false;
108539
+ }
108022
108540
  export {
108023
108541
  HELP,
108024
108542
  createLocalRuntime,
108025
108543
  parseRuntimeKind,
108026
108544
  resolveRuntime,
108027
108545
  runCli,
108546
+ runCliWithUpdateCheck,
108028
108547
  runtimeForKind
108029
108548
  };
108030
108549
  //# sourceMappingURL=index.js.map