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