@vapi-network/core 0.7.0 → 0.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (129) hide show
  1. package/README.md +14 -1
  2. package/dist/account-add.d.ts +8 -1
  3. package/dist/account-add.d.ts.map +1 -1
  4. package/dist/account-movement-lock.d.ts +10 -0
  5. package/dist/account-movement-lock.d.ts.map +1 -0
  6. package/dist/agent-link.d.ts +1 -0
  7. package/dist/agent-link.d.ts.map +1 -1
  8. package/dist/agent-link.js +27 -11
  9. package/dist/agent-link.js.map +1 -1
  10. package/dist/agent-profile.d.ts +18 -2
  11. package/dist/agent-profile.d.ts.map +1 -1
  12. package/dist/agent-run.d.ts +12 -0
  13. package/dist/agent-run.d.ts.map +1 -0
  14. package/dist/allocation.d.ts +35 -4
  15. package/dist/allocation.d.ts.map +1 -1
  16. package/dist/api-key.js +47 -0
  17. package/dist/api-key.js.map +1 -1
  18. package/dist/atomic-file.d.ts +23 -0
  19. package/dist/atomic-file.d.ts.map +1 -0
  20. package/dist/audit.d.ts +4 -1
  21. package/dist/audit.d.ts.map +1 -1
  22. package/dist/backup.d.ts +155 -32
  23. package/dist/backup.d.ts.map +1 -1
  24. package/dist/backup.js +2600 -139
  25. package/dist/backup.js.map +3 -3
  26. package/dist/call-contracts-wire.d.ts +12 -12
  27. package/dist/ceiling.d.ts +8 -0
  28. package/dist/ceiling.d.ts.map +1 -1
  29. package/dist/cloud-backup.d.ts +8 -10
  30. package/dist/cloud-backup.d.ts.map +1 -1
  31. package/dist/cloud-backup.js +2876 -381
  32. package/dist/cloud-backup.js.map +3 -3
  33. package/dist/config.d.ts +9 -0
  34. package/dist/config.d.ts.map +1 -1
  35. package/dist/distribute.d.ts +9 -1
  36. package/dist/distribute.d.ts.map +1 -1
  37. package/dist/docs.d.ts +40 -0
  38. package/dist/docs.d.ts.map +1 -0
  39. package/dist/funding-policy.d.ts +29 -0
  40. package/dist/funding-policy.d.ts.map +1 -0
  41. package/dist/index.d.ts +12 -2
  42. package/dist/index.d.ts.map +1 -1
  43. package/dist/index.js +5832 -1213
  44. package/dist/index.js.map +3 -3
  45. package/dist/marketplace-contracts.d.ts +14 -14
  46. package/dist/member-bundle.d.ts +110 -0
  47. package/dist/member-bundle.d.ts.map +1 -0
  48. package/dist/movement-open.d.ts +10 -0
  49. package/dist/movement-open.d.ts.map +1 -0
  50. package/dist/movement.d.ts +77 -7
  51. package/dist/movement.d.ts.map +1 -1
  52. package/dist/receipts.d.ts +9 -0
  53. package/dist/receipts.d.ts.map +1 -1
  54. package/dist/router-client.d.ts +9 -1
  55. package/dist/router-client.d.ts.map +1 -1
  56. package/dist/router-client.js +2272 -609
  57. package/dist/router-client.js.map +3 -3
  58. package/dist/run-budget.d.ts +17 -0
  59. package/dist/run-budget.d.ts.map +1 -0
  60. package/dist/secret-store.d.ts +6 -0
  61. package/dist/secret-store.d.ts.map +1 -1
  62. package/dist/secrets.d.ts +2 -1
  63. package/dist/secrets.d.ts.map +1 -1
  64. package/dist/secrets.js +912 -48
  65. package/dist/secrets.js.map +3 -3
  66. package/dist/spend-policy.d.ts +41 -7
  67. package/dist/spend-policy.d.ts.map +1 -1
  68. package/dist/support-report.d.ts +1 -1
  69. package/dist/swarm-capital.d.ts +147 -0
  70. package/dist/swarm-capital.d.ts.map +1 -0
  71. package/dist/swarm.d.ts +224 -0
  72. package/dist/swarm.d.ts.map +1 -0
  73. package/dist/tasks/actions.d.ts +152 -0
  74. package/dist/tasks/actions.d.ts.map +1 -0
  75. package/dist/tasks/canonical-json.d.ts +6 -0
  76. package/dist/tasks/canonical-json.d.ts.map +1 -0
  77. package/dist/tasks/chain-error.d.ts +6 -0
  78. package/dist/tasks/chain-error.d.ts.map +1 -0
  79. package/dist/tasks/chain-port.d.ts +88 -0
  80. package/dist/tasks/chain-port.d.ts.map +1 -0
  81. package/dist/tasks/chain-verification.d.ts +36 -0
  82. package/dist/tasks/chain-verification.d.ts.map +1 -0
  83. package/dist/tasks/chain.d.ts +22 -0
  84. package/dist/tasks/chain.d.ts.map +1 -0
  85. package/dist/tasks/client.d.ts +76 -0
  86. package/dist/tasks/client.d.ts.map +1 -0
  87. package/dist/tasks/delivery-manifest.d.ts +24 -0
  88. package/dist/tasks/delivery-manifest.d.ts.map +1 -0
  89. package/dist/tasks/dispute-fee.d.ts +4 -0
  90. package/dist/tasks/dispute-fee.d.ts.map +1 -0
  91. package/dist/tasks/index.d.ts +22 -0
  92. package/dist/tasks/index.d.ts.map +1 -0
  93. package/dist/tasks/money.d.ts +17 -0
  94. package/dist/tasks/money.d.ts.map +1 -0
  95. package/dist/tasks/operation-support.d.ts +127 -0
  96. package/dist/tasks/operation-support.d.ts.map +1 -0
  97. package/dist/tasks/operations.d.ts +722 -0
  98. package/dist/tasks/operations.d.ts.map +1 -0
  99. package/dist/tasks/pending-transactions.d.ts +52 -0
  100. package/dist/tasks/pending-transactions.d.ts.map +1 -0
  101. package/dist/tasks/plan-guard.d.ts +326 -0
  102. package/dist/tasks/plan-guard.d.ts.map +1 -0
  103. package/dist/tasks/rpc.d.ts +8 -0
  104. package/dist/tasks/rpc.d.ts.map +1 -0
  105. package/dist/tasks/scope-bindings.d.ts +20 -0
  106. package/dist/tasks/scope-bindings.d.ts.map +1 -0
  107. package/dist/tasks/scope-terms.d.ts +75 -0
  108. package/dist/tasks/scope-terms.d.ts.map +1 -0
  109. package/dist/tasks/trusted-deployments.d.ts +14 -0
  110. package/dist/tasks/trusted-deployments.d.ts.map +1 -0
  111. package/dist/tasks/types.d.ts +4439 -0
  112. package/dist/tasks/types.d.ts.map +1 -0
  113. package/dist/tasks/verbs.d.ts +4 -0
  114. package/dist/tasks/verbs.d.ts.map +1 -0
  115. package/dist/tasks.js +43906 -0
  116. package/dist/tasks.js.map +6 -0
  117. package/dist/transfer-journal.d.ts +11 -0
  118. package/dist/transfer-journal.d.ts.map +1 -0
  119. package/dist/transfer.d.ts +4 -1
  120. package/dist/transfer.d.ts.map +1 -1
  121. package/dist/vault.d.ts +11 -0
  122. package/dist/vault.d.ts.map +1 -1
  123. package/dist/wallet-store.d.ts +19 -8
  124. package/dist/wallet-store.d.ts.map +1 -1
  125. package/dist/x402-pay.d.ts +7 -0
  126. package/dist/x402-pay.d.ts.map +1 -1
  127. package/dist/x402.d.ts +3 -0
  128. package/dist/x402.d.ts.map +1 -1
  129. package/package.json +5 -1
