@dominusnode/flowise-tools 1.2.0 → 1.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/toolkit.js CHANGED
@@ -2,9 +2,10 @@
2
2
  /**
3
3
  * Dominus Node Flowise Toolkit
4
4
  *
5
- * Provides 26 LangChain-compatible DynamicStructuredTool instances for use
5
+ * Provides 53 LangChain-compatible DynamicStructuredTool instances for use
6
6
  * inside Flowise AI workflows. Covers proxied fetching, wallet management,
7
- * agentic wallets, teams, Stripe/PayPal/crypto top-up, and x402 micropayment info.
7
+ * agentic wallets, teams, Stripe/PayPal/crypto top-up, x402 micropayment info,
8
+ * account management, API key management, plans, sessions, and usage analytics.
8
9
  *
9
10
  * Security:
10
11
  * - Full SSRF protection (private IP blocking, DNS rebinding, Teredo/6to4,
@@ -67,6 +68,7 @@ exports.formatCents = formatCents;
67
68
  // @ts-ignore
68
69
  const tools_1 = require("@langchain/core/tools");
69
70
  const zod_1 = require("zod");
71
+ const crypto = __importStar(require("node:crypto"));
70
72
  const http = __importStar(require("node:http"));
71
73
  const tls = __importStar(require("node:tls"));
72
74
  const dns = __importStar(require("dns/promises"));
@@ -88,7 +90,7 @@ const UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/
88
90
  // ---------------------------------------------------------------------------
89
91
  /** Remove any dn_live_* or dn_test_* tokens from error messages. */
90
92
  function scrubCredentials(msg) {
91
- return msg.replace(/dn_(live|test)_[A-Za-z0-9_-]+/g, "dn_$1_***REDACTED***");
93
+ return msg.replace(/dn_(live|test|proxy)_[A-Za-z0-9_-]+/g, "dn_$1_***REDACTED***");
92
94
  }
93
95
  function safeError(err) {
94
96
  const raw = err instanceof Error ? err.message : String(err);
@@ -100,7 +102,8 @@ function safeError(err) {
100
102
  function truncate(text, max = MAX_RESPONSE_CHARS) {
101
103
  if (text.length <= max)
102
104
  return text;
103
- return text.slice(0, max) + `\n\n... [truncated, ${text.length - max} chars omitted]`;
105
+ return (text.slice(0, max) +
106
+ `\n\n... [truncated, ${text.length - max} chars omitted]`);
104
107
  }
105
108
  // ---------------------------------------------------------------------------
106
109
  // SSRF Protection
@@ -386,12 +389,71 @@ class DominusNodeToolkit {
386
389
  this.token = null;
387
390
  this.tokenExpiresAt = 0;
388
391
  this.apiKey = options.apiKey || process.env.DOMINUSNODE_API_KEY || "";
389
- this.baseUrl = (options.baseUrl || process.env.DOMINUSNODE_BASE_URL || "https://api.dominusnode.com").replace(/\/+$/, "");
390
- this.proxyHost = options.proxyHost || process.env.DOMINUSNODE_PROXY_HOST || "proxy.dominusnode.com";
392
+ this.baseUrl = (options.baseUrl ||
393
+ process.env.DOMINUSNODE_BASE_URL ||
394
+ "https://api.dominusnode.com").replace(/\/+$/, "");
395
+ this.proxyHost =
396
+ options.proxyHost ||
397
+ process.env.DOMINUSNODE_PROXY_HOST ||
398
+ "proxy.dominusnode.com";
391
399
  const portVal = Number(options.proxyPort || process.env.DOMINUSNODE_PROXY_PORT || 8080);
392
- this.proxyPort = isNaN(portVal) || portVal < 1 || portVal > 65535 ? 8080 : portVal;
400
+ this.proxyPort =
401
+ isNaN(portVal) || portVal < 1 || portVal > 65535 ? 8080 : portVal;
393
402
  this.timeout = options.timeout || 30000;
394
- this.agentSecret = options.agentSecret || process.env.DOMINUSNODE_AGENT_SECRET;
403
+ this.agentSecret =
404
+ options.agentSecret || process.env.DOMINUSNODE_AGENT_SECRET;
405
+ }
406
+ // -----------------------------------------------------------------------
407
+ // SHA-256 Proof-of-Work solver
408
+ // -----------------------------------------------------------------------
409
+ static _countLeadingZeroBits(buf) {
410
+ let count = 0;
411
+ for (const byte of buf) {
412
+ if (byte === 0) {
413
+ count += 8;
414
+ continue;
415
+ }
416
+ let mask = 0x80;
417
+ while (mask && !(byte & mask)) {
418
+ count++;
419
+ mask >>= 1;
420
+ }
421
+ break;
422
+ }
423
+ return count;
424
+ }
425
+ async _solvePoW() {
426
+ try {
427
+ const resp = await fetch(`${this.baseUrl}/api/auth/pow/challenge`, {
428
+ method: "POST",
429
+ headers: { "Content-Type": "application/json" },
430
+ redirect: "error",
431
+ });
432
+ if (!resp.ok)
433
+ return null;
434
+ const text = await resp.text();
435
+ if (text.length > 10485760)
436
+ return null;
437
+ const challenge = JSON.parse(text);
438
+ const prefix = challenge.prefix ?? "";
439
+ const difficulty = challenge.difficulty ?? 20;
440
+ const challengeId = challenge.challengeId ?? "";
441
+ if (!prefix || !challengeId)
442
+ return null;
443
+ for (let nonce = 0; nonce < 100000000; nonce++) {
444
+ const hash = crypto
445
+ .createHash("sha256")
446
+ .update(prefix + nonce.toString())
447
+ .digest();
448
+ if (DominusNodeToolkit._countLeadingZeroBits(hash) >= difficulty) {
449
+ return { challengeId, nonce: nonce.toString() };
450
+ }
451
+ }
452
+ return null;
453
+ }
454
+ catch {
455
+ return null;
456
+ }
395
457
  }
396
458
  // -----------------------------------------------------------------------
397
459
  // Authentication
@@ -400,7 +462,8 @@ class DominusNodeToolkit {
400
462
  if (!this.apiKey) {
401
463
  throw new Error("Dominus Node API key is required. Pass apiKey in options or set DOMINUSNODE_API_KEY env var.");
402
464
  }
403
- if (!this.apiKey.startsWith("dn_live_") && !this.apiKey.startsWith("dn_test_")) {
465
+ if (!this.apiKey.startsWith("dn_live_") &&
466
+ !this.apiKey.startsWith("dn_test_")) {
404
467
  throw new Error('DOMINUSNODE_API_KEY must start with "dn_live_" or "dn_test_".');
405
468
  }
406
469
  const authHeaders = {
@@ -521,6 +584,76 @@ class DominusNodeToolkit {
521
584
  }
522
585
  }
523
586
  // -----------------------------------------------------------------------
587
+ // Unauthenticated request helper (register, login, verifyEmail)
588
+ // -----------------------------------------------------------------------
589
+ async _unauthenticatedRequest(method, path, body) {
590
+ const url = `${this.baseUrl}${path}`;
591
+ const headers = {
592
+ "Content-Type": "application/json",
593
+ "User-Agent": "dominusnode-flowise/1.0.0",
594
+ };
595
+ if (this.agentSecret) {
596
+ headers["X-DominusNode-Agent"] = "mcp";
597
+ headers["X-DominusNode-Agent-Secret"] = this.agentSecret;
598
+ }
599
+ const init = {
600
+ method,
601
+ headers,
602
+ signal: AbortSignal.timeout(REQUEST_TIMEOUT_MS),
603
+ redirect: "error",
604
+ };
605
+ if (body) {
606
+ init.body = JSON.stringify(body);
607
+ }
608
+ let res;
609
+ try {
610
+ res = await fetch(url, init);
611
+ }
612
+ catch (err) {
613
+ throw new Error(`Request failed: ${safeError(err)}`);
614
+ }
615
+ let rawText;
616
+ try {
617
+ rawText = await res.text();
618
+ }
619
+ catch {
620
+ rawText = "";
621
+ }
622
+ if (new TextEncoder().encode(rawText).length > MAX_RESPONSE_BYTES) {
623
+ throw new Error("Response too large");
624
+ }
625
+ if (!res.ok) {
626
+ let errorMsg = `Error ${res.status}`;
627
+ if (rawText) {
628
+ try {
629
+ const parsed = JSON.parse(rawText);
630
+ stripDangerousKeys(parsed);
631
+ if (parsed.error) {
632
+ errorMsg = `Error ${res.status}: ${scrubCredentials(String(parsed.error))}`;
633
+ }
634
+ else if (parsed.message) {
635
+ errorMsg = `Error ${res.status}: ${scrubCredentials(String(parsed.message))}`;
636
+ }
637
+ }
638
+ catch {
639
+ errorMsg = `Error ${res.status}: ${scrubCredentials(rawText.slice(0, 200))}`;
640
+ }
641
+ }
642
+ throw new Error(errorMsg);
643
+ }
644
+ if (!rawText || rawText.trim().length === 0) {
645
+ return {};
646
+ }
647
+ try {
648
+ const parsed = JSON.parse(rawText);
649
+ stripDangerousKeys(parsed);
650
+ return parsed;
651
+ }
652
+ catch {
653
+ throw new Error("Failed to parse response as JSON");
654
+ }
655
+ }
656
+ // -----------------------------------------------------------------------
524
657
  // Tool 1: proxiedFetch
525
658
  // -----------------------------------------------------------------------
526
659
  async proxiedFetch(url, method = "GET", country, proxyType = "dc") {
@@ -535,7 +668,9 @@ class DominusNodeToolkit {
535
668
  if (!ALLOWED_METHODS.has(methodUpper)) {
536
669
  return `Error: HTTP method "${methodUpper}" is not allowed. Only GET, HEAD, and OPTIONS are permitted.`;
537
670
  }
538
- if (proxyType !== "dc" && proxyType !== "residential" && proxyType !== "auto") {
671
+ if (proxyType !== "dc" &&
672
+ proxyType !== "residential" &&
673
+ proxyType !== "auto") {
539
674
  return "Error: proxyType must be 'dc', 'residential', or 'auto'.";
540
675
  }
541
676
  const apiKey = this.apiKey;
@@ -603,13 +738,19 @@ class DominusNodeToolkit {
603
738
  return;
604
739
  }
605
740
  const hdr = raw.substring(0, hEnd);
606
- const respBody = raw.substring(hEnd + 4).substring(0, MAX_PROXY_RESPONSE_BYTES);
607
- const sm = hdr.split("\r\n")[0].match(/^HTTP\/\d\.\d\s+(\d+)/);
741
+ const respBody = raw
742
+ .substring(hEnd + 4)
743
+ .substring(0, MAX_PROXY_RESPONSE_BYTES);
744
+ const sm = hdr
745
+ .split("\r\n")[0]
746
+ .match(/^HTTP\/\d\.\d\s+(\d+)/);
608
747
  const hdrs = {};
609
748
  for (const l of hdr.split("\r\n").slice(1)) {
610
749
  const ci = l.indexOf(":");
611
750
  if (ci > 0)
612
- hdrs[l.substring(0, ci).trim().toLowerCase()] = l.substring(ci + 1).trim();
751
+ hdrs[l.substring(0, ci).trim().toLowerCase()] = l
752
+ .substring(ci + 1)
753
+ .trim();
613
754
  }
614
755
  resolve({
615
756
  status: sm ? parseInt(sm[1], 10) : 0,
@@ -660,13 +801,19 @@ class DominusNodeToolkit {
660
801
  return;
661
802
  done = true;
662
803
  clearTimeout(timer);
663
- const respBody = Buffer.concat(chunks).toString("utf-8").substring(0, MAX_PROXY_RESPONSE_BYTES);
804
+ const respBody = Buffer.concat(chunks)
805
+ .toString("utf-8")
806
+ .substring(0, MAX_PROXY_RESPONSE_BYTES);
664
807
  const hdrs = {};
665
808
  for (const [k, v] of Object.entries(res.headers)) {
666
809
  if (v)
667
810
  hdrs[k] = Array.isArray(v) ? v.join(", ") : v;
668
811
  }
669
- resolve({ status: res.statusCode ?? 0, headers: hdrs, body: respBody });
812
+ resolve({
813
+ status: res.statusCode ?? 0,
814
+ headers: hdrs,
815
+ body: respBody,
816
+ });
670
817
  };
671
818
  res.on("end", fin);
672
819
  res.on("close", fin);
@@ -688,7 +835,13 @@ class DominusNodeToolkit {
688
835
  "",
689
836
  ];
690
837
  if (result.headers) {
691
- const showHeaders = ["content-type", "content-length", "server", "x-cache", "cache-control"];
838
+ const showHeaders = [
839
+ "content-type",
840
+ "content-length",
841
+ "server",
842
+ "x-cache",
843
+ "cache-control",
844
+ ];
692
845
  for (const h of showHeaders) {
693
846
  if (result.headers[h]) {
694
847
  lines.push(`${h}: ${result.headers[h]}`);
@@ -828,7 +981,9 @@ class DominusNodeToolkit {
828
981
  spendingLimitCents: limitCents,
829
982
  };
830
983
  if (dailyLimitCents !== undefined && dailyLimitCents !== null) {
831
- if (!Number.isInteger(dailyLimitCents) || dailyLimitCents < 1 || dailyLimitCents > 1000000) {
984
+ if (!Number.isInteger(dailyLimitCents) ||
985
+ dailyLimitCents < 1 ||
986
+ dailyLimitCents > 1000000) {
832
987
  return "Error: daily_limit_cents must be an integer between 1 and 1,000,000.";
833
988
  }
834
989
  body.dailyLimitCents = dailyLimitCents;
@@ -878,7 +1033,9 @@ class DominusNodeToolkit {
878
1033
  body.dailyLimitCents = null;
879
1034
  }
880
1035
  else {
881
- if (!Number.isInteger(dailyLimitCents) || dailyLimitCents < 1 || dailyLimitCents > 1000000) {
1036
+ if (!Number.isInteger(dailyLimitCents) ||
1037
+ dailyLimitCents < 1 ||
1038
+ dailyLimitCents > 1000000) {
882
1039
  return "Error: daily_limit_cents must be an integer between 1 and 1,000,000, or null to remove.";
883
1040
  }
884
1041
  body.dailyLimitCents = dailyLimitCents;
@@ -935,7 +1092,9 @@ class DominusNodeToolkit {
935
1092
  async fundAgenticWallet(walletId, amountCents) {
936
1093
  try {
937
1094
  const wid = validateUuid(walletId, "wallet_id");
938
- if (!Number.isInteger(amountCents) || amountCents < 100 || amountCents > 1000000) {
1095
+ if (!Number.isInteger(amountCents) ||
1096
+ amountCents < 100 ||
1097
+ amountCents > 1000000) {
939
1098
  return "Error: amount_cents must be an integer between 100 ($1) and 1000000 ($10,000).";
940
1099
  }
941
1100
  const data = await this._requestWithRetry("POST", `/api/agent-wallet/${encodeURIComponent(wid)}/fund`, {
@@ -989,7 +1148,9 @@ class DominusNodeToolkit {
989
1148
  }
990
1149
  const lines = [`Agentic Wallets (${wallets.length})`, ""];
991
1150
  for (const w of wallets) {
992
- const limit = w.spendingLimitCents > 0 ? `${formatCents(w.spendingLimitCents)}/tx` : "none";
1151
+ const limit = w.spendingLimitCents > 0
1152
+ ? `${formatCents(w.spendingLimitCents)}/tx`
1153
+ : "none";
993
1154
  lines.push(` ${w.label} (${w.id.slice(0, 8)}...)`);
994
1155
  lines.push(` Balance: ${formatCents(w.balanceCents)} | Limit: ${limit} | Status: ${w.status}`);
995
1156
  lines.push("");
@@ -1015,7 +1176,9 @@ class DominusNodeToolkit {
1015
1176
  const lines = [`Wallet Transactions (${txs.length})`, ""];
1016
1177
  for (const tx of txs) {
1017
1178
  const sign = tx.type === "fund" || tx.type === "refund" ? "+" : "-";
1018
- const session = tx.sessionId ? ` | Session: ${tx.sessionId.slice(0, 8)}` : "";
1179
+ const session = tx.sessionId
1180
+ ? ` | Session: ${tx.sessionId.slice(0, 8)}`
1181
+ : "";
1019
1182
  lines.push(` ${sign}${formatCents(tx.amountCents)} [${tx.type}] ${tx.description}`);
1020
1183
  lines.push(` ${tx.createdAt}${session}`);
1021
1184
  }
@@ -1102,7 +1265,9 @@ class DominusNodeToolkit {
1102
1265
  }
1103
1266
  const body = { name: name.trim() };
1104
1267
  if (maxMembers !== undefined) {
1105
- if (!Number.isInteger(maxMembers) || maxMembers < 1 || maxMembers > 100) {
1268
+ if (!Number.isInteger(maxMembers) ||
1269
+ maxMembers < 1 ||
1270
+ maxMembers > 100) {
1106
1271
  return "Error: max_members must be an integer between 1 and 100.";
1107
1272
  }
1108
1273
  body.maxMembers = maxMembers;
@@ -1184,7 +1349,9 @@ class DominusNodeToolkit {
1184
1349
  async teamFund(teamId, amountCents) {
1185
1350
  try {
1186
1351
  const tid = validateUuid(teamId, "team_id");
1187
- if (!Number.isInteger(amountCents) || amountCents < 100 || amountCents > 1000000) {
1352
+ if (!Number.isInteger(amountCents) ||
1353
+ amountCents < 100 ||
1354
+ amountCents > 1000000) {
1188
1355
  return "Error: amount_cents must be an integer between 100 ($1) and 1000000 ($10,000).";
1189
1356
  }
1190
1357
  const data = await this._requestWithRetry("POST", `/api/teams/${encodeURIComponent(tid)}/wallet/fund`, {
@@ -1280,7 +1447,9 @@ class DominusNodeToolkit {
1280
1447
  body.name = name.trim();
1281
1448
  }
1282
1449
  if (maxMembers !== undefined) {
1283
- if (!Number.isInteger(maxMembers) || maxMembers < 1 || maxMembers > 100) {
1450
+ if (!Number.isInteger(maxMembers) ||
1451
+ maxMembers < 1 ||
1452
+ maxMembers > 100) {
1284
1453
  return "Error: max_members must be an integer between 1 and 100.";
1285
1454
  }
1286
1455
  body.maxMembers = maxMembers;
@@ -1332,7 +1501,9 @@ class DominusNodeToolkit {
1332
1501
  // -----------------------------------------------------------------------
1333
1502
  async topupPaypal(amountCents) {
1334
1503
  try {
1335
- if (!Number.isInteger(amountCents) || amountCents < 500 || amountCents > 100000) {
1504
+ if (!Number.isInteger(amountCents) ||
1505
+ amountCents < 500 ||
1506
+ amountCents > 100000) {
1336
1507
  return "Error: amount_cents must be an integer between 500 ($5) and 100000 ($1,000).";
1337
1508
  }
1338
1509
  const data = await this._requestWithRetry("POST", "/api/wallet/topup/paypal", { amountCents });
@@ -1356,7 +1527,9 @@ class DominusNodeToolkit {
1356
1527
  // -----------------------------------------------------------------------
1357
1528
  async topupStripe(amountCents) {
1358
1529
  try {
1359
- if (!Number.isInteger(amountCents) || amountCents < 500 || amountCents > 100000) {
1530
+ if (!Number.isInteger(amountCents) ||
1531
+ amountCents < 500 ||
1532
+ amountCents > 100000) {
1360
1533
  return "Error: amount_cents must be an integer between 500 ($5) and 100000 ($1,000).";
1361
1534
  }
1362
1535
  const data = await this._requestWithRetry("POST", "/api/wallet/topup/stripe", { amountCents });
@@ -1377,7 +1550,10 @@ class DominusNodeToolkit {
1377
1550
  }
1378
1551
  async topupCrypto(amountUsd, currency) {
1379
1552
  try {
1380
- if (typeof amountUsd !== "number" || !Number.isFinite(amountUsd) || amountUsd < 5 || amountUsd > 1000) {
1553
+ if (typeof amountUsd !== "number" ||
1554
+ !Number.isFinite(amountUsd) ||
1555
+ amountUsd < 5 ||
1556
+ amountUsd > 1000) {
1381
1557
  return "Error: amount_usd must be a number between 5 and 1,000.";
1382
1558
  }
1383
1559
  const cur = String(currency ?? "").toLowerCase();
@@ -1414,194 +1590,920 @@ class DominusNodeToolkit {
1414
1590
  }
1415
1591
  }
1416
1592
  // -----------------------------------------------------------------------
1417
- // getTools() -- returns LangChain DynamicStructuredTool[] for Flowise
1593
+ // Tool 26: getProxyStatus
1418
1594
  // -----------------------------------------------------------------------
1419
- getTools() {
1420
- return [
1421
- // 1. proxied_fetch
1422
- new tools_1.DynamicStructuredTool({
1423
- name: "dominusnode_proxied_fetch",
1424
- description: "Fetch a URL through Dominus Node's rotating proxy network. Supports geo-targeting " +
1425
- "by country. Returns status code, headers, and response body (truncated).",
1426
- schema: zod_1.z.object({
1427
- url: zod_1.z.string().describe("The target URL to fetch (http or https)"),
1428
- method: zod_1.z.enum(["GET", "HEAD", "OPTIONS"]).default("GET").describe("HTTP method"),
1429
- country: zod_1.z.string().optional().describe("ISO 3166-1 alpha-2 country code for geo-targeting (e.g., US, GB, DE)"),
1430
- proxyType: zod_1.z.enum(["dc", "residential"]).default("dc").describe("Proxy pool: dc ($3/GB) or residential ($5/GB)"),
1431
- }),
1432
- func: async ({ url, method, country, proxyType }) => {
1433
- return this.proxiedFetch(url, method, country, proxyType);
1434
- },
1435
- }),
1436
- // 2. check_balance
1437
- new tools_1.DynamicStructuredTool({
1438
- name: "dominusnode_check_balance",
1439
- description: "Check your Dominus Node wallet balance and estimated remaining bandwidth at current pricing.",
1440
- schema: zod_1.z.object({}),
1441
- func: async () => {
1442
- return this.checkBalance();
1443
- },
1444
- }),
1445
- // 3. check_usage
1446
- new tools_1.DynamicStructuredTool({
1447
- name: "dominusnode_check_usage",
1448
- description: "View bandwidth usage statistics for a specified time period. Shows total bytes, cost, and request count.",
1449
- schema: zod_1.z.object({
1450
- days: zod_1.z.number().min(1).max(365).default(30).describe("Number of days to look back (1-365)"),
1451
- }),
1452
- func: async ({ days }) => {
1453
- return this.checkUsage(days);
1454
- },
1455
- }),
1456
- // 4. get_proxy_config
1457
- new tools_1.DynamicStructuredTool({
1458
- name: "dominusnode_get_proxy_config",
1459
- description: "Get available proxy pools, pricing, supported countries, and endpoint configuration.",
1460
- schema: zod_1.z.object({}),
1461
- func: async () => {
1462
- return this.getProxyConfig();
1463
- },
1464
- }),
1465
- // 5. list_sessions
1466
- new tools_1.DynamicStructuredTool({
1467
- name: "dominusnode_list_sessions",
1468
- description: "List all active proxy sessions showing target hosts, bandwidth used, and status.",
1469
- schema: zod_1.z.object({}),
1470
- func: async () => {
1471
- return this.listSessions();
1472
- },
1473
- }),
1474
- // 6. create_agentic_wallet
1475
- new tools_1.DynamicStructuredTool({
1476
- name: "dominusnode_create_agentic_wallet",
1477
- description: "Create a server-side custodial agentic wallet for autonomous proxy billing. " +
1478
- "Set a spending limit per transaction for safety. Optionally set a daily budget cap and domain allowlist.",
1479
- schema: zod_1.z.object({
1480
- label: zod_1.z.string().min(1).max(100).describe('Label for this wallet (e.g., "scraper-bot")'),
1481
- spendingLimitCents: zod_1.z
1482
- .number()
1483
- .int()
1484
- .min(0)
1485
- .max(1000000)
1486
- .default(10000)
1487
- .describe("Max spend per transaction in cents (0 = no limit, default $100)"),
1488
- dailyLimitCents: zod_1.z
1489
- .number()
1490
- .int()
1491
- .positive()
1492
- .max(1000000)
1493
- .optional()
1494
- .describe("Optional daily budget cap in cents (max 1,000,000 = $10,000)"),
1495
- allowedDomains: zod_1.z
1496
- .array(zod_1.z.string().max(253))
1497
- .max(100)
1498
- .optional()
1499
- .describe("Optional list of allowed domains for proxy access (max 100 entries)"),
1500
- }),
1501
- func: async ({ label, spendingLimitCents, dailyLimitCents, allowedDomains }) => {
1502
- return this.createAgenticWallet(label, spendingLimitCents, dailyLimitCents, allowedDomains);
1503
- },
1504
- }),
1505
- // 7. fund_agentic_wallet
1506
- new tools_1.DynamicStructuredTool({
1507
- name: "dominusnode_fund_agentic_wallet",
1508
- description: "Transfer funds from your main wallet to an agentic wallet. Min $1, max $10,000.",
1509
- schema: zod_1.z.object({
1510
- walletId: zod_1.z.string().uuid().describe("Agentic wallet ID (UUID)"),
1511
- amountCents: zod_1.z.number().int().min(100).max(1000000).describe("Amount in cents to transfer"),
1512
- }),
1513
- func: async ({ walletId, amountCents }) => {
1514
- return this.fundAgenticWallet(walletId, amountCents);
1515
- },
1516
- }),
1517
- // 8. agentic_wallet_balance
1518
- new tools_1.DynamicStructuredTool({
1519
- name: "dominusnode_agentic_wallet_balance",
1520
- description: "Check the balance and details of an agentic wallet.",
1521
- schema: zod_1.z.object({
1522
- walletId: zod_1.z.string().uuid().describe("Agentic wallet ID (UUID)"),
1523
- }),
1524
- func: async ({ walletId }) => {
1525
- return this.agenticWalletBalance(walletId);
1526
- },
1527
- }),
1528
- // 9. list_agentic_wallets
1529
- new tools_1.DynamicStructuredTool({
1530
- name: "dominusnode_list_agentic_wallets",
1531
- description: "List all your agentic wallets with balances and status.",
1532
- schema: zod_1.z.object({}),
1533
- func: async () => {
1534
- return this.listAgenticWallets();
1535
- },
1536
- }),
1537
- // 10. agentic_transactions
1538
- new tools_1.DynamicStructuredTool({
1539
- name: "dominusnode_agentic_transactions",
1540
- description: "Get transaction history for an agentic wallet.",
1541
- schema: zod_1.z.object({
1542
- walletId: zod_1.z.string().uuid().describe("Agentic wallet ID (UUID)"),
1543
- limit: zod_1.z.number().int().min(1).max(100).default(20).describe("Number of transactions to return"),
1544
- }),
1545
- func: async ({ walletId, limit }) => {
1546
- return this.agenticTransactions(walletId, limit);
1547
- },
1548
- }),
1549
- // 11. freeze_agentic_wallet
1550
- new tools_1.DynamicStructuredTool({
1551
- name: "dominusnode_freeze_agentic_wallet",
1552
- description: "Freeze an agentic wallet to prevent spending. Balance is preserved until unfrozen.",
1553
- schema: zod_1.z.object({
1554
- walletId: zod_1.z.string().uuid().describe("Agentic wallet ID (UUID)"),
1555
- }),
1556
- func: async ({ walletId }) => {
1557
- return this.freezeAgenticWallet(walletId);
1558
- },
1559
- }),
1560
- // 12. unfreeze_agentic_wallet
1561
- new tools_1.DynamicStructuredTool({
1562
- name: "dominusnode_unfreeze_agentic_wallet",
1563
- description: "Unfreeze a previously frozen agentic wallet to re-enable spending.",
1564
- schema: zod_1.z.object({
1565
- walletId: zod_1.z.string().uuid().describe("Agentic wallet ID (UUID)"),
1566
- }),
1567
- func: async ({ walletId }) => {
1568
- return this.unfreezeAgenticWallet(walletId);
1569
- },
1570
- }),
1571
- // 13. delete_agentic_wallet
1572
- new tools_1.DynamicStructuredTool({
1573
- name: "dominusnode_delete_agentic_wallet",
1574
- description: "Delete an agentic wallet. Must be unfrozen first. Remaining balance refunded to main wallet.",
1575
- schema: zod_1.z.object({
1576
- walletId: zod_1.z.string().uuid().describe("Agentic wallet ID (UUID)"),
1577
- }),
1578
- func: async ({ walletId }) => {
1579
- return this.deleteAgenticWallet(walletId);
1580
- },
1581
- }),
1582
- // 13b. update_wallet_policy
1583
- new tools_1.DynamicStructuredTool({
1584
- name: "dominusnode_update_wallet_policy",
1585
- description: "Update spending policy for an agentic wallet. Set or remove daily budget caps and domain restrictions.",
1586
- schema: zod_1.z.object({
1587
- walletId: zod_1.z.string().uuid().describe("Agentic wallet ID (UUID)"),
1588
- dailyLimitCents: zod_1.z
1589
- .number()
1590
- .int()
1591
- .positive()
1592
- .max(1000000)
1593
- .nullable()
1594
- .optional()
1595
- .describe("Daily budget cap in cents (max 1,000,000). Set null to remove."),
1596
- allowedDomains: zod_1.z
1597
- .array(zod_1.z.string().max(253))
1598
- .max(100)
1599
- .nullable()
1600
- .optional()
1601
- .describe("List of allowed domains (max 100). Set null to remove restriction."),
1602
- }),
1603
- func: async ({ walletId, dailyLimitCents, allowedDomains }) => {
1604
- return this.updateWalletPolicy(walletId, dailyLimitCents, allowedDomains);
1595
+ async getProxyStatus() {
1596
+ try {
1597
+ const data = await this._requestWithRetry("GET", "/api/proxy/status");
1598
+ const lines = ["Proxy Status", ""];
1599
+ if (data.status)
1600
+ lines.push(`Status: ${data.status}`);
1601
+ if (data.uptime !== undefined)
1602
+ lines.push(`Uptime: ${data.uptime}`);
1603
+ if (data.activeConnections !== undefined)
1604
+ lines.push(`Active Connections: ${data.activeConnections}`);
1605
+ if (data.providerStatus)
1606
+ lines.push(`Provider Status: ${JSON.stringify(data.providerStatus)}`);
1607
+ if (Object.keys(data).length === 0) {
1608
+ lines.push("No status data available.");
1609
+ }
1610
+ return truncate(lines.join("\n"));
1611
+ }
1612
+ catch (err) {
1613
+ return `Error: ${safeError(err)}`;
1614
+ }
1615
+ }
1616
+ // -----------------------------------------------------------------------
1617
+ // Tool 27: getTransactions
1618
+ // -----------------------------------------------------------------------
1619
+ async getTransactions(limit = 20) {
1620
+ try {
1621
+ const lim = Math.min(Math.max(Math.floor(limit), 1), 100);
1622
+ const data = await this._requestWithRetry("GET", `/api/wallet/transactions?limit=${lim}`);
1623
+ const txs = data.transactions ?? [];
1624
+ if (txs.length === 0) {
1625
+ return "No wallet transactions found.";
1626
+ }
1627
+ const lines = [`Wallet Transactions (${txs.length})`, ""];
1628
+ for (const tx of txs) {
1629
+ const sign = tx.type === "topup" || tx.type === "fund" || tx.type === "refund"
1630
+ ? "+"
1631
+ : "-";
1632
+ lines.push(` ${sign}${formatCents(tx.amountCents)} [${tx.type}] ${tx.description}`);
1633
+ lines.push(` ${tx.createdAt}`);
1634
+ }
1635
+ return truncate(lines.join("\n"));
1636
+ }
1637
+ catch (err) {
1638
+ return `Error: ${safeError(err)}`;
1639
+ }
1640
+ }
1641
+ // -----------------------------------------------------------------------
1642
+ // Tool 28: getForecast
1643
+ // -----------------------------------------------------------------------
1644
+ async getForecast() {
1645
+ try {
1646
+ const data = await this._requestWithRetry("GET", "/api/wallet/forecast");
1647
+ const lines = [
1648
+ "Wallet Balance Forecast",
1649
+ "",
1650
+ `Current Balance: ${formatCents(data.balanceCents ?? 0)}`,
1651
+ `Average Daily Spend: ${formatCents(data.avgDailySpendCents ?? 0)}`,
1652
+ `Estimated Days Remaining: ${data.daysRemaining ?? "N/A"}`,
1653
+ ];
1654
+ if (data.estimatedDepletionDate) {
1655
+ lines.push(`Estimated Depletion Date: ${data.estimatedDepletionDate}`);
1656
+ }
1657
+ return lines.join("\n");
1658
+ }
1659
+ catch (err) {
1660
+ return `Error: ${safeError(err)}`;
1661
+ }
1662
+ }
1663
+ // -----------------------------------------------------------------------
1664
+ // Tool 29: checkPayment
1665
+ // -----------------------------------------------------------------------
1666
+ async checkPayment(invoiceId) {
1667
+ try {
1668
+ if (!invoiceId || invoiceId.trim().length === 0) {
1669
+ return "Error: invoice_id is required.";
1670
+ }
1671
+ if (/[\x00-\x1f\x7f]/.test(invoiceId)) {
1672
+ return "Error: invoice_id contains invalid control characters.";
1673
+ }
1674
+ const data = await this._requestWithRetry("GET", `/api/wallet/topup/crypto/${encodeURIComponent(invoiceId.trim())}/status`);
1675
+ const lines = [
1676
+ "Crypto Payment Status",
1677
+ "",
1678
+ `Invoice ID: ${data.invoiceId ?? invoiceId}`,
1679
+ `Status: ${data.status ?? "unknown"}`,
1680
+ `Amount: $${data.amountUsd ?? "N/A"}`,
1681
+ `Currency: ${data.payCurrency?.toUpperCase() ?? "N/A"}`,
1682
+ ];
1683
+ if (data.paidAt) {
1684
+ lines.push(`Paid At: ${data.paidAt}`);
1685
+ }
1686
+ return lines.join("\n");
1687
+ }
1688
+ catch (err) {
1689
+ return `Error: ${safeError(err)}`;
1690
+ }
1691
+ }
1692
+ // -----------------------------------------------------------------------
1693
+ // Tool 30: getDailyUsage
1694
+ // -----------------------------------------------------------------------
1695
+ async getDailyUsage(days = 7) {
1696
+ try {
1697
+ const d = Math.min(Math.max(Math.floor(days), 1), 365);
1698
+ const data = await this._requestWithRetry("GET", `/api/usage/daily?days=${d}`);
1699
+ const dayEntries = data.days ?? [];
1700
+ if (dayEntries.length === 0) {
1701
+ return "No daily usage data available.";
1702
+ }
1703
+ const lines = [`Daily Usage (last ${d} days)`, ""];
1704
+ for (const day of dayEntries) {
1705
+ lines.push(` ${day.date}: ${formatBytes(day.bytes)} | ${formatCents(day.costCents)} | ${day.requests} reqs`);
1706
+ }
1707
+ return truncate(lines.join("\n"));
1708
+ }
1709
+ catch (err) {
1710
+ return `Error: ${safeError(err)}`;
1711
+ }
1712
+ }
1713
+ // -----------------------------------------------------------------------
1714
+ // Tool 31: getTopHosts
1715
+ // -----------------------------------------------------------------------
1716
+ async getTopHosts(limit = 10) {
1717
+ try {
1718
+ const lim = Math.min(Math.max(Math.floor(limit), 1), 100);
1719
+ const data = await this._requestWithRetry("GET", `/api/usage/top-hosts?limit=${lim}`);
1720
+ const hosts = data.hosts ?? [];
1721
+ if (hosts.length === 0) {
1722
+ return "No top hosts data available.";
1723
+ }
1724
+ const lines = [`Top Hosts by Bandwidth (${hosts.length})`, ""];
1725
+ for (const h of hosts) {
1726
+ lines.push(` ${h.host}: ${formatBytes(h.bytes)} | ${formatCents(h.costCents)} | ${h.requests} reqs`);
1727
+ }
1728
+ return truncate(lines.join("\n"));
1729
+ }
1730
+ catch (err) {
1731
+ return `Error: ${safeError(err)}`;
1732
+ }
1733
+ }
1734
+ // -----------------------------------------------------------------------
1735
+ // Tool 32: register (unauthenticated)
1736
+ // -----------------------------------------------------------------------
1737
+ async register(email, password) {
1738
+ try {
1739
+ if (!email || !/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email)) {
1740
+ return "Error: a valid email address is required.";
1741
+ }
1742
+ if (!password || password.length < 8 || password.length > 128) {
1743
+ return "Error: password must be between 8 and 128 characters.";
1744
+ }
1745
+ // Solve PoW for CAPTCHA-free registration
1746
+ const pow = await this._solvePoW();
1747
+ const regBody = { email, password };
1748
+ if (pow)
1749
+ regBody.pow = pow;
1750
+ const data = await this._unauthenticatedRequest("POST", "/api/auth/register", regBody);
1751
+ return [
1752
+ "Account Created",
1753
+ "",
1754
+ `User ID: ${data.user?.id ?? "N/A"}`,
1755
+ `Email: ${data.user?.email ?? email}`,
1756
+ "",
1757
+ "Verify your email to unlock financial features.",
1758
+ "MCP agents are auto-verified via agent headers.",
1759
+ ].join("\n");
1760
+ }
1761
+ catch (err) {
1762
+ return `Error: ${safeError(err)}`;
1763
+ }
1764
+ }
1765
+ // -----------------------------------------------------------------------
1766
+ // Tool 33: login (unauthenticated)
1767
+ // -----------------------------------------------------------------------
1768
+ async login(email, password) {
1769
+ try {
1770
+ if (!email || !/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email)) {
1771
+ return "Error: a valid email address is required.";
1772
+ }
1773
+ if (!password || password.length < 1) {
1774
+ return "Error: password is required.";
1775
+ }
1776
+ const data = await this._unauthenticatedRequest("POST", "/api/auth/login", { email, password });
1777
+ if (data.mfaRequired) {
1778
+ return [
1779
+ "MFA Required",
1780
+ "",
1781
+ `Challenge Token: ${data.challengeToken ?? "N/A"}`,
1782
+ "",
1783
+ "Multi-factor authentication is required. Complete the MFA challenge to proceed.",
1784
+ ].join("\n");
1785
+ }
1786
+ return [
1787
+ "Login Successful",
1788
+ "",
1789
+ "Access and refresh tokens have been issued.",
1790
+ "Use get_account_info to view your account details.",
1791
+ ].join("\n");
1792
+ }
1793
+ catch (err) {
1794
+ return `Error: ${safeError(err)}`;
1795
+ }
1796
+ }
1797
+ // -----------------------------------------------------------------------
1798
+ // Tool 34: getAccountInfo
1799
+ // -----------------------------------------------------------------------
1800
+ async getAccountInfo() {
1801
+ try {
1802
+ const data = await this._requestWithRetry("GET", "/api/auth/me");
1803
+ const user = data.user;
1804
+ return [
1805
+ "Account Information",
1806
+ "",
1807
+ `User ID: ${user?.id ?? "N/A"}`,
1808
+ `Email: ${user?.email ?? "N/A"}`,
1809
+ `Plan: ${user?.plan ?? "N/A"}`,
1810
+ `Email Verified: ${user?.emailVerified ?? false}`,
1811
+ `Status: ${user?.status ?? "N/A"}`,
1812
+ `Created: ${user?.createdAt ?? "N/A"}`,
1813
+ ].join("\n");
1814
+ }
1815
+ catch (err) {
1816
+ return `Error: ${safeError(err)}`;
1817
+ }
1818
+ }
1819
+ // -----------------------------------------------------------------------
1820
+ // Tool 35: verifyEmail (unauthenticated)
1821
+ // -----------------------------------------------------------------------
1822
+ async verifyEmail(token) {
1823
+ try {
1824
+ if (!token || token.trim().length === 0) {
1825
+ return "Error: verification token is required.";
1826
+ }
1827
+ if (/[\x00-\x1f\x7f]/.test(token)) {
1828
+ return "Error: token contains invalid control characters.";
1829
+ }
1830
+ await this._unauthenticatedRequest("POST", "/api/auth/verify-email", {
1831
+ token: token.trim(),
1832
+ });
1833
+ return "Email verified successfully. Financial features are now unlocked.";
1834
+ }
1835
+ catch (err) {
1836
+ return `Error: ${safeError(err)}`;
1837
+ }
1838
+ }
1839
+ // -----------------------------------------------------------------------
1840
+ // Tool 36: resendVerification
1841
+ // -----------------------------------------------------------------------
1842
+ async resendVerification() {
1843
+ try {
1844
+ await this._requestWithRetry("POST", "/api/auth/resend-verification");
1845
+ return "Verification email sent. Check your inbox for the verification link.";
1846
+ }
1847
+ catch (err) {
1848
+ return `Error: ${safeError(err)}`;
1849
+ }
1850
+ }
1851
+ // -----------------------------------------------------------------------
1852
+ // Tool 37: updatePassword
1853
+ // -----------------------------------------------------------------------
1854
+ async updatePassword(currentPassword, newPassword) {
1855
+ try {
1856
+ if (!currentPassword || currentPassword.length < 1) {
1857
+ return "Error: current password is required.";
1858
+ }
1859
+ if (!newPassword || newPassword.length < 8 || newPassword.length > 128) {
1860
+ return "Error: new password must be between 8 and 128 characters.";
1861
+ }
1862
+ await this._requestWithRetry("POST", "/api/auth/change-password", {
1863
+ currentPassword,
1864
+ newPassword,
1865
+ });
1866
+ return "Password updated successfully.";
1867
+ }
1868
+ catch (err) {
1869
+ return `Error: ${safeError(err)}`;
1870
+ }
1871
+ }
1872
+ // -----------------------------------------------------------------------
1873
+ // Tool 38: listKeys
1874
+ // -----------------------------------------------------------------------
1875
+ async listKeys() {
1876
+ try {
1877
+ const data = await this._requestWithRetry("GET", "/api/keys");
1878
+ const keys = data.keys ?? [];
1879
+ if (keys.length === 0) {
1880
+ return "No API keys found. Use create_key to create one.";
1881
+ }
1882
+ const lines = [`API Keys (${keys.length})`, ""];
1883
+ for (const k of keys) {
1884
+ lines.push(` ${k.label ?? "unlabeled"} (${k.id.slice(0, 8)}...)`);
1885
+ lines.push(` Prefix: ${k.prefix} | Created: ${k.createdAt}`);
1886
+ }
1887
+ return truncate(lines.join("\n"));
1888
+ }
1889
+ catch (err) {
1890
+ return `Error: ${safeError(err)}`;
1891
+ }
1892
+ }
1893
+ // -----------------------------------------------------------------------
1894
+ // Tool 39: createKey
1895
+ // -----------------------------------------------------------------------
1896
+ async createKey(label) {
1897
+ try {
1898
+ if (label !== undefined) {
1899
+ if (label.length === 0 || label.length > 100) {
1900
+ return "Error: label must be 1-100 characters.";
1901
+ }
1902
+ if (/[\x00-\x1f\x7f]/.test(label)) {
1903
+ return "Error: label contains invalid control characters.";
1904
+ }
1905
+ }
1906
+ const body = {};
1907
+ if (label)
1908
+ body.label = label.trim();
1909
+ const data = await this._requestWithRetry("POST", "/api/keys", body);
1910
+ return [
1911
+ "API Key Created",
1912
+ "",
1913
+ `Key ID: ${data.id}`,
1914
+ `API Key: ${data.key}`,
1915
+ `Prefix: ${data.prefix}`,
1916
+ `Label: ${data.label ?? ""}`,
1917
+ `Created: ${data.createdAt}`,
1918
+ "",
1919
+ "IMPORTANT: Save this API key now -- it will not be shown again.",
1920
+ ].join("\n");
1921
+ }
1922
+ catch (err) {
1923
+ return `Error: ${safeError(err)}`;
1924
+ }
1925
+ }
1926
+ // -----------------------------------------------------------------------
1927
+ // Tool 40: revokeKey
1928
+ // -----------------------------------------------------------------------
1929
+ async revokeKey(keyId) {
1930
+ try {
1931
+ const kid = validateUuid(keyId, "key_id");
1932
+ await this._requestWithRetry("DELETE", `/api/keys/${encodeURIComponent(kid)}`);
1933
+ return [
1934
+ "API Key Revoked",
1935
+ "",
1936
+ `Key ID: ${kid}`,
1937
+ "",
1938
+ "The key is now permanently deactivated and cannot be used.",
1939
+ ].join("\n");
1940
+ }
1941
+ catch (err) {
1942
+ return `Error: ${safeError(err)}`;
1943
+ }
1944
+ }
1945
+ // -----------------------------------------------------------------------
1946
+ // Tool 41: getPlan
1947
+ // -----------------------------------------------------------------------
1948
+ async getPlan() {
1949
+ try {
1950
+ const data = await this._requestWithRetry("GET", "/api/plans/user/plan");
1951
+ const lines = [
1952
+ "Current Plan",
1953
+ "",
1954
+ `Plan ID: ${data.id ?? "N/A"}`,
1955
+ `Name: ${data.name ?? "N/A"}`,
1956
+ ];
1957
+ if (data.bandwidthLimitBytes !== undefined) {
1958
+ lines.push(`Bandwidth Limit: ${formatBytes(data.bandwidthLimitBytes)}`);
1959
+ }
1960
+ if (data.pricePerGbCents !== undefined) {
1961
+ lines.push(`Price Per GB: ${formatCents(data.pricePerGbCents)}`);
1962
+ }
1963
+ if (data.features && data.features.length > 0) {
1964
+ lines.push(`Features: ${data.features.join(", ")}`);
1965
+ }
1966
+ return lines.join("\n");
1967
+ }
1968
+ catch (err) {
1969
+ return `Error: ${safeError(err)}`;
1970
+ }
1971
+ }
1972
+ // -----------------------------------------------------------------------
1973
+ // Tool 42: listPlans
1974
+ // -----------------------------------------------------------------------
1975
+ async listPlans() {
1976
+ try {
1977
+ const data = await this._requestWithRetry("GET", "/api/plans");
1978
+ const plans = data.plans ?? [];
1979
+ if (plans.length === 0) {
1980
+ return "No plans available.";
1981
+ }
1982
+ const lines = [`Available Plans (${plans.length})`, ""];
1983
+ for (const p of plans) {
1984
+ lines.push(` ${p.name} (${p.id})`);
1985
+ if (p.bandwidthLimitBytes !== undefined) {
1986
+ lines.push(` Bandwidth: ${formatBytes(p.bandwidthLimitBytes)} | Price: ${formatCents(p.pricePerGbCents)}/GB`);
1987
+ }
1988
+ if (p.features && p.features.length > 0) {
1989
+ lines.push(` Features: ${p.features.join(", ")}`);
1990
+ }
1991
+ lines.push("");
1992
+ }
1993
+ return truncate(lines.join("\n"));
1994
+ }
1995
+ catch (err) {
1996
+ return `Error: ${safeError(err)}`;
1997
+ }
1998
+ }
1999
+ // -----------------------------------------------------------------------
2000
+ // Tool 43: changePlan
2001
+ // -----------------------------------------------------------------------
2002
+ async changePlan(planId) {
2003
+ try {
2004
+ if (!planId || planId.trim().length === 0) {
2005
+ return "Error: plan_id is required.";
2006
+ }
2007
+ if (/[\x00-\x1f\x7f]/.test(planId)) {
2008
+ return "Error: plan_id contains invalid control characters.";
2009
+ }
2010
+ const data = await this._requestWithRetry("PUT", "/api/plans/user/plan", { planId: planId.trim() });
2011
+ return [
2012
+ "Plan Changed",
2013
+ "",
2014
+ `New Plan: ${data.name ?? data.id ?? planId}`,
2015
+ data.message ? `Message: ${data.message}` : "",
2016
+ ]
2017
+ .filter(Boolean)
2018
+ .join("\n");
2019
+ }
2020
+ catch (err) {
2021
+ return `Error: ${safeError(err)}`;
2022
+ }
2023
+ }
2024
+ // -----------------------------------------------------------------------
2025
+ // Tool 44: teamDelete
2026
+ // -----------------------------------------------------------------------
2027
+ async teamDelete(teamId) {
2028
+ try {
2029
+ const tid = validateUuid(teamId, "team_id");
2030
+ await this._requestWithRetry("DELETE", `/api/teams/${encodeURIComponent(tid)}`);
2031
+ return [
2032
+ "Team Deleted",
2033
+ "",
2034
+ `Team ID: ${tid}`,
2035
+ "",
2036
+ "The team has been permanently deleted.",
2037
+ ].join("\n");
2038
+ }
2039
+ catch (err) {
2040
+ return `Error: ${safeError(err)}`;
2041
+ }
2042
+ }
2043
+ // -----------------------------------------------------------------------
2044
+ // Tool 45: teamRevokeKey
2045
+ // -----------------------------------------------------------------------
2046
+ async teamRevokeKey(teamId, keyId) {
2047
+ try {
2048
+ const tid = validateUuid(teamId, "team_id");
2049
+ const kid = validateUuid(keyId, "key_id");
2050
+ await this._requestWithRetry("DELETE", `/api/teams/${encodeURIComponent(tid)}/keys/${encodeURIComponent(kid)}`);
2051
+ return [
2052
+ "Team API Key Revoked",
2053
+ "",
2054
+ `Team ID: ${tid}`,
2055
+ `Key ID: ${kid}`,
2056
+ "",
2057
+ "The team key is now permanently deactivated.",
2058
+ ].join("\n");
2059
+ }
2060
+ catch (err) {
2061
+ return `Error: ${safeError(err)}`;
2062
+ }
2063
+ }
2064
+ // -----------------------------------------------------------------------
2065
+ // Tool 46: teamListKeys
2066
+ // -----------------------------------------------------------------------
2067
+ async teamListKeys(teamId) {
2068
+ try {
2069
+ const tid = validateUuid(teamId, "team_id");
2070
+ const data = await this._requestWithRetry("GET", `/api/teams/${encodeURIComponent(tid)}/keys`);
2071
+ const keys = data.keys ?? [];
2072
+ if (keys.length === 0) {
2073
+ return "No API keys found for this team. Use team_create_key to create one.";
2074
+ }
2075
+ const lines = [`Team API Keys (${keys.length})`, ""];
2076
+ for (const k of keys) {
2077
+ lines.push(` ${k.label ?? "unlabeled"} (${k.id.slice(0, 8)}...)`);
2078
+ lines.push(` Prefix: ${k.prefix} | Created: ${k.createdAt}`);
2079
+ }
2080
+ return truncate(lines.join("\n"));
2081
+ }
2082
+ catch (err) {
2083
+ return `Error: ${safeError(err)}`;
2084
+ }
2085
+ }
2086
+ // -----------------------------------------------------------------------
2087
+ // Tool 47: teamListMembers
2088
+ // -----------------------------------------------------------------------
2089
+ async teamListMembers(teamId) {
2090
+ try {
2091
+ const tid = validateUuid(teamId, "team_id");
2092
+ const data = await this._requestWithRetry("GET", `/api/teams/${encodeURIComponent(tid)}/members`);
2093
+ const members = data.members ?? [];
2094
+ if (members.length === 0) {
2095
+ return "No members found for this team.";
2096
+ }
2097
+ const lines = [`Team Members (${members.length})`, ""];
2098
+ for (const m of members) {
2099
+ lines.push(` ${m.email} -- ${m.role}`);
2100
+ lines.push(` User ID: ${m.userId} | Joined: ${m.joinedAt}`);
2101
+ }
2102
+ return truncate(lines.join("\n"));
2103
+ }
2104
+ catch (err) {
2105
+ return `Error: ${safeError(err)}`;
2106
+ }
2107
+ }
2108
+ // -----------------------------------------------------------------------
2109
+ // Tool 48: teamAddMember
2110
+ // -----------------------------------------------------------------------
2111
+ async teamAddMember(teamId, email, role) {
2112
+ try {
2113
+ const tid = validateUuid(teamId, "team_id");
2114
+ if (!email || !/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email)) {
2115
+ return "Error: a valid email address is required.";
2116
+ }
2117
+ if (role !== undefined && role !== "member" && role !== "admin") {
2118
+ return "Error: role must be 'member' or 'admin'.";
2119
+ }
2120
+ const body = { email };
2121
+ if (role)
2122
+ body.role = role;
2123
+ const data = await this._requestWithRetry("POST", `/api/teams/${encodeURIComponent(tid)}/members`, body);
2124
+ return [
2125
+ "Team Member Added",
2126
+ "",
2127
+ `Team ID: ${tid}`,
2128
+ `Email: ${data.email ?? email}`,
2129
+ `Role: ${data.role ?? role ?? "member"}`,
2130
+ ].join("\n");
2131
+ }
2132
+ catch (err) {
2133
+ return `Error: ${safeError(err)}`;
2134
+ }
2135
+ }
2136
+ // -----------------------------------------------------------------------
2137
+ // Tool 49: teamRemoveMember
2138
+ // -----------------------------------------------------------------------
2139
+ async teamRemoveMember(teamId, userId) {
2140
+ try {
2141
+ const tid = validateUuid(teamId, "team_id");
2142
+ const uid = validateUuid(userId, "user_id");
2143
+ await this._requestWithRetry("DELETE", `/api/teams/${encodeURIComponent(tid)}/members/${encodeURIComponent(uid)}`);
2144
+ return [
2145
+ "Team Member Removed",
2146
+ "",
2147
+ `Team ID: ${tid}`,
2148
+ `User ID: ${uid}`,
2149
+ ].join("\n");
2150
+ }
2151
+ catch (err) {
2152
+ return `Error: ${safeError(err)}`;
2153
+ }
2154
+ }
2155
+ // -----------------------------------------------------------------------
2156
+ // Tool 50: teamInviteMember
2157
+ // -----------------------------------------------------------------------
2158
+ async teamInviteMember(teamId, email, role) {
2159
+ try {
2160
+ const tid = validateUuid(teamId, "team_id");
2161
+ if (!email || !/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email)) {
2162
+ return "Error: a valid email address is required.";
2163
+ }
2164
+ if (role !== undefined && role !== "member" && role !== "admin") {
2165
+ return "Error: role must be 'member' or 'admin'.";
2166
+ }
2167
+ const body = { email };
2168
+ if (role)
2169
+ body.role = role;
2170
+ const data = await this._requestWithRetry("POST", `/api/teams/${encodeURIComponent(tid)}/invites`, body);
2171
+ return [
2172
+ "Team Invitation Sent",
2173
+ "",
2174
+ `Invite ID: ${data.id ?? "N/A"}`,
2175
+ `Team ID: ${tid}`,
2176
+ `Email: ${data.email ?? email}`,
2177
+ `Role: ${data.role ?? role ?? "member"}`,
2178
+ data.expiresAt ? `Expires: ${data.expiresAt}` : "",
2179
+ ]
2180
+ .filter(Boolean)
2181
+ .join("\n");
2182
+ }
2183
+ catch (err) {
2184
+ return `Error: ${safeError(err)}`;
2185
+ }
2186
+ }
2187
+ // -----------------------------------------------------------------------
2188
+ // Tool 51: teamListInvites
2189
+ // -----------------------------------------------------------------------
2190
+ async teamListInvites(teamId) {
2191
+ try {
2192
+ const tid = validateUuid(teamId, "team_id");
2193
+ const data = await this._requestWithRetry("GET", `/api/teams/${encodeURIComponent(tid)}/invites`);
2194
+ const invites = data.invites ?? [];
2195
+ if (invites.length === 0) {
2196
+ return "No pending invitations for this team.";
2197
+ }
2198
+ const lines = [`Team Invitations (${invites.length})`, ""];
2199
+ for (const inv of invites) {
2200
+ lines.push(` ${inv.email} -- ${inv.role} [${inv.status}]`);
2201
+ lines.push(` Invite ID: ${inv.id.slice(0, 8)}... | Created: ${inv.createdAt}`);
2202
+ }
2203
+ return truncate(lines.join("\n"));
2204
+ }
2205
+ catch (err) {
2206
+ return `Error: ${safeError(err)}`;
2207
+ }
2208
+ }
2209
+ // -----------------------------------------------------------------------
2210
+ // Tool 52: teamCancelInvite
2211
+ // -----------------------------------------------------------------------
2212
+ async teamCancelInvite(teamId, inviteId) {
2213
+ try {
2214
+ const tid = validateUuid(teamId, "team_id");
2215
+ const iid = validateUuid(inviteId, "invite_id");
2216
+ await this._requestWithRetry("DELETE", `/api/teams/${encodeURIComponent(tid)}/invites/${encodeURIComponent(iid)}`);
2217
+ return [
2218
+ "Team Invitation Cancelled",
2219
+ "",
2220
+ `Team ID: ${tid}`,
2221
+ `Invite ID: ${iid}`,
2222
+ ].join("\n");
2223
+ }
2224
+ catch (err) {
2225
+ return `Error: ${safeError(err)}`;
2226
+ }
2227
+ }
2228
+ // -----------------------------------------------------------------------
2229
+ // MPP (Machine Payment Protocol) tools
2230
+ // -----------------------------------------------------------------------
2231
+ async mppInfo() {
2232
+ try {
2233
+ const data = await this._requestWithRetry("GET", "/api/mpp/info");
2234
+ return JSON.stringify(data, null, 2);
2235
+ }
2236
+ catch (err) {
2237
+ return `Error: ${safeError(err)}`;
2238
+ }
2239
+ }
2240
+ async payMpp(amountCents, method) {
2241
+ if (!Number.isInteger(amountCents) ||
2242
+ amountCents < 500 ||
2243
+ amountCents > 100000) {
2244
+ return "Error: amount_cents must be an integer between 500 and 100,000";
2245
+ }
2246
+ if (!["tempo", "stripe_spt", "lightning"].includes(method)) {
2247
+ return "Error: method must be one of: tempo, stripe_spt, lightning";
2248
+ }
2249
+ try {
2250
+ const data = await this._requestWithRetry("POST", "/api/mpp/topup", { amountCents, method });
2251
+ return JSON.stringify(data, null, 2);
2252
+ }
2253
+ catch (err) {
2254
+ return `Error: ${safeError(err)}`;
2255
+ }
2256
+ }
2257
+ async mppSessionOpen(maxDepositCents, method, poolType = "dc") {
2258
+ if (!Number.isInteger(maxDepositCents) ||
2259
+ maxDepositCents < 500 ||
2260
+ maxDepositCents > 100000) {
2261
+ return "Error: max_deposit_cents must be an integer between 500 and 100,000";
2262
+ }
2263
+ if (!["tempo", "stripe_spt", "lightning"].includes(method)) {
2264
+ return "Error: method must be one of: tempo, stripe_spt, lightning";
2265
+ }
2266
+ if (!["dc", "residential"].includes(poolType)) {
2267
+ return "Error: pool_type must be dc or residential";
2268
+ }
2269
+ try {
2270
+ const data = await this._requestWithRetry("POST", "/api/mpp/session/open", { maxDepositCents, method, poolType });
2271
+ return JSON.stringify(data, null, 2);
2272
+ }
2273
+ catch (err) {
2274
+ return `Error: ${safeError(err)}`;
2275
+ }
2276
+ }
2277
+ async mppSessionClose(channelId) {
2278
+ if (!channelId) {
2279
+ return "Error: channel_id is required";
2280
+ }
2281
+ try {
2282
+ const data = await this._requestWithRetry("POST", "/api/mpp/session/close", { channelId });
2283
+ return JSON.stringify(data, null, 2);
2284
+ }
2285
+ catch (err) {
2286
+ return `Error: ${safeError(err)}`;
2287
+ }
2288
+ }
2289
+ // -----------------------------------------------------------------------
2290
+ // getTools() -- returns LangChain DynamicStructuredTool[] for Flowise
2291
+ // -----------------------------------------------------------------------
2292
+ getTools() {
2293
+ return [
2294
+ // 1. proxied_fetch
2295
+ new tools_1.DynamicStructuredTool({
2296
+ name: "dominusnode_proxied_fetch",
2297
+ description: "Fetch a URL through Dominus Node's rotating proxy network. Supports geo-targeting " +
2298
+ "by country. Returns status code, headers, and response body (truncated).",
2299
+ schema: zod_1.z.object({
2300
+ url: zod_1.z.string().describe("The target URL to fetch (http or https)"),
2301
+ method: zod_1.z
2302
+ .enum(["GET", "HEAD", "OPTIONS"])
2303
+ .default("GET")
2304
+ .describe("HTTP method"),
2305
+ country: zod_1.z
2306
+ .string()
2307
+ .optional()
2308
+ .describe("ISO 3166-1 alpha-2 country code for geo-targeting (e.g., US, GB, DE)"),
2309
+ proxyType: zod_1.z
2310
+ .enum(["dc", "residential"])
2311
+ .default("dc")
2312
+ .describe("Proxy pool: dc ($3/GB) or residential ($5/GB)"),
2313
+ }),
2314
+ func: async ({ url, method, country, proxyType, }) => {
2315
+ return this.proxiedFetch(url, method, country, proxyType);
2316
+ },
2317
+ }),
2318
+ // 2. check_balance
2319
+ new tools_1.DynamicStructuredTool({
2320
+ name: "dominusnode_check_balance",
2321
+ description: "Check your Dominus Node wallet balance and estimated remaining bandwidth at current pricing.",
2322
+ schema: zod_1.z.object({}),
2323
+ func: async () => {
2324
+ return this.checkBalance();
2325
+ },
2326
+ }),
2327
+ // 3. check_usage
2328
+ new tools_1.DynamicStructuredTool({
2329
+ name: "dominusnode_check_usage",
2330
+ description: "View bandwidth usage statistics for a specified time period. Shows total bytes, cost, and request count.",
2331
+ schema: zod_1.z.object({
2332
+ days: zod_1.z
2333
+ .number()
2334
+ .min(1)
2335
+ .max(365)
2336
+ .default(30)
2337
+ .describe("Number of days to look back (1-365)"),
2338
+ }),
2339
+ func: async ({ days }) => {
2340
+ return this.checkUsage(days);
2341
+ },
2342
+ }),
2343
+ // 4. get_proxy_config
2344
+ new tools_1.DynamicStructuredTool({
2345
+ name: "dominusnode_get_proxy_config",
2346
+ description: "Get available proxy pools, pricing, supported countries, and endpoint configuration.",
2347
+ schema: zod_1.z.object({}),
2348
+ func: async () => {
2349
+ return this.getProxyConfig();
2350
+ },
2351
+ }),
2352
+ // 5. list_sessions
2353
+ new tools_1.DynamicStructuredTool({
2354
+ name: "dominusnode_list_sessions",
2355
+ description: "List all active proxy sessions showing target hosts, bandwidth used, and status.",
2356
+ schema: zod_1.z.object({}),
2357
+ func: async () => {
2358
+ return this.listSessions();
2359
+ },
2360
+ }),
2361
+ // 6. create_agentic_wallet
2362
+ new tools_1.DynamicStructuredTool({
2363
+ name: "dominusnode_create_agentic_wallet",
2364
+ description: "Create a server-side custodial agentic wallet for autonomous proxy billing. " +
2365
+ "Set a spending limit per transaction for safety. Optionally set a daily budget cap and domain allowlist.",
2366
+ schema: zod_1.z.object({
2367
+ label: zod_1.z
2368
+ .string()
2369
+ .min(1)
2370
+ .max(100)
2371
+ .describe('Label for this wallet (e.g., "scraper-bot")'),
2372
+ spendingLimitCents: zod_1.z
2373
+ .number()
2374
+ .int()
2375
+ .min(0)
2376
+ .max(1000000)
2377
+ .default(10000)
2378
+ .describe("Max spend per transaction in cents (0 = no limit, default $100)"),
2379
+ dailyLimitCents: zod_1.z
2380
+ .number()
2381
+ .int()
2382
+ .positive()
2383
+ .max(1000000)
2384
+ .optional()
2385
+ .describe("Optional daily budget cap in cents (max 1,000,000 = $10,000)"),
2386
+ allowedDomains: zod_1.z
2387
+ .array(zod_1.z.string().max(253))
2388
+ .max(100)
2389
+ .optional()
2390
+ .describe("Optional list of allowed domains for proxy access (max 100 entries)"),
2391
+ }),
2392
+ func: async ({ label, spendingLimitCents, dailyLimitCents, allowedDomains, }) => {
2393
+ return this.createAgenticWallet(label, spendingLimitCents, dailyLimitCents, allowedDomains);
2394
+ },
2395
+ }),
2396
+ // 7. fund_agentic_wallet
2397
+ new tools_1.DynamicStructuredTool({
2398
+ name: "dominusnode_fund_agentic_wallet",
2399
+ description: "Transfer funds from your main wallet to an agentic wallet. Min $1, max $10,000.",
2400
+ schema: zod_1.z.object({
2401
+ walletId: zod_1.z.string().uuid().describe("Agentic wallet ID (UUID)"),
2402
+ amountCents: zod_1.z
2403
+ .number()
2404
+ .int()
2405
+ .min(100)
2406
+ .max(1000000)
2407
+ .describe("Amount in cents to transfer"),
2408
+ }),
2409
+ func: async ({ walletId, amountCents }) => {
2410
+ return this.fundAgenticWallet(walletId, amountCents);
2411
+ },
2412
+ }),
2413
+ // 8. agentic_wallet_balance
2414
+ new tools_1.DynamicStructuredTool({
2415
+ name: "dominusnode_agentic_wallet_balance",
2416
+ description: "Check the balance and details of an agentic wallet.",
2417
+ schema: zod_1.z.object({
2418
+ walletId: zod_1.z.string().uuid().describe("Agentic wallet ID (UUID)"),
2419
+ }),
2420
+ func: async ({ walletId }) => {
2421
+ return this.agenticWalletBalance(walletId);
2422
+ },
2423
+ }),
2424
+ // 9. list_agentic_wallets
2425
+ new tools_1.DynamicStructuredTool({
2426
+ name: "dominusnode_list_agentic_wallets",
2427
+ description: "List all your agentic wallets with balances and status.",
2428
+ schema: zod_1.z.object({}),
2429
+ func: async () => {
2430
+ return this.listAgenticWallets();
2431
+ },
2432
+ }),
2433
+ // 10. agentic_transactions
2434
+ new tools_1.DynamicStructuredTool({
2435
+ name: "dominusnode_agentic_transactions",
2436
+ description: "Get transaction history for an agentic wallet.",
2437
+ schema: zod_1.z.object({
2438
+ walletId: zod_1.z.string().uuid().describe("Agentic wallet ID (UUID)"),
2439
+ limit: zod_1.z
2440
+ .number()
2441
+ .int()
2442
+ .min(1)
2443
+ .max(100)
2444
+ .default(20)
2445
+ .describe("Number of transactions to return"),
2446
+ }),
2447
+ func: async ({ walletId, limit }) => {
2448
+ return this.agenticTransactions(walletId, limit);
2449
+ },
2450
+ }),
2451
+ // 11. freeze_agentic_wallet
2452
+ new tools_1.DynamicStructuredTool({
2453
+ name: "dominusnode_freeze_agentic_wallet",
2454
+ description: "Freeze an agentic wallet to prevent spending. Balance is preserved until unfrozen.",
2455
+ schema: zod_1.z.object({
2456
+ walletId: zod_1.z.string().uuid().describe("Agentic wallet ID (UUID)"),
2457
+ }),
2458
+ func: async ({ walletId }) => {
2459
+ return this.freezeAgenticWallet(walletId);
2460
+ },
2461
+ }),
2462
+ // 12. unfreeze_agentic_wallet
2463
+ new tools_1.DynamicStructuredTool({
2464
+ name: "dominusnode_unfreeze_agentic_wallet",
2465
+ description: "Unfreeze a previously frozen agentic wallet to re-enable spending.",
2466
+ schema: zod_1.z.object({
2467
+ walletId: zod_1.z.string().uuid().describe("Agentic wallet ID (UUID)"),
2468
+ }),
2469
+ func: async ({ walletId }) => {
2470
+ return this.unfreezeAgenticWallet(walletId);
2471
+ },
2472
+ }),
2473
+ // 13. delete_agentic_wallet
2474
+ new tools_1.DynamicStructuredTool({
2475
+ name: "dominusnode_delete_agentic_wallet",
2476
+ description: "Delete an agentic wallet. Must be unfrozen first. Remaining balance refunded to main wallet.",
2477
+ schema: zod_1.z.object({
2478
+ walletId: zod_1.z.string().uuid().describe("Agentic wallet ID (UUID)"),
2479
+ }),
2480
+ func: async ({ walletId }) => {
2481
+ return this.deleteAgenticWallet(walletId);
2482
+ },
2483
+ }),
2484
+ // 13b. update_wallet_policy
2485
+ new tools_1.DynamicStructuredTool({
2486
+ name: "dominusnode_update_wallet_policy",
2487
+ description: "Update spending policy for an agentic wallet. Set or remove daily budget caps and domain restrictions.",
2488
+ schema: zod_1.z.object({
2489
+ walletId: zod_1.z.string().uuid().describe("Agentic wallet ID (UUID)"),
2490
+ dailyLimitCents: zod_1.z
2491
+ .number()
2492
+ .int()
2493
+ .positive()
2494
+ .max(1000000)
2495
+ .nullable()
2496
+ .optional()
2497
+ .describe("Daily budget cap in cents (max 1,000,000). Set null to remove."),
2498
+ allowedDomains: zod_1.z
2499
+ .array(zod_1.z.string().max(253))
2500
+ .max(100)
2501
+ .nullable()
2502
+ .optional()
2503
+ .describe("List of allowed domains (max 100). Set null to remove restriction."),
2504
+ }),
2505
+ func: async ({ walletId, dailyLimitCents, allowedDomains, }) => {
2506
+ return this.updateWalletPolicy(walletId, dailyLimitCents, allowedDomains);
1605
2507
  },
1606
2508
  }),
1607
2509
  // 14. create_team
@@ -1609,8 +2511,18 @@ class DominusNodeToolkit {
1609
2511
  name: "dominusnode_create_team",
1610
2512
  description: "Create a new team with shared wallet billing. Teams let multiple users share proxy access.",
1611
2513
  schema: zod_1.z.object({
1612
- name: zod_1.z.string().min(1).max(100).describe("Team name (1-100 characters)"),
1613
- maxMembers: zod_1.z.number().int().min(1).max(100).optional().describe("Maximum team members (1-100, optional)"),
2514
+ name: zod_1.z
2515
+ .string()
2516
+ .min(1)
2517
+ .max(100)
2518
+ .describe("Team name (1-100 characters)"),
2519
+ maxMembers: zod_1.z
2520
+ .number()
2521
+ .int()
2522
+ .min(1)
2523
+ .max(100)
2524
+ .optional()
2525
+ .describe("Maximum team members (1-100, optional)"),
1614
2526
  }),
1615
2527
  func: async ({ name, maxMembers }) => {
1616
2528
  return this.createTeam(name, maxMembers);
@@ -1642,7 +2554,12 @@ class DominusNodeToolkit {
1642
2554
  description: "Transfer funds from your personal wallet to a team wallet. Min $1, max $10,000.",
1643
2555
  schema: zod_1.z.object({
1644
2556
  teamId: zod_1.z.string().uuid().describe("Team ID (UUID)"),
1645
- amountCents: zod_1.z.number().int().min(100).max(1000000).describe("Amount in cents to transfer"),
2557
+ amountCents: zod_1.z
2558
+ .number()
2559
+ .int()
2560
+ .min(100)
2561
+ .max(1000000)
2562
+ .describe("Amount in cents to transfer"),
1646
2563
  }),
1647
2564
  func: async ({ teamId, amountCents }) => {
1648
2565
  return this.teamFund(teamId, amountCents);
@@ -1655,7 +2572,11 @@ class DominusNodeToolkit {
1655
2572
  "The key is shown only once.",
1656
2573
  schema: zod_1.z.object({
1657
2574
  teamId: zod_1.z.string().uuid().describe("Team ID (UUID)"),
1658
- label: zod_1.z.string().min(1).max(100).describe('Label for the API key (e.g., "production")'),
2575
+ label: zod_1.z
2576
+ .string()
2577
+ .min(1)
2578
+ .max(100)
2579
+ .describe('Label for the API key (e.g., "production")'),
1659
2580
  }),
1660
2581
  func: async ({ teamId, label }) => {
1661
2582
  return this.teamCreateKey(teamId, label);
@@ -1667,7 +2588,13 @@ class DominusNodeToolkit {
1667
2588
  description: "Get the team wallet transaction history (funding, usage charges, refunds).",
1668
2589
  schema: zod_1.z.object({
1669
2590
  teamId: zod_1.z.string().uuid().describe("Team ID (UUID)"),
1670
- limit: zod_1.z.number().int().min(1).max(100).default(20).describe("Number of transactions to return"),
2591
+ limit: zod_1.z
2592
+ .number()
2593
+ .int()
2594
+ .min(1)
2595
+ .max(100)
2596
+ .default(20)
2597
+ .describe("Number of transactions to return"),
1671
2598
  }),
1672
2599
  func: async ({ teamId, limit }) => {
1673
2600
  return this.teamUsage(teamId, limit);
@@ -1680,7 +2607,13 @@ class DominusNodeToolkit {
1680
2607
  schema: zod_1.z.object({
1681
2608
  teamId: zod_1.z.string().uuid().describe("Team ID (UUID)"),
1682
2609
  name: zod_1.z.string().min(1).max(100).optional().describe("New team name"),
1683
- maxMembers: zod_1.z.number().int().min(1).max(100).optional().describe("New max member count"),
2610
+ maxMembers: zod_1.z
2611
+ .number()
2612
+ .int()
2613
+ .min(1)
2614
+ .max(100)
2615
+ .optional()
2616
+ .describe("New max member count"),
1684
2617
  }),
1685
2618
  func: async ({ teamId, name, maxMembers }) => {
1686
2619
  return this.updateTeam(teamId, name, maxMembers);
@@ -1705,7 +2638,12 @@ class DominusNodeToolkit {
1705
2638
  description: "Top up your Dominus Node wallet via PayPal. Creates a PayPal order and returns an " +
1706
2639
  "approval URL. Minimum $5, maximum $1,000.",
1707
2640
  schema: zod_1.z.object({
1708
- amountCents: zod_1.z.number().int().min(500).max(100000).describe("Amount in cents to top up (min 500 = $5)"),
2641
+ amountCents: zod_1.z
2642
+ .number()
2643
+ .int()
2644
+ .min(500)
2645
+ .max(100000)
2646
+ .describe("Amount in cents to top up (min 500 = $5)"),
1709
2647
  }),
1710
2648
  func: async ({ amountCents }) => {
1711
2649
  return this.topupPaypal(amountCents);
@@ -1717,7 +2655,12 @@ class DominusNodeToolkit {
1717
2655
  description: "Top up your Dominus Node wallet via Stripe. Creates a Stripe checkout session and returns " +
1718
2656
  "a checkout URL. Minimum $5 (500 cents), maximum $1,000 (100000 cents).",
1719
2657
  schema: zod_1.z.object({
1720
- amountCents: zod_1.z.number().int().min(500).max(100000).describe("Amount in cents to top up (min 500 = $5)"),
2658
+ amountCents: zod_1.z
2659
+ .number()
2660
+ .int()
2661
+ .min(500)
2662
+ .max(100000)
2663
+ .describe("Amount in cents to top up (min 500 = $5)"),
1721
2664
  }),
1722
2665
  func: async ({ amountCents }) => {
1723
2666
  return this.topupStripe(amountCents);
@@ -1730,8 +2673,25 @@ class DominusNodeToolkit {
1730
2673
  "Supports BTC, ETH, LTC, XMR, ZEC, USDC, SOL, USDT, DAI, BNB, LINK. " +
1731
2674
  "Minimum $5, maximum $1,000.",
1732
2675
  schema: zod_1.z.object({
1733
- amountUsd: zod_1.z.number().min(5).max(1000).describe("Amount in USD to top up (5-1000)"),
1734
- currency: zod_1.z.enum(["btc", "eth", "ltc", "xmr", "zec", "usdc", "sol", "usdt", "dai", "bnb", "link"])
2676
+ amountUsd: zod_1.z
2677
+ .number()
2678
+ .min(5)
2679
+ .max(1000)
2680
+ .describe("Amount in USD to top up (5-1000)"),
2681
+ currency: zod_1.z
2682
+ .enum([
2683
+ "btc",
2684
+ "eth",
2685
+ "ltc",
2686
+ "xmr",
2687
+ "zec",
2688
+ "usdc",
2689
+ "sol",
2690
+ "usdt",
2691
+ "dai",
2692
+ "bnb",
2693
+ "link",
2694
+ ])
1735
2695
  .describe("Cryptocurrency to pay with"),
1736
2696
  }),
1737
2697
  func: async ({ amountUsd, currency }) => {
@@ -1748,6 +2708,427 @@ class DominusNodeToolkit {
1748
2708
  return this.x402Info();
1749
2709
  },
1750
2710
  }),
2711
+ // 26. get_proxy_status
2712
+ new tools_1.DynamicStructuredTool({
2713
+ name: "dominusnode_get_proxy_status",
2714
+ description: "Get proxy health and status information including uptime, active connections, and provider status.",
2715
+ schema: zod_1.z.object({}),
2716
+ func: async () => {
2717
+ return this.getProxyStatus();
2718
+ },
2719
+ }),
2720
+ // 27. get_transactions
2721
+ new tools_1.DynamicStructuredTool({
2722
+ name: "dominusnode_get_transactions",
2723
+ description: "Get wallet transaction history including top-ups, usage charges, and refunds.",
2724
+ schema: zod_1.z.object({
2725
+ limit: zod_1.z
2726
+ .number()
2727
+ .int()
2728
+ .min(1)
2729
+ .max(100)
2730
+ .default(20)
2731
+ .describe("Number of transactions to return (1-100)"),
2732
+ }),
2733
+ func: async ({ limit }) => {
2734
+ return this.getTransactions(limit);
2735
+ },
2736
+ }),
2737
+ // 28. get_forecast
2738
+ new tools_1.DynamicStructuredTool({
2739
+ name: "dominusnode_get_forecast",
2740
+ description: "Get a wallet balance forecast based on recent usage patterns. Shows estimated days until balance depletion.",
2741
+ schema: zod_1.z.object({}),
2742
+ func: async () => {
2743
+ return this.getForecast();
2744
+ },
2745
+ }),
2746
+ // 29. check_payment
2747
+ new tools_1.DynamicStructuredTool({
2748
+ name: "dominusnode_check_payment",
2749
+ description: "Check the status of a cryptocurrency payment invoice. Use after creating a crypto top-up.",
2750
+ schema: zod_1.z.object({
2751
+ invoiceId: zod_1.z
2752
+ .string()
2753
+ .min(1)
2754
+ .describe("The invoice ID from the crypto top-up creation"),
2755
+ }),
2756
+ func: async ({ invoiceId }) => {
2757
+ return this.checkPayment(invoiceId);
2758
+ },
2759
+ }),
2760
+ // 30. get_daily_usage
2761
+ new tools_1.DynamicStructuredTool({
2762
+ name: "dominusnode_get_daily_usage",
2763
+ description: "Get daily usage breakdown showing bandwidth, cost, and request count per day.",
2764
+ schema: zod_1.z.object({
2765
+ days: zod_1.z
2766
+ .number()
2767
+ .int()
2768
+ .min(1)
2769
+ .max(365)
2770
+ .default(7)
2771
+ .describe("Number of days to look back (1-365)"),
2772
+ }),
2773
+ func: async ({ days }) => {
2774
+ return this.getDailyUsage(days);
2775
+ },
2776
+ }),
2777
+ // 31. get_top_hosts
2778
+ new tools_1.DynamicStructuredTool({
2779
+ name: "dominusnode_get_top_hosts",
2780
+ description: "Get the top accessed hosts ranked by bandwidth usage. Useful for understanding proxy usage patterns.",
2781
+ schema: zod_1.z.object({
2782
+ limit: zod_1.z
2783
+ .number()
2784
+ .int()
2785
+ .min(1)
2786
+ .max(100)
2787
+ .default(10)
2788
+ .describe("Number of top hosts to return (1-100)"),
2789
+ }),
2790
+ func: async ({ limit }) => {
2791
+ return this.getTopHosts(limit);
2792
+ },
2793
+ }),
2794
+ // 32. register
2795
+ new tools_1.DynamicStructuredTool({
2796
+ name: "dominusnode_register",
2797
+ description: "Register a new Dominus Node account. Returns user info. " +
2798
+ "After registering, verify email or rely on MCP agent auto-verification.",
2799
+ schema: zod_1.z.object({
2800
+ email: zod_1.z
2801
+ .string()
2802
+ .email()
2803
+ .describe("Email address for the new account"),
2804
+ password: zod_1.z
2805
+ .string()
2806
+ .min(8)
2807
+ .max(128)
2808
+ .describe("Password (min 8, max 128 characters)"),
2809
+ }),
2810
+ func: async ({ email, password }) => {
2811
+ return this.register(email, password);
2812
+ },
2813
+ }),
2814
+ // 33. login
2815
+ new tools_1.DynamicStructuredTool({
2816
+ name: "dominusnode_login",
2817
+ description: "Log into an existing Dominus Node account. Returns login status. " +
2818
+ "Detects MFA requirements and surfaces challenge tokens.",
2819
+ schema: zod_1.z.object({
2820
+ email: zod_1.z.string().email().describe("Account email address"),
2821
+ password: zod_1.z.string().min(1).describe("Account password"),
2822
+ }),
2823
+ func: async ({ email, password }) => {
2824
+ return this.login(email, password);
2825
+ },
2826
+ }),
2827
+ // 34. get_account_info
2828
+ new tools_1.DynamicStructuredTool({
2829
+ name: "dominusnode_get_account_info",
2830
+ description: "Get the current authenticated account information including email, plan, verification status, and creation date.",
2831
+ schema: zod_1.z.object({}),
2832
+ func: async () => {
2833
+ return this.getAccountInfo();
2834
+ },
2835
+ }),
2836
+ // 35. verify_email
2837
+ new tools_1.DynamicStructuredTool({
2838
+ name: "dominusnode_verify_email",
2839
+ description: "Verify email address using the verification token sent to email. " +
2840
+ "MCP agents are auto-verified via agent headers.",
2841
+ schema: zod_1.z.object({
2842
+ token: zod_1.z
2843
+ .string()
2844
+ .min(1)
2845
+ .describe("Email verification token from the verification email"),
2846
+ }),
2847
+ func: async ({ token }) => {
2848
+ return this.verifyEmail(token);
2849
+ },
2850
+ }),
2851
+ // 36. resend_verification
2852
+ new tools_1.DynamicStructuredTool({
2853
+ name: "dominusnode_resend_verification",
2854
+ description: "Resend the email verification token to the account's email address.",
2855
+ schema: zod_1.z.object({}),
2856
+ func: async () => {
2857
+ return this.resendVerification();
2858
+ },
2859
+ }),
2860
+ // 37. update_password
2861
+ new tools_1.DynamicStructuredTool({
2862
+ name: "dominusnode_update_password",
2863
+ description: "Change the password for the current Dominus Node account. Requires the current password.",
2864
+ schema: zod_1.z.object({
2865
+ currentPassword: zod_1.z
2866
+ .string()
2867
+ .min(1)
2868
+ .describe("Current account password"),
2869
+ newPassword: zod_1.z
2870
+ .string()
2871
+ .min(8)
2872
+ .max(128)
2873
+ .describe("New password (min 8, max 128 characters)"),
2874
+ }),
2875
+ func: async ({ currentPassword, newPassword }) => {
2876
+ return this.updatePassword(currentPassword, newPassword);
2877
+ },
2878
+ }),
2879
+ // 38. list_keys
2880
+ new tools_1.DynamicStructuredTool({
2881
+ name: "dominusnode_list_keys",
2882
+ description: "List all API keys for the current account. Shows key ID, label, prefix, and creation date.",
2883
+ schema: zod_1.z.object({}),
2884
+ func: async () => {
2885
+ return this.listKeys();
2886
+ },
2887
+ }),
2888
+ // 39. create_key
2889
+ new tools_1.DynamicStructuredTool({
2890
+ name: "dominusnode_create_key",
2891
+ description: "Create a new API key for the current account. The key is shown only once on creation.",
2892
+ schema: zod_1.z.object({
2893
+ label: zod_1.z
2894
+ .string()
2895
+ .min(1)
2896
+ .max(100)
2897
+ .optional()
2898
+ .describe('Optional label for the API key (e.g., "production")'),
2899
+ }),
2900
+ func: async ({ label }) => {
2901
+ return this.createKey(label);
2902
+ },
2903
+ }),
2904
+ // 40. revoke_key
2905
+ new tools_1.DynamicStructuredTool({
2906
+ name: "dominusnode_revoke_key",
2907
+ description: "Revoke (permanently delete) an API key. The key will immediately stop working.",
2908
+ schema: zod_1.z.object({
2909
+ keyId: zod_1.z.string().uuid().describe("UUID of the API key to revoke"),
2910
+ }),
2911
+ func: async ({ keyId }) => {
2912
+ return this.revokeKey(keyId);
2913
+ },
2914
+ }),
2915
+ // 41. get_plan
2916
+ new tools_1.DynamicStructuredTool({
2917
+ name: "dominusnode_get_plan",
2918
+ description: "Get the current user's plan details including bandwidth limits, pricing tier, and features.",
2919
+ schema: zod_1.z.object({}),
2920
+ func: async () => {
2921
+ return this.getPlan();
2922
+ },
2923
+ }),
2924
+ // 42. list_plans
2925
+ new tools_1.DynamicStructuredTool({
2926
+ name: "dominusnode_list_plans",
2927
+ description: "List all available Dominus Node plans with pricing, bandwidth limits, and features.",
2928
+ schema: zod_1.z.object({}),
2929
+ func: async () => {
2930
+ return this.listPlans();
2931
+ },
2932
+ }),
2933
+ // 43. change_plan
2934
+ new tools_1.DynamicStructuredTool({
2935
+ name: "dominusnode_change_plan",
2936
+ description: "Change the current user's plan. Provide the plan ID of the desired plan from list_plans.",
2937
+ schema: zod_1.z.object({
2938
+ planId: zod_1.z.string().min(1).describe("ID of the plan to switch to"),
2939
+ }),
2940
+ func: async ({ planId }) => {
2941
+ return this.changePlan(planId);
2942
+ },
2943
+ }),
2944
+ // 44. team_delete
2945
+ new tools_1.DynamicStructuredTool({
2946
+ name: "dominusnode_team_delete",
2947
+ description: "Delete a team permanently. Requires owner role. All team keys are revoked and members removed.",
2948
+ schema: zod_1.z.object({
2949
+ teamId: zod_1.z.string().uuid().describe("Team ID (UUID) to delete"),
2950
+ }),
2951
+ func: async ({ teamId }) => {
2952
+ return this.teamDelete(teamId);
2953
+ },
2954
+ }),
2955
+ // 45. team_revoke_key
2956
+ new tools_1.DynamicStructuredTool({
2957
+ name: "dominusnode_team_revoke_key",
2958
+ description: "Revoke (delete) a team API key. Requires owner or admin role.",
2959
+ schema: zod_1.z.object({
2960
+ teamId: zod_1.z.string().uuid().describe("Team ID (UUID)"),
2961
+ keyId: zod_1.z.string().uuid().describe("UUID of the team key to revoke"),
2962
+ }),
2963
+ func: async ({ teamId, keyId }) => {
2964
+ return this.teamRevokeKey(teamId, keyId);
2965
+ },
2966
+ }),
2967
+ // 46. team_list_keys
2968
+ new tools_1.DynamicStructuredTool({
2969
+ name: "dominusnode_team_list_keys",
2970
+ description: "List all API keys for a team. Shows key ID, label, prefix, and creation date.",
2971
+ schema: zod_1.z.object({
2972
+ teamId: zod_1.z.string().uuid().describe("Team ID (UUID)"),
2973
+ }),
2974
+ func: async ({ teamId }) => {
2975
+ return this.teamListKeys(teamId);
2976
+ },
2977
+ }),
2978
+ // 47. team_list_members
2979
+ new tools_1.DynamicStructuredTool({
2980
+ name: "dominusnode_team_list_members",
2981
+ description: "List all members of a team with their roles and join dates.",
2982
+ schema: zod_1.z.object({
2983
+ teamId: zod_1.z.string().uuid().describe("Team ID (UUID)"),
2984
+ }),
2985
+ func: async ({ teamId }) => {
2986
+ return this.teamListMembers(teamId);
2987
+ },
2988
+ }),
2989
+ // 48. team_add_member
2990
+ new tools_1.DynamicStructuredTool({
2991
+ name: "dominusnode_team_add_member",
2992
+ description: "Add a member to a team by email address. Optionally specify their role (member or admin).",
2993
+ schema: zod_1.z.object({
2994
+ teamId: zod_1.z.string().uuid().describe("Team ID (UUID)"),
2995
+ email: zod_1.z
2996
+ .string()
2997
+ .email()
2998
+ .describe("Email address of the user to add"),
2999
+ role: zod_1.z
3000
+ .enum(["member", "admin"])
3001
+ .optional()
3002
+ .describe("Role for the new member (default: member)"),
3003
+ }),
3004
+ func: async ({ teamId, email, role }) => {
3005
+ return this.teamAddMember(teamId, email, role);
3006
+ },
3007
+ }),
3008
+ // 49. team_remove_member
3009
+ new tools_1.DynamicStructuredTool({
3010
+ name: "dominusnode_team_remove_member",
3011
+ description: "Remove a member from a team. Requires owner or admin role. Cannot remove the owner.",
3012
+ schema: zod_1.z.object({
3013
+ teamId: zod_1.z.string().uuid().describe("Team ID (UUID)"),
3014
+ userId: zod_1.z
3015
+ .string()
3016
+ .uuid()
3017
+ .describe("User ID (UUID) of the member to remove"),
3018
+ }),
3019
+ func: async ({ teamId, userId }) => {
3020
+ return this.teamRemoveMember(teamId, userId);
3021
+ },
3022
+ }),
3023
+ // 50. team_invite_member
3024
+ new tools_1.DynamicStructuredTool({
3025
+ name: "dominusnode_team_invite_member",
3026
+ description: "Send a team invitation to an email address. Invited users can accept to join the team.",
3027
+ schema: zod_1.z.object({
3028
+ teamId: zod_1.z.string().uuid().describe("Team ID (UUID)"),
3029
+ email: zod_1.z.string().email().describe("Email address to invite"),
3030
+ role: zod_1.z
3031
+ .enum(["member", "admin"])
3032
+ .optional()
3033
+ .describe("Role for the invited member (default: member)"),
3034
+ }),
3035
+ func: async ({ teamId, email, role }) => {
3036
+ return this.teamInviteMember(teamId, email, role);
3037
+ },
3038
+ }),
3039
+ // 51. team_list_invites
3040
+ new tools_1.DynamicStructuredTool({
3041
+ name: "dominusnode_team_list_invites",
3042
+ description: "List all pending invitations for a team. Shows invite ID, email, role, and status.",
3043
+ schema: zod_1.z.object({
3044
+ teamId: zod_1.z.string().uuid().describe("Team ID (UUID)"),
3045
+ }),
3046
+ func: async ({ teamId }) => {
3047
+ return this.teamListInvites(teamId);
3048
+ },
3049
+ }),
3050
+ // 52. team_cancel_invite
3051
+ new tools_1.DynamicStructuredTool({
3052
+ name: "dominusnode_team_cancel_invite",
3053
+ description: "Cancel a pending team invitation. Requires owner or admin role.",
3054
+ schema: zod_1.z.object({
3055
+ teamId: zod_1.z.string().uuid().describe("Team ID (UUID)"),
3056
+ inviteId: zod_1.z
3057
+ .string()
3058
+ .uuid()
3059
+ .describe("UUID of the invitation to cancel"),
3060
+ }),
3061
+ func: async ({ teamId, inviteId }) => {
3062
+ return this.teamCancelInvite(teamId, inviteId);
3063
+ },
3064
+ }),
3065
+ // 53 (MPP). mpp_info
3066
+ new tools_1.DynamicStructuredTool({
3067
+ name: "dominusnode_mpp_info",
3068
+ description: "Get Machine Payment Protocol (MPP) information including enabled status, " +
3069
+ "supported payment methods, pricing, and session limits.",
3070
+ schema: zod_1.z.object({}),
3071
+ func: async () => {
3072
+ return this.mppInfo();
3073
+ },
3074
+ }),
3075
+ // 54 (MPP). pay_mpp
3076
+ new tools_1.DynamicStructuredTool({
3077
+ name: "dominusnode_pay_mpp",
3078
+ description: "Top up wallet via Machine Payment Protocol (MPP). " +
3079
+ "Supports tempo, stripe_spt, and lightning payment methods.",
3080
+ schema: zod_1.z.object({
3081
+ amountCents: zod_1.z
3082
+ .number()
3083
+ .int()
3084
+ .min(500)
3085
+ .max(100000)
3086
+ .describe("Amount in cents to top up (min 500, max 100000)"),
3087
+ method: zod_1.z
3088
+ .enum(["tempo", "stripe_spt", "lightning"])
3089
+ .describe("MPP payment method"),
3090
+ }),
3091
+ func: async ({ amountCents, method }) => {
3092
+ return this.payMpp(amountCents, method);
3093
+ },
3094
+ }),
3095
+ // 55 (MPP). mpp_session_open
3096
+ new tools_1.DynamicStructuredTool({
3097
+ name: "dominusnode_mpp_session_open",
3098
+ description: "Open a pay-as-you-go MPP session. Returns a channelId for metered proxy usage.",
3099
+ schema: zod_1.z.object({
3100
+ maxDepositCents: zod_1.z
3101
+ .number()
3102
+ .int()
3103
+ .min(500)
3104
+ .max(100000)
3105
+ .describe("Maximum deposit in cents"),
3106
+ method: zod_1.z
3107
+ .enum(["tempo", "stripe_spt", "lightning"])
3108
+ .describe("MPP payment method"),
3109
+ poolType: zod_1.z
3110
+ .enum(["dc", "residential"])
3111
+ .default("dc")
3112
+ .describe("Proxy pool type"),
3113
+ }),
3114
+ func: async ({ maxDepositCents, method, poolType, }) => {
3115
+ return this.mppSessionOpen(maxDepositCents, method, poolType);
3116
+ },
3117
+ }),
3118
+ // 56 (MPP). mpp_session_close
3119
+ new tools_1.DynamicStructuredTool({
3120
+ name: "dominusnode_mpp_session_close",
3121
+ description: "Close an MPP pay-as-you-go session. Returns the amount spent and refunded.",
3122
+ schema: zod_1.z.object({
3123
+ channelId: zod_1.z
3124
+ .string()
3125
+ .min(1)
3126
+ .describe("The channelId returned from mpp_session_open"),
3127
+ }),
3128
+ func: async ({ channelId }) => {
3129
+ return this.mppSessionClose(channelId);
3130
+ },
3131
+ }),
1751
3132
  ];
1752
3133
  }
1753
3134
  }
@@ -1756,6 +3137,16 @@ exports.DominusNodeToolkit = DominusNodeToolkit;
1756
3137
  // Tool 24: topupCrypto
1757
3138
  // -----------------------------------------------------------------------
1758
3139
  DominusNodeToolkit.VALID_CRYPTO_CURRENCIES = new Set([
1759
- "btc", "eth", "ltc", "xmr", "zec", "usdc", "sol", "usdt", "dai", "bnb", "link",
3140
+ "btc",
3141
+ "eth",
3142
+ "ltc",
3143
+ "xmr",
3144
+ "zec",
3145
+ "usdc",
3146
+ "sol",
3147
+ "usdt",
3148
+ "dai",
3149
+ "bnb",
3150
+ "link",
1760
3151
  ]);
1761
3152
  //# sourceMappingURL=toolkit.js.map