@dominusnode/pi-extension 1.1.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
  *
@@ -94,4 +94,35 @@ export declare class DominusNodeToolkit {
94
94
  topupCrypto(amountUsd: number, currency: string): Promise<PiToolResult>;
95
95
  x402Info(): Promise<PiToolResult>;
96
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>;
97
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
  *
@@ -789,7 +789,7 @@ class DominusNodeToolkit {
789
789
  const amount = Math.floor(Number(amountCents));
790
790
  if (isNaN(amount) || amount < 1 || amount > 1000000)
791
791
  return err("amountCents must be between 1 and 1,000,000");
792
- 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 });
793
793
  return ok(JSON.stringify(data, null, 2));
794
794
  }
795
795
  catch (e) {
@@ -802,7 +802,7 @@ class DominusNodeToolkit {
802
802
  async checkAgenticBalance(walletId) {
803
803
  try {
804
804
  const id = validateUuid(walletId, "walletId");
805
- const data = await this._req("GET", `/api/agent-wallet/${id}`);
805
+ const data = await this._req("GET", `/api/agent-wallet/${encodeURIComponent(id)}`);
806
806
  return ok(JSON.stringify(data, null, 2));
807
807
  }
808
808
  catch (e) {
@@ -831,7 +831,7 @@ class DominusNodeToolkit {
831
831
  if (!Number.isFinite(rawLim))
832
832
  return err("limit must be a finite number");
833
833
  const lim = Math.max(1, Math.min(100, Math.floor(rawLim)));
834
- 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}`);
835
835
  return ok(JSON.stringify(data, null, 2));
836
836
  }
837
837
  catch (e) {
@@ -844,7 +844,7 @@ class DominusNodeToolkit {
844
844
  async freezeAgenticWallet(walletId) {
845
845
  try {
846
846
  const id = validateUuid(walletId, "walletId");
847
- const data = await this._req("POST", `/api/agent-wallet/${id}/freeze`);
847
+ const data = await this._req("POST", `/api/agent-wallet/${encodeURIComponent(id)}/freeze`);
848
848
  return ok(JSON.stringify(data, null, 2));
849
849
  }
850
850
  catch (e) {
@@ -857,7 +857,7 @@ class DominusNodeToolkit {
857
857
  async unfreezeAgenticWallet(walletId) {
858
858
  try {
859
859
  const id = validateUuid(walletId, "walletId");
860
- const data = await this._req("POST", `/api/agent-wallet/${id}/unfreeze`);
860
+ const data = await this._req("POST", `/api/agent-wallet/${encodeURIComponent(id)}/unfreeze`);
861
861
  return ok(JSON.stringify(data, null, 2));
862
862
  }
863
863
  catch (e) {
@@ -870,7 +870,7 @@ class DominusNodeToolkit {
870
870
  async deleteAgenticWallet(walletId) {
871
871
  try {
872
872
  const id = validateUuid(walletId, "walletId");
873
- const data = await this._req("DELETE", `/api/agent-wallet/${id}`);
873
+ const data = await this._req("DELETE", `/api/agent-wallet/${encodeURIComponent(id)}`);
874
874
  return ok(JSON.stringify(data, null, 2));
875
875
  }
876
876
  catch (e) {
@@ -917,7 +917,7 @@ class DominusNodeToolkit {
917
917
  async teamDetails(teamId) {
918
918
  try {
919
919
  const id = validateUuid(teamId, "teamId");
920
- const data = await this._req("GET", `/api/teams/${id}`);
920
+ const data = await this._req("GET", `/api/teams/${encodeURIComponent(id)}`);
921
921
  return ok(JSON.stringify(data, null, 2));
922
922
  }
923
923
  catch (e) {
@@ -933,7 +933,7 @@ class DominusNodeToolkit {
933
933
  const amount = Math.floor(Number(amountCents));
934
934
  if (isNaN(amount) || amount < 1 || amount > 1000000)
935
935
  return err("amountCents must be between 1 and 1,000,000");
936
- 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 });
937
937
  return ok(JSON.stringify(data, null, 2));
938
938
  }
939
939
  catch (e) {
@@ -949,7 +949,7 @@ class DominusNodeToolkit {
949
949
  const labelErr = validateLabel(label);
950
950
  if (labelErr)
951
951
  return err(labelErr);
952
- 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() });
953
953
  return ok(JSON.stringify(data, null, 2) + "\n\nIMPORTANT: Store this API key securely — it will not be shown again.");
954
954
  }
955
955
  catch (e) {
@@ -968,7 +968,7 @@ class DominusNodeToolkit {
968
968
  const d = Math.max(1, Math.min(365, Math.floor(rawDays)));
969
969
  const until = new Date().toISOString();
970
970
  const since = new Date(Date.now() - d * 86400000).toISOString();
971
- 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)}`);
972
972
  return ok(JSON.stringify(data, null, 2));
973
973
  }
974
974
  catch (e) {
@@ -996,7 +996,7 @@ class DominusNodeToolkit {
996
996
  }
997
997
  if (!Object.keys(body).length)
998
998
  return err("At least one of name or maxMembers must be provided");
999
- const data = await this._req("PATCH", `/api/teams/${id}`, body);
999
+ const data = await this._req("PATCH", `/api/teams/${encodeURIComponent(id)}`, body);
1000
1000
  return ok(JSON.stringify(data, null, 2));
1001
1001
  }
1002
1002
  catch (e) {
@@ -1112,7 +1112,477 @@ class DominusNodeToolkit {
1112
1112
  }
1113
1113
  if (!Object.keys(body).length)
1114
1114
  return err("At least one of dailyLimitCents or allowedDomains must be provided");
1115
- 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)}`);
1116
1586
  return ok(JSON.stringify(data, null, 2));
1117
1587
  }
1118
1588
  catch (e) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dominusnode/pi-extension",
3
- "version": "1.1.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",