package/dist/secrets.js CHANGED
@@ -2212,7 +2212,7 @@ function weierstrass(curveDef) {
2212
2212
  function prepSig(msgHash, privateKey, opts = defaultSigOpts) {
2213
2213
  if (["recovered", "canonical"].some((k) => k in opts))
2214
2214
  throw new Error("sign() legacy options not supported");
2215
- const { hash: hash2, randomBytes: randomBytes4 } = CURVE;
2215
+ const { hash: hash2, randomBytes: randomBytes5 } = CURVE;
2216
2216
  let { lowS, prehash, extraEntropy: ent } = opts;
2217
2217
  if (lowS == null)
2218
2218
  lowS = true;
@@ -2224,7 +2224,7 @@ function weierstrass(curveDef) {
2224
2224
  const d = normPrivateKeyToScalar(privateKey);
2225
2225
  const seedArgs = [int2octets(d), int2octets(h1int)];
2226
2226
  if (ent != null && ent !== false) {
2227
- const e2 = ent === true ? randomBytes4(Fp.BYTES) : ent;
2227
+ const e2 = ent === true ? randomBytes5(Fp.BYTES) : ent;
2228
2228
  seedArgs.push(ensureBytes("extraEntropy", e2));
2229
2229
  }
2230
2230
  const seed = concatBytes2(...seedArgs);
@@ -2793,16 +2793,16 @@ function hexToBytes3(hex_, opts = {}) {
2793
2793
  assertSize(hex3, { size: opts.size });
2794
2794
  hex3 = pad(hex3, { dir: "right", size: opts.size });
2795
2795
  }
2796
- let hexString = hex3.slice(2);
2797
- if (hexString.length % 2)
2798
- hexString = `0${hexString}`;
2799
- const length = hexString.length / 2;
2796
+ let hexString2 = hex3.slice(2);
2797
+ if (hexString2.length % 2)
2798
+ hexString2 = `0${hexString2}`;
2799
+ const length = hexString2.length / 2;
2800
2800
  const bytes = new Uint8Array(length);
2801
2801
  for (let index = 0, j = 0; index < length; index++) {
2802
- const nibbleLeft = charCodeToBase16(hexString.charCodeAt(j++));
2803
- const nibbleRight = charCodeToBase16(hexString.charCodeAt(j++));
2802
+ const nibbleLeft = charCodeToBase16(hexString2.charCodeAt(j++));
2803
+ const nibbleRight = charCodeToBase16(hexString2.charCodeAt(j++));
2804
2804
  if (nibbleLeft === void 0 || nibbleRight === void 0) {
2805
- throw new BaseError(`Invalid byte sequence ("${hexString[j - 2]}${hexString[j - 1]}" in "${hexString}").`);
2805
+ throw new BaseError(`Invalid byte sequence ("${hexString2[j - 2]}${hexString2[j - 1]}" in "${hexString2}").`);
2806
2806
  }
2807
2807
  bytes[index] = nibbleLeft * 16 + nibbleRight;
2808
2808
  }
@@ -4273,9 +4273,9 @@ var init_stringify = __esm({
4273
4273
  });
4274
4274
 
4275
4275
  // src/keystore.ts
4276
- import { createCipheriv, createDecipheriv, randomBytes as randomBytes2, scrypt } from "node:crypto";
4277
- import { mkdir as mkdir2, readFile as readFile2, rename as rename2, stat as stat2, writeFile as writeFile2 } from "node:fs/promises";
4278
- import { dirname as dirname2 } from "node:path";
4276
+ import { createCipheriv, createDecipheriv, randomBytes as randomBytes3, scrypt } from "node:crypto";
4277
+ import { mkdir as mkdir3, readFile as readFile3, rename as rename3, stat as stat3, writeFile as writeFile2 } from "node:fs/promises";
4278
+ import { dirname as dirname3 } from "node:path";
4279
4279
 
4280
4280
  // ../../node_modules/.pnpm/@solana+errors@5.5.1_typescript@6.0.3/node_modules/@solana/errors/dist/index.node.mjs
4281
4281
  var SOLANA_ERROR__BLOCK_HEIGHT_EXCEEDED = 1;
@@ -46542,13 +46542,232 @@ function date4(params) {
46542
46542
 
46543
46543
  // src/config.ts
46544
46544
  import { constants } from "node:fs";
46545
- import { copyFile, mkdir, readFile, rename, stat, writeFile } from "node:fs/promises";
46545
+ import { copyFile, mkdir as mkdir2, readFile as readFile2, rename as rename2, stat as stat2, writeFile } from "node:fs/promises";
46546
46546
  import { homedir } from "node:os";
46547
- import { dirname, join as join2 } from "node:path";
46547
+ import { dirname as dirname2, join as join3 } from "node:path";
46548
46548
 
46549
46549
  // ../../node_modules/.pnpm/viem@2.56.1_typescript@6.0.3_zod@4.5.4/node_modules/viem/_esm/index.js
46550
46550
  init_getAddress();
46551
46551
 
46552
+ // src/atomic-file.ts
46553
+ import { randomBytes as randomBytes2 } from "node:crypto";
46554
+ import { link, mkdir, open as open2, readdir, readFile, rename, stat, unlink } from "node:fs/promises";
46555
+ import { basename, dirname, join as join2 } from "node:path";
46556
+ var DEFAULT_LOCK_TIMEOUT_MS = 2e3;
46557
+ var LOCK_RETRY_MS = 20;
46558
+ var LOCK_STALE_AFTER_MS = 12e4;
46559
+ var LOCK_HEARTBEAT_MS = 3e4;
46560
+ var atomicFileTestHooks;
46561
+ var FileLockedError = class extends Error {
46562
+ constructor(message = "Timed out waiting for the file lock.") {
46563
+ super(message);
46564
+ this.name = "FileLockedError";
46565
+ }
46566
+ };
46567
+ async function withFileLock(lockPath, fn, options = {}) {
46568
+ await mkdir(dirname(lockPath), { recursive: true, mode: 448 });
46569
+ const deadline = Date.now() + (options.timeoutMs ?? DEFAULT_LOCK_TIMEOUT_MS);
46570
+ const ownerRecord = {
46571
+ pid: process.pid,
46572
+ token: randomBytes2(16).toString("hex")
46573
+ };
46574
+ const owner = JSON.stringify(ownerRecord);
46575
+ const releasedOwner = JSON.stringify({ ...ownerRecord, released: true });
46576
+ let handle;
46577
+ while (handle === void 0) {
46578
+ await atomicFileTestHooks?.beforeLockAttempt?.(lockPath);
46579
+ try {
46580
+ const candidate = await open2(lockPath, "wx", 384);
46581
+ try {
46582
+ await candidate.writeFile(owner, "utf8");
46583
+ await candidate.sync();
46584
+ await atomicFileTestHooks?.afterLockCreate?.(lockPath);
46585
+ if (await lockTakeoverInProgress(lockPath)) {
46586
+ await candidate.close();
46587
+ await removeOwnedLock(lockPath, [owner]);
46588
+ await removeAbandonedLockTombs(lockPath);
46589
+ if (Date.now() >= deadline) {
46590
+ throw new FileLockedError(options.lockedMessage);
46591
+ }
46592
+ await new Promise((resolve) => setTimeout(resolve, LOCK_RETRY_MS));
46593
+ continue;
46594
+ }
46595
+ handle = candidate;
46596
+ } catch (error61) {
46597
+ await candidate.close().catch(() => void 0);
46598
+ await removeOwnedLock(lockPath, [owner]).catch(() => void 0);
46599
+ throw error61;
46600
+ }
46601
+ } catch (error61) {
46602
+ if (!hasCode(error61, "EEXIST")) throw error61;
46603
+ await removeStaleLock(lockPath);
46604
+ if (Date.now() >= deadline) {
46605
+ throw new FileLockedError(options.lockedMessage);
46606
+ }
46607
+ await new Promise((resolve) => setTimeout(resolve, LOCK_RETRY_MS));
46608
+ }
46609
+ }
46610
+ const ownedHandle = handle;
46611
+ const heartbeat = setInterval(() => {
46612
+ const time3 = /* @__PURE__ */ new Date();
46613
+ void ownedHandle.utimes(time3, time3).catch(() => void 0);
46614
+ }, LOCK_HEARTBEAT_MS);
46615
+ heartbeat.unref();
46616
+ try {
46617
+ return await fn();
46618
+ } finally {
46619
+ clearInterval(heartbeat);
46620
+ try {
46621
+ await markLockReleased(ownedHandle, releasedOwner);
46622
+ } finally {
46623
+ try {
46624
+ await ownedHandle.close();
46625
+ } finally {
46626
+ await removeOwnedLock(lockPath, [owner, releasedOwner]);
46627
+ }
46628
+ }
46629
+ }
46630
+ }
46631
+ async function removeStaleLock(path) {
46632
+ try {
46633
+ const owner = await readFile(path, "utf8");
46634
+ if (lockOwnerReleased(owner)) {
46635
+ await removeOwnedLock(path, [owner]);
46636
+ return;
46637
+ }
46638
+ const metadata = await stat(path);
46639
+ if (Date.now() - metadata.mtimeMs <= LOCK_STALE_AFTER_MS) return;
46640
+ const pid = lockOwnerPid(owner);
46641
+ if (pid !== void 0 && processIsAlive(pid)) return;
46642
+ await atomicFileTestHooks?.beforeStaleLockBreak?.(path);
46643
+ await removeOwnedLock(path, [owner]);
46644
+ } catch (error61) {
46645
+ if (!hasCode(error61, "ENOENT")) throw error61;
46646
+ }
46647
+ }
46648
+ async function removeOwnedLock(path, owners) {
46649
+ const tombPath = `${path}.stale.${randomBytes2(16).toString("hex")}`;
46650
+ try {
46651
+ await rename(path, tombPath);
46652
+ } catch (error61) {
46653
+ if (hasCode(error61, "ENOENT")) {
46654
+ await removeOwnedTombs(path, owners);
46655
+ const currentOwner = await readFile(path, "utf8").catch(() => void 0);
46656
+ if (currentOwner !== void 0 && owners.includes(currentOwner)) {
46657
+ await removeOwnedLock(path, owners);
46658
+ }
46659
+ return;
46660
+ }
46661
+ throw error61;
46662
+ }
46663
+ let pendingError;
46664
+ try {
46665
+ const renamedOwner = await readFile(tombPath, "utf8");
46666
+ if (!owners.includes(renamedOwner) && !lockOwnerReleased(renamedOwner)) {
46667
+ await atomicFileTestHooks?.afterMismatchedLockRename?.(path);
46668
+ const currentOwner = await readFile(tombPath, "utf8");
46669
+ if (!lockOwnerReleased(currentOwner)) await restoreRenamedLock(path, tombPath);
46670
+ await atomicFileTestHooks?.afterMismatchedLockRestore?.(path);
46671
+ }
46672
+ } catch (error61) {
46673
+ pendingError = error61;
46674
+ }
46675
+ try {
46676
+ await unlink(tombPath);
46677
+ } catch (error61) {
46678
+ if (!hasCode(error61, "ENOENT") && pendingError === void 0) {
46679
+ pendingError = error61;
46680
+ }
46681
+ }
46682
+ if (pendingError !== void 0) throw pendingError;
46683
+ }
46684
+ async function lockTakeoverInProgress(path) {
46685
+ const prefix = `${basename(path)}.stale.`;
46686
+ return (await readdir(dirname(path))).some((entry) => entry.startsWith(prefix));
46687
+ }
46688
+ async function removeAbandonedLockTombs(path) {
46689
+ const directory = dirname(path);
46690
+ const prefix = `${basename(path)}.stale.`;
46691
+ for (const entry of await readdir(directory)) {
46692
+ if (!entry.startsWith(prefix)) continue;
46693
+ const tombPath = join2(directory, entry);
46694
+ const [metadata, owner] = await Promise.all([
46695
+ stat(tombPath).catch(() => void 0),
46696
+ readFile(tombPath, "utf8").catch(() => void 0)
46697
+ ]);
46698
+ if (metadata === void 0 || owner === void 0) continue;
46699
+ const pid = lockOwnerPid(owner);
46700
+ const abandoned = lockOwnerReleased(owner) || Date.now() - metadata.mtimeMs > LOCK_STALE_AFTER_MS && (pid === void 0 || !processIsAlive(pid));
46701
+ if (!abandoned) continue;
46702
+ await unlink(tombPath).catch((error61) => {
46703
+ if (!hasCode(error61, "ENOENT")) throw error61;
46704
+ });
46705
+ }
46706
+ }
46707
+ async function removeOwnedTombs(path, owners) {
46708
+ const directory = dirname(path);
46709
+ const prefix = `${basename(path)}.stale.`;
46710
+ for (const entry of await readdir(directory)) {
46711
+ if (!entry.startsWith(prefix)) continue;
46712
+ const tombPath = join2(directory, entry);
46713
+ const owner = await readFile(tombPath, "utf8").catch(() => void 0);
46714
+ if (owner === void 0 || !owners.includes(owner)) continue;
46715
+ await unlink(tombPath).catch((error61) => {
46716
+ if (!hasCode(error61, "ENOENT")) throw error61;
46717
+ });
46718
+ }
46719
+ }
46720
+ async function restoreRenamedLock(path, tombPath) {
46721
+ while (true) {
46722
+ try {
46723
+ await link(tombPath, path);
46724
+ return;
46725
+ } catch (error61) {
46726
+ if (hasCode(error61, "ENOENT")) return;
46727
+ if (!hasCode(error61, "EEXIST")) throw error61;
46728
+ await new Promise((resolve) => setTimeout(resolve, LOCK_RETRY_MS));
46729
+ }
46730
+ }
46731
+ }
46732
+ async function markLockReleased(handle, owner) {
46733
+ const contents = Buffer.from(owner, "utf8");
46734
+ await handle.write(contents, 0, contents.length, 0);
46735
+ await handle.truncate(contents.length);
46736
+ await handle.sync();
46737
+ }
46738
+ function lockOwnerPid(owner) {
46739
+ try {
46740
+ const value = JSON.parse(owner);
46741
+ if (typeof value !== "object" || value === null) return void 0;
46742
+ const pid = Reflect.get(value, "pid");
46743
+ return typeof pid === "number" && Number.isSafeInteger(pid) && pid > 0 ? pid : void 0;
46744
+ } catch {
46745
+ return void 0;
46746
+ }
46747
+ }
46748
+ function lockOwnerReleased(owner) {
46749
+ try {
46750
+ const value = JSON.parse(owner);
46751
+ return typeof value === "object" && value !== null && Reflect.get(value, "released") === true;
46752
+ } catch {
46753
+ return false;
46754
+ }
46755
+ }
46756
+ function processIsAlive(pid) {
46757
+ if (atomicFileTestHooks?.isProcessAlive !== void 0) {
46758
+ return atomicFileTestHooks.isProcessAlive(pid);
46759
+ }
46760
+ try {
46761
+ process.kill(pid, 0);
46762
+ return true;
46763
+ } catch (error61) {
46764
+ return hasCode(error61, "EPERM");
46765
+ }
46766
+ }
46767
+ function hasCode(error61, code) {
46768
+ return error61 instanceof Error && "code" in error61 && error61.code === code;
46769
+ }
46770
+
46552
46771
  // src/x402-networks.ts
46553
46772
  var BASE_MAINNET_CAIP2 = "eip155:8453";
46554
46773
  var ARC_MAINNET_CAIP2 = "eip155:5042";
@@ -46592,6 +46811,205 @@ var BROWSER_ENABLED_X402_NETWORK_CONFIG = Object.freeze({
46592
46811
  [ARC_TESTNET_CAIP2]: browserNetwork(arcTestnetUsdc)
46593
46812
  });
46594
46813
 
46814
+ // src/net-guard.ts
46815
+ import { lookup as dnsLookup } from "node:dns/promises";
46816
+ import { request as httpRequest } from "node:http";
46817
+ import { request as httpsRequest } from "node:https";
46818
+ import { isIP } from "node:net";
46819
+ import { Readable } from "node:stream";
46820
+ var defaultLookup = async (hostname3) => {
46821
+ const addresses = await dnsLookup(hostname3, { all: true });
46822
+ return addresses.map(({ address }) => address);
46823
+ };
46824
+ async function assertPublicUrl(url2, options) {
46825
+ if (url2.username || url2.password) {
46826
+ throw guardError(url2);
46827
+ }
46828
+ if (url2.protocol !== "http:" && url2.protocol !== "https:") {
46829
+ throw guardError(url2);
46830
+ }
46831
+ if (options.allowPrivateNetwork) {
46832
+ return;
46833
+ }
46834
+ const hostname3 = normalizeHostname(url2.hostname);
46835
+ const lowercaseHostname = hostname3.toLowerCase();
46836
+ if (!lowercaseHostname || lowercaseHostname === "localhost" || lowercaseHostname.endsWith(".localhost") || lowercaseHostname.endsWith(".local") || lowercaseHostname.endsWith(".internal")) {
46837
+ throw guardError(url2);
46838
+ }
46839
+ if (isIP(hostname3)) {
46840
+ if (isNonPublicAddress(hostname3)) {
46841
+ throw guardError(url2);
46842
+ }
46843
+ return;
46844
+ }
46845
+ let addresses;
46846
+ try {
46847
+ addresses = await withTimeout(
46848
+ (options.lookup ?? defaultLookup)(hostname3),
46849
+ options.timeoutMs ?? 5e3
46850
+ );
46851
+ } catch {
46852
+ throw guardError(url2);
46853
+ }
46854
+ if (addresses.length === 0 || addresses.some(isNonPublicAddress)) {
46855
+ throw guardError(url2);
46856
+ }
46857
+ }
46858
+ function createPublicFetch(options) {
46859
+ const lookupFn = options.lookup ?? defaultLookup;
46860
+ return (async (input2, init) => {
46861
+ const url2 = new URL(input2 instanceof Request ? input2.url : input2);
46862
+ await assertPublicUrl(url2, {
46863
+ allowPrivateNetwork: options.allowPrivateNetwork,
46864
+ lookup: lookupFn,
46865
+ timeoutMs: 5e3
46866
+ });
46867
+ const normalized = new Request(input2, init);
46868
+ const bytes = normalized.body ? Buffer.from(await normalized.arrayBuffer()) : null;
46869
+ return await new Promise((resolve, reject) => {
46870
+ const requestOptions = {
46871
+ method: normalized.method,
46872
+ headers: Object.fromEntries(normalized.headers),
46873
+ signal: normalized.signal,
46874
+ ...options.allowPrivateNetwork ? {} : { lookup: pinnedLookup(lookupFn) }
46875
+ };
46876
+ const onResponse = (incoming) => {
46877
+ try {
46878
+ const headers = new Headers();
46879
+ for (const [name, value] of Object.entries(incoming.headers)) {
46880
+ if (Array.isArray(value)) {
46881
+ for (const item of value) headers.append(name, item);
46882
+ } else if (value !== void 0) {
46883
+ headers.set(name, value);
46884
+ }
46885
+ }
46886
+ const status = incoming.statusCode ?? 500;
46887
+ const bodyForbidden = normalized.method === "HEAD" || [204, 205, 304].includes(status);
46888
+ if (bodyForbidden) incoming.resume();
46889
+ const response = new Response(
46890
+ bodyForbidden ? null : Readable.toWeb(incoming),
46891
+ { status, statusText: incoming.statusMessage, headers }
46892
+ );
46893
+ Object.defineProperty(response, "url", { value: url2.toString() });
46894
+ resolve(response);
46895
+ } catch (error61) {
46896
+ incoming.destroy();
46897
+ reject(error61);
46898
+ }
46899
+ };
46900
+ const request = url2.protocol === "https:" ? httpsRequest(url2, requestOptions, onResponse) : httpRequest(url2, requestOptions, onResponse);
46901
+ request.on("error", reject);
46902
+ if (bytes) request.write(bytes);
46903
+ request.end();
46904
+ });
46905
+ });
46906
+ }
46907
+ function pinnedLookup(lookup) {
46908
+ return (hostname3, dnsOptions, callback) => {
46909
+ void lookup(normalizeHostname(hostname3)).then((addresses) => {
46910
+ if (addresses.length === 0 || addresses.some(isNonPublicAddress)) {
46911
+ callback(guardError(new URL(`https://${hostname3}`)), "");
46912
+ return;
46913
+ }
46914
+ const address = addresses[0];
46915
+ const family = isIP(address);
46916
+ callback(
46917
+ null,
46918
+ dnsOptions.all ? [{ address, family }] : address,
46919
+ dnsOptions.all ? void 0 : family
46920
+ );
46921
+ }).catch(
46922
+ (error61) => callback(error61 instanceof Error ? error61 : new Error("DNS lookup failed."), "")
46923
+ );
46924
+ };
46925
+ }
46926
+ async function withTimeout(operation, timeoutMs) {
46927
+ let timeout;
46928
+ try {
46929
+ return await Promise.race([
46930
+ operation,
46931
+ new Promise((_resolve, reject) => {
46932
+ timeout = setTimeout(() => reject(new Error("DNS lookup timed out.")), timeoutMs);
46933
+ })
46934
+ ]);
46935
+ } finally {
46936
+ if (timeout) clearTimeout(timeout);
46937
+ }
46938
+ }
46939
+ function normalizeHostname(hostname3) {
46940
+ const unbracketed = hostname3.startsWith("[") && hostname3.endsWith("]") ? hostname3.slice(1, -1) : hostname3;
46941
+ return unbracketed.endsWith(".") ? unbracketed.slice(0, -1) : unbracketed;
46942
+ }
46943
+ function isNonPublicAddress(address) {
46944
+ const normalized = normalizeHostname(address);
46945
+ const version3 = isIP(normalized);
46946
+ if (version3 === 4) {
46947
+ return isNonPublicIpv4(parseIpv4(normalized));
46948
+ }
46949
+ if (version3 === 6) {
46950
+ return isNonPublicIpv6(parseIpv6(normalized));
46951
+ }
46952
+ return true;
46953
+ }
46954
+ function parseIpv4(address) {
46955
+ const octets = address.split(".").map(Number);
46956
+ return [octets[0], octets[1], octets[2], octets[3]];
46957
+ }
46958
+ function isNonPublicIpv4([first, second, third]) {
46959
+ return first === 0 || first === 10 || first === 100 && second >= 64 && second <= 127 || first === 127 || first === 169 && second === 254 || first === 172 && second >= 16 && second <= 31 || first === 192 && second === 0 && (third === 0 || third === 2) || first === 192 && second === 168 || first === 198 && second >= 18 && second <= 19 || first === 198 && second === 51 && third === 100 || first === 203 && second === 0 && third === 113 || first >= 224;
46960
+ }
46961
+ function parseIpv6(address) {
46962
+ let normalized = address.toLowerCase();
46963
+ const lastColon = normalized.lastIndexOf(":");
46964
+ const dottedTail = normalized.slice(lastColon + 1);
46965
+ if (dottedTail.includes(".")) {
46966
+ const [first, second, third, fourth] = parseIpv4(dottedTail);
46967
+ normalized = `${normalized.slice(0, lastColon + 1)}${(first << 8 | second).toString(16)}:${(third << 8 | fourth).toString(16)}`;
46968
+ }
46969
+ const halves = normalized.split("::");
46970
+ const left = halves[0] ? halves[0].split(":").map(parseHex) : [];
46971
+ const right = halves[1] ? halves[1].split(":").map(parseHex) : [];
46972
+ const omittedCount = 8 - left.length - right.length;
46973
+ return halves.length === 2 ? [...left, ...Array.from({ length: omittedCount }, () => 0), ...right] : left;
46974
+ }
46975
+ function parseHex(value) {
46976
+ return Number.parseInt(value, 16);
46977
+ }
46978
+ function isNonPublicIpv6(hextets) {
46979
+ if (hextets.slice(0, 5).every((hextet) => hextet === 0) && hextets[5] === 65535) {
46980
+ const embeddedIpv4 = [
46981
+ hextets[6] >> 8,
46982
+ hextets[6] & 255,
46983
+ hextets[7] >> 8,
46984
+ hextets[7] & 255
46985
+ ];
46986
+ return isNonPublicIpv4(embeddedIpv4);
46987
+ }
46988
+ if (hextets.slice(0, 6).every((hextet) => hextet === 0)) {
46989
+ const compatibleIpv4 = [
46990
+ hextets[6] >> 8,
46991
+ hextets[6] & 255,
46992
+ hextets[7] >> 8,
46993
+ hextets[7] & 255
46994
+ ];
46995
+ if (isNonPublicIpv4(compatibleIpv4)) return true;
46996
+ }
46997
+ const isUnspecified = hextets.every((hextet) => hextet === 0);
46998
+ const isLoopback = hextets.slice(0, 7).every((hextet) => hextet === 0) && hextets[7] === 1;
46999
+ const first = hextets[0];
47000
+ const isUniqueLocal = first >= 64512 && first <= 65023;
47001
+ const isLinkLocal = first >= 65152 && first <= 65215;
47002
+ const isSiteLocal = first >= 65216 && first <= 65279;
47003
+ const isMulticast = first >= 65280;
47004
+ const isDocumentation = first === 8193 && hextets[1] === 3512;
47005
+ return isUnspecified || isLoopback || isUniqueLocal || isLinkLocal || isSiteLocal || isMulticast || isDocumentation;
47006
+ }
47007
+ function guardError(url2) {
47008
+ return new Error(
47009
+ `URL hostname ${JSON.stringify(url2.hostname)} is not allowed; private or internal destinations require allowPrivateNetwork true in the vAPI config.`
47010
+ );
47011
+ }
47012
+
46595
47013
  // src/networks.ts
46596
47014
  var NETWORKS = {
46597
47015
  [BASE_MAINNET_CAIP2]: {
@@ -46667,6 +47085,12 @@ function isSupportedPaymentNetwork(network) {
46667
47085
  var DEFAULT_REGISTRY_URL = "https://api.vapinetwork.ai";
46668
47086
  var DEFAULT_DISCOVERY_URL = `${DEFAULT_REGISTRY_URL}/api/call/services`;
46669
47087
  var DEFAULT_MARKETPLACE_DISCOVERY_URL = `${DEFAULT_REGISTRY_URL}/api/call/discovery`;
47088
+ var DEFAULT_SPEND_CAPS = {
47089
+ perCallAtomic: "100000",
47090
+ perDayAtomic: "1000000"
47091
+ };
47092
+ var DEFAULT_MAX_PER_TASK_USD = 100;
47093
+ var DEFAULT_AUTO_RELEASE_BELOW_USD = 25;
46670
47094
  var atomicString = external_exports.string().regex(/^\d+$/, "Expected non-negative atomic units.");
46671
47095
  var spendCapsSchema = external_exports.object({
46672
47096
  perCallAtomic: atomicString,
@@ -46682,6 +47106,14 @@ var configSchema = external_exports.object({
46682
47106
  })
46683
47107
  ).optional(),
46684
47108
  allowPrivateNetwork: external_exports.boolean().default(false).optional(),
47109
+ tasksEscrowDurationOverrides: external_exports.record(
47110
+ external_exports.string().regex(/^\d+$/),
47111
+ external_exports.object({
47112
+ workDurationSeconds: external_exports.number().int().positive().max(Number.MAX_SAFE_INTEGER).optional(),
47113
+ reviewWindowSeconds: external_exports.number().int().positive().max(Number.MAX_SAFE_INTEGER).optional()
47114
+ }).strict()
47115
+ ).optional(),
47116
+ tasksEscrowFactoryOverrides: external_exports.record(external_exports.string().regex(/^\d+$/), external_exports.string()).optional(),
46685
47117
  networks: external_exports.record(
46686
47118
  external_exports.string().refine((network) => isSupportedPaymentNetwork(network), {
46687
47119
  message: "Expected a supported eip155:<chainId> or Solana network identifier."
@@ -46700,6 +47132,17 @@ var configSchema = external_exports.object({
46700
47132
  spendCaps: spendCapsSchema,
46701
47133
  device: external_exports.string().regex(/^[a-z0-9][a-z0-9-]{0,31}$/).optional()
46702
47134
  }).superRefine((config2, context) => {
47135
+ for (const [chainId, factory] of Object.entries(config2.tasksEscrowFactoryOverrides ?? {})) {
47136
+ try {
47137
+ getAddress(factory);
47138
+ } catch {
47139
+ context.addIssue({
47140
+ code: "custom",
47141
+ path: ["tasksEscrowFactoryOverrides", chainId],
47142
+ message: "Expected a valid EVM escrow factory address."
47143
+ });
47144
+ }
47145
+ }
46703
47146
  for (const [network, configured] of Object.entries(config2.networks)) {
46704
47147
  if (isSolanaNetwork(network)) {
46705
47148
  if (configured.usdc !== NETWORKS[SOLANA_MAINNET_CAIP2].usdc) {
@@ -46729,22 +47172,22 @@ var configSchema = external_exports.object({
46729
47172
  }
46730
47173
  }
46731
47174
  });
46732
- function getVapiPaths(directory = process.env.VAPI_HOME?.trim() || join2(homedir(), ".vapi")) {
47175
+ function getVapiPaths(directory = process.env.VAPI_HOME?.trim() || join3(homedir(), ".vapi")) {
46733
47176
  return {
46734
47177
  directory,
46735
- agentsDir: join2(directory, "agents"),
46736
- config: join2(directory, "config.json"),
46737
- keystore: join2(directory, "keystore.json"),
46738
- receipts: join2(directory, "receipts.jsonl"),
46739
- searches: join2(directory, "searches.jsonl"),
46740
- ledger: join2(directory, "spend-ledger.json")
47178
+ agentsDir: join3(directory, "agents"),
47179
+ config: join3(directory, "config.json"),
47180
+ keystore: join3(directory, "keystore.json"),
47181
+ receipts: join3(directory, "receipts.jsonl"),
47182
+ searches: join3(directory, "searches.jsonl"),
47183
+ ledger: join3(directory, "spend-ledger.json")
46741
47184
  };
46742
47185
  }
46743
47186
  async function migrateLegacyVapiHome(options = {}) {
46744
47187
  const target = getVapiPaths(options.targetDirectory);
46745
- const legacyDirectory = options.legacyDirectory ?? join2(homedir(), ".vapi", "agent-cash");
47188
+ const legacyDirectory = options.legacyDirectory ?? join3(homedir(), ".vapi", "agent-cash");
46746
47189
  if (legacyDirectory === target.directory || !await pathExists(legacyDirectory)) return [];
46747
- await mkdir(target.directory, { recursive: true, mode: 448 });
47190
+ await mkdir2(target.directory, { recursive: true, mode: 448 });
46748
47191
  const copied = [];
46749
47192
  for (const filename of [
46750
47193
  "config.json",
@@ -46753,10 +47196,17 @@ async function migrateLegacyVapiHome(options = {}) {
46753
47196
  "searches.jsonl",
46754
47197
  "spend-ledger.json"
46755
47198
  ]) {
46756
- const source = join2(legacyDirectory, filename);
46757
- const destination = join2(target.directory, filename);
47199
+ const source = join3(legacyDirectory, filename);
47200
+ const destination = join3(target.directory, filename);
46758
47201
  try {
46759
- await copyFile(source, destination, constants.COPYFILE_EXCL);
47202
+ const copy = async () => await copyFile(source, destination, constants.COPYFILE_EXCL);
47203
+ if (filename === "receipts.jsonl") {
47204
+ await withFileLock(`${destination}.lock`, copy, {
47205
+ lockedMessage: "The receipt journal is busy. Wait for the other vapi command to finish, then retry."
47206
+ });
47207
+ } else {
47208
+ await copy();
47209
+ }
46760
47210
  copied.push(destination);
46761
47211
  } catch (error61) {
46762
47212
  if (isMissingFile(error61) || isAlreadyExists(error61)) continue;
@@ -46772,7 +47222,7 @@ async function migrateLegacyVapiHome(options = {}) {
46772
47222
  }
46773
47223
  async function pathExists(path) {
46774
47224
  try {
46775
- await stat(path);
47225
+ await stat2(path);
46776
47226
  return true;
46777
47227
  } catch (error61) {
46778
47228
  if (isMissingFile(error61)) return false;
@@ -46943,7 +47393,7 @@ function encryptWithKey(key, plaintext) {
46943
47393
  if (key.byteLength !== KEY_LENGTH) {
46944
47394
  throw new Error(`Expected a ${KEY_LENGTH}-byte AES-256-GCM key.`);
46945
47395
  }
46946
- const nonce = randomBytes2(12);
47396
+ const nonce = randomBytes3(12);
46947
47397
  const cipher = createCipheriv("aes-256-gcm", key, nonce, {
46948
47398
  authTagLength: AUTH_TAG_LENGTH
46949
47399
  });
@@ -47027,7 +47477,7 @@ async function sealPlaintext(plaintext, passphrase) {
47027
47477
  if (passphrase.length === 0) {
47028
47478
  throw new KeystoreError("Keystore passphrase cannot be empty.");
47029
47479
  }
47030
- const salt = randomBytes2(32);
47480
+ const salt = randomBytes3(32);
47031
47481
  const key = await deriveScryptKey(passphrase, salt);
47032
47482
  try {
47033
47483
  const sealed = encryptWithKey(key, Buffer.from(plaintext, "utf8"));
@@ -47145,7 +47595,7 @@ async function refuseExistingKeystore(path) {
47145
47595
  await migrateLegacyVapiHome({ targetDirectory: getVapiPaths().directory });
47146
47596
  }
47147
47597
  try {
47148
- await stat2(path);
47598
+ await stat3(path);
47149
47599
  throw new KeystoreError(
47150
47600
  `Keystore already exists at ${path}. Refusing to replace the local payment key.`
47151
47601
  );
@@ -47167,7 +47617,7 @@ function validatePrivateKey(value) {
47167
47617
  async function readStoredKeystore(path) {
47168
47618
  let raw;
47169
47619
  try {
47170
- raw = await readFile2(path, "utf8");
47620
+ raw = await readFile3(path, "utf8");
47171
47621
  } catch (error61) {
47172
47622
  if (isMissingFile(error61)) {
47173
47623
  throw new KeystoreError(`No vAPI keystore found at ${path}. Run vapi init.`);
@@ -47240,8 +47690,8 @@ async function createSolanaSigner(seed) {
47240
47690
  }
47241
47691
  }
47242
47692
  async function writeKeystore(path, keystore, exclusive) {
47243
- await mkdir2(dirname2(path), { recursive: true, mode: 448 });
47244
- const temporaryPath = `${path}.${process.pid}.${randomBytes2(6).toString("hex")}.tmp`;
47693
+ await mkdir3(dirname3(path), { recursive: true, mode: 448 });
47694
+ const temporaryPath = `${path}.${process.pid}.${randomBytes3(6).toString("hex")}.tmp`;
47245
47695
  await writeFile2(temporaryPath, `${JSON.stringify(keystore, null, 2)}
47246
47696
  `, {
47247
47697
  encoding: "utf8",
@@ -47250,7 +47700,7 @@ async function writeKeystore(path, keystore, exclusive) {
47250
47700
  });
47251
47701
  if (exclusive) {
47252
47702
  try {
47253
- await stat2(path);
47703
+ await stat3(path);
47254
47704
  throw new KeystoreError(
47255
47705
  `Keystore already exists at ${path}. Refusing to replace the local payment key.`
47256
47706
  );
@@ -47258,13 +47708,13 @@ async function writeKeystore(path, keystore, exclusive) {
47258
47708
  if (!isMissingFile(error61)) throw error61;
47259
47709
  }
47260
47710
  }
47261
- await rename2(temporaryPath, path);
47711
+ await rename3(temporaryPath, path);
47262
47712
  }
47263
47713
 
47264
47714
  // src/vault.ts
47265
- import { randomBytes as randomBytes3 } from "node:crypto";
47266
- import { mkdir as mkdir3, open as open2, readFile as readFile3, rename as rename3, rm, stat as stat3, unlink, writeFile as writeFile3 } from "node:fs/promises";
47267
- import { dirname as dirname3 } from "node:path";
47715
+ import { randomBytes as randomBytes4 } from "node:crypto";
47716
+ import { mkdir as mkdir4, open as open3, readFile as readFile4, rename as rename4, rm, stat as stat4, unlink as unlink2, writeFile as writeFile3 } from "node:fs/promises";
47717
+ import { dirname as dirname4 } from "node:path";
47268
47718
 
47269
47719
  // src/wallet-name.ts
47270
47720
  var WALLET_NAME_PATTERN = /^[a-z0-9][a-z0-9-]{0,31}$/;
@@ -47272,6 +47722,9 @@ var walletNameSchema = external_exports.string().regex(
47272
47722
  WALLET_NAME_PATTERN,
47273
47723
  "A wallet name is 1 to 32 characters of lowercase letters, digits and dashes, starting with a letter or digit."
47274
47724
  );
47725
+ function isWalletName(value) {
47726
+ return WALLET_NAME_PATTERN.test(value);
47727
+ }
47275
47728
 
47276
47729
  // src/vault.ts
47277
47730
  var VaultError = class extends Error {
@@ -47590,6 +48043,9 @@ async function exportVaultAccountKey(args) {
47590
48043
  throw asVaultError(error61, "corrupt", "Unable to export the vault account key.");
47591
48044
  }
47592
48045
  }
48046
+ async function exportMemberKey(args) {
48047
+ return await exportVaultAccountKey(args);
48048
+ }
47593
48049
  function assertVaultKey(key) {
47594
48050
  if (key.byteLength !== 32) {
47595
48051
  throw new VaultError("bad_key", "A device vault key must contain exactly 32 bytes.");
@@ -47706,7 +48162,7 @@ async function readVaultFile(path, key) {
47706
48162
  async function readVaultFileUnlocked(path) {
47707
48163
  let raw;
47708
48164
  try {
47709
- raw = await readFile3(path, "utf8");
48165
+ raw = await readFile4(path, "utf8");
47710
48166
  } catch (error61) {
47711
48167
  if (isMissingFile2(error61)) {
47712
48168
  throw new VaultError("not_found", "No vault file was found at the requested path.", {
@@ -47718,8 +48174,8 @@ async function readVaultFileUnlocked(path) {
47718
48174
  return parseVaultFile(raw);
47719
48175
  }
47720
48176
  async function writeVaultFile(path, file2) {
47721
- await mkdir3(dirname3(path), { recursive: true, mode: 448 });
47722
- const temporaryPath = `${path}.${process.pid}.${randomBytes3(6).toString("hex")}.tmp`;
48177
+ await mkdir4(dirname4(path), { recursive: true, mode: 448 });
48178
+ const temporaryPath = `${path}.${process.pid}.${randomBytes4(6).toString("hex")}.tmp`;
47723
48179
  try {
47724
48180
  await writeFile3(temporaryPath, `${JSON.stringify(file2, null, 2)}
47725
48181
  `, {
@@ -47727,20 +48183,20 @@ async function writeVaultFile(path, file2) {
47727
48183
  mode: 384,
47728
48184
  flag: "wx"
47729
48185
  });
47730
- await rename3(temporaryPath, path);
48186
+ await rename4(temporaryPath, path);
47731
48187
  } catch (error61) {
47732
48188
  await rm(temporaryPath, { force: true }).catch(() => void 0);
47733
48189
  throw error61;
47734
48190
  }
47735
48191
  }
47736
48192
  async function withVaultLock(path, operation) {
47737
- await mkdir3(dirname3(path), { recursive: true, mode: 448 });
48193
+ await mkdir4(dirname4(path), { recursive: true, mode: 448 });
47738
48194
  const lockPath = `${path}.lock`;
47739
48195
  const deadline = Date.now() + VAULT_LOCK_TIMEOUT_MS;
47740
48196
  let handle;
47741
48197
  while (!handle) {
47742
48198
  try {
47743
- handle = await open2(lockPath, "wx", 384);
48199
+ handle = await open3(lockPath, "wx", 384);
47744
48200
  } catch (error61) {
47745
48201
  if (!isExistingFile(error61)) throw error61;
47746
48202
  await removeStaleVaultLock(lockPath);
@@ -47754,13 +48210,13 @@ async function withVaultLock(path, operation) {
47754
48210
  return await operation();
47755
48211
  } finally {
47756
48212
  await handle.close();
47757
- await unlink(lockPath).catch(() => void 0);
48213
+ await unlink2(lockPath).catch(() => void 0);
47758
48214
  }
47759
48215
  }
47760
48216
  async function removeStaleVaultLock(path) {
47761
48217
  try {
47762
- const metadata = await stat3(path);
47763
- if (Date.now() - metadata.mtimeMs > STALE_VAULT_LOCK_MS) await unlink(path);
48218
+ const metadata = await stat4(path);
48219
+ if (Date.now() - metadata.mtimeMs > STALE_VAULT_LOCK_MS) await unlink2(path);
47764
48220
  } catch (error61) {
47765
48221
  if (!isMissingFile2(error61)) throw error61;
47766
48222
  }
@@ -47774,12 +48230,420 @@ function isExistingFile(error61) {
47774
48230
  function asVaultError(error61, code, message) {
47775
48231
  return error61 instanceof VaultError ? error61 : new VaultError(code, message, { cause: error61 });
47776
48232
  }
48233
+
48234
+ // src/device.ts
48235
+ var DEVICE_NAME_PATTERN = /^[a-z0-9][a-z0-9-]{0,31}$/;
48236
+
48237
+ // src/agent-link.ts
48238
+ var DEFAULT_AGENT_SCOPES = ["mcp:call", "router.use"];
48239
+ var ALLOWED_AGENT_SCOPES = /* @__PURE__ */ new Set([
48240
+ ...DEFAULT_AGENT_SCOPES,
48241
+ "call.publish",
48242
+ "tasks:read",
48243
+ "tasks:write"
48244
+ ]);
48245
+ var publicFetch = createPublicFetch({ allowPrivateNetwork: false });
48246
+ var agentSecretAccounts = (wallet) => ({
48247
+ tokens: `vapi.agent.${wallet}.tokens`,
48248
+ routerStake: `vapi.agent.${wallet}.router.stake`,
48249
+ routerBalance: `vapi.agent.${wallet}.router.balance`
48250
+ });
48251
+
48252
+ // src/agent-profile.ts
48253
+ var DEFAULT_AGENT_TOOLS = ["call.search", "call.inspect", "call.pay"];
48254
+ var AGENT_GRANTS = ["read", "delegate", "allocate"];
48255
+ var agentProfileShape = {
48256
+ version: external_exports.literal(1),
48257
+ name: walletNameSchema,
48258
+ wallet: external_exports.string(),
48259
+ model: external_exports.string().min(1),
48260
+ instructions: external_exports.string().max(2e4),
48261
+ verifiedOnly: external_exports.boolean().default(true),
48262
+ approveAboveUsd: external_exports.number().min(0).default(0.5),
48263
+ maxPerTaskUsd: external_exports.number().min(0).default(DEFAULT_MAX_PER_TASK_USD),
48264
+ autoReleaseBelowUsd: external_exports.number().min(0).default(DEFAULT_AUTO_RELEASE_BELOW_USD),
48265
+ maxSteps: external_exports.number().int().min(1).max(50).default(12),
48266
+ paused: external_exports.boolean().default(false),
48267
+ grants: external_exports.array(external_exports.enum(AGENT_GRANTS)).default([]),
48268
+ createdAt: external_exports.string()
48269
+ };
48270
+ function createAgentProfileSchema(toolNames) {
48271
+ if (toolNames.length === 0) {
48272
+ throw new Error("Agent profiles require at least one registered tool.");
48273
+ }
48274
+ const tools = [...toolNames];
48275
+ return external_exports.object({ ...agentProfileShape, tools: external_exports.array(external_exports.enum(tools)).default(tools) });
48276
+ }
48277
+ var agentProfileSchema = createAgentProfileSchema(DEFAULT_AGENT_TOOLS);
48278
+
48279
+ // src/agent-run.ts
48280
+ var RUN_ID_PATTERN = /^run_[0-9a-f]{24}$/;
48281
+ var runRefSchema = external_exports.strictObject({
48282
+ id: external_exports.string().regex(RUN_ID_PATTERN),
48283
+ swarm: external_exports.string().optional(),
48284
+ member: external_exports.string().optional(),
48285
+ parentRunId: external_exports.string().optional()
48286
+ });
48287
+
48288
+ // src/swarm.ts
48289
+ var SWARM_NAME_PATTERN = /^[a-z][a-z0-9-]{0,15}$/;
48290
+ var SWARM_ROLE_PATTERN = /^[a-z][a-z0-9]{0,7}$/;
48291
+ var atomicSchema = external_exports.string().regex(/^\d+$/);
48292
+ var addressSchema2 = external_exports.string().regex(/^0x[0-9a-fA-F]{40}$/);
48293
+ var capsSchema = external_exports.strictObject({ perCallAtomic: atomicSchema, perDayAtomic: atomicSchema });
48294
+ var movementIdSchema = external_exports.string().regex(/^mv_[A-Za-z0-9_-]{8,128}$/u);
48295
+ var amountUsdSchema = external_exports.string().regex(/^\d+\.\d{2}$/u);
48296
+ var setupFundingStatusSchema = external_exports.enum(["planned", "sent", "incomplete"]);
48297
+ var blockedFundingLegSchema = external_exports.strictObject({
48298
+ to: external_exports.string().trim().min(1),
48299
+ amountUsd: amountUsdSchema,
48300
+ reason: external_exports.string().trim().min(1)
48301
+ });
48302
+ var setupFundingSchema = external_exports.strictObject({
48303
+ amountUsd: amountUsdSchema,
48304
+ from: walletNameSchema,
48305
+ movementId: movementIdSchema.optional(),
48306
+ status: setupFundingStatusSchema,
48307
+ policy: external_exports.strictObject({
48308
+ strategy: external_exports.enum(["targets", "even", "weights"]),
48309
+ movementId: movementIdSchema.optional(),
48310
+ status: setupFundingStatusSchema,
48311
+ blocked: external_exports.array(blockedFundingLegSchema).optional()
48312
+ }).optional()
48313
+ });
48314
+ var accountSteps = {
48315
+ creating: external_exports.boolean().default(false),
48316
+ created: external_exports.boolean(),
48317
+ capped: external_exports.boolean(),
48318
+ linked: external_exports.boolean()
48319
+ };
48320
+ var treasurySchema = external_exports.strictObject({
48321
+ account: walletNameSchema,
48322
+ // A planned account has no address until its vault derivation succeeds.
48323
+ address: addressSchema2.optional(),
48324
+ steps: external_exports.strictObject(accountSteps)
48325
+ }).refine(
48326
+ (value) => !value.steps.created || value.address !== void 0,
48327
+ "Created accounts require an address."
48328
+ );
48329
+ var memberSchema = external_exports.strictObject({
48330
+ account: walletNameSchema,
48331
+ address: addressSchema2.optional(),
48332
+ role: external_exports.string().regex(SWARM_ROLE_PATTERN),
48333
+ weight: external_exports.number().int().positive(),
48334
+ targetAtomic: atomicSchema,
48335
+ ceilingAtomic: atomicSchema.nullable(),
48336
+ steps: external_exports.strictObject({ ...accountSteps, profiled: external_exports.boolean() })
48337
+ }).refine(
48338
+ (value) => !value.steps.created || value.address !== void 0,
48339
+ "Created accounts require an address."
48340
+ );
48341
+ var swarmFileSchema = external_exports.strictObject({
48342
+ v: external_exports.literal(1),
48343
+ name: external_exports.string().regex(SWARM_NAME_PATTERN),
48344
+ device: external_exports.string().regex(DEVICE_NAME_PATTERN),
48345
+ network: external_exports.enum([BASE_MAINNET_CAIP2, ARC_MAINNET_CAIP2]),
48346
+ createdAt: external_exports.iso.datetime(),
48347
+ treasury: treasurySchema,
48348
+ members: external_exports.array(memberSchema),
48349
+ setupFunding: setupFundingSchema.optional(),
48350
+ policy: external_exports.strictObject({
48351
+ strategy: external_exports.enum(["targets", "even", "weights"]),
48352
+ treasuryCaps: capsSchema
48353
+ })
48354
+ }).refine(
48355
+ (value) => (/* @__PURE__ */ new Set([value.treasury.account, ...value.members.map((member) => member.account)])).size === value.members.length + 1,
48356
+ "Swarm accounts must be unique."
48357
+ );
48358
+
48359
+ // src/member-bundle.ts
48360
+ var MEMBER_BUNDLE_MAX_BYTES = 32 * 1024;
48361
+ var REMOTE_BLOCKED_GRANTS = /* @__PURE__ */ new Set([
48362
+ "delegate",
48363
+ "allocate"
48364
+ ]);
48365
+ var BASE64URL_PATTERN = /^[A-Za-z0-9_-]+$/;
48366
+ var ADDRESS_PATTERN2 = /^0x[0-9a-fA-F]{40}$/;
48367
+ var PRIVATE_KEY_PATTERN = /^0x[0-9a-fA-F]{64}$/;
48368
+ var ATOMIC_PATTERN = /^\d+$/;
48369
+ var FORBIDDEN_CONFIG_KEYS = /* @__PURE__ */ new Set(["rpcUrl", "apiKey"]);
48370
+ var MemberBundleError = class extends Error {
48371
+ constructor(code, message) {
48372
+ super(message);
48373
+ this.code = code;
48374
+ this.name = "MemberBundleError";
48375
+ }
48376
+ code;
48377
+ };
48378
+ var hexString = (pattern, message) => external_exports.custom((value) => typeof value === "string" && pattern.test(value), message);
48379
+ var linkSchema = external_exports.strictObject({
48380
+ apiBase: external_exports.string(),
48381
+ clientId: external_exports.string(),
48382
+ owner: external_exports.custom((value) => typeof value === "string" && value.startsWith("0x")),
48383
+ label: external_exports.string(),
48384
+ scopes: external_exports.array(external_exports.string()),
48385
+ linkedAt: external_exports.iso.datetime(),
48386
+ routerBaseUrl: external_exports.string().optional()
48387
+ });
48388
+ var remoteTokensSchema = external_exports.strictObject({
48389
+ accessToken: external_exports.string().min(1),
48390
+ expiresAt: external_exports.number().finite(),
48391
+ scopes: external_exports.array(external_exports.string()),
48392
+ refreshable: external_exports.literal(false)
48393
+ });
48394
+ var storedTokensSchema = external_exports.object({
48395
+ accessToken: external_exports.string().min(1),
48396
+ refreshToken: external_exports.string().min(1),
48397
+ expiresAt: external_exports.number().finite(),
48398
+ scopes: external_exports.array(external_exports.string())
48399
+ });
48400
+ var credentialsSchema = external_exports.strictObject({
48401
+ tokens: external_exports.string().min(1).refine(isRemoteTokens, "A member bundle carries a non-refreshable access token only."),
48402
+ routerStake: external_exports.string().min(1).optional(),
48403
+ routerBalance: external_exports.string().min(1).optional()
48404
+ });
48405
+ var remoteProfileSchema = agentProfileSchema.strict().refine((profile) => profile.grants.every((grant) => !REMOTE_BLOCKED_GRANTS.has(grant)), {
48406
+ message: "A remote member never holds the delegate or allocate grant.",
48407
+ path: ["grants"]
48408
+ });
48409
+ var credentialFreeUrl = external_exports.url().refine((value) => unsafeUrlPart(value) === void 0, {
48410
+ message: "A member bundle URL never carries a user name, password, query or fragment."
48411
+ });
48412
+ var memberBundleConfigSchema = external_exports.unknown().refine((value) => !hasForbiddenConfigKey(value), {
48413
+ message: "A member bundle never carries RPC URLs or API keys."
48414
+ }).pipe(
48415
+ external_exports.strictObject({
48416
+ discoveryUrl: credentialFreeUrl,
48417
+ marketplaceDiscoveryUrl: credentialFreeUrl,
48418
+ networks: external_exports.record(
48419
+ external_exports.string().refine(isMemberBundleNetwork, {
48420
+ message: "Expected a network with a public RPC default."
48421
+ }),
48422
+ external_exports.strictObject({ usdc: external_exports.string() })
48423
+ ).refine(
48424
+ (networks) => Object.entries(networks).every(
48425
+ ([id, network]) => isMemberBundleNetwork(id) && network.usdc === NETWORKS[id].usdc
48426
+ ),
48427
+ { message: "Expected the canonical USDC token of each network." }
48428
+ ).refine((networks) => Object.keys(networks).length === 1, {
48429
+ message: "A member bundle carries exactly one network: the swarm's."
48430
+ })
48431
+ })
48432
+ );
48433
+ var memberBundleSchema = external_exports.strictObject({
48434
+ v: external_exports.literal(1),
48435
+ account: walletNameSchema,
48436
+ address: hexString(ADDRESS_PATTERN2, "Expected a 20-byte 0x address."),
48437
+ privateKey: hexString(PRIVATE_KEY_PATTERN, "Expected a 32-byte 0x private key."),
48438
+ swarm: external_exports.string().regex(SWARM_NAME_PATTERN),
48439
+ profile: remoteProfileSchema,
48440
+ link: linkSchema,
48441
+ credentials: credentialsSchema,
48442
+ caps: external_exports.strictObject(spendCapsSchema.shape),
48443
+ allowanceExpiresAt: external_exports.iso.datetime(),
48444
+ ceilingAtomic: external_exports.string().regex(ATOMIC_PATTERN, "Expected non-negative atomic units."),
48445
+ config: memberBundleConfigSchema,
48446
+ runId: external_exports.string().regex(RUN_ID_PATTERN),
48447
+ parentRunId: external_exports.string().regex(RUN_ID_PATTERN).optional()
48448
+ });
48449
+ function memberBundleConfig(owner, network) {
48450
+ const discoveryUrl = safeDiscoveryUrl("discoveryUrl", owner.discoveryUrl);
48451
+ const marketplaceDiscoveryUrl = safeDiscoveryUrl(
48452
+ "marketplaceDiscoveryUrl",
48453
+ owner.marketplaceDiscoveryUrl
48454
+ );
48455
+ if (!Object.hasOwn(owner.networks, network) || !isMemberBundleNetwork(network)) {
48456
+ throw new MemberBundleError(
48457
+ "unsupported_network",
48458
+ `A member bundle runs on the swarm network ${network}, which must be enabled in this config and have a public RPC default.`
48459
+ );
48460
+ }
48461
+ return {
48462
+ discoveryUrl,
48463
+ marketplaceDiscoveryUrl,
48464
+ networks: { [network]: { usdc: NETWORKS[network].usdc } }
48465
+ };
48466
+ }
48467
+ function headlessConfigFromBundle(config2) {
48468
+ const networks = {};
48469
+ for (const [id, network] of Object.entries(config2.networks)) {
48470
+ if (!isMemberBundleNetwork(id) || network === void 0) continue;
48471
+ networks[id] = { rpcUrl: NETWORKS[id].publicRpcUrl, usdc: network.usdc };
48472
+ }
48473
+ return configSchema.parse({
48474
+ discoveryUrl: config2.discoveryUrl,
48475
+ marketplaceDiscoveryUrl: config2.marketplaceDiscoveryUrl,
48476
+ networks,
48477
+ spendCaps: { ...DEFAULT_SPEND_CAPS }
48478
+ });
48479
+ }
48480
+ function createMemberBundle(input2) {
48481
+ const bundle = parseBundle({ ...input2, profile: withoutRemoteGrants(input2.profile), v: 1 });
48482
+ assertKeyMatchesAddress(bundle);
48483
+ const encoded = Buffer.from(JSON.stringify(bundle), "utf8").toString("base64url");
48484
+ if (encoded.length > MEMBER_BUNDLE_MAX_BYTES) {
48485
+ throw new MemberBundleError(
48486
+ "too_large",
48487
+ `The member bundle is larger than ${MEMBER_BUNDLE_MAX_BYTES} bytes.`
48488
+ );
48489
+ }
48490
+ return encoded;
48491
+ }
48492
+ function openMemberBundle(text) {
48493
+ if (typeof text !== "string") {
48494
+ throw new MemberBundleError("invalid", "The member bundle is not a string.");
48495
+ }
48496
+ if (text.length > MEMBER_BUNDLE_MAX_BYTES) {
48497
+ throw new MemberBundleError(
48498
+ "too_large",
48499
+ `The member bundle is larger than ${MEMBER_BUNDLE_MAX_BYTES} bytes.`
48500
+ );
48501
+ }
48502
+ if (!BASE64URL_PATTERN.test(text)) {
48503
+ throw new MemberBundleError("invalid", "The member bundle is not base64url text.");
48504
+ }
48505
+ let decoded;
48506
+ try {
48507
+ decoded = JSON.parse(Buffer.from(text, "base64url").toString("utf8"));
48508
+ } catch {
48509
+ throw new MemberBundleError("invalid", "The member bundle does not decode to JSON.");
48510
+ }
48511
+ const bundle = parseBundle(decoded);
48512
+ assertKeyMatchesAddress(bundle);
48513
+ return bundle;
48514
+ }
48515
+ async function readMemberCredentials(args) {
48516
+ if (!isWalletName(args.account)) {
48517
+ throw new MemberBundleError("invalid", "The member account name is not valid.");
48518
+ }
48519
+ const names = agentSecretAccounts(args.account);
48520
+ const storedTokens = await args.secrets.get(names.tokens);
48521
+ if (storedTokens === void 0 || storedTokens === "") {
48522
+ throw new MemberBundleError(
48523
+ "not_linked",
48524
+ `The account ${args.account} is not linked to vAPI. Link it with vapi login first.`
48525
+ );
48526
+ }
48527
+ const routerStake = await args.secrets.get(names.routerStake);
48528
+ const routerBalance = await args.secrets.get(names.routerBalance);
48529
+ const parsed = parseStoredTokens(storedTokens);
48530
+ if (parsed === void 0) {
48531
+ throw new MemberBundleError(
48532
+ "not_linked",
48533
+ `The account ${args.account}'s vAPI credentials cannot be exported safely. Run vapi login --account ${args.account} again.`
48534
+ );
48535
+ }
48536
+ const tokens = JSON.stringify({
48537
+ accessToken: parsed.accessToken,
48538
+ expiresAt: parsed.expiresAt,
48539
+ scopes: parsed.scopes,
48540
+ refreshable: false
48541
+ });
48542
+ return {
48543
+ tokens,
48544
+ ...routerStake === void 0 || routerStake === "" ? {} : { routerStake },
48545
+ ...routerBalance === void 0 || routerBalance === "" ? {} : { routerBalance }
48546
+ };
48547
+ }
48548
+ function isRemoteTokens(value) {
48549
+ try {
48550
+ return remoteTokensSchema.safeParse(JSON.parse(value)).success;
48551
+ } catch {
48552
+ return false;
48553
+ }
48554
+ }
48555
+ function parseStoredTokens(value) {
48556
+ try {
48557
+ const parsed = storedTokensSchema.safeParse(JSON.parse(value));
48558
+ return parsed.success ? parsed.data : void 0;
48559
+ } catch {
48560
+ return void 0;
48561
+ }
48562
+ }
48563
+ function isMemberBundleNetwork(id) {
48564
+ return Object.hasOwn(NETWORKS, id) && typeof NETWORKS[id].publicRpcUrl === "string";
48565
+ }
48566
+ function hasForbiddenConfigKey(value) {
48567
+ if (Array.isArray(value)) return value.some(hasForbiddenConfigKey);
48568
+ if (typeof value !== "object" || value === null) return false;
48569
+ return Object.entries(value).some(
48570
+ ([key, item]) => FORBIDDEN_CONFIG_KEYS.has(key) || hasForbiddenConfigKey(item)
48571
+ );
48572
+ }
48573
+ function unsafeUrlPart(value) {
48574
+ let url2;
48575
+ try {
48576
+ url2 = new URL(value);
48577
+ } catch {
48578
+ return "an unparseable value";
48579
+ }
48580
+ if (url2.username !== "" || url2.password !== "") return "a user name or password";
48581
+ if (url2.search !== "" || value.includes("?")) return "a query string";
48582
+ if (url2.hash !== "" || value.includes("#")) return "a fragment";
48583
+ return void 0;
48584
+ }
48585
+ function safeDiscoveryUrl(field, value) {
48586
+ const part = unsafeUrlPart(value);
48587
+ if (part !== void 0) {
48588
+ throw new MemberBundleError(
48589
+ "unsafe_config",
48590
+ `The owner config's ${field} has ${part}, which can carry a credential, so it never goes into a member bundle. Point ${field} at a plain URL (check VAPI_DISCOVERY_URL, VAPI_MARKETPLACE_DISCOVERY_URL and config.json).`
48591
+ );
48592
+ }
48593
+ return value;
48594
+ }
48595
+ function withoutRemoteGrants(profile) {
48596
+ if (typeof profile !== "object" || profile === null || !Array.isArray(profile.grants)) {
48597
+ return profile;
48598
+ }
48599
+ return {
48600
+ ...profile,
48601
+ grants: profile.grants.filter((grant) => !REMOTE_BLOCKED_GRANTS.has(grant))
48602
+ };
48603
+ }
48604
+ function parseBundle(value) {
48605
+ const parsed = memberBundleSchema.safeParse(value);
48606
+ if (!parsed.success) {
48607
+ const fields = [
48608
+ ...new Set(parsed.error.issues.map((issue2) => issue2.path.map(String).join(".") || "(root)"))
48609
+ ];
48610
+ throw new MemberBundleError(
48611
+ "invalid",
48612
+ `The member bundle is not valid (fields: ${fields.join(", ")}).`
48613
+ );
48614
+ }
48615
+ return parsed.data;
48616
+ }
48617
+ function assertKeyMatchesAddress(bundle) {
48618
+ let derived;
48619
+ try {
48620
+ derived = privateKeyToAccount(bundle.privateKey).address;
48621
+ } catch {
48622
+ throw new MemberBundleError("key_mismatch", "The member bundle's key is not a valid key.");
48623
+ }
48624
+ if (derived.toLowerCase() !== bundle.address.toLowerCase()) {
48625
+ throw new MemberBundleError(
48626
+ "key_mismatch",
48627
+ "The member bundle's key does not match its address."
48628
+ );
48629
+ }
48630
+ }
47777
48631
  export {
48632
+ MEMBER_BUNDLE_MAX_BYTES,
48633
+ MemberBundleError,
47778
48634
  createKeystoreWithPhrase,
48635
+ createMemberBundle,
47779
48636
  decryptPrivateKey,
47780
48637
  exportKeystoreKeys,
48638
+ exportMemberKey,
47781
48639
  exportRecoveryPhrase,
47782
48640
  exportVaultAccountKey,
47783
- exportVaultPhrase
48641
+ exportVaultPhrase,
48642
+ headlessConfigFromBundle,
48643
+ memberBundleConfig,
48644
+ memberBundleConfigSchema,
48645
+ memberBundleSchema,
48646
+ openMemberBundle,
48647
+ readMemberCredentials
47784
48648
  };
47785
48649
  //# sourceMappingURL=secrets.js.map