@dominusnode/pi-extension 1.0.0 → 1.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +29 -2
- package/dist/index.d.ts +1 -1
- package/dist/index.js +332 -1
- package/dist/toolkit.d.ts +35 -1
- package/dist/toolkit.js +498 -14
- package/package.json +7 -3
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# @dominusnode/pi-extension
|
|
2
2
|
|
|
3
|
-
[Pi](https://github.com/badlogic/pi-mono) extension providing **
|
|
3
|
+
[Pi](https://github.com/badlogic/pi-mono) extension providing **53 tools** for the [Dominus Node](https://dominusnode.com) rotating proxy and management platform.
|
|
4
4
|
|
|
5
5
|
## What is Pi?
|
|
6
6
|
|
|
@@ -39,7 +39,7 @@ export DOMINUSNODE_API_KEY="dn_live_your_key_here"
|
|
|
39
39
|
|
|
40
40
|
Get your API key at [dominusnode.com](https://dominusnode.com) → Dashboard → API Keys.
|
|
41
41
|
|
|
42
|
-
## Available Tools (
|
|
42
|
+
## Available Tools (53 total)
|
|
43
43
|
|
|
44
44
|
| Tool | Description |
|
|
45
45
|
|------|-------------|
|
|
@@ -69,6 +69,33 @@ Get your API key at [dominusnode.com](https://dominusnode.com) → Dashboard →
|
|
|
69
69
|
| `dominusnode_topup_crypto` | Top up via crypto (BTC/ETH/USDC/...) |
|
|
70
70
|
| `dominusnode_x402_info` | x402 micropayment config |
|
|
71
71
|
| `dominusnode_update_wallet_policy` | Set spending limits/domain restrictions |
|
|
72
|
+
| `dominusnode_get_proxy_status` | Proxy gateway status and pool health |
|
|
73
|
+
| `dominusnode_get_transactions` | Wallet transaction history |
|
|
74
|
+
| `dominusnode_get_forecast` | Spending forecast and projected costs |
|
|
75
|
+
| `dominusnode_check_payment` | Check crypto payment status by invoice ID |
|
|
76
|
+
| `dominusnode_get_daily_usage` | Daily bandwidth usage breakdown |
|
|
77
|
+
| `dominusnode_get_top_hosts` | Top hosts by bandwidth usage |
|
|
78
|
+
| `dominusnode_register` | Register a new account |
|
|
79
|
+
| `dominusnode_login` | Log in to an existing account |
|
|
80
|
+
| `dominusnode_get_account_info` | Get account profile information |
|
|
81
|
+
| `dominusnode_verify_email` | Verify email with token |
|
|
82
|
+
| `dominusnode_resend_verification` | Resend email verification link |
|
|
83
|
+
| `dominusnode_update_password` | Change account password |
|
|
84
|
+
| `dominusnode_list_keys` | List personal API keys |
|
|
85
|
+
| `dominusnode_create_key` | Create a new personal API key |
|
|
86
|
+
| `dominusnode_revoke_key` | Revoke a personal API key |
|
|
87
|
+
| `dominusnode_get_plan` | Get current subscription plan |
|
|
88
|
+
| `dominusnode_list_plans` | List available plans |
|
|
89
|
+
| `dominusnode_change_plan` | Change subscription plan |
|
|
90
|
+
| `dominusnode_team_delete` | Delete a team |
|
|
91
|
+
| `dominusnode_team_revoke_key` | Revoke a team API key |
|
|
92
|
+
| `dominusnode_team_list_keys` | List team API keys |
|
|
93
|
+
| `dominusnode_team_list_members` | List team members |
|
|
94
|
+
| `dominusnode_team_add_member` | Add a member to a team |
|
|
95
|
+
| `dominusnode_team_remove_member` | Remove a member from a team |
|
|
96
|
+
| `dominusnode_team_invite_member` | Invite a user to a team by email |
|
|
97
|
+
| `dominusnode_team_list_invites` | List pending team invitations |
|
|
98
|
+
| `dominusnode_team_cancel_invite` | Cancel a pending team invitation |
|
|
72
99
|
|
|
73
100
|
## Proxy Usage
|
|
74
101
|
|
package/dist/index.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Dominus Node — Pi Extension
|
|
3
3
|
*
|
|
4
|
-
* Pi-mono extension providing
|
|
4
|
+
* Pi-mono extension providing 53 tools for the Dominus Node rotating proxy
|
|
5
5
|
* and management platform. Loaded by the pi coding agent from:
|
|
6
6
|
* ~/.pi/agent/extensions/dominusnode/ (global)
|
|
7
7
|
* .pi/extensions/dominusnode/ (project-local)
|
package/dist/index.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
/**
|
|
3
3
|
* Dominus Node — Pi Extension
|
|
4
4
|
*
|
|
5
|
-
* Pi-mono extension providing
|
|
5
|
+
* Pi-mono extension providing 53 tools for the Dominus Node rotating proxy
|
|
6
6
|
* and management platform. Loaded by the pi coding agent from:
|
|
7
7
|
* ~/.pi/agent/extensions/dominusnode/ (global)
|
|
8
8
|
* .pi/extensions/dominusnode/ (project-local)
|
|
@@ -370,4 +370,335 @@ function dominusNodeExtension(pi) {
|
|
|
370
370
|
return toolkit.updateWalletPolicy(String(params.walletId ?? ""), params.dailyLimitCents !== undefined ? Number(params.dailyLimitCents) : undefined, params.allowedDomains !== undefined ? params.allowedDomains : undefined);
|
|
371
371
|
},
|
|
372
372
|
});
|
|
373
|
+
// ── Tool 27: get_proxy_status ───────────────────────────────────────────
|
|
374
|
+
pi.registerTool({
|
|
375
|
+
name: "dominusnode_get_proxy_status",
|
|
376
|
+
label: "DominusNode: Get Proxy Status",
|
|
377
|
+
description: "Get the current status of the proxy gateway including uptime, active connections, and pool health.",
|
|
378
|
+
parameters: typebox_1.Type.Object({}),
|
|
379
|
+
async execute(_id, _params, _signal, _onUpdate, _ctx) {
|
|
380
|
+
return toolkit.getProxyStatus();
|
|
381
|
+
},
|
|
382
|
+
});
|
|
383
|
+
// ── Tool 28: get_transactions ───────────────────────────────────────────
|
|
384
|
+
pi.registerTool({
|
|
385
|
+
name: "dominusnode_get_transactions",
|
|
386
|
+
label: "DominusNode: Get Wallet Transactions",
|
|
387
|
+
description: "Get wallet transaction history showing top-ups, charges, and refunds.",
|
|
388
|
+
parameters: typebox_1.Type.Object({
|
|
389
|
+
limit: typebox_1.Type.Optional(typebox_1.Type.Number({ description: "Number of transactions to return (default: 20, max: 100)", minimum: 1, maximum: 100 })),
|
|
390
|
+
}),
|
|
391
|
+
async execute(_id, params, _signal, _onUpdate, _ctx) {
|
|
392
|
+
return toolkit.getTransactions(params.limit !== undefined ? Number(params.limit) : 20);
|
|
393
|
+
},
|
|
394
|
+
});
|
|
395
|
+
// ── Tool 29: get_forecast ──────────────────────────────────────────────
|
|
396
|
+
pi.registerTool({
|
|
397
|
+
name: "dominusnode_get_forecast",
|
|
398
|
+
label: "DominusNode: Get Spending Forecast",
|
|
399
|
+
description: "Get a spending forecast based on recent usage patterns. " +
|
|
400
|
+
"Shows estimated days until balance runs out and projected monthly cost.",
|
|
401
|
+
parameters: typebox_1.Type.Object({}),
|
|
402
|
+
async execute(_id, _params, _signal, _onUpdate, _ctx) {
|
|
403
|
+
return toolkit.getForecast();
|
|
404
|
+
},
|
|
405
|
+
});
|
|
406
|
+
// ── Tool 30: check_payment ─────────────────────────────────────────────
|
|
407
|
+
pi.registerTool({
|
|
408
|
+
name: "dominusnode_check_payment",
|
|
409
|
+
label: "DominusNode: Check Crypto Payment Status",
|
|
410
|
+
description: "Check the status of a crypto top-up payment by invoice ID. " +
|
|
411
|
+
"Returns payment status (pending, confirming, completed, expired).",
|
|
412
|
+
parameters: typebox_1.Type.Object({
|
|
413
|
+
invoiceId: typebox_1.Type.String({ description: "Crypto invoice ID (UUID) returned from topup_crypto" }),
|
|
414
|
+
}),
|
|
415
|
+
async execute(_id, params, _signal, _onUpdate, _ctx) {
|
|
416
|
+
return toolkit.checkPayment(String(params.invoiceId ?? ""));
|
|
417
|
+
},
|
|
418
|
+
});
|
|
419
|
+
// ── Tool 31: get_daily_usage ───────────────────────────────────────────
|
|
420
|
+
pi.registerTool({
|
|
421
|
+
name: "dominusnode_get_daily_usage",
|
|
422
|
+
label: "DominusNode: Get Daily Usage Breakdown",
|
|
423
|
+
description: "Get daily bandwidth usage breakdown for the specified number of days. " +
|
|
424
|
+
"Returns per-day bytes transferred and cost.",
|
|
425
|
+
parameters: typebox_1.Type.Object({
|
|
426
|
+
days: typebox_1.Type.Optional(typebox_1.Type.Number({ description: "Number of days to look back (default: 7, max: 365)", minimum: 1, maximum: 365 })),
|
|
427
|
+
}),
|
|
428
|
+
async execute(_id, params, _signal, _onUpdate, _ctx) {
|
|
429
|
+
return toolkit.getDailyUsage(params.days !== undefined ? Number(params.days) : 7);
|
|
430
|
+
},
|
|
431
|
+
});
|
|
432
|
+
// ── Tool 32: get_top_hosts ─────────────────────────────────────────────
|
|
433
|
+
pi.registerTool({
|
|
434
|
+
name: "dominusnode_get_top_hosts",
|
|
435
|
+
label: "DominusNode: Get Top Hosts by Usage",
|
|
436
|
+
description: "Get the top hosts by bandwidth usage. Shows which domains consume the most proxy traffic.",
|
|
437
|
+
parameters: typebox_1.Type.Object({
|
|
438
|
+
limit: typebox_1.Type.Optional(typebox_1.Type.Number({ description: "Number of top hosts to return (default: 10, max: 100)", minimum: 1, maximum: 100 })),
|
|
439
|
+
}),
|
|
440
|
+
async execute(_id, params, _signal, _onUpdate, _ctx) {
|
|
441
|
+
return toolkit.getTopHosts(params.limit !== undefined ? Number(params.limit) : 10);
|
|
442
|
+
},
|
|
443
|
+
});
|
|
444
|
+
// ── Tool 33: register ──────────────────────────────────────────────────
|
|
445
|
+
pi.registerTool({
|
|
446
|
+
name: "dominusnode_register",
|
|
447
|
+
label: "DominusNode: Register Account",
|
|
448
|
+
description: "Register a new Dominus Node account. Does not require authentication. " +
|
|
449
|
+
"Returns user info and initial API key.",
|
|
450
|
+
parameters: typebox_1.Type.Object({
|
|
451
|
+
email: typebox_1.Type.String({ description: "Email address for the new account" }),
|
|
452
|
+
password: typebox_1.Type.String({ description: "Password (8-128 characters)" }),
|
|
453
|
+
}),
|
|
454
|
+
async execute(_id, params, _signal, _onUpdate, _ctx) {
|
|
455
|
+
return toolkit.register(String(params.email ?? ""), String(params.password ?? ""));
|
|
456
|
+
},
|
|
457
|
+
});
|
|
458
|
+
// ── Tool 34: login ─────────────────────────────────────────────────────
|
|
459
|
+
pi.registerTool({
|
|
460
|
+
name: "dominusnode_login",
|
|
461
|
+
label: "DominusNode: Login",
|
|
462
|
+
description: "Log in to an existing Dominus Node account. Does not require authentication. " +
|
|
463
|
+
"Returns JWT access and refresh tokens.",
|
|
464
|
+
parameters: typebox_1.Type.Object({
|
|
465
|
+
email: typebox_1.Type.String({ description: "Account email address" }),
|
|
466
|
+
password: typebox_1.Type.String({ description: "Account password" }),
|
|
467
|
+
}),
|
|
468
|
+
async execute(_id, params, _signal, _onUpdate, _ctx) {
|
|
469
|
+
return toolkit.login(String(params.email ?? ""), String(params.password ?? ""));
|
|
470
|
+
},
|
|
471
|
+
});
|
|
472
|
+
// ── Tool 35: get_account_info ──────────────────────────────────────────
|
|
473
|
+
pi.registerTool({
|
|
474
|
+
name: "dominusnode_get_account_info",
|
|
475
|
+
label: "DominusNode: Get Account Info",
|
|
476
|
+
description: "Get your account profile information including email, plan, verification status, and creation date.",
|
|
477
|
+
parameters: typebox_1.Type.Object({}),
|
|
478
|
+
async execute(_id, _params, _signal, _onUpdate, _ctx) {
|
|
479
|
+
return toolkit.getAccountInfo();
|
|
480
|
+
},
|
|
481
|
+
});
|
|
482
|
+
// ── Tool 36: verify_email ──────────────────────────────────────────────
|
|
483
|
+
pi.registerTool({
|
|
484
|
+
name: "dominusnode_verify_email",
|
|
485
|
+
label: "DominusNode: Verify Email",
|
|
486
|
+
description: "Verify an email address using the verification token sent to the user's email. " +
|
|
487
|
+
"Does not require authentication.",
|
|
488
|
+
parameters: typebox_1.Type.Object({
|
|
489
|
+
token: typebox_1.Type.String({ description: "Email verification token from the verification email" }),
|
|
490
|
+
}),
|
|
491
|
+
async execute(_id, params, _signal, _onUpdate, _ctx) {
|
|
492
|
+
return toolkit.verifyEmail(String(params.token ?? ""));
|
|
493
|
+
},
|
|
494
|
+
});
|
|
495
|
+
// ── Tool 37: resend_verification ───────────────────────────────────────
|
|
496
|
+
pi.registerTool({
|
|
497
|
+
name: "dominusnode_resend_verification",
|
|
498
|
+
label: "DominusNode: Resend Verification Email",
|
|
499
|
+
description: "Resend the email verification link. Requires authentication.",
|
|
500
|
+
parameters: typebox_1.Type.Object({}),
|
|
501
|
+
async execute(_id, _params, _signal, _onUpdate, _ctx) {
|
|
502
|
+
return toolkit.resendVerification();
|
|
503
|
+
},
|
|
504
|
+
});
|
|
505
|
+
// ── Tool 38: update_password ───────────────────────────────────────────
|
|
506
|
+
pi.registerTool({
|
|
507
|
+
name: "dominusnode_update_password",
|
|
508
|
+
label: "DominusNode: Update Password",
|
|
509
|
+
description: "Change your account password. Requires current password for verification.",
|
|
510
|
+
parameters: typebox_1.Type.Object({
|
|
511
|
+
currentPassword: typebox_1.Type.String({ description: "Current account password" }),
|
|
512
|
+
newPassword: typebox_1.Type.String({ description: "New password (8-128 characters)" }),
|
|
513
|
+
}),
|
|
514
|
+
async execute(_id, params, _signal, _onUpdate, _ctx) {
|
|
515
|
+
return toolkit.updatePassword(String(params.currentPassword ?? ""), String(params.newPassword ?? ""));
|
|
516
|
+
},
|
|
517
|
+
});
|
|
518
|
+
// ── Tool 39: list_keys ─────────────────────────────────────────────────
|
|
519
|
+
pi.registerTool({
|
|
520
|
+
name: "dominusnode_list_keys",
|
|
521
|
+
label: "DominusNode: List API Keys",
|
|
522
|
+
description: "List all your personal API keys with their labels, creation dates, and last-used timestamps.",
|
|
523
|
+
parameters: typebox_1.Type.Object({}),
|
|
524
|
+
async execute(_id, _params, _signal, _onUpdate, _ctx) {
|
|
525
|
+
return toolkit.listKeys();
|
|
526
|
+
},
|
|
527
|
+
});
|
|
528
|
+
// ── Tool 40: create_key ────────────────────────────────────────────────
|
|
529
|
+
pi.registerTool({
|
|
530
|
+
name: "dominusnode_create_key",
|
|
531
|
+
label: "DominusNode: Create API Key",
|
|
532
|
+
description: "Create a new personal API key. The key is shown only once -- save it immediately. " +
|
|
533
|
+
"Usage is billed against your personal wallet.",
|
|
534
|
+
parameters: typebox_1.Type.Object({
|
|
535
|
+
label: typebox_1.Type.String({ description: "Label for the API key (e.g. 'production', 'dev-testing')" }),
|
|
536
|
+
}),
|
|
537
|
+
async execute(_id, params, _signal, _onUpdate, _ctx) {
|
|
538
|
+
return toolkit.createKey(String(params.label ?? ""));
|
|
539
|
+
},
|
|
540
|
+
});
|
|
541
|
+
// ── Tool 41: revoke_key ────────────────────────────────────────────────
|
|
542
|
+
pi.registerTool({
|
|
543
|
+
name: "dominusnode_revoke_key",
|
|
544
|
+
label: "DominusNode: Revoke API Key",
|
|
545
|
+
description: "Revoke (delete) a personal API key. This action is irreversible -- " +
|
|
546
|
+
"any applications using this key will lose access immediately.",
|
|
547
|
+
parameters: typebox_1.Type.Object({
|
|
548
|
+
keyId: typebox_1.Type.String({ description: "API key ID (UUID) to revoke" }),
|
|
549
|
+
}),
|
|
550
|
+
async execute(_id, params, _signal, _onUpdate, _ctx) {
|
|
551
|
+
return toolkit.revokeKey(String(params.keyId ?? ""));
|
|
552
|
+
},
|
|
553
|
+
});
|
|
554
|
+
// ── Tool 42: get_plan ──────────────────────────────────────────────────
|
|
555
|
+
pi.registerTool({
|
|
556
|
+
name: "dominusnode_get_plan",
|
|
557
|
+
label: "DominusNode: Get Current Plan",
|
|
558
|
+
description: "Get your current subscription plan including tier, bandwidth limits, and pricing.",
|
|
559
|
+
parameters: typebox_1.Type.Object({}),
|
|
560
|
+
async execute(_id, _params, _signal, _onUpdate, _ctx) {
|
|
561
|
+
return toolkit.getPlan();
|
|
562
|
+
},
|
|
563
|
+
});
|
|
564
|
+
// ── Tool 43: list_plans ────────────────────────────────────────────────
|
|
565
|
+
pi.registerTool({
|
|
566
|
+
name: "dominusnode_list_plans",
|
|
567
|
+
label: "DominusNode: List Available Plans",
|
|
568
|
+
description: "List all available subscription plans with features, pricing, and bandwidth limits.",
|
|
569
|
+
parameters: typebox_1.Type.Object({}),
|
|
570
|
+
async execute(_id, _params, _signal, _onUpdate, _ctx) {
|
|
571
|
+
return toolkit.listPlans();
|
|
572
|
+
},
|
|
573
|
+
});
|
|
574
|
+
// ── Tool 44: change_plan ───────────────────────────────────────────────
|
|
575
|
+
pi.registerTool({
|
|
576
|
+
name: "dominusnode_change_plan",
|
|
577
|
+
label: "DominusNode: Change Subscription Plan",
|
|
578
|
+
description: "Change your subscription plan. Takes effect immediately. " +
|
|
579
|
+
"Use list_plans to see available options.",
|
|
580
|
+
parameters: typebox_1.Type.Object({
|
|
581
|
+
planId: typebox_1.Type.String({ description: "Plan ID (UUID) to switch to" }),
|
|
582
|
+
}),
|
|
583
|
+
async execute(_id, params, _signal, _onUpdate, _ctx) {
|
|
584
|
+
return toolkit.changePlan(String(params.planId ?? ""));
|
|
585
|
+
},
|
|
586
|
+
});
|
|
587
|
+
// ── Tool 45: team_delete ───────────────────────────────────────────────
|
|
588
|
+
pi.registerTool({
|
|
589
|
+
name: "dominusnode_team_delete",
|
|
590
|
+
label: "DominusNode: Delete Team",
|
|
591
|
+
description: "Delete a team. Only the team owner can delete. " +
|
|
592
|
+
"All team keys are revoked and remaining balance is refunded.",
|
|
593
|
+
parameters: typebox_1.Type.Object({
|
|
594
|
+
teamId: typebox_1.Type.String({ description: "Team ID (UUID) to delete" }),
|
|
595
|
+
}),
|
|
596
|
+
async execute(_id, params, _signal, _onUpdate, _ctx) {
|
|
597
|
+
return toolkit.teamDelete(String(params.teamId ?? ""));
|
|
598
|
+
},
|
|
599
|
+
});
|
|
600
|
+
// ── Tool 46: team_revoke_key ───────────────────────────────────────────
|
|
601
|
+
pi.registerTool({
|
|
602
|
+
name: "dominusnode_team_revoke_key",
|
|
603
|
+
label: "DominusNode: Revoke Team API Key",
|
|
604
|
+
description: "Revoke a team API key. Only owners and admins can revoke keys. " +
|
|
605
|
+
"Applications using this key will lose access immediately.",
|
|
606
|
+
parameters: typebox_1.Type.Object({
|
|
607
|
+
teamId: typebox_1.Type.String({ description: "Team ID (UUID)" }),
|
|
608
|
+
keyId: typebox_1.Type.String({ description: "API key ID (UUID) to revoke" }),
|
|
609
|
+
}),
|
|
610
|
+
async execute(_id, params, _signal, _onUpdate, _ctx) {
|
|
611
|
+
return toolkit.teamRevokeKey(String(params.teamId ?? ""), String(params.keyId ?? ""));
|
|
612
|
+
},
|
|
613
|
+
});
|
|
614
|
+
// ── Tool 47: team_list_keys ────────────────────────────────────────────
|
|
615
|
+
pi.registerTool({
|
|
616
|
+
name: "dominusnode_team_list_keys",
|
|
617
|
+
label: "DominusNode: List Team API Keys",
|
|
618
|
+
description: "List all API keys for a team with labels, creation dates, and last-used timestamps.",
|
|
619
|
+
parameters: typebox_1.Type.Object({
|
|
620
|
+
teamId: typebox_1.Type.String({ description: "Team ID (UUID)" }),
|
|
621
|
+
}),
|
|
622
|
+
async execute(_id, params, _signal, _onUpdate, _ctx) {
|
|
623
|
+
return toolkit.teamListKeys(String(params.teamId ?? ""));
|
|
624
|
+
},
|
|
625
|
+
});
|
|
626
|
+
// ── Tool 48: team_list_members ─────────────────────────────────────────
|
|
627
|
+
pi.registerTool({
|
|
628
|
+
name: "dominusnode_team_list_members",
|
|
629
|
+
label: "DominusNode: List Team Members",
|
|
630
|
+
description: "List all members of a team with their roles and join dates.",
|
|
631
|
+
parameters: typebox_1.Type.Object({
|
|
632
|
+
teamId: typebox_1.Type.String({ description: "Team ID (UUID)" }),
|
|
633
|
+
}),
|
|
634
|
+
async execute(_id, params, _signal, _onUpdate, _ctx) {
|
|
635
|
+
return toolkit.teamListMembers(String(params.teamId ?? ""));
|
|
636
|
+
},
|
|
637
|
+
});
|
|
638
|
+
// ── Tool 49: team_add_member ───────────────────────────────────────────
|
|
639
|
+
pi.registerTool({
|
|
640
|
+
name: "dominusnode_team_add_member",
|
|
641
|
+
label: "DominusNode: Add Team Member",
|
|
642
|
+
description: "Add a user directly to a team by user ID. Only owners and admins can add members.",
|
|
643
|
+
parameters: typebox_1.Type.Object({
|
|
644
|
+
teamId: typebox_1.Type.String({ description: "Team ID (UUID)" }),
|
|
645
|
+
userId: typebox_1.Type.String({ description: "User ID (UUID) of the user to add" }),
|
|
646
|
+
role: typebox_1.Type.Optional(typebox_1.Type.Union([typebox_1.Type.Literal("member"), typebox_1.Type.Literal("admin")], { description: "Role for the new member (default: 'member')" })),
|
|
647
|
+
}),
|
|
648
|
+
async execute(_id, params, _signal, _onUpdate, _ctx) {
|
|
649
|
+
return toolkit.teamAddMember(String(params.teamId ?? ""), String(params.userId ?? ""), params.role !== undefined ? String(params.role) : "member");
|
|
650
|
+
},
|
|
651
|
+
});
|
|
652
|
+
// ── Tool 50: team_remove_member ────────────────────────────────────────
|
|
653
|
+
pi.registerTool({
|
|
654
|
+
name: "dominusnode_team_remove_member",
|
|
655
|
+
label: "DominusNode: Remove Team Member",
|
|
656
|
+
description: "Remove a member from a team. Only owners and admins can remove members.",
|
|
657
|
+
parameters: typebox_1.Type.Object({
|
|
658
|
+
teamId: typebox_1.Type.String({ description: "Team ID (UUID)" }),
|
|
659
|
+
userId: typebox_1.Type.String({ description: "User ID (UUID) of the member to remove" }),
|
|
660
|
+
}),
|
|
661
|
+
async execute(_id, params, _signal, _onUpdate, _ctx) {
|
|
662
|
+
return toolkit.teamRemoveMember(String(params.teamId ?? ""), String(params.userId ?? ""));
|
|
663
|
+
},
|
|
664
|
+
});
|
|
665
|
+
// ── Tool 51: team_invite_member ────────────────────────────────────────
|
|
666
|
+
pi.registerTool({
|
|
667
|
+
name: "dominusnode_team_invite_member",
|
|
668
|
+
label: "DominusNode: Invite Team Member",
|
|
669
|
+
description: "Invite a user to join a team by email address. The user will receive an invitation email.",
|
|
670
|
+
parameters: typebox_1.Type.Object({
|
|
671
|
+
teamId: typebox_1.Type.String({ description: "Team ID (UUID)" }),
|
|
672
|
+
email: typebox_1.Type.String({ description: "Email address of the user to invite" }),
|
|
673
|
+
role: typebox_1.Type.Optional(typebox_1.Type.Union([typebox_1.Type.Literal("member"), typebox_1.Type.Literal("admin")], { description: "Role for the invited member (default: 'member')" })),
|
|
674
|
+
}),
|
|
675
|
+
async execute(_id, params, _signal, _onUpdate, _ctx) {
|
|
676
|
+
return toolkit.teamInviteMember(String(params.teamId ?? ""), String(params.email ?? ""), params.role !== undefined ? String(params.role) : "member");
|
|
677
|
+
},
|
|
678
|
+
});
|
|
679
|
+
// ── Tool 52: team_list_invites ─────────────────────────────────────────
|
|
680
|
+
pi.registerTool({
|
|
681
|
+
name: "dominusnode_team_list_invites",
|
|
682
|
+
label: "DominusNode: List Team Invites",
|
|
683
|
+
description: "List all pending invitations for a team.",
|
|
684
|
+
parameters: typebox_1.Type.Object({
|
|
685
|
+
teamId: typebox_1.Type.String({ description: "Team ID (UUID)" }),
|
|
686
|
+
}),
|
|
687
|
+
async execute(_id, params, _signal, _onUpdate, _ctx) {
|
|
688
|
+
return toolkit.teamListInvites(String(params.teamId ?? ""));
|
|
689
|
+
},
|
|
690
|
+
});
|
|
691
|
+
// ── Tool 53: team_cancel_invite ────────────────────────────────────────
|
|
692
|
+
pi.registerTool({
|
|
693
|
+
name: "dominusnode_team_cancel_invite",
|
|
694
|
+
label: "DominusNode: Cancel Team Invite",
|
|
695
|
+
description: "Cancel a pending team invitation. Only owners and admins can cancel invites.",
|
|
696
|
+
parameters: typebox_1.Type.Object({
|
|
697
|
+
teamId: typebox_1.Type.String({ description: "Team ID (UUID)" }),
|
|
698
|
+
inviteId: typebox_1.Type.String({ description: "Invite ID (UUID) to cancel" }),
|
|
699
|
+
}),
|
|
700
|
+
async execute(_id, params, _signal, _onUpdate, _ctx) {
|
|
701
|
+
return toolkit.teamCancelInvite(String(params.teamId ?? ""), String(params.inviteId ?? ""));
|
|
702
|
+
},
|
|
703
|
+
});
|
|
373
704
|
}
|
package/dist/toolkit.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Dominus Node Pi Extension Toolkit
|
|
3
3
|
*
|
|
4
|
-
* Provides
|
|
4
|
+
* Provides 53 tools for the pi-mono agent framework (github.com/badlogic/pi-mono).
|
|
5
5
|
* Covers proxied fetching, wallet management, agentic wallets, teams,
|
|
6
6
|
* Stripe/PayPal/crypto top-up, and x402 micropayment info.
|
|
7
7
|
*
|
|
@@ -50,6 +50,8 @@ export interface DominusNodeToolkitOptions {
|
|
|
50
50
|
proxyHost?: string;
|
|
51
51
|
proxyPort?: number;
|
|
52
52
|
timeout?: number;
|
|
53
|
+
/** Optional agent secret for MCP agent auto-verification (bypasses reCAPTCHA). */
|
|
54
|
+
agentSecret?: string;
|
|
53
55
|
}
|
|
54
56
|
export declare class DominusNodeToolkit {
|
|
55
57
|
private apiKey;
|
|
@@ -57,6 +59,7 @@ export declare class DominusNodeToolkit {
|
|
|
57
59
|
private proxyHost;
|
|
58
60
|
private proxyPort;
|
|
59
61
|
private timeout;
|
|
62
|
+
private agentSecret?;
|
|
60
63
|
private token;
|
|
61
64
|
private tokenExpiresAt;
|
|
62
65
|
private _authPromise;
|
|
@@ -91,4 +94,35 @@ export declare class DominusNodeToolkit {
|
|
|
91
94
|
topupCrypto(amountUsd: number, currency: string): Promise<PiToolResult>;
|
|
92
95
|
x402Info(): Promise<PiToolResult>;
|
|
93
96
|
updateWalletPolicy(walletId: string, dailyLimitCents?: number, allowedDomains?: string[]): Promise<PiToolResult>;
|
|
97
|
+
private _rawRequest;
|
|
98
|
+
private static readonly EMAIL_RE;
|
|
99
|
+
private static validateEmail;
|
|
100
|
+
private static validatePassword;
|
|
101
|
+
getProxyStatus(): Promise<PiToolResult>;
|
|
102
|
+
getTransactions(limit?: number): Promise<PiToolResult>;
|
|
103
|
+
getForecast(): Promise<PiToolResult>;
|
|
104
|
+
checkPayment(invoiceId: string): Promise<PiToolResult>;
|
|
105
|
+
getDailyUsage(days?: number): Promise<PiToolResult>;
|
|
106
|
+
getTopHosts(limit?: number): Promise<PiToolResult>;
|
|
107
|
+
register(email: string, password: string): Promise<PiToolResult>;
|
|
108
|
+
login(email: string, password: string): Promise<PiToolResult>;
|
|
109
|
+
getAccountInfo(): Promise<PiToolResult>;
|
|
110
|
+
verifyEmail(token: string): Promise<PiToolResult>;
|
|
111
|
+
resendVerification(): Promise<PiToolResult>;
|
|
112
|
+
updatePassword(currentPassword: string, newPassword: string): Promise<PiToolResult>;
|
|
113
|
+
listKeys(): Promise<PiToolResult>;
|
|
114
|
+
createKey(label: string): Promise<PiToolResult>;
|
|
115
|
+
revokeKey(keyId: string): Promise<PiToolResult>;
|
|
116
|
+
getPlan(): Promise<PiToolResult>;
|
|
117
|
+
listPlans(): Promise<PiToolResult>;
|
|
118
|
+
changePlan(planId: string): Promise<PiToolResult>;
|
|
119
|
+
teamDelete(teamId: string): Promise<PiToolResult>;
|
|
120
|
+
teamRevokeKey(teamId: string, keyId: string): Promise<PiToolResult>;
|
|
121
|
+
teamListKeys(teamId: string): Promise<PiToolResult>;
|
|
122
|
+
teamListMembers(teamId: string): Promise<PiToolResult>;
|
|
123
|
+
teamAddMember(teamId: string, userId: string, role?: string): Promise<PiToolResult>;
|
|
124
|
+
teamRemoveMember(teamId: string, userId: string): Promise<PiToolResult>;
|
|
125
|
+
teamInviteMember(teamId: string, email: string, role?: string): Promise<PiToolResult>;
|
|
126
|
+
teamListInvites(teamId: string): Promise<PiToolResult>;
|
|
127
|
+
teamCancelInvite(teamId: string, inviteId: string): Promise<PiToolResult>;
|
|
94
128
|
}
|
package/dist/toolkit.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
/**
|
|
3
3
|
* Dominus Node Pi Extension Toolkit
|
|
4
4
|
*
|
|
5
|
-
* Provides
|
|
5
|
+
* Provides 53 tools for the pi-mono agent framework (github.com/badlogic/pi-mono).
|
|
6
6
|
* Covers proxied fetching, wallet management, agentic wallets, teams,
|
|
7
7
|
* Stripe/PayPal/crypto top-up, and x402 micropayment info.
|
|
8
8
|
*
|
|
@@ -381,6 +381,7 @@ class DominusNodeToolkit {
|
|
|
381
381
|
proxyHost;
|
|
382
382
|
proxyPort;
|
|
383
383
|
timeout;
|
|
384
|
+
agentSecret;
|
|
384
385
|
token = null;
|
|
385
386
|
tokenExpiresAt = 0;
|
|
386
387
|
_authPromise = null; // H-1: mutex for concurrent _ensureAuth
|
|
@@ -418,6 +419,7 @@ class DominusNodeToolkit {
|
|
|
418
419
|
// H-2: Validate timeout option; store but use REQUEST_TIMEOUT_MS constant for requests
|
|
419
420
|
const tVal = Number(options.timeout ?? 30000);
|
|
420
421
|
this.timeout = Number.isFinite(tVal) && tVal >= 1000 && tVal <= 120000 ? tVal : 30000;
|
|
422
|
+
this.agentSecret = options.agentSecret || process.env["DOMINUSNODE_AGENT_SECRET"];
|
|
421
423
|
}
|
|
422
424
|
// -----------------------------------------------------------------------
|
|
423
425
|
// Authentication
|
|
@@ -428,9 +430,17 @@ class DominusNodeToolkit {
|
|
|
428
430
|
if (!this.apiKey.startsWith("dn_live_") && !this.apiKey.startsWith("dn_test_")) {
|
|
429
431
|
throw new Error('DOMINUSNODE_API_KEY must start with "dn_live_" or "dn_test_".');
|
|
430
432
|
}
|
|
433
|
+
const authHeaders = {
|
|
434
|
+
"Content-Type": "application/json",
|
|
435
|
+
"User-Agent": "dominusnode-pi/1.0.0",
|
|
436
|
+
};
|
|
437
|
+
if (this.agentSecret) {
|
|
438
|
+
authHeaders["X-DominusNode-Agent"] = "mcp";
|
|
439
|
+
authHeaders["X-DominusNode-Agent-Secret"] = this.agentSecret;
|
|
440
|
+
}
|
|
431
441
|
const res = await fetch(`${this.baseUrl}/api/auth/verify-key`, {
|
|
432
442
|
method: "POST",
|
|
433
|
-
headers:
|
|
443
|
+
headers: authHeaders,
|
|
434
444
|
body: JSON.stringify({ apiKey: this.apiKey }),
|
|
435
445
|
redirect: "error",
|
|
436
446
|
signal: AbortSignal.timeout(REQUEST_TIMEOUT_MS),
|
|
@@ -491,6 +501,10 @@ class DominusNodeToolkit {
|
|
|
491
501
|
Accept: "application/json",
|
|
492
502
|
"User-Agent": "dominusnode-pi/1.0.0",
|
|
493
503
|
};
|
|
504
|
+
if (this.agentSecret) {
|
|
505
|
+
headers["X-DominusNode-Agent"] = "mcp";
|
|
506
|
+
headers["X-DominusNode-Agent-Secret"] = this.agentSecret;
|
|
507
|
+
}
|
|
494
508
|
const init = { method, headers, signal: AbortSignal.timeout(REQUEST_TIMEOUT_MS), redirect: "error" };
|
|
495
509
|
// M-6: Drop body on safe HTTP methods
|
|
496
510
|
if (body && !["GET", "HEAD"].includes(method) && ["POST", "PUT", "PATCH", "DELETE"].includes(method)) {
|
|
@@ -775,7 +789,7 @@ class DominusNodeToolkit {
|
|
|
775
789
|
const amount = Math.floor(Number(amountCents));
|
|
776
790
|
if (isNaN(amount) || amount < 1 || amount > 1000000)
|
|
777
791
|
return err("amountCents must be between 1 and 1,000,000");
|
|
778
|
-
const data = await this._req("POST", `/api/agent-wallet/${id}/fund`, { amountCents: amount });
|
|
792
|
+
const data = await this._req("POST", `/api/agent-wallet/${encodeURIComponent(id)}/fund`, { amountCents: amount });
|
|
779
793
|
return ok(JSON.stringify(data, null, 2));
|
|
780
794
|
}
|
|
781
795
|
catch (e) {
|
|
@@ -788,7 +802,7 @@ class DominusNodeToolkit {
|
|
|
788
802
|
async checkAgenticBalance(walletId) {
|
|
789
803
|
try {
|
|
790
804
|
const id = validateUuid(walletId, "walletId");
|
|
791
|
-
const data = await this._req("GET", `/api/agent-wallet/${id}`);
|
|
805
|
+
const data = await this._req("GET", `/api/agent-wallet/${encodeURIComponent(id)}`);
|
|
792
806
|
return ok(JSON.stringify(data, null, 2));
|
|
793
807
|
}
|
|
794
808
|
catch (e) {
|
|
@@ -817,7 +831,7 @@ class DominusNodeToolkit {
|
|
|
817
831
|
if (!Number.isFinite(rawLim))
|
|
818
832
|
return err("limit must be a finite number");
|
|
819
833
|
const lim = Math.max(1, Math.min(100, Math.floor(rawLim)));
|
|
820
|
-
const data = await this._req("GET", `/api/agent-wallet/${id}/transactions?limit=${lim}`);
|
|
834
|
+
const data = await this._req("GET", `/api/agent-wallet/${encodeURIComponent(id)}/transactions?limit=${lim}`);
|
|
821
835
|
return ok(JSON.stringify(data, null, 2));
|
|
822
836
|
}
|
|
823
837
|
catch (e) {
|
|
@@ -830,7 +844,7 @@ class DominusNodeToolkit {
|
|
|
830
844
|
async freezeAgenticWallet(walletId) {
|
|
831
845
|
try {
|
|
832
846
|
const id = validateUuid(walletId, "walletId");
|
|
833
|
-
const data = await this._req("POST", `/api/agent-wallet/${id}/freeze`);
|
|
847
|
+
const data = await this._req("POST", `/api/agent-wallet/${encodeURIComponent(id)}/freeze`);
|
|
834
848
|
return ok(JSON.stringify(data, null, 2));
|
|
835
849
|
}
|
|
836
850
|
catch (e) {
|
|
@@ -843,7 +857,7 @@ class DominusNodeToolkit {
|
|
|
843
857
|
async unfreezeAgenticWallet(walletId) {
|
|
844
858
|
try {
|
|
845
859
|
const id = validateUuid(walletId, "walletId");
|
|
846
|
-
const data = await this._req("POST", `/api/agent-wallet/${id}/unfreeze`);
|
|
860
|
+
const data = await this._req("POST", `/api/agent-wallet/${encodeURIComponent(id)}/unfreeze`);
|
|
847
861
|
return ok(JSON.stringify(data, null, 2));
|
|
848
862
|
}
|
|
849
863
|
catch (e) {
|
|
@@ -856,7 +870,7 @@ class DominusNodeToolkit {
|
|
|
856
870
|
async deleteAgenticWallet(walletId) {
|
|
857
871
|
try {
|
|
858
872
|
const id = validateUuid(walletId, "walletId");
|
|
859
|
-
const data = await this._req("DELETE", `/api/agent-wallet/${id}`);
|
|
873
|
+
const data = await this._req("DELETE", `/api/agent-wallet/${encodeURIComponent(id)}`);
|
|
860
874
|
return ok(JSON.stringify(data, null, 2));
|
|
861
875
|
}
|
|
862
876
|
catch (e) {
|
|
@@ -903,7 +917,7 @@ class DominusNodeToolkit {
|
|
|
903
917
|
async teamDetails(teamId) {
|
|
904
918
|
try {
|
|
905
919
|
const id = validateUuid(teamId, "teamId");
|
|
906
|
-
const data = await this._req("GET", `/api/teams/${id}`);
|
|
920
|
+
const data = await this._req("GET", `/api/teams/${encodeURIComponent(id)}`);
|
|
907
921
|
return ok(JSON.stringify(data, null, 2));
|
|
908
922
|
}
|
|
909
923
|
catch (e) {
|
|
@@ -919,7 +933,7 @@ class DominusNodeToolkit {
|
|
|
919
933
|
const amount = Math.floor(Number(amountCents));
|
|
920
934
|
if (isNaN(amount) || amount < 1 || amount > 1000000)
|
|
921
935
|
return err("amountCents must be between 1 and 1,000,000");
|
|
922
|
-
const data = await this._req("POST", `/api/teams/${id}/wallet/fund`, { amountCents: amount });
|
|
936
|
+
const data = await this._req("POST", `/api/teams/${encodeURIComponent(id)}/wallet/fund`, { amountCents: amount });
|
|
923
937
|
return ok(JSON.stringify(data, null, 2));
|
|
924
938
|
}
|
|
925
939
|
catch (e) {
|
|
@@ -935,7 +949,7 @@ class DominusNodeToolkit {
|
|
|
935
949
|
const labelErr = validateLabel(label);
|
|
936
950
|
if (labelErr)
|
|
937
951
|
return err(labelErr);
|
|
938
|
-
const data = await this._req("POST", `/api/teams/${id}/keys`, { label: label.trim() });
|
|
952
|
+
const data = await this._req("POST", `/api/teams/${encodeURIComponent(id)}/keys`, { label: label.trim() });
|
|
939
953
|
return ok(JSON.stringify(data, null, 2) + "\n\nIMPORTANT: Store this API key securely — it will not be shown again.");
|
|
940
954
|
}
|
|
941
955
|
catch (e) {
|
|
@@ -954,7 +968,7 @@ class DominusNodeToolkit {
|
|
|
954
968
|
const d = Math.max(1, Math.min(365, Math.floor(rawDays)));
|
|
955
969
|
const until = new Date().toISOString();
|
|
956
970
|
const since = new Date(Date.now() - d * 86400000).toISOString();
|
|
957
|
-
const data = await this._req("GET", `/api/teams/${id}/usage?since=${encodeURIComponent(since)}&until=${encodeURIComponent(until)}`);
|
|
971
|
+
const data = await this._req("GET", `/api/teams/${encodeURIComponent(id)}/usage?since=${encodeURIComponent(since)}&until=${encodeURIComponent(until)}`);
|
|
958
972
|
return ok(JSON.stringify(data, null, 2));
|
|
959
973
|
}
|
|
960
974
|
catch (e) {
|
|
@@ -982,7 +996,7 @@ class DominusNodeToolkit {
|
|
|
982
996
|
}
|
|
983
997
|
if (!Object.keys(body).length)
|
|
984
998
|
return err("At least one of name or maxMembers must be provided");
|
|
985
|
-
const data = await this._req("PATCH", `/api/teams/${id}`, body);
|
|
999
|
+
const data = await this._req("PATCH", `/api/teams/${encodeURIComponent(id)}`, body);
|
|
986
1000
|
return ok(JSON.stringify(data, null, 2));
|
|
987
1001
|
}
|
|
988
1002
|
catch (e) {
|
|
@@ -1098,7 +1112,477 @@ class DominusNodeToolkit {
|
|
|
1098
1112
|
}
|
|
1099
1113
|
if (!Object.keys(body).length)
|
|
1100
1114
|
return err("At least one of dailyLimitCents or allowedDomains must be provided");
|
|
1101
|
-
const data = await this._req("PATCH", `/api/agent-wallet/${id}/policy`, body);
|
|
1115
|
+
const data = await this._req("PATCH", `/api/agent-wallet/${encodeURIComponent(id)}/policy`, body);
|
|
1116
|
+
return ok(JSON.stringify(data, null, 2));
|
|
1117
|
+
}
|
|
1118
|
+
catch (e) {
|
|
1119
|
+
return err(e);
|
|
1120
|
+
}
|
|
1121
|
+
}
|
|
1122
|
+
// -----------------------------------------------------------------------
|
|
1123
|
+
// Unauthenticated request helper (register, login, verify-email)
|
|
1124
|
+
// -----------------------------------------------------------------------
|
|
1125
|
+
async _rawRequest(method, path, body) {
|
|
1126
|
+
const url = `${this.baseUrl}${path}`;
|
|
1127
|
+
const headers = {
|
|
1128
|
+
Accept: "application/json",
|
|
1129
|
+
"User-Agent": "dominusnode-pi/1.0.0",
|
|
1130
|
+
};
|
|
1131
|
+
if (this.agentSecret) {
|
|
1132
|
+
headers["X-DominusNode-Agent"] = "mcp";
|
|
1133
|
+
headers["X-DominusNode-Agent-Secret"] = this.agentSecret;
|
|
1134
|
+
}
|
|
1135
|
+
const init = { method, headers, signal: AbortSignal.timeout(REQUEST_TIMEOUT_MS), redirect: "error" };
|
|
1136
|
+
if (body && ["POST", "PUT", "PATCH", "DELETE"].includes(method)) {
|
|
1137
|
+
headers["Content-Type"] = "application/json";
|
|
1138
|
+
init.body = JSON.stringify(body);
|
|
1139
|
+
}
|
|
1140
|
+
let res;
|
|
1141
|
+
try {
|
|
1142
|
+
res = await fetch(url, init);
|
|
1143
|
+
}
|
|
1144
|
+
catch (e) {
|
|
1145
|
+
throw new Error(`API request failed: ${safeError(e)}`);
|
|
1146
|
+
}
|
|
1147
|
+
let rawText = "";
|
|
1148
|
+
if (res.body) {
|
|
1149
|
+
const reader = res.body.getReader();
|
|
1150
|
+
const chunks = [];
|
|
1151
|
+
let totalBytes = 0;
|
|
1152
|
+
try {
|
|
1153
|
+
while (true) {
|
|
1154
|
+
const { done, value } = await reader.read();
|
|
1155
|
+
if (done)
|
|
1156
|
+
break;
|
|
1157
|
+
totalBytes += value.length;
|
|
1158
|
+
if (totalBytes > MAX_RESPONSE_BYTES) {
|
|
1159
|
+
reader.cancel().catch(() => { });
|
|
1160
|
+
throw new Error("API response too large");
|
|
1161
|
+
}
|
|
1162
|
+
chunks.push(value);
|
|
1163
|
+
}
|
|
1164
|
+
}
|
|
1165
|
+
catch (e) {
|
|
1166
|
+
reader.cancel().catch(() => { });
|
|
1167
|
+
throw e;
|
|
1168
|
+
}
|
|
1169
|
+
rawText = Buffer.concat(chunks).toString("utf-8");
|
|
1170
|
+
}
|
|
1171
|
+
if (!res.ok) {
|
|
1172
|
+
let msg = `API error ${res.status}`;
|
|
1173
|
+
try {
|
|
1174
|
+
const parsed = JSON.parse(rawText);
|
|
1175
|
+
stripDangerousKeys(parsed);
|
|
1176
|
+
const detail = parsed.error ?? parsed.message;
|
|
1177
|
+
if (detail)
|
|
1178
|
+
msg = `API error ${res.status}: ${scrubCredentials(String(detail))}`;
|
|
1179
|
+
}
|
|
1180
|
+
catch {
|
|
1181
|
+
if (rawText)
|
|
1182
|
+
msg = `API error ${res.status}: ${scrubCredentials(rawText.slice(0, 200))}`;
|
|
1183
|
+
}
|
|
1184
|
+
throw new Error(msg);
|
|
1185
|
+
}
|
|
1186
|
+
if (!rawText || !rawText.trim())
|
|
1187
|
+
return {};
|
|
1188
|
+
try {
|
|
1189
|
+
const parsed = JSON.parse(rawText);
|
|
1190
|
+
stripDangerousKeys(parsed);
|
|
1191
|
+
return parsed;
|
|
1192
|
+
}
|
|
1193
|
+
catch {
|
|
1194
|
+
throw new Error("Failed to parse API response as JSON");
|
|
1195
|
+
}
|
|
1196
|
+
}
|
|
1197
|
+
// -----------------------------------------------------------------------
|
|
1198
|
+
// Validation helpers for account tools
|
|
1199
|
+
// -----------------------------------------------------------------------
|
|
1200
|
+
static EMAIL_RE = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
|
1201
|
+
static validateEmail(email) {
|
|
1202
|
+
const trimmed = email.trim();
|
|
1203
|
+
if (!trimmed || !DominusNodeToolkit.EMAIL_RE.test(trimmed)) {
|
|
1204
|
+
throw new Error("Invalid email address.");
|
|
1205
|
+
}
|
|
1206
|
+
if (trimmed.length > 254) {
|
|
1207
|
+
throw new Error("Email address too long (max 254 characters).");
|
|
1208
|
+
}
|
|
1209
|
+
return trimmed;
|
|
1210
|
+
}
|
|
1211
|
+
static validatePassword(password) {
|
|
1212
|
+
if (!password || password.length < 8) {
|
|
1213
|
+
throw new Error("Password must be at least 8 characters.");
|
|
1214
|
+
}
|
|
1215
|
+
if (password.length > 128) {
|
|
1216
|
+
throw new Error("Password must be at most 128 characters.");
|
|
1217
|
+
}
|
|
1218
|
+
return password;
|
|
1219
|
+
}
|
|
1220
|
+
// -----------------------------------------------------------------------
|
|
1221
|
+
// Tool 27: getProxyStatus
|
|
1222
|
+
// -----------------------------------------------------------------------
|
|
1223
|
+
async getProxyStatus() {
|
|
1224
|
+
try {
|
|
1225
|
+
const data = await this._req("GET", "/api/proxy/status");
|
|
1226
|
+
return ok(JSON.stringify(data, null, 2));
|
|
1227
|
+
}
|
|
1228
|
+
catch (e) {
|
|
1229
|
+
return err(e);
|
|
1230
|
+
}
|
|
1231
|
+
}
|
|
1232
|
+
// -----------------------------------------------------------------------
|
|
1233
|
+
// Tool 28: getTransactions
|
|
1234
|
+
// -----------------------------------------------------------------------
|
|
1235
|
+
async getTransactions(limit = 20) {
|
|
1236
|
+
try {
|
|
1237
|
+
const rawLim = Number(limit);
|
|
1238
|
+
if (!Number.isFinite(rawLim))
|
|
1239
|
+
return err("limit must be a finite number");
|
|
1240
|
+
const lim = Math.max(1, Math.min(100, Math.floor(rawLim)));
|
|
1241
|
+
const data = await this._req("GET", `/api/wallet/transactions?limit=${lim}`);
|
|
1242
|
+
return ok(JSON.stringify(data, null, 2));
|
|
1243
|
+
}
|
|
1244
|
+
catch (e) {
|
|
1245
|
+
return err(e);
|
|
1246
|
+
}
|
|
1247
|
+
}
|
|
1248
|
+
// -----------------------------------------------------------------------
|
|
1249
|
+
// Tool 29: getForecast
|
|
1250
|
+
// -----------------------------------------------------------------------
|
|
1251
|
+
async getForecast() {
|
|
1252
|
+
try {
|
|
1253
|
+
const data = await this._req("GET", "/api/wallet/forecast");
|
|
1254
|
+
return ok(JSON.stringify(data, null, 2));
|
|
1255
|
+
}
|
|
1256
|
+
catch (e) {
|
|
1257
|
+
return err(e);
|
|
1258
|
+
}
|
|
1259
|
+
}
|
|
1260
|
+
// -----------------------------------------------------------------------
|
|
1261
|
+
// Tool 30: checkPayment
|
|
1262
|
+
// -----------------------------------------------------------------------
|
|
1263
|
+
async checkPayment(invoiceId) {
|
|
1264
|
+
try {
|
|
1265
|
+
const id = validateUuid(invoiceId, "invoiceId");
|
|
1266
|
+
const data = await this._req("GET", `/api/wallet/topup/crypto/${encodeURIComponent(id)}/status`);
|
|
1267
|
+
return ok(JSON.stringify(data, null, 2));
|
|
1268
|
+
}
|
|
1269
|
+
catch (e) {
|
|
1270
|
+
return err(e);
|
|
1271
|
+
}
|
|
1272
|
+
}
|
|
1273
|
+
// -----------------------------------------------------------------------
|
|
1274
|
+
// Tool 31: getDailyUsage
|
|
1275
|
+
// -----------------------------------------------------------------------
|
|
1276
|
+
async getDailyUsage(days = 7) {
|
|
1277
|
+
try {
|
|
1278
|
+
const rawDays = Number(days);
|
|
1279
|
+
if (!Number.isFinite(rawDays))
|
|
1280
|
+
return err("days must be a finite number between 1 and 365");
|
|
1281
|
+
const d = Math.max(1, Math.min(365, Math.floor(rawDays)));
|
|
1282
|
+
const data = await this._req("GET", `/api/usage/daily?days=${d}`);
|
|
1283
|
+
return ok(JSON.stringify(data, null, 2));
|
|
1284
|
+
}
|
|
1285
|
+
catch (e) {
|
|
1286
|
+
return err(e);
|
|
1287
|
+
}
|
|
1288
|
+
}
|
|
1289
|
+
// -----------------------------------------------------------------------
|
|
1290
|
+
// Tool 32: getTopHosts
|
|
1291
|
+
// -----------------------------------------------------------------------
|
|
1292
|
+
async getTopHosts(limit = 10) {
|
|
1293
|
+
try {
|
|
1294
|
+
const rawLim = Number(limit);
|
|
1295
|
+
if (!Number.isFinite(rawLim))
|
|
1296
|
+
return err("limit must be a finite number");
|
|
1297
|
+
const lim = Math.max(1, Math.min(100, Math.floor(rawLim)));
|
|
1298
|
+
const data = await this._req("GET", `/api/usage/top-hosts?limit=${lim}`);
|
|
1299
|
+
return ok(JSON.stringify(data, null, 2));
|
|
1300
|
+
}
|
|
1301
|
+
catch (e) {
|
|
1302
|
+
return err(e);
|
|
1303
|
+
}
|
|
1304
|
+
}
|
|
1305
|
+
// -----------------------------------------------------------------------
|
|
1306
|
+
// Tool 33: register
|
|
1307
|
+
// -----------------------------------------------------------------------
|
|
1308
|
+
async register(email, password) {
|
|
1309
|
+
try {
|
|
1310
|
+
const safeEmail = DominusNodeToolkit.validateEmail(email);
|
|
1311
|
+
const safePassword = DominusNodeToolkit.validatePassword(password);
|
|
1312
|
+
const data = await this._rawRequest("POST", "/api/auth/register", { email: safeEmail, password: safePassword });
|
|
1313
|
+
return ok(JSON.stringify(data, null, 2));
|
|
1314
|
+
}
|
|
1315
|
+
catch (e) {
|
|
1316
|
+
return err(e);
|
|
1317
|
+
}
|
|
1318
|
+
}
|
|
1319
|
+
// -----------------------------------------------------------------------
|
|
1320
|
+
// Tool 34: login
|
|
1321
|
+
// -----------------------------------------------------------------------
|
|
1322
|
+
async login(email, password) {
|
|
1323
|
+
try {
|
|
1324
|
+
const safeEmail = DominusNodeToolkit.validateEmail(email);
|
|
1325
|
+
const safePassword = DominusNodeToolkit.validatePassword(password);
|
|
1326
|
+
const data = await this._rawRequest("POST", "/api/auth/login", { email: safeEmail, password: safePassword });
|
|
1327
|
+
return ok(JSON.stringify(data, null, 2));
|
|
1328
|
+
}
|
|
1329
|
+
catch (e) {
|
|
1330
|
+
return err(e);
|
|
1331
|
+
}
|
|
1332
|
+
}
|
|
1333
|
+
// -----------------------------------------------------------------------
|
|
1334
|
+
// Tool 35: getAccountInfo
|
|
1335
|
+
// -----------------------------------------------------------------------
|
|
1336
|
+
async getAccountInfo() {
|
|
1337
|
+
try {
|
|
1338
|
+
const data = await this._req("GET", "/api/auth/me");
|
|
1339
|
+
return ok(JSON.stringify(data, null, 2));
|
|
1340
|
+
}
|
|
1341
|
+
catch (e) {
|
|
1342
|
+
return err(e);
|
|
1343
|
+
}
|
|
1344
|
+
}
|
|
1345
|
+
// -----------------------------------------------------------------------
|
|
1346
|
+
// Tool 36: verifyEmail
|
|
1347
|
+
// -----------------------------------------------------------------------
|
|
1348
|
+
async verifyEmail(token) {
|
|
1349
|
+
try {
|
|
1350
|
+
if (!token || typeof token !== "string" || token.trim().length === 0) {
|
|
1351
|
+
return err("Verification token is required.");
|
|
1352
|
+
}
|
|
1353
|
+
if (/[\x00-\x1f\x7f]/.test(token)) {
|
|
1354
|
+
return err("Token contains invalid control characters.");
|
|
1355
|
+
}
|
|
1356
|
+
const data = await this._rawRequest("POST", "/api/auth/verify-email", { token: token.trim() });
|
|
1357
|
+
return ok(JSON.stringify(data, null, 2));
|
|
1358
|
+
}
|
|
1359
|
+
catch (e) {
|
|
1360
|
+
return err(e);
|
|
1361
|
+
}
|
|
1362
|
+
}
|
|
1363
|
+
// -----------------------------------------------------------------------
|
|
1364
|
+
// Tool 37: resendVerification
|
|
1365
|
+
// -----------------------------------------------------------------------
|
|
1366
|
+
async resendVerification() {
|
|
1367
|
+
try {
|
|
1368
|
+
const data = await this._req("POST", "/api/auth/resend-verification");
|
|
1369
|
+
return ok(JSON.stringify(data, null, 2));
|
|
1370
|
+
}
|
|
1371
|
+
catch (e) {
|
|
1372
|
+
return err(e);
|
|
1373
|
+
}
|
|
1374
|
+
}
|
|
1375
|
+
// -----------------------------------------------------------------------
|
|
1376
|
+
// Tool 38: updatePassword
|
|
1377
|
+
// -----------------------------------------------------------------------
|
|
1378
|
+
async updatePassword(currentPassword, newPassword) {
|
|
1379
|
+
try {
|
|
1380
|
+
DominusNodeToolkit.validatePassword(currentPassword);
|
|
1381
|
+
DominusNodeToolkit.validatePassword(newPassword);
|
|
1382
|
+
const data = await this._req("POST", "/api/auth/change-password", { currentPassword, newPassword });
|
|
1383
|
+
return ok(JSON.stringify(data, null, 2));
|
|
1384
|
+
}
|
|
1385
|
+
catch (e) {
|
|
1386
|
+
return err(e);
|
|
1387
|
+
}
|
|
1388
|
+
}
|
|
1389
|
+
// -----------------------------------------------------------------------
|
|
1390
|
+
// Tool 39: listKeys
|
|
1391
|
+
// -----------------------------------------------------------------------
|
|
1392
|
+
async listKeys() {
|
|
1393
|
+
try {
|
|
1394
|
+
const data = await this._req("GET", "/api/keys");
|
|
1395
|
+
return ok(JSON.stringify(data, null, 2));
|
|
1396
|
+
}
|
|
1397
|
+
catch (e) {
|
|
1398
|
+
return err(e);
|
|
1399
|
+
}
|
|
1400
|
+
}
|
|
1401
|
+
// -----------------------------------------------------------------------
|
|
1402
|
+
// Tool 40: createKey
|
|
1403
|
+
// -----------------------------------------------------------------------
|
|
1404
|
+
async createKey(label) {
|
|
1405
|
+
try {
|
|
1406
|
+
const labelErr = validateLabel(label);
|
|
1407
|
+
if (labelErr)
|
|
1408
|
+
return err(labelErr);
|
|
1409
|
+
const data = await this._req("POST", "/api/keys", { label: label.trim() });
|
|
1410
|
+
return ok(JSON.stringify(data, null, 2) + "\n\nIMPORTANT: Store this API key securely — it will not be shown again.");
|
|
1411
|
+
}
|
|
1412
|
+
catch (e) {
|
|
1413
|
+
return err(e);
|
|
1414
|
+
}
|
|
1415
|
+
}
|
|
1416
|
+
// -----------------------------------------------------------------------
|
|
1417
|
+
// Tool 41: revokeKey
|
|
1418
|
+
// -----------------------------------------------------------------------
|
|
1419
|
+
async revokeKey(keyId) {
|
|
1420
|
+
try {
|
|
1421
|
+
const id = validateUuid(keyId, "keyId");
|
|
1422
|
+
const data = await this._req("DELETE", `/api/keys/${encodeURIComponent(id)}`);
|
|
1423
|
+
return ok(JSON.stringify(data, null, 2));
|
|
1424
|
+
}
|
|
1425
|
+
catch (e) {
|
|
1426
|
+
return err(e);
|
|
1427
|
+
}
|
|
1428
|
+
}
|
|
1429
|
+
// -----------------------------------------------------------------------
|
|
1430
|
+
// Tool 42: getPlan
|
|
1431
|
+
// -----------------------------------------------------------------------
|
|
1432
|
+
async getPlan() {
|
|
1433
|
+
try {
|
|
1434
|
+
const data = await this._req("GET", "/api/plans/user/plan");
|
|
1435
|
+
return ok(JSON.stringify(data, null, 2));
|
|
1436
|
+
}
|
|
1437
|
+
catch (e) {
|
|
1438
|
+
return err(e);
|
|
1439
|
+
}
|
|
1440
|
+
}
|
|
1441
|
+
// -----------------------------------------------------------------------
|
|
1442
|
+
// Tool 43: listPlans
|
|
1443
|
+
// -----------------------------------------------------------------------
|
|
1444
|
+
async listPlans() {
|
|
1445
|
+
try {
|
|
1446
|
+
const data = await this._req("GET", "/api/plans");
|
|
1447
|
+
return ok(JSON.stringify(data, null, 2));
|
|
1448
|
+
}
|
|
1449
|
+
catch (e) {
|
|
1450
|
+
return err(e);
|
|
1451
|
+
}
|
|
1452
|
+
}
|
|
1453
|
+
// -----------------------------------------------------------------------
|
|
1454
|
+
// Tool 44: changePlan
|
|
1455
|
+
// -----------------------------------------------------------------------
|
|
1456
|
+
async changePlan(planId) {
|
|
1457
|
+
try {
|
|
1458
|
+
const id = validateUuid(planId, "planId");
|
|
1459
|
+
const data = await this._req("PUT", "/api/plans/user/plan", { planId: id });
|
|
1460
|
+
return ok(JSON.stringify(data, null, 2));
|
|
1461
|
+
}
|
|
1462
|
+
catch (e) {
|
|
1463
|
+
return err(e);
|
|
1464
|
+
}
|
|
1465
|
+
}
|
|
1466
|
+
// -----------------------------------------------------------------------
|
|
1467
|
+
// Tool 45: teamDelete
|
|
1468
|
+
// -----------------------------------------------------------------------
|
|
1469
|
+
async teamDelete(teamId) {
|
|
1470
|
+
try {
|
|
1471
|
+
const id = validateUuid(teamId, "teamId");
|
|
1472
|
+
const data = await this._req("DELETE", `/api/teams/${encodeURIComponent(id)}`);
|
|
1473
|
+
return ok(JSON.stringify(data, null, 2));
|
|
1474
|
+
}
|
|
1475
|
+
catch (e) {
|
|
1476
|
+
return err(e);
|
|
1477
|
+
}
|
|
1478
|
+
}
|
|
1479
|
+
// -----------------------------------------------------------------------
|
|
1480
|
+
// Tool 46: teamRevokeKey
|
|
1481
|
+
// -----------------------------------------------------------------------
|
|
1482
|
+
async teamRevokeKey(teamId, keyId) {
|
|
1483
|
+
try {
|
|
1484
|
+
const tid = validateUuid(teamId, "teamId");
|
|
1485
|
+
const kid = validateUuid(keyId, "keyId");
|
|
1486
|
+
const data = await this._req("DELETE", `/api/teams/${encodeURIComponent(tid)}/keys/${encodeURIComponent(kid)}`);
|
|
1487
|
+
return ok(JSON.stringify(data, null, 2));
|
|
1488
|
+
}
|
|
1489
|
+
catch (e) {
|
|
1490
|
+
return err(e);
|
|
1491
|
+
}
|
|
1492
|
+
}
|
|
1493
|
+
// -----------------------------------------------------------------------
|
|
1494
|
+
// Tool 47: teamListKeys
|
|
1495
|
+
// -----------------------------------------------------------------------
|
|
1496
|
+
async teamListKeys(teamId) {
|
|
1497
|
+
try {
|
|
1498
|
+
const id = validateUuid(teamId, "teamId");
|
|
1499
|
+
const data = await this._req("GET", `/api/teams/${encodeURIComponent(id)}/keys`);
|
|
1500
|
+
return ok(JSON.stringify(data, null, 2));
|
|
1501
|
+
}
|
|
1502
|
+
catch (e) {
|
|
1503
|
+
return err(e);
|
|
1504
|
+
}
|
|
1505
|
+
}
|
|
1506
|
+
// -----------------------------------------------------------------------
|
|
1507
|
+
// Tool 48: teamListMembers
|
|
1508
|
+
// -----------------------------------------------------------------------
|
|
1509
|
+
async teamListMembers(teamId) {
|
|
1510
|
+
try {
|
|
1511
|
+
const id = validateUuid(teamId, "teamId");
|
|
1512
|
+
const data = await this._req("GET", `/api/teams/${encodeURIComponent(id)}/members`);
|
|
1513
|
+
return ok(JSON.stringify(data, null, 2));
|
|
1514
|
+
}
|
|
1515
|
+
catch (e) {
|
|
1516
|
+
return err(e);
|
|
1517
|
+
}
|
|
1518
|
+
}
|
|
1519
|
+
// -----------------------------------------------------------------------
|
|
1520
|
+
// Tool 49: teamAddMember
|
|
1521
|
+
// -----------------------------------------------------------------------
|
|
1522
|
+
async teamAddMember(teamId, userId, role = "member") {
|
|
1523
|
+
try {
|
|
1524
|
+
const tid = validateUuid(teamId, "teamId");
|
|
1525
|
+
const uid = validateUuid(userId, "userId");
|
|
1526
|
+
if (role !== "member" && role !== "admin")
|
|
1527
|
+
return err("role must be 'member' or 'admin'");
|
|
1528
|
+
const data = await this._req("POST", `/api/teams/${encodeURIComponent(tid)}/members`, { userId: uid, role });
|
|
1529
|
+
return ok(JSON.stringify(data, null, 2));
|
|
1530
|
+
}
|
|
1531
|
+
catch (e) {
|
|
1532
|
+
return err(e);
|
|
1533
|
+
}
|
|
1534
|
+
}
|
|
1535
|
+
// -----------------------------------------------------------------------
|
|
1536
|
+
// Tool 50: teamRemoveMember
|
|
1537
|
+
// -----------------------------------------------------------------------
|
|
1538
|
+
async teamRemoveMember(teamId, userId) {
|
|
1539
|
+
try {
|
|
1540
|
+
const tid = validateUuid(teamId, "teamId");
|
|
1541
|
+
const uid = validateUuid(userId, "userId");
|
|
1542
|
+
const data = await this._req("DELETE", `/api/teams/${encodeURIComponent(tid)}/members/${encodeURIComponent(uid)}`);
|
|
1543
|
+
return ok(JSON.stringify(data, null, 2));
|
|
1544
|
+
}
|
|
1545
|
+
catch (e) {
|
|
1546
|
+
return err(e);
|
|
1547
|
+
}
|
|
1548
|
+
}
|
|
1549
|
+
// -----------------------------------------------------------------------
|
|
1550
|
+
// Tool 51: teamInviteMember
|
|
1551
|
+
// -----------------------------------------------------------------------
|
|
1552
|
+
async teamInviteMember(teamId, email, role = "member") {
|
|
1553
|
+
try {
|
|
1554
|
+
const id = validateUuid(teamId, "teamId");
|
|
1555
|
+
const safeEmail = DominusNodeToolkit.validateEmail(email);
|
|
1556
|
+
if (role !== "member" && role !== "admin")
|
|
1557
|
+
return err("role must be 'member' or 'admin'");
|
|
1558
|
+
const data = await this._req("POST", `/api/teams/${encodeURIComponent(id)}/invites`, { email: safeEmail, role });
|
|
1559
|
+
return ok(JSON.stringify(data, null, 2));
|
|
1560
|
+
}
|
|
1561
|
+
catch (e) {
|
|
1562
|
+
return err(e);
|
|
1563
|
+
}
|
|
1564
|
+
}
|
|
1565
|
+
// -----------------------------------------------------------------------
|
|
1566
|
+
// Tool 52: teamListInvites
|
|
1567
|
+
// -----------------------------------------------------------------------
|
|
1568
|
+
async teamListInvites(teamId) {
|
|
1569
|
+
try {
|
|
1570
|
+
const id = validateUuid(teamId, "teamId");
|
|
1571
|
+
const data = await this._req("GET", `/api/teams/${encodeURIComponent(id)}/invites`);
|
|
1572
|
+
return ok(JSON.stringify(data, null, 2));
|
|
1573
|
+
}
|
|
1574
|
+
catch (e) {
|
|
1575
|
+
return err(e);
|
|
1576
|
+
}
|
|
1577
|
+
}
|
|
1578
|
+
// -----------------------------------------------------------------------
|
|
1579
|
+
// Tool 53: teamCancelInvite
|
|
1580
|
+
// -----------------------------------------------------------------------
|
|
1581
|
+
async teamCancelInvite(teamId, inviteId) {
|
|
1582
|
+
try {
|
|
1583
|
+
const tid = validateUuid(teamId, "teamId");
|
|
1584
|
+
const iid = validateUuid(inviteId, "inviteId");
|
|
1585
|
+
const data = await this._req("DELETE", `/api/teams/${encodeURIComponent(tid)}/invites/${encodeURIComponent(iid)}`);
|
|
1102
1586
|
return ok(JSON.stringify(data, null, 2));
|
|
1103
1587
|
}
|
|
1104
1588
|
catch (e) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dominusnode/pi-extension",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.2.0",
|
|
4
4
|
"description": "Dominus Node pi-mono extension — 26 tools for rotating proxy, wallet, agentic wallets, teams, and payments",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"pi-package",
|
|
@@ -20,8 +20,12 @@
|
|
|
20
20
|
"CHANGELOG.md"
|
|
21
21
|
],
|
|
22
22
|
"pi": {
|
|
23
|
-
"extensions": [
|
|
24
|
-
|
|
23
|
+
"extensions": [
|
|
24
|
+
"./dist"
|
|
25
|
+
],
|
|
26
|
+
"skills": [
|
|
27
|
+
"./skills"
|
|
28
|
+
]
|
|
25
29
|
},
|
|
26
30
|
"scripts": {
|
|
27
31
|
"build": "tsc",
|