deepctl-cmd-members 0.0.2__tar.gz

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.
@@ -0,0 +1,63 @@
1
+ Metadata-Version: 2.4
2
+ Name: deepctl-cmd-members
3
+ Version: 0.0.2
4
+ Summary: Members management command for deepctl
5
+ Author-email: Deepgram <devrel@deepgram.com>
6
+ Maintainer-email: Deepgram <devrel@deepgram.com>
7
+ License-Expression: MIT
8
+ Keywords: deepgram,cli,members,team
9
+ Classifier: Development Status :: 3 - Alpha
10
+ Classifier: Intended Audience :: Developers
11
+ Classifier: Programming Language :: Python :: 3
12
+ Classifier: Programming Language :: Python :: 3.10
13
+ Classifier: Programming Language :: Python :: 3.11
14
+ Classifier: Programming Language :: Python :: 3.12
15
+ Requires-Python: >=3.10
16
+ Description-Content-Type: text/markdown
17
+ Requires-Dist: deepctl-core>=0.1.10
18
+ Requires-Dist: click>=8.0.0
19
+ Requires-Dist: rich>=13.0.0
20
+ Requires-Dist: pydantic>=2.0.0
21
+
22
+ # deepctl-cmd-members
23
+
24
+ > Part of [deepctl](https://github.com/deepgram/cli) — Official Deepgram CLI
25
+
26
+ Members management command for deepctl
27
+
28
+ ## Installation
29
+
30
+ This package is included with deepctl and does not need to be installed separately.
31
+
32
+ ### Install deepctl
33
+
34
+ ```bash
35
+ # Install with pip
36
+ pip install deepctl
37
+
38
+ # Or install with uv
39
+ uv tool install deepctl
40
+
41
+ # Or install with pipx
42
+ pipx install deepctl
43
+
44
+ # Or run without installing
45
+ uvx deepctl --help
46
+ pipx run deepctl --help
47
+ ```
48
+
49
+ ## Commands
50
+
51
+ | Command | Entry Point |
52
+ |---------|-------------|
53
+ | `deepctl members` | `deepctl_cmd_members.command:MembersCommand` |
54
+
55
+ ## Dependencies
56
+
57
+ - `click>=8.0.0`
58
+ - `rich>=13.0.0`
59
+ - `pydantic>=2.0.0`
60
+
61
+ ## License
62
+
63
+ MIT — see [LICENSE](../../LICENSE)
@@ -0,0 +1,42 @@
1
+ # deepctl-cmd-members
2
+
3
+ > Part of [deepctl](https://github.com/deepgram/cli) — Official Deepgram CLI
4
+
5
+ Members management command for deepctl
6
+
7
+ ## Installation
8
+
9
+ This package is included with deepctl and does not need to be installed separately.
10
+
11
+ ### Install deepctl
12
+
13
+ ```bash
14
+ # Install with pip
15
+ pip install deepctl
16
+
17
+ # Or install with uv
18
+ uv tool install deepctl
19
+
20
+ # Or install with pipx
21
+ pipx install deepctl
22
+
23
+ # Or run without installing
24
+ uvx deepctl --help
25
+ pipx run deepctl --help
26
+ ```
27
+
28
+ ## Commands
29
+
30
+ | Command | Entry Point |
31
+ |---------|-------------|
32
+ | `deepctl members` | `deepctl_cmd_members.command:MembersCommand` |
33
+
34
+ ## Dependencies
35
+
36
+ - `click>=8.0.0`
37
+ - `rich>=13.0.0`
38
+ - `pydantic>=2.0.0`
39
+
40
+ ## License
41
+
42
+ MIT — see [LICENSE](../../LICENSE)
@@ -0,0 +1,40 @@
1
+ [build-system]
2
+ requires = ["setuptools>=61.0", "wheel"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "deepctl-cmd-members"
7
+ version = "0.0.2" # x-release-please-version
8
+ description = "Members management command for deepctl"
9
+ readme = "README.md"
10
+ license = "MIT"
11
+ authors = [{ name = "Deepgram", email = "devrel@deepgram.com" }]
12
+ maintainers = [{ name = "Deepgram", email = "devrel@deepgram.com" }]
13
+ classifiers = [
14
+ "Development Status :: 3 - Alpha",
15
+ "Intended Audience :: Developers",
16
+ "Programming Language :: Python :: 3",
17
+ "Programming Language :: Python :: 3.10",
18
+ "Programming Language :: Python :: 3.11",
19
+ "Programming Language :: Python :: 3.12",
20
+ ]
21
+ keywords = ["deepgram", "cli", "members", "team"]
22
+ requires-python = ">=3.10"
23
+ dependencies = [
24
+ "deepctl-core>=0.1.10",
25
+ "click>=8.0.0",
26
+ "rich>=13.0.0",
27
+ "pydantic>=2.0.0",
28
+ ]
29
+
30
+ [project.scripts]
31
+
32
+ [project.entry-points."deepctl.commands"]
33
+ members = "deepctl_cmd_members.command:MembersCommand"
34
+
35
+ [tool.setuptools]
36
+ package-dir = { "" = "src" }
37
+
38
+ [tool.setuptools.packages.find]
39
+ where = ["src"]
40
+ include = ["deepctl_cmd_members*"]
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1 @@
1
+ """Members management command for deepctl."""
@@ -0,0 +1,261 @@
1
+ """Members management command for deepctl."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from typing import Any
6
+
7
+ from deepctl_core import (
8
+ AuthManager,
9
+ BaseCommand,
10
+ BaseResult,
11
+ Config,
12
+ DeepgramClient,
13
+ )
14
+ from rich.console import Console
15
+ from rich.table import Table
16
+
17
+ from .models import InviteInfo, MemberInfo, MembersResult
18
+
19
+ console = Console()
20
+
21
+
22
+ class MembersCommand(BaseCommand):
23
+ """Command for managing project members."""
24
+
25
+ name = "members"
26
+ help = "Manage Deepgram project members"
27
+ short_help = "Manage members"
28
+
29
+ requires_auth = True
30
+ requires_project = True
31
+ ci_friendly = True
32
+
33
+ examples = [
34
+ "dg members",
35
+ "dg members --list",
36
+ "dg members --invite user@example.com --scope member",
37
+ "dg members --remove MEMBER_ID",
38
+ "dg members --invites",
39
+ "dg members --revoke-invite user@example.com",
40
+ ]
41
+ agent_help = (
42
+ "Manage project members and invitations. "
43
+ "List members, invite new ones, remove existing, and manage invites. "
44
+ "Requires authentication and a project ID."
45
+ )
46
+
47
+ def get_arguments(self) -> list[dict[str, Any]]:
48
+ return [
49
+ {
50
+ "names": ["--list", "-l"],
51
+ "help": "List all project members",
52
+ "is_flag": True,
53
+ "is_option": True,
54
+ },
55
+ {
56
+ "names": ["--invite", "-i"],
57
+ "help": "Invite a member by email",
58
+ "type": str,
59
+ "is_option": True,
60
+ },
61
+ {
62
+ "names": ["--scope"],
63
+ "help": "Scope for invite (e.g., member, admin)",
64
+ "type": str,
65
+ "is_option": True,
66
+ "default": "member",
67
+ },
68
+ {
69
+ "names": ["--remove", "-r"],
70
+ "help": "Remove a member by ID",
71
+ "type": str,
72
+ "is_option": True,
73
+ },
74
+ {
75
+ "names": ["--invites"],
76
+ "help": "List pending invites",
77
+ "is_flag": True,
78
+ "is_option": True,
79
+ },
80
+ {
81
+ "names": ["--revoke-invite"],
82
+ "help": "Revoke an invite by email",
83
+ "type": str,
84
+ "is_option": True,
85
+ },
86
+ {
87
+ "names": ["--project-id", "-p"],
88
+ "help": "Project ID (uses configured project if not provided)",
89
+ "type": str,
90
+ "is_option": True,
91
+ },
92
+ {
93
+ "names": ["--yes", "-y"],
94
+ "help": "Skip confirmation prompts",
95
+ "is_flag": True,
96
+ "is_option": True,
97
+ },
98
+ ]
99
+
100
+ def handle(
101
+ self,
102
+ config: Config,
103
+ auth_manager: AuthManager,
104
+ client: DeepgramClient,
105
+ **kwargs: Any,
106
+ ) -> BaseResult:
107
+ invite_email = kwargs.get("invite")
108
+ remove_id = kwargs.get("remove")
109
+ show_invites = kwargs.get("invites", False)
110
+ revoke_email = kwargs.get("revoke_invite")
111
+ project_id = kwargs.get("project_id")
112
+ yes = kwargs.get("yes", False)
113
+
114
+ try:
115
+ if invite_email:
116
+ return self._invite_member(
117
+ client, invite_email, kwargs.get("scope", "member"), project_id
118
+ )
119
+ elif remove_id:
120
+ return self._remove_member(client, remove_id, project_id, yes)
121
+ elif show_invites:
122
+ return self._list_invites(client, project_id)
123
+ elif revoke_email:
124
+ return self._revoke_invite(client, revoke_email, project_id, yes)
125
+ else:
126
+ return self._list_members(client, project_id)
127
+
128
+ except Exception as e:
129
+ console.print(f"[red]Error:[/red] {e}")
130
+ return BaseResult(status="error", message=str(e))
131
+
132
+ def _list_members(
133
+ self, client: DeepgramClient, project_id: str | None
134
+ ) -> BaseResult:
135
+ console.print("[blue]Fetching project members...[/blue]")
136
+ result = client.list_members(project_id=project_id)
137
+
138
+ members_raw = result.get("members", [])
139
+ if not members_raw:
140
+ console.print("[yellow]No members found[/yellow]")
141
+ return MembersResult(status="info", message="No members found")
142
+
143
+ member_models: list[MemberInfo] = []
144
+ table = Table(
145
+ title="Project Members", show_header=True, header_style="bold blue"
146
+ )
147
+ table.add_column("Name", style="green")
148
+ table.add_column("Email")
149
+ table.add_column("Scopes")
150
+ table.add_column("Member ID", style="dim")
151
+
152
+ for m in members_raw:
153
+ m_data = (
154
+ m
155
+ if isinstance(m, dict)
156
+ else (m.__dict__ if hasattr(m, "__dict__") else {})
157
+ )
158
+ info = MemberInfo(
159
+ member_id=m_data.get("member_id", ""),
160
+ email=m_data.get("email", ""),
161
+ first_name=m_data.get("first_name", ""),
162
+ last_name=m_data.get("last_name", ""),
163
+ scopes=m_data.get("scopes", []),
164
+ )
165
+ member_models.append(info)
166
+
167
+ name = f"{info.first_name} {info.last_name}".strip() or "(no name)"
168
+ table.add_row(
169
+ name,
170
+ info.email,
171
+ ", ".join(info.scopes) if info.scopes else "-",
172
+ info.member_id,
173
+ )
174
+
175
+ console.print(table)
176
+ console.print(f"\n[dim]{len(member_models)} member(s)[/dim]")
177
+
178
+ return MembersResult(
179
+ status="success", members=member_models, count=len(member_models)
180
+ )
181
+
182
+ def _invite_member(
183
+ self,
184
+ client: DeepgramClient,
185
+ email: str,
186
+ scope: str,
187
+ project_id: str | None,
188
+ ) -> BaseResult:
189
+ console.print(f"[blue]Inviting {email} with scope '{scope}'...[/blue]")
190
+ client.create_invite(email=email, scope=scope, project_id=project_id)
191
+ console.print(f"[green]Invitation sent to {email}[/green]")
192
+ return BaseResult(status="success", message=f"Invited {email}")
193
+
194
+ def _remove_member(
195
+ self,
196
+ client: DeepgramClient,
197
+ member_id: str,
198
+ project_id: str | None,
199
+ yes: bool = False,
200
+ ) -> BaseResult:
201
+ if not yes and not self.confirm(
202
+ f"Remove member {member_id} from the project?", default=False
203
+ ):
204
+ return BaseResult(status="cancelled", message="Cancelled by user")
205
+
206
+ console.print(f"[blue]Removing member {member_id}...[/blue]")
207
+ client.remove_member(member_id, project_id=project_id)
208
+ console.print(f"[green]Member {member_id} removed[/green]")
209
+ return BaseResult(status="success", message=f"Member {member_id} removed")
210
+
211
+ def _list_invites(
212
+ self, client: DeepgramClient, project_id: str | None
213
+ ) -> BaseResult:
214
+ console.print("[blue]Fetching pending invites...[/blue]")
215
+ result = client.list_invites(project_id=project_id)
216
+
217
+ invites_raw = result.get("invites", [])
218
+ if not invites_raw:
219
+ console.print("[yellow]No pending invites[/yellow]")
220
+ return MembersResult(status="info", message="No pending invites")
221
+
222
+ invite_models: list[InviteInfo] = []
223
+ table = Table(
224
+ title="Pending Invites", show_header=True, header_style="bold blue"
225
+ )
226
+ table.add_column("Email", style="green")
227
+ table.add_column("Scope")
228
+
229
+ for inv in invites_raw:
230
+ inv_data = (
231
+ inv
232
+ if isinstance(inv, dict)
233
+ else (inv.__dict__ if hasattr(inv, "__dict__") else {})
234
+ )
235
+ info = InviteInfo(
236
+ email=inv_data.get("email", ""),
237
+ scope=inv_data.get("scope", ""),
238
+ )
239
+ invite_models.append(info)
240
+ table.add_row(info.email, info.scope)
241
+
242
+ console.print(table)
243
+
244
+ return MembersResult(
245
+ status="success", invites=invite_models, count=len(invite_models)
246
+ )
247
+
248
+ def _revoke_invite(
249
+ self,
250
+ client: DeepgramClient,
251
+ email: str,
252
+ project_id: str | None,
253
+ yes: bool = False,
254
+ ) -> BaseResult:
255
+ if not yes and not self.confirm(f"Revoke invite for {email}?", default=False):
256
+ return BaseResult(status="cancelled", message="Cancelled by user")
257
+
258
+ console.print(f"[blue]Revoking invite for {email}...[/blue]")
259
+ client.delete_invite(email, project_id=project_id)
260
+ console.print(f"[green]Invite for {email} revoked[/green]")
261
+ return BaseResult(status="success", message=f"Invite for {email} revoked")
@@ -0,0 +1,25 @@
1
+ """Models for members command."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from deepctl_core import BaseResult
6
+ from pydantic import BaseModel, Field
7
+
8
+
9
+ class MemberInfo(BaseModel):
10
+ member_id: str = ""
11
+ email: str = ""
12
+ first_name: str = ""
13
+ last_name: str = ""
14
+ scopes: list[str] = Field(default_factory=list)
15
+
16
+
17
+ class InviteInfo(BaseModel):
18
+ email: str = ""
19
+ scope: str = ""
20
+
21
+
22
+ class MembersResult(BaseResult):
23
+ members: list[MemberInfo] = Field(default_factory=list)
24
+ invites: list[InviteInfo] = Field(default_factory=list)
25
+ count: int = 0
@@ -0,0 +1,63 @@
1
+ Metadata-Version: 2.4
2
+ Name: deepctl-cmd-members
3
+ Version: 0.0.2
4
+ Summary: Members management command for deepctl
5
+ Author-email: Deepgram <devrel@deepgram.com>
6
+ Maintainer-email: Deepgram <devrel@deepgram.com>
7
+ License-Expression: MIT
8
+ Keywords: deepgram,cli,members,team
9
+ Classifier: Development Status :: 3 - Alpha
10
+ Classifier: Intended Audience :: Developers
11
+ Classifier: Programming Language :: Python :: 3
12
+ Classifier: Programming Language :: Python :: 3.10
13
+ Classifier: Programming Language :: Python :: 3.11
14
+ Classifier: Programming Language :: Python :: 3.12
15
+ Requires-Python: >=3.10
16
+ Description-Content-Type: text/markdown
17
+ Requires-Dist: deepctl-core>=0.1.10
18
+ Requires-Dist: click>=8.0.0
19
+ Requires-Dist: rich>=13.0.0
20
+ Requires-Dist: pydantic>=2.0.0
21
+
22
+ # deepctl-cmd-members
23
+
24
+ > Part of [deepctl](https://github.com/deepgram/cli) — Official Deepgram CLI
25
+
26
+ Members management command for deepctl
27
+
28
+ ## Installation
29
+
30
+ This package is included with deepctl and does not need to be installed separately.
31
+
32
+ ### Install deepctl
33
+
34
+ ```bash
35
+ # Install with pip
36
+ pip install deepctl
37
+
38
+ # Or install with uv
39
+ uv tool install deepctl
40
+
41
+ # Or install with pipx
42
+ pipx install deepctl
43
+
44
+ # Or run without installing
45
+ uvx deepctl --help
46
+ pipx run deepctl --help
47
+ ```
48
+
49
+ ## Commands
50
+
51
+ | Command | Entry Point |
52
+ |---------|-------------|
53
+ | `deepctl members` | `deepctl_cmd_members.command:MembersCommand` |
54
+
55
+ ## Dependencies
56
+
57
+ - `click>=8.0.0`
58
+ - `rich>=13.0.0`
59
+ - `pydantic>=2.0.0`
60
+
61
+ ## License
62
+
63
+ MIT — see [LICENSE](../../LICENSE)
@@ -0,0 +1,11 @@
1
+ README.md
2
+ pyproject.toml
3
+ src/deepctl_cmd_members/__init__.py
4
+ src/deepctl_cmd_members/command.py
5
+ src/deepctl_cmd_members/models.py
6
+ src/deepctl_cmd_members.egg-info/PKG-INFO
7
+ src/deepctl_cmd_members.egg-info/SOURCES.txt
8
+ src/deepctl_cmd_members.egg-info/dependency_links.txt
9
+ src/deepctl_cmd_members.egg-info/entry_points.txt
10
+ src/deepctl_cmd_members.egg-info/requires.txt
11
+ src/deepctl_cmd_members.egg-info/top_level.txt
@@ -0,0 +1,2 @@
1
+ [deepctl.commands]
2
+ members = deepctl_cmd_members.command:MembersCommand
@@ -0,0 +1,4 @@
1
+ deepctl-core>=0.1.10
2
+ click>=8.0.0
3
+ rich>=13.0.0
4
+ pydantic>=2.0.0
@@ -0,0 +1 @@
1
+ deepctl_cmd_members