@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.
- package/README.md +14 -1
- package/dist/account-add.d.ts +8 -1
- package/dist/account-add.d.ts.map +1 -1
- package/dist/account-movement-lock.d.ts +10 -0
- package/dist/account-movement-lock.d.ts.map +1 -0
- package/dist/agent-link.d.ts +1 -0
- package/dist/agent-link.d.ts.map +1 -1
- package/dist/agent-link.js +27 -11
- package/dist/agent-link.js.map +1 -1
- package/dist/agent-profile.d.ts +18 -2
- package/dist/agent-profile.d.ts.map +1 -1
- package/dist/agent-run.d.ts +12 -0
- package/dist/agent-run.d.ts.map +1 -0
- package/dist/allocation.d.ts +35 -4
- package/dist/allocation.d.ts.map +1 -1
- package/dist/api-key.js +47 -0
- package/dist/api-key.js.map +1 -1
- package/dist/atomic-file.d.ts +23 -0
- package/dist/atomic-file.d.ts.map +1 -0
- package/dist/audit.d.ts +4 -1
- package/dist/audit.d.ts.map +1 -1
- package/dist/backup.d.ts +155 -32
- package/dist/backup.d.ts.map +1 -1
- package/dist/backup.js +2600 -139
- package/dist/backup.js.map +3 -3
- package/dist/call-contracts-wire.d.ts +12 -12
- package/dist/ceiling.d.ts +8 -0
- package/dist/ceiling.d.ts.map +1 -1
- package/dist/cloud-backup.d.ts +8 -10
- package/dist/cloud-backup.d.ts.map +1 -1
- package/dist/cloud-backup.js +2876 -381
- package/dist/cloud-backup.js.map +3 -3
- package/dist/config.d.ts +9 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/distribute.d.ts +9 -1
- package/dist/distribute.d.ts.map +1 -1
- package/dist/docs.d.ts +40 -0
- package/dist/docs.d.ts.map +1 -0
- package/dist/funding-policy.d.ts +29 -0
- package/dist/funding-policy.d.ts.map +1 -0
- package/dist/index.d.ts +12 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +5832 -1213
- package/dist/index.js.map +3 -3
- package/dist/marketplace-contracts.d.ts +14 -14
- package/dist/member-bundle.d.ts +110 -0
- package/dist/member-bundle.d.ts.map +1 -0
- package/dist/movement-open.d.ts +10 -0
- package/dist/movement-open.d.ts.map +1 -0
- package/dist/movement.d.ts +77 -7
- package/dist/movement.d.ts.map +1 -1
- package/dist/receipts.d.ts +9 -0
- package/dist/receipts.d.ts.map +1 -1
- package/dist/router-client.d.ts +9 -1
- package/dist/router-client.d.ts.map +1 -1
- package/dist/router-client.js +2272 -609
- package/dist/router-client.js.map +3 -3
- package/dist/run-budget.d.ts +17 -0
- package/dist/run-budget.d.ts.map +1 -0
- package/dist/secret-store.d.ts +6 -0
- package/dist/secret-store.d.ts.map +1 -1
- package/dist/secrets.d.ts +2 -1
- package/dist/secrets.d.ts.map +1 -1
- package/dist/secrets.js +912 -48
- package/dist/secrets.js.map +3 -3
- package/dist/spend-policy.d.ts +41 -7
- package/dist/spend-policy.d.ts.map +1 -1
- package/dist/support-report.d.ts +1 -1
- package/dist/swarm-capital.d.ts +147 -0
- package/dist/swarm-capital.d.ts.map +1 -0
- package/dist/swarm.d.ts +224 -0
- package/dist/swarm.d.ts.map +1 -0
- package/dist/tasks/actions.d.ts +152 -0
- package/dist/tasks/actions.d.ts.map +1 -0
- package/dist/tasks/canonical-json.d.ts +6 -0
- package/dist/tasks/canonical-json.d.ts.map +1 -0
- package/dist/tasks/chain-error.d.ts +6 -0
- package/dist/tasks/chain-error.d.ts.map +1 -0
- package/dist/tasks/chain-port.d.ts +88 -0
- package/dist/tasks/chain-port.d.ts.map +1 -0
- package/dist/tasks/chain-verification.d.ts +36 -0
- package/dist/tasks/chain-verification.d.ts.map +1 -0
- package/dist/tasks/chain.d.ts +22 -0
- package/dist/tasks/chain.d.ts.map +1 -0
- package/dist/tasks/client.d.ts +76 -0
- package/dist/tasks/client.d.ts.map +1 -0
- package/dist/tasks/delivery-manifest.d.ts +24 -0
- package/dist/tasks/delivery-manifest.d.ts.map +1 -0
- package/dist/tasks/dispute-fee.d.ts +4 -0
- package/dist/tasks/dispute-fee.d.ts.map +1 -0
- package/dist/tasks/index.d.ts +22 -0
- package/dist/tasks/index.d.ts.map +1 -0
- package/dist/tasks/money.d.ts +17 -0
- package/dist/tasks/money.d.ts.map +1 -0
- package/dist/tasks/operation-support.d.ts +127 -0
- package/dist/tasks/operation-support.d.ts.map +1 -0
- package/dist/tasks/operations.d.ts +722 -0
- package/dist/tasks/operations.d.ts.map +1 -0
- package/dist/tasks/pending-transactions.d.ts +52 -0
- package/dist/tasks/pending-transactions.d.ts.map +1 -0
- package/dist/tasks/plan-guard.d.ts +326 -0
- package/dist/tasks/plan-guard.d.ts.map +1 -0
- package/dist/tasks/rpc.d.ts +8 -0
- package/dist/tasks/rpc.d.ts.map +1 -0
- package/dist/tasks/scope-bindings.d.ts +20 -0
- package/dist/tasks/scope-bindings.d.ts.map +1 -0
- package/dist/tasks/scope-terms.d.ts +75 -0
- package/dist/tasks/scope-terms.d.ts.map +1 -0
- package/dist/tasks/trusted-deployments.d.ts +14 -0
- package/dist/tasks/trusted-deployments.d.ts.map +1 -0
- package/dist/tasks/types.d.ts +4439 -0
- package/dist/tasks/types.d.ts.map +1 -0
- package/dist/tasks/verbs.d.ts +4 -0
- package/dist/tasks/verbs.d.ts.map +1 -0
- package/dist/tasks.js +43906 -0
- package/dist/tasks.js.map +6 -0
- package/dist/transfer-journal.d.ts +11 -0
- package/dist/transfer-journal.d.ts.map +1 -0
- package/dist/transfer.d.ts +4 -1
- package/dist/transfer.d.ts.map +1 -1
- package/dist/vault.d.ts +11 -0
- package/dist/vault.d.ts.map +1 -1
- package/dist/wallet-store.d.ts +19 -8
- package/dist/wallet-store.d.ts.map +1 -1
- package/dist/x402-pay.d.ts +7 -0
- package/dist/x402-pay.d.ts.map +1 -1
- package/dist/x402.d.ts +3 -0
- package/dist/x402.d.ts.map +1 -1
- 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:
|
|
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 ?
|
|
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
|
|
2797
|
-
if (
|
|
2798
|
-
|
|
2799
|
-
const length =
|
|
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(
|
|
2803
|
-
const nibbleRight = charCodeToBase16(
|
|
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 ("${
|
|
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
|
|
4277
|
-
import { mkdir as
|
|
4278
|
-
import { dirname as
|
|
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
|
|
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() ||
|
|
47175
|
+
function getVapiPaths(directory = process.env.VAPI_HOME?.trim() || join3(homedir(), ".vapi")) {
|
|
46733
47176
|
return {
|
|
46734
47177
|
directory,
|
|
46735
|
-
agentsDir:
|
|
46736
|
-
config:
|
|
46737
|
-
keystore:
|
|
46738
|
-
receipts:
|
|
46739
|
-
searches:
|
|
46740
|
-
ledger:
|
|
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 ??
|
|
47188
|
+
const legacyDirectory = options.legacyDirectory ?? join3(homedir(), ".vapi", "agent-cash");
|
|
46746
47189
|
if (legacyDirectory === target.directory || !await pathExists(legacyDirectory)) return [];
|
|
46747
|
-
await
|
|
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 =
|
|
46757
|
-
const destination =
|
|
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
|
|
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 =
|
|
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 =
|
|
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
|
|
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
|
|
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
|
|
47244
|
-
const temporaryPath = `${path}.${process.pid}.${
|
|
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
|
|
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
|
|
47711
|
+
await rename3(temporaryPath, path);
|
|
47262
47712
|
}
|
|
47263
47713
|
|
|
47264
47714
|
// src/vault.ts
|
|
47265
|
-
import { randomBytes as
|
|
47266
|
-
import { mkdir as
|
|
47267
|
-
import { dirname as
|
|
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
|
|
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
|
|
47722
|
-
const temporaryPath = `${path}.${process.pid}.${
|
|
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
|
|
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
|
|
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
|
|
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
|
|
48213
|
+
await unlink2(lockPath).catch(() => void 0);
|
|
47758
48214
|
}
|
|
47759
48215
|
}
|
|
47760
48216
|
async function removeStaleVaultLock(path) {
|
|
47761
48217
|
try {
|
|
47762
|
-
const metadata = await
|
|
47763
|
-
if (Date.now() - metadata.mtimeMs > STALE_VAULT_LOCK_MS) await
|
|
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
|