@dominusnode/mastra-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.d.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * Dominus Node Mastra AI Toolkit
3
3
  *
4
- * Implements 26 tools for interacting with Dominus Node's rotating proxy service
4
+ * Implements 53 tools for interacting with Dominus Node's rotating proxy service
5
5
  * from Mastra AI agents and workflows.
6
6
  *
7
7
  * Uses createTool() from @mastra/core/tools with Zod schemas.
@@ -76,12 +76,20 @@ export declare class DominusNodeToolkit {
76
76
  private apiPost;
77
77
  private apiDelete;
78
78
  private apiPatch;
79
+ private apiPut;
80
+ /**
81
+ * Raw POST/GET for unauthenticated endpoints (register, login, verify-email).
82
+ * Does NOT use ensureAuth(). Includes agent headers if configured.
83
+ */
84
+ private rawRequest;
79
85
  proxiedFetch(url: string, method?: string, country?: string, proxyType?: string): Promise<{
80
86
  status: number;
81
87
  headers: Record<string, string>;
82
88
  body: string;
89
+ bytes: number;
83
90
  pool: string;
84
91
  country: string;
92
+ error?: string;
85
93
  }>;
86
94
  checkBalance(): Promise<{
87
95
  balanceCents: number;
@@ -119,21 +127,46 @@ export declare class DominusNodeToolkit {
119
127
  private static readonly VALID_CRYPTO_CURRENCIES;
120
128
  topupCrypto(amountUsd: number, currency: string): Promise<Record<string, unknown>>;
121
129
  x402Info(): Promise<Record<string, unknown>>;
130
+ getProxyStatus(): Promise<Record<string, unknown>>;
131
+ getTransactions(limit?: number): Promise<Record<string, unknown>>;
132
+ getForecast(): Promise<Record<string, unknown>>;
133
+ checkPayment(invoiceId: string): Promise<Record<string, unknown>>;
134
+ getDailyUsage(days?: number): Promise<Record<string, unknown>>;
135
+ getTopHosts(limit?: number): Promise<Record<string, unknown>>;
136
+ private static readonly EMAIL_RE;
137
+ private static validateEmail;
138
+ private static validatePassword;
139
+ register(email: string, password: string): Promise<Record<string, unknown>>;
140
+ login(email: string, password: string): Promise<Record<string, unknown>>;
141
+ getAccountInfo(): Promise<Record<string, unknown>>;
142
+ verifyEmail(token: string): Promise<Record<string, unknown>>;
143
+ resendVerification(): Promise<Record<string, unknown>>;
144
+ updatePassword(currentPassword: string, newPassword: string): Promise<Record<string, unknown>>;
145
+ listKeys(): Promise<Record<string, unknown>>;
146
+ createKey(label: string): Promise<Record<string, unknown>>;
147
+ revokeKey(keyId: string): Promise<Record<string, unknown>>;
148
+ getPlan(): Promise<Record<string, unknown>>;
149
+ listPlans(): Promise<Record<string, unknown>>;
150
+ changePlan(planId: string): Promise<Record<string, unknown>>;
151
+ teamDelete(teamId: string): Promise<Record<string, unknown>>;
152
+ teamRevokeKey(teamId: string, keyId: string): Promise<Record<string, unknown>>;
153
+ teamListKeys(teamId: string): Promise<Record<string, unknown>>;
154
+ teamListMembers(teamId: string): Promise<Record<string, unknown>>;
155
+ teamAddMember(teamId: string, userId: string, role?: string): Promise<Record<string, unknown>>;
156
+ teamRemoveMember(teamId: string, userId: string): Promise<Record<string, unknown>>;
157
+ teamInviteMember(teamId: string, email: string, role?: string): Promise<Record<string, unknown>>;
158
+ teamListInvites(teamId: string): Promise<Record<string, unknown>>;
159
+ teamCancelInvite(teamId: string, inviteId: string): Promise<Record<string, unknown>>;
122
160
  getTools(): (import("@mastra/core/tools", { with: { "resolution-mode": "import" } }).Tool<{
123
161
  context: any;
124
162
  }, {
125
163
  status: number;
126
164
  headers: Record<string, string>;
127
165
  body: string;
166
+ bytes: number;
128
167
  pool: string;
129
168
  country: string;
130
- } | {
131
- status: number;
132
- headers: {};
133
- body: string;
134
- pool: any;
135
- country: any;
136
- error: string;
169
+ error?: string;
137
170
  }, unknown, unknown, import("@mastra/core/tools", { with: { "resolution-mode": "import" } }).ToolExecutionContext<unknown, unknown, unknown>, "dominusnode_proxied_fetch", unknown> | import("@mastra/core/tools", { with: { "resolution-mode": "import" } }).Tool<unknown, {
138
171
  balanceCents: number;
139
172
  balanceUsd: number;
@@ -263,5 +296,126 @@ export declare class DominusNodeToolkit {
263
296
  }, unknown, unknown, import("@mastra/core/tools", { with: { "resolution-mode": "import" } }).ToolExecutionContext<unknown, unknown, unknown>, "dominusnode_topup_crypto", unknown> | import("@mastra/core/tools", { with: { "resolution-mode": "import" } }).Tool<unknown, {
264
297
  error?: string | undefined;
265
298
  data?: unknown;
266
- }, unknown, unknown, import("@mastra/core/tools", { with: { "resolution-mode": "import" } }).ToolExecutionContext<unknown, unknown, unknown>, "dominusnode_x402_info", unknown>)[];
299
+ }, unknown, unknown, import("@mastra/core/tools", { with: { "resolution-mode": "import" } }).ToolExecutionContext<unknown, unknown, unknown>, "dominusnode_x402_info", unknown> | import("@mastra/core/tools", { with: { "resolution-mode": "import" } }).Tool<unknown, {
300
+ error?: string | undefined;
301
+ data?: unknown;
302
+ }, unknown, unknown, import("@mastra/core/tools", { with: { "resolution-mode": "import" } }).ToolExecutionContext<unknown, unknown, unknown>, "dominusnode_get_proxy_status", unknown> | import("@mastra/core/tools", { with: { "resolution-mode": "import" } }).Tool<{
303
+ context: any;
304
+ }, {
305
+ error?: string | undefined;
306
+ data?: unknown;
307
+ }, unknown, unknown, import("@mastra/core/tools", { with: { "resolution-mode": "import" } }).ToolExecutionContext<unknown, unknown, unknown>, "dominusnode_get_transactions", unknown> | import("@mastra/core/tools", { with: { "resolution-mode": "import" } }).Tool<unknown, {
308
+ error?: string | undefined;
309
+ data?: unknown;
310
+ }, unknown, unknown, import("@mastra/core/tools", { with: { "resolution-mode": "import" } }).ToolExecutionContext<unknown, unknown, unknown>, "dominusnode_get_forecast", unknown> | import("@mastra/core/tools", { with: { "resolution-mode": "import" } }).Tool<{
311
+ context: any;
312
+ }, {
313
+ error?: string | undefined;
314
+ data?: unknown;
315
+ }, unknown, unknown, import("@mastra/core/tools", { with: { "resolution-mode": "import" } }).ToolExecutionContext<unknown, unknown, unknown>, "dominusnode_check_payment", unknown> | import("@mastra/core/tools", { with: { "resolution-mode": "import" } }).Tool<{
316
+ context: any;
317
+ }, {
318
+ error?: string | undefined;
319
+ data?: unknown;
320
+ }, unknown, unknown, import("@mastra/core/tools", { with: { "resolution-mode": "import" } }).ToolExecutionContext<unknown, unknown, unknown>, "dominusnode_get_daily_usage", unknown> | import("@mastra/core/tools", { with: { "resolution-mode": "import" } }).Tool<{
321
+ context: any;
322
+ }, {
323
+ error?: string | undefined;
324
+ data?: unknown;
325
+ }, unknown, unknown, import("@mastra/core/tools", { with: { "resolution-mode": "import" } }).ToolExecutionContext<unknown, unknown, unknown>, "dominusnode_get_top_hosts", unknown> | import("@mastra/core/tools", { with: { "resolution-mode": "import" } }).Tool<{
326
+ context: any;
327
+ }, {
328
+ error?: string | undefined;
329
+ data?: unknown;
330
+ }, unknown, unknown, import("@mastra/core/tools", { with: { "resolution-mode": "import" } }).ToolExecutionContext<unknown, unknown, unknown>, "dominusnode_register", unknown> | import("@mastra/core/tools", { with: { "resolution-mode": "import" } }).Tool<{
331
+ context: any;
332
+ }, {
333
+ error?: string | undefined;
334
+ data?: unknown;
335
+ }, unknown, unknown, import("@mastra/core/tools", { with: { "resolution-mode": "import" } }).ToolExecutionContext<unknown, unknown, unknown>, "dominusnode_login", unknown> | import("@mastra/core/tools", { with: { "resolution-mode": "import" } }).Tool<unknown, {
336
+ error?: string | undefined;
337
+ data?: unknown;
338
+ }, unknown, unknown, import("@mastra/core/tools", { with: { "resolution-mode": "import" } }).ToolExecutionContext<unknown, unknown, unknown>, "dominusnode_get_account_info", unknown> | import("@mastra/core/tools", { with: { "resolution-mode": "import" } }).Tool<{
339
+ context: any;
340
+ }, {
341
+ error?: string | undefined;
342
+ data?: unknown;
343
+ }, unknown, unknown, import("@mastra/core/tools", { with: { "resolution-mode": "import" } }).ToolExecutionContext<unknown, unknown, unknown>, "dominusnode_verify_email", unknown> | import("@mastra/core/tools", { with: { "resolution-mode": "import" } }).Tool<unknown, {
344
+ error?: string | undefined;
345
+ data?: unknown;
346
+ }, unknown, unknown, import("@mastra/core/tools", { with: { "resolution-mode": "import" } }).ToolExecutionContext<unknown, unknown, unknown>, "dominusnode_resend_verification", unknown> | import("@mastra/core/tools", { with: { "resolution-mode": "import" } }).Tool<{
347
+ context: any;
348
+ }, {
349
+ error?: string | undefined;
350
+ data?: unknown;
351
+ }, unknown, unknown, import("@mastra/core/tools", { with: { "resolution-mode": "import" } }).ToolExecutionContext<unknown, unknown, unknown>, "dominusnode_update_password", unknown> | import("@mastra/core/tools", { with: { "resolution-mode": "import" } }).Tool<unknown, {
352
+ error?: string | undefined;
353
+ data?: unknown;
354
+ }, unknown, unknown, import("@mastra/core/tools", { with: { "resolution-mode": "import" } }).ToolExecutionContext<unknown, unknown, unknown>, "dominusnode_list_keys", unknown> | import("@mastra/core/tools", { with: { "resolution-mode": "import" } }).Tool<{
355
+ context: any;
356
+ }, {
357
+ error?: string | undefined;
358
+ data?: unknown;
359
+ }, unknown, unknown, import("@mastra/core/tools", { with: { "resolution-mode": "import" } }).ToolExecutionContext<unknown, unknown, unknown>, "dominusnode_create_key", unknown> | import("@mastra/core/tools", { with: { "resolution-mode": "import" } }).Tool<{
360
+ context: any;
361
+ }, {
362
+ error?: string | undefined;
363
+ data?: unknown;
364
+ }, unknown, unknown, import("@mastra/core/tools", { with: { "resolution-mode": "import" } }).ToolExecutionContext<unknown, unknown, unknown>, "dominusnode_revoke_key", unknown> | import("@mastra/core/tools", { with: { "resolution-mode": "import" } }).Tool<unknown, {
365
+ error?: string | undefined;
366
+ data?: unknown;
367
+ }, unknown, unknown, import("@mastra/core/tools", { with: { "resolution-mode": "import" } }).ToolExecutionContext<unknown, unknown, unknown>, "dominusnode_get_plan", unknown> | import("@mastra/core/tools", { with: { "resolution-mode": "import" } }).Tool<unknown, {
368
+ error?: string | undefined;
369
+ data?: unknown;
370
+ }, unknown, unknown, import("@mastra/core/tools", { with: { "resolution-mode": "import" } }).ToolExecutionContext<unknown, unknown, unknown>, "dominusnode_list_plans", unknown> | import("@mastra/core/tools", { with: { "resolution-mode": "import" } }).Tool<{
371
+ context: any;
372
+ }, {
373
+ error?: string | undefined;
374
+ data?: unknown;
375
+ }, unknown, unknown, import("@mastra/core/tools", { with: { "resolution-mode": "import" } }).ToolExecutionContext<unknown, unknown, unknown>, "dominusnode_change_plan", unknown> | import("@mastra/core/tools", { with: { "resolution-mode": "import" } }).Tool<{
376
+ context: any;
377
+ }, {
378
+ error?: string | undefined;
379
+ data?: unknown;
380
+ }, unknown, unknown, import("@mastra/core/tools", { with: { "resolution-mode": "import" } }).ToolExecutionContext<unknown, unknown, unknown>, "dominusnode_team_delete", unknown> | import("@mastra/core/tools", { with: { "resolution-mode": "import" } }).Tool<{
381
+ context: any;
382
+ }, {
383
+ error?: string | undefined;
384
+ data?: unknown;
385
+ }, unknown, unknown, import("@mastra/core/tools", { with: { "resolution-mode": "import" } }).ToolExecutionContext<unknown, unknown, unknown>, "dominusnode_team_revoke_key", unknown> | import("@mastra/core/tools", { with: { "resolution-mode": "import" } }).Tool<{
386
+ context: any;
387
+ }, {
388
+ error?: string | undefined;
389
+ data?: unknown;
390
+ }, unknown, unknown, import("@mastra/core/tools", { with: { "resolution-mode": "import" } }).ToolExecutionContext<unknown, unknown, unknown>, "dominusnode_team_list_keys", unknown> | import("@mastra/core/tools", { with: { "resolution-mode": "import" } }).Tool<{
391
+ context: any;
392
+ }, {
393
+ error?: string | undefined;
394
+ data?: unknown;
395
+ }, unknown, unknown, import("@mastra/core/tools", { with: { "resolution-mode": "import" } }).ToolExecutionContext<unknown, unknown, unknown>, "dominusnode_team_list_members", unknown> | import("@mastra/core/tools", { with: { "resolution-mode": "import" } }).Tool<{
396
+ context: any;
397
+ }, {
398
+ error?: string | undefined;
399
+ data?: unknown;
400
+ }, unknown, unknown, import("@mastra/core/tools", { with: { "resolution-mode": "import" } }).ToolExecutionContext<unknown, unknown, unknown>, "dominusnode_team_add_member", unknown> | import("@mastra/core/tools", { with: { "resolution-mode": "import" } }).Tool<{
401
+ context: any;
402
+ }, {
403
+ error?: string | undefined;
404
+ data?: unknown;
405
+ }, unknown, unknown, import("@mastra/core/tools", { with: { "resolution-mode": "import" } }).ToolExecutionContext<unknown, unknown, unknown>, "dominusnode_team_remove_member", unknown> | import("@mastra/core/tools", { with: { "resolution-mode": "import" } }).Tool<{
406
+ context: any;
407
+ }, {
408
+ error?: string | undefined;
409
+ data?: unknown;
410
+ }, unknown, unknown, import("@mastra/core/tools", { with: { "resolution-mode": "import" } }).ToolExecutionContext<unknown, unknown, unknown>, "dominusnode_team_invite_member", unknown> | import("@mastra/core/tools", { with: { "resolution-mode": "import" } }).Tool<{
411
+ context: any;
412
+ }, {
413
+ error?: string | undefined;
414
+ data?: unknown;
415
+ }, unknown, unknown, import("@mastra/core/tools", { with: { "resolution-mode": "import" } }).ToolExecutionContext<unknown, unknown, unknown>, "dominusnode_team_list_invites", unknown> | import("@mastra/core/tools", { with: { "resolution-mode": "import" } }).Tool<{
416
+ context: any;
417
+ }, {
418
+ error?: string | undefined;
419
+ data?: unknown;
420
+ }, unknown, unknown, import("@mastra/core/tools", { with: { "resolution-mode": "import" } }).ToolExecutionContext<unknown, unknown, unknown>, "dominusnode_team_cancel_invite", unknown>)[];
267
421
  }
package/dist/toolkit.js CHANGED
@@ -2,7 +2,7 @@
2
2
  /**
3
3
  * Dominus Node Mastra AI Toolkit
4
4
  *
5
- * Implements 26 tools for interacting with Dominus Node's rotating proxy service
5
+ * Implements 53 tools for interacting with Dominus Node's rotating proxy service
6
6
  * from Mastra AI agents and workflows.
7
7
  *
8
8
  * Uses createTool() from @mastra/core/tools with Zod schemas.
@@ -523,54 +523,178 @@ class DominusNodeToolkit {
523
523
  async apiPatch(path, body) {
524
524
  return this.apiRequest("PATCH", path, body);
525
525
  }
526
+ async apiPut(path, body) {
527
+ return this.apiRequest("PUT", path, body);
528
+ }
529
+ /**
530
+ * Raw POST/GET for unauthenticated endpoints (register, login, verify-email).
531
+ * Does NOT use ensureAuth(). Includes agent headers if configured.
532
+ */
533
+ async rawRequest(method, path, body) {
534
+ const url = `${this.baseUrl}${path}`;
535
+ const headers = {
536
+ Accept: "application/json",
537
+ "User-Agent": "dominusnode-mastra/1.0.0",
538
+ };
539
+ if (this.agentSecret) {
540
+ headers["X-DominusNode-Agent"] = "mcp";
541
+ headers["X-DominusNode-Agent-Secret"] = this.agentSecret;
542
+ }
543
+ const init = {
544
+ method,
545
+ headers,
546
+ signal: AbortSignal.timeout(REQUEST_TIMEOUT_MS),
547
+ redirect: "error",
548
+ };
549
+ if (body && (method === "POST" || method === "PUT" || method === "PATCH")) {
550
+ headers["Content-Type"] = "application/json";
551
+ init.body = JSON.stringify(body);
552
+ }
553
+ let res;
554
+ try {
555
+ res = await fetch(url, init);
556
+ }
557
+ catch (err) {
558
+ throw new Error(`API request failed: ${safeError(err)}`);
559
+ }
560
+ let rawText;
561
+ try {
562
+ rawText = await res.text();
563
+ }
564
+ catch {
565
+ rawText = "";
566
+ }
567
+ if (new TextEncoder().encode(rawText).length > MAX_RESPONSE_BYTES) {
568
+ throw new Error("API response too large");
569
+ }
570
+ if (!res.ok) {
571
+ let errorMsg = `API error ${res.status}`;
572
+ if (rawText) {
573
+ try {
574
+ const parsed = JSON.parse(rawText);
575
+ stripDangerousKeys(parsed);
576
+ if (parsed.error) {
577
+ errorMsg = `API error ${res.status}: ${scrubCredentials(String(parsed.error))}`;
578
+ }
579
+ else if (parsed.message) {
580
+ errorMsg = `API error ${res.status}: ${scrubCredentials(String(parsed.message))}`;
581
+ }
582
+ }
583
+ catch {
584
+ errorMsg = `API error ${res.status}: ${scrubCredentials(rawText.slice(0, 200))}`;
585
+ }
586
+ }
587
+ throw new Error(errorMsg);
588
+ }
589
+ if (!rawText || rawText.trim().length === 0) {
590
+ return {};
591
+ }
592
+ try {
593
+ const parsed = JSON.parse(rawText);
594
+ stripDangerousKeys(parsed);
595
+ return parsed;
596
+ }
597
+ catch {
598
+ throw new Error("Failed to parse API response as JSON");
599
+ }
600
+ }
526
601
  // -----------------------------------------------------------------------
527
602
  // Tool implementations
528
603
  // -----------------------------------------------------------------------
529
604
  async proxiedFetch(url, method = "GET", country, proxyType = "dc") {
530
- const parsedUrl = validateTargetUrl(url);
531
- await checkDnsRebinding(parsedUrl.hostname);
532
- const validCountry = validateCountry(country);
533
- const ALLOWED_METHODS = new Set(["GET", "HEAD", "OPTIONS"]);
534
- const methodUpper = method.toUpperCase();
535
- if (!ALLOWED_METHODS.has(methodUpper)) {
536
- throw new Error(`HTTP method "${methodUpper}" is not allowed. Only GET, HEAD, and OPTIONS are permitted.`);
537
- }
538
- const apiKey = this.getApiKey();
539
- const parts = [];
540
- if (proxyType && proxyType !== "auto")
541
- parts.push(proxyType);
542
- if (validCountry)
543
- parts.push(`country-${validCountry.toUpperCase()}`);
544
- const username = parts.length > 0 ? parts.join("-") : "auto";
545
- const proxyAuth = "Basic " + Buffer.from(`${username}:${apiKey}`).toString("base64");
546
- const parsed = new URL(url);
547
- const MAX_RESP = 1_048_576; // 1MB
548
- const result = await new Promise((resolve, reject) => {
549
- const timer = setTimeout(() => reject(new Error("Proxy request timed out")), REQUEST_TIMEOUT_MS);
550
- if (parsed.protocol === "https:") {
551
- const connectHost = parsed.hostname.includes(":") ? `[${parsed.hostname}]` : parsed.hostname;
552
- const connectReq = http.request({
553
- hostname: this.proxyHost,
554
- port: this.proxyPort,
555
- method: "CONNECT",
556
- path: `${connectHost}:${parsed.port || 443}`,
557
- headers: { "Proxy-Authorization": proxyAuth, Host: `${connectHost}:${parsed.port || 443}` },
558
- });
559
- connectReq.on("connect", (_res, sock) => {
560
- if (_res.statusCode !== 200) {
561
- clearTimeout(timer);
562
- sock.destroy();
563
- reject(new Error(`CONNECT failed: ${_res.statusCode}`));
564
- return;
565
- }
566
- const tlsSock = tls.connect({ host: parsed.hostname, socket: sock, servername: parsed.hostname, minVersion: "TLSv1.2" }, () => {
567
- const reqLine = `${methodUpper} ${parsed.pathname + parsed.search} HTTP/1.1\r\nHost: ${parsed.host}\r\nUser-Agent: dominusnode-mastra/1.0.0\r\nConnection: close\r\n\r\n`;
568
- tlsSock.write(reqLine);
605
+ try {
606
+ const parsedUrl = validateTargetUrl(url);
607
+ await checkDnsRebinding(parsedUrl.hostname);
608
+ const validCountry = validateCountry(country);
609
+ const ALLOWED_METHODS = new Set(["GET", "HEAD", "OPTIONS"]);
610
+ const methodUpper = method.toUpperCase();
611
+ if (!ALLOWED_METHODS.has(methodUpper)) {
612
+ return { status: 0, headers: {}, body: "", bytes: 0, pool: proxyType, country: country ?? "auto", error: `HTTP method "${methodUpper}" is not allowed. Only GET, HEAD, and OPTIONS are permitted.` };
613
+ }
614
+ const apiKey = this.getApiKey();
615
+ const parts = [];
616
+ if (proxyType && proxyType !== "auto")
617
+ parts.push(proxyType);
618
+ if (validCountry)
619
+ parts.push(`country-${validCountry.toUpperCase()}`);
620
+ const username = parts.length > 0 ? parts.join("-") : "auto";
621
+ const proxyAuth = "Basic " + Buffer.from(`${username}:${apiKey}`).toString("base64");
622
+ const parsed = new URL(url);
623
+ const MAX_RESP = 1_048_576; // 1MB
624
+ const result = await new Promise((resolve, reject) => {
625
+ const timer = setTimeout(() => reject(new Error("Proxy request timed out")), REQUEST_TIMEOUT_MS);
626
+ if (parsed.protocol === "https:") {
627
+ const connectHost = parsed.hostname.includes(":") ? `[${parsed.hostname}]` : parsed.hostname;
628
+ const connectReq = http.request({
629
+ hostname: this.proxyHost,
630
+ port: this.proxyPort,
631
+ method: "CONNECT",
632
+ path: `${connectHost}:${parsed.port || 443}`,
633
+ headers: { "Proxy-Authorization": proxyAuth, Host: `${connectHost}:${parsed.port || 443}` },
634
+ });
635
+ connectReq.on("connect", (_res, sock) => {
636
+ if (_res.statusCode !== 200) {
637
+ clearTimeout(timer);
638
+ sock.destroy();
639
+ reject(new Error(`CONNECT failed: ${_res.statusCode}`));
640
+ return;
641
+ }
642
+ const tlsSock = tls.connect({ host: parsed.hostname, socket: sock, servername: parsed.hostname, minVersion: "TLSv1.2" }, () => {
643
+ const reqLine = `${methodUpper} ${parsed.pathname + parsed.search} HTTP/1.1\r\nHost: ${parsed.host}\r\nUser-Agent: dominusnode-mastra/1.0.0\r\nConnection: close\r\n\r\n`;
644
+ tlsSock.write(reqLine);
645
+ const chunks = [];
646
+ let bytes = 0;
647
+ tlsSock.on("data", (c) => {
648
+ bytes += c.length;
649
+ if (bytes <= MAX_RESP + 16384)
650
+ chunks.push(c);
651
+ });
652
+ let done = false;
653
+ const fin = () => {
654
+ if (done)
655
+ return;
656
+ done = true;
657
+ clearTimeout(timer);
658
+ const raw = Buffer.concat(chunks).toString("utf-8");
659
+ const hEnd = raw.indexOf("\r\n\r\n");
660
+ if (hEnd === -1) {
661
+ reject(new Error("Malformed response"));
662
+ return;
663
+ }
664
+ const hdr = raw.substring(0, hEnd);
665
+ const body = raw.substring(hEnd + 4).substring(0, MAX_RESP);
666
+ const bodyBytes = new TextEncoder().encode(body).length;
667
+ const sm = hdr.split("\r\n")[0].match(/^HTTP\/\d\.\d\s+(\d+)/);
668
+ const hdrs = {};
669
+ for (const l of hdr.split("\r\n").slice(1)) {
670
+ const ci = l.indexOf(":");
671
+ if (ci > 0)
672
+ hdrs[l.substring(0, ci).trim().toLowerCase()] = l.substring(ci + 1).trim();
673
+ }
674
+ resolve({ status: sm ? parseInt(sm[1], 10) : 0, headers: hdrs, body, bytes: bodyBytes });
675
+ };
676
+ tlsSock.on("end", fin);
677
+ tlsSock.on("close", fin);
678
+ tlsSock.on("error", (e) => { clearTimeout(timer); reject(e); });
679
+ });
680
+ tlsSock.on("error", (e) => { clearTimeout(timer); reject(e); });
681
+ });
682
+ connectReq.on("error", (e) => { clearTimeout(timer); reject(e); });
683
+ connectReq.end();
684
+ }
685
+ else {
686
+ const req = http.request({
687
+ hostname: this.proxyHost,
688
+ port: this.proxyPort,
689
+ method: methodUpper,
690
+ path: url,
691
+ headers: { "Proxy-Authorization": proxyAuth, Host: parsed.host ?? "" },
692
+ }, (res) => {
569
693
  const chunks = [];
570
694
  let bytes = 0;
571
- tlsSock.on("data", (c) => {
695
+ res.on("data", (c) => {
572
696
  bytes += c.length;
573
- if (bytes <= MAX_RESP + 16384)
697
+ if (bytes <= MAX_RESP)
574
698
  chunks.push(c);
575
699
  });
576
700
  let done = false;
@@ -579,76 +703,43 @@ class DominusNodeToolkit {
579
703
  return;
580
704
  done = true;
581
705
  clearTimeout(timer);
582
- const raw = Buffer.concat(chunks).toString("utf-8");
583
- const hEnd = raw.indexOf("\r\n\r\n");
584
- if (hEnd === -1) {
585
- reject(new Error("Malformed response"));
586
- return;
587
- }
588
- const hdr = raw.substring(0, hEnd);
589
- const body = raw.substring(hEnd + 4).substring(0, MAX_RESP);
590
- const sm = hdr.split("\r\n")[0].match(/^HTTP\/\d\.\d\s+(\d+)/);
706
+ const body = Buffer.concat(chunks).toString("utf-8").substring(0, MAX_RESP);
707
+ const bodyBytes = new TextEncoder().encode(body).length;
591
708
  const hdrs = {};
592
- for (const l of hdr.split("\r\n").slice(1)) {
593
- const ci = l.indexOf(":");
594
- if (ci > 0)
595
- hdrs[l.substring(0, ci).trim().toLowerCase()] = l.substring(ci + 1).trim();
709
+ for (const [k, v] of Object.entries(res.headers)) {
710
+ if (v)
711
+ hdrs[k] = Array.isArray(v) ? v.join(", ") : v;
596
712
  }
597
- resolve({ status: sm ? parseInt(sm[1], 10) : 0, headers: hdrs, body });
713
+ resolve({ status: res.statusCode ?? 0, headers: hdrs, body, bytes: bodyBytes });
598
714
  };
599
- tlsSock.on("end", fin);
600
- tlsSock.on("close", fin);
601
- tlsSock.on("error", (e) => { clearTimeout(timer); reject(e); });
602
- });
603
- tlsSock.on("error", (e) => { clearTimeout(timer); reject(e); });
604
- });
605
- connectReq.on("error", (e) => { clearTimeout(timer); reject(e); });
606
- connectReq.end();
607
- }
608
- else {
609
- const req = http.request({
610
- hostname: this.proxyHost,
611
- port: this.proxyPort,
612
- method: methodUpper,
613
- path: url,
614
- headers: { "Proxy-Authorization": proxyAuth, Host: parsed.host ?? "" },
615
- }, (res) => {
616
- const chunks = [];
617
- let bytes = 0;
618
- res.on("data", (c) => {
619
- bytes += c.length;
620
- if (bytes <= MAX_RESP)
621
- chunks.push(c);
715
+ res.on("end", fin);
716
+ res.on("close", fin);
717
+ res.on("error", (e) => { clearTimeout(timer); reject(e); });
622
718
  });
623
- let done = false;
624
- const fin = () => {
625
- if (done)
626
- return;
627
- done = true;
628
- clearTimeout(timer);
629
- const body = Buffer.concat(chunks).toString("utf-8").substring(0, MAX_RESP);
630
- const hdrs = {};
631
- for (const [k, v] of Object.entries(res.headers)) {
632
- if (v)
633
- hdrs[k] = Array.isArray(v) ? v.join(", ") : v;
634
- }
635
- resolve({ status: res.statusCode ?? 0, headers: hdrs, body });
636
- };
637
- res.on("end", fin);
638
- res.on("close", fin);
639
- res.on("error", (e) => { clearTimeout(timer); reject(e); });
640
- });
641
- req.on("error", (e) => { clearTimeout(timer); reject(e); });
642
- req.end();
643
- }
644
- });
645
- return {
646
- status: result.status,
647
- headers: result.headers,
648
- body: truncate(scrubCredentials(result.body)),
649
- pool: proxyType,
650
- country: validCountry ?? "auto",
651
- };
719
+ req.on("error", (e) => { clearTimeout(timer); reject(e); });
720
+ req.end();
721
+ }
722
+ });
723
+ return {
724
+ status: result.status,
725
+ headers: result.headers,
726
+ body: truncate(scrubCredentials(result.body)),
727
+ bytes: result.bytes,
728
+ pool: proxyType,
729
+ country: validCountry ?? "auto",
730
+ };
731
+ }
732
+ catch (err) {
733
+ return {
734
+ status: 0,
735
+ headers: {},
736
+ body: "",
737
+ bytes: 0,
738
+ pool: proxyType,
739
+ country: country ?? "auto",
740
+ error: safeError(err),
741
+ };
742
+ }
652
743
  }
653
744
  async checkBalance() {
654
745
  const data = await this.apiGet("/api/wallet");
@@ -873,8 +964,163 @@ class DominusNodeToolkit {
873
964
  async x402Info() {
874
965
  return this.apiGet("/api/x402/info");
875
966
  }
967
+ // -- Proxy --
968
+ async getProxyStatus() {
969
+ return this.apiGet("/api/proxy/status");
970
+ }
971
+ // -- Wallet --
972
+ async getTransactions(limit = 20) {
973
+ const safeLimit = Math.min(Math.max(limit, 1), 100);
974
+ return this.apiGet(`/api/wallet/transactions?limit=${safeLimit}`);
975
+ }
976
+ async getForecast() {
977
+ return this.apiGet("/api/wallet/forecast");
978
+ }
979
+ async checkPayment(invoiceId) {
980
+ validateUuid(invoiceId, "invoice_id");
981
+ return this.apiGet(`/api/wallet/topup/crypto/${encodeURIComponent(invoiceId)}/status`);
982
+ }
983
+ // -- Usage --
984
+ async getDailyUsage(days = 7) {
985
+ const safeDays = Math.min(Math.max(days, 1), 365);
986
+ return this.apiGet(`/api/usage/daily?days=${safeDays}`);
987
+ }
988
+ async getTopHosts(limit = 10) {
989
+ const safeLimit = Math.min(Math.max(limit, 1), 100);
990
+ return this.apiGet(`/api/usage/top-hosts?limit=${safeLimit}`);
991
+ }
992
+ // -- Account (unauthenticated) --
993
+ static EMAIL_RE = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
994
+ static validateEmail(email) {
995
+ const trimmed = email.trim();
996
+ if (!trimmed || !DominusNodeToolkit.EMAIL_RE.test(trimmed)) {
997
+ throw new Error("Invalid email address.");
998
+ }
999
+ if (trimmed.length > 254) {
1000
+ throw new Error("Email address too long (max 254 characters).");
1001
+ }
1002
+ return trimmed;
1003
+ }
1004
+ static validatePassword(password) {
1005
+ if (!password || password.length < 8) {
1006
+ throw new Error("Password must be at least 8 characters.");
1007
+ }
1008
+ if (password.length > 128) {
1009
+ throw new Error("Password must be at most 128 characters.");
1010
+ }
1011
+ return password;
1012
+ }
1013
+ async register(email, password) {
1014
+ const safeEmail = DominusNodeToolkit.validateEmail(email);
1015
+ const safePassword = DominusNodeToolkit.validatePassword(password);
1016
+ return this.rawRequest("POST", "/api/auth/register", { email: safeEmail, password: safePassword });
1017
+ }
1018
+ async login(email, password) {
1019
+ const safeEmail = DominusNodeToolkit.validateEmail(email);
1020
+ const safePassword = DominusNodeToolkit.validatePassword(password);
1021
+ return this.rawRequest("POST", "/api/auth/login", { email: safeEmail, password: safePassword });
1022
+ }
1023
+ async getAccountInfo() {
1024
+ return this.apiGet("/api/auth/me");
1025
+ }
1026
+ async verifyEmail(token) {
1027
+ if (!token || typeof token !== "string" || token.trim().length === 0) {
1028
+ throw new Error("Verification token is required.");
1029
+ }
1030
+ if (/[\x00-\x1f\x7f]/.test(token)) {
1031
+ throw new Error("Token contains invalid control characters.");
1032
+ }
1033
+ return this.rawRequest("POST", "/api/auth/verify-email", { token: token.trim() });
1034
+ }
1035
+ async resendVerification() {
1036
+ return this.apiPost("/api/auth/resend-verification");
1037
+ }
1038
+ async updatePassword(currentPassword, newPassword) {
1039
+ DominusNodeToolkit.validatePassword(currentPassword);
1040
+ DominusNodeToolkit.validatePassword(newPassword);
1041
+ return this.apiPost("/api/auth/change-password", {
1042
+ currentPassword,
1043
+ newPassword,
1044
+ });
1045
+ }
1046
+ // -- API Keys --
1047
+ async listKeys() {
1048
+ return this.apiGet("/api/keys");
1049
+ }
1050
+ async createKey(label) {
1051
+ if (!label || label.length === 0 || label.length > 100) {
1052
+ throw new Error("label is required and must be 1-100 characters.");
1053
+ }
1054
+ if (/[\x00-\x1f\x7f]/.test(label)) {
1055
+ throw new Error("label contains invalid control characters.");
1056
+ }
1057
+ return this.apiPost("/api/keys", { label });
1058
+ }
1059
+ async revokeKey(keyId) {
1060
+ validateUuid(keyId, "key_id");
1061
+ return this.apiDelete(`/api/keys/${encodeURIComponent(keyId)}`);
1062
+ }
1063
+ // -- Plans --
1064
+ async getPlan() {
1065
+ return this.apiGet("/api/plans/user/plan");
1066
+ }
1067
+ async listPlans() {
1068
+ return this.apiGet("/api/plans");
1069
+ }
1070
+ async changePlan(planId) {
1071
+ validateUuid(planId, "plan_id");
1072
+ return this.apiPut("/api/plans/user/plan", { planId });
1073
+ }
1074
+ // -- Teams (additional) --
1075
+ async teamDelete(teamId) {
1076
+ validateUuid(teamId, "team_id");
1077
+ return this.apiDelete(`/api/teams/${encodeURIComponent(teamId)}`);
1078
+ }
1079
+ async teamRevokeKey(teamId, keyId) {
1080
+ validateUuid(teamId, "team_id");
1081
+ validateUuid(keyId, "key_id");
1082
+ return this.apiDelete(`/api/teams/${encodeURIComponent(teamId)}/keys/${encodeURIComponent(keyId)}`);
1083
+ }
1084
+ async teamListKeys(teamId) {
1085
+ validateUuid(teamId, "team_id");
1086
+ return this.apiGet(`/api/teams/${encodeURIComponent(teamId)}/keys`);
1087
+ }
1088
+ async teamListMembers(teamId) {
1089
+ validateUuid(teamId, "team_id");
1090
+ return this.apiGet(`/api/teams/${encodeURIComponent(teamId)}/members`);
1091
+ }
1092
+ async teamAddMember(teamId, userId, role = "member") {
1093
+ validateUuid(teamId, "team_id");
1094
+ validateUuid(userId, "user_id");
1095
+ if (role !== "member" && role !== "admin") {
1096
+ throw new Error("role must be 'member' or 'admin'.");
1097
+ }
1098
+ return this.apiPost(`/api/teams/${encodeURIComponent(teamId)}/members`, { userId, role });
1099
+ }
1100
+ async teamRemoveMember(teamId, userId) {
1101
+ validateUuid(teamId, "team_id");
1102
+ validateUuid(userId, "user_id");
1103
+ return this.apiDelete(`/api/teams/${encodeURIComponent(teamId)}/members/${encodeURIComponent(userId)}`);
1104
+ }
1105
+ async teamInviteMember(teamId, email, role = "member") {
1106
+ validateUuid(teamId, "team_id");
1107
+ const safeEmail = DominusNodeToolkit.validateEmail(email);
1108
+ if (role !== "member" && role !== "admin") {
1109
+ throw new Error("role must be 'member' or 'admin'.");
1110
+ }
1111
+ return this.apiPost(`/api/teams/${encodeURIComponent(teamId)}/invites`, { email: safeEmail, role });
1112
+ }
1113
+ async teamListInvites(teamId) {
1114
+ validateUuid(teamId, "team_id");
1115
+ return this.apiGet(`/api/teams/${encodeURIComponent(teamId)}/invites`);
1116
+ }
1117
+ async teamCancelInvite(teamId, inviteId) {
1118
+ validateUuid(teamId, "team_id");
1119
+ validateUuid(inviteId, "invite_id");
1120
+ return this.apiDelete(`/api/teams/${encodeURIComponent(teamId)}/invites/${encodeURIComponent(inviteId)}`);
1121
+ }
876
1122
  // -----------------------------------------------------------------------
877
- // getTools() -- returns Mastra createTool() instances for all 26 tools
1123
+ // getTools() -- returns Mastra createTool() instances for all 53 tools
878
1124
  // -----------------------------------------------------------------------
879
1125
  getTools() {
880
1126
  return [
@@ -894,17 +1140,13 @@ class DominusNodeToolkit {
894
1140
  status: zod_1.z.number(),
895
1141
  headers: zod_1.z.record(zod_1.z.string()),
896
1142
  body: zod_1.z.string(),
1143
+ bytes: zod_1.z.number(),
897
1144
  pool: zod_1.z.string(),
898
1145
  country: zod_1.z.string(),
899
1146
  error: zod_1.z.string().optional(),
900
1147
  }),
901
1148
  execute: async ({ context }) => {
902
- try {
903
- return await this.proxiedFetch(context.url, context.method, context.country, context.proxyType);
904
- }
905
- catch (err) {
906
- return { status: 0, headers: {}, body: "", pool: context.proxyType ?? "dc", country: context.country ?? "auto", error: safeError(err) };
907
- }
1149
+ return await this.proxiedFetch(context.url, context.method, context.country, context.proxyType);
908
1150
  },
909
1151
  }),
910
1152
  // 2. check_balance
@@ -1442,6 +1684,556 @@ class DominusNodeToolkit {
1442
1684
  }
1443
1685
  },
1444
1686
  }),
1687
+ // 27. get_proxy_status
1688
+ (0, tools_1.createTool)({
1689
+ id: "dominusnode_get_proxy_status",
1690
+ description: "Get the current status of the proxy gateway including uptime, active connections, " +
1691
+ "and pool health.",
1692
+ inputSchema: zod_1.z.object({}),
1693
+ outputSchema: zod_1.z.object({
1694
+ data: zod_1.z.unknown(),
1695
+ error: zod_1.z.string().optional(),
1696
+ }),
1697
+ execute: async () => {
1698
+ try {
1699
+ return { data: await this.getProxyStatus() };
1700
+ }
1701
+ catch (err) {
1702
+ return { data: null, error: safeError(err) };
1703
+ }
1704
+ },
1705
+ }),
1706
+ // 28. get_transactions
1707
+ (0, tools_1.createTool)({
1708
+ id: "dominusnode_get_transactions",
1709
+ description: "Get wallet transaction history showing top-ups, charges, and refunds.",
1710
+ inputSchema: zod_1.z.object({
1711
+ limit: zod_1.z.number().int().min(1).max(100).default(20).describe("Number of transactions to return (1-100, default 20)"),
1712
+ }),
1713
+ outputSchema: zod_1.z.object({
1714
+ data: zod_1.z.unknown(),
1715
+ error: zod_1.z.string().optional(),
1716
+ }),
1717
+ execute: async ({ context }) => {
1718
+ try {
1719
+ return { data: await this.getTransactions(context.limit) };
1720
+ }
1721
+ catch (err) {
1722
+ return { data: null, error: safeError(err) };
1723
+ }
1724
+ },
1725
+ }),
1726
+ // 29. get_forecast
1727
+ (0, tools_1.createTool)({
1728
+ id: "dominusnode_get_forecast",
1729
+ description: "Get a spending forecast based on recent usage patterns. " +
1730
+ "Shows estimated days until balance runs out and projected monthly cost.",
1731
+ inputSchema: zod_1.z.object({}),
1732
+ outputSchema: zod_1.z.object({
1733
+ data: zod_1.z.unknown(),
1734
+ error: zod_1.z.string().optional(),
1735
+ }),
1736
+ execute: async () => {
1737
+ try {
1738
+ return { data: await this.getForecast() };
1739
+ }
1740
+ catch (err) {
1741
+ return { data: null, error: safeError(err) };
1742
+ }
1743
+ },
1744
+ }),
1745
+ // 30. check_payment
1746
+ (0, tools_1.createTool)({
1747
+ id: "dominusnode_check_payment",
1748
+ description: "Check the status of a crypto top-up payment by invoice ID. " +
1749
+ "Returns payment status (pending, confirming, completed, expired).",
1750
+ inputSchema: zod_1.z.object({
1751
+ invoiceId: zod_1.z.string().describe("Crypto invoice ID (UUID) returned from topup_crypto"),
1752
+ }),
1753
+ outputSchema: zod_1.z.object({
1754
+ data: zod_1.z.unknown(),
1755
+ error: zod_1.z.string().optional(),
1756
+ }),
1757
+ execute: async ({ context }) => {
1758
+ try {
1759
+ return { data: await this.checkPayment(context.invoiceId) };
1760
+ }
1761
+ catch (err) {
1762
+ return { data: null, error: safeError(err) };
1763
+ }
1764
+ },
1765
+ }),
1766
+ // 31. get_daily_usage
1767
+ (0, tools_1.createTool)({
1768
+ id: "dominusnode_get_daily_usage",
1769
+ description: "Get daily bandwidth usage breakdown for the specified number of days. " +
1770
+ "Returns per-day bytes transferred and cost.",
1771
+ inputSchema: zod_1.z.object({
1772
+ days: zod_1.z.number().int().min(1).max(365).default(7).describe("Number of days to look back (1-365, default 7)"),
1773
+ }),
1774
+ outputSchema: zod_1.z.object({
1775
+ data: zod_1.z.unknown(),
1776
+ error: zod_1.z.string().optional(),
1777
+ }),
1778
+ execute: async ({ context }) => {
1779
+ try {
1780
+ return { data: await this.getDailyUsage(context.days) };
1781
+ }
1782
+ catch (err) {
1783
+ return { data: null, error: safeError(err) };
1784
+ }
1785
+ },
1786
+ }),
1787
+ // 32. get_top_hosts
1788
+ (0, tools_1.createTool)({
1789
+ id: "dominusnode_get_top_hosts",
1790
+ description: "Get the top hosts by bandwidth usage. Shows which domains consume the most proxy traffic.",
1791
+ inputSchema: zod_1.z.object({
1792
+ limit: zod_1.z.number().int().min(1).max(100).default(10).describe("Number of top hosts to return (1-100, default 10)"),
1793
+ }),
1794
+ outputSchema: zod_1.z.object({
1795
+ data: zod_1.z.unknown(),
1796
+ error: zod_1.z.string().optional(),
1797
+ }),
1798
+ execute: async ({ context }) => {
1799
+ try {
1800
+ return { data: await this.getTopHosts(context.limit) };
1801
+ }
1802
+ catch (err) {
1803
+ return { data: null, error: safeError(err) };
1804
+ }
1805
+ },
1806
+ }),
1807
+ // 33. register
1808
+ (0, tools_1.createTool)({
1809
+ id: "dominusnode_register",
1810
+ description: "Register a new Dominus Node account. Does not require authentication. " +
1811
+ "Returns user info and initial API key.",
1812
+ inputSchema: zod_1.z.object({
1813
+ email: zod_1.z.string().describe("Email address for the new account"),
1814
+ password: zod_1.z.string().min(8).max(128).describe("Password (8-128 characters)"),
1815
+ }),
1816
+ outputSchema: zod_1.z.object({
1817
+ data: zod_1.z.unknown(),
1818
+ error: zod_1.z.string().optional(),
1819
+ }),
1820
+ execute: async ({ context }) => {
1821
+ try {
1822
+ return { data: await this.register(context.email, context.password) };
1823
+ }
1824
+ catch (err) {
1825
+ return { data: null, error: safeError(err) };
1826
+ }
1827
+ },
1828
+ }),
1829
+ // 34. login
1830
+ (0, tools_1.createTool)({
1831
+ id: "dominusnode_login",
1832
+ description: "Log in to an existing Dominus Node account. Does not require authentication. " +
1833
+ "Returns JWT access and refresh tokens.",
1834
+ inputSchema: zod_1.z.object({
1835
+ email: zod_1.z.string().describe("Account email address"),
1836
+ password: zod_1.z.string().min(8).max(128).describe("Account password"),
1837
+ }),
1838
+ outputSchema: zod_1.z.object({
1839
+ data: zod_1.z.unknown(),
1840
+ error: zod_1.z.string().optional(),
1841
+ }),
1842
+ execute: async ({ context }) => {
1843
+ try {
1844
+ return { data: await this.login(context.email, context.password) };
1845
+ }
1846
+ catch (err) {
1847
+ return { data: null, error: safeError(err) };
1848
+ }
1849
+ },
1850
+ }),
1851
+ // 35. get_account_info
1852
+ (0, tools_1.createTool)({
1853
+ id: "dominusnode_get_account_info",
1854
+ description: "Get your account profile information including email, plan, verification status, and creation date.",
1855
+ inputSchema: zod_1.z.object({}),
1856
+ outputSchema: zod_1.z.object({
1857
+ data: zod_1.z.unknown(),
1858
+ error: zod_1.z.string().optional(),
1859
+ }),
1860
+ execute: async () => {
1861
+ try {
1862
+ return { data: await this.getAccountInfo() };
1863
+ }
1864
+ catch (err) {
1865
+ return { data: null, error: safeError(err) };
1866
+ }
1867
+ },
1868
+ }),
1869
+ // 36. verify_email
1870
+ (0, tools_1.createTool)({
1871
+ id: "dominusnode_verify_email",
1872
+ description: "Verify an email address using the verification token sent to the user's email. " +
1873
+ "Does not require authentication.",
1874
+ inputSchema: zod_1.z.object({
1875
+ token: zod_1.z.string().describe("Email verification token from the verification email"),
1876
+ }),
1877
+ outputSchema: zod_1.z.object({
1878
+ data: zod_1.z.unknown(),
1879
+ error: zod_1.z.string().optional(),
1880
+ }),
1881
+ execute: async ({ context }) => {
1882
+ try {
1883
+ return { data: await this.verifyEmail(context.token) };
1884
+ }
1885
+ catch (err) {
1886
+ return { data: null, error: safeError(err) };
1887
+ }
1888
+ },
1889
+ }),
1890
+ // 37. resend_verification
1891
+ (0, tools_1.createTool)({
1892
+ id: "dominusnode_resend_verification",
1893
+ description: "Resend the email verification link. Requires authentication.",
1894
+ inputSchema: zod_1.z.object({}),
1895
+ outputSchema: zod_1.z.object({
1896
+ data: zod_1.z.unknown(),
1897
+ error: zod_1.z.string().optional(),
1898
+ }),
1899
+ execute: async () => {
1900
+ try {
1901
+ return { data: await this.resendVerification() };
1902
+ }
1903
+ catch (err) {
1904
+ return { data: null, error: safeError(err) };
1905
+ }
1906
+ },
1907
+ }),
1908
+ // 38. update_password
1909
+ (0, tools_1.createTool)({
1910
+ id: "dominusnode_update_password",
1911
+ description: "Change your account password. Requires current password for verification.",
1912
+ inputSchema: zod_1.z.object({
1913
+ currentPassword: zod_1.z.string().min(8).max(128).describe("Current account password"),
1914
+ newPassword: zod_1.z.string().min(8).max(128).describe("New password (8-128 characters)"),
1915
+ }),
1916
+ outputSchema: zod_1.z.object({
1917
+ data: zod_1.z.unknown(),
1918
+ error: zod_1.z.string().optional(),
1919
+ }),
1920
+ execute: async ({ context }) => {
1921
+ try {
1922
+ return { data: await this.updatePassword(context.currentPassword, context.newPassword) };
1923
+ }
1924
+ catch (err) {
1925
+ return { data: null, error: safeError(err) };
1926
+ }
1927
+ },
1928
+ }),
1929
+ // 39. list_keys
1930
+ (0, tools_1.createTool)({
1931
+ id: "dominusnode_list_keys",
1932
+ description: "List all your personal API keys with their labels, creation dates, and last-used timestamps.",
1933
+ inputSchema: zod_1.z.object({}),
1934
+ outputSchema: zod_1.z.object({
1935
+ data: zod_1.z.unknown(),
1936
+ error: zod_1.z.string().optional(),
1937
+ }),
1938
+ execute: async () => {
1939
+ try {
1940
+ return { data: await this.listKeys() };
1941
+ }
1942
+ catch (err) {
1943
+ return { data: null, error: safeError(err) };
1944
+ }
1945
+ },
1946
+ }),
1947
+ // 40. create_key
1948
+ (0, tools_1.createTool)({
1949
+ id: "dominusnode_create_key",
1950
+ description: "Create a new personal API key. The key is shown only once -- save it immediately. " +
1951
+ "Usage is billed against your personal wallet.",
1952
+ inputSchema: zod_1.z.object({
1953
+ label: zod_1.z.string().min(1).max(100).describe('Label for the API key (e.g., "production", "dev-testing")'),
1954
+ }),
1955
+ outputSchema: zod_1.z.object({
1956
+ data: zod_1.z.unknown(),
1957
+ error: zod_1.z.string().optional(),
1958
+ }),
1959
+ execute: async ({ context }) => {
1960
+ try {
1961
+ return { data: await this.createKey(context.label) };
1962
+ }
1963
+ catch (err) {
1964
+ return { data: null, error: safeError(err) };
1965
+ }
1966
+ },
1967
+ }),
1968
+ // 41. revoke_key
1969
+ (0, tools_1.createTool)({
1970
+ id: "dominusnode_revoke_key",
1971
+ description: "Revoke (delete) a personal API key. This action is irreversible -- " +
1972
+ "any applications using this key will lose access immediately.",
1973
+ inputSchema: zod_1.z.object({
1974
+ keyId: zod_1.z.string().describe("API key ID (UUID) to revoke"),
1975
+ }),
1976
+ outputSchema: zod_1.z.object({
1977
+ data: zod_1.z.unknown(),
1978
+ error: zod_1.z.string().optional(),
1979
+ }),
1980
+ execute: async ({ context }) => {
1981
+ try {
1982
+ return { data: await this.revokeKey(context.keyId) };
1983
+ }
1984
+ catch (err) {
1985
+ return { data: null, error: safeError(err) };
1986
+ }
1987
+ },
1988
+ }),
1989
+ // 42. get_plan
1990
+ (0, tools_1.createTool)({
1991
+ id: "dominusnode_get_plan",
1992
+ description: "Get your current subscription plan including tier, bandwidth limits, and pricing.",
1993
+ inputSchema: zod_1.z.object({}),
1994
+ outputSchema: zod_1.z.object({
1995
+ data: zod_1.z.unknown(),
1996
+ error: zod_1.z.string().optional(),
1997
+ }),
1998
+ execute: async () => {
1999
+ try {
2000
+ return { data: await this.getPlan() };
2001
+ }
2002
+ catch (err) {
2003
+ return { data: null, error: safeError(err) };
2004
+ }
2005
+ },
2006
+ }),
2007
+ // 43. list_plans
2008
+ (0, tools_1.createTool)({
2009
+ id: "dominusnode_list_plans",
2010
+ description: "List all available subscription plans with features, pricing, and bandwidth limits.",
2011
+ inputSchema: zod_1.z.object({}),
2012
+ outputSchema: zod_1.z.object({
2013
+ data: zod_1.z.unknown(),
2014
+ error: zod_1.z.string().optional(),
2015
+ }),
2016
+ execute: async () => {
2017
+ try {
2018
+ return { data: await this.listPlans() };
2019
+ }
2020
+ catch (err) {
2021
+ return { data: null, error: safeError(err) };
2022
+ }
2023
+ },
2024
+ }),
2025
+ // 44. change_plan
2026
+ (0, tools_1.createTool)({
2027
+ id: "dominusnode_change_plan",
2028
+ description: "Change your subscription plan. Takes effect immediately. " +
2029
+ "Use list_plans to see available options.",
2030
+ inputSchema: zod_1.z.object({
2031
+ planId: zod_1.z.string().describe("Plan ID (UUID) to switch to"),
2032
+ }),
2033
+ outputSchema: zod_1.z.object({
2034
+ data: zod_1.z.unknown(),
2035
+ error: zod_1.z.string().optional(),
2036
+ }),
2037
+ execute: async ({ context }) => {
2038
+ try {
2039
+ return { data: await this.changePlan(context.planId) };
2040
+ }
2041
+ catch (err) {
2042
+ return { data: null, error: safeError(err) };
2043
+ }
2044
+ },
2045
+ }),
2046
+ // 45. team_delete
2047
+ (0, tools_1.createTool)({
2048
+ id: "dominusnode_team_delete",
2049
+ description: "Delete a team. Only the team owner can delete. " +
2050
+ "All team keys are revoked and remaining balance is refunded.",
2051
+ inputSchema: zod_1.z.object({
2052
+ teamId: zod_1.z.string().describe("Team ID (UUID) to delete"),
2053
+ }),
2054
+ outputSchema: zod_1.z.object({
2055
+ data: zod_1.z.unknown(),
2056
+ error: zod_1.z.string().optional(),
2057
+ }),
2058
+ execute: async ({ context }) => {
2059
+ try {
2060
+ return { data: await this.teamDelete(context.teamId) };
2061
+ }
2062
+ catch (err) {
2063
+ return { data: null, error: safeError(err) };
2064
+ }
2065
+ },
2066
+ }),
2067
+ // 46. team_revoke_key
2068
+ (0, tools_1.createTool)({
2069
+ id: "dominusnode_team_revoke_key",
2070
+ description: "Revoke a team API key. Only owners and admins can revoke keys. " +
2071
+ "Applications using this key will lose access immediately.",
2072
+ inputSchema: zod_1.z.object({
2073
+ teamId: zod_1.z.string().describe("Team ID (UUID)"),
2074
+ keyId: zod_1.z.string().describe("API key ID (UUID) to revoke"),
2075
+ }),
2076
+ outputSchema: zod_1.z.object({
2077
+ data: zod_1.z.unknown(),
2078
+ error: zod_1.z.string().optional(),
2079
+ }),
2080
+ execute: async ({ context }) => {
2081
+ try {
2082
+ return { data: await this.teamRevokeKey(context.teamId, context.keyId) };
2083
+ }
2084
+ catch (err) {
2085
+ return { data: null, error: safeError(err) };
2086
+ }
2087
+ },
2088
+ }),
2089
+ // 47. team_list_keys
2090
+ (0, tools_1.createTool)({
2091
+ id: "dominusnode_team_list_keys",
2092
+ description: "List all API keys for a team with labels, creation dates, and last-used timestamps.",
2093
+ inputSchema: zod_1.z.object({
2094
+ teamId: zod_1.z.string().describe("Team ID (UUID)"),
2095
+ }),
2096
+ outputSchema: zod_1.z.object({
2097
+ data: zod_1.z.unknown(),
2098
+ error: zod_1.z.string().optional(),
2099
+ }),
2100
+ execute: async ({ context }) => {
2101
+ try {
2102
+ return { data: await this.teamListKeys(context.teamId) };
2103
+ }
2104
+ catch (err) {
2105
+ return { data: null, error: safeError(err) };
2106
+ }
2107
+ },
2108
+ }),
2109
+ // 48. team_list_members
2110
+ (0, tools_1.createTool)({
2111
+ id: "dominusnode_team_list_members",
2112
+ description: "List all members of a team with their roles and join dates.",
2113
+ inputSchema: zod_1.z.object({
2114
+ teamId: zod_1.z.string().describe("Team ID (UUID)"),
2115
+ }),
2116
+ outputSchema: zod_1.z.object({
2117
+ data: zod_1.z.unknown(),
2118
+ error: zod_1.z.string().optional(),
2119
+ }),
2120
+ execute: async ({ context }) => {
2121
+ try {
2122
+ return { data: await this.teamListMembers(context.teamId) };
2123
+ }
2124
+ catch (err) {
2125
+ return { data: null, error: safeError(err) };
2126
+ }
2127
+ },
2128
+ }),
2129
+ // 49. team_add_member
2130
+ (0, tools_1.createTool)({
2131
+ id: "dominusnode_team_add_member",
2132
+ description: "Add a user directly to a team by user ID. " +
2133
+ "Only owners and admins can add members.",
2134
+ inputSchema: zod_1.z.object({
2135
+ teamId: zod_1.z.string().describe("Team ID (UUID)"),
2136
+ userId: zod_1.z.string().describe("User ID (UUID) of the user to add"),
2137
+ role: zod_1.z.enum(["member", "admin"]).default("member").describe("Role for the new member"),
2138
+ }),
2139
+ outputSchema: zod_1.z.object({
2140
+ data: zod_1.z.unknown(),
2141
+ error: zod_1.z.string().optional(),
2142
+ }),
2143
+ execute: async ({ context }) => {
2144
+ try {
2145
+ return { data: await this.teamAddMember(context.teamId, context.userId, context.role) };
2146
+ }
2147
+ catch (err) {
2148
+ return { data: null, error: safeError(err) };
2149
+ }
2150
+ },
2151
+ }),
2152
+ // 50. team_remove_member
2153
+ (0, tools_1.createTool)({
2154
+ id: "dominusnode_team_remove_member",
2155
+ description: "Remove a member from a team. Only owners and admins can remove members.",
2156
+ inputSchema: zod_1.z.object({
2157
+ teamId: zod_1.z.string().describe("Team ID (UUID)"),
2158
+ userId: zod_1.z.string().describe("User ID (UUID) of the member to remove"),
2159
+ }),
2160
+ outputSchema: zod_1.z.object({
2161
+ data: zod_1.z.unknown(),
2162
+ error: zod_1.z.string().optional(),
2163
+ }),
2164
+ execute: async ({ context }) => {
2165
+ try {
2166
+ return { data: await this.teamRemoveMember(context.teamId, context.userId) };
2167
+ }
2168
+ catch (err) {
2169
+ return { data: null, error: safeError(err) };
2170
+ }
2171
+ },
2172
+ }),
2173
+ // 51. team_invite_member
2174
+ (0, tools_1.createTool)({
2175
+ id: "dominusnode_team_invite_member",
2176
+ description: "Invite a user to join a team by email address. " +
2177
+ "The user will receive an invitation email.",
2178
+ inputSchema: zod_1.z.object({
2179
+ teamId: zod_1.z.string().describe("Team ID (UUID)"),
2180
+ email: zod_1.z.string().describe("Email address of the user to invite"),
2181
+ role: zod_1.z.enum(["member", "admin"]).default("member").describe("Role for the invited member"),
2182
+ }),
2183
+ outputSchema: zod_1.z.object({
2184
+ data: zod_1.z.unknown(),
2185
+ error: zod_1.z.string().optional(),
2186
+ }),
2187
+ execute: async ({ context }) => {
2188
+ try {
2189
+ return { data: await this.teamInviteMember(context.teamId, context.email, context.role) };
2190
+ }
2191
+ catch (err) {
2192
+ return { data: null, error: safeError(err) };
2193
+ }
2194
+ },
2195
+ }),
2196
+ // 52. team_list_invites
2197
+ (0, tools_1.createTool)({
2198
+ id: "dominusnode_team_list_invites",
2199
+ description: "List all pending invitations for a team.",
2200
+ inputSchema: zod_1.z.object({
2201
+ teamId: zod_1.z.string().describe("Team ID (UUID)"),
2202
+ }),
2203
+ outputSchema: zod_1.z.object({
2204
+ data: zod_1.z.unknown(),
2205
+ error: zod_1.z.string().optional(),
2206
+ }),
2207
+ execute: async ({ context }) => {
2208
+ try {
2209
+ return { data: await this.teamListInvites(context.teamId) };
2210
+ }
2211
+ catch (err) {
2212
+ return { data: null, error: safeError(err) };
2213
+ }
2214
+ },
2215
+ }),
2216
+ // 53. team_cancel_invite
2217
+ (0, tools_1.createTool)({
2218
+ id: "dominusnode_team_cancel_invite",
2219
+ description: "Cancel a pending team invitation. Only owners and admins can cancel invites.",
2220
+ inputSchema: zod_1.z.object({
2221
+ teamId: zod_1.z.string().describe("Team ID (UUID)"),
2222
+ inviteId: zod_1.z.string().describe("Invite ID (UUID) to cancel"),
2223
+ }),
2224
+ outputSchema: zod_1.z.object({
2225
+ data: zod_1.z.unknown(),
2226
+ error: zod_1.z.string().optional(),
2227
+ }),
2228
+ execute: async ({ context }) => {
2229
+ try {
2230
+ return { data: await this.teamCancelInvite(context.teamId, context.inviteId) };
2231
+ }
2232
+ catch (err) {
2233
+ return { data: null, error: safeError(err) };
2234
+ }
2235
+ },
2236
+ }),
1445
2237
  ];
1446
2238
  }
1447
2239
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dominusnode/mastra-tools",
3
- "version": "1.2.0",
3
+ "version": "1.3.1",
4
4
  "description": "Dominus Node rotating proxy tools for Mastra AI",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",