mem0ai-azure-mysql 0.2.0__py3-none-any.whl → 0.2.2__py3-none-any.whl

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.
mem0/client/project.py DELETED
@@ -1,860 +0,0 @@
1
- import logging
2
- from abc import ABC, abstractmethod
3
- from typing import Any, Dict, List, Optional
4
-
5
- import httpx
6
- from pydantic import BaseModel, Field
7
-
8
- from mem0.client.utils import api_error_handler
9
- from mem0.memory.telemetry import capture_client_event
10
-
11
- logger = logging.getLogger(__name__)
12
-
13
-
14
- class ProjectConfig(BaseModel):
15
- """
16
- Configuration for project management operations.
17
- """
18
-
19
- org_id: Optional[str] = Field(default=None, description="Organization ID")
20
- project_id: Optional[str] = Field(default=None, description="Project ID")
21
- user_email: Optional[str] = Field(default=None, description="User email")
22
-
23
- class Config:
24
- validate_assignment = True
25
- extra = "forbid"
26
-
27
-
28
- class BaseProject(ABC):
29
- """
30
- Abstract base class for project management operations.
31
- """
32
-
33
- def __init__(
34
- self,
35
- client: Any,
36
- config: Optional[ProjectConfig] = None,
37
- org_id: Optional[str] = None,
38
- project_id: Optional[str] = None,
39
- user_email: Optional[str] = None,
40
- ):
41
- """
42
- Initialize the project manager.
43
-
44
- Args:
45
- client: HTTP client instance
46
- config: Project manager configuration
47
- org_id: Organization ID
48
- project_id: Project ID
49
- user_email: User email
50
- """
51
- self._client = client
52
-
53
- # Handle config initialization
54
- if config is not None:
55
- self.config = config
56
- else:
57
- # Create config from parameters
58
- self.config = ProjectConfig(org_id=org_id, project_id=project_id, user_email=user_email)
59
-
60
- @property
61
- def org_id(self) -> Optional[str]:
62
- """Get the organization ID."""
63
- return self.config.org_id
64
-
65
- @property
66
- def project_id(self) -> Optional[str]:
67
- """Get the project ID."""
68
- return self.config.project_id
69
-
70
- @property
71
- def user_email(self) -> Optional[str]:
72
- """Get the user email."""
73
- return self.config.user_email
74
-
75
- def _validate_org_project(self) -> None:
76
- """
77
- Validate that both org_id and project_id are set.
78
-
79
- Raises:
80
- ValueError: If org_id or project_id are not set.
81
- """
82
- if not (self.config.org_id and self.config.project_id):
83
- raise ValueError("org_id and project_id must be set to access project operations")
84
-
85
- def _prepare_params(self, kwargs: Optional[Dict[str, Any]] = None) -> Dict[str, Any]:
86
- """
87
- Prepare query parameters for API requests.
88
-
89
- Args:
90
- kwargs: Additional keyword arguments.
91
-
92
- Returns:
93
- Dictionary containing prepared parameters.
94
-
95
- Raises:
96
- ValueError: If org_id or project_id validation fails.
97
- """
98
- if kwargs is None:
99
- kwargs = {}
100
-
101
- # Add org_id and project_id if available
102
- if self.config.org_id and self.config.project_id:
103
- kwargs["org_id"] = self.config.org_id
104
- kwargs["project_id"] = self.config.project_id
105
- elif self.config.org_id or self.config.project_id:
106
- raise ValueError("Please provide both org_id and project_id")
107
-
108
- return {k: v for k, v in kwargs.items() if v is not None}
109
-
110
- def _prepare_org_params(self, kwargs: Optional[Dict[str, Any]] = None) -> Dict[str, Any]:
111
- """
112
- Prepare query parameters for organization-level API requests.
113
-
114
- Args:
115
- kwargs: Additional keyword arguments.
116
-
117
- Returns:
118
- Dictionary containing prepared parameters.
119
-
120
- Raises:
121
- ValueError: If org_id is not provided.
122
- """
123
- if kwargs is None:
124
- kwargs = {}
125
-
126
- # Add org_id if available
127
- if self.config.org_id:
128
- kwargs["org_id"] = self.config.org_id
129
- else:
130
- raise ValueError("org_id must be set for organization-level operations")
131
-
132
- return {k: v for k, v in kwargs.items() if v is not None}
133
-
134
- @abstractmethod
135
- def get(self, fields: Optional[List[str]] = None) -> Dict[str, Any]:
136
- """
137
- Get project details.
138
-
139
- Args:
140
- fields: List of fields to retrieve
141
-
142
- Returns:
143
- Dictionary containing the requested project fields.
144
-
145
- Raises:
146
- APIError: If the API request fails.
147
- ValueError: If org_id or project_id are not set.
148
- """
149
- pass
150
-
151
- @abstractmethod
152
- def create(self, name: str, description: Optional[str] = None) -> Dict[str, Any]:
153
- """
154
- Create a new project within the organization.
155
-
156
- Args:
157
- name: Name of the project to be created
158
- description: Optional description for the project
159
-
160
- Returns:
161
- Dictionary containing the created project details.
162
-
163
- Raises:
164
- APIError: If the API request fails.
165
- ValueError: If org_id is not set.
166
- """
167
- pass
168
-
169
- @abstractmethod
170
- def update(
171
- self,
172
- custom_instructions: Optional[str] = None,
173
- custom_categories: Optional[List[str]] = None,
174
- retrieval_criteria: Optional[List[Dict[str, Any]]] = None,
175
- enable_graph: Optional[bool] = None,
176
- ) -> Dict[str, Any]:
177
- """
178
- Update project settings.
179
-
180
- Args:
181
- custom_instructions: New instructions for the project
182
- custom_categories: New categories for the project
183
- retrieval_criteria: New retrieval criteria for the project
184
- enable_graph: Enable or disable the graph for the project
185
-
186
- Returns:
187
- Dictionary containing the API response.
188
-
189
- Raises:
190
- APIError: If the API request fails.
191
- ValueError: If org_id or project_id are not set.
192
- """
193
- pass
194
-
195
- @abstractmethod
196
- def delete(self) -> Dict[str, Any]:
197
- """
198
- Delete the current project and its related data.
199
-
200
- Returns:
201
- Dictionary containing the API response.
202
-
203
- Raises:
204
- APIError: If the API request fails.
205
- ValueError: If org_id or project_id are not set.
206
- """
207
- pass
208
-
209
- @abstractmethod
210
- def get_members(self) -> Dict[str, Any]:
211
- """
212
- Get all members of the current project.
213
-
214
- Returns:
215
- Dictionary containing the list of project members.
216
-
217
- Raises:
218
- APIError: If the API request fails.
219
- ValueError: If org_id or project_id are not set.
220
- """
221
- pass
222
-
223
- @abstractmethod
224
- def add_member(self, email: str, role: str = "READER") -> Dict[str, Any]:
225
- """
226
- Add a new member to the current project.
227
-
228
- Args:
229
- email: Email address of the user to add
230
- role: Role to assign ("READER" or "OWNER")
231
-
232
- Returns:
233
- Dictionary containing the API response.
234
-
235
- Raises:
236
- APIError: If the API request fails.
237
- ValueError: If org_id or project_id are not set.
238
- """
239
- pass
240
-
241
- @abstractmethod
242
- def update_member(self, email: str, role: str) -> Dict[str, Any]:
243
- """
244
- Update a member's role in the current project.
245
-
246
- Args:
247
- email: Email address of the user to update
248
- role: New role to assign ("READER" or "OWNER")
249
-
250
- Returns:
251
- Dictionary containing the API response.
252
-
253
- Raises:
254
- APIError: If the API request fails.
255
- ValueError: If org_id or project_id are not set.
256
- """
257
- pass
258
-
259
- @abstractmethod
260
- def remove_member(self, email: str) -> Dict[str, Any]:
261
- """
262
- Remove a member from the current project.
263
-
264
- Args:
265
- email: Email address of the user to remove
266
-
267
- Returns:
268
- Dictionary containing the API response.
269
-
270
- Raises:
271
- APIError: If the API request fails.
272
- ValueError: If org_id or project_id are not set.
273
- """
274
- pass
275
-
276
-
277
- class Project(BaseProject):
278
- """
279
- Synchronous project management operations.
280
- """
281
-
282
- def __init__(
283
- self,
284
- client: httpx.Client,
285
- config: Optional[ProjectConfig] = None,
286
- org_id: Optional[str] = None,
287
- project_id: Optional[str] = None,
288
- user_email: Optional[str] = None,
289
- ):
290
- """
291
- Initialize the synchronous project manager.
292
-
293
- Args:
294
- client: HTTP client instance
295
- config: Project manager configuration
296
- org_id: Organization ID
297
- project_id: Project ID
298
- user_email: User email
299
- """
300
- super().__init__(client, config, org_id, project_id, user_email)
301
- self._validate_org_project()
302
-
303
- @api_error_handler
304
- def get(self, fields: Optional[List[str]] = None) -> Dict[str, Any]:
305
- """
306
- Get project details.
307
-
308
- Args:
309
- fields: List of fields to retrieve
310
-
311
- Returns:
312
- Dictionary containing the requested project fields.
313
-
314
- Raises:
315
- APIError: If the API request fails.
316
- ValueError: If org_id or project_id are not set.
317
- """
318
- params = self._prepare_params({"fields": fields})
319
- response = self._client.get(
320
- f"/api/v1/orgs/organizations/{self.config.org_id}/projects/{self.config.project_id}/",
321
- params=params,
322
- )
323
- response.raise_for_status()
324
- capture_client_event(
325
- "client.project.get",
326
- self,
327
- {"fields": fields, "sync_type": "sync"},
328
- )
329
- return response.json()
330
-
331
- @api_error_handler
332
- def create(self, name: str, description: Optional[str] = None) -> Dict[str, Any]:
333
- """
334
- Create a new project within the organization.
335
-
336
- Args:
337
- name: Name of the project to be created
338
- description: Optional description for the project
339
-
340
- Returns:
341
- Dictionary containing the created project details.
342
-
343
- Raises:
344
- APIError: If the API request fails.
345
- ValueError: If org_id is not set.
346
- """
347
- if not self.config.org_id:
348
- raise ValueError("org_id must be set to create a project")
349
-
350
- payload = {"name": name}
351
- if description is not None:
352
- payload["description"] = description
353
-
354
- response = self._client.post(
355
- f"/api/v1/orgs/organizations/{self.config.org_id}/projects/",
356
- json=payload,
357
- )
358
- response.raise_for_status()
359
- capture_client_event(
360
- "client.project.create",
361
- self,
362
- {"name": name, "description": description, "sync_type": "sync"},
363
- )
364
- return response.json()
365
-
366
- @api_error_handler
367
- def update(
368
- self,
369
- custom_instructions: Optional[str] = None,
370
- custom_categories: Optional[List[str]] = None,
371
- retrieval_criteria: Optional[List[Dict[str, Any]]] = None,
372
- enable_graph: Optional[bool] = None,
373
- ) -> Dict[str, Any]:
374
- """
375
- Update project settings.
376
-
377
- Args:
378
- custom_instructions: New instructions for the project
379
- custom_categories: New categories for the project
380
- retrieval_criteria: New retrieval criteria for the project
381
- enable_graph: Enable or disable the graph for the project
382
-
383
- Returns:
384
- Dictionary containing the API response.
385
-
386
- Raises:
387
- APIError: If the API request fails.
388
- ValueError: If org_id or project_id are not set.
389
- """
390
- if (
391
- custom_instructions is None
392
- and custom_categories is None
393
- and retrieval_criteria is None
394
- and enable_graph is None
395
- ):
396
- raise ValueError(
397
- "At least one parameter must be provided for update: "
398
- "custom_instructions, custom_categories, retrieval_criteria, "
399
- "enable_graph"
400
- )
401
-
402
- payload = self._prepare_params(
403
- {
404
- "custom_instructions": custom_instructions,
405
- "custom_categories": custom_categories,
406
- "retrieval_criteria": retrieval_criteria,
407
- "enable_graph": enable_graph,
408
- }
409
- )
410
- response = self._client.patch(
411
- f"/api/v1/orgs/organizations/{self.config.org_id}/projects/{self.config.project_id}/",
412
- json=payload,
413
- )
414
- response.raise_for_status()
415
- capture_client_event(
416
- "client.project.update",
417
- self,
418
- {
419
- "custom_instructions": custom_instructions,
420
- "custom_categories": custom_categories,
421
- "retrieval_criteria": retrieval_criteria,
422
- "enable_graph": enable_graph,
423
- "sync_type": "sync",
424
- },
425
- )
426
- return response.json()
427
-
428
- @api_error_handler
429
- def delete(self) -> Dict[str, Any]:
430
- """
431
- Delete the current project and its related data.
432
-
433
- Returns:
434
- Dictionary containing the API response.
435
-
436
- Raises:
437
- APIError: If the API request fails.
438
- ValueError: If org_id or project_id are not set.
439
- """
440
- response = self._client.delete(
441
- f"/api/v1/orgs/organizations/{self.config.org_id}/projects/{self.config.project_id}/",
442
- )
443
- response.raise_for_status()
444
- capture_client_event(
445
- "client.project.delete",
446
- self,
447
- {"sync_type": "sync"},
448
- )
449
- return response.json()
450
-
451
- @api_error_handler
452
- def get_members(self) -> Dict[str, Any]:
453
- """
454
- Get all members of the current project.
455
-
456
- Returns:
457
- Dictionary containing the list of project members.
458
-
459
- Raises:
460
- APIError: If the API request fails.
461
- ValueError: If org_id or project_id are not set.
462
- """
463
- response = self._client.get(
464
- f"/api/v1/orgs/organizations/{self.config.org_id}/projects/{self.config.project_id}/members/",
465
- )
466
- response.raise_for_status()
467
- capture_client_event(
468
- "client.project.get_members",
469
- self,
470
- {"sync_type": "sync"},
471
- )
472
- return response.json()
473
-
474
- @api_error_handler
475
- def add_member(self, email: str, role: str = "READER") -> Dict[str, Any]:
476
- """
477
- Add a new member to the current project.
478
-
479
- Args:
480
- email: Email address of the user to add
481
- role: Role to assign ("READER" or "OWNER")
482
-
483
- Returns:
484
- Dictionary containing the API response.
485
-
486
- Raises:
487
- APIError: If the API request fails.
488
- ValueError: If org_id or project_id are not set.
489
- """
490
- if role not in ["READER", "OWNER"]:
491
- raise ValueError("Role must be either 'READER' or 'OWNER'")
492
-
493
- payload = {"email": email, "role": role}
494
-
495
- response = self._client.post(
496
- f"/api/v1/orgs/organizations/{self.config.org_id}/projects/{self.config.project_id}/members/",
497
- json=payload,
498
- )
499
- response.raise_for_status()
500
- capture_client_event(
501
- "client.project.add_member",
502
- self,
503
- {"email": email, "role": role, "sync_type": "sync"},
504
- )
505
- return response.json()
506
-
507
- @api_error_handler
508
- def update_member(self, email: str, role: str) -> Dict[str, Any]:
509
- """
510
- Update a member's role in the current project.
511
-
512
- Args:
513
- email: Email address of the user to update
514
- role: New role to assign ("READER" or "OWNER")
515
-
516
- Returns:
517
- Dictionary containing the API response.
518
-
519
- Raises:
520
- APIError: If the API request fails.
521
- ValueError: If org_id or project_id are not set.
522
- """
523
- if role not in ["READER", "OWNER"]:
524
- raise ValueError("Role must be either 'READER' or 'OWNER'")
525
-
526
- payload = {"email": email, "role": role}
527
-
528
- response = self._client.put(
529
- f"/api/v1/orgs/organizations/{self.config.org_id}/projects/{self.config.project_id}/members/",
530
- json=payload,
531
- )
532
- response.raise_for_status()
533
- capture_client_event(
534
- "client.project.update_member",
535
- self,
536
- {"email": email, "role": role, "sync_type": "sync"},
537
- )
538
- return response.json()
539
-
540
- @api_error_handler
541
- def remove_member(self, email: str) -> Dict[str, Any]:
542
- """
543
- Remove a member from the current project.
544
-
545
- Args:
546
- email: Email address of the user to remove
547
-
548
- Returns:
549
- Dictionary containing the API response.
550
-
551
- Raises:
552
- APIError: If the API request fails.
553
- ValueError: If org_id or project_id are not set.
554
- """
555
- params = {"email": email}
556
-
557
- response = self._client.delete(
558
- f"/api/v1/orgs/organizations/{self.config.org_id}/projects/{self.config.project_id}/members/",
559
- params=params,
560
- )
561
- response.raise_for_status()
562
- capture_client_event(
563
- "client.project.remove_member",
564
- self,
565
- {"email": email, "sync_type": "sync"},
566
- )
567
- return response.json()
568
-
569
-
570
- class AsyncProject(BaseProject):
571
- """
572
- Asynchronous project management operations.
573
- """
574
-
575
- def __init__(
576
- self,
577
- client: httpx.AsyncClient,
578
- config: Optional[ProjectConfig] = None,
579
- org_id: Optional[str] = None,
580
- project_id: Optional[str] = None,
581
- user_email: Optional[str] = None,
582
- ):
583
- """
584
- Initialize the asynchronous project manager.
585
-
586
- Args:
587
- client: HTTP client instance
588
- config: Project manager configuration
589
- org_id: Organization ID
590
- project_id: Project ID
591
- user_email: User email
592
- """
593
- super().__init__(client, config, org_id, project_id, user_email)
594
- self._validate_org_project()
595
-
596
- @api_error_handler
597
- async def get(self, fields: Optional[List[str]] = None) -> Dict[str, Any]:
598
- """
599
- Get project details.
600
-
601
- Args:
602
- fields: List of fields to retrieve
603
-
604
- Returns:
605
- Dictionary containing the requested project fields.
606
-
607
- Raises:
608
- APIError: If the API request fails.
609
- ValueError: If org_id or project_id are not set.
610
- """
611
- params = self._prepare_params({"fields": fields})
612
- response = await self._client.get(
613
- f"/api/v1/orgs/organizations/{self.config.org_id}/projects/{self.config.project_id}/",
614
- params=params,
615
- )
616
- response.raise_for_status()
617
- capture_client_event(
618
- "client.project.get",
619
- self,
620
- {"fields": fields, "sync_type": "async"},
621
- )
622
- return response.json()
623
-
624
- @api_error_handler
625
- async def create(self, name: str, description: Optional[str] = None) -> Dict[str, Any]:
626
- """
627
- Create a new project within the organization.
628
-
629
- Args:
630
- name: Name of the project to be created
631
- description: Optional description for the project
632
-
633
- Returns:
634
- Dictionary containing the created project details.
635
-
636
- Raises:
637
- APIError: If the API request fails.
638
- ValueError: If org_id is not set.
639
- """
640
- if not self.config.org_id:
641
- raise ValueError("org_id must be set to create a project")
642
-
643
- payload = {"name": name}
644
- if description is not None:
645
- payload["description"] = description
646
-
647
- response = await self._client.post(
648
- f"/api/v1/orgs/organizations/{self.config.org_id}/projects/",
649
- json=payload,
650
- )
651
- response.raise_for_status()
652
- capture_client_event(
653
- "client.project.create",
654
- self,
655
- {"name": name, "description": description, "sync_type": "async"},
656
- )
657
- return response.json()
658
-
659
- @api_error_handler
660
- async def update(
661
- self,
662
- custom_instructions: Optional[str] = None,
663
- custom_categories: Optional[List[str]] = None,
664
- retrieval_criteria: Optional[List[Dict[str, Any]]] = None,
665
- enable_graph: Optional[bool] = None,
666
- ) -> Dict[str, Any]:
667
- """
668
- Update project settings.
669
-
670
- Args:
671
- custom_instructions: New instructions for the project
672
- custom_categories: New categories for the project
673
- retrieval_criteria: New retrieval criteria for the project
674
- enable_graph: Enable or disable the graph for the project
675
-
676
- Returns:
677
- Dictionary containing the API response.
678
-
679
- Raises:
680
- APIError: If the API request fails.
681
- ValueError: If org_id or project_id are not set.
682
- """
683
- if (
684
- custom_instructions is None
685
- and custom_categories is None
686
- and retrieval_criteria is None
687
- and enable_graph is None
688
- ):
689
- raise ValueError(
690
- "At least one parameter must be provided for update: "
691
- "custom_instructions, custom_categories, retrieval_criteria, "
692
- "enable_graph"
693
- )
694
-
695
- payload = self._prepare_params(
696
- {
697
- "custom_instructions": custom_instructions,
698
- "custom_categories": custom_categories,
699
- "retrieval_criteria": retrieval_criteria,
700
- "enable_graph": enable_graph,
701
- }
702
- )
703
- response = await self._client.patch(
704
- f"/api/v1/orgs/organizations/{self.config.org_id}/projects/{self.config.project_id}/",
705
- json=payload,
706
- )
707
- response.raise_for_status()
708
- capture_client_event(
709
- "client.project.update",
710
- self,
711
- {
712
- "custom_instructions": custom_instructions,
713
- "custom_categories": custom_categories,
714
- "retrieval_criteria": retrieval_criteria,
715
- "enable_graph": enable_graph,
716
- "sync_type": "async",
717
- },
718
- )
719
- return response.json()
720
-
721
- @api_error_handler
722
- async def delete(self) -> Dict[str, Any]:
723
- """
724
- Delete the current project and its related data.
725
-
726
- Returns:
727
- Dictionary containing the API response.
728
-
729
- Raises:
730
- APIError: If the API request fails.
731
- ValueError: If org_id or project_id are not set.
732
- """
733
- response = await self._client.delete(
734
- f"/api/v1/orgs/organizations/{self.config.org_id}/projects/{self.config.project_id}/",
735
- )
736
- response.raise_for_status()
737
- capture_client_event(
738
- "client.project.delete",
739
- self,
740
- {"sync_type": "async"},
741
- )
742
- return response.json()
743
-
744
- @api_error_handler
745
- async def get_members(self) -> Dict[str, Any]:
746
- """
747
- Get all members of the current project.
748
-
749
- Returns:
750
- Dictionary containing the list of project members.
751
-
752
- Raises:
753
- APIError: If the API request fails.
754
- ValueError: If org_id or project_id are not set.
755
- """
756
- response = await self._client.get(
757
- f"/api/v1/orgs/organizations/{self.config.org_id}/projects/{self.config.project_id}/members/",
758
- )
759
- response.raise_for_status()
760
- capture_client_event(
761
- "client.project.get_members",
762
- self,
763
- {"sync_type": "async"},
764
- )
765
- return response.json()
766
-
767
- @api_error_handler
768
- async def add_member(self, email: str, role: str = "READER") -> Dict[str, Any]:
769
- """
770
- Add a new member to the current project.
771
-
772
- Args:
773
- email: Email address of the user to add
774
- role: Role to assign ("READER" or "OWNER")
775
-
776
- Returns:
777
- Dictionary containing the API response.
778
-
779
- Raises:
780
- APIError: If the API request fails.
781
- ValueError: If org_id or project_id are not set.
782
- """
783
- if role not in ["READER", "OWNER"]:
784
- raise ValueError("Role must be either 'READER' or 'OWNER'")
785
-
786
- payload = {"email": email, "role": role}
787
-
788
- response = await self._client.post(
789
- f"/api/v1/orgs/organizations/{self.config.org_id}/projects/{self.config.project_id}/members/",
790
- json=payload,
791
- )
792
- response.raise_for_status()
793
- capture_client_event(
794
- "client.project.add_member",
795
- self,
796
- {"email": email, "role": role, "sync_type": "async"},
797
- )
798
- return response.json()
799
-
800
- @api_error_handler
801
- async def update_member(self, email: str, role: str) -> Dict[str, Any]:
802
- """
803
- Update a member's role in the current project.
804
-
805
- Args:
806
- email: Email address of the user to update
807
- role: New role to assign ("READER" or "OWNER")
808
-
809
- Returns:
810
- Dictionary containing the API response.
811
-
812
- Raises:
813
- APIError: If the API request fails.
814
- ValueError: If org_id or project_id are not set.
815
- """
816
- if role not in ["READER", "OWNER"]:
817
- raise ValueError("Role must be either 'READER' or 'OWNER'")
818
-
819
- payload = {"email": email, "role": role}
820
-
821
- response = await self._client.put(
822
- f"/api/v1/orgs/organizations/{self.config.org_id}/projects/{self.config.project_id}/members/",
823
- json=payload,
824
- )
825
- response.raise_for_status()
826
- capture_client_event(
827
- "client.project.update_member",
828
- self,
829
- {"email": email, "role": role, "sync_type": "async"},
830
- )
831
- return response.json()
832
-
833
- @api_error_handler
834
- async def remove_member(self, email: str) -> Dict[str, Any]:
835
- """
836
- Remove a member from the current project.
837
-
838
- Args:
839
- email: Email address of the user to remove
840
-
841
- Returns:
842
- Dictionary containing the API response.
843
-
844
- Raises:
845
- APIError: If the API request fails.
846
- ValueError: If org_id or project_id are not set.
847
- """
848
- params = {"email": email}
849
-
850
- response = await self._client.delete(
851
- f"/api/v1/orgs/organizations/{self.config.org_id}/projects/{self.config.project_id}/members/",
852
- params=params,
853
- )
854
- response.raise_for_status()
855
- capture_client_event(
856
- "client.project.remove_member",
857
- self,
858
- {"email": email, "sync_type": "async"},
859
- )
860
- return response.json()