@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/CHANGELOG.md +2 -0
- package/README.md +10 -6
- package/dist/toolkit.d.ts +37 -2
- package/dist/toolkit.d.ts.map +1 -1
- package/dist/toolkit.js +1616 -225
- package/dist/toolkit.js.map +1 -1
- package/package.json +2 -1
package/dist/toolkit.js
CHANGED
|
@@ -2,9 +2,10 @@
|
|
|
2
2
|
/**
|
|
3
3
|
* Dominus Node Flowise Toolkit
|
|
4
4
|
*
|
|
5
|
-
* Provides
|
|
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,
|
|
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) +
|
|
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 ||
|
|
390
|
-
|
|
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 =
|
|
400
|
+
this.proxyPort =
|
|
401
|
+
isNaN(portVal) || portVal < 1 || portVal > 65535 ? 8080 : portVal;
|
|
393
402
|
this.timeout = options.timeout || 30000;
|
|
394
|
-
this.agentSecret =
|
|
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_") &&
|
|
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" &&
|
|
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
|
|
607
|
-
|
|
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
|
|
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)
|
|
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({
|
|
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 = [
|
|
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) ||
|
|
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) ||
|
|
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) ||
|
|
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
|
|
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
|
|
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) ||
|
|
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) ||
|
|
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) ||
|
|
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) ||
|
|
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) ||
|
|
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" ||
|
|
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
|
-
//
|
|
1593
|
+
// Tool 26: getProxyStatus
|
|
1418
1594
|
// -----------------------------------------------------------------------
|
|
1419
|
-
|
|
1420
|
-
|
|
1421
|
-
|
|
1422
|
-
|
|
1423
|
-
|
|
1424
|
-
|
|
1425
|
-
|
|
1426
|
-
|
|
1427
|
-
|
|
1428
|
-
|
|
1429
|
-
|
|
1430
|
-
|
|
1431
|
-
|
|
1432
|
-
|
|
1433
|
-
|
|
1434
|
-
|
|
1435
|
-
|
|
1436
|
-
|
|
1437
|
-
|
|
1438
|
-
|
|
1439
|
-
|
|
1440
|
-
|
|
1441
|
-
|
|
1442
|
-
|
|
1443
|
-
|
|
1444
|
-
|
|
1445
|
-
|
|
1446
|
-
|
|
1447
|
-
|
|
1448
|
-
|
|
1449
|
-
|
|
1450
|
-
|
|
1451
|
-
|
|
1452
|
-
|
|
1453
|
-
|
|
1454
|
-
|
|
1455
|
-
|
|
1456
|
-
|
|
1457
|
-
|
|
1458
|
-
|
|
1459
|
-
|
|
1460
|
-
|
|
1461
|
-
|
|
1462
|
-
|
|
1463
|
-
|
|
1464
|
-
|
|
1465
|
-
|
|
1466
|
-
|
|
1467
|
-
|
|
1468
|
-
|
|
1469
|
-
|
|
1470
|
-
|
|
1471
|
-
|
|
1472
|
-
|
|
1473
|
-
|
|
1474
|
-
|
|
1475
|
-
|
|
1476
|
-
|
|
1477
|
-
|
|
1478
|
-
|
|
1479
|
-
|
|
1480
|
-
|
|
1481
|
-
|
|
1482
|
-
|
|
1483
|
-
|
|
1484
|
-
|
|
1485
|
-
|
|
1486
|
-
|
|
1487
|
-
|
|
1488
|
-
|
|
1489
|
-
|
|
1490
|
-
|
|
1491
|
-
|
|
1492
|
-
|
|
1493
|
-
|
|
1494
|
-
|
|
1495
|
-
|
|
1496
|
-
|
|
1497
|
-
|
|
1498
|
-
|
|
1499
|
-
|
|
1500
|
-
|
|
1501
|
-
|
|
1502
|
-
|
|
1503
|
-
}
|
|
1504
|
-
|
|
1505
|
-
|
|
1506
|
-
|
|
1507
|
-
|
|
1508
|
-
|
|
1509
|
-
|
|
1510
|
-
|
|
1511
|
-
|
|
1512
|
-
|
|
1513
|
-
|
|
1514
|
-
|
|
1515
|
-
|
|
1516
|
-
|
|
1517
|
-
|
|
1518
|
-
|
|
1519
|
-
|
|
1520
|
-
|
|
1521
|
-
|
|
1522
|
-
|
|
1523
|
-
|
|
1524
|
-
|
|
1525
|
-
|
|
1526
|
-
|
|
1527
|
-
})
|
|
1528
|
-
|
|
1529
|
-
|
|
1530
|
-
|
|
1531
|
-
|
|
1532
|
-
|
|
1533
|
-
|
|
1534
|
-
|
|
1535
|
-
|
|
1536
|
-
|
|
1537
|
-
|
|
1538
|
-
|
|
1539
|
-
|
|
1540
|
-
|
|
1541
|
-
|
|
1542
|
-
|
|
1543
|
-
|
|
1544
|
-
|
|
1545
|
-
|
|
1546
|
-
|
|
1547
|
-
|
|
1548
|
-
})
|
|
1549
|
-
|
|
1550
|
-
|
|
1551
|
-
|
|
1552
|
-
|
|
1553
|
-
|
|
1554
|
-
|
|
1555
|
-
|
|
1556
|
-
|
|
1557
|
-
|
|
1558
|
-
|
|
1559
|
-
|
|
1560
|
-
|
|
1561
|
-
|
|
1562
|
-
|
|
1563
|
-
|
|
1564
|
-
|
|
1565
|
-
|
|
1566
|
-
|
|
1567
|
-
|
|
1568
|
-
|
|
1569
|
-
|
|
1570
|
-
|
|
1571
|
-
|
|
1572
|
-
|
|
1573
|
-
|
|
1574
|
-
|
|
1575
|
-
|
|
1576
|
-
|
|
1577
|
-
|
|
1578
|
-
|
|
1579
|
-
|
|
1580
|
-
|
|
1581
|
-
|
|
1582
|
-
|
|
1583
|
-
|
|
1584
|
-
|
|
1585
|
-
|
|
1586
|
-
|
|
1587
|
-
|
|
1588
|
-
|
|
1589
|
-
|
|
1590
|
-
|
|
1591
|
-
|
|
1592
|
-
|
|
1593
|
-
|
|
1594
|
-
|
|
1595
|
-
|
|
1596
|
-
|
|
1597
|
-
|
|
1598
|
-
|
|
1599
|
-
|
|
1600
|
-
|
|
1601
|
-
|
|
1602
|
-
|
|
1603
|
-
|
|
1604
|
-
|
|
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
|
|
1613
|
-
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
1734
|
-
|
|
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",
|
|
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
|