@vapi-network/core 0.8.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/agent-link.d.ts.map +1 -1
- package/dist/agent-link.js +6 -1
- package/dist/agent-link.js.map +1 -1
- package/dist/agent-profile.d.ts +4 -0
- package/dist/agent-profile.d.ts.map +1 -1
- package/dist/api-key.js +47 -0
- package/dist/api-key.js.map +1 -1
- package/dist/backup.d.ts +2 -0
- package/dist/backup.d.ts.map +1 -1
- package/dist/backup.js +65 -0
- package/dist/backup.js.map +1 -1
- package/dist/cloud-backup.js +71 -1
- package/dist/cloud-backup.js.map +1 -1
- package/dist/config.d.ts +9 -0
- package/dist/config.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 +4 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +718 -35
- package/dist/index.js.map +3 -3
- package/dist/router-client.js +230 -33
- package/dist/router-client.js.map +2 -2
- package/dist/secrets.js +29 -1
- package/dist/secrets.js.map +1 -1
- 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/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.d.ts.map +1 -1
- package/package.json +5 -1
package/dist/index.js
CHANGED
|
@@ -39074,7 +39074,9 @@ function http(url2, config2 = {}) {
|
|
|
39074
39074
|
// ../../node_modules/.pnpm/viem@2.56.1_typescript@6.0.3_zod@4.5.4/node_modules/viem/_esm/index.js
|
|
39075
39075
|
init_getAddress();
|
|
39076
39076
|
init_isAddress();
|
|
39077
|
+
init_toBytes();
|
|
39077
39078
|
init_toHex();
|
|
39079
|
+
init_keccak256();
|
|
39078
39080
|
|
|
39079
39081
|
// src/x402-networks.ts
|
|
39080
39082
|
var BASE_MAINNET_CAIP2 = "eip155:8453";
|
|
@@ -46438,6 +46440,8 @@ var DEFAULT_SPEND_CAPS = {
|
|
|
46438
46440
|
perCallAtomic: "100000",
|
|
46439
46441
|
perDayAtomic: "1000000"
|
|
46440
46442
|
};
|
|
46443
|
+
var DEFAULT_MAX_PER_TASK_USD = 100;
|
|
46444
|
+
var DEFAULT_AUTO_RELEASE_BELOW_USD = 25;
|
|
46441
46445
|
var DEFAULT_CEILING_ATOMIC = 5000000n;
|
|
46442
46446
|
var atomicString = external_exports.string().regex(/^\d+$/, "Expected non-negative atomic units.");
|
|
46443
46447
|
var spendCapsSchema = external_exports.object({
|
|
@@ -46454,6 +46458,14 @@ var configSchema = external_exports.object({
|
|
|
46454
46458
|
})
|
|
46455
46459
|
).optional(),
|
|
46456
46460
|
allowPrivateNetwork: external_exports.boolean().default(false).optional(),
|
|
46461
|
+
tasksEscrowDurationOverrides: external_exports.record(
|
|
46462
|
+
external_exports.string().regex(/^\d+$/),
|
|
46463
|
+
external_exports.object({
|
|
46464
|
+
workDurationSeconds: external_exports.number().int().positive().max(Number.MAX_SAFE_INTEGER).optional(),
|
|
46465
|
+
reviewWindowSeconds: external_exports.number().int().positive().max(Number.MAX_SAFE_INTEGER).optional()
|
|
46466
|
+
}).strict()
|
|
46467
|
+
).optional(),
|
|
46468
|
+
tasksEscrowFactoryOverrides: external_exports.record(external_exports.string().regex(/^\d+$/), external_exports.string()).optional(),
|
|
46457
46469
|
networks: external_exports.record(
|
|
46458
46470
|
external_exports.string().refine((network) => isSupportedPaymentNetwork(network), {
|
|
46459
46471
|
message: "Expected a supported eip155:<chainId> or Solana network identifier."
|
|
@@ -46472,6 +46484,17 @@ var configSchema = external_exports.object({
|
|
|
46472
46484
|
spendCaps: spendCapsSchema,
|
|
46473
46485
|
device: external_exports.string().regex(/^[a-z0-9][a-z0-9-]{0,31}$/).optional()
|
|
46474
46486
|
}).superRefine((config2, context) => {
|
|
46487
|
+
for (const [chainId, factory] of Object.entries(config2.tasksEscrowFactoryOverrides ?? {})) {
|
|
46488
|
+
try {
|
|
46489
|
+
getAddress(factory);
|
|
46490
|
+
} catch {
|
|
46491
|
+
context.addIssue({
|
|
46492
|
+
code: "custom",
|
|
46493
|
+
path: ["tasksEscrowFactoryOverrides", chainId],
|
|
46494
|
+
message: "Expected a valid EVM escrow factory address."
|
|
46495
|
+
});
|
|
46496
|
+
}
|
|
46497
|
+
}
|
|
46475
46498
|
for (const [network, configured] of Object.entries(config2.networks)) {
|
|
46476
46499
|
if (isSolanaNetwork(network)) {
|
|
46477
46500
|
if (configured.usdc !== NETWORKS[SOLANA_MAINNET_CAIP2].usdc) {
|
|
@@ -46634,6 +46657,7 @@ function getDefaultConfig(source = process.env, options = {}) {
|
|
|
46634
46657
|
const registry2 = registryEndpoints(source.VAPI_REGISTRY_URL?.trim() || DEFAULT_REGISTRY_URL);
|
|
46635
46658
|
const requested = new Set(options.networks ?? ["base"]);
|
|
46636
46659
|
const networks = {};
|
|
46660
|
+
const tasksEscrowFactoryOverrides = tasksFactoryOverridesFromEnv(source);
|
|
46637
46661
|
if (requested.has("base") || requested.has(BASE_MAINNET_CAIP2)) {
|
|
46638
46662
|
networks[BASE_MAINNET_CAIP2] = {
|
|
46639
46663
|
rpcUrl: source.BASE_RPC_URL?.trim() || NETWORKS[BASE_MAINNET_CAIP2].publicRpcUrl,
|
|
@@ -46671,6 +46695,8 @@ function getDefaultConfig(source = process.env, options = {}) {
|
|
|
46671
46695
|
marketplaceDiscoveryUrl: source.VAPI_MARKETPLACE_DISCOVERY_URL?.trim() || registry2.marketplaceDiscoveryUrl,
|
|
46672
46696
|
registryFallbacks: DEFAULT_REGISTRY_FALLBACKS.map((fallback) => ({ ...fallback })),
|
|
46673
46697
|
allowPrivateNetwork: false,
|
|
46698
|
+
tasksEscrowFactoryOverrides,
|
|
46699
|
+
tasksEscrowDurationOverrides: tasksDurationOverridesFromEnv(source),
|
|
46674
46700
|
networks,
|
|
46675
46701
|
spendCaps: { ...DEFAULT_SPEND_CAPS }
|
|
46676
46702
|
};
|
|
@@ -46688,8 +46714,10 @@ async function loadConfig(path = getVapiPaths().config, source = process.env, op
|
|
|
46688
46714
|
}
|
|
46689
46715
|
const parsed = configSchema.parse(JSON.parse(raw));
|
|
46690
46716
|
parsed.registryFallbacks ??= DEFAULT_REGISTRY_FALLBACKS.map((fallback) => ({ ...fallback }));
|
|
46717
|
+
parsed.tasksEscrowFactoryOverrides ??= {};
|
|
46691
46718
|
const migrated = rewriteLegacyRegistryUrls(parsed);
|
|
46692
46719
|
const config2 = migrated.config;
|
|
46720
|
+
config2.tasksEscrowFactoryOverrides ??= {};
|
|
46693
46721
|
if (migrated.changes.length > 0 && options.notice) {
|
|
46694
46722
|
options.notice(
|
|
46695
46723
|
`${formatLegacyRegistryRewrites(migrated.changes)}
|
|
@@ -46703,6 +46731,14 @@ Run vapi init to write the new URLs to ${path}.`
|
|
|
46703
46731
|
const discoveryUrl = source.VAPI_DISCOVERY_URL?.trim();
|
|
46704
46732
|
const marketplaceDiscoveryUrl = source.VAPI_MARKETPLACE_DISCOVERY_URL?.trim();
|
|
46705
46733
|
const registryUrl = source.VAPI_REGISTRY_URL?.trim();
|
|
46734
|
+
Object.assign(config2.tasksEscrowFactoryOverrides, tasksFactoryOverridesFromEnv(source));
|
|
46735
|
+
config2.tasksEscrowDurationOverrides ??= {};
|
|
46736
|
+
for (const [chainId, overrides] of Object.entries(tasksDurationOverridesFromEnv(source))) {
|
|
46737
|
+
config2.tasksEscrowDurationOverrides[chainId] = {
|
|
46738
|
+
...config2.tasksEscrowDurationOverrides[chainId],
|
|
46739
|
+
...overrides
|
|
46740
|
+
};
|
|
46741
|
+
}
|
|
46706
46742
|
if (config2.networks[BASE_MAINNET_CAIP2] && baseRpcUrl) {
|
|
46707
46743
|
config2.networks[BASE_MAINNET_CAIP2].rpcUrl = baseRpcUrl;
|
|
46708
46744
|
}
|
|
@@ -46743,6 +46779,31 @@ Run vapi init to write the new URLs to ${path}.`
|
|
|
46743
46779
|
}
|
|
46744
46780
|
return config2;
|
|
46745
46781
|
}
|
|
46782
|
+
function tasksDurationOverridesFromEnv(source) {
|
|
46783
|
+
const result = {};
|
|
46784
|
+
for (const [name, raw] of Object.entries(source)) {
|
|
46785
|
+
const match = /^VAPI_TASKS_(WORK_DURATION|REVIEW_WINDOW)_SECONDS_(\d+)$/.exec(name);
|
|
46786
|
+
const value = raw?.trim();
|
|
46787
|
+
if (!match || !value) continue;
|
|
46788
|
+
const seconds = Number(value);
|
|
46789
|
+
if (!/^\d+$/.test(value) || !Number.isSafeInteger(seconds) || seconds <= 0)
|
|
46790
|
+
throw new Error(`Invalid trusted Tasks duration ${name}.`);
|
|
46791
|
+
const entry = result[match[2]] ??= {};
|
|
46792
|
+
if (match[1] === "WORK_DURATION") entry.workDurationSeconds = seconds;
|
|
46793
|
+
else entry.reviewWindowSeconds = seconds;
|
|
46794
|
+
}
|
|
46795
|
+
return result;
|
|
46796
|
+
}
|
|
46797
|
+
function tasksFactoryOverridesFromEnv(source) {
|
|
46798
|
+
const overrides = {};
|
|
46799
|
+
for (const [name, raw] of Object.entries(source)) {
|
|
46800
|
+
const match = /^VAPI_TASKS_ESCROW_FACTORY_(\d+)$/.exec(name);
|
|
46801
|
+
const value = raw?.trim();
|
|
46802
|
+
if (!match || !value) continue;
|
|
46803
|
+
overrides[match[1]] = getAddress(value);
|
|
46804
|
+
}
|
|
46805
|
+
return overrides;
|
|
46806
|
+
}
|
|
46746
46807
|
function registryEndpoints(baseUrl) {
|
|
46747
46808
|
const base = new URL(baseUrl);
|
|
46748
46809
|
base.search = "";
|
|
@@ -46999,7 +47060,12 @@ var AgentLinkError = class extends Error {
|
|
|
46999
47060
|
code;
|
|
47000
47061
|
};
|
|
47001
47062
|
var DEFAULT_AGENT_SCOPES = ["mcp:call", "router.use"];
|
|
47002
|
-
var ALLOWED_AGENT_SCOPES = /* @__PURE__ */ new Set([
|
|
47063
|
+
var ALLOWED_AGENT_SCOPES = /* @__PURE__ */ new Set([
|
|
47064
|
+
...DEFAULT_AGENT_SCOPES,
|
|
47065
|
+
"call.publish",
|
|
47066
|
+
"tasks:read",
|
|
47067
|
+
"tasks:write"
|
|
47068
|
+
]);
|
|
47003
47069
|
var publicFetch = createPublicFetch({ allowPrivateNetwork: false });
|
|
47004
47070
|
async function startDeviceLink(args) {
|
|
47005
47071
|
if (args.device !== void 0 && !DEVICE_NAME_PATTERN.test(args.device)) {
|
|
@@ -72953,6 +73019,8 @@ var agentProfileShape = {
|
|
|
72953
73019
|
instructions: external_exports.string().max(2e4),
|
|
72954
73020
|
verifiedOnly: external_exports.boolean().default(true),
|
|
72955
73021
|
approveAboveUsd: external_exports.number().min(0).default(0.5),
|
|
73022
|
+
maxPerTaskUsd: external_exports.number().min(0).default(DEFAULT_MAX_PER_TASK_USD),
|
|
73023
|
+
autoReleaseBelowUsd: external_exports.number().min(0).default(DEFAULT_AUTO_RELEASE_BELOW_USD),
|
|
72956
73024
|
maxSteps: external_exports.number().int().min(1).max(50).default(12),
|
|
72957
73025
|
paused: external_exports.boolean().default(false),
|
|
72958
73026
|
grants: external_exports.array(external_exports.enum(AGENT_GRANTS)).default([]),
|
|
@@ -73113,7 +73181,9 @@ var ledgerSchema = external_exports.object({
|
|
|
73113
73181
|
});
|
|
73114
73182
|
var spendReservationSchema = external_exports.object({
|
|
73115
73183
|
id: external_exports.string().min(1),
|
|
73116
|
-
amountAtomic: external_exports.string().regex(/^\d+$/)
|
|
73184
|
+
amountAtomic: external_exports.string().regex(/^\d+$/),
|
|
73185
|
+
kind: external_exports.enum(["payment", "escrow-funding", "dispute-fee"]).optional(),
|
|
73186
|
+
taskKey: external_exports.string().optional()
|
|
73117
73187
|
});
|
|
73118
73188
|
var ledgerRowSchema = ledgerSchema.extend({
|
|
73119
73189
|
wallet: walletNameSchema.optional(),
|
|
@@ -73139,6 +73209,29 @@ async function readSpendLedger(path = getAgentCashPaths().ledger, now = /* @__PU
|
|
|
73139
73209
|
const row = rows.find((candidate) => candidate.wallet === wallet);
|
|
73140
73210
|
return { date: utcDateKey(now), spentAtomic: row?.spentAtomic ?? "0" };
|
|
73141
73211
|
}
|
|
73212
|
+
async function escrowFundingDayRemainingAtomic(input2) {
|
|
73213
|
+
const perDayAtomic = parseAtomicCap(input2.caps.perDayAtomic, "per-day");
|
|
73214
|
+
const rows = await readStoredSpendLedgerRows(input2.ledgerPath, input2.now);
|
|
73215
|
+
const row = rows.find((candidate) => candidate.wallet === input2.wallet);
|
|
73216
|
+
const reserved = input2.reservationId ? row?.reservations?.find((candidate) => candidate.id === input2.reservationId) : void 0;
|
|
73217
|
+
const remaining = perDayAtomic - BigInt(row?.spentAtomic ?? "0") + BigInt(reserved?.amountAtomic ?? "0");
|
|
73218
|
+
return remaining > 0n ? remaining : 0n;
|
|
73219
|
+
}
|
|
73220
|
+
async function taskReservedAtomic(input2) {
|
|
73221
|
+
const rows = await readStoredSpendLedgerRows(input2.ledgerPath, input2.now, true);
|
|
73222
|
+
return sumTaskReservations(rows, input2.wallet, input2.taskKey, input2.excludeReservationId);
|
|
73223
|
+
}
|
|
73224
|
+
function sumTaskReservations(rows, wallet, taskKey, excludeReservationId) {
|
|
73225
|
+
let total = 0n;
|
|
73226
|
+
for (const row of rows) {
|
|
73227
|
+
if (row.wallet !== wallet) continue;
|
|
73228
|
+
for (const reservation of row.reservations ?? []) {
|
|
73229
|
+
if (reservation.taskKey === taskKey && reservation.id !== excludeReservationId)
|
|
73230
|
+
total += BigInt(reservation.amountAtomic);
|
|
73231
|
+
}
|
|
73232
|
+
}
|
|
73233
|
+
return total;
|
|
73234
|
+
}
|
|
73142
73235
|
async function readSpendLedgerRows(path = getAgentCashPaths().ledger, now = /* @__PURE__ */ new Date()) {
|
|
73143
73236
|
return (await readStoredSpendLedgerRows(path, now)).map(({ date: date5, spentAtomic, wallet }) => ({
|
|
73144
73237
|
date: date5,
|
|
@@ -73146,7 +73239,7 @@ async function readSpendLedgerRows(path = getAgentCashPaths().ledger, now = /* @
|
|
|
73146
73239
|
wallet
|
|
73147
73240
|
}));
|
|
73148
73241
|
}
|
|
73149
|
-
async function readStoredSpendLedgerRows(path, now) {
|
|
73242
|
+
async function readStoredSpendLedgerRows(path, now, allDays = false) {
|
|
73150
73243
|
let raw;
|
|
73151
73244
|
try {
|
|
73152
73245
|
raw = await readFile13(path, "utf8");
|
|
@@ -73157,7 +73250,7 @@ async function readStoredSpendLedgerRows(path, now) {
|
|
|
73157
73250
|
const parsed = ledgerFileSchema.parse(JSON.parse(raw));
|
|
73158
73251
|
const rows = "rows" in parsed ? parsed.rows : [parsed];
|
|
73159
73252
|
const today = utcDateKey(now);
|
|
73160
|
-
return rows.filter((row) => row.date === today).map((row) => ({
|
|
73253
|
+
return rows.filter((row) => allDays || row.date === today).map((row) => ({
|
|
73161
73254
|
date: row.date,
|
|
73162
73255
|
spentAtomic: row.spentAtomic,
|
|
73163
73256
|
wallet: row.wallet ?? DEFAULT_WALLET_NAME,
|
|
@@ -73168,49 +73261,164 @@ async function reserveSpend(amountAtomic, caps, options) {
|
|
|
73168
73261
|
if (amountAtomic < 0n) {
|
|
73169
73262
|
throw new Error("Spend amount cannot be negative.");
|
|
73170
73263
|
}
|
|
73171
|
-
const
|
|
73172
|
-
|
|
73173
|
-
if (
|
|
73174
|
-
|
|
73175
|
-
|
|
73176
|
-
|
|
73177
|
-
|
|
73264
|
+
const kind = options?.kind ?? "payment";
|
|
73265
|
+
let perDayAtomic;
|
|
73266
|
+
if (kind === "escrow-funding" || kind === "dispute-fee") {
|
|
73267
|
+
const maxPerTaskAtomic = options?.maxPerTaskAtomic;
|
|
73268
|
+
if (maxPerTaskAtomic === void 0 || maxPerTaskAtomic < 0n) {
|
|
73269
|
+
throw new Error("Escrow funding requires a non-negative per-task cap.");
|
|
73270
|
+
}
|
|
73271
|
+
if (amountAtomic > maxPerTaskAtomic) {
|
|
73272
|
+
throw new SpendCapError(
|
|
73273
|
+
"per_task_cap_exceeded",
|
|
73274
|
+
`Escrow funding ${amountAtomic} atomic USDC exceeds the per-task cap ${maxPerTaskAtomic}. Refusing to sign.`
|
|
73275
|
+
);
|
|
73276
|
+
}
|
|
73277
|
+
perDayAtomic = parseAtomicCap(caps.perDayAtomic, "per-day");
|
|
73278
|
+
} else {
|
|
73279
|
+
const perCallAtomic = parseAtomicCap(caps.perCallAtomic, "per-call");
|
|
73280
|
+
perDayAtomic = parseAtomicCap(caps.perDayAtomic, "per-day");
|
|
73281
|
+
if (amountAtomic > perCallAtomic) {
|
|
73282
|
+
throw new SpendCapError(
|
|
73283
|
+
"per_call_cap_exceeded",
|
|
73284
|
+
`Payment quote ${amountAtomic} atomic USDC exceeds the per-call cap ${perCallAtomic}. Refusing to sign.`
|
|
73285
|
+
);
|
|
73286
|
+
}
|
|
73178
73287
|
}
|
|
73179
73288
|
const ledgerPath = options?.ledgerPath ?? getAgentCashPaths().ledger;
|
|
73180
73289
|
const now = options?.now ?? /* @__PURE__ */ new Date();
|
|
73181
73290
|
const wallet = options?.wallet ?? DEFAULT_WALLET_NAME;
|
|
73182
73291
|
return await withLedgerLock(ledgerPath, async () => {
|
|
73183
|
-
const rows = await readStoredSpendLedgerRows(ledgerPath, now);
|
|
73184
|
-
const
|
|
73292
|
+
const rows = await readStoredSpendLedgerRows(ledgerPath, now, true);
|
|
73293
|
+
const today = utcDateKey(now);
|
|
73294
|
+
const current = rows.find((row) => row.wallet === wallet && row.date === today);
|
|
73295
|
+
if ((kind === "escrow-funding" || kind === "dispute-fee") && options?.taskKey !== void 0) {
|
|
73296
|
+
const taskTotal = sumTaskReservations(
|
|
73297
|
+
rows,
|
|
73298
|
+
wallet,
|
|
73299
|
+
options.taskKey,
|
|
73300
|
+
options.reuseExistingEscrowReservation || options.resumeEscrowReservation ? options.reservationId : void 0
|
|
73301
|
+
) + amountAtomic;
|
|
73302
|
+
if (taskTotal > options.maxPerTaskAtomic)
|
|
73303
|
+
throw new SpendCapError(
|
|
73304
|
+
"per_task_cap_exceeded",
|
|
73305
|
+
`New spend ${amountAtomic} atomic USDC would raise the running total for task ${options.taskKey} and wallet ${wallet} to ${taskTotal}, above the per-task cap ${options.maxPerTaskAtomic}. Refusing to sign.`
|
|
73306
|
+
);
|
|
73307
|
+
}
|
|
73185
73308
|
if (options?.reservationId !== void 0) {
|
|
73186
|
-
|
|
73309
|
+
const existing = current?.reservations?.find(
|
|
73310
|
+
(reservation) => reservation.id === options.reservationId
|
|
73311
|
+
);
|
|
73312
|
+
if (existing && options.reuseExistingEscrowReservation) {
|
|
73313
|
+
if (kind !== "escrow-funding" && kind !== "dispute-fee" || existing.kind !== kind || existing.amountAtomic !== amountAtomic.toString() || existing.taskKey !== void 0 && existing.taskKey !== options.taskKey)
|
|
73314
|
+
throw new Error(
|
|
73315
|
+
`Spend reservation ${options.reservationId} does not match this funding.`
|
|
73316
|
+
);
|
|
73317
|
+
if (existing.taskKey === void 0 && options.taskKey !== void 0) {
|
|
73318
|
+
existing.taskKey = options.taskKey;
|
|
73319
|
+
await writeLedgerAtomically(ledgerPath, rows);
|
|
73320
|
+
}
|
|
73321
|
+
return {
|
|
73322
|
+
date: current.date,
|
|
73323
|
+
spentAtomic: current.spentAtomic,
|
|
73324
|
+
reservationReused: true
|
|
73325
|
+
};
|
|
73326
|
+
}
|
|
73327
|
+
if (existing) {
|
|
73187
73328
|
throw new Error(`Spend reservation ${options.reservationId} already exists.`);
|
|
73188
73329
|
}
|
|
73330
|
+
if (options.resumeEscrowReservation) {
|
|
73331
|
+
const resumed = options.resumeEscrowReservation;
|
|
73332
|
+
const historical = rows.find((row) => row.wallet === wallet && row.date === resumed.date);
|
|
73333
|
+
const stored = historical?.reservations?.find(
|
|
73334
|
+
(reservation) => reservation.id === resumed.id
|
|
73335
|
+
);
|
|
73336
|
+
if (kind !== "escrow-funding" && kind !== "dispute-fee" || resumed.id !== options.reservationId || resumed.wallet !== wallet || resumed.amountAtomic !== amountAtomic.toString() || resumed.date >= utcDateKey(now) || resumed.exposed !== true || resumed.invalidated === true || stored !== void 0 && (stored.kind !== kind || stored.amountAtomic !== amountAtomic.toString() || stored.taskKey !== void 0 && stored.taskKey !== options.taskKey))
|
|
73337
|
+
throw new Error(
|
|
73338
|
+
`Spend reservation ${options.reservationId} does not match this funding.`
|
|
73339
|
+
);
|
|
73340
|
+
if (stored?.taskKey === void 0 && options.taskKey !== void 0) {
|
|
73341
|
+
if (stored) stored.taskKey = options.taskKey;
|
|
73342
|
+
else {
|
|
73343
|
+
const reservation = {
|
|
73344
|
+
id: resumed.id,
|
|
73345
|
+
amountAtomic: resumed.amountAtomic,
|
|
73346
|
+
kind,
|
|
73347
|
+
taskKey: options.taskKey
|
|
73348
|
+
};
|
|
73349
|
+
if (historical)
|
|
73350
|
+
historical.reservations = [...historical.reservations ?? [], reservation];
|
|
73351
|
+
else
|
|
73352
|
+
rows.push({
|
|
73353
|
+
date: resumed.date,
|
|
73354
|
+
spentAtomic: resumed.amountAtomic,
|
|
73355
|
+
wallet,
|
|
73356
|
+
reservations: [reservation]
|
|
73357
|
+
});
|
|
73358
|
+
}
|
|
73359
|
+
await writeLedgerAtomically(ledgerPath, rows);
|
|
73360
|
+
}
|
|
73361
|
+
return {
|
|
73362
|
+
date: resumed.date,
|
|
73363
|
+
spentAtomic: current?.spentAtomic ?? "0",
|
|
73364
|
+
reservationReused: true
|
|
73365
|
+
};
|
|
73366
|
+
}
|
|
73189
73367
|
}
|
|
73190
73368
|
const spentAtomic = current?.spentAtomic ?? "0";
|
|
73191
73369
|
const nextSpent = BigInt(spentAtomic) + amountAtomic;
|
|
73192
73370
|
if (nextSpent > perDayAtomic) {
|
|
73193
73371
|
throw new SpendCapError(
|
|
73194
73372
|
"per_day_cap_exceeded",
|
|
73195
|
-
|
|
73373
|
+
`${kind === "escrow-funding" ? "Escrow funding" : "Payment quote"} ${amountAtomic} atomic USDC would raise today's spend to ${nextSpent} for wallet ${wallet}, above the per-day cap ${perDayAtomic}. Refusing to sign.`
|
|
73196
73374
|
);
|
|
73197
73375
|
}
|
|
73376
|
+
const reservationId = options?.reservationId ?? (options?.taskKey === void 0 ? void 0 : randomBytes10(16).toString("hex"));
|
|
73198
73377
|
const nextRow = {
|
|
73199
73378
|
date: utcDateKey(now),
|
|
73200
73379
|
spentAtomic: nextSpent.toString(),
|
|
73201
73380
|
wallet,
|
|
73202
|
-
...(current?.reservations?.length ?? 0) === 0 &&
|
|
73381
|
+
...(current?.reservations?.length ?? 0) === 0 && reservationId === void 0 ? {} : {
|
|
73203
73382
|
reservations: [
|
|
73204
73383
|
...current?.reservations ?? [],
|
|
73205
|
-
...
|
|
73384
|
+
...reservationId === void 0 ? [] : [
|
|
73385
|
+
{
|
|
73386
|
+
id: reservationId,
|
|
73387
|
+
amountAtomic: amountAtomic.toString(),
|
|
73388
|
+
...kind !== "payment" ? { kind } : {},
|
|
73389
|
+
...options?.taskKey === void 0 ? {} : { taskKey: options.taskKey }
|
|
73390
|
+
}
|
|
73391
|
+
]
|
|
73206
73392
|
]
|
|
73207
73393
|
}
|
|
73208
73394
|
};
|
|
73209
|
-
const
|
|
73210
|
-
(
|
|
73395
|
+
const otherRows = rows.filter((row) => row.wallet !== wallet || row.date !== today).map((row) => {
|
|
73396
|
+
if (row.wallet !== wallet || !options?.reuseExistingEscrowReservation || options.reservationId === void 0)
|
|
73397
|
+
return row;
|
|
73398
|
+
const previous = row.reservations?.find(
|
|
73399
|
+
(reservation) => reservation.id === options.reservationId
|
|
73400
|
+
);
|
|
73401
|
+
if (!previous) return row;
|
|
73402
|
+
if (kind !== "escrow-funding" && kind !== "dispute-fee" || previous.kind !== kind || previous.amountAtomic !== amountAtomic.toString() || previous.taskKey !== void 0 && previous.taskKey !== options.taskKey)
|
|
73403
|
+
throw new Error(
|
|
73404
|
+
`Spend reservation ${options.reservationId} does not match this funding.`
|
|
73405
|
+
);
|
|
73406
|
+
return {
|
|
73407
|
+
...row,
|
|
73408
|
+
reservations: row.reservations.filter(
|
|
73409
|
+
(reservation) => reservation.id !== options.reservationId
|
|
73410
|
+
)
|
|
73411
|
+
};
|
|
73412
|
+
});
|
|
73413
|
+
const nextRows = [...otherRows, nextRow].sort(
|
|
73414
|
+
(a, b) => a.wallet.localeCompare(b.wallet) || a.date.localeCompare(b.date)
|
|
73211
73415
|
);
|
|
73212
73416
|
await writeLedgerAtomically(ledgerPath, nextRows);
|
|
73213
|
-
return {
|
|
73417
|
+
return {
|
|
73418
|
+
date: nextRow.date,
|
|
73419
|
+
spentAtomic: nextRow.spentAtomic,
|
|
73420
|
+
...options?.reservationId === void 0 && reservationId !== void 0 ? { reservationId } : {}
|
|
73421
|
+
};
|
|
73214
73422
|
});
|
|
73215
73423
|
}
|
|
73216
73424
|
async function releaseSpend(amountAtomic, options) {
|
|
@@ -73222,35 +73430,40 @@ async function releaseSpend(amountAtomic, options) {
|
|
|
73222
73430
|
const wallet = options.wallet ?? DEFAULT_WALLET_NAME;
|
|
73223
73431
|
return await withLedgerLock(ledgerPath, async () => {
|
|
73224
73432
|
const today = utcDateKey(now);
|
|
73225
|
-
const rows = await readStoredSpendLedgerRows(ledgerPath, now);
|
|
73226
|
-
const current = rows.find((row) => row.wallet === wallet);
|
|
73227
|
-
if (options.reservedOn !== today) {
|
|
73433
|
+
const rows = await readStoredSpendLedgerRows(ledgerPath, now, true);
|
|
73434
|
+
const current = rows.find((row) => row.wallet === wallet && row.date === today);
|
|
73435
|
+
if (options.reservedOn !== today && options.reservationId === void 0) {
|
|
73228
73436
|
return { date: today, spentAtomic: current?.spentAtomic ?? "0" };
|
|
73229
73437
|
}
|
|
73230
|
-
const
|
|
73438
|
+
const reserved = rows.find((row) => row.wallet === wallet && row.date === options.reservedOn);
|
|
73439
|
+
const reservation = options.reservationId === void 0 ? void 0 : reserved?.reservations?.find((candidate) => candidate.id === options.reservationId);
|
|
73231
73440
|
if (options.reservationId !== void 0 && reservation === void 0) {
|
|
73232
73441
|
return { date: today, spentAtomic: current?.spentAtomic ?? "0" };
|
|
73233
73442
|
}
|
|
73234
73443
|
if (reservation !== void 0 && reservation.amountAtomic !== amountAtomic.toString()) {
|
|
73235
73444
|
throw new Error(`Spend reservation ${options.reservationId} has a different amount.`);
|
|
73236
73445
|
}
|
|
73237
|
-
const spentAtomic = BigInt(
|
|
73446
|
+
const spentAtomic = BigInt(reserved?.spentAtomic ?? "0");
|
|
73238
73447
|
const releasedAmount = reservation === void 0 ? amountAtomic : BigInt(reservation.amountAtomic);
|
|
73239
73448
|
const nextSpent = spentAtomic > releasedAmount ? spentAtomic - releasedAmount : 0n;
|
|
73240
|
-
const remainingReservations =
|
|
73449
|
+
const remainingReservations = reserved?.reservations?.filter(
|
|
73241
73450
|
(candidate) => candidate.id !== options.reservationId
|
|
73242
73451
|
);
|
|
73243
73452
|
const nextRow = {
|
|
73244
|
-
date:
|
|
73453
|
+
date: options.reservedOn,
|
|
73245
73454
|
spentAtomic: nextSpent.toString(),
|
|
73246
73455
|
wallet,
|
|
73247
73456
|
...remainingReservations === void 0 || remainingReservations.length === 0 ? {} : { reservations: remainingReservations }
|
|
73248
73457
|
};
|
|
73249
|
-
const nextRows = [
|
|
73250
|
-
(
|
|
73251
|
-
|
|
73458
|
+
const nextRows = [
|
|
73459
|
+
...rows.filter((row) => row.wallet !== wallet || row.date !== options.reservedOn),
|
|
73460
|
+
nextRow
|
|
73461
|
+
].sort((a, b) => a.wallet.localeCompare(b.wallet) || a.date.localeCompare(b.date));
|
|
73252
73462
|
await writeLedgerAtomically(ledgerPath, nextRows);
|
|
73253
|
-
return {
|
|
73463
|
+
return {
|
|
73464
|
+
date: today,
|
|
73465
|
+
spentAtomic: options.reservedOn === today ? nextRow.spentAtomic : current?.spentAtomic ?? "0"
|
|
73466
|
+
};
|
|
73254
73467
|
});
|
|
73255
73468
|
}
|
|
73256
73469
|
function parseAtomicCap(value, label) {
|
|
@@ -73547,7 +73760,9 @@ async function transferBetweenAccounts(args) {
|
|
|
73547
73760
|
);
|
|
73548
73761
|
reservedOn = reservation.date;
|
|
73549
73762
|
} catch (error61) {
|
|
73550
|
-
if (error61 instanceof SpendCapError
|
|
73763
|
+
if (error61 instanceof SpendCapError && isTransferErrorCode(error61.code)) {
|
|
73764
|
+
throw transferError(error61.code);
|
|
73765
|
+
}
|
|
73551
73766
|
throw transferError("network_error");
|
|
73552
73767
|
}
|
|
73553
73768
|
}
|
|
@@ -76685,7 +76900,7 @@ function createRunBudget(args) {
|
|
|
76685
76900
|
import { mkdir as mkdir15, writeFile as writeFile8 } from "node:fs/promises";
|
|
76686
76901
|
import { arch, platform, release } from "node:os";
|
|
76687
76902
|
import { join as join13 } from "node:path";
|
|
76688
|
-
var VAPI_CLIENT_VERSION = "0.
|
|
76903
|
+
var VAPI_CLIENT_VERSION = "0.9.0";
|
|
76689
76904
|
async function createSupportReport(options) {
|
|
76690
76905
|
const message = options.message.trim();
|
|
76691
76906
|
if (!message) throw new Error("Support report message must not be empty.");
|
|
@@ -77687,6 +77902,115 @@ async function responseJson(response) {
|
|
|
77687
77902
|
}
|
|
77688
77903
|
}
|
|
77689
77904
|
|
|
77905
|
+
// src/tasks/canonical-json.ts
|
|
77906
|
+
function canonicalizeJson(value) {
|
|
77907
|
+
if (value === null || typeof value === "string" || typeof value === "boolean") {
|
|
77908
|
+
return value;
|
|
77909
|
+
}
|
|
77910
|
+
if (typeof value === "number") {
|
|
77911
|
+
if (!Number.isFinite(value)) {
|
|
77912
|
+
throw new Error("Value is not JSON serializable");
|
|
77913
|
+
}
|
|
77914
|
+
return value;
|
|
77915
|
+
}
|
|
77916
|
+
if (Array.isArray(value)) {
|
|
77917
|
+
return value.map(canonicalizeJson);
|
|
77918
|
+
}
|
|
77919
|
+
if (typeof value === "object") {
|
|
77920
|
+
const prototype = Object.getPrototypeOf(value);
|
|
77921
|
+
if (prototype !== Object.prototype && prototype !== null) {
|
|
77922
|
+
throw new Error("Value is not JSON serializable");
|
|
77923
|
+
}
|
|
77924
|
+
return Object.fromEntries(
|
|
77925
|
+
Object.entries(value).sort(([left], [right]) => left < right ? -1 : left > right ? 1 : 0).map(([key, item]) => [key, canonicalizeJson(item)])
|
|
77926
|
+
);
|
|
77927
|
+
}
|
|
77928
|
+
throw new Error("Value is not JSON serializable");
|
|
77929
|
+
}
|
|
77930
|
+
function canonicalJson(value) {
|
|
77931
|
+
return JSON.stringify(canonicalizeJson(value));
|
|
77932
|
+
}
|
|
77933
|
+
|
|
77934
|
+
// src/tasks/delivery-manifest.ts
|
|
77935
|
+
import { createHash as createHash2 } from "node:crypto";
|
|
77936
|
+
var sha256Schema = external_exports.string().regex(/^[0-9a-fA-F]{64}$/).transform((digest) => digest.toLowerCase());
|
|
77937
|
+
var deliveryManifestSchema = external_exports.object({
|
|
77938
|
+
files: external_exports.array(
|
|
77939
|
+
external_exports.object({
|
|
77940
|
+
fileId: external_exports.uuid(),
|
|
77941
|
+
fileName: external_exports.string().min(1).max(255),
|
|
77942
|
+
sha256: sha256Schema,
|
|
77943
|
+
sizeBytes: external_exports.number().int().positive()
|
|
77944
|
+
}).strict()
|
|
77945
|
+
).min(1).max(20),
|
|
77946
|
+
noteSha256: sha256Schema
|
|
77947
|
+
}).strict().superRefine((manifest, context) => {
|
|
77948
|
+
if (new Set(manifest.files.map((file2) => file2.fileId)).size !== manifest.files.length) {
|
|
77949
|
+
context.addIssue({ code: "custom", path: ["files"], message: "File ids must be unique" });
|
|
77950
|
+
}
|
|
77951
|
+
});
|
|
77952
|
+
function freezeDeliveryManifest(input2) {
|
|
77953
|
+
const parsed = deliveryManifestSchema.parse(input2);
|
|
77954
|
+
const manifest = deliveryManifestSchema.parse({
|
|
77955
|
+
...parsed,
|
|
77956
|
+
files: [...parsed.files].sort((left, right) => left.fileId.localeCompare(right.fileId))
|
|
77957
|
+
});
|
|
77958
|
+
return {
|
|
77959
|
+
manifest,
|
|
77960
|
+
manifestHash: keccak256(toBytes(canonicalJson(manifest)))
|
|
77961
|
+
};
|
|
77962
|
+
}
|
|
77963
|
+
async function sha256Hex(bytes) {
|
|
77964
|
+
return createHash2("sha256").update(bytes).digest("hex");
|
|
77965
|
+
}
|
|
77966
|
+
async function prepareDeliveryManifest(files, note) {
|
|
77967
|
+
if (files.length === 0) {
|
|
77968
|
+
throw new Error("Upload at least one delivery file.");
|
|
77969
|
+
}
|
|
77970
|
+
const noteSha256 = await sha256Hex(new TextEncoder().encode(note));
|
|
77971
|
+
return freezeDeliveryManifest({ files, noteSha256 });
|
|
77972
|
+
}
|
|
77973
|
+
|
|
77974
|
+
// src/tasks/verbs.ts
|
|
77975
|
+
var TASKS_CLIENT_VERBS = [
|
|
77976
|
+
"search",
|
|
77977
|
+
"show",
|
|
77978
|
+
"post",
|
|
77979
|
+
"propose",
|
|
77980
|
+
"submit",
|
|
77981
|
+
"award",
|
|
77982
|
+
"sign",
|
|
77983
|
+
"fund",
|
|
77984
|
+
"deliver",
|
|
77985
|
+
"release",
|
|
77986
|
+
"refund",
|
|
77987
|
+
"dispute",
|
|
77988
|
+
"counter-evidence",
|
|
77989
|
+
"resolve-unmatched",
|
|
77990
|
+
"message",
|
|
77991
|
+
"thread",
|
|
77992
|
+
"watch",
|
|
77993
|
+
"status"
|
|
77994
|
+
];
|
|
77995
|
+
|
|
77996
|
+
// src/funding-policy.ts
|
|
77997
|
+
function decideFunding(input2) {
|
|
77998
|
+
validateAmount(input2.amountUsd);
|
|
77999
|
+
if (input2.amountUsd > input2.maxPerTaskUsd) return { ok: false, reason: "policy.perTask" };
|
|
78000
|
+
if (input2.amountUsd > input2.dayRemainingUsd) return { ok: false, reason: "policy.perDay" };
|
|
78001
|
+
if (input2.amountUsd > input2.approveAboveUsd) return { approval: true };
|
|
78002
|
+
return { ok: true };
|
|
78003
|
+
}
|
|
78004
|
+
function decideRelease(input2) {
|
|
78005
|
+
validateAmount(input2.amountUsd);
|
|
78006
|
+
return input2.amountUsd < input2.autoReleaseBelowUsd ? { auto: true } : { approval: true };
|
|
78007
|
+
}
|
|
78008
|
+
function validateAmount(amountUsd) {
|
|
78009
|
+
if (!Number.isFinite(amountUsd) || amountUsd < 0) {
|
|
78010
|
+
throw new Error("Task amount must be a finite, non-negative USD number.");
|
|
78011
|
+
}
|
|
78012
|
+
}
|
|
78013
|
+
|
|
77690
78014
|
// src/searches.ts
|
|
77691
78015
|
import { mkdir as mkdir16, open as open11, readFile as readFile16 } from "node:fs/promises";
|
|
77692
78016
|
import { dirname as dirname10 } from "node:path";
|
|
@@ -77867,6 +78191,351 @@ function dedupeProvenance(values) {
|
|
|
77867
78191
|
});
|
|
77868
78192
|
}
|
|
77869
78193
|
|
|
78194
|
+
// src/docs.ts
|
|
78195
|
+
var DEFAULT_DOCS_ORIGIN = "https://docs.vapinetwork.ai";
|
|
78196
|
+
var DOCS_URL_ENV = "VAPI_DOCS_URL";
|
|
78197
|
+
var DOCS_RESPONSE_MAX_BYTES = 2 * 1024 * 1024;
|
|
78198
|
+
var SEARCH_TIMEOUT_MS = 15e3;
|
|
78199
|
+
var READ_TIMEOUT_MS = 15e3;
|
|
78200
|
+
var ASK_TIMEOUT_MS = 6e4;
|
|
78201
|
+
var MAX_REDIRECTS = 5;
|
|
78202
|
+
var REDIRECT_STATUSES = /* @__PURE__ */ new Set([301, 302, 303, 307, 308]);
|
|
78203
|
+
var DocsError = class extends Error {
|
|
78204
|
+
constructor(code, message, options) {
|
|
78205
|
+
super(message, options);
|
|
78206
|
+
this.code = code;
|
|
78207
|
+
}
|
|
78208
|
+
code;
|
|
78209
|
+
name = "DocsError";
|
|
78210
|
+
};
|
|
78211
|
+
var publicFetch3 = createPublicFetch({ allowPrivateNetwork: false });
|
|
78212
|
+
function resolveDocsOrigin(env = process.env) {
|
|
78213
|
+
const configured = env[DOCS_URL_ENV]?.trim() || DEFAULT_DOCS_ORIGIN;
|
|
78214
|
+
let url2;
|
|
78215
|
+
try {
|
|
78216
|
+
url2 = new URL(configured);
|
|
78217
|
+
} catch (cause) {
|
|
78218
|
+
throw new DocsError("host_not_allowed", `The configured docs origin is invalid.`, { cause });
|
|
78219
|
+
}
|
|
78220
|
+
if (url2.protocol !== "https:" || url2.username || url2.password || url2.pathname !== "/" || url2.search || url2.hash) {
|
|
78221
|
+
throw new DocsError(
|
|
78222
|
+
"host_not_allowed",
|
|
78223
|
+
"The configured docs origin must be an HTTPS origin without credentials, a path, a query, or a fragment."
|
|
78224
|
+
);
|
|
78225
|
+
}
|
|
78226
|
+
return url2.origin;
|
|
78227
|
+
}
|
|
78228
|
+
async function searchDocs(query, options = {}) {
|
|
78229
|
+
const normalized = nonEmpty(query, "Search query");
|
|
78230
|
+
if (options.limit !== void 0 && (!Number.isSafeInteger(options.limit) || options.limit < 1)) {
|
|
78231
|
+
throw new DocsError("invalid_input", "Search limit must be a positive integer.");
|
|
78232
|
+
}
|
|
78233
|
+
const origin = resolveDocsOrigin(options.env);
|
|
78234
|
+
const { text: body } = await requestText(
|
|
78235
|
+
new URL("/~gitbook/mcp", origin),
|
|
78236
|
+
{
|
|
78237
|
+
method: "POST",
|
|
78238
|
+
headers: {
|
|
78239
|
+
"content-type": "application/json",
|
|
78240
|
+
accept: "application/json, text/event-stream"
|
|
78241
|
+
},
|
|
78242
|
+
body: JSON.stringify({
|
|
78243
|
+
jsonrpc: "2.0",
|
|
78244
|
+
id: 1,
|
|
78245
|
+
method: "tools/call",
|
|
78246
|
+
params: { name: "searchDocumentation", arguments: { query: normalized } }
|
|
78247
|
+
})
|
|
78248
|
+
},
|
|
78249
|
+
{
|
|
78250
|
+
operation: "search",
|
|
78251
|
+
origin,
|
|
78252
|
+
timeoutMs: options.timeoutMs ?? SEARCH_TIMEOUT_MS,
|
|
78253
|
+
fetchImpl: options.fetchImpl
|
|
78254
|
+
}
|
|
78255
|
+
);
|
|
78256
|
+
const payload = parseSearchEnvelope(body);
|
|
78257
|
+
const blocks = searchTextBlocks(payload);
|
|
78258
|
+
const results = blocks.flatMap((block) => {
|
|
78259
|
+
const parsed = parseSearchBlock(block);
|
|
78260
|
+
return parsed === void 0 ? [] : [parsed];
|
|
78261
|
+
});
|
|
78262
|
+
return { results: options.limit === void 0 ? results : results.slice(0, options.limit) };
|
|
78263
|
+
}
|
|
78264
|
+
async function readDocs(pageUrlOrPath, options = {}) {
|
|
78265
|
+
const input2 = nonEmpty(pageUrlOrPath, "Documentation page");
|
|
78266
|
+
const origin = resolveDocsOrigin(options.env);
|
|
78267
|
+
const page = docsPagePath(input2, origin);
|
|
78268
|
+
const requestOptions = {
|
|
78269
|
+
operation: "read",
|
|
78270
|
+
origin,
|
|
78271
|
+
timeoutMs: options.timeoutMs ?? READ_TIMEOUT_MS,
|
|
78272
|
+
fetchImpl: options.fetchImpl
|
|
78273
|
+
};
|
|
78274
|
+
const found = await readFirstMarkdown(page, requestOptions);
|
|
78275
|
+
if (found !== void 0) return found;
|
|
78276
|
+
const { url: canonical } = await requestText(
|
|
78277
|
+
page,
|
|
78278
|
+
{ method: "HEAD" },
|
|
78279
|
+
{ ...requestOptions, notFoundOn404: true }
|
|
78280
|
+
);
|
|
78281
|
+
if (canonical.pathname !== page.pathname) {
|
|
78282
|
+
const moved = await readFirstMarkdown(canonical, requestOptions);
|
|
78283
|
+
if (moved !== void 0) return moved;
|
|
78284
|
+
}
|
|
78285
|
+
throw new DocsError("not_found", `Documentation page not found: ${page.href}`);
|
|
78286
|
+
}
|
|
78287
|
+
async function readFirstMarkdown(page, options) {
|
|
78288
|
+
const path = page.pathname.replace(/\/+$/u, "");
|
|
78289
|
+
const candidates = path ? [`${path}.md`, `${path}/readme.md`] : ["/readme.md"];
|
|
78290
|
+
for (const pathname of candidates) {
|
|
78291
|
+
const candidate = new URL(page);
|
|
78292
|
+
candidate.pathname = pathname;
|
|
78293
|
+
try {
|
|
78294
|
+
const { text: markdown, url: url2 } = await requestText(
|
|
78295
|
+
candidate,
|
|
78296
|
+
{ method: "GET", headers: { accept: "text/markdown" } },
|
|
78297
|
+
{ ...options, notFoundOn404: true }
|
|
78298
|
+
);
|
|
78299
|
+
if (!markdown.trimStart().startsWith("# Page Not Found")) {
|
|
78300
|
+
return { url: url2.href, markdown };
|
|
78301
|
+
}
|
|
78302
|
+
} catch (error61) {
|
|
78303
|
+
if (!(error61 instanceof DocsError && error61.code === "not_found")) throw error61;
|
|
78304
|
+
}
|
|
78305
|
+
}
|
|
78306
|
+
return void 0;
|
|
78307
|
+
}
|
|
78308
|
+
async function askDocs(question, options = {}) {
|
|
78309
|
+
const normalized = nonEmpty(question, "Question");
|
|
78310
|
+
const origin = resolveDocsOrigin(options.env);
|
|
78311
|
+
const url2 = new URL("/readme.md", origin);
|
|
78312
|
+
url2.searchParams.set("ask", normalized);
|
|
78313
|
+
const { text: markdown } = await requestText(
|
|
78314
|
+
url2,
|
|
78315
|
+
{ method: "GET", headers: { accept: "text/markdown" } },
|
|
78316
|
+
{
|
|
78317
|
+
operation: "ask",
|
|
78318
|
+
origin,
|
|
78319
|
+
timeoutMs: options.timeoutMs ?? ASK_TIMEOUT_MS,
|
|
78320
|
+
fetchImpl: options.fetchImpl
|
|
78321
|
+
}
|
|
78322
|
+
);
|
|
78323
|
+
return parseAnswer(markdown);
|
|
78324
|
+
}
|
|
78325
|
+
function nonEmpty(value, label) {
|
|
78326
|
+
const normalized = value.trim();
|
|
78327
|
+
if (!normalized) throw new DocsError("invalid_input", `${label} must not be empty.`);
|
|
78328
|
+
return normalized;
|
|
78329
|
+
}
|
|
78330
|
+
function docsPagePath(value, origin) {
|
|
78331
|
+
let url2;
|
|
78332
|
+
try {
|
|
78333
|
+
url2 = new URL(value, `${origin}/`);
|
|
78334
|
+
} catch (cause) {
|
|
78335
|
+
throw new DocsError("invalid_input", "Documentation page must be a docs URL or path.", {
|
|
78336
|
+
cause
|
|
78337
|
+
});
|
|
78338
|
+
}
|
|
78339
|
+
if (url2.origin !== origin || url2.username || url2.password) {
|
|
78340
|
+
throw new DocsError(
|
|
78341
|
+
"host_not_allowed",
|
|
78342
|
+
`Documentation pages must use the configured docs origin ${origin}.`
|
|
78343
|
+
);
|
|
78344
|
+
}
|
|
78345
|
+
url2.search = "";
|
|
78346
|
+
url2.hash = "";
|
|
78347
|
+
url2.pathname = url2.pathname.replace(/\/+$/u, "").replace(/(?:\/readme)?\.md$/iu, "") || "/";
|
|
78348
|
+
return url2;
|
|
78349
|
+
}
|
|
78350
|
+
async function requestText(requestUrl, init, options) {
|
|
78351
|
+
if (!Number.isSafeInteger(options.timeoutMs) || options.timeoutMs < 1) {
|
|
78352
|
+
throw new DocsError("invalid_input", "Documentation request timeout must be positive.");
|
|
78353
|
+
}
|
|
78354
|
+
assertAllowedUrl(requestUrl, options.origin);
|
|
78355
|
+
const controller = new AbortController();
|
|
78356
|
+
const timeoutError = new DocsError(
|
|
78357
|
+
"timeout",
|
|
78358
|
+
`The documentation ${options.operation} request timed out.`
|
|
78359
|
+
);
|
|
78360
|
+
let timer;
|
|
78361
|
+
const timeout = new Promise((_resolve, reject) => {
|
|
78362
|
+
timer = setTimeout(() => {
|
|
78363
|
+
controller.abort(timeoutError);
|
|
78364
|
+
reject(timeoutError);
|
|
78365
|
+
}, options.timeoutMs);
|
|
78366
|
+
});
|
|
78367
|
+
let url2 = requestUrl;
|
|
78368
|
+
try {
|
|
78369
|
+
let response;
|
|
78370
|
+
for (let hops = 0; ; hops += 1) {
|
|
78371
|
+
response = await Promise.race([
|
|
78372
|
+
(options.fetchImpl ?? publicFetch3)(url2, {
|
|
78373
|
+
...init,
|
|
78374
|
+
redirect: "manual",
|
|
78375
|
+
signal: controller.signal
|
|
78376
|
+
}),
|
|
78377
|
+
timeout
|
|
78378
|
+
]);
|
|
78379
|
+
if (response.url) assertAllowedUrl(new URL(response.url), options.origin);
|
|
78380
|
+
const location = response.headers.get("location");
|
|
78381
|
+
if (init.method !== "GET" && init.method !== "HEAD" || !REDIRECT_STATUSES.has(response.status) || !location) {
|
|
78382
|
+
break;
|
|
78383
|
+
}
|
|
78384
|
+
if (hops === MAX_REDIRECTS) {
|
|
78385
|
+
throw new DocsError(
|
|
78386
|
+
"bad_response",
|
|
78387
|
+
`The documentation ${options.operation} request redirected too many times.`
|
|
78388
|
+
);
|
|
78389
|
+
}
|
|
78390
|
+
await response.body?.cancel();
|
|
78391
|
+
const next = new URL(location, url2);
|
|
78392
|
+
assertAllowedUrl(next, options.origin);
|
|
78393
|
+
url2 = next;
|
|
78394
|
+
}
|
|
78395
|
+
if (options.notFoundOn404 && response.status === 404) {
|
|
78396
|
+
throw new DocsError("not_found", `Documentation page not found: ${url2.href}`);
|
|
78397
|
+
}
|
|
78398
|
+
if (!response.ok) {
|
|
78399
|
+
throw new DocsError(
|
|
78400
|
+
"bad_response",
|
|
78401
|
+
`The documentation ${options.operation} request returned HTTP ${response.status}.`
|
|
78402
|
+
);
|
|
78403
|
+
}
|
|
78404
|
+
return { text: await Promise.race([readCappedText(response), timeout]), url: url2 };
|
|
78405
|
+
} catch (error61) {
|
|
78406
|
+
if (error61 instanceof DocsError) throw error61;
|
|
78407
|
+
if (controller.signal.aborted) throw timeoutError;
|
|
78408
|
+
throw new DocsError("bad_response", `The documentation ${options.operation} request failed.`, {
|
|
78409
|
+
cause: error61
|
|
78410
|
+
});
|
|
78411
|
+
} finally {
|
|
78412
|
+
if (timer !== void 0) clearTimeout(timer);
|
|
78413
|
+
}
|
|
78414
|
+
}
|
|
78415
|
+
function assertAllowedUrl(url2, origin) {
|
|
78416
|
+
if (url2.origin !== origin || url2.username || url2.password) {
|
|
78417
|
+
throw new DocsError(
|
|
78418
|
+
"host_not_allowed",
|
|
78419
|
+
`Documentation requests may only contact the configured docs origin ${origin}.`
|
|
78420
|
+
);
|
|
78421
|
+
}
|
|
78422
|
+
}
|
|
78423
|
+
async function readCappedText(response) {
|
|
78424
|
+
const contentLength = response.headers.get("content-length");
|
|
78425
|
+
if (contentLength !== null && Number(contentLength) > DOCS_RESPONSE_MAX_BYTES) {
|
|
78426
|
+
throw responseTooLarge();
|
|
78427
|
+
}
|
|
78428
|
+
if (response.body === null) return "";
|
|
78429
|
+
const reader = response.body.getReader();
|
|
78430
|
+
const chunks = [];
|
|
78431
|
+
let size5 = 0;
|
|
78432
|
+
try {
|
|
78433
|
+
while (true) {
|
|
78434
|
+
const { done, value } = await reader.read();
|
|
78435
|
+
if (done) break;
|
|
78436
|
+
size5 += value.byteLength;
|
|
78437
|
+
if (size5 > DOCS_RESPONSE_MAX_BYTES) {
|
|
78438
|
+
await reader.cancel();
|
|
78439
|
+
throw responseTooLarge();
|
|
78440
|
+
}
|
|
78441
|
+
chunks.push(value);
|
|
78442
|
+
}
|
|
78443
|
+
} finally {
|
|
78444
|
+
reader.releaseLock();
|
|
78445
|
+
}
|
|
78446
|
+
const bytes = new Uint8Array(size5);
|
|
78447
|
+
let offset = 0;
|
|
78448
|
+
for (const chunk of chunks) {
|
|
78449
|
+
bytes.set(chunk, offset);
|
|
78450
|
+
offset += chunk.byteLength;
|
|
78451
|
+
}
|
|
78452
|
+
return new TextDecoder().decode(bytes);
|
|
78453
|
+
}
|
|
78454
|
+
function responseTooLarge() {
|
|
78455
|
+
return new DocsError(
|
|
78456
|
+
"bad_response",
|
|
78457
|
+
`The documentation response exceeded ${DOCS_RESPONSE_MAX_BYTES} bytes.`
|
|
78458
|
+
);
|
|
78459
|
+
}
|
|
78460
|
+
function parseSearchEnvelope(body) {
|
|
78461
|
+
const trimmed = body.trim();
|
|
78462
|
+
if (!trimmed) throw invalidSearchResponse();
|
|
78463
|
+
if (trimmed.startsWith("{")) return parseJson2(trimmed);
|
|
78464
|
+
const records = [];
|
|
78465
|
+
let data = [];
|
|
78466
|
+
for (const line of body.split(/\r?\n/u)) {
|
|
78467
|
+
if (line === "") {
|
|
78468
|
+
if (data.length > 0) records.push(data.join("\n"));
|
|
78469
|
+
data = [];
|
|
78470
|
+
} else if (line.startsWith("data:")) {
|
|
78471
|
+
data.push(line.slice(5).trimStart());
|
|
78472
|
+
}
|
|
78473
|
+
}
|
|
78474
|
+
if (data.length > 0) records.push(data.join("\n"));
|
|
78475
|
+
for (const record2 of records) {
|
|
78476
|
+
try {
|
|
78477
|
+
return JSON.parse(record2);
|
|
78478
|
+
} catch {
|
|
78479
|
+
}
|
|
78480
|
+
}
|
|
78481
|
+
throw invalidSearchResponse();
|
|
78482
|
+
}
|
|
78483
|
+
function parseJson2(value) {
|
|
78484
|
+
try {
|
|
78485
|
+
return JSON.parse(value);
|
|
78486
|
+
} catch (cause) {
|
|
78487
|
+
throw new DocsError("bad_response", "The documentation search response was invalid JSON.", {
|
|
78488
|
+
cause
|
|
78489
|
+
});
|
|
78490
|
+
}
|
|
78491
|
+
}
|
|
78492
|
+
function searchTextBlocks(payload) {
|
|
78493
|
+
const envelope = asRecord(payload);
|
|
78494
|
+
const rpcError = asRecord(envelope?.error);
|
|
78495
|
+
if (rpcError !== void 0) {
|
|
78496
|
+
const message = typeof rpcError.message === "string" ? `: ${rpcError.message}` : "";
|
|
78497
|
+
throw new DocsError("bad_response", `The documentation search returned an error${message}`);
|
|
78498
|
+
}
|
|
78499
|
+
const result = asRecord(envelope?.result);
|
|
78500
|
+
if (!Array.isArray(result?.content)) throw invalidSearchResponse();
|
|
78501
|
+
return result.content.flatMap((item) => {
|
|
78502
|
+
const block = asRecord(item);
|
|
78503
|
+
return block?.type === "text" && typeof block.text === "string" ? [block.text] : [];
|
|
78504
|
+
});
|
|
78505
|
+
}
|
|
78506
|
+
function parseSearchBlock(block) {
|
|
78507
|
+
const match = /^Title:\s*([^\r\n]+)\r?\nLink:\s*([^\r\n]+)\r?\nContent:\s*([\s\S]*)$/u.exec(
|
|
78508
|
+
block.trim()
|
|
78509
|
+
);
|
|
78510
|
+
if (!match) return void 0;
|
|
78511
|
+
const title = match[1].trim();
|
|
78512
|
+
const url2 = match[2].trim();
|
|
78513
|
+
const excerpt = match[3].trim();
|
|
78514
|
+
return title && url2 && excerpt ? { title, url: url2, excerpt } : void 0;
|
|
78515
|
+
}
|
|
78516
|
+
function invalidSearchResponse() {
|
|
78517
|
+
return new DocsError("bad_response", "The documentation search response was invalid.");
|
|
78518
|
+
}
|
|
78519
|
+
function parseAnswer(markdown) {
|
|
78520
|
+
const heading = /^# Sources:\s*$/gmu;
|
|
78521
|
+
const matches = [...markdown.matchAll(heading)];
|
|
78522
|
+
const last = matches.at(-1);
|
|
78523
|
+
if (last?.index === void 0) return { answer: markdown.trimEnd(), sources: [] };
|
|
78524
|
+
const answer = markdown.slice(0, last.index).trimEnd();
|
|
78525
|
+
const sourceText = markdown.slice(last.index + last[0].length).trim();
|
|
78526
|
+
const sources = sourceText.split(/\r?\n/u).flatMap((line) => {
|
|
78527
|
+
const linked = /^\s*(?:[-*]|\d+\.)\s+\[([^\]]+)\]\((https?:\/\/[^)\s]+)\)\s*$/u.exec(line);
|
|
78528
|
+
if (linked) return [{ title: linked[1].trim(), url: linked[2] }];
|
|
78529
|
+
const bare = /^\s*(?:[-*]|\d+\.)\s+(https?:\/\/\S+)\s*$/u.exec(line);
|
|
78530
|
+
if (!bare) return [];
|
|
78531
|
+
return [{ title: bare[1], url: bare[1] }];
|
|
78532
|
+
});
|
|
78533
|
+
return { answer, sources };
|
|
78534
|
+
}
|
|
78535
|
+
function asRecord(value) {
|
|
78536
|
+
return typeof value === "object" && value !== null && !Array.isArray(value) ? value : void 0;
|
|
78537
|
+
}
|
|
78538
|
+
|
|
77870
78539
|
// src/distribute.ts
|
|
77871
78540
|
var DistributeError = class extends Error {
|
|
77872
78541
|
constructor(code, message, movementId) {
|
|
@@ -78425,7 +79094,7 @@ function csvCell(value) {
|
|
|
78425
79094
|
}
|
|
78426
79095
|
|
|
78427
79096
|
// src/swarm-capital.ts
|
|
78428
|
-
import { createHash as
|
|
79097
|
+
import { createHash as createHash3, randomBytes as randomBytes15 } from "node:crypto";
|
|
78429
79098
|
import { readFile as readFile17, unlink as unlink12 } from "node:fs/promises";
|
|
78430
79099
|
import { join as join14 } from "node:path";
|
|
78431
79100
|
var movementIdSchema3 = external_exports.string().regex(/^mv_[A-Za-z0-9_-]{8,128}$/u);
|
|
@@ -78497,7 +79166,7 @@ var resumableSwarmReasons = /* @__PURE__ */ new Set([
|
|
|
78497
79166
|
"sweep"
|
|
78498
79167
|
]);
|
|
78499
79168
|
function treasuryRequestMovementId(swarm, requestId) {
|
|
78500
|
-
const digest =
|
|
79169
|
+
const digest = createHash3("sha256").update(`${swarm}
|
|
78501
79170
|
${requestId}`).digest("hex").slice(0, 24);
|
|
78502
79171
|
return movementIdSchema3.parse(`mv_${digest}`);
|
|
78503
79172
|
}
|
|
@@ -80556,9 +81225,12 @@ export {
|
|
|
80556
81225
|
CEILING_SWEEP_TIMEOUT_MS,
|
|
80557
81226
|
DEFAULT_AGENT_TOOLS,
|
|
80558
81227
|
DEFAULT_ARC_GAS_HEADROOM_ATOMIC,
|
|
81228
|
+
DEFAULT_AUTO_RELEASE_BELOW_USD,
|
|
80559
81229
|
DEFAULT_CEILING_ATOMIC,
|
|
80560
81230
|
DEFAULT_DISCOVERY_URL,
|
|
81231
|
+
DEFAULT_DOCS_ORIGIN,
|
|
80561
81232
|
DEFAULT_MARKETPLACE_DISCOVERY_URL,
|
|
81233
|
+
DEFAULT_MAX_PER_TASK_USD,
|
|
80562
81234
|
DEFAULT_REGISTRY_FALLBACKS,
|
|
80563
81235
|
DEFAULT_REGISTRY_URL,
|
|
80564
81236
|
DEFAULT_SPEND_CAPS,
|
|
@@ -80568,6 +81240,7 @@ export {
|
|
|
80568
81240
|
DISCOVERY_CATEGORIES,
|
|
80569
81241
|
DiscoveryCatalogError,
|
|
80570
81242
|
DistributeError,
|
|
81243
|
+
DocsError,
|
|
80571
81244
|
EIP3009_AUTHORIZATION_STATE_ABI,
|
|
80572
81245
|
EIP3009_AUTHORIZATION_TYPES,
|
|
80573
81246
|
ERC20_ABI,
|
|
@@ -80611,6 +81284,7 @@ export {
|
|
|
80611
81284
|
SpendPolicy,
|
|
80612
81285
|
SwarmError,
|
|
80613
81286
|
SweepGasError,
|
|
81287
|
+
TASKS_CLIENT_VERBS,
|
|
80614
81288
|
TransferError,
|
|
80615
81289
|
USDC_DECIMALS,
|
|
80616
81290
|
VAPI_BUILDER_CODE,
|
|
@@ -80637,6 +81311,7 @@ export {
|
|
|
80637
81311
|
appendReceipt,
|
|
80638
81312
|
appendSearchEvent,
|
|
80639
81313
|
areSamePaymentNetwork,
|
|
81314
|
+
askDocs,
|
|
80640
81315
|
assertMaxPrice,
|
|
80641
81316
|
assertPublicUrl,
|
|
80642
81317
|
assertSIWxChallengeBoundToOrigin,
|
|
@@ -80674,6 +81349,8 @@ export {
|
|
|
80674
81349
|
createRunId,
|
|
80675
81350
|
createSIWxMessage,
|
|
80676
81351
|
createSupportReport,
|
|
81352
|
+
decideFunding,
|
|
81353
|
+
decideRelease,
|
|
80677
81354
|
decodePaymentRequiredHeader,
|
|
80678
81355
|
deleteSwarmFile,
|
|
80679
81356
|
deriveEvmPrivateKey,
|
|
@@ -80694,6 +81371,7 @@ export {
|
|
|
80694
81371
|
encryptPrivateKey,
|
|
80695
81372
|
ensureDeviceName,
|
|
80696
81373
|
entropyToPhrase,
|
|
81374
|
+
escrowFundingDayRemainingAtomic,
|
|
80697
81375
|
executeMovement,
|
|
80698
81376
|
executionModeSchema,
|
|
80699
81377
|
explorerAddressUrl,
|
|
@@ -80778,12 +81456,14 @@ export {
|
|
|
80778
81456
|
phraseToSeed,
|
|
80779
81457
|
pinnedLookup,
|
|
80780
81458
|
planAllocation,
|
|
81459
|
+
prepareDeliveryManifest,
|
|
80781
81460
|
promptForSecret,
|
|
80782
81461
|
protectVault,
|
|
80783
81462
|
provenanceSchema,
|
|
80784
81463
|
readAgentProfile,
|
|
80785
81464
|
readAuditLog,
|
|
80786
81465
|
readDelegationRecord,
|
|
81466
|
+
readDocs,
|
|
80787
81467
|
readKeystoreAddress,
|
|
80788
81468
|
readKeystoreVersion,
|
|
80789
81469
|
readMovement,
|
|
@@ -80813,6 +81493,7 @@ export {
|
|
|
80813
81493
|
roleGrants,
|
|
80814
81494
|
runRefSchema,
|
|
80815
81495
|
scheduleCeilingSweep,
|
|
81496
|
+
searchDocs,
|
|
80816
81497
|
searchServicesResponseSchema,
|
|
80817
81498
|
secretStore,
|
|
80818
81499
|
secretsAllowed,
|
|
@@ -80820,6 +81501,7 @@ export {
|
|
|
80820
81501
|
serviceSummarySchema,
|
|
80821
81502
|
serviceTierSchema,
|
|
80822
81503
|
setupSwarm,
|
|
81504
|
+
sha256Hex,
|
|
80823
81505
|
slugifyDeviceName,
|
|
80824
81506
|
spendCapsForWallet,
|
|
80825
81507
|
spendCapsSchema,
|
|
@@ -80838,6 +81520,7 @@ export {
|
|
|
80838
81520
|
sweepBack,
|
|
80839
81521
|
sweepSolanaUsdc,
|
|
80840
81522
|
sweepTarget,
|
|
81523
|
+
taskReservedAtomic,
|
|
80841
81524
|
transferBetweenAccounts,
|
|
80842
81525
|
treasuryRequestMovementId,
|
|
80843
81526
|
unlockKeystore,
|