@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/cli.js CHANGED
@@ -9442,13 +9442,13 @@ var init_getCallError = __esm({
9442
9442
 
9443
9443
  // ../../node_modules/.pnpm/viem@2.56.1_typescript@6.0.3_zod@4.5.4/node_modules/viem/_esm/utils/promise/withResolvers.js
9444
9444
  function withResolvers() {
9445
- let resolve2 = () => void 0;
9445
+ let resolve3 = () => void 0;
9446
9446
  let reject = () => void 0;
9447
9447
  const promise2 = new Promise((resolve_, reject_) => {
9448
- resolve2 = resolve_;
9448
+ resolve3 = resolve_;
9449
9449
  reject = reject_;
9450
9450
  });
9451
- return { promise: promise2, resolve: resolve2, reject };
9451
+ return { promise: promise2, resolve: resolve3, reject };
9452
9452
  }
9453
9453
  var init_withResolvers = __esm({
9454
9454
  "../../node_modules/.pnpm/viem@2.56.1_typescript@6.0.3_zod@4.5.4/node_modules/viem/_esm/utils/promise/withResolvers.js"() {
@@ -9467,8 +9467,8 @@ function createBatchScheduler({ fn, id: id2, shouldSplitBatch, wait: wait2 = 0,
9467
9467
  if (sort && Array.isArray(data))
9468
9468
  data.sort(sort);
9469
9469
  for (let i = 0; i < scheduler.length; i++) {
9470
- const { resolve: resolve2 } = scheduler[i];
9471
- resolve2?.([data[i], data]);
9470
+ const { resolve: resolve3 } = scheduler[i];
9471
+ resolve3?.([data[i], data]);
9472
9472
  }
9473
9473
  }).catch((err) => {
9474
9474
  for (let i = 0; i < scheduler.length; i++) {
@@ -9484,16 +9484,16 @@ function createBatchScheduler({ fn, id: id2, shouldSplitBatch, wait: wait2 = 0,
9484
9484
  return {
9485
9485
  flush,
9486
9486
  async schedule(args) {
9487
- const { promise: promise2, resolve: resolve2, reject } = withResolvers();
9487
+ const { promise: promise2, resolve: resolve3, reject } = withResolvers();
9488
9488
  const split2 = shouldSplitBatch?.([...getBatchedArgs(), args]);
9489
9489
  if (split2)
9490
9490
  exec();
9491
9491
  const hasActiveScheduler = getScheduler().length > 0;
9492
9492
  if (hasActiveScheduler) {
9493
- setScheduler({ args, resolve: resolve2, reject });
9493
+ setScheduler({ args, resolve: resolve3, reject });
9494
9494
  return promise2;
9495
9495
  }
9496
- setScheduler({ args, resolve: resolve2, reject });
9496
+ setScheduler({ args, resolve: resolve3, reject });
9497
9497
  setTimeout(exec, wait2);
9498
9498
  return promise2;
9499
9499
  }
@@ -10116,11 +10116,9 @@ var init_call = __esm({
10116
10116
  }
10117
10117
  });
10118
10118
 
10119
- // src/cli.ts
10120
- import { spawn as spawn3 } from "node:child_process";
10121
- import { stat as stat16 } from "node:fs/promises";
10122
- import { join as join28 } from "node:path";
10123
- import { createInterface as createInterface3 } from "node:readline/promises";
10119
+ // src/update-check.ts
10120
+ import { lookup } from "node:dns/promises";
10121
+ import { mkdir as mkdir21, readFile as readFile29, writeFile as writeFile12 } from "node:fs/promises";
10124
10122
 
10125
10123
  // ../../node_modules/.pnpm/zod@4.5.4/node_modules/zod/v4/classic/external.js
10126
10124
  var external_exports = {};
@@ -30775,7 +30773,7 @@ function observe(observerId, callbacks, fn) {
30775
30773
  // ../../node_modules/.pnpm/viem@2.56.1_typescript@6.0.3_zod@4.5.4/node_modules/viem/_esm/utils/wait.js
30776
30774
  init_utils3();
30777
30775
  async function wait(time3, { signal } = {}) {
30778
- return new Promise((resolve2, reject) => {
30776
+ return new Promise((resolve3, reject) => {
30779
30777
  if (signal?.aborted) {
30780
30778
  reject(getAbortError(signal));
30781
30779
  return;
@@ -30783,7 +30781,7 @@ async function wait(time3, { signal } = {}) {
30783
30781
  const cleanup = () => signal?.removeEventListener("abort", onAbort);
30784
30782
  const timeout = setTimeout(() => {
30785
30783
  cleanup();
30786
- resolve2();
30784
+ resolve3();
30787
30785
  }, time3);
30788
30786
  const onAbort = () => {
30789
30787
  clearTimeout(timeout);
@@ -31359,7 +31357,7 @@ init_withResolvers();
31359
31357
  // ../../node_modules/.pnpm/viem@2.56.1_typescript@6.0.3_zod@4.5.4/node_modules/viem/_esm/utils/promise/withRetry.js
31360
31358
  init_utils3();
31361
31359
  function withRetry(fn, { delay: delay_ = 100, retryCount = 2, shouldRetry: shouldRetry2 = () => true, signal } = {}) {
31362
- return new Promise((resolve2, reject) => {
31360
+ return new Promise((resolve3, reject) => {
31363
31361
  const attemptRetry = async ({ count = 0 } = {}) => {
31364
31362
  if (signal?.aborted) {
31365
31363
  reject(getAbortError(signal));
@@ -31379,7 +31377,7 @@ function withRetry(fn, { delay: delay_ = 100, retryCount = 2, shouldRetry: shoul
31379
31377
  };
31380
31378
  try {
31381
31379
  const data = await fn();
31382
- resolve2(data);
31380
+ resolve3(data);
31383
31381
  } catch (err) {
31384
31382
  if (signal?.aborted) {
31385
31383
  reject(getAbortError(signal));
@@ -31530,7 +31528,7 @@ async function sendCalls(client, parameters) {
31530
31528
  results.push({ reason, status: "rejected" });
31531
31529
  }
31532
31530
  if (experimental_fallbackDelay > 0)
31533
- await new Promise((resolve2) => setTimeout(resolve2, experimental_fallbackDelay));
31531
+ await new Promise((resolve3) => setTimeout(resolve3, experimental_fallbackDelay));
31534
31532
  }
31535
31533
  if (results.every((r) => r.status === "rejected"))
31536
31534
  throw results[0].reason;
@@ -31633,9 +31631,9 @@ async function waitForCallsStatus(client, parameters) {
31633
31631
  throwOnFailure = false
31634
31632
  } = parameters;
31635
31633
  const observerId = stringify(["waitForCallsStatus", client.uid, id2]);
31636
- const { promise: promise2, resolve: resolve2, reject } = withResolvers();
31634
+ const { promise: promise2, resolve: resolve3, reject } = withResolvers();
31637
31635
  let timer;
31638
- const unobserve = observe(observerId, { resolve: resolve2, reject }, (emit) => {
31636
+ const unobserve = observe(observerId, { resolve: resolve3, reject }, (emit) => {
31639
31637
  const unpoll = poll(async () => {
31640
31638
  const done = (fn) => {
31641
31639
  clearTimeout(timer);
@@ -32017,13 +32015,13 @@ async function isImageUri(uri) {
32017
32015
  }
32018
32016
  if (!Object.hasOwn(globalThis, "Image"))
32019
32017
  return false;
32020
- return new Promise((resolve2) => {
32018
+ return new Promise((resolve3) => {
32021
32019
  const img = new Image();
32022
32020
  img.onload = () => {
32023
- resolve2(true);
32021
+ resolve3(true);
32024
32022
  };
32025
32023
  img.onerror = () => {
32026
- resolve2(false);
32024
+ resolve3(false);
32027
32025
  };
32028
32026
  img.src = uri;
32029
32027
  });
@@ -33486,7 +33484,7 @@ init_utils3();
33486
33484
  // ../../node_modules/.pnpm/viem@2.56.1_typescript@6.0.3_zod@4.5.4/node_modules/viem/_esm/utils/promise/withTimeout.js
33487
33485
  init_utils3();
33488
33486
  function withTimeout(fn, { errorInstance = new Error("timed out"), timeout, signal }) {
33489
- return new Promise((resolve2, reject) => {
33487
+ return new Promise((resolve3, reject) => {
33490
33488
  ;
33491
33489
  (async () => {
33492
33490
  let timeoutId;
@@ -33501,7 +33499,7 @@ function withTimeout(fn, { errorInstance = new Error("timed out"), timeout, sign
33501
33499
  }
33502
33500
  }, timeout);
33503
33501
  }
33504
- resolve2(await fn({ signal: controller?.signal || null }));
33502
+ resolve3(await fn({ signal: controller?.signal || null }));
33505
33503
  } catch (err) {
33506
33504
  if (controller?.signal.aborted && isAbortError(err)) {
33507
33505
  reject(errorInstance);
@@ -37481,13 +37479,13 @@ async function waitForTransactionReceipt(client, parameters) {
37481
37479
  let retrying = false;
37482
37480
  let _unobserve;
37483
37481
  let _unwatch;
37484
- const { promise: promise2, resolve: resolve2, reject } = withResolvers();
37482
+ const { promise: promise2, resolve: resolve3, reject } = withResolvers();
37485
37483
  const timer = timeout ? setTimeout(() => {
37486
37484
  _unwatch?.();
37487
37485
  _unobserve?.();
37488
37486
  reject(new WaitForTransactionReceiptTimeoutError({ hash: hash5 }));
37489
37487
  }, timeout) : void 0;
37490
- _unobserve = observe(observerId, { onReplaced, resolve: resolve2, reject }, async (emit) => {
37488
+ _unobserve = observe(observerId, { onReplaced, resolve: resolve3, reject }, async (emit) => {
37491
37489
  receipt = await getAction(client, getTransactionReceipt, "getTransactionReceipt")({ hash: hash5 }).catch(() => void 0);
37492
37490
  if (receipt && confirmations <= 1) {
37493
37491
  clearTimeout(timer);
@@ -39357,8 +39355,10 @@ var listingIdentitySchema = external_exports.looseObject({
39357
39355
  }).optional().catch(void 0)
39358
39356
  });
39359
39357
  var listingDisclosureShape = {
39360
- group: listingGroupSchema.optional(),
39361
- fee: listingFeeSchema.optional(),
39358
+ // Presentation metadata must not make an otherwise executable row vanish
39359
+ // when the registry adds a new group or changes the fee display shape.
39360
+ group: listingGroupSchema.optional().catch(void 0),
39361
+ fee: listingFeeSchema.optional().catch(void 0),
39362
39362
  verification: listingVerificationFieldSchema,
39363
39363
  liveness: listingLivenessSchema.optional().catch(void 0),
39364
39364
  conformance: listingConformanceSchema.optional().catch(void 0),
@@ -39366,11 +39366,13 @@ var listingDisclosureShape = {
39366
39366
  };
39367
39367
  var marketplaceBadgeCodeSchema = external_exports.enum([
39368
39368
  "live_x402",
39369
+ "mpp",
39369
39370
  "partner",
39370
39371
  "payout_wallet_confirmed",
39371
39372
  "vapi_verified",
39372
39373
  "external_catalog",
39373
- "approved_vendor"
39374
+ "approved_vendor",
39375
+ "unverified"
39374
39376
  ]);
39375
39377
  var marketplaceBadgeSchema = external_exports.looseObject({
39376
39378
  code: marketplaceBadgeCodeSchema,
@@ -39389,7 +39391,13 @@ var marketplaceCardSchema = external_exports.looseObject({
39389
39391
  summary: external_exports.string().trim().min(1).max(1e3),
39390
39392
  byline: external_exports.string().trim().min(1).max(160).optional(),
39391
39393
  bylineHref: marketplaceHrefSchema.optional(),
39392
- badges: external_exports.array(marketplaceBadgeSchema).max(8),
39394
+ badges: external_exports.preprocess(
39395
+ (badges) => Array.isArray(badges) ? badges.flatMap((badge) => {
39396
+ const parsed = marketplaceBadgeSchema.safeParse(badge);
39397
+ return parsed.success ? [parsed.data] : [];
39398
+ }) : badges,
39399
+ external_exports.array(marketplaceBadgeSchema).max(8)
39400
+ ),
39393
39401
  facts: external_exports.array(marketplacePublicFactSchema).max(12)
39394
39402
  });
39395
39403
  var marketplaceHitBase = {
@@ -43436,7 +43444,7 @@ function getRpcTransportWithRequestCoalescing(transport, getDeduplicationKey) {
43436
43444
  coalescedRequest.numConsumers++;
43437
43445
  if (signal) {
43438
43446
  const responsePromise = coalescedRequest.responsePromise;
43439
- return await new Promise((resolve2, reject) => {
43447
+ return await new Promise((resolve3, reject) => {
43440
43448
  const handleAbort = (e22) => {
43441
43449
  signal.removeEventListener("abort", handleAbort);
43442
43450
  coalescedRequest.numConsumers -= 1;
@@ -43449,7 +43457,7 @@ function getRpcTransportWithRequestCoalescing(transport, getDeduplicationKey) {
43449
43457
  reject(e22.target.reason);
43450
43458
  };
43451
43459
  signal.addEventListener("abort", handleAbort);
43452
- responsePromise.then(resolve2).catch(reject).finally(() => {
43460
+ responsePromise.then(resolve3).catch(reject).finally(() => {
43453
43461
  signal.removeEventListener("abort", handleAbort);
43454
43462
  });
43455
43463
  });
@@ -44832,7 +44840,7 @@ function createPublicFetch(options) {
44832
44840
  });
44833
44841
  const normalized = new Request(input2, init);
44834
44842
  const bytes = normalized.body ? Buffer.from(await normalized.arrayBuffer()) : null;
44835
- return await new Promise((resolve2, reject) => {
44843
+ return await new Promise((resolve3, reject) => {
44836
44844
  const requestOptions2 = {
44837
44845
  method: normalized.method,
44838
44846
  headers: Object.fromEntries(normalized.headers),
@@ -44857,7 +44865,7 @@ function createPublicFetch(options) {
44857
44865
  { status, statusText: incoming.statusMessage, headers }
44858
44866
  );
44859
44867
  Object.defineProperty(response, "url", { value: url2.toString() });
44860
- resolve2(response);
44868
+ resolve3(response);
44861
44869
  } catch (error61) {
44862
44870
  incoming.destroy();
44863
44871
  reject(error61);
@@ -44870,9 +44878,9 @@ function createPublicFetch(options) {
44870
44878
  });
44871
44879
  });
44872
44880
  }
44873
- function pinnedLookup(lookup) {
44881
+ function pinnedLookup(lookup2) {
44874
44882
  return (hostname3, dnsOptions, callback) => {
44875
- void lookup(normalizeHostname(hostname3)).then((addresses) => {
44883
+ void lookup2(normalizeHostname(hostname3)).then((addresses) => {
44876
44884
  if (addresses.length === 0 || addresses.some(isNonPublicAddress)) {
44877
44885
  callback(guardError(new URL(`https://${hostname3}`)), "");
44878
44886
  return;
@@ -45626,8 +45634,8 @@ var svmFetchQueue = Promise.resolve();
45626
45634
  async function withGuardedSvmFetch(fetchImpl, operation) {
45627
45635
  const previous = svmFetchQueue;
45628
45636
  let release2;
45629
- svmFetchQueue = new Promise((resolve2) => {
45630
- release2 = resolve2;
45637
+ svmFetchQueue = new Promise((resolve3) => {
45638
+ release2 = resolve3;
45631
45639
  });
45632
45640
  await previous;
45633
45641
  const originalFetch = globalThis.fetch;
@@ -46010,9 +46018,9 @@ function isRecord2(value) {
46010
46018
  var CALLABLE_CATEGORIES = ["ai", "data", "crypto", "compute", "search"];
46011
46019
  var callableCategorySchema = external_exports.enum(CALLABLE_CATEGORIES);
46012
46020
  var DISCOVERY_CATEGORIES = [...CALLABLE_CATEGORIES, "other"];
46013
- var discoveryCategorySchema = external_exports.enum(DISCOVERY_CATEGORIES);
46021
+ var discoveryCategorySchema = external_exports.string().trim().min(1);
46014
46022
  var CALLABLE_CATEGORY_SET = new Set(CALLABLE_CATEGORIES);
46015
- var serviceTierSchema = external_exports.enum(["listed", "verified", "partner"]);
46023
+ var serviceTierSchema = external_exports.string().trim().min(1);
46016
46024
  var discoveryEndpointSchema = external_exports.looseObject({
46017
46025
  name: external_exports.string(),
46018
46026
  method: external_exports.string(),
@@ -46042,6 +46050,24 @@ var discoveryEndpointSchema = external_exports.looseObject({
46042
46050
  asset: external_exports.string().refine(isSolanaAddress, "Expected a Solana base58 address."),
46043
46051
  payTo: external_exports.string().refine(isSolanaAddress, "Expected a Solana base58 address."),
46044
46052
  checkedAt: external_exports.iso.datetime()
46053
+ }),
46054
+ external_exports.looseObject({
46055
+ protocol: external_exports.literal("mpp"),
46056
+ intent: external_exports.enum(["charge", "authorize", "subscription"]).nullable(),
46057
+ method: external_exports.string().trim().min(1).max(40).nullable(),
46058
+ checkedAt: external_exports.iso.datetime(),
46059
+ // Keep common x402 properties readable on the union while making it
46060
+ // impossible for MPP metadata to masquerade as executable x402 terms.
46061
+ network: external_exports.never().optional(),
46062
+ payTo: external_exports.never().optional()
46063
+ }),
46064
+ external_exports.looseObject({
46065
+ // Future payment protocols remain visible to callers so the payment
46066
+ // layer can refuse them explicitly instead of discovery losing the row.
46067
+ protocol: external_exports.string().trim().min(1).max(40),
46068
+ checkedAt: external_exports.iso.datetime(),
46069
+ network: external_exports.never().optional(),
46070
+ payTo: external_exports.never().optional()
46045
46071
  })
46046
46072
  ]).optional()
46047
46073
  });
@@ -46135,7 +46161,7 @@ function resolveTarget(service, endpointName) {
46135
46161
  }
46136
46162
  if (targets.size !== 1) {
46137
46163
  const paymentNetworks = service.endpoints.flatMap(
46138
- (endpoint) => endpoint.payment ? [endpoint.payment.network] : []
46164
+ (endpoint) => typeof endpoint.payment?.network === "string" ? [endpoint.payment.network] : []
46139
46165
  );
46140
46166
  throw new DiscoveryCatalogError(
46141
46167
  "ambiguous_default",
@@ -46822,7 +46848,7 @@ async function withFileLock(lockPath, fn, options = {}) {
46822
46848
  if (Date.now() >= deadline) {
46823
46849
  throw new FileLockedError(options.lockedMessage);
46824
46850
  }
46825
- await new Promise((resolve2) => setTimeout(resolve2, LOCK_RETRY_MS));
46851
+ await new Promise((resolve3) => setTimeout(resolve3, LOCK_RETRY_MS));
46826
46852
  continue;
46827
46853
  }
46828
46854
  handle = candidate;
@@ -46837,7 +46863,7 @@ async function withFileLock(lockPath, fn, options = {}) {
46837
46863
  if (Date.now() >= deadline) {
46838
46864
  throw new FileLockedError(options.lockedMessage);
46839
46865
  }
46840
- await new Promise((resolve2) => setTimeout(resolve2, LOCK_RETRY_MS));
46866
+ await new Promise((resolve3) => setTimeout(resolve3, LOCK_RETRY_MS));
46841
46867
  }
46842
46868
  }
46843
46869
  const ownedHandle = handle;
@@ -46958,7 +46984,7 @@ async function restoreRenamedLock(path, tombPath) {
46958
46984
  } catch (error61) {
46959
46985
  if (hasCode(error61, "ENOENT")) return;
46960
46986
  if (!hasCode(error61, "EEXIST")) throw error61;
46961
- await new Promise((resolve2) => setTimeout(resolve2, LOCK_RETRY_MS));
46987
+ await new Promise((resolve3) => setTimeout(resolve3, LOCK_RETRY_MS));
46962
46988
  }
46963
46989
  }
46964
46990
  }
@@ -47110,7 +47136,8 @@ function getVapiPaths(directory = process.env.VAPI_HOME?.trim() || join2(homedir
47110
47136
  keystore: join2(directory, "keystore.json"),
47111
47137
  receipts: join2(directory, "receipts.jsonl"),
47112
47138
  searches: join2(directory, "searches.jsonl"),
47113
- ledger: join2(directory, "spend-ledger.json")
47139
+ ledger: join2(directory, "spend-ledger.json"),
47140
+ updateCheck: join2(directory, "update-check.json")
47114
47141
  };
47115
47142
  }
47116
47143
  var getAgentCashPaths = getVapiPaths;
@@ -47956,7 +47983,7 @@ async function withAgentCredentialLock(wallets, clientId, operation) {
47956
47983
  if (Date.now() >= deadline) {
47957
47984
  throw httpError("Timed out waiting to update the agent credentials.");
47958
47985
  }
47959
- await new Promise((resolve2) => setTimeout(resolve2, 20));
47986
+ await new Promise((resolve3) => setTimeout(resolve3, 20));
47960
47987
  }
47961
47988
  }
47962
47989
  try {
@@ -48109,7 +48136,7 @@ function splitScopes(scope) {
48109
48136
  return scope.split(/\s+/u).filter(Boolean);
48110
48137
  }
48111
48138
  async function sleepFor(milliseconds) {
48112
- await new Promise((resolve2) => setTimeout(resolve2, milliseconds));
48139
+ await new Promise((resolve3) => setTimeout(resolve3, milliseconds));
48113
48140
  }
48114
48141
 
48115
48142
  // ../core/src/keystore.ts
@@ -69587,7 +69614,7 @@ function decryptWithKey(key2, sealed) {
69587
69614
  return Buffer.concat([decipher.update(sealed.ciphertext), decipher.final()]);
69588
69615
  }
69589
69616
  async function deriveScryptKey(passphrase, salt) {
69590
- return await new Promise((resolve2, reject) => {
69617
+ return await new Promise((resolve3, reject) => {
69591
69618
  scrypt(
69592
69619
  passphrase,
69593
69620
  salt,
@@ -69603,7 +69630,7 @@ async function deriveScryptKey(passphrase, salt) {
69603
69630
  reject(error61);
69604
69631
  return;
69605
69632
  }
69606
- resolve2(derivedKey);
69633
+ resolve3(derivedKey);
69607
69634
  }
69608
69635
  );
69609
69636
  });
@@ -69927,7 +69954,7 @@ async function promptForSecret(prompt, noTerminalHint) {
69927
69954
  stdin.setRawMode(true);
69928
69955
  stdin.resume();
69929
69956
  stdin.setEncoding("utf8");
69930
- return await new Promise((resolve2, reject) => {
69957
+ return await new Promise((resolve3, reject) => {
69931
69958
  let value = "";
69932
69959
  const cleanup = () => {
69933
69960
  stdin.off("data", onData);
@@ -69944,7 +69971,7 @@ async function promptForSecret(prompt, noTerminalHint) {
69944
69971
  }
69945
69972
  if (character === "\r" || character === "\n") {
69946
69973
  cleanup();
69947
- resolve2(value);
69974
+ resolve3(value);
69948
69975
  return;
69949
69976
  }
69950
69977
  if (character === "\x7F" || character === "\b") {
@@ -70006,7 +70033,7 @@ async function withAccountMovementLock(home, account, timeoutMs, operation, sign
70006
70033
  if (!(error61 instanceof Error && "code" in error61 && error61.code === "EEXIST")) throw error61;
70007
70034
  await removeStaleLock2(path);
70008
70035
  if (Date.now() >= deadline) throw new AccountMovementLockedError(account);
70009
- await new Promise((resolve2) => setTimeout(resolve2, 20));
70036
+ await new Promise((resolve3) => setTimeout(resolve3, 20));
70010
70037
  }
70011
70038
  }
70012
70039
  const ownedHandle = handle;
@@ -70374,7 +70401,7 @@ function windowsDataProtectionStore(platform2, run, env, installed) {
70374
70401
  };
70375
70402
  }
70376
70403
  function libsecretStore(platform2, run, installed) {
70377
- const lookup = async (name) => {
70404
+ const lookup2 = async (name) => {
70378
70405
  const result = await run(SECRET_TOOL_BINARY, [
70379
70406
  "lookup",
70380
70407
  "service",
@@ -70393,9 +70420,9 @@ function libsecretStore(platform2, run, installed) {
70393
70420
  available: installed(SECRET_TOOL_BINARY),
70394
70421
  platform: platform2,
70395
70422
  description: "the libsecret keyring",
70396
- get: lookup,
70423
+ get: lookup2,
70397
70424
  async has(name) {
70398
- return await lookup(name) !== void 0;
70425
+ return await lookup2(name) !== void 0;
70399
70426
  },
70400
70427
  async set(name, passphrase) {
70401
70428
  requirePassphrase(passphrase);
@@ -70417,7 +70444,7 @@ function libsecretStore(platform2, run, installed) {
70417
70444
  requireSuccess(result, `store the passphrase of ${name} in the secret service`);
70418
70445
  },
70419
70446
  async remove(name) {
70420
- const existed = await lookup(name) !== void 0;
70447
+ const existed = await lookup2(name) !== void 0;
70421
70448
  const result = await run(SECRET_TOOL_BINARY, [
70422
70449
  "clear",
70423
70450
  "service",
@@ -70477,14 +70504,14 @@ function requireSuccess(result, what) {
70477
70504
  function withoutTrailingNewline(value) {
70478
70505
  return value.replace(/\r?\n$/u, "");
70479
70506
  }
70480
- var spawnRunner = async (file2, args, input2) => await new Promise((resolve2) => {
70507
+ var spawnRunner = async (file2, args, input2) => await new Promise((resolve3) => {
70481
70508
  let stdout = "";
70482
70509
  let stderr2 = "";
70483
70510
  let settled = false;
70484
70511
  const finish = (outcome) => {
70485
70512
  if (settled) return;
70486
70513
  settled = true;
70487
- resolve2(outcome);
70514
+ resolve3(outcome);
70488
70515
  };
70489
70516
  const child = spawn(file2, [...args], {
70490
70517
  detached: true,
@@ -71447,7 +71474,7 @@ async function withVaultLock(path, operation) {
71447
71474
  if (Date.now() >= deadline) {
71448
71475
  throw new VaultError("corrupt", "Timed out waiting for the vault lock.");
71449
71476
  }
71450
- await new Promise((resolve2) => setTimeout(resolve2, 20));
71477
+ await new Promise((resolve3) => setTimeout(resolve3, 20));
71451
71478
  }
71452
71479
  }
71453
71480
  try {
@@ -71480,6 +71507,8 @@ var VAULT_KEY_ACCOUNT = "vault-key";
71480
71507
  var VAULT_SESSION_ACCOUNT = "vault-session";
71481
71508
  var DEVICE_KEY_LENGTH = 32;
71482
71509
  var DEFAULT_SESSION_HOURS = 8;
71510
+ var RESTORE_GAP_LIMIT = 5;
71511
+ var MAX_RESTORE_ACCOUNTS = 1e4;
71483
71512
  var BASE64_PATTERN = /^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$/u;
71484
71513
  var deviceKeyOperations = Promise.resolve();
71485
71514
  var sessionSchema = external_exports.object({
@@ -71629,26 +71658,41 @@ async function restoreVault(args) {
71629
71658
  throw new VaultError("corrupt", "That recovery phrase is not valid.", { cause: error61 });
71630
71659
  }
71631
71660
  let seed;
71632
- let discoveredAccounts = 0;
71661
+ if (args.accountCount !== void 0 && (!Number.isSafeInteger(args.accountCount) || args.accountCount < 1 || args.accountCount > MAX_RESTORE_ACCOUNTS)) {
71662
+ throw new VaultError(
71663
+ "corrupt",
71664
+ `Account count must be a positive integer no greater than ${MAX_RESTORE_ACCOUNTS}.`
71665
+ );
71666
+ }
71667
+ let discoveredAccounts = args.accountCount ?? 0;
71668
+ let scannedAddresses = 0;
71633
71669
  try {
71634
71670
  seed = phraseToSeed(phrase);
71635
71671
  } catch (error61) {
71636
71672
  throw asVaultError2(error61, "Unable to derive an account while restoring the vault.");
71637
71673
  }
71638
71674
  try {
71639
- for (let index2 = 0; ; index2 += 1) {
71675
+ for (let index2 = 0, emptyRun = 0; args.accountCount === void 0; index2 += 1) {
71640
71676
  let address4;
71641
71677
  try {
71642
71678
  address4 = privateKeyToAccount(deriveEvmPrivateKey(seed, `m/44'/60'/0'/0/${index2}`)).address;
71643
71679
  } catch (error61) {
71644
71680
  throw asVaultError2(error61, "Unable to derive an account while restoring the vault.");
71645
71681
  }
71646
- if (!await args.probe(address4)) break;
71647
- discoveredAccounts += 1;
71682
+ const funded = await args.probe(address4);
71683
+ scannedAddresses += 1;
71684
+ if (funded) {
71685
+ discoveredAccounts = index2 + 1;
71686
+ emptyRun = 0;
71687
+ } else {
71688
+ emptyRun += 1;
71689
+ if (emptyRun === RESTORE_GAP_LIMIT) break;
71690
+ }
71648
71691
  }
71649
71692
  } finally {
71650
71693
  seed.fill(0);
71651
71694
  }
71695
+ args.onScanComplete?.(scannedAddresses);
71652
71696
  let vault;
71653
71697
  try {
71654
71698
  vault = await createVault({ path: args.path, key: args.key, phrase, now: args.now });
@@ -72137,6 +72181,26 @@ var WalletStore = class _WalletStore {
72137
72181
  }
72138
72182
  );
72139
72183
  }
72184
+ /** Checks a cached signer's current vault session without decrypting its account again. */
72185
+ async assertSigningAuthority(name) {
72186
+ const stored = await this.readVaultUnlocked();
72187
+ if (!stored?.protected || !stored.accounts.some((account) => account.name === name)) return;
72188
+ try {
72189
+ const key2 = await unlockProtectedVault({
72190
+ path: this.vaultPath,
72191
+ secrets: this.secrets,
72192
+ env: this.environment,
72193
+ now: () => this.now()
72194
+ });
72195
+ key2.fill(0);
72196
+ } catch (error61) {
72197
+ this.dropVaultCache();
72198
+ if (error61 instanceof VaultError && error61.code === "password_required") {
72199
+ throw new KeystoreError(VAULT_LOCKED_MESSAGE, { cause: error61 });
72200
+ }
72201
+ throw error61;
72202
+ }
72203
+ }
72140
72204
  /** Returns one wallet's vault signer, migrating its legacy keystore if needed. */
72141
72205
  async unlock(name, passphrase) {
72142
72206
  const wallet = this.resolve({ name });
@@ -73143,7 +73207,7 @@ async function withRegistryLock(path, operation) {
73143
73207
  if (Date.now() >= deadline) {
73144
73208
  throw new KeystoreError("Timed out waiting for the wallet registry lock.");
73145
73209
  }
73146
- await new Promise((resolve2) => setTimeout(resolve2, 20));
73210
+ await new Promise((resolve3) => setTimeout(resolve3, 20));
73147
73211
  }
73148
73212
  }
73149
73213
  try {
@@ -73489,11 +73553,11 @@ function publicErrorMessage(error61, fallback, sensitiveValues = []) {
73489
73553
  return error61 instanceof Error ? message : fallback;
73490
73554
  }
73491
73555
  async function unrefSleep(milliseconds, signal) {
73492
- await new Promise((resolve2) => {
73556
+ await new Promise((resolve3) => {
73493
73557
  const finish = () => {
73494
73558
  clearTimeout(timer);
73495
73559
  signal?.removeEventListener("abort", finish);
73496
- resolve2();
73560
+ resolve3();
73497
73561
  };
73498
73562
  const timer = setTimeout(finish, milliseconds);
73499
73563
  timer.unref();
@@ -74030,7 +74094,7 @@ async function withLedgerLock(path, operation) {
74030
74094
  if (Date.now() >= deadline) {
74031
74095
  throw new Error("Timed out waiting for the spend ledger lock.");
74032
74096
  }
74033
- await new Promise((resolve2) => setTimeout(resolve2, 20));
74097
+ await new Promise((resolve3) => setTimeout(resolve3, 20));
74034
74098
  }
74035
74099
  }
74036
74100
  try {
@@ -74664,7 +74728,7 @@ async function withTransferLock(context, nonce, operation) {
74664
74728
  if (Date.now() >= deadline) {
74665
74729
  throw new Error("Timed out waiting for the transfer lock.");
74666
74730
  }
74667
- await new Promise((resolve2) => setTimeout(resolve2, 20));
74731
+ await new Promise((resolve3) => setTimeout(resolve3, 20));
74668
74732
  }
74669
74733
  }
74670
74734
  try {
@@ -76382,8 +76446,8 @@ async function sweepAllAboveCeiling(args) {
76382
76446
  }
76383
76447
  var pendingCeilingSweeps = /* @__PURE__ */ new Set();
76384
76448
  function scheduleCeilingSweep(hook) {
76385
- const task = new Promise((resolve2) => {
76386
- setTimeout(resolve2, 0);
76449
+ const task = new Promise((resolve3) => {
76450
+ setTimeout(resolve3, 0);
76387
76451
  }).then(async () => {
76388
76452
  const timeoutMs = hook.timeoutMs ?? CEILING_SWEEP_TIMEOUT_MS;
76389
76453
  const controller = new AbortController();
@@ -76423,8 +76487,8 @@ async function drainCeilingSweeps(timeoutMs = CEILING_SWEEP_TIMEOUT_MS) {
76423
76487
  try {
76424
76488
  await Promise.race([
76425
76489
  Promise.allSettled(pending),
76426
- new Promise((resolve2) => {
76427
- timeout = setTimeout(resolve2, timeoutMs);
76490
+ new Promise((resolve3) => {
76491
+ timeout = setTimeout(resolve3, timeoutMs);
76428
76492
  })
76429
76493
  ]);
76430
76494
  } finally {
@@ -77523,7 +77587,7 @@ function createRunBudget(args) {
77523
77587
  import { mkdir as mkdir15, writeFile as writeFile8 } from "node:fs/promises";
77524
77588
  import { arch, platform, release } from "node:os";
77525
77589
  import { join as join13 } from "node:path";
77526
- var VAPI_CLIENT_VERSION = "0.9.2";
77590
+ var VAPI_CLIENT_VERSION = "0.9.5";
77527
77591
  async function createSupportReport(options) {
77528
77592
  const message = options.message.trim();
77529
77593
  if (!message) throw new Error("Support report message must not be empty.");
@@ -77796,7 +77860,7 @@ async function completeX402Payment(args) {
77796
77860
  let paidAttempt;
77797
77861
  const requestStarted = nowMs();
77798
77862
  try {
77799
- paidAttempt = await args.send(paidRequest);
77863
+ paidAttempt = await args.send(paidRequest, quote);
77800
77864
  } catch (error61) {
77801
77865
  if (trace) trace.phases.requestMs = elapsed(nowMs, requestStarted);
77802
77866
  throw settlementUnknown(
@@ -77814,7 +77878,7 @@ async function completeX402Payment(args) {
77814
77878
  const settleStarted = nowMs();
77815
77879
  const settlement = parseSettlementResponse(paidResponse.headers);
77816
77880
  const settlementOutcome = classifySettlement(settlement);
77817
- const receiptSettlement = sanitizeReceiptValue(settlement, receiptSecrets);
77881
+ const receiptSettlement = sanitizeReturnedValue(settlement, receiptSecrets);
77818
77882
  if (trace) {
77819
77883
  const transaction2 = settlementTransaction(receiptSettlement);
77820
77884
  const explorerUrl = transaction2 ? explorerTransactionUrl(quote.accepted.network, transaction2) : void 0;
@@ -77891,6 +77955,7 @@ async function completeX402Payment(args) {
77891
77955
  trace.phases.requestMs = (trace.phases.requestMs ?? 0) + elapsed(nowMs, bodyStarted);
77892
77956
  }
77893
77957
  }
77958
+ body = sanitizeReturnedValue(body, receiptSecrets);
77894
77959
  }
77895
77960
  const result = {
77896
77961
  response: paidResponse,
@@ -77899,7 +77964,11 @@ async function completeX402Payment(args) {
77899
77964
  quote,
77900
77965
  payer,
77901
77966
  ...payment.paymentId ? { paymentId: payment.paymentId } : {},
77902
- settlement,
77967
+ paymentProof: sanitizeReturnedValue(
77968
+ paidResponse.headers.get("x-vapi-payment-proof"),
77969
+ receiptSecrets
77970
+ ),
77971
+ settlement: receiptSettlement,
77903
77972
  settlementOutcome
77904
77973
  };
77905
77974
  if (settlementOutcome === "succeeded" && args.ceilingSweep) {
@@ -78036,19 +78105,70 @@ function sanitizeThrownError(error61, secrets) {
78036
78105
  }
78037
78106
  return new Error(message, cause === void 0 ? void 0 : { cause });
78038
78107
  }
78039
- function sanitizeReceiptValue(value, secrets, depth = 0) {
78108
+ function sanitizeReturnedValue(value, secrets) {
78040
78109
  if (typeof value === "string") return redactKnownSecrets(value, secrets);
78041
- if (value === null || typeof value !== "object") return value;
78042
- if (depth >= 16) return "[redacted nested settlement value]";
78043
- if (Array.isArray(value)) {
78044
- return value.map((item) => sanitizeReceiptValue(item, secrets, depth + 1));
78110
+ if (!isPlainReturnedContainer(value)) return value;
78111
+ const nodes = /* @__PURE__ */ new WeakMap();
78112
+ const ordered = [];
78113
+ const nodeFor = (source) => {
78114
+ const existing = nodes.get(source);
78115
+ if (existing) return existing;
78116
+ const copy = Array.isArray(source) ? new Array(source.length) : Object.create(Object.getPrototypeOf(source));
78117
+ const node2 = { source, copy, parents: /* @__PURE__ */ new Set(), changed: false };
78118
+ nodes.set(source, node2);
78119
+ ordered.push(node2);
78120
+ return node2;
78121
+ };
78122
+ const root = nodeFor(value);
78123
+ for (let index2 = 0; index2 < ordered.length; index2 += 1) {
78124
+ const node2 = ordered[index2];
78125
+ for (const [key2, item] of Object.entries(node2.source)) {
78126
+ const safeKey = Array.isArray(node2.source) ? key2 : redactKnownSecrets(key2, secrets);
78127
+ if (safeKey !== key2) node2.changed = true;
78128
+ if (typeof item === "string") {
78129
+ const safeItem = redactKnownSecrets(item, secrets);
78130
+ defineReturnedProperty(node2.copy, safeKey, safeItem);
78131
+ if (safeItem !== item) node2.changed = true;
78132
+ } else if (isPlainReturnedContainer(item)) {
78133
+ const child = nodeFor(item);
78134
+ child.parents.add(node2);
78135
+ defineReturnedProperty(node2.copy, safeKey, child.copy);
78136
+ } else {
78137
+ defineReturnedProperty(node2.copy, safeKey, item);
78138
+ }
78139
+ }
78045
78140
  }
78046
- return Object.fromEntries(
78047
- Object.entries(value).map(([key2, item]) => [
78048
- redactKnownSecrets(key2, secrets),
78049
- sanitizeReceiptValue(item, secrets, depth + 1)
78050
- ])
78051
- );
78141
+ const changed = ordered.filter((node2) => node2.changed);
78142
+ for (let index2 = 0; index2 < changed.length; index2 += 1) {
78143
+ for (const parent of changed[index2].parents) {
78144
+ if (parent.changed) continue;
78145
+ parent.changed = true;
78146
+ changed.push(parent);
78147
+ }
78148
+ }
78149
+ for (const node2 of ordered) {
78150
+ for (const [key2, item] of Object.entries(node2.source)) {
78151
+ if (!isPlainReturnedContainer(item)) continue;
78152
+ const safeKey = Array.isArray(node2.source) ? key2 : redactKnownSecrets(key2, secrets);
78153
+ const child = nodes.get(item);
78154
+ defineReturnedProperty(node2.copy, safeKey, child.changed ? child.copy : item);
78155
+ }
78156
+ }
78157
+ return root.changed ? root.copy : value;
78158
+ }
78159
+ function defineReturnedProperty(target, key2, value) {
78160
+ Object.defineProperty(target, key2, {
78161
+ value,
78162
+ enumerable: true,
78163
+ configurable: true,
78164
+ writable: true
78165
+ });
78166
+ }
78167
+ function isPlainReturnedContainer(value) {
78168
+ if (Array.isArray(value)) return true;
78169
+ if (value === null || typeof value !== "object") return false;
78170
+ const prototype = Object.getPrototypeOf(value);
78171
+ return prototype === Object.prototype || prototype === null;
78052
78172
  }
78053
78173
  function redactKnownSecrets(value, secrets) {
78054
78174
  let redacted = value;
@@ -78083,9 +78203,7 @@ function possibleSettlement(quote, payment, payer, receipt) {
78083
78203
  payTo: quote.accepted.payTo,
78084
78204
  payer,
78085
78205
  ...payment.paymentId ? { paymentId: payment.paymentId } : {},
78086
- ...isSvmPaymentRequirements(quote.accepted) ? {
78087
- authorizationTransaction: "transaction" in payment.payload.payload ? payment.payload.payload.transaction : ""
78088
- } : "authorization" in payment.payload.payload ? {
78206
+ ...isSvmPaymentRequirements(quote.accepted) ? {} : "authorization" in payment.payload.payload ? {
78089
78207
  authorizationNonce: payment.payload.payload.authorization.nonce,
78090
78208
  authorizationExpiresAt: payment.payload.payload.authorization.validBefore
78091
78209
  } : {},
@@ -78463,13 +78581,22 @@ async function sendRouterChat(deps, routerBaseUrl, routerKey, request, keyUsed)
78463
78581
  }
78464
78582
  const body = await responseText(response);
78465
78583
  if (!response.ok) {
78466
- if (response.status === 429 || body.includes("Budget has been exceeded") || body.includes("ExceededBudget")) {
78584
+ if (/budget (?:has been )?exceeded|exceededbudget/iu.test(body)) {
78467
78585
  throw new RouterClientError(
78468
78586
  "budget_exhausted",
78469
78587
  "The Router key has no remaining budget.",
78470
78588
  response.status
78471
78589
  );
78472
78590
  }
78591
+ if (response.status === 429) {
78592
+ const retryAfter = response.headers.get("retry-after")?.trim();
78593
+ const retrySeconds = retryAfter !== void 0 && /^\d+$/u.test(retryAfter) ? Number(retryAfter) : void 0;
78594
+ throw new RouterClientError(
78595
+ "rate_limited",
78596
+ `The vAPI Router is rate limited. ${retrySeconds !== void 0 && Number.isFinite(retrySeconds) ? `Retry after ${retrySeconds} seconds.` : "Wait and retry shortly."}`,
78597
+ response.status
78598
+ );
78599
+ }
78473
78600
  if (response.status === 401) {
78474
78601
  throw new RouterClientError(
78475
78602
  "no_router_key",
@@ -81166,7 +81293,7 @@ var authorizationTypes = {
81166
81293
  function createTasksChain(options) {
81167
81294
  const { account, client, pending, rpcFor } = options;
81168
81295
  const now = options.now ?? (() => /* @__PURE__ */ new Date());
81169
- const sleep = options.sleep ?? ((ms) => new Promise((resolve2) => setTimeout(resolve2, ms)));
81296
+ const sleep = options.sleep ?? ((ms) => new Promise((resolve3) => setTimeout(resolve3, ms)));
81170
81297
  const randomBytes17 = options.randomBytes ?? cryptoRandomBytes2;
81171
81298
  const confirmations = options.confirmations ?? 2;
81172
81299
  if (!Number.isSafeInteger(confirmations) || confirmations < 1)
@@ -81971,7 +82098,7 @@ async function waitForMilestone(client, input2) {
81971
82098
  throw new RangeError("The milestone wait timeout must be non-negative and finite.");
81972
82099
  if (!Number.isFinite(intervalMs) || intervalMs <= 0)
81973
82100
  throw new RangeError("The milestone wait interval must be positive and finite.");
81974
- const sleep = input2.sleep ?? ((ms) => new Promise((resolve2) => setTimeout(resolve2, ms)));
82101
+ const sleep = input2.sleep ?? ((ms) => new Promise((resolve3) => setTimeout(resolve3, ms)));
81975
82102
  const now = input2.now ?? (() => /* @__PURE__ */ new Date());
81976
82103
  const started = now().getTime();
81977
82104
  const deadline = started + timeoutMs;
@@ -86573,10 +86700,10 @@ async function buildStatus(deps) {
86573
86700
  const timers = deps.timers ?? { setTimeout, clearTimeout };
86574
86701
  const controller = new AbortController();
86575
86702
  let timeout;
86576
- const deadline = new Promise((resolve2) => {
86703
+ const deadline = new Promise((resolve3) => {
86577
86704
  timeout = timers.setTimeout(() => {
86578
86705
  controller.abort(new Error("Status request deadline exceeded."));
86579
- resolve2();
86706
+ resolve3();
86580
86707
  }, deps.timeoutMs ?? STATUS_TIMEOUT_MS);
86581
86708
  });
86582
86709
  try {
@@ -87055,6 +87182,12 @@ function isRecord4(value) {
87055
87182
  return typeof value === "object" && value !== null && !Array.isArray(value);
87056
87183
  }
87057
87184
 
87185
+ // src/cli.ts
87186
+ import { spawn as spawn3 } from "node:child_process";
87187
+ import { stat as stat16 } from "node:fs/promises";
87188
+ import { join as join28 } from "node:path";
87189
+ import { createInterface as createInterface3 } from "node:readline/promises";
87190
+
87058
87191
  // ../core/src/member-bundle.ts
87059
87192
  var MEMBER_BUNDLE_MAX_BYTES = 32 * 1024;
87060
87193
  var REMOTE_BLOCKED_GRANTS = /* @__PURE__ */ new Set([
@@ -87746,12 +87879,13 @@ var BODY_HEADER_NAMES = [
87746
87879
  "content-type"
87747
87880
  ];
87748
87881
  async function callService(args) {
87882
+ validateTimeoutSeconds(args.input.timeoutSeconds);
87749
87883
  const trace = createCallTrace(args);
87750
87884
  let execution;
87751
87885
  try {
87752
87886
  execution = await executeCallService(args, trace);
87753
87887
  } catch (error61) {
87754
- if (!(error61 instanceof VapiCallError && error61.code === "unsupported_network")) {
87888
+ if (!(error61 instanceof VapiCallError && (error61.code === "unsupported_network" || error61.code === "unsupported_payment"))) {
87755
87889
  await recordCallError(args, error61, trace).catch(() => void 0);
87756
87890
  }
87757
87891
  throw error61;
@@ -87865,6 +87999,8 @@ async function executeCallService(args, trace) {
87865
87999
  body: method === "GET" || method === "HEAD" ? void 0 : requestBody
87866
88000
  });
87867
88001
  const request = createRequest(headers);
88002
+ const probeTimeoutMs = input2.timeoutSeconds === void 0 ? args.timeoutMs ?? 3e4 : Math.min(input2.timeoutSeconds, 30) * 1e3;
88003
+ let requestTimeoutMs = probeTimeoutMs;
87868
88004
  const fetchWithGuardedRedirects = async (candidateRequest, followRedirects = true) => {
87869
88005
  let currentRequest = candidateRequest;
87870
88006
  let followedRedirects = 0;
@@ -87872,7 +88008,7 @@ async function executeCallService(args, trace) {
87872
88008
  const attempt = await fetchAttempt(
87873
88009
  fetchImpl,
87874
88010
  new Request(currentRequest.clone(), { redirect: "manual" }),
87875
- args.timeoutMs ?? 3e4
88011
+ requestTimeoutMs
87876
88012
  );
87877
88013
  const response = attempt.response;
87878
88014
  if (!isRedirectStatus2(response.status)) {
@@ -88027,7 +88163,12 @@ async function executeCallService(args, trace) {
88027
88163
  account,
88028
88164
  caps: args.spendCaps ?? config2.spendCaps,
88029
88165
  config: payableConfig(config2, account),
88030
- send: async (paidRequest) => {
88166
+ send: async (paidRequest, quote) => {
88167
+ requestTimeoutMs = paidRequestTimeoutMs(
88168
+ input2.timeoutSeconds,
88169
+ args.timeoutMs,
88170
+ quote.accepted.maxTimeoutSeconds
88171
+ );
88031
88172
  paidAttempt = await fetchWithGuardedRedirects(paidRequest, false);
88032
88173
  return paidAttempt;
88033
88174
  },
@@ -88066,7 +88207,7 @@ async function executeCallService(args, trace) {
88066
88207
  asset: completed.quote.accepted.asset,
88067
88208
  payTo: completed.quote.accepted.payTo,
88068
88209
  settlement: settlementWithExplorer2(completed.settlement, completed.quote.accepted.network),
88069
- proof: completed.response.headers.get("x-vapi-payment-proof")
88210
+ proof: completed.paymentProof
88070
88211
  },
88071
88212
  ...verificationFor(endpoint),
88072
88213
  ...expectedRequestFor(endpoint, completed.response.status)
@@ -88313,8 +88454,16 @@ async function resolveCallEndpoint(id2, endpointName, marketplaceHit, config2, f
88313
88454
  );
88314
88455
  }
88315
88456
  function registeredEndpoint(listing, verification) {
88457
+ const { payment, ...endpoint } = listing.endpoint;
88458
+ if (payment && (typeof payment.protocol === "string" || typeof payment.network !== "string")) {
88459
+ throw new VapiCallError(
88460
+ "unsupported_payment",
88461
+ `Payment protocol ${payment.protocol} is not supported. This client pays x402 exact USDC endpoints only.`
88462
+ );
88463
+ }
88316
88464
  return {
88317
- ...listing.endpoint,
88465
+ ...endpoint,
88466
+ ...payment ? { payment: { network: payment.network, payTo: payment.payTo } } : {},
88318
88467
  verification: verification ?? listing.service.verification,
88319
88468
  serviceNetworks: listing.service.networks,
88320
88469
  registered: true,
@@ -88476,7 +88625,7 @@ async function readResponseBody2(response) {
88476
88625
  async function fetchAttempt(fetchImpl, request, timeoutMs) {
88477
88626
  const controller = new AbortController();
88478
88627
  let rejectTimeout = null;
88479
- const timeoutError = new Error(`API request timed out after ${timeoutMs}ms.`);
88628
+ const timeoutError = new Error(`API request timed out after ${timeoutMs / 1e3} seconds.`);
88480
88629
  const timedOut = new Promise((_resolve, reject) => {
88481
88630
  rejectTimeout = reject;
88482
88631
  });
@@ -88516,6 +88665,19 @@ async function fetchAttempt(fetchImpl, request, timeoutMs) {
88516
88665
  throw error61;
88517
88666
  }
88518
88667
  }
88668
+ function validateTimeoutSeconds(timeoutSeconds) {
88669
+ if (timeoutSeconds !== void 0 && (!Number.isInteger(timeoutSeconds) || timeoutSeconds < 1 || timeoutSeconds > 300)) {
88670
+ throw new Error("call timeoutSeconds must be an integer from 1 to 300 seconds.");
88671
+ }
88672
+ }
88673
+ function paidRequestTimeoutMs(timeoutSeconds, internalTimeoutMs, offerTimeoutSeconds) {
88674
+ const usableOfferTimeout = Number.isInteger(offerTimeoutSeconds) && offerTimeoutSeconds > 0 ? offerTimeoutSeconds : void 0;
88675
+ if (timeoutSeconds !== void 0) {
88676
+ return Math.min(timeoutSeconds, usableOfferTimeout ?? timeoutSeconds) * 1e3;
88677
+ }
88678
+ if (internalTimeoutMs !== void 0) return internalTimeoutMs;
88679
+ return usableOfferTimeout === void 0 ? 12e4 : Math.min(12e4, Math.max(3e4, usableOfferTimeout * 1e3));
88680
+ }
88519
88681
  function mapX402PaymentError(error61, resumeId) {
88520
88682
  if (!(error61 instanceof X402PaymentError)) return error61;
88521
88683
  if (error61.code === "payment_rejected") {
@@ -88531,9 +88693,10 @@ function mapX402PaymentError(error61, resumeId) {
88531
88693
  });
88532
88694
  }
88533
88695
  const resume = resumeId !== void 0 && error61.possibleSettlement?.authorizationNonce ? ` Check whether it settled with \`vapi pay --resume ${resumeId}\` before paying again.` : "";
88696
+ const timeoutDetail = error61.cause instanceof Error && error61.cause.message.startsWith("API request timed out after ") ? `${error61.cause.message} ` : "";
88534
88697
  return new VapiCallError(
88535
88698
  "settlement_unknown",
88536
- `${error61.message}${resume}`,
88699
+ `${timeoutDetail}${error61.message}${resume}`,
88537
88700
  error61.possibleSettlement,
88538
88701
  { cause: error61.cause }
88539
88702
  );
@@ -88665,13 +88828,7 @@ var inspectToolResultSchema = external_exports.object({
88665
88828
  liveness: listingLivenessSchema.optional(),
88666
88829
  conformance: listingConformanceSchema.optional(),
88667
88830
  identity: listingIdentitySchema.optional(),
88668
- payment: external_exports.object({
88669
- scheme: external_exports.literal("exact"),
88670
- network: external_exports.string(),
88671
- asset: external_exports.string(),
88672
- payTo: external_exports.string(),
88673
- checkedAt: external_exports.string()
88674
- }).nullable()
88831
+ payment: discoveryEndpointSchema.shape.payment.unwrap().nullable()
88675
88832
  });
88676
88833
  var callSearchInputSchema = external_exports.object({
88677
88834
  query: external_exports.string().trim().max(200).optional().describe("Capability, API, service, or request."),
@@ -88700,7 +88857,10 @@ var callPayInputSchema = external_exports.object({
88700
88857
  (value) => /^0x[0-9a-fA-F]{40}$/.test(value) || isSolanaAddress(value),
88701
88858
  "Expected an EVM or Solana address."
88702
88859
  ).optional(),
88703
- maxPriceUsd: external_exports.union([external_exports.number().nonnegative(), external_exports.string().regex(/^\d+(?:\.\d{1,6})?$/)]).optional()
88860
+ maxPriceUsd: external_exports.union([external_exports.number().nonnegative(), external_exports.string().regex(/^\d+(?:\.\d{1,6})?$/)]).optional(),
88861
+ timeoutSeconds: external_exports.number().int().min(1).max(300).optional().describe(
88862
+ "Seconds to wait for the paid response. Default: the provider's maxTimeoutSeconds, at most 120."
88863
+ )
88704
88864
  });
88705
88865
  var callSearch = defineAction({
88706
88866
  name: "call.search",
@@ -88963,7 +89123,7 @@ async function readResult(response, signal, secrets = []) {
88963
89123
  return {
88964
89124
  status: response.status,
88965
89125
  contentType: contentType === null ? null : redactKnownSecrets2(contentType, secrets),
88966
- body: sanitizeReturnedValue(await readResponseBody3(response, contentType, signal), secrets)
89126
+ body: sanitizeReturnedValue2(await readResponseBody3(response, contentType, signal), secrets)
88967
89127
  };
88968
89128
  }
88969
89129
  async function readResponseBody3(response, contentType, signal) {
@@ -89008,17 +89168,17 @@ function isJsonContentType2(value) {
89008
89168
  const mediaType = value?.split(";", 1)[0]?.trim().toLowerCase() ?? "";
89009
89169
  return mediaType === "application/json" || mediaType.endsWith("+json");
89010
89170
  }
89011
- function sanitizeReturnedValue(value, secrets, depth = 0) {
89171
+ function sanitizeReturnedValue2(value, secrets, depth = 0) {
89012
89172
  if (typeof value === "string") return redactKnownSecrets2(value, secrets);
89013
89173
  if (value === null || typeof value !== "object") return value;
89014
89174
  if (depth >= 16) return "[redacted nested response value]";
89015
89175
  if (Array.isArray(value)) {
89016
- return value.map((item) => sanitizeReturnedValue(item, secrets, depth + 1));
89176
+ return value.map((item) => sanitizeReturnedValue2(item, secrets, depth + 1));
89017
89177
  }
89018
89178
  return Object.fromEntries(
89019
89179
  Object.entries(value).map(([key2, item]) => [
89020
89180
  redactKnownSecrets2(key2, secrets),
89021
- sanitizeReturnedValue(item, secrets, depth + 1)
89181
+ sanitizeReturnedValue2(item, secrets, depth + 1)
89022
89182
  ])
89023
89183
  );
89024
89184
  }
@@ -94524,7 +94684,13 @@ function toolError(error61) {
94524
94684
  {
94525
94685
  error: error61.message,
94526
94686
  code: error61.code,
94527
- ...error61.possibleSettlement ? { possibleSettlement: error61.possibleSettlement } : {},
94687
+ ...error61.possibleSettlement ? {
94688
+ possibleSettlement: Object.fromEntries(
94689
+ Object.entries(error61.possibleSettlement).filter(
94690
+ ([key2]) => key2 !== "authorizationTransaction"
94691
+ )
94692
+ )
94693
+ } : {},
94528
94694
  ...error61.paymentRejection ? { paymentRejection: error61.paymentRejection } : {},
94529
94695
  ...error61.confirmedSettlement ? { confirmedSettlement: error61.confirmedSettlement } : {}
94530
94696
  },
@@ -94706,6 +94872,9 @@ function rgbToAnsi256(red, green, blue) {
94706
94872
  import { readFile as readFile24, stat as stat14 } from "node:fs/promises";
94707
94873
  import { join as join21 } from "node:path";
94708
94874
 
94875
+ // src/dashboard.ts
94876
+ import { resolve as resolve2 } from "node:path";
94877
+
94709
94878
  // src/publish-client.ts
94710
94879
  var LISTING_CATEGORIES = ["ai", "data", "crypto", "compute", "search"];
94711
94880
  var PROBE_MODES = ["origin", "endpoint", "openapi"];
@@ -95026,7 +95195,8 @@ async function runLoginFlow(argv, json2, io, dependencies, options = {}) {
95026
95195
  booleanOptions: /* @__PURE__ */ new Set(["--publish", "--no-browser"]),
95027
95196
  maximumPositionals: 0
95028
95197
  });
95029
- const target = await targetWallet(parsed, dependencies);
95198
+ const paths = getVapiPaths(options.home);
95199
+ const target = await targetWallet(parsed, dependencies, paths.directory);
95030
95200
  const { account } = await unlockTarget(target, dependencies);
95031
95201
  const label = parsed.one("--label") ?? target.name;
95032
95202
  const scopes = [
@@ -95035,13 +95205,13 @@ async function runLoginFlow(argv, json2, io, dependencies, options = {}) {
95035
95205
  "tasks:write",
95036
95206
  ...parsed.has("--publish") ? ["call.publish"] : []
95037
95207
  ];
95038
- const config2 = await loadConfig(getVapiPaths().config, process.env, { notice: io.stderr });
95039
- const apiBase = registryBaseUrl(config2);
95208
+ const config2 = await loadConfig(paths.config, process.env, { notice: io.stderr });
95209
+ const apiBase = options.apiBase ?? registryBaseUrl(config2);
95040
95210
  const fetchImpl = dependencies.fetchImpl ?? createPublicFetch({ allowPrivateNetwork: false });
95041
95211
  const secrets = getSecretStore(dependencies);
95042
95212
  const device = await ensureDeviceName({
95043
95213
  env: getEnvironment(dependencies),
95044
- configPath: getVapiPaths().config,
95214
+ configPath: paths.config,
95045
95215
  ...dependencies.hostname === void 0 ? {} : { hostname: dependencies.hostname() }
95046
95216
  });
95047
95217
  const bearer = await trustedLinkBearer({
@@ -95295,6 +95465,87 @@ function shortAddress(address4) {
95295
95465
  return address4.length <= 12 ? address4 : `${address4.slice(0, 6)}\u2026${address4.slice(-4)}`;
95296
95466
  }
95297
95467
 
95468
+ // src/dashboard.ts
95469
+ function dashboardUrl(apiBase) {
95470
+ return `${apiBase.replace(/\/+$/u, "")}/agents`;
95471
+ }
95472
+ async function offerDashboardLink({
95473
+ name,
95474
+ json: json2,
95475
+ noLink = false,
95476
+ io,
95477
+ dependencies,
95478
+ home = getVapiPaths().directory,
95479
+ apiBase
95480
+ }) {
95481
+ const otherHome = resolve2(home) !== resolve2(getVapiPaths().directory);
95482
+ const command = `${otherHome ? `VAPI_HOME=${shellQuote(home)} ` : ""}${apiBase === void 0 ? "" : `VAPI_REGISTRY_URL=${shellQuote(apiBase)} `}vapi login --account ${name}`;
95483
+ const unlinked = {
95484
+ linked: false,
95485
+ next: [{ kind: "link", account: name, command }]
95486
+ };
95487
+ const hint = () => {
95488
+ if (!json2) io.stdout(`Run \`${command}\` to see this wallet on your dashboard.`);
95489
+ return unlinked;
95490
+ };
95491
+ try {
95492
+ const store = await WalletStore.open(home, {
95493
+ secrets: getSecretStore(dependencies),
95494
+ env: getEnvironment(dependencies)
95495
+ });
95496
+ if (store.entry(name)?.link !== void 0) return { linked: true };
95497
+ if (noLink || json2 || !isInteractive(dependencies) || activeAgentMarker(getEnvironment(dependencies)) !== void 0) {
95498
+ return hint();
95499
+ }
95500
+ const answer = (await getLinePrompt(dependencies)(`Link ${name} to your vAPI dashboard? [Y/n] `)).trim();
95501
+ if (!/^(?:y|yes)?$/iu.test(answer)) return hint();
95502
+ await runLoginFlow(["--account", name, "--label", name], false, io, dependencies, {
95503
+ home,
95504
+ ...apiBase === void 0 ? {} : { apiBase }
95505
+ });
95506
+ await store.reload();
95507
+ const link3 = store.entry(name)?.link;
95508
+ if (link3 === void 0) return hint();
95509
+ io.stdout(`See it on your dashboard: ${dashboardUrl(link3.apiBase)}`);
95510
+ return { linked: true };
95511
+ } catch (error61) {
95512
+ if (!json2) {
95513
+ io.stderr(`Link not completed: ${error61 instanceof Error ? error61.message : String(error61)}`);
95514
+ }
95515
+ return hint();
95516
+ }
95517
+ }
95518
+ async function dashboardCommand(argv, json2, io, dependencies) {
95519
+ const parsed = parseArguments(argv, {
95520
+ valueOptions: /* @__PURE__ */ new Set(["--wallet"]),
95521
+ booleanOptions: /* @__PURE__ */ new Set(["--no-browser", "--no-link"]),
95522
+ maximumPositionals: 0
95523
+ });
95524
+ const target = await targetWallet(parsed, dependencies);
95525
+ let status = { linked: true };
95526
+ if (target.entry.link === void 0) {
95527
+ if (!json2) io.stdout(`${target.name} is not linked to your vAPI dashboard yet.`);
95528
+ status = await offerDashboardLink({
95529
+ name: target.name,
95530
+ json: json2,
95531
+ noLink: parsed.has("--no-link"),
95532
+ io,
95533
+ dependencies: parsed.has("--no-browser") ? { ...dependencies, openUrl: () => false } : dependencies
95534
+ });
95535
+ }
95536
+ await target.store.reload();
95537
+ const apiBase = target.store.entry(target.name)?.link?.apiBase ?? registryBaseUrl(await readConfig(getVapiPaths().config, io));
95538
+ const url2 = dashboardUrl(apiBase);
95539
+ let opened = false;
95540
+ if (status.linked && !parsed.has("--no-browser") && (dependencies.interactive ?? Boolean(process.stdout.isTTY)) && activeAgentMarker(getEnvironment(dependencies)) === void 0) {
95541
+ opened = (dependencies.openUrl ?? openInBrowser)(url2);
95542
+ }
95543
+ io.stdout(json2 ? JSON.stringify({ account: target.name, url: url2, ...status, opened }) : url2);
95544
+ }
95545
+ function shellQuote(value) {
95546
+ return /^[a-zA-Z0-9_./-]+$/u.test(value) ? value : `'${value.replace(/'/gu, "'\\''")}'`;
95547
+ }
95548
+
95298
95549
  // src/status.ts
95299
95550
  import { stat as stat13 } from "node:fs/promises";
95300
95551
  import { homedir as homedir2 } from "node:os";
@@ -97680,10 +97931,10 @@ function apiEndpoint2(apiBase, path) {
97680
97931
  }
97681
97932
  async function sleepFor2(milliseconds, signal) {
97682
97933
  if (signal?.aborted === true) throw signal.reason;
97683
- await new Promise((resolve2, reject) => {
97934
+ await new Promise((resolve3, reject) => {
97684
97935
  const finish = () => {
97685
97936
  signal?.removeEventListener("abort", abort);
97686
- resolve2();
97937
+ resolve3();
97687
97938
  };
97688
97939
  const timeout = setTimeout(finish, milliseconds);
97689
97940
  const abort = () => {
@@ -98018,7 +98269,7 @@ async function readProcessStdin() {
98018
98269
  }
98019
98270
 
98020
98271
  // src/version.ts
98021
- var CLI_VERSION = "0.9.2";
98272
+ var CLI_VERSION = "0.9.5";
98022
98273
 
98023
98274
  // src/status.ts
98024
98275
  async function statusCommand(argv, json2, io, dependencies) {
@@ -98162,10 +98413,10 @@ async function runStatusSweep(args) {
98162
98413
  timeoutMs,
98163
98414
  ...args.warn === void 0 ? {} : { warn: args.warn }
98164
98415
  }),
98165
- new Promise((resolve2) => {
98416
+ new Promise((resolve3) => {
98166
98417
  timeout = setTimeout(() => {
98167
98418
  controller.abort();
98168
- resolve2();
98419
+ resolve3();
98169
98420
  }, timeoutMs);
98170
98421
  timeout.unref();
98171
98422
  })
@@ -98394,7 +98645,7 @@ async function siblingsFetchImpl(dependencies) {
98394
98645
  function shortAddress3(address4) {
98395
98646
  return address4.length <= 12 ? address4 : `${address4.slice(0, 6)}\u2026${address4.slice(-4)}`;
98396
98647
  }
98397
- async function accountsAddCommand(argv, json2, io, dependencies) {
98648
+ async function accountsAddCommand(argv, json2, io, dependencies, options = { link: "always" }) {
98398
98649
  const parsed = parseArguments(argv, {
98399
98650
  valueOptions: /* @__PURE__ */ new Set(["--label"]),
98400
98651
  booleanOptions: /* @__PURE__ */ new Set(["--no-link"]),
@@ -98411,6 +98662,18 @@ async function accountsAddCommand(argv, json2, io, dependencies) {
98411
98662
  });
98412
98663
  await recordAudit(dependencies, "wallet.create", { wallet: created.account });
98413
98664
  const address4 = created.address;
98665
+ if (options.link === "offer") {
98666
+ if (!json2) io.stdout(`Account ${created.account} derived: ${address4}`);
98667
+ const link3 = await offerDashboardLink({
98668
+ name: created.account,
98669
+ json: json2,
98670
+ noLink: parsed.has("--no-link"),
98671
+ io,
98672
+ dependencies
98673
+ });
98674
+ if (json2) io.stdout(JSON.stringify({ account: created.account, address: address4, ...link3 }));
98675
+ return;
98676
+ }
98414
98677
  if (parsed.has("--no-link")) {
98415
98678
  output2(
98416
98679
  io,
@@ -99226,10 +99489,10 @@ async function autoUploadBackup(io, json2, dependencies) {
99226
99489
  const timeoutMs = dependencies.cloudBackup?.uploadTimeoutMs ?? DEFAULT_UPLOAD_TIMEOUT_MS;
99227
99490
  const controller = new AbortController();
99228
99491
  let timer;
99229
- const timeout = new Promise((resolve2) => {
99492
+ const timeout = new Promise((resolve3) => {
99230
99493
  timer = setTimeout(() => {
99231
99494
  controller.abort();
99232
- resolve2({ status: "skipped", reason: "timeout" });
99495
+ resolve3({ status: "skipped", reason: "timeout" });
99233
99496
  }, timeoutMs);
99234
99497
  timer.unref();
99235
99498
  });
@@ -100453,7 +100716,7 @@ var HTTP_NOT_FOUND_PATTERN = /\b404\b/u;
100453
100716
  var OTHER_SCOPE_PATTERN = /\b(?:project|environment|service|workspace|team|token|user|account|volume|deployment|command|file|directory|module|package)s?\b/iu;
100454
100717
  var SIDECAR_SUFFIX = ".railway.json";
100455
100718
  var MINIMUM_SECRET_LENGTH = 8;
100456
- var defaultRailwayExec = (file2, args) => new Promise((resolve2, reject) => {
100719
+ var defaultRailwayExec = (file2, args) => new Promise((resolve3, reject) => {
100457
100720
  const child = spawn2(file2, [...args], {
100458
100721
  stdio: ["ignore", "pipe", "pipe"],
100459
100722
  env: process.env,
@@ -100468,7 +100731,7 @@ var defaultRailwayExec = (file2, args) => new Promise((resolve2, reject) => {
100468
100731
  stderr2 += chunk;
100469
100732
  });
100470
100733
  child.once("error", reject);
100471
- child.once("close", (code) => resolve2({ code, stdout, stderr: stderr2 }));
100734
+ child.once("close", (code) => resolve3({ code, stdout, stderr: stderr2 }));
100472
100735
  });
100473
100736
  function parseSandboxId(stdout) {
100474
100737
  const trimmed = stdout.trim();
@@ -100601,8 +100864,8 @@ function createRailwayRuntime(options) {
100601
100864
  const readyAttempts = options.readyAttempts ?? DEFAULT_RAILWAY_READY_ATTEMPTS;
100602
100865
  const readyIntervalMs = options.readyIntervalMs ?? DEFAULT_RAILWAY_READY_INTERVAL_MS;
100603
100866
  const signalDestroyTimeoutMs = options.signalDestroyTimeoutMs ?? DEFAULT_RAILWAY_SIGNAL_DESTROY_TIMEOUT_MS;
100604
- const sleep = options.sleep ?? ((milliseconds) => new Promise((resolve2) => {
100605
- setTimeout(resolve2, milliseconds);
100867
+ const sleep = options.sleep ?? ((milliseconds) => new Promise((resolve3) => {
100868
+ setTimeout(resolve3, milliseconds);
100606
100869
  }));
100607
100870
  let secrets = options.secrets;
100608
100871
  const getSecrets = () => secrets ??= secretStore();
@@ -101520,7 +101783,7 @@ function createLocalRuntime(options) {
101520
101783
  const processCommand = options.processCommand ?? defaultProcessCommand;
101521
101784
  const ownsProcess = (handle, pid) => processCommand(pid)?.includes(runResultPath(home, handle.runId)) === true;
101522
101785
  const closeFd = options.closeFd ?? closeSync2;
101523
- const readFile29 = options.readFile ?? nodeReadFile;
101786
+ const readFile30 = options.readFile ?? nodeReadFile;
101524
101787
  const now = options.now ?? (() => /* @__PURE__ */ new Date());
101525
101788
  const openLog = options.openLog ?? ((path) => {
101526
101789
  mkdirSync2(runsDirectory(home), { recursive: true, mode: 448 });
@@ -101575,7 +101838,7 @@ function createLocalRuntime(options) {
101575
101838
  return handle;
101576
101839
  },
101577
101840
  async status(handle) {
101578
- const result = await readResultFile(readFile29, runResultPath(home, handle.runId));
101841
+ const result = await readResultFile(readFile30, runResultPath(home, handle.runId));
101579
101842
  if (result !== void 0) return result;
101580
101843
  const pid = localPid(handle);
101581
101844
  if (pid === void 0 || handle.kind !== "local") {
@@ -101678,10 +101941,10 @@ function childArguments(member, run) {
101678
101941
  ...run.drawUsd ? ["--draw", run.drawUsd] : []
101679
101942
  ];
101680
101943
  }
101681
- async function readResultFile(readFile29, path) {
101944
+ async function readResultFile(readFile30, path) {
101682
101945
  let text;
101683
101946
  try {
101684
- text = await readFile29(path, "utf8");
101947
+ text = await readFile30(path, "utf8");
101685
101948
  } catch (error61) {
101686
101949
  if (hasCode3(error61, "ENOENT")) return void 0;
101687
101950
  return { state: "failed", detail: "unreadable result file" };
@@ -102455,7 +102718,7 @@ function usd(value, minimumDecimals = 0) {
102455
102718
  import { mkdir as mkdir20, readFile as readFile27, writeFile as writeFile11 } from "node:fs/promises";
102456
102719
  import { homedir as systemHomedir } from "node:os";
102457
102720
  import { dirname as dirname14, posix, win32 as win322 } from "node:path";
102458
- var MCP_INSTALL_USAGE = "Usage: vapi mcp install <claude|cursor|codex> [--home <dir>] [--registry <url>] [--json]";
102721
+ var MCP_INSTALL_USAGE = "Usage: vapi mcp install <claude|cursor|codex> [--home <dir>] [--registry <url>] [--no-link] [--json]";
102459
102722
  var APPS = /* @__PURE__ */ new Set(["claude", "cursor", "codex"]);
102460
102723
  var NEXT_STEP = {
102461
102724
  claude: 'Restart Claude Desktop, then ask it: "Search vAPI for a weather API."',
@@ -102496,6 +102759,7 @@ function mcpInstallTarget(app, context) {
102496
102759
  async function mcpInstallCommand(argv, json2, io, dependencies) {
102497
102760
  const parsed = parseArguments(argv, {
102498
102761
  valueOptions: /* @__PURE__ */ new Set(["--home", "--registry"]),
102762
+ booleanOptions: /* @__PURE__ */ new Set(["--no-link"]),
102499
102763
  maximumPositionals: 1
102500
102764
  });
102501
102765
  const appValue = parsed.positionals[0];
@@ -102517,13 +102781,39 @@ ${MCP_INSTALL_USAGE}`
102517
102781
  });
102518
102782
  const entry = serverEntry(home, registry2);
102519
102783
  const created = await writeMcpConfig(target, entry);
102784
+ const name = await unlinkedDefaultAccount(home, dependencies);
102785
+ const offerLink = (name2) => offerDashboardLink({
102786
+ name: name2,
102787
+ json: json2,
102788
+ noLink: parsed.has("--no-link"),
102789
+ io,
102790
+ dependencies,
102791
+ home,
102792
+ apiBase: parsed.one("--registry")
102793
+ });
102794
+ const link3 = json2 && name !== void 0 ? await offerLink(name) : {};
102520
102795
  output3(
102521
102796
  io,
102522
102797
  json2,
102523
- { command: "mcp install", app: appValue, path: target.path, created, home, registry: registry2 },
102798
+ { ...link3, command: "mcp install", app: appValue, path: target.path, created, home, registry: registry2 },
102524
102799
  `${created ? "Wrote" : "Updated"} ${target.path}.`
102525
102800
  );
102526
- if (!json2) io.stdout(NEXT_STEP[appValue]);
102801
+ if (!json2) {
102802
+ io.stdout(NEXT_STEP[appValue]);
102803
+ if (name !== void 0) await offerLink(name);
102804
+ }
102805
+ }
102806
+ async function unlinkedDefaultAccount(home, dependencies) {
102807
+ try {
102808
+ const store = await WalletStore.open(home, {
102809
+ secrets: getSecretStore(dependencies),
102810
+ env: getEnvironment(dependencies)
102811
+ });
102812
+ const name = store.defaultName;
102813
+ if (name !== void 0 && store.resolve({ name }).entry.link === void 0) return name;
102814
+ } catch {
102815
+ }
102816
+ return void 0;
102527
102817
  }
102528
102818
  function isMcpInstallApp(value) {
102529
102819
  return APPS.has(value);
@@ -102531,7 +102821,7 @@ function isMcpInstallApp(value) {
102531
102821
  function serverEntry(home, registry2) {
102532
102822
  return {
102533
102823
  command: "npx",
102534
- args: ["-y", "vapi-network", "mcp"],
102824
+ args: ["-y", "vapi-network@latest", "mcp"],
102535
102825
  env: { VAPI_HOME: home, VAPI_REGISTRY_URL: registry2 }
102536
102826
  };
102537
102827
  }
@@ -102580,7 +102870,7 @@ function tomlConfig(existing, entry) {
102580
102870
  const block = [
102581
102871
  "[mcp_servers.vapi]",
102582
102872
  'command = "npx"',
102583
- 'args = ["-y", "vapi-network", "mcp"]',
102873
+ 'args = ["-y", "vapi-network@latest", "mcp"]',
102584
102874
  `env = { VAPI_HOME = "${escapeToml(entry.env.VAPI_HOME)}", VAPI_REGISTRY_URL = "${escapeToml(entry.env.VAPI_REGISTRY_URL)}" }`,
102585
102875
  ""
102586
102876
  ].join("\n");
@@ -102747,13 +103037,13 @@ async function sendConfig(dependencies) {
102747
103037
  // src/setup.ts
102748
103038
  import { rm as rm5 } from "node:fs/promises";
102749
103039
  import { join as join26 } from "node:path";
102750
- 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.";
103040
+ 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.`;
102751
103041
  var VAULT_CHOICE = "Create a new vault, or restore one from a recovery phrase? [new/restore] ";
102752
103042
  async function setupCommand(argv, json2, io, dependencies) {
102753
103043
  let parsed;
102754
103044
  try {
102755
103045
  parsed = parseArguments(argv, {
102756
- valueOptions: /* @__PURE__ */ new Set(),
103046
+ valueOptions: /* @__PURE__ */ new Set(["--accounts"]),
102757
103047
  booleanOptions: /* @__PURE__ */ new Set(["--no-cloud-backup"]),
102758
103048
  maximumPositionals: 0
102759
103049
  });
@@ -102764,6 +103054,7 @@ async function setupCommand(argv, json2, io, dependencies) {
102764
103054
  const paths = getVapiPaths();
102765
103055
  const steps = [];
102766
103056
  const humanIo = json2 ? stderrIo(io) : io;
103057
+ const accountCount = parseAccountCount(parsed.one("--accounts"));
102767
103058
  if (!await fileExists2(paths.config)) {
102768
103059
  await writeDefaultConfig(paths.config, process.env, { networks: ["base"] });
102769
103060
  steps.push("config");
@@ -102774,6 +103065,7 @@ async function setupCommand(argv, json2, io, dependencies) {
102774
103065
  let changedVault = false;
102775
103066
  let changedAccount = false;
102776
103067
  let changedLink = false;
103068
+ let scannedAddresses;
102777
103069
  if (!await fileExists2(join26(paths.directory, "vault.json"))) {
102778
103070
  const choice = await vaultChoice(dependencies);
102779
103071
  if (choice === "restore") {
@@ -102781,12 +103073,14 @@ async function setupCommand(argv, json2, io, dependencies) {
102781
103073
  throw new Error("Restoring needs a terminal to type the phrase.");
102782
103074
  }
102783
103075
  const readSecret = dependencies.prompts?.secret ?? promptForSecret;
102784
- await restoreVaultFromPhrase(
103076
+ const restored = await restoreVaultFromPhrase(
102785
103077
  await readSecret("Recovery phrase: "),
102786
103078
  config2,
102787
103079
  humanIo,
102788
- dependencies
103080
+ dependencies,
103081
+ accountCount
102789
103082
  );
103083
+ scannedAddresses = restored.scannedAddresses;
102790
103084
  store = await WalletStore.open(paths.directory, {
102791
103085
  secrets: getSecretStore(dependencies),
102792
103086
  env: dependencies.env ?? process.env,
@@ -102839,22 +103133,35 @@ async function setupCommand(argv, json2, io, dependencies) {
102839
103133
  }
102840
103134
  if (json2) {
102841
103135
  io.stdout(
102842
- JSON.stringify({ vault, account, address: address4, linked, steps, cloudBackup })
103136
+ JSON.stringify({
103137
+ vault,
103138
+ account,
103139
+ address: address4,
103140
+ linked,
103141
+ steps,
103142
+ cloudBackup,
103143
+ ...scannedAddresses === void 0 ? {} : { scannedAddresses }
103144
+ })
102843
103145
  );
102844
103146
  }
102845
103147
  }
102846
- async function restoreVaultFromPhrase(phrase, config2, io, dependencies) {
103148
+ async function restoreVaultFromPhrase(phrase, config2, io, dependencies, accountCount) {
102847
103149
  const paths = getVapiPaths();
102848
103150
  const validatedPhrase = validateRecoveryPhrase(phrase);
102849
103151
  const readBalance3 = baseUsdcBalanceReader(config2, dependencies);
102850
103152
  const key2 = await loadOrCreateDeviceKey({ secrets: getSecretStore(dependencies) });
102851
103153
  let names;
103154
+ let scannedAddresses = 0;
102852
103155
  try {
102853
103156
  const restored = await restoreVault({
102854
103157
  path: join26(paths.directory, "vault.json"),
102855
103158
  key: key2,
102856
103159
  phrase: validatedPhrase,
102857
103160
  probe: async (address4) => await readBalance3(address4) > 0n,
103161
+ ...accountCount === void 0 ? {} : { accountCount },
103162
+ onScanComplete: (count) => {
103163
+ scannedAddresses = count;
103164
+ },
102858
103165
  ...dependencies.now === void 0 ? {} : { now: dependencies.now }
102859
103166
  });
102860
103167
  names = restored.accounts().map((account) => account.name);
@@ -102866,8 +103173,25 @@ async function restoreVaultFromPhrase(phrase, config2, io, dependencies) {
102866
103173
  ...names[0] === void 0 ? {} : { wallet: names[0] },
102867
103174
  detail: `${names.length} account(s)`
102868
103175
  });
102869
- io.stdout(`Vault restored with ${names.length} account(s): ${names.join(", ")}`);
102870
- return { names };
103176
+ io.stdout(
103177
+ `Vault restored with ${names.length} account(s): ${names.join(", ")}. ${scannedAddresses} address(es) scanned.`
103178
+ );
103179
+ return { names, scannedAddresses };
103180
+ }
103181
+ function parseAccountCount(value) {
103182
+ if (value === void 0) return void 0;
103183
+ if (!/^\d+$/u.test(value)) {
103184
+ throw new UsageError(
103185
+ `--accounts must be a positive integer no greater than ${MAX_RESTORE_ACCOUNTS}.`
103186
+ );
103187
+ }
103188
+ const count = Number(value);
103189
+ if (!Number.isSafeInteger(count) || count < 1 || count > MAX_RESTORE_ACCOUNTS) {
103190
+ throw new UsageError(
103191
+ `--accounts must be a positive integer no greater than ${MAX_RESTORE_ACCOUNTS}.`
103192
+ );
103193
+ }
103194
+ return count;
102871
103195
  }
102872
103196
  async function vaultChoice(dependencies) {
102873
103197
  const answer = dependencies.prompts?.line === void 0 ? isInteractive(dependencies) ? await promptForLine(VAULT_CHOICE) : "" : await dependencies.prompts.line(VAULT_CHOICE);
@@ -103159,7 +103483,7 @@ async function taskContext(parsed, io, dependencies, publicOnly = false) {
103159
103483
  pending,
103160
103484
  randomUUID: dependencies.tasks?.randomUUID ?? randomUUID6,
103161
103485
  signInHint: "Run vapi login for the acting wallet.",
103162
- sleep: dependencies.tasks?.sleep ?? ((milliseconds) => new Promise((resolve2) => setTimeout(resolve2, milliseconds)))
103486
+ sleep: dependencies.tasks?.sleep ?? ((milliseconds) => new Promise((resolve3) => setTimeout(resolve3, milliseconds)))
103163
103487
  };
103164
103488
  }
103165
103489
  async function taskRequest2(verb, route, operation) {
@@ -104959,11 +105283,11 @@ ${usage}`);
104959
105283
  }
104960
105284
  }
104961
105285
  async function referencedSleep(milliseconds, signal) {
104962
- await new Promise((resolve2) => {
105286
+ await new Promise((resolve3) => {
104963
105287
  const finish = () => {
104964
105288
  clearTimeout(timer);
104965
105289
  signal?.removeEventListener("abort", finish);
104966
- resolve2();
105290
+ resolve3();
104967
105291
  };
104968
105292
  const timer = setTimeout(finish, milliseconds);
104969
105293
  if (signal === void 0) return;
@@ -104975,6 +105299,7 @@ async function referencedSleep(milliseconds, signal) {
104975
105299
  // src/vault.ts
104976
105300
  import { join as join27 } from "node:path";
104977
105301
  var VAULT_USAGE = "Usage: vapi vault protect|unprotect|lock|unlock|status [--json]";
105302
+ var RESTORE_USAGE = "Usage: vapi restore [--accounts <n> | --from-owner [--owner <0x\u2026>]] [--json]";
104978
105303
  var LEGACY_PASSWORD_NOTICE = "VAPI_KEYSTORE_PASSWORD is deprecated for vault passwords; use VAPI_VAULT_PASSWORD instead.";
104979
105304
  async function vaultCommand(argv, json2, io, dependencies) {
104980
105305
  const subcommand = argv[0];
@@ -105004,9 +105329,17 @@ async function restoreCommand(argv, json2, io, dependencies) {
105004
105329
  await restoreFromOwnerCommand(argv, json2, io, dependencies);
105005
105330
  return;
105006
105331
  }
105007
- if (argv.length > 0) {
105008
- throw new UsageError("Usage: vapi restore [--from-owner [--owner <0x\u2026>]] [--json]");
105332
+ let parsed;
105333
+ try {
105334
+ parsed = parseArguments(argv, {
105335
+ valueOptions: /* @__PURE__ */ new Set(["--accounts"]),
105336
+ maximumPositionals: 0
105337
+ });
105338
+ } catch (error61) {
105339
+ if (error61 instanceof UsageError) throw new UsageError(RESTORE_USAGE);
105340
+ throw error61;
105009
105341
  }
105342
+ const accountCount = parseRestoreAccountCount(parsed.one("--accounts"));
105010
105343
  const paths = getVapiPaths();
105011
105344
  const path = join27(paths.directory, "vault.json");
105012
105345
  if (await fileExists2(path)) {
@@ -105020,13 +105353,39 @@ async function restoreCommand(argv, json2, io, dependencies) {
105020
105353
  const config2 = await readConfig(paths.config, json2 ? quietIo(io) : io);
105021
105354
  const phrase = isStdinInteractive(dependencies) ? await getPrompts(dependencies).secret("Recovery phrase: ") : await (dependencies.readStdin ?? readProcessStdin3)();
105022
105355
  const restoreIo = json2 ? quietIo(io) : io;
105023
- const { names } = await restoreVaultFromPhrase(phrase.trim(), config2, restoreIo, dependencies);
105356
+ const { names, scannedAddresses } = await restoreVaultFromPhrase(
105357
+ phrase.trim(),
105358
+ config2,
105359
+ restoreIo,
105360
+ dependencies,
105361
+ accountCount
105362
+ );
105024
105363
  if (json2) {
105025
- output3(io, true, { command: "restore", vault: "restored", accounts: names }, "");
105364
+ output3(
105365
+ io,
105366
+ true,
105367
+ { command: "restore", vault: "restored", accounts: names, scannedAddresses },
105368
+ ""
105369
+ );
105026
105370
  return;
105027
105371
  }
105028
105372
  io.stdout(`Run vapi setup to link ${names[0]}.`);
105029
105373
  }
105374
+ function parseRestoreAccountCount(value) {
105375
+ if (value === void 0) return void 0;
105376
+ if (!/^\d+$/u.test(value)) {
105377
+ throw new UsageError(
105378
+ `--accounts must be a positive integer no greater than ${MAX_RESTORE_ACCOUNTS}.`
105379
+ );
105380
+ }
105381
+ const count = Number(value);
105382
+ if (!Number.isSafeInteger(count) || count < 1 || count > MAX_RESTORE_ACCOUNTS) {
105383
+ throw new UsageError(
105384
+ `--accounts must be a positive integer no greater than ${MAX_RESTORE_ACCOUNTS}.`
105385
+ );
105386
+ }
105387
+ return count;
105388
+ }
105030
105389
  async function protectCommand(argv, json2, io, dependencies) {
105031
105390
  requireNoArguments(argv);
105032
105391
  const env = getEnvironment(dependencies);
@@ -105156,8 +105515,8 @@ var HELP_HEADING = "vAPI Network";
105156
105515
  var HELP = `${HELP_HEADING}
105157
105516
 
105158
105517
  Usage:
105159
- vapi init [--networks <base,arc,solana>] [--json]
105160
- vapi setup [--no-cloud-backup] [--json]
105518
+ vapi init [--networks <base,arc>] [--no-link] [--json]
105519
+ vapi setup [--no-cloud-backup] [--accounts <n>] [--json]
105161
105520
  vapi accounts [--all] [--json]
105162
105521
  vapi accounts add <name> [--label <text>] [--no-link] [--json]
105163
105522
  vapi accounts import <name> [--keystore <path> | --key-file <path>] [--label <text>] [--json]
@@ -105187,7 +105546,7 @@ Usage:
105187
105546
  vapi docs read <url-or-path> [--json]
105188
105547
  vapi search [query] [--kind <kind>] [--network <caip2>] [--limit <n>] [--cursor <cursor>] [--include-unverified] [--json]
105189
105548
  vapi inspect <id> [--endpoint <name>] [--json]
105190
- 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]
105549
+ 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]
105191
105550
  vapi pay --resume <receipt-id> [--json]
105192
105551
  vapi check <url> [--method <method>] [--json]
105193
105552
  vapi balance [--account <name>] [--json]
@@ -105203,6 +105562,7 @@ Usage:
105203
105562
  vapi agent pause <name> [--json]
105204
105563
  vapi agent resume <name> [--json]
105205
105564
  vapi agent revoke <name> [--json]
105565
+ vapi dashboard [--account <name>] [--no-browser] [--json]
105206
105566
  vapi login [--account <name>] [--label <name>] [--publish] [--no-browser] [--json]
105207
105567
  vapi logout [--account <name>] [--json]
105208
105568
  vapi whoami [--account <name>] [--json]
@@ -105233,8 +105593,8 @@ Usage:
105233
105593
  vapi task status <id> [--account <name>] [--json]
105234
105594
  vapi export-key [--network <caip2>] [--account <name>] [--json]
105235
105595
  vapi backup [--account <name>] [--cloud [off]] [--json]
105236
- vapi restore [--from-owner [--owner <0x\u2026>]] [--json]
105237
- vapi import (--phrase | --key) [--account <name>] [--networks <base,arc,solana>] [--replace] [--force] [--json]
105596
+ vapi restore [--accounts <n> | --from-owner [--owner <0x\u2026>]] [--json]
105597
+ vapi import (--phrase | --key) [--account <name>] [--networks <base,arc>] [--replace] [--force] [--json]
105238
105598
  vapi passphrase [--account <name>] [--json]
105239
105599
  vapi vault protect [--json]
105240
105600
  vapi vault unprotect [--json]
@@ -105253,15 +105613,19 @@ Usage:
105253
105613
  vapi publish list [--json]
105254
105614
  vapi claim <origin> [--account <name>] [--json]
105255
105615
  vapi mcp [--account <name>] [--json]
105256
- vapi mcp install <claude|cursor|codex> [--home <dir>] [--registry <url>] [--json]
105616
+ vapi mcp install <claude|cursor|codex> [--home <dir>] [--registry <url>] [--no-link] [--json]
105257
105617
  vapi serve [--json]
105258
105618
  vapi version [--json]
105259
105619
  vapi help [--json]
105260
105620
 
105621
+ \`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.
105622
+
105261
105623
  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.
105262
105624
 
105263
105625
  \`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]\`.
105264
105626
 
105627
+ Solana listings remain searchable; inspect and pay return \`unsupported_network\`. Solana keys are not part of the device vault yet.
105628
+
105265
105629
  \`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.
105266
105630
 
105267
105631
  \`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.
@@ -105274,7 +105638,7 @@ Every command that touches a wallet takes \`--account <name>\`, falls back to \`
105274
105638
 
105275
105639
  \`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.
105276
105640
 
105277
- \`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.
105641
+ \`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.
105278
105642
 
105279
105643
  \`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.
105280
105644
 
@@ -105320,8 +105684,8 @@ var ACCOUNT_OPTION2 = "--account";
105320
105684
  var WALLET_OPTION_DEPRECATION = "--wallet is now --account; --wallet keeps working for one release.";
105321
105685
  var SOLANA_VAULT_UNAVAILABLE2 = "Solana keys are not part of the device vault yet.";
105322
105686
  var INCLUDE_UNVERIFIED_OPTION = "--include-unverified";
105323
- async function openWalletStore(dependencies) {
105324
- return await WalletStore.open(getVapiPaths().directory, {
105687
+ async function openWalletStore(dependencies, home = getVapiPaths().directory) {
105688
+ return await WalletStore.open(home, {
105325
105689
  secrets: getSecretStore(dependencies),
105326
105690
  env: getEnvironment(dependencies),
105327
105691
  ...dependencies.now === void 0 ? {} : { now: dependencies.now }
@@ -105336,8 +105700,8 @@ async function selectWallet(store, parsed, dependencies) {
105336
105700
  const address4 = await store.readAddress(resolved.name);
105337
105701
  return { store, ...resolved, ...address4 === void 0 ? {} : { address: address4 } };
105338
105702
  }
105339
- async function targetWallet(parsed, dependencies) {
105340
- return await selectWallet(await openWalletStore(dependencies), parsed, dependencies);
105703
+ async function targetWallet(parsed, dependencies, home = getVapiPaths().directory) {
105704
+ return await selectWallet(await openWalletStore(dependencies, home), parsed, dependencies);
105341
105705
  }
105342
105706
  function getSecretStore(dependencies) {
105343
105707
  return dependencies.secretStore ?? secretStore();
@@ -105516,6 +105880,10 @@ async function runCli(argv = process.argv.slice(2), io = processIo, dependencies
105516
105880
  case "agent":
105517
105881
  exitCode = await agentCommand(args.slice(1), json2, runIo, dependencies);
105518
105882
  break;
105883
+ case "dashboard":
105884
+ await dashboardCommand(args.slice(1), json2, io, dependencies);
105885
+ exitCode = 0;
105886
+ break;
105519
105887
  case "login":
105520
105888
  await loginCommand(args.slice(1), json2, io, dependencies);
105521
105889
  exitCode = 0;
@@ -105730,6 +106098,7 @@ function shouldAutoUploadAfterFailure(args) {
105730
106098
  async function initCommand(argv, json2, io, dependencies) {
105731
106099
  const parsed = parseArguments(argv, {
105732
106100
  valueOptions: /* @__PURE__ */ new Set(["--networks"]),
106101
+ booleanOptions: /* @__PURE__ */ new Set(["--no-link"]),
105733
106102
  maximumPositionals: 0
105734
106103
  });
105735
106104
  const networks = parseInitNetworks(parsed.one("--networks") ?? "base");
@@ -105777,7 +106146,14 @@ async function initCommand(argv, json2, io, dependencies) {
105777
106146
  nextSteps: buildNextSteps(account.address)
105778
106147
  };
105779
106148
  if (json2) {
105780
- io.stdout(JSON.stringify(result));
106149
+ const link3 = await offerDashboardLink({
106150
+ name: created.name,
106151
+ json: json2,
106152
+ noLink: parsed.has("--no-link"),
106153
+ io,
106154
+ dependencies
106155
+ });
106156
+ io.stdout(JSON.stringify({ ...result, ...link3 }));
105781
106157
  return;
105782
106158
  }
105783
106159
  if (configRewrites.length > 0) io.stdout(formatLegacyRegistryRewrites(configRewrites));
@@ -105798,6 +106174,13 @@ async function initCommand(argv, json2, io, dependencies) {
105798
106174
  io.stdout(formatAccounts(accounts));
105799
106175
  io.stdout("");
105800
106176
  io.stdout(result.nextSteps.join("\n"));
106177
+ await offerDashboardLink({
106178
+ name: created.name,
106179
+ json: json2,
106180
+ noLink: parsed.has("--no-link"),
106181
+ io,
106182
+ dependencies
106183
+ });
105801
106184
  }
105802
106185
  var INIT_ALREADY_DONE = "This machine already has a wallet, so vapi init created nothing.";
105803
106186
  async function reportExistingWallets(store, json2, io, dependencies) {
@@ -105833,12 +106216,11 @@ async function walletCommand(argv, json2, io, dependencies) {
105833
106216
  `Unknown wallet subcommand ${JSON.stringify(subcommand)}. ${WALLET_USAGE}`
105834
106217
  );
105835
106218
  }
105836
- await accountsCommand(
105837
- [mapped2, ...rest, ...subcommand === "create" ? ["--no-link"] : []],
105838
- json2,
105839
- io,
105840
- dependencies
105841
- );
106219
+ if (subcommand === "create") {
106220
+ await accountsAddCommand(rest, json2, io, dependencies, { link: "offer" });
106221
+ return;
106222
+ }
106223
+ await accountsCommand([mapped2, ...rest], json2, io, dependencies);
105842
106224
  }
105843
106225
  async function unlockedWallets(walletsStore, wallets, dependencies) {
105844
106226
  const secrets = getSecretStore(dependencies);
@@ -106063,7 +106445,7 @@ async function inspectCommand(argv, json2, io, dependencies) {
106063
106445
  );
106064
106446
  output3(io, json2, result, formatInspect(result));
106065
106447
  }
106066
- 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]";
106448
+ 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]";
106067
106449
  async function payCommand(argv, json2, io, dependencies) {
106068
106450
  if (argv.includes(RESUME_OPTION)) {
106069
106451
  await payResumeCommand(argv, json2, io, dependencies);
@@ -106079,11 +106461,13 @@ async function payCommand(argv, json2, io, dependencies) {
106079
106461
  "--expected-pay-to",
106080
106462
  "--max",
106081
106463
  "--max-price-usd",
106464
+ "--timeout",
106082
106465
  WALLET_OPTION5
106083
106466
  ]),
106084
106467
  maximumPositionals: 1
106085
106468
  });
106086
106469
  const target = requiredPositional(parsed.positionals[0], "<id-or-url>", PAY_USAGE);
106470
+ const timeoutSeconds = optionalBoundedInteger(parsed.one("--timeout"), "--timeout", 1, 300);
106087
106471
  const paths = getVapiPaths();
106088
106472
  const config2 = await readConfig(paths.config, io);
106089
106473
  const wallet = await targetWallet(parsed, dependencies);
@@ -106099,7 +106483,8 @@ async function payCommand(argv, json2, io, dependencies) {
106099
106483
  ...parsed.one("--content-type") ? { contentType: parsed.one("--content-type") } : {},
106100
106484
  ...parsed.one("--network") ? { network: parsed.one("--network") } : {},
106101
106485
  ...parsed.one("--expected-pay-to") ? { expectedPayTo: parsed.one("--expected-pay-to") } : {},
106102
- ...maxPriceUsd ? { maxPriceUsd } : {}
106486
+ ...maxPriceUsd ? { maxPriceUsd } : {},
106487
+ ...timeoutSeconds === void 0 ? {} : { timeoutSeconds }
106103
106488
  };
106104
106489
  const call2 = createCallPort({
106105
106490
  config: config2,
@@ -106377,8 +106762,8 @@ async function fetchNetworkStats(dependencies) {
106377
106762
  })();
106378
106763
  let timeout;
106379
106764
  try {
106380
- const timedOut = new Promise((resolve2) => {
106381
- timeout = setTimeout(() => resolve2(null), NETWORK_STATS_REQUEST_TIMEOUT_MS);
106765
+ const timedOut = new Promise((resolve3) => {
106766
+ timeout = setTimeout(() => resolve3(null), NETWORK_STATS_REQUEST_TIMEOUT_MS);
106382
106767
  });
106383
106768
  return await Promise.race([request, timedOut]);
106384
106769
  } finally {
@@ -107774,7 +108159,7 @@ function buildNextSteps(address4) {
107774
108159
  formatNextStep("Pay", "vapi pay <ref> --max 0.02"),
107775
108160
  formatNextStep(
107776
108161
  "Agent",
107777
- 'add {"command":"npx","args":["-y","vapi-network","mcp"]} to your MCP config'
108162
+ 'add {"command":"npx","args":["-y","vapi-network@latest","mcp"]} to your MCP config'
107778
108163
  )
107779
108164
  ];
107780
108165
  }
@@ -107955,6 +108340,17 @@ function optionalPositiveInteger(value, option) {
107955
108340
  if (result === 0) throw new UsageError(`${option} must be a positive integer.`);
107956
108341
  return result;
107957
108342
  }
108343
+ function optionalBoundedInteger(value, option, minimum, maximum) {
108344
+ if (value === void 0) return void 0;
108345
+ if (!/^\d+$/.test(value)) {
108346
+ throw new UsageError(`${option} must be an integer from ${minimum} to ${maximum}.`);
108347
+ }
108348
+ const parsed = Number(value);
108349
+ if (!Number.isSafeInteger(parsed) || parsed < minimum || parsed > maximum) {
108350
+ throw new UsageError(`${option} must be an integer from ${minimum} to ${maximum}.`);
108351
+ }
108352
+ return parsed;
108353
+ }
107958
108354
  function optionalUsdAmount(value, option) {
107959
108355
  if (value === void 0) return void 0;
107960
108356
  if (!/^\d+(?:\.\d{1,2})?$/.test(value)) {
@@ -108015,12 +108411,136 @@ function parseInitNetworks(value) {
108015
108411
  }
108016
108412
  for (const network of networks) {
108017
108413
  if (network !== "base" && network !== "arc" && network !== "solana") {
108018
- throw new UsageError("--networks supports base, arc and solana.");
108414
+ throw new UsageError("--networks supports base and arc; Solana vault setup is unavailable.");
108019
108415
  }
108020
108416
  }
108021
108417
  return networks;
108022
108418
  }
108023
108419
 
108420
+ // src/update-check.ts
108421
+ var CHECK_INTERVAL_MS = 24 * 60 * 60 * 1e3;
108422
+ var CHECK_TIMEOUT_MS = 1500;
108423
+ var LATEST_URL = "https://registry.npmjs.org/vapi-network/latest";
108424
+ async function runCliWithUpdateCheck(argv = process.argv.slice(2), io = {
108425
+ stdout: (message) => console.log(message),
108426
+ stderr: (message) => console.error(message)
108427
+ }, dependencies = {}, options = {}) {
108428
+ const notice = checkForUpdate({ ...options, env: options.env ?? dependencies.env, argv });
108429
+ const code = await runCli(argv, io, dependencies);
108430
+ const message = await notice;
108431
+ if (message) io.stderr(message);
108432
+ return code;
108433
+ }
108434
+ async function checkForUpdate(options = {}) {
108435
+ const env = options.env ?? process.env;
108436
+ const argv = options.argv ?? process.argv.slice(2);
108437
+ 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) {
108438
+ return void 0;
108439
+ }
108440
+ const controller = new AbortController();
108441
+ let timer;
108442
+ try {
108443
+ return await Promise.race([
108444
+ latestNotice(options, env, controller.signal),
108445
+ new Promise((resolve3) => {
108446
+ timer = setTimeout(() => {
108447
+ controller.abort();
108448
+ resolve3(void 0);
108449
+ }, CHECK_TIMEOUT_MS);
108450
+ })
108451
+ ]);
108452
+ } catch {
108453
+ return void 0;
108454
+ } finally {
108455
+ if (timer !== void 0) clearTimeout(timer);
108456
+ controller.abort();
108457
+ }
108458
+ }
108459
+ async function latestNotice(options, env, signal) {
108460
+ const paths = getVapiPaths(options.home ?? (env.VAPI_HOME?.trim() || void 0));
108461
+ const now = (options.nowMs ?? Date.now)();
108462
+ let cached2;
108463
+ try {
108464
+ const value = JSON.parse(await readFile29(paths.updateCheck, "utf8"));
108465
+ if (isRecord12(value) && typeof value.checkedAt === "number" && Number.isFinite(value.checkedAt) && typeof value.latest === "string" && parseVersion(value.latest)) {
108466
+ cached2 = { checkedAt: value.checkedAt, latest: value.latest };
108467
+ }
108468
+ } catch {
108469
+ }
108470
+ signal.throwIfAborted();
108471
+ let latest = cached2?.latest ?? CLI_VERSION;
108472
+ if (cached2 === void 0 || now - cached2.checkedAt >= CHECK_INTERVAL_MS || now < cached2.checkedAt) {
108473
+ await mkdir21(paths.directory, { recursive: true });
108474
+ signal.throwIfAborted();
108475
+ await writeFile12(paths.updateCheck, JSON.stringify({ checkedAt: now, latest }), { mode: 384 });
108476
+ signal.throwIfAborted();
108477
+ const fetchImpl = options.fetchImpl ?? createPublicFetch({
108478
+ allowPrivateNetwork: false,
108479
+ lookup: async (hostname3) => {
108480
+ let onAbort;
108481
+ const aborted2 = new Promise((_resolve, reject) => {
108482
+ onAbort = () => reject(signal.reason);
108483
+ signal.addEventListener("abort", onAbort, { once: true });
108484
+ });
108485
+ try {
108486
+ signal.throwIfAborted();
108487
+ const addresses = await Promise.race([lookup(hostname3, { all: true }), aborted2]);
108488
+ return addresses.map(({ address: address4 }) => address4);
108489
+ } finally {
108490
+ signal.removeEventListener("abort", onAbort);
108491
+ }
108492
+ }
108493
+ });
108494
+ const response = await fetchImpl(LATEST_URL, { signal, redirect: "error" });
108495
+ if (!response.ok) return void 0;
108496
+ const body = await response.json();
108497
+ signal.throwIfAborted();
108498
+ if (!isRecord12(body) || typeof body.version !== "string" || !parseVersion(body.version)) {
108499
+ return void 0;
108500
+ }
108501
+ latest = body.version;
108502
+ await writeFile12(paths.updateCheck, JSON.stringify({ checkedAt: now, latest }), { mode: 384 });
108503
+ }
108504
+ signal.throwIfAborted();
108505
+ return isNewerVersion(latest, CLI_VERSION) ? `vapi-network ${latest} is available (you have ${CLI_VERSION}). Update: npm i -g vapi-network@latest` : void 0;
108506
+ }
108507
+ function isRecord12(value) {
108508
+ return typeof value === "object" && value !== null && !Array.isArray(value);
108509
+ }
108510
+ function parseVersion(version5) {
108511
+ const match = /^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-([\da-zA-Z.-]+))?(?:\+[\da-zA-Z-]+(?:\.[\da-zA-Z-]+)*)?$/.exec(
108512
+ version5
108513
+ );
108514
+ if (!match) return void 0;
108515
+ const prerelease = match[4]?.split(".");
108516
+ if (prerelease?.some((part) => part === "" || /^\d+$/.test(part) && /^0\d/.test(part))) {
108517
+ return void 0;
108518
+ }
108519
+ return { core: match.slice(1, 4).map(BigInt), prerelease };
108520
+ }
108521
+ function isNewerVersion(latest, current) {
108522
+ const next = parseVersion(latest);
108523
+ const running = parseVersion(current);
108524
+ for (let index2 = 0; index2 < 3; index2 += 1) {
108525
+ if (next.core[index2] !== running.core[index2]) return next.core[index2] > running.core[index2];
108526
+ }
108527
+ if (running.prerelease === void 0) return false;
108528
+ if (next.prerelease === void 0) return true;
108529
+ for (let index2 = 0; index2 < Math.max(next.prerelease.length, running.prerelease.length); index2 += 1) {
108530
+ const a = next.prerelease[index2];
108531
+ const b = running.prerelease[index2];
108532
+ if (a === b) continue;
108533
+ if (a === void 0) return false;
108534
+ if (b === void 0) return true;
108535
+ const aNumeric = /^\d+$/.test(a);
108536
+ const bNumeric = /^\d+$/.test(b);
108537
+ if (aNumeric && bNumeric) return BigInt(a) > BigInt(b);
108538
+ if (aNumeric !== bNumeric) return !aNumeric;
108539
+ return a > b;
108540
+ }
108541
+ return false;
108542
+ }
108543
+
108024
108544
  // src/main-module.ts
108025
108545
  import { realpathSync as realpathSync2 } from "node:fs";
108026
108546
  import { pathToFileURL } from "node:url";
@@ -108037,7 +108557,7 @@ function isMainModule(entry, moduleUrl, realpath = realpathSync2) {
108037
108557
 
108038
108558
  // src/bin.ts
108039
108559
  if (isMainModule(process.argv[1], import.meta.url)) {
108040
- process.exitCode = await runCli();
108560
+ process.exitCode = await runCliWithUpdateCheck();
108041
108561
  }
108042
108562
  export {
108043
108563
  CUSTODY_NOTICE,