@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 CHANGED
@@ -1,6 +1,6 @@
1
1
  # @dominusnode/pi-extension
2
2
 
3
- [Pi](https://github.com/badlogic/pi-mono) extension providing **26 tools** for the [Dominus Node](https://dominusnode.com) rotating proxy and management platform.
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 (26 total)
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 26 tools for the Dominus Node rotating proxy
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 26 tools for the Dominus Node rotating proxy
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 26 tools for the pi-mono agent framework (github.com/badlogic/pi-mono).
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 26 tools for the pi-mono agent framework (github.com/badlogic/pi-mono).
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: { "Content-Type": "application/json", "User-Agent": "dominusnode-pi/1.0.0" },
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.0.0",
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": ["./dist"],
24
- "skills": ["./skills"]
23
+ "extensions": [
24
+ "./dist"
25
+ ],
26
+ "skills": [
27
+ "./skills"
28
+ ]
25
29
  },
26
30
  "scripts": {
27
31
  "build": "tsc",