diff --git a/api/ee/src/routers/organization_router.py b/api/ee/src/routers/organization_router.py index 7b265a692a..739894b7b8 100644 --- a/api/ee/src/routers/organization_router.py +++ b/api/ee/src/routers/organization_router.py @@ -53,9 +53,9 @@ async def get_user_organization( raise HTTPException(status_code=500, detail=str(e)) -@router.get("/{org_id}/", operation_id="fetch_ee_organization_details") +@router.get("/{organization_id}/", operation_id="fetch_ee_organization_details") async def fetch_organization_details( - org_id: str, + organization_id: str, request: Request, ): """Get an organization's details. @@ -70,7 +70,7 @@ async def fetch_organization_details( try: workspace_id = await db_manager_ee.get_default_workspace_id_from_organization( - organization_id=org_id + organization_id=organization_id ) project_id = await db_manager.get_default_project_id_from_workspace( @@ -96,14 +96,16 @@ async def fetch_organization_details( user_org_workspace_data = await get_user_org_and_workspace_id( request.state.user_id ) - has_permission = await check_user_org_access(user_org_workspace_data, org_id) + has_permission = await check_user_org_access( + user_org_workspace_data, organization_id + ) if not has_permission: return JSONResponse( status_code=403, content={"detail": "You do not have access to this organization"}, ) - organization = await get_organization_details(org_id) + organization = await get_organization_details(organization_id) if membership.role == "viewer" or membership.is_demo: if "default_workspace" in organization: @@ -121,9 +123,9 @@ async def fetch_organization_details( ) -@router.put("/{org_id}/", operation_id="update_organization") +@router.put("/{organization_id}/", operation_id="update_organization") async def update_organization( - org_id: str, + organization_id: str, payload: OrganizationUpdate, request: Request, ): @@ -138,7 +140,7 @@ async def update_organization( request.state.user_id ) has_permission = await check_user_org_access( - user_org_workspace_data, org_id, check_owner=True + user_org_workspace_data, organization_id, check_owner=True ) if not has_permission: return JSONResponse( @@ -146,7 +148,7 @@ async def update_organization( status_code=403, ) - organization = await update_an_organization(org_id, payload) + organization = await update_an_organization(organization_id, payload) return organization @@ -158,12 +160,12 @@ async def update_organization( @router.post( - "/{org_id}/workspaces/", + "/{organization_id}/workspaces/", operation_id="create_workspace", response_model=WorkspaceResponse, ) async def create_workspace( - org_id: str, + organization_id: str, payload: CreateWorkspace, request: Request, ) -> WorkspaceResponse: @@ -172,7 +174,7 @@ async def create_workspace( request.state.user_id ) has_permission = await check_user_org_access( - user_org_workspace_data, org_id, check_owner=True + user_org_workspace_data, organization_id, check_owner=True ) if not has_permission: return JSONResponse( @@ -186,7 +188,7 @@ async def create_workspace( status_code=400, ) workspace = await workspace_manager.create_new_workspace( - payload, org_id, user_org_workspace_data["uid"] + payload, organization_id, user_org_workspace_data["uid"] ) return workspace @@ -198,12 +200,12 @@ async def create_workspace( @router.put( - "/{org_id}/workspaces/{workspace_id}/", + "/{organization_id}/workspaces/{workspace_id}/", operation_id="update_workspace", response_model=WorkspaceResponse, ) async def update_workspace( - org_id: str, + organization_id: str, workspace_id: str, payload: UpdateWorkspace, request: Request, diff --git a/api/ee/src/routers/workspace_router.py b/api/ee/src/routers/workspace_router.py index 40e0e17885..db14403946 100644 --- a/api/ee/src/routers/workspace_router.py +++ b/api/ee/src/routers/workspace_router.py @@ -110,7 +110,7 @@ async def assign_role_to_user( @router.delete("/{workspace_id}/roles/", operation_id="unassign_role_from_user") async def unassign_role_from_user( email: str, - org_id: str, + organization_id: str, role: str, workspace_id: str, request: Request, @@ -121,7 +121,7 @@ async def unassign_role_from_user( Args: workspace_id (str): The ID of the workspace. email (str): The email of the user to remove the role from. - org_id (str): The ID of the organization. + organization_id (str): The ID of the organization. role (str): The role to remove from the user. request (Request): The FastAPI request object. @@ -153,7 +153,7 @@ async def unassign_role_from_user( payload = UserRole( email=email, - organization_id=org_id, + organization_id=organization_id, role=role, ) diff --git a/api/ee/src/services/db_manager_ee.py b/api/ee/src/services/db_manager_ee.py index c0076afac3..c8ebffece7 100644 --- a/api/ee/src/services/db_manager_ee.py +++ b/api/ee/src/services/db_manager_ee.py @@ -105,7 +105,9 @@ async def get_organizations_by_list_ids(organization_ids: List) -> List[Organiza """ async with engine.core_session() as session: - organization_uuids = [uuid.UUID(org_id) for org_id in organization_ids] + organization_uuids = [ + uuid.UUID(organization_id) for organization_id in organization_ids + ] query = select(OrganizationDB).where(OrganizationDB.id.in_(organization_uuids)) result = await session.execute(query) organizations = result.scalars().all() diff --git a/api/ee/src/services/organization_service.py b/api/ee/src/services/organization_service.py index 7ee4fdb150..73488353b4 100644 --- a/api/ee/src/services/organization_service.py +++ b/api/ee/src/services/organization_service.py @@ -15,9 +15,9 @@ async def update_an_organization( - org_id: str, payload: OrganizationUpdate + organization_id: str, payload: OrganizationUpdate ) -> OrganizationDB: - org = await db_manager_ee.get_organization(org_id) + org = await db_manager_ee.get_organization(organization_id) if org is not None: await db_manager_ee.update_organization(str(org.id), payload) return org @@ -61,8 +61,12 @@ async def send_invitation_email( project_param = quote(project_id, safe="") invite_link = ( - f"{env.AGENTA_WEB_URL}/auth?token={token_param}&email={email_param}" - f"&org_id={org_param}&workspace_id={workspace_param}&project_id={project_param}" + f"{env.AGENTA_WEB_URL}/auth" + f"?token={token_param}" + f"&email={email_param}" + f"&organization_id={org_param}" + f"&workspace_id={workspace_param}" + f"&project_id={project_param}" ) html_content = html_template.format( @@ -116,6 +120,6 @@ async def notify_org_admin_invitation(workspace: WorkspaceDB, user: UserDB) -> b return True -async def get_organization_details(org_id: str) -> dict: - organization = await db_manager_ee.get_organization(org_id) +async def get_organization_details(organization_id: str) -> dict: + organization = await db_manager_ee.get_organization(organization_id) return await db_manager_ee.get_org_details(organization) diff --git a/api/ee/src/services/workspace_manager.py b/api/ee/src/services/workspace_manager.py index d446729804..5bbebc78e6 100644 --- a/api/ee/src/services/workspace_manager.py +++ b/api/ee/src/services/workspace_manager.py @@ -128,7 +128,7 @@ async def get_all_workspace_permissions() -> List[Permission]: async def invite_user_to_workspace( payload: List[InviteRequest], - org_id: str, + organization_id: str, project_id: str, workspace_id: str, user_uid: str, @@ -138,7 +138,7 @@ async def invite_user_to_workspace( Args: user_uid (str): The user uid. - org_id (str): The ID of the organization that the workspace belongs to. + organization_id (str): The ID of the organization that the workspace belongs to. project_id (str): The ID of the project that belongs to the workspace. workspace_id (str): The ID of the workspace. payload (InviteRequest): The payload containing the email address of the user to invite. @@ -152,7 +152,7 @@ async def invite_user_to_workspace( try: workspace = await get_workspace(workspace_id) - organization = await db_manager_ee.get_organization(org_id) + organization = await db_manager_ee.get_organization(organization_id) user_performing_action = await db_manager.get_user(user_uid) for payload_invite in payload: @@ -216,7 +216,7 @@ async def invite_user_to_workspace( async def resend_user_workspace_invite( payload: ReseendInviteRequest, project_id: str, - org_id: str, + organization_id: str, workspace_id: str, user_uid: str, ) -> JSONResponse: @@ -224,7 +224,7 @@ async def resend_user_workspace_invite( Resend an invitation to a user to a workspace. Args: - org_id (str): The ID of the organization that the workspace belongs to. + organization_id (str): The ID of the organization that the workspace belongs to. project_id (str): The ID of the project. workspace_id (str): The ID of the workspace. payload (ReseendInviteRequest): The payload containing the email address of the user to invite. @@ -238,7 +238,7 @@ async def resend_user_workspace_invite( try: workspace = await get_workspace(workspace_id) - organization = await db_manager_ee.get_organization(org_id) + organization = await db_manager_ee.get_organization(organization_id) user_performing_action = await db_manager.get_user(user_uid) # Check if the email address already has a valid, unused invitation for the workspace diff --git a/api/oss/src/routers/organization_router.py b/api/oss/src/routers/organization_router.py index 7a50c3bd7d..16e9593fcc 100644 --- a/api/oss/src/routers/organization_router.py +++ b/api/oss/src/routers/organization_router.py @@ -85,12 +85,12 @@ async def list_organizations( @router.get( - "/{org_id}/", + "/{organization_id}/", operation_id="fetch_organization_details", response_model=OrganizationDetails, ) async def fetch_organization_details( - org_id: str, + organization_id: str, request: Request, ): """Return the details of the organization.""" @@ -100,11 +100,15 @@ async def fetch_organization_details( if not active_workspace: return {} - organization_owner = await db_manager.get_organization_owner(organization_id=org_id) + organization_owner = await db_manager.get_organization_owner( + organization_id=organization_id + ) project_invitations = await db_manager.get_project_invitations( project_id=request.state.project_id ) - organization_db = await db_manager.get_organization_by_id(organization_id=org_id) + organization_db = await db_manager.get_organization_by_id( + organization_id=organization_id + ) invited_members = [ { @@ -164,11 +168,11 @@ async def fetch_organization_details( @router.post( - "/{org_id}/workspaces/{workspace_id}/invite/", + "/{organization_id}/workspaces/{workspace_id}/invite/", operation_id="invite_user_to_workspace", ) async def invite_user_to_organization( - org_id: str, + organization_id: str, payload: List[InviteRequest], workspace_id: str, request: Request, @@ -177,7 +181,7 @@ async def invite_user_to_organization( Assigns a role to a user in an organization. Args: - org_id (str): The ID of the organization. + organization_id (str): The ID of the organization. payload (InviteRequest): The payload containing the organization id, user email, and role to assign. workspace_id (str): The ID of the workspace. @@ -213,7 +217,7 @@ async def invite_user_to_organization( }, ) - owner = await db_manager.get_organization_owner(org_id) + owner = await db_manager.get_organization_owner(organization_id) owner_domain = owner.email.split("@")[-1].lower() if owner else "" user_domain = payload[0].email.split("@")[-1].lower() skip_meter = owner_domain != "agenta.ai" and user_domain == "agenta.ai" @@ -230,7 +234,7 @@ async def invite_user_to_organization( invite_user = await workspace_manager.invite_user_to_workspace( payload=payload, - org_id=org_id, + organization_id=organization_id, project_id=str(project.id), workspace_id=workspace_id, user_uid=request.state.user_id, @@ -246,11 +250,11 @@ async def invite_user_to_organization( @router.post( - "/{org_id}/workspaces/{workspace_id}/invite/resend/", + "/{organization_id}/workspaces/{workspace_id}/invite/resend/", operation_id="resend_invitation", ) async def resend_user_invitation_to_organization( - org_id: str, + organization_id: str, workspace_id: str, payload: ResendInviteRequest, request: Request, @@ -287,7 +291,7 @@ async def resend_user_invitation_to_organization( invite_user = await workspace_manager.resend_user_workspace_invite( payload=payload, project_id=request.state.project_id, - org_id=org_id, + organization_id=organization_id, workspace_id=workspace_id, user_uid=request.state.user_id, ) @@ -302,11 +306,11 @@ async def resend_user_invitation_to_organization( @router.post( - "/{org_id}/workspaces/{workspace_id}/invite/accept/", + "/{organization_id}/workspaces/{workspace_id}/invite/accept/", operation_id="accept_invitation", ) async def accept_organization_invitation( - org_id: str, + organization_id: str, workspace_id: str, project_id: str, payload: InviteToken, @@ -326,7 +330,7 @@ async def accept_organization_invitation( if is_ee(): workspace = await workspace_manager.get_workspace(workspace_id) - organization = await db_manager_ee.get_organization(org_id) + organization = await db_manager_ee.get_organization(organization_id) user = await db_manager.get_user(request.state.user_id) accept_invitation = await workspace_manager.accept_workspace_invitation( @@ -343,7 +347,7 @@ async def accept_organization_invitation( else: await organization_service.accept_organization_invitation( token=payload.token, - organization_id=org_id, + organization_id=organization_id, email=payload.email, ) return JSONResponse({"message": "Added user to workspace"}, status_code=200) diff --git a/api/oss/src/routers/projects_router.py b/api/oss/src/routers/projects_router.py index ae88d3562d..2288ee38e2 100644 --- a/api/oss/src/routers/projects_router.py +++ b/api/oss/src/routers/projects_router.py @@ -49,10 +49,39 @@ async def get_projects( project_id=request.state.project_id ) + if not _project: + raise HTTPException(status_code=404, detail="Project not found") + + _workspace = await db_manager.fetch_workspace_by_id( + workspace_id=str(_project.workspace_id) + ) + + if not _workspace: + raise HTTPException(status_code=404, detail="Workspace not found") + + _organization = await db_manager.fetch_organization_by_id( + organization_id=str(_workspace.organization_id) + ) + + if not _organization: + raise HTTPException(status_code=404, detail="Organization not found") + + user_role = ( + "owner" + if str(_organization.owner) == str(request.state.user_id) + else "editor" + ) + projects = [ ProjectsResponse( - project_id=_project.id, - project_name=_project.project_name, + organization_id=UUID(str(_organization.id)), + organization_name=str(_organization.name), + workspace_id=UUID(str(_workspace.id)), + workspace_name=str(_workspace.name), + project_id=UUID(str(_project.id)), + project_name=str(_project.project_name), + user_role=user_role, + is_demo=False, ) ] diff --git a/api/oss/src/services/db_manager.py b/api/oss/src/services/db_manager.py index 6a73cf8339..2639f29711 100644 --- a/api/oss/src/services/db_manager.py +++ b/api/oss/src/services/db_manager.py @@ -58,7 +58,7 @@ async def fetch_project_by_id( project_id: str, -) -> ProjectDB: +) -> Optional[ProjectDB]: async with engine.core_session() as session: project = ( ( @@ -75,6 +75,44 @@ async def fetch_project_by_id( return project +async def fetch_workspace_by_id( + workspace_id: str, +) -> Optional[WorkspaceDB]: + async with engine.core_session() as session: + workspace = ( + ( + await session.execute( + select(WorkspaceDB).filter_by( + id=uuid.UUID(workspace_id), + ) + ) + ) + .scalars() + .first() + ) + + return workspace + + +async def fetch_organization_by_id( + organization_id: str, +) -> Optional[OrganizationDB]: + async with engine.core_session() as session: + organization = ( + ( + await session.execute( + select(OrganizationDB).filter_by( + id=uuid.UUID(organization_id), + ) + ) + ) + .scalars() + .first() + ) + + return organization + + async def add_testset_to_app_variant( template_name: str, app_name: str, project_id: str ): diff --git a/api/oss/src/services/organization_service.py b/api/oss/src/services/organization_service.py index 427279fd85..030ce6bd3f 100644 --- a/api/oss/src/services/organization_service.py +++ b/api/oss/src/services/organization_service.py @@ -1,5 +1,6 @@ import secrets from datetime import datetime, timedelta, timezone +from urllib.parse import quote from fastapi import HTTPException @@ -94,16 +95,29 @@ async def send_invitation_email( bool: True if the email was sent successfully, False otherwise. """ - invitation_link = f"""{env.AGENTA_WEB_URL}/auth?token={token}&org_id={organization_id}&project_id={project_id}&workspace_id={workspace_id}&email={email}""" + token_param = quote(token, safe="") + email_param = quote(email, safe="") + org_param = quote(str(organization_id), safe="") + workspace_param = quote(str(workspace_id), safe="") + project_param = quote(project_id, safe="") + + invite_link = ( + f"{env.AGENTA_WEB_URL}/auth" + f"?token={token_param}" + f"&email={email_param}" + f"&organization_id={org_param}" + f"&workspace_id={workspace_param}" + f"&project_id={project_param}" + ) if not env.SENDGRID_API_KEY: - return invitation_link + return invite_link html_template = email_service.read_email_template("./templates/send_email.html") html_content = html_template.format( username_placeholder=user.username, action_placeholder="invited you to join", workspace_placeholder="their organization", - call_to_action=f"""Click the link below to accept the invitation:


Accept Invitation""", + call_to_action=f"""Click the link below to accept the invitation:


Accept Invitation""", ) if not env.AGENTA_SEND_EMAIL_FROM_ADDRESS: @@ -219,7 +233,7 @@ async def resend_user_organization_invite( Args: user_uid (str): The user uid. - org_id (str): The ID of the organization to invite the user to. + organization_id (str): The ID of the organization to invite the user to. project_id (str): The ID of the project that belongs to the workspace/organization. payload (ResendInviteRequest): The payload containing the email address of the user to invite. """ @@ -283,10 +297,8 @@ async def accept_organization_invitation( try: user_exists = await db_manager.get_user_with_email(email=email) - if user_exists is not None: - raise HTTPException( - status_code=400, detail="User is already a member of the organization" - ) + if user_exists is None: + raise HTTPException(status_code=400, detail="User does not exist") project_db = await db_manager.get_project_by_organization_id( organization_id=organization_id diff --git a/api/pyproject.toml b/api/pyproject.toml index 35e55fa50d..feeb72eeea 100644 --- a/api/pyproject.toml +++ b/api/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "api" -version = "0.59.0" +version = "0.59.1" description = "Agenta API" authors = [ { name = "Mahmoud Mabrouk", email = "mahmoud@agenta.ai" }, diff --git a/docs/docs/reference/api/accept-invitation.api.mdx b/docs/docs/reference/api/accept-invitation.api.mdx index bce95f2bf9..b1b953d05c 100644 --- a/docs/docs/reference/api/accept-invitation.api.mdx +++ b/docs/docs/reference/api/accept-invitation.api.mdx @@ -33,7 +33,7 @@ import TabItem from "@theme/TabItem"; Accept an invitation to an organization. @@ -69,7 +69,7 @@ JSONResponse: Accepted invitation to workspace; status_code: 200 Create Workspace @@ -61,7 +61,7 @@ Create Workspace - + Return the details of the organization. @@ -42,7 +42,7 @@ Return the details of the organization. Assigns a role to a user in an organization. Args: -org_id (str): The ID of the organization. +organization_id (str): The ID of the organization. payload (InviteRequest): The payload containing the organization id, user email, and role to assign. workspace_id (str): The ID of the workspace. @@ -73,7 +73,7 @@ HTTPException: If there is an error assigning the role to the user. Resend an invitation to a user to an Organization. @@ -69,7 +69,7 @@ JSONResponse: Resent invitation to user; status_code: 200 Update Organization @@ -61,7 +61,7 @@ Update Organization Update Workspace @@ -61,7 +61,7 @@ Update Workspace typing.Optional[typing.Any]: @@ -437,7 +439,7 @@ def unassign_role_from_user( Args: workspace_id (str): The ID of the workspace. email (str): The email of the user to remove the role from. - org_id (str): The ID of the organization. + organization_id (str): The ID of the organization. role (str): The role to remove from the user. request (Request): The FastAPI request object. @@ -454,7 +456,7 @@ def unassign_role_from_user( email : str - org_id : str + organization_id : str role : str @@ -476,14 +478,14 @@ def unassign_role_from_user( client.unassign_role_from_user( workspace_id="workspace_id", email="email", - org_id="org_id", + organization_id="organization_id", role="role", ) """ _response = self._raw_client.unassign_role_from_user( workspace_id, email=email, - org_id=org_id, + organization_id=organization_id, role=role, request_options=request_options, ) @@ -650,20 +652,22 @@ def __init__( _defaulted_timeout = ( timeout if timeout is not None - else 60 - if httpx_client is None - else httpx_client.timeout.read + else 60 if httpx_client is None else httpx_client.timeout.read ) self._client_wrapper = AsyncClientWrapper( base_url=_get_base_url(base_url=base_url, environment=environment), api_key=api_key, - httpx_client=httpx_client - if httpx_client is not None - else httpx.AsyncClient( - timeout=_defaulted_timeout, follow_redirects=follow_redirects - ) - if follow_redirects is not None - else httpx.AsyncClient(timeout=_defaulted_timeout), + httpx_client=( + httpx_client + if httpx_client is not None + else ( + httpx.AsyncClient( + timeout=_defaulted_timeout, follow_redirects=follow_redirects + ) + if follow_redirects is not None + else httpx.AsyncClient(timeout=_defaulted_timeout) + ) + ), timeout=_defaulted_timeout, ) self._raw_client = AsyncRawAgentaApi(client_wrapper=self._client_wrapper) @@ -743,7 +747,7 @@ async def main() -> None: async def update_organization( self, - org_id: str, + organization_id: str, *, name: typing.Optional[str] = OMIT, description: typing.Optional[str] = OMIT, @@ -753,7 +757,7 @@ async def update_organization( """ Parameters ---------- - org_id : str + organization_id : str name : typing.Optional[str] @@ -782,14 +786,14 @@ async def update_organization( async def main() -> None: await client.update_organization( - org_id="org_id", + organization_id="organization_id", ) asyncio.run(main()) """ _response = await self._raw_client.update_organization( - org_id, + organization_id, name=name, description=description, updated_at=updated_at, @@ -799,7 +803,7 @@ async def main() -> None: async def create_workspace( self, - org_id: str, + organization_id: str, *, name: str, description: typing.Optional[str] = OMIT, @@ -809,7 +813,7 @@ async def create_workspace( """ Parameters ---------- - org_id : str + organization_id : str name : str @@ -838,7 +842,7 @@ async def create_workspace( async def main() -> None: await client.create_workspace( - org_id="org_id", + organization_id="organization_id", name="name", ) @@ -846,7 +850,7 @@ async def main() -> None: asyncio.run(main()) """ _response = await self._raw_client.create_workspace( - org_id, + organization_id, name=name, description=description, type=type, @@ -856,7 +860,7 @@ async def main() -> None: async def update_workspace( self, - org_id: str, + organization_id: str, workspace_id: str, *, name: typing.Optional[str] = OMIT, @@ -867,7 +871,7 @@ async def update_workspace( """ Parameters ---------- - org_id : str + organization_id : str workspace_id : str @@ -898,7 +902,7 @@ async def update_workspace( async def main() -> None: await client.update_workspace( - org_id="org_id", + organization_id="organization_id", workspace_id="workspace_id", ) @@ -906,7 +910,7 @@ async def main() -> None: asyncio.run(main()) """ _response = await self._raw_client.update_workspace( - org_id, + organization_id, workspace_id, name=name, description=description, @@ -1038,7 +1042,7 @@ async def unassign_role_from_user( workspace_id: str, *, email: str, - org_id: str, + organization_id: str, role: str, request_options: typing.Optional[RequestOptions] = None, ) -> typing.Optional[typing.Any]: @@ -1048,7 +1052,7 @@ async def unassign_role_from_user( Args: workspace_id (str): The ID of the workspace. email (str): The email of the user to remove the role from. - org_id (str): The ID of the organization. + organization_id (str): The ID of the organization. role (str): The role to remove from the user. request (Request): The FastAPI request object. @@ -1065,7 +1069,7 @@ async def unassign_role_from_user( email : str - org_id : str + organization_id : str role : str @@ -1092,7 +1096,7 @@ async def main() -> None: await client.unassign_role_from_user( workspace_id="workspace_id", email="email", - org_id="org_id", + organization_id="organization_id", role="role", ) @@ -1102,7 +1106,7 @@ async def main() -> None: _response = await self._raw_client.unassign_role_from_user( workspace_id, email=email, - org_id=org_id, + organization_id=organization_id, role=role, request_options=request_options, ) diff --git a/sdk/agenta/client/backend/organization/client.py b/sdk/agenta/client/backend/organization/client.py index a2a3ec473d..bac17e1d92 100644 --- a/sdk/agenta/client/backend/organization/client.py +++ b/sdk/agenta/client/backend/organization/client.py @@ -29,14 +29,17 @@ def with_raw_response(self) -> RawOrganizationClient: return self._raw_client def fetch_organization_details( - self, org_id: str, *, request_options: typing.Optional[RequestOptions] = None + self, + organization_id: str, + *, + request_options: typing.Optional[RequestOptions] = None, ) -> OrganizationDetails: """ Return the details of the organization. Parameters ---------- - org_id : str + organization_id : str request_options : typing.Optional[RequestOptions] Request-specific configuration. @@ -54,11 +57,11 @@ def fetch_organization_details( api_key="YOUR_API_KEY", ) client.organization.fetch_organization_details( - org_id="org_id", + organization_id="organization_id", ) """ _response = self._raw_client.fetch_organization_details( - org_id, request_options=request_options + organization_id, request_options=request_options ) return _response.data @@ -98,7 +101,7 @@ def list_organizations( def invite_user_to_workspace( self, - org_id: str, + organization_id: str, workspace_id: str, *, request: typing.Sequence[InviteRequest], @@ -108,7 +111,7 @@ def invite_user_to_workspace( Assigns a role to a user in an organization. Args: - org_id (str): The ID of the organization. + organization_id (str): The ID of the organization. payload (InviteRequest): The payload containing the organization id, user email, and role to assign. workspace_id (str): The ID of the workspace. @@ -121,7 +124,7 @@ def invite_user_to_workspace( Parameters ---------- - org_id : str + organization_id : str workspace_id : str @@ -143,7 +146,7 @@ def invite_user_to_workspace( api_key="YOUR_API_KEY", ) client.organization.invite_user_to_workspace( - org_id="org_id", + organization_id="organization_id", workspace_id="workspace_id", request=[ InviteRequest( @@ -153,13 +156,16 @@ def invite_user_to_workspace( ) """ _response = self._raw_client.invite_user_to_workspace( - org_id, workspace_id, request=request, request_options=request_options + organization_id, + workspace_id, + request=request, + request_options=request_options, ) return _response.data def resend_invitation( self, - org_id: str, + organization_id: str, workspace_id: str, *, email: str, @@ -178,7 +184,7 @@ def resend_invitation( Parameters ---------- - org_id : str + organization_id : str workspace_id : str @@ -200,19 +206,19 @@ def resend_invitation( api_key="YOUR_API_KEY", ) client.organization.resend_invitation( - org_id="org_id", + organization_id="organization_id", workspace_id="workspace_id", email="email", ) """ _response = self._raw_client.resend_invitation( - org_id, workspace_id, email=email, request_options=request_options + organization_id, workspace_id, email=email, request_options=request_options ) return _response.data def accept_invitation( self, - org_id: str, + organization_id: str, workspace_id: str, *, project_id: str, @@ -233,7 +239,7 @@ def accept_invitation( Parameters ---------- - org_id : str + organization_id : str workspace_id : str @@ -259,7 +265,7 @@ def accept_invitation( api_key="YOUR_API_KEY", ) client.organization.accept_invitation( - org_id="org_id", + organization_id="organization_id", workspace_id="workspace_id", project_id="project_id", token="token", @@ -267,7 +273,7 @@ def accept_invitation( ) """ _response = self._raw_client.accept_invitation( - org_id, + organization_id, workspace_id, project_id=project_id, token=token, @@ -293,14 +299,17 @@ def with_raw_response(self) -> AsyncRawOrganizationClient: return self._raw_client async def fetch_organization_details( - self, org_id: str, *, request_options: typing.Optional[RequestOptions] = None + self, + organization_id: str, + *, + request_options: typing.Optional[RequestOptions] = None, ) -> OrganizationDetails: """ Return the details of the organization. Parameters ---------- - org_id : str + organization_id : str request_options : typing.Optional[RequestOptions] Request-specific configuration. @@ -323,14 +332,14 @@ async def fetch_organization_details( async def main() -> None: await client.organization.fetch_organization_details( - org_id="org_id", + organization_id="organization_id", ) asyncio.run(main()) """ _response = await self._raw_client.fetch_organization_details( - org_id, request_options=request_options + organization_id, request_options=request_options ) return _response.data @@ -380,7 +389,7 @@ async def main() -> None: async def invite_user_to_workspace( self, - org_id: str, + organization_id: str, workspace_id: str, *, request: typing.Sequence[InviteRequest], @@ -390,7 +399,7 @@ async def invite_user_to_workspace( Assigns a role to a user in an organization. Args: - org_id (str): The ID of the organization. + organization_id (str): The ID of the organization. payload (InviteRequest): The payload containing the organization id, user email, and role to assign. workspace_id (str): The ID of the workspace. @@ -403,7 +412,7 @@ async def invite_user_to_workspace( Parameters ---------- - org_id : str + organization_id : str workspace_id : str @@ -430,7 +439,7 @@ async def invite_user_to_workspace( async def main() -> None: await client.organization.invite_user_to_workspace( - org_id="org_id", + organization_id="organization_id", workspace_id="workspace_id", request=[ InviteRequest( @@ -443,13 +452,16 @@ async def main() -> None: asyncio.run(main()) """ _response = await self._raw_client.invite_user_to_workspace( - org_id, workspace_id, request=request, request_options=request_options + organization_id, + workspace_id, + request=request, + request_options=request_options, ) return _response.data async def resend_invitation( self, - org_id: str, + organization_id: str, workspace_id: str, *, email: str, @@ -468,7 +480,7 @@ async def resend_invitation( Parameters ---------- - org_id : str + organization_id : str workspace_id : str @@ -495,7 +507,7 @@ async def resend_invitation( async def main() -> None: await client.organization.resend_invitation( - org_id="org_id", + organization_id="organization_id", workspace_id="workspace_id", email="email", ) @@ -504,13 +516,13 @@ async def main() -> None: asyncio.run(main()) """ _response = await self._raw_client.resend_invitation( - org_id, workspace_id, email=email, request_options=request_options + organization_id, workspace_id, email=email, request_options=request_options ) return _response.data async def accept_invitation( self, - org_id: str, + organization_id: str, workspace_id: str, *, project_id: str, @@ -531,7 +543,7 @@ async def accept_invitation( Parameters ---------- - org_id : str + organization_id : str workspace_id : str @@ -562,7 +574,7 @@ async def accept_invitation( async def main() -> None: await client.organization.accept_invitation( - org_id="org_id", + organization_id="organization_id", workspace_id="workspace_id", project_id="project_id", token="token", @@ -573,7 +585,7 @@ async def main() -> None: asyncio.run(main()) """ _response = await self._raw_client.accept_invitation( - org_id, + organization_id, workspace_id, project_id=project_id, token=token, diff --git a/sdk/agenta/client/backend/organization/raw_client.py b/sdk/agenta/client/backend/organization/raw_client.py index caadce246f..01b9d88a99 100644 --- a/sdk/agenta/client/backend/organization/raw_client.py +++ b/sdk/agenta/client/backend/organization/raw_client.py @@ -25,14 +25,17 @@ def __init__(self, *, client_wrapper: SyncClientWrapper): self._client_wrapper = client_wrapper def fetch_organization_details( - self, org_id: str, *, request_options: typing.Optional[RequestOptions] = None + self, + organization_id: str, + *, + request_options: typing.Optional[RequestOptions] = None, ) -> HttpResponse[OrganizationDetails]: """ Return the details of the organization. Parameters ---------- - org_id : str + organization_id : str request_options : typing.Optional[RequestOptions] Request-specific configuration. @@ -43,7 +46,7 @@ def fetch_organization_details( Successful Response """ _response = self._client_wrapper.httpx_client.request( - f"organizations/{jsonable_encoder(org_id)}", + f"organizations/{jsonable_encoder(organization_id)}", method="GET", request_options=request_options, ) @@ -133,7 +136,7 @@ def list_organizations( def invite_user_to_workspace( self, - org_id: str, + organization_id: str, workspace_id: str, *, request: typing.Sequence[InviteRequest], @@ -143,7 +146,7 @@ def invite_user_to_workspace( Assigns a role to a user in an organization. Args: - org_id (str): The ID of the organization. + organization_id (str): The ID of the organization. payload (InviteRequest): The payload containing the organization id, user email, and role to assign. workspace_id (str): The ID of the workspace. @@ -156,7 +159,7 @@ def invite_user_to_workspace( Parameters ---------- - org_id : str + organization_id : str workspace_id : str @@ -171,7 +174,7 @@ def invite_user_to_workspace( Successful Response """ _response = self._client_wrapper.httpx_client.request( - f"organizations/{jsonable_encoder(org_id)}/workspaces/{jsonable_encoder(workspace_id)}/invite", + f"organizations/{jsonable_encoder(organization_id)}/workspaces/{jsonable_encoder(workspace_id)}/invite", method="POST", json=convert_and_respect_annotation_metadata( object_=request, @@ -222,7 +225,7 @@ def invite_user_to_workspace( def resend_invitation( self, - org_id: str, + organization_id: str, workspace_id: str, *, email: str, @@ -241,7 +244,7 @@ def resend_invitation( Parameters ---------- - org_id : str + organization_id : str workspace_id : str @@ -256,7 +259,7 @@ def resend_invitation( Successful Response """ _response = self._client_wrapper.httpx_client.request( - f"organizations/{jsonable_encoder(org_id)}/workspaces/{jsonable_encoder(workspace_id)}/invite/resend", + f"organizations/{jsonable_encoder(organization_id)}/workspaces/{jsonable_encoder(workspace_id)}/invite/resend", method="POST", json={ "email": email, @@ -305,7 +308,7 @@ def resend_invitation( def accept_invitation( self, - org_id: str, + organization_id: str, workspace_id: str, *, project_id: str, @@ -326,7 +329,7 @@ def accept_invitation( Parameters ---------- - org_id : str + organization_id : str workspace_id : str @@ -345,7 +348,7 @@ def accept_invitation( Successful Response """ _response = self._client_wrapper.httpx_client.request( - f"organizations/{jsonable_encoder(org_id)}/workspaces/{jsonable_encoder(workspace_id)}/invite/accept", + f"organizations/{jsonable_encoder(organization_id)}/workspaces/{jsonable_encoder(workspace_id)}/invite/accept", method="POST", params={ "project_id": project_id, @@ -402,14 +405,17 @@ def __init__(self, *, client_wrapper: AsyncClientWrapper): self._client_wrapper = client_wrapper async def fetch_organization_details( - self, org_id: str, *, request_options: typing.Optional[RequestOptions] = None + self, + organization_id: str, + *, + request_options: typing.Optional[RequestOptions] = None, ) -> AsyncHttpResponse[OrganizationDetails]: """ Return the details of the organization. Parameters ---------- - org_id : str + organization_id : str request_options : typing.Optional[RequestOptions] Request-specific configuration. @@ -420,7 +426,7 @@ async def fetch_organization_details( Successful Response """ _response = await self._client_wrapper.httpx_client.request( - f"organizations/{jsonable_encoder(org_id)}", + f"organizations/{jsonable_encoder(organization_id)}", method="GET", request_options=request_options, ) @@ -510,7 +516,7 @@ async def list_organizations( async def invite_user_to_workspace( self, - org_id: str, + organization_id: str, workspace_id: str, *, request: typing.Sequence[InviteRequest], @@ -520,7 +526,7 @@ async def invite_user_to_workspace( Assigns a role to a user in an organization. Args: - org_id (str): The ID of the organization. + organization_id (str): The ID of the organization. payload (InviteRequest): The payload containing the organization id, user email, and role to assign. workspace_id (str): The ID of the workspace. @@ -533,7 +539,7 @@ async def invite_user_to_workspace( Parameters ---------- - org_id : str + organization_id : str workspace_id : str @@ -548,7 +554,7 @@ async def invite_user_to_workspace( Successful Response """ _response = await self._client_wrapper.httpx_client.request( - f"organizations/{jsonable_encoder(org_id)}/workspaces/{jsonable_encoder(workspace_id)}/invite", + f"organizations/{jsonable_encoder(organization_id)}/workspaces/{jsonable_encoder(workspace_id)}/invite", method="POST", json=convert_and_respect_annotation_metadata( object_=request, @@ -599,7 +605,7 @@ async def invite_user_to_workspace( async def resend_invitation( self, - org_id: str, + organization_id: str, workspace_id: str, *, email: str, @@ -618,7 +624,7 @@ async def resend_invitation( Parameters ---------- - org_id : str + organization_id : str workspace_id : str @@ -633,7 +639,7 @@ async def resend_invitation( Successful Response """ _response = await self._client_wrapper.httpx_client.request( - f"organizations/{jsonable_encoder(org_id)}/workspaces/{jsonable_encoder(workspace_id)}/invite/resend", + f"organizations/{jsonable_encoder(organization_id)}/workspaces/{jsonable_encoder(workspace_id)}/invite/resend", method="POST", json={ "email": email, @@ -682,7 +688,7 @@ async def resend_invitation( async def accept_invitation( self, - org_id: str, + organization_id: str, workspace_id: str, *, project_id: str, @@ -703,7 +709,7 @@ async def accept_invitation( Parameters ---------- - org_id : str + organization_id : str workspace_id : str @@ -722,7 +728,7 @@ async def accept_invitation( Successful Response """ _response = await self._client_wrapper.httpx_client.request( - f"organizations/{jsonable_encoder(org_id)}/workspaces/{jsonable_encoder(workspace_id)}/invite/accept", + f"organizations/{jsonable_encoder(organization_id)}/workspaces/{jsonable_encoder(workspace_id)}/invite/accept", method="POST", params={ "project_id": project_id, diff --git a/sdk/agenta/client/backend/raw_client.py b/sdk/agenta/client/backend/raw_client.py index bee6046b5e..a4b4a7857b 100644 --- a/sdk/agenta/client/backend/raw_client.py +++ b/sdk/agenta/client/backend/raw_client.py @@ -68,7 +68,7 @@ def get_own_org( def update_organization( self, - org_id: str, + organization_id: str, *, name: typing.Optional[str] = OMIT, description: typing.Optional[str] = OMIT, @@ -78,7 +78,7 @@ def update_organization( """ Parameters ---------- - org_id : str + organization_id : str name : typing.Optional[str] @@ -95,7 +95,7 @@ def update_organization( Successful Response """ _response = self._client_wrapper.httpx_client.request( - f"organizations/{jsonable_encoder(org_id)}", + f"organizations/{jsonable_encoder(organization_id)}", method="PUT", json={ "name": name, @@ -146,7 +146,7 @@ def update_organization( def create_workspace( self, - org_id: str, + organization_id: str, *, name: str, description: typing.Optional[str] = OMIT, @@ -156,7 +156,7 @@ def create_workspace( """ Parameters ---------- - org_id : str + organization_id : str name : str @@ -173,7 +173,7 @@ def create_workspace( Successful Response """ _response = self._client_wrapper.httpx_client.request( - f"organizations/{jsonable_encoder(org_id)}/workspaces", + f"organizations/{jsonable_encoder(organization_id)}/workspaces", method="POST", json={ "name": name, @@ -222,7 +222,7 @@ def create_workspace( def update_workspace( self, - org_id: str, + organization_id: str, workspace_id: str, *, name: typing.Optional[str] = OMIT, @@ -233,7 +233,7 @@ def update_workspace( """ Parameters ---------- - org_id : str + organization_id : str workspace_id : str @@ -252,7 +252,7 @@ def update_workspace( Successful Response """ _response = self._client_wrapper.httpx_client.request( - f"organizations/{jsonable_encoder(org_id)}/workspaces/{jsonable_encoder(workspace_id)}", + f"organizations/{jsonable_encoder(organization_id)}/workspaces/{jsonable_encoder(workspace_id)}", method="PUT", json={ "name": name, @@ -448,7 +448,7 @@ def unassign_role_from_user( workspace_id: str, *, email: str, - org_id: str, + organization_id: str, role: str, request_options: typing.Optional[RequestOptions] = None, ) -> HttpResponse[typing.Optional[typing.Any]]: @@ -458,7 +458,7 @@ def unassign_role_from_user( Args: workspace_id (str): The ID of the workspace. email (str): The email of the user to remove the role from. - org_id (str): The ID of the organization. + organization_id (str): The ID of the organization. role (str): The role to remove from the user. request (Request): The FastAPI request object. @@ -475,7 +475,7 @@ def unassign_role_from_user( email : str - org_id : str + organization_id : str role : str @@ -492,7 +492,7 @@ def unassign_role_from_user( method="DELETE", params={ "email": email, - "org_id": org_id, + "organization_id": organization_id, "role": role, }, request_options=request_options, @@ -774,7 +774,7 @@ async def get_own_org( async def update_organization( self, - org_id: str, + organization_id: str, *, name: typing.Optional[str] = OMIT, description: typing.Optional[str] = OMIT, @@ -784,7 +784,7 @@ async def update_organization( """ Parameters ---------- - org_id : str + organization_id : str name : typing.Optional[str] @@ -801,7 +801,7 @@ async def update_organization( Successful Response """ _response = await self._client_wrapper.httpx_client.request( - f"organizations/{jsonable_encoder(org_id)}", + f"organizations/{jsonable_encoder(organization_id)}", method="PUT", json={ "name": name, @@ -852,7 +852,7 @@ async def update_organization( async def create_workspace( self, - org_id: str, + organization_id: str, *, name: str, description: typing.Optional[str] = OMIT, @@ -862,7 +862,7 @@ async def create_workspace( """ Parameters ---------- - org_id : str + organization_id : str name : str @@ -879,7 +879,7 @@ async def create_workspace( Successful Response """ _response = await self._client_wrapper.httpx_client.request( - f"organizations/{jsonable_encoder(org_id)}/workspaces", + f"organizations/{jsonable_encoder(organization_id)}/workspaces", method="POST", json={ "name": name, @@ -928,7 +928,7 @@ async def create_workspace( async def update_workspace( self, - org_id: str, + organization_id: str, workspace_id: str, *, name: typing.Optional[str] = OMIT, @@ -939,7 +939,7 @@ async def update_workspace( """ Parameters ---------- - org_id : str + organization_id : str workspace_id : str @@ -958,7 +958,7 @@ async def update_workspace( Successful Response """ _response = await self._client_wrapper.httpx_client.request( - f"organizations/{jsonable_encoder(org_id)}/workspaces/{jsonable_encoder(workspace_id)}", + f"organizations/{jsonable_encoder(organization_id)}/workspaces/{jsonable_encoder(workspace_id)}", method="PUT", json={ "name": name, @@ -1154,7 +1154,7 @@ async def unassign_role_from_user( workspace_id: str, *, email: str, - org_id: str, + organization_id: str, role: str, request_options: typing.Optional[RequestOptions] = None, ) -> AsyncHttpResponse[typing.Optional[typing.Any]]: @@ -1164,7 +1164,7 @@ async def unassign_role_from_user( Args: workspace_id (str): The ID of the workspace. email (str): The email of the user to remove the role from. - org_id (str): The ID of the organization. + organization_id (str): The ID of the organization. role (str): The role to remove from the user. request (Request): The FastAPI request object. @@ -1181,7 +1181,7 @@ async def unassign_role_from_user( email : str - org_id : str + organization_id : str role : str @@ -1198,7 +1198,7 @@ async def unassign_role_from_user( method="DELETE", params={ "email": email, - "org_id": org_id, + "organization_id": organization_id, "role": role, }, request_options=request_options, diff --git a/sdk/agenta/client/client.py b/sdk/agenta/client/client.py index 535818f5d2..305f7fc9c6 100644 --- a/sdk/agenta/client/client.py +++ b/sdk/agenta/client/client.py @@ -99,13 +99,17 @@ def __init__( self._client_wrapper = SyncClientWrapper( base_url=base_url, api_key=api_key, - httpx_client=httpx_client - if httpx_client is not None - else httpx.Client( - timeout=_defaulted_timeout, follow_redirects=follow_redirects - ) - if follow_redirects is not None - else httpx.Client(timeout=_defaulted_timeout), + httpx_client=( + httpx_client + if httpx_client is not None + else ( + httpx.Client( + timeout=_defaulted_timeout, follow_redirects=follow_redirects + ) + if follow_redirects is not None + else httpx.Client(timeout=_defaulted_timeout) + ) + ), timeout=_defaulted_timeout, ) self.admin = AdminClient(client_wrapper=self._client_wrapper) @@ -542,7 +546,10 @@ def get_own_org( raise ApiError(status_code=_response.status_code, body=_response_json) def fetch_organization_details( - self, org_id: str, *, request_options: typing.Optional[RequestOptions] = None + self, + organization_id: str, + *, + request_options: typing.Optional[RequestOptions] = None, ) -> typing.Optional[typing.Any]: """ Get an organization's details. @@ -556,7 +563,7 @@ def fetch_organization_details( Parameters ---------- - org_id : str + organization_id : str request_options : typing.Optional[RequestOptions] Request-specific configuration. @@ -575,11 +582,11 @@ def fetch_organization_details( base_url="https://yourhost.com/path/to/api", ) client.fetch_organization_details( - org_id="org_id", + organization_id="organization_id", ) """ _response = self._client_wrapper.httpx_client.request( - f"organizations/{jsonable_encoder(org_id)}", + f"organizations/{jsonable_encoder(organization_id)}", method="GET", request_options=request_options, ) @@ -609,7 +616,7 @@ def fetch_organization_details( def update_organization( self, - org_id: str, + organization_id: str, *, name: typing.Optional[str] = OMIT, description: typing.Optional[str] = OMIT, @@ -619,7 +626,7 @@ def update_organization( """ Parameters ---------- - org_id : str + organization_id : str name : typing.Optional[str] @@ -644,11 +651,11 @@ def update_organization( base_url="https://yourhost.com/path/to/api", ) client.update_organization( - org_id="org_id", + organization_id="organization_id", ) """ _response = self._client_wrapper.httpx_client.request( - f"organizations/{jsonable_encoder(org_id)}", + f"organizations/{jsonable_encoder(organization_id)}", method="PUT", json={ "name": name, @@ -687,7 +694,7 @@ def update_organization( def invite_user_to_workspace( self, - org_id: str, + organization_id: str, workspace_id: str, *, request: typing.Sequence[InviteRequest], @@ -696,7 +703,7 @@ def invite_user_to_workspace( """ Parameters ---------- - org_id : str + organization_id : str workspace_id : str @@ -719,7 +726,7 @@ def invite_user_to_workspace( base_url="https://yourhost.com/path/to/api", ) client.invite_user_to_workspace( - org_id="org_id", + organization_id="organization_id", workspace_id="workspace_id", request=[ InviteRequest( @@ -730,7 +737,7 @@ def invite_user_to_workspace( ) """ _response = self._client_wrapper.httpx_client.request( - f"organizations/{jsonable_encoder(org_id)}/workspaces/{jsonable_encoder(workspace_id)}/invite", + f"organizations/{jsonable_encoder(organization_id)}/workspaces/{jsonable_encoder(workspace_id)}/invite", method="POST", json=convert_and_respect_annotation_metadata( object_=request, @@ -766,7 +773,7 @@ def invite_user_to_workspace( def resend_invitation( self, - org_id: str, + organization_id: str, workspace_id: str, *, email: str, @@ -785,7 +792,7 @@ def resend_invitation( Parameters ---------- - org_id : str + organization_id : str workspace_id : str @@ -808,13 +815,13 @@ def resend_invitation( base_url="https://yourhost.com/path/to/api", ) client.resend_invitation( - org_id="org_id", + organization_id="organization_id", workspace_id="workspace_id", email="email", ) """ _response = self._client_wrapper.httpx_client.request( - f"organizations/{jsonable_encoder(org_id)}/workspaces/{jsonable_encoder(workspace_id)}/invite/resend", + f"organizations/{jsonable_encoder(organization_id)}/workspaces/{jsonable_encoder(workspace_id)}/invite/resend", method="POST", json={ "email": email, @@ -851,7 +858,7 @@ def resend_invitation( def accept_invitation( self, - org_id: str, + organization_id: str, workspace_id: str, *, project_id: str, @@ -871,7 +878,7 @@ def accept_invitation( Parameters ---------- - org_id : str + organization_id : str workspace_id : str @@ -896,14 +903,14 @@ def accept_invitation( base_url="https://yourhost.com/path/to/api", ) client.accept_invitation( - org_id="org_id", + organization_id="organization_id", workspace_id="workspace_id", project_id="project_id", token="token", ) """ _response = self._client_wrapper.httpx_client.request( - f"organizations/{jsonable_encoder(org_id)}/workspaces/{jsonable_encoder(workspace_id)}/invite/accept", + f"organizations/{jsonable_encoder(organization_id)}/workspaces/{jsonable_encoder(workspace_id)}/invite/accept", method="POST", params={ "project_id": project_id, @@ -943,7 +950,7 @@ def accept_invitation( def create_workspace( self, - org_id: str, + organization_id: str, *, name: str, description: typing.Optional[str] = OMIT, @@ -953,7 +960,7 @@ def create_workspace( """ Parameters ---------- - org_id : str + organization_id : str name : str @@ -978,12 +985,12 @@ def create_workspace( base_url="https://yourhost.com/path/to/api", ) client.create_workspace( - org_id="org_id", + organization_id="organization_id", name="name", ) """ _response = self._client_wrapper.httpx_client.request( - f"organizations/{jsonable_encoder(org_id)}/workspaces", + f"organizations/{jsonable_encoder(organization_id)}/workspaces", method="POST", json={ "name": name, @@ -1022,7 +1029,7 @@ def create_workspace( def update_workspace( self, - org_id: str, + organization_id: str, workspace_id: str, *, name: typing.Optional[str] = OMIT, @@ -1033,7 +1040,7 @@ def update_workspace( """ Parameters ---------- - org_id : str + organization_id : str workspace_id : str @@ -1060,12 +1067,12 @@ def update_workspace( base_url="https://yourhost.com/path/to/api", ) client.update_workspace( - org_id="org_id", + organization_id="organization_id", workspace_id="workspace_id", ) """ _response = self._client_wrapper.httpx_client.request( - f"organizations/{jsonable_encoder(org_id)}/workspaces/{jsonable_encoder(workspace_id)}", + f"organizations/{jsonable_encoder(organization_id)}/workspaces/{jsonable_encoder(workspace_id)}", method="PUT", json={ "name": name, @@ -1307,7 +1314,7 @@ def unassign_role_from_user( workspace_id: str, *, email: str, - org_id: str, + organization_id: str, role: str, request_options: typing.Optional[RequestOptions] = None, ) -> typing.Optional[typing.Any]: @@ -1317,7 +1324,7 @@ def unassign_role_from_user( Args: workspace_id (str): The ID of the workspace. email (str): The email of the user to remove the role from. - org_id (str): The ID of the organization. + organization_id (str): The ID of the organization. role (str): The role to remove from the user. request (Request): The FastAPI request object. @@ -1334,7 +1341,7 @@ def unassign_role_from_user( email : str - org_id : str + organization_id : str role : str @@ -1357,7 +1364,7 @@ def unassign_role_from_user( client.unassign_role_from_user( workspace_id="workspace_id", email="email", - org_id="org_id", + organization_id="organization_id", role="role", ) """ @@ -1366,7 +1373,7 @@ def unassign_role_from_user( method="DELETE", params={ "email": email, - "org_id": org_id, + "organization_id": organization_id, "role": role, }, request_options=request_options, @@ -1399,7 +1406,7 @@ def remove_user_from_workspace( self, workspace_id: str, *, - org_id: str, + organization_id: str, email: str, request_options: typing.Optional[RequestOptions] = None, ) -> WorkspaceResponse: @@ -1422,7 +1429,7 @@ def remove_user_from_workspace( ---------- workspace_id : str - org_id : str + organization_id : str email : str @@ -1444,7 +1451,7 @@ def remove_user_from_workspace( ) client.remove_user_from_workspace( workspace_id="workspace_id", - org_id="org_id", + organization_id="organization_id", email="email", ) """ @@ -1452,7 +1459,7 @@ def remove_user_from_workspace( f"workspaces/{jsonable_encoder(workspace_id)}/users", method="DELETE", params={ - "org_id": org_id, + "organization_id": organization_id, "email": email, }, request_options=request_options, @@ -1630,13 +1637,17 @@ def __init__( self._client_wrapper = AsyncClientWrapper( base_url=base_url, api_key=api_key, - httpx_client=httpx_client - if httpx_client is not None - else httpx.AsyncClient( - timeout=_defaulted_timeout, follow_redirects=follow_redirects - ) - if follow_redirects is not None - else httpx.AsyncClient(timeout=_defaulted_timeout), + httpx_client=( + httpx_client + if httpx_client is not None + else ( + httpx.AsyncClient( + timeout=_defaulted_timeout, follow_redirects=follow_redirects + ) + if follow_redirects is not None + else httpx.AsyncClient(timeout=_defaulted_timeout) + ) + ), timeout=_defaulted_timeout, ) self.admin = AsyncAdminClient(client_wrapper=self._client_wrapper) @@ -2133,7 +2144,10 @@ async def main() -> None: raise ApiError(status_code=_response.status_code, body=_response_json) async def fetch_organization_details( - self, org_id: str, *, request_options: typing.Optional[RequestOptions] = None + self, + organization_id: str, + *, + request_options: typing.Optional[RequestOptions] = None, ) -> typing.Optional[typing.Any]: """ Get an organization's details. @@ -2147,7 +2161,7 @@ async def fetch_organization_details( Parameters ---------- - org_id : str + organization_id : str request_options : typing.Optional[RequestOptions] Request-specific configuration. @@ -2171,14 +2185,14 @@ async def fetch_organization_details( async def main() -> None: await client.fetch_organization_details( - org_id="org_id", + organization_id="organization_id", ) asyncio.run(main()) """ _response = await self._client_wrapper.httpx_client.request( - f"organizations/{jsonable_encoder(org_id)}", + f"organizations/{jsonable_encoder(organization_id)}", method="GET", request_options=request_options, ) @@ -2208,7 +2222,7 @@ async def main() -> None: async def update_organization( self, - org_id: str, + organization_id: str, *, name: typing.Optional[str] = OMIT, description: typing.Optional[str] = OMIT, @@ -2218,7 +2232,7 @@ async def update_organization( """ Parameters ---------- - org_id : str + organization_id : str name : typing.Optional[str] @@ -2248,14 +2262,14 @@ async def update_organization( async def main() -> None: await client.update_organization( - org_id="org_id", + organization_id="organization_id", ) asyncio.run(main()) """ _response = await self._client_wrapper.httpx_client.request( - f"organizations/{jsonable_encoder(org_id)}", + f"organizations/{jsonable_encoder(organization_id)}", method="PUT", json={ "name": name, @@ -2294,7 +2308,7 @@ async def main() -> None: async def invite_user_to_workspace( self, - org_id: str, + organization_id: str, workspace_id: str, *, request: typing.Sequence[InviteRequest], @@ -2303,7 +2317,7 @@ async def invite_user_to_workspace( """ Parameters ---------- - org_id : str + organization_id : str workspace_id : str @@ -2331,7 +2345,7 @@ async def invite_user_to_workspace( async def main() -> None: await client.invite_user_to_workspace( - org_id="org_id", + organization_id="organization_id", workspace_id="workspace_id", request=[ InviteRequest( @@ -2345,7 +2359,7 @@ async def main() -> None: asyncio.run(main()) """ _response = await self._client_wrapper.httpx_client.request( - f"organizations/{jsonable_encoder(org_id)}/workspaces/{jsonable_encoder(workspace_id)}/invite", + f"organizations/{jsonable_encoder(organization_id)}/workspaces/{jsonable_encoder(workspace_id)}/invite", method="POST", json=convert_and_respect_annotation_metadata( object_=request, @@ -2381,7 +2395,7 @@ async def main() -> None: async def resend_invitation( self, - org_id: str, + organization_id: str, workspace_id: str, *, email: str, @@ -2400,7 +2414,7 @@ async def resend_invitation( Parameters ---------- - org_id : str + organization_id : str workspace_id : str @@ -2428,7 +2442,7 @@ async def resend_invitation( async def main() -> None: await client.resend_invitation( - org_id="org_id", + organization_id="organization_id", workspace_id="workspace_id", email="email", ) @@ -2437,7 +2451,7 @@ async def main() -> None: asyncio.run(main()) """ _response = await self._client_wrapper.httpx_client.request( - f"organizations/{jsonable_encoder(org_id)}/workspaces/{jsonable_encoder(workspace_id)}/invite/resend", + f"organizations/{jsonable_encoder(organization_id)}/workspaces/{jsonable_encoder(workspace_id)}/invite/resend", method="POST", json={ "email": email, @@ -2474,7 +2488,7 @@ async def main() -> None: async def accept_invitation( self, - org_id: str, + organization_id: str, workspace_id: str, *, project_id: str, @@ -2494,7 +2508,7 @@ async def accept_invitation( Parameters ---------- - org_id : str + organization_id : str workspace_id : str @@ -2524,7 +2538,7 @@ async def accept_invitation( async def main() -> None: await client.accept_invitation( - org_id="org_id", + organization_id="organization_id", workspace_id="workspace_id", project_id="project_id", token="token", @@ -2534,7 +2548,7 @@ async def main() -> None: asyncio.run(main()) """ _response = await self._client_wrapper.httpx_client.request( - f"organizations/{jsonable_encoder(org_id)}/workspaces/{jsonable_encoder(workspace_id)}/invite/accept", + f"organizations/{jsonable_encoder(organization_id)}/workspaces/{jsonable_encoder(workspace_id)}/invite/accept", method="POST", params={ "project_id": project_id, @@ -2574,7 +2588,7 @@ async def main() -> None: async def create_workspace( self, - org_id: str, + organization_id: str, *, name: str, description: typing.Optional[str] = OMIT, @@ -2584,7 +2598,7 @@ async def create_workspace( """ Parameters ---------- - org_id : str + organization_id : str name : str @@ -2614,7 +2628,7 @@ async def create_workspace( async def main() -> None: await client.create_workspace( - org_id="org_id", + organization_id="organization_id", name="name", ) @@ -2622,7 +2636,7 @@ async def main() -> None: asyncio.run(main()) """ _response = await self._client_wrapper.httpx_client.request( - f"organizations/{jsonable_encoder(org_id)}/workspaces", + f"organizations/{jsonable_encoder(organization_id)}/workspaces", method="POST", json={ "name": name, @@ -2661,7 +2675,7 @@ async def main() -> None: async def update_workspace( self, - org_id: str, + organization_id: str, workspace_id: str, *, name: typing.Optional[str] = OMIT, @@ -2672,7 +2686,7 @@ async def update_workspace( """ Parameters ---------- - org_id : str + organization_id : str workspace_id : str @@ -2704,7 +2718,7 @@ async def update_workspace( async def main() -> None: await client.update_workspace( - org_id="org_id", + organization_id="organization_id", workspace_id="workspace_id", ) @@ -2712,7 +2726,7 @@ async def main() -> None: asyncio.run(main()) """ _response = await self._client_wrapper.httpx_client.request( - f"organizations/{jsonable_encoder(org_id)}/workspaces/{jsonable_encoder(workspace_id)}", + f"organizations/{jsonable_encoder(organization_id)}/workspaces/{jsonable_encoder(workspace_id)}", method="PUT", json={ "name": name, @@ -2978,7 +2992,7 @@ async def unassign_role_from_user( workspace_id: str, *, email: str, - org_id: str, + organization_id: str, role: str, request_options: typing.Optional[RequestOptions] = None, ) -> typing.Optional[typing.Any]: @@ -2988,7 +3002,7 @@ async def unassign_role_from_user( Args: workspace_id (str): The ID of the workspace. email (str): The email of the user to remove the role from. - org_id (str): The ID of the organization. + organization_id (str): The ID of the organization. role (str): The role to remove from the user. request (Request): The FastAPI request object. @@ -3005,7 +3019,7 @@ async def unassign_role_from_user( email : str - org_id : str + organization_id : str role : str @@ -3033,7 +3047,7 @@ async def main() -> None: await client.unassign_role_from_user( workspace_id="workspace_id", email="email", - org_id="org_id", + organization_id="organization_id", role="role", ) @@ -3045,7 +3059,7 @@ async def main() -> None: method="DELETE", params={ "email": email, - "org_id": org_id, + "organization_id": organization_id, "role": role, }, request_options=request_options, @@ -3078,7 +3092,7 @@ async def remove_user_from_workspace( self, workspace_id: str, *, - org_id: str, + organization_id: str, email: str, request_options: typing.Optional[RequestOptions] = None, ) -> WorkspaceResponse: @@ -3101,7 +3115,7 @@ async def remove_user_from_workspace( ---------- workspace_id : str - org_id : str + organization_id : str email : str @@ -3128,7 +3142,7 @@ async def remove_user_from_workspace( async def main() -> None: await client.remove_user_from_workspace( workspace_id="workspace_id", - org_id="org_id", + organization_id="organization_id", email="email", ) @@ -3139,7 +3153,7 @@ async def main() -> None: f"workspaces/{jsonable_encoder(workspace_id)}/users", method="DELETE", params={ - "org_id": org_id, + "organization_id": organization_id, "email": email, }, request_options=request_options, diff --git a/sdk/pyproject.toml b/sdk/pyproject.toml index 9efac11f7f..bd48a0dfa3 100644 --- a/sdk/pyproject.toml +++ b/sdk/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "agenta" -version = "0.59.0" +version = "0.59.1" description = "The SDK for agenta is an open-source LLMOps platform." readme = "README.md" authors = [ diff --git a/web/ee/package.json b/web/ee/package.json index fc2d4e4b96..100f95b689 100644 --- a/web/ee/package.json +++ b/web/ee/package.json @@ -1,6 +1,6 @@ { "name": "@agenta/ee", - "version": "0.59.0", + "version": "0.59.1", "private": true, "engines": { "node": ">=18" diff --git a/web/ee/src/state/billing/atoms.ts b/web/ee/src/state/billing/atoms.ts index a6e2fc02b8..974e9a8dec 100644 --- a/web/ee/src/state/billing/atoms.ts +++ b/web/ee/src/state/billing/atoms.ts @@ -50,10 +50,10 @@ export const subscriptionQueryAtom = atomWithQuery((get) => { const profileQuery = get(profileQueryAtom) const user = profileQuery.data as User | undefined const projectId = get(projectIdAtom) - const orgId = get(selectedOrgIdAtom) + const organizationId = get(selectedOrgIdAtom) return { - queryKey: ["billing", "subscription", projectId, user?.id, orgId], + queryKey: ["billing", "subscription", projectId, user?.id, organizationId], queryFn: async () => { const response = await axios.get( `${getAgentaApiUrl()}/billing/subscription?project_id=${projectId}`, @@ -64,7 +64,7 @@ export const subscriptionQueryAtom = atomWithQuery((get) => { refetchOnWindowFocus: false, refetchOnReconnect: false, refetchOnMount: true, - enabled: !!orgId && !!user && !!projectId, + enabled: !!organizationId && !!user && !!projectId, retry: (failureCount, error) => { // Don't retry on client errors if ((error as any)?.response?.status >= 400 && (error as any)?.response?.status < 500) { diff --git a/web/ee/src/state/url/focusDrawer.ts b/web/ee/src/state/url/focusDrawer.ts index 0a87387caf..d847262900 100644 --- a/web/ee/src/state/url/focusDrawer.ts +++ b/web/ee/src/state/url/focusDrawer.ts @@ -129,3 +129,13 @@ export const clearFocusDrawerQueryParams = () => { console.error("Failed to clear focus drawer query params:", err) } } + +export type FocusDrawerPublicApi = { + syncFocusDrawerStateFromUrl: (nextUrl?: string) => void; + clearFocusDrawerQueryParams: () => void; +}; + +export default { + syncFocusDrawerStateFromUrl, + clearFocusDrawerQueryParams, +} satisfies FocusDrawerPublicApi; diff --git a/web/oss/package.json b/web/oss/package.json index 253f1db73c..f5af13ff7e 100644 --- a/web/oss/package.json +++ b/web/oss/package.json @@ -1,6 +1,6 @@ { "name": "@agenta/oss", - "version": "0.59.0", + "version": "0.59.1", "private": true, "engines": { "node": ">=18" diff --git a/web/oss/src/components/Playground/state/atoms/appCreationMutations.ts b/web/oss/src/components/Playground/state/atoms/appCreationMutations.ts index 620a10c5c0..c118d07be5 100644 --- a/web/oss/src/components/Playground/state/atoms/appCreationMutations.ts +++ b/web/oss/src/components/Playground/state/atoms/appCreationMutations.ts @@ -68,11 +68,7 @@ const createApp = async ({templateKey, appName}: {appName: string; templateKey: const {selectedOrg} = getOrgValues() const {project, projectId} = getProjectValues() // Prefer selectedOrg, fallback to current project's org/workspace when available - const organization_id = - (selectedOrg as any)?.id || - (project as any)?.organization_id || - (project as any)?.org_id || - null + const organization_id = (selectedOrg as any)?.id || (project as any)?.organization_id || null const workspace_id = (selectedOrg as any)?.default_workspace?.id || (project as any)?.workspace_id || null const url = new URL(`${getAgentaApiUrl()}/apps?project_id=${projectId}`) diff --git a/web/oss/src/components/Sidebar/hooks/useSidebarConfig/index.tsx b/web/oss/src/components/Sidebar/hooks/useSidebarConfig/index.tsx index 5e6138bc75..b70f6d69ab 100644 --- a/web/oss/src/components/Sidebar/hooks/useSidebarConfig/index.tsx +++ b/web/oss/src/components/Sidebar/hooks/useSidebarConfig/index.tsx @@ -57,6 +57,7 @@ export const useSidebarConfig = () => { key: "project-evaluators-link", title: "Evaluators", link: `${projectURL}/evaluators`, + isHidden: !isDemo(), icon: , }, { diff --git a/web/oss/src/components/pages/settings/WorkspaceManage/Modals/InviteUsersModal.tsx b/web/oss/src/components/pages/settings/WorkspaceManage/Modals/InviteUsersModal.tsx index a5fbeef0e1..77b721e53c 100644 --- a/web/oss/src/components/pages/settings/WorkspaceManage/Modals/InviteUsersModal.tsx +++ b/web/oss/src/components/pages/settings/WorkspaceManage/Modals/InviteUsersModal.tsx @@ -23,7 +23,7 @@ const InviteForm: FC = ({onSuccess, workspaceId, form, setLoadi const {selectedOrg, refetch} = useOrgData() const [roles] = useAtom(workspaceRolesAtom) const {token} = theme.useToken() - const orgId = selectedOrg?.id + const organizationId = selectedOrg?.id const filteredRoles = useMemo(() => { if (!isDemo()) { @@ -34,7 +34,7 @@ const InviteForm: FC = ({onSuccess, workspaceId, form, setLoadi const onSubmit = useCallback( ({emails, role}: {emails: string[]; role: string | null}) => { - if (!orgId) return + if (!organizationId) return setLoading(true) @@ -43,7 +43,7 @@ const InviteForm: FC = ({onSuccess, workspaceId, form, setLoadi email, ...(role ? {roles: [role]} : {}), })), - orgId, + organizationId, workspaceId, }) .then((responses) => { @@ -63,7 +63,7 @@ const InviteForm: FC = ({onSuccess, workspaceId, form, setLoadi .catch(console.error) .finally(() => setLoading(false)) }, - [orgId], + [organizationId], ) return ( diff --git a/web/oss/src/components/pages/settings/WorkspaceManage/WorkspaceManage.tsx b/web/oss/src/components/pages/settings/WorkspaceManage/WorkspaceManage.tsx index ea56a05159..a041a7d624 100644 --- a/web/oss/src/components/pages/settings/WorkspaceManage/WorkspaceManage.tsx +++ b/web/oss/src/components/pages/settings/WorkspaceManage/WorkspaceManage.tsx @@ -32,7 +32,7 @@ const WorkspaceManage: FC = () => { }) const [queryInviteModalOpen, setQueryInviteModalOpen] = useQueryParam("inviteModal") - const orgId = selectedOrg?.id + const organizationId = selectedOrg?.id const workspaceId = selectedOrg?.default_workspace?.id const workspace = selectedOrg?.default_workspace @@ -81,7 +81,7 @@ const WorkspaceManage: FC = () => { ), @@ -128,7 +128,7 @@ const WorkspaceManage: FC = () => { member.user.email === signedInUser?.email || member.user.id === selectedOrg?.owner } - orgId={orgId!} + organizationId={organizationId!} workspaceId={workspaceId!} onResendInvite={(data: any) => { if (!isDemo() && data.uri) { @@ -146,10 +146,10 @@ const WorkspaceManage: FC = () => { ) const handleSaveWorkspaceName = async () => { - if (!workspaceId || !orgId) return + if (!workspaceId || !organizationId) return await updateWorkspaceName({ - orgId, + organizationId, workspaceId, name: workspaceNameInput, onSuccess: () => { diff --git a/web/oss/src/components/pages/settings/WorkspaceManage/cellRenderers.tsx b/web/oss/src/components/pages/settings/WorkspaceManage/cellRenderers.tsx index 477764547b..cd897096f2 100644 --- a/web/oss/src/components/pages/settings/WorkspaceManage/cellRenderers.tsx +++ b/web/oss/src/components/pages/settings/WorkspaceManage/cellRenderers.tsx @@ -21,10 +21,10 @@ import {useWorkspaceRoles} from "@/oss/state/workspace" export const Actions: React.FC<{ member: WorkspaceMember hidden?: boolean - orgId: string + organizationId: string workspaceId: string onResendInvite: any -}> = ({member, hidden, orgId, workspaceId, onResendInvite}) => { +}> = ({member, hidden, organizationId, workspaceId, onResendInvite}) => { const {user} = member const isMember = user.status === "member" @@ -34,9 +34,9 @@ export const Actions: React.FC<{ if (hidden) return null const handleResendInvite = () => { - if (!orgId || !user.email || !workspaceId) return + if (!organizationId || !user.email || !workspaceId) return setResendLoading(true) - resendInviteToWorkspace({orgId, workspaceId, email: user.email}) + resendInviteToWorkspace({organizationId, workspaceId, email: user.email}) .then((res) => { if (!isDemo() && typeof res.url === "string") { onResendInvite({email: user.email, uri: res.url}) @@ -50,12 +50,12 @@ export const Actions: React.FC<{ } const handleRemove = () => { - if (!orgId || !user.email || !workspaceId) return + if (!organizationId || !user.email || !workspaceId) return AlertPopup({ title: "Remove member", message: `Are you sure you want to remove ${user.username} from this workspace?`, onOk: () => - removeFromWorkspace({orgId, workspaceId, email: user.email}, true).then(() => + removeFromWorkspace({organizationId, workspaceId, email: user.email}, true).then(() => refetch(), ), okText: "Remove", @@ -109,9 +109,9 @@ export const Actions: React.FC<{ export const Roles: React.FC<{ member: WorkspaceMember signedInUser: User - orgId: string + organizationId: string workspaceId: string -}> = ({member, signedInUser, orgId, workspaceId}) => { +}> = ({member, signedInUser, organizationId, workspaceId}) => { const [loading, setLoading] = useState(false) const {roles} = useWorkspaceRoles() const {selectedOrg, refetch} = useOrgData() @@ -127,13 +127,13 @@ export const Roles: React.FC<{ const handleChangeRole = async (roleName: string) => { setLoading(true) try { - await assignWorkspaceRole({orgId, workspaceId, email: user.email, role: roleName}) + await assignWorkspaceRole({organizationId, workspaceId, email: user.email, role: roleName}) await Promise.all( member.roles .filter((item) => item.role_name !== roleName) .map((item) => unAssignWorkspaceRole({ - orgId, + organizationId, workspaceId, email: user.email, role: item.role_name, diff --git a/web/oss/src/pages/auth/[[...path]].tsx b/web/oss/src/pages/auth/[[...path]].tsx index a3343ae556..f7da2782d8 100644 --- a/web/oss/src/pages/auth/[[...path]].tsx +++ b/web/oss/src/pages/auth/[[...path]].tsx @@ -36,7 +36,7 @@ const Auth = () => { } const token = firstString(router.query.token) - const orgId = firstString(router.query.org_id) + const organizationId = firstString(router.query.organization_id) const projectId = firstString(router.query.project_id) const workspaceId = firstString(router.query.workspace_id) const emailFromQuery = firstString(router.query.email) @@ -49,13 +49,13 @@ const Auth = () => { if (isInvitedUser && Object.keys(invite).length === 0) { setInvite({ token, - org_id: orgId, + organization_id: organizationId, project_id: projectId, workspace_id: workspaceId, email: emailFromQuery, }) } - }, [isInvitedUser, invite, setInvite, token, orgId, projectId, workspaceId, emailFromQuery]) + }, [isInvitedUser, invite, setInvite, token, organizationId, projectId, workspaceId, emailFromQuery]) const authErrorMsg = (error: any) => { if (error.isSuperTokensGeneralError === true) { diff --git a/web/oss/src/pages/workspaces/accept.tsx b/web/oss/src/pages/workspaces/accept.tsx index c78c6ad2c3..1a45a69423 100644 --- a/web/oss/src/pages/workspaces/accept.tsx +++ b/web/oss/src/pages/workspaces/accept.tsx @@ -35,21 +35,21 @@ const Accept: FC = () => { ? { token: inviteFromState.token, email: inviteFromState.email, - org_id: inviteFromState.org_id, + organization_id: inviteFromState.organization_id, workspace_id: inviteFromState.workspace_id, project_id: inviteFromState.project_id, survey: inviteFromState.survey, } : invite const token = firstString(source?.token) as string | undefined - const orgId = firstString(source?.org_id) as string | undefined + const organizationId = firstString(source?.organization_id) as string | undefined const projectId = firstString(source?.project_id) as string | undefined const workspaceId = firstString(source?.workspace_id) as string | undefined const email = firstString(source?.email) as string | undefined const isSurvey = Boolean(router.query.survey) const onAcceptInvite = async () => { - if (!orgId || !token) return + if (!organizationId || !token) return if (processedTokens.has(token)) return if (!accept.current) { @@ -74,7 +74,7 @@ const Accept: FC = () => { await acceptWorkspaceInvite( { token, - orgId, + organizationId, workspaceId, projectId, email, @@ -87,8 +87,8 @@ const Accept: FC = () => { await refetchOrganization() await refetchProject() - const targetWorkspace = workspaceId || orgId - cacheWorkspaceOrgPair(targetWorkspace, orgId) + const targetWorkspace = workspaceId || organizationId + cacheWorkspaceOrgPair(targetWorkspace, organizationId) store.set(activeInviteAtom, null) removeInvite() if (isSurvey) { @@ -112,8 +112,8 @@ const Accept: FC = () => { } catch (error) { if (error?.response?.status === 409) { message.error("You're already a member of this workspace") - const targetWorkspace = workspaceId || orgId - cacheWorkspaceOrgPair(targetWorkspace, orgId) + const targetWorkspace = workspaceId || organizationId + cacheWorkspaceOrgPair(targetWorkspace, organizationId) store.set(activeInviteAtom, null) removeInvite() @@ -154,7 +154,7 @@ const Accept: FC = () => { if (alreadyMember) { message.info("You are already a member of this workspace") - cacheWorkspaceOrgPair(workspaceId || orgId, orgId) + cacheWorkspaceOrgPair(workspaceId || organizationId, organizationId) } else { console.error("[invite] accept failed", error) message.error(detailMessage) @@ -163,11 +163,11 @@ const Accept: FC = () => { store.set(activeInviteAtom, null) removeInvite() if (isSurvey) { - const redirect = encodeURIComponent(`/w/${workspaceId || orgId || ""}`) + const redirect = encodeURIComponent(`/w/${workspaceId || organizationId || ""}`) await router.replace(`/post-signup?redirect=${redirect}`) - } else if (workspaceId || orgId) { + } else if (workspaceId || organizationId) { const nextPath = buildPostLoginPath({ - workspaceId: workspaceId || orgId || null, + workspaceId: workspaceId || organizationId || null, projectId: null, }) await router.replace(nextPath) @@ -180,8 +180,8 @@ const Accept: FC = () => { useEffect(() => { onAcceptInvite() - // We only need to react to orgId/token presence; jwt readiness awaited inside - }, [orgId, token]) + // We only need to react to organizationId/token presence; jwt readiness awaited inside + }, [organizationId, token]) return } diff --git a/web/oss/src/services/organization/api/index.ts b/web/oss/src/services/organization/api/index.ts index 862f88d1f8..ee9329af9f 100644 --- a/web/oss/src/services/organization/api/index.ts +++ b/web/oss/src/services/organization/api/index.ts @@ -41,13 +41,17 @@ export const fetchAllOrgsList = async (): Promise => { * Fetch single organization details using modern fetchJson * Replaces the old axios-based fetchSingleOrg */ -export const fetchSingleOrg = async ({orgId}: {orgId: string}): Promise => { +export const fetchSingleOrg = async ({ + organizationId, +}: { + organizationId: string +}): Promise => { const base = getBaseUrl() - const url = new URL(`api/organizations/${orgId}`, base) + const url = new URL(`api/organizations/${organizationId}`, base) console.log("🔍 Single organization fetcher debug:", { base, - orgId, + organizationId, url: url.toString(), }) @@ -55,7 +59,7 @@ export const fetchSingleOrg = async ({orgId}: {orgId: string}): Promise { - const response = await axios.put(`${getAgentaApiUrl()}/organizations/${orgId}/`, {name}, { - _ignoreError: ignoreAxiosError, - } as any) +export const updateOrganization = async ( + organizationId: string, + name: string, + ignoreAxiosError = false, +) => { + const response = await axios.put( + `${getAgentaApiUrl()}/organizations/${organizationId}/`, + {name}, + { + _ignoreError: ignoreAxiosError, + } as any, + ) return response.data } diff --git a/web/oss/src/services/workspace/api/index.ts b/web/oss/src/services/workspace/api/index.ts index 6ca61387bb..a5ded23d8b 100644 --- a/web/oss/src/services/workspace/api/index.ts +++ b/web/oss/src/services/workspace/api/index.ts @@ -24,18 +24,18 @@ export const fetchAllWorkspaceRoles = async (ignoreAxiosError = false) => { export const assignWorkspaceRole = async ( { - orgId, + organizationId, workspaceId, email, role, - }: {orgId: string; workspaceId: string; email: string; role: string}, + }: {organizationId: string; workspaceId: string; email: string; role: string}, ignoreAxiosError = false, ) => { const {projectId} = getProjectValues() const response = await axios.post( `${getAgentaApiUrl()}/workspaces/${workspaceId}/roles?project_id=${projectId}`, - {email, organization_id: orgId, role}, + {email, organization_id: organizationId, role}, { _ignoreError: ignoreAxiosError, } as any, @@ -45,11 +45,11 @@ export const assignWorkspaceRole = async ( export const unAssignWorkspaceRole = async ( { - orgId, + organizationId, workspaceId, email, role, - }: {orgId: string; workspaceId: string; email: string; role: string}, + }: {organizationId: string; workspaceId: string; email: string; role: string}, ignoreAxiosError = false, ) => { const {projectId} = getProjectValues() @@ -57,7 +57,7 @@ export const unAssignWorkspaceRole = async ( const response = await axios.delete( `${getAgentaApiUrl()}/workspaces/${workspaceId}/roles?project_id=${projectId}`, { - params: {email, org_id: orgId, role}, + params: {email, organization_id: organizationId, role}, _ignoreError: ignoreAxiosError, } as any, ) @@ -68,10 +68,10 @@ export const unAssignWorkspaceRole = async ( export const inviteToWorkspace = async ( { data, - orgId, + organizationId, workspaceId, }: { - orgId: string + organizationId: string workspaceId: string data: {email: string; roles?: string[]}[] }, @@ -80,7 +80,7 @@ export const inviteToWorkspace = async ( const {projectId} = getProjectValues() const response = await axios.post( - `${getAgentaApiUrl()}/organizations/${orgId}/workspaces/${workspaceId}/invite?project_id=${projectId}`, + `${getAgentaApiUrl()}/organizations/${organizationId}/workspaces/${workspaceId}/invite?project_id=${projectId}`, data, { _ignoreError: ignoreAxiosError, @@ -90,13 +90,17 @@ export const inviteToWorkspace = async ( } export const resendInviteToWorkspace = async ( - {email, orgId, workspaceId}: {orgId: string; workspaceId: string; email: string}, + { + email, + organizationId, + workspaceId, + }: {organizationId: string; workspaceId: string; email: string}, ignoreAxiosError = false, ) => { const {projectId} = getProjectValues() const response = await axios.post( - `${getAgentaApiUrl()}/organizations/${orgId}/workspaces/${workspaceId}/invite/resend?project_id=${projectId}`, + `${getAgentaApiUrl()}/organizations/${organizationId}/workspaces/${workspaceId}/invite/resend?project_id=${projectId}`, {email}, { _ignoreError: ignoreAxiosError, @@ -108,15 +112,21 @@ export const resendInviteToWorkspace = async ( export const acceptWorkspaceInvite = async ( { token, - orgId, + organizationId, workspaceId, projectId, email, - }: {token: string; orgId: string; workspaceId: string; projectId: string; email?: string}, + }: { + token: string + organizationId: string + workspaceId: string + projectId: string + email?: string + }, ignoreAxiosError = false, ) => { const response = await axios.post( - `${getAgentaApiUrl()}/organizations/${orgId}/workspaces/${workspaceId}/invite/accept?project_id=${projectId}`, + `${getAgentaApiUrl()}/organizations/${organizationId}/workspaces/${workspaceId}/invite/accept?project_id=${projectId}`, {token, ...(email ? {email} : {})}, { _ignoreError: ignoreAxiosError, @@ -126,26 +136,34 @@ export const acceptWorkspaceInvite = async ( } export const removeFromWorkspace = async ( - {orgId, workspaceId, email}: {orgId: string; workspaceId: string; email: string}, + { + organizationId, + workspaceId, + email, + }: {organizationId: string; workspaceId: string; email: string}, ignoreAxiosError = false, ) => { const {projectId} = getProjectValues() const response = await axios.delete( `${getAgentaApiUrl()}/workspaces/${workspaceId}/users?project_id=${projectId}`, - {params: {email, org_id: orgId}, _ignoreError: ignoreAxiosError} as any, + {params: {email, organization_id: organizationId}, _ignoreError: ignoreAxiosError} as any, ) return response.data } export const updateWorkspace = async ( - {orgId, workspaceId, name}: {orgId: string; workspaceId: string; name: string}, + { + organizationId, + workspaceId, + name, + }: {organizationId: string; workspaceId: string; name: string}, ignoreAxiosError = false, ) => { const {projectId} = getProjectValues() const response = await axios.put( - `${getAgentaApiUrl()}/organizations/${orgId}/workspaces/${workspaceId}/?project_id=${projectId}`, + `${getAgentaApiUrl()}/organizations/${organizationId}/workspaces/${workspaceId}/?project_id=${projectId}`, {name}, {_ignoreError: ignoreAxiosError} as any, ) diff --git a/web/oss/src/state/app/atoms/fetcher.ts b/web/oss/src/state/app/atoms/fetcher.ts index 9936de4185..a52478d6c3 100644 --- a/web/oss/src/state/app/atoms/fetcher.ts +++ b/web/oss/src/state/app/atoms/fetcher.ts @@ -64,7 +64,7 @@ export const appsQueryAtom = atomWithQuery((get) => { const user = get(userAtom) as User | null const isProj = !!projectId const jwtReady = get(jwtReadyAtom).data ?? false - const orgId = get(selectedOrgIdAtom) + const organizationId = get(selectedOrgIdAtom) const activeInvite = get(activeInviteAtom) const enabled = profileState.isSuccess && @@ -72,7 +72,7 @@ export const appsQueryAtom = atomWithQuery((get) => { !!user?.id && isProj && !!projectId && - !!orgId && + !!organizationId && !activeInvite return { diff --git a/web/oss/src/state/org/hooks.ts b/web/oss/src/state/org/hooks.ts index 755df0c76c..e8a91df867 100644 --- a/web/oss/src/state/org/hooks.ts +++ b/web/oss/src/state/org/hooks.ts @@ -43,32 +43,32 @@ export const useOrgData = () => { const resolveWorkspaceForOrg = useCallback( async ( - orgId: string, + organizationId: string, ): Promise<{workspaceId: string | null; preferredProject: ProjectsResponse | null}> => { const matchingProject = projects.find((project) => - projectMatchesWorkspace(project, orgId), + projectMatchesWorkspace(project, organizationId), ) if (matchingProject) { return { - workspaceId: matchingProject.workspace_id || orgId, + workspaceId: matchingProject.workspace_id || organizationId, preferredProject: matchingProject, } } const cachedDetails = queryClient.getQueryData([ "selectedOrg", - orgId, + organizationId, ]) const resolvedDetails = cachedDetails ?? (await queryClient.fetchQuery({ - queryKey: ["selectedOrg", orgId], - queryFn: () => fetchSingleOrg({orgId}), + queryKey: ["selectedOrg", organizationId], + queryFn: () => fetchSingleOrg({organizationId}), })) - const workspaceId = resolvedDetails?.default_workspace?.id ?? orgId + const workspaceId = resolvedDetails?.default_workspace?.id ?? organizationId if (resolvedDetails?.default_workspace?.id) { cacheWorkspaceOrgPair(resolvedDetails.default_workspace.id, resolvedDetails.id) @@ -83,14 +83,14 @@ export const useOrgData = () => { ) const changeSelectedOrg = useCallback( - async (orgId: string, onSuccess?: () => void) => { + async (organizationId: string, onSuccess?: () => void) => { if (loadingOrgs) return - if (!orgId) { + if (!organizationId) { navigate({type: "href", href: "/w", method: "replace"}) return } - if (orgId === selectedOrgId) { + if (organizationId === selectedOrgId) { onSuccess?.() return } @@ -98,7 +98,7 @@ export const useOrgData = () => { queryClient.removeQueries({queryKey: ["selectedOrg", selectedOrgId]}) try { - const {workspaceId, preferredProject} = await resolveWorkspaceForOrg(orgId) + const {workspaceId, preferredProject} = await resolveWorkspaceForOrg(organizationId) if (!workspaceId) return if (preferredProject?.organization_id) { diff --git a/web/oss/src/state/org/selectors/org.ts b/web/oss/src/state/org/selectors/org.ts index ec503e2c21..e22e66036a 100644 --- a/web/oss/src/state/org/selectors/org.ts +++ b/web/oss/src/state/org/selectors/org.ts @@ -25,11 +25,14 @@ const readWorkspaceOrgMap = (): Record => { } } -export const cacheWorkspaceOrgPair = (workspaceId: string | null, orgId: string | null) => { +export const cacheWorkspaceOrgPair = ( + workspaceId: string | null, + organizationId: string | null, +) => { if (typeof window === "undefined") return - if (!workspaceId || !orgId) return + if (!workspaceId || !organizationId) return const map = readWorkspaceOrgMap() - map[workspaceId] = orgId + map[workspaceId] = organizationId try { window.localStorage.setItem(WORKSPACE_ORG_MAP_KEY, JSON.stringify(map)) } catch { @@ -67,7 +70,7 @@ export const orgsAtom = eagerAtom((get) => { export const selectedOrgIdAtom = atom((get) => { const snapshot = get(appStateSnapshotAtom) - const queryOrgId = snapshot.query["org_id"] + const queryOrgId = snapshot.query["organization_id"] if (typeof queryOrgId === "string" && queryOrgId) return queryOrgId const {workspaceId} = get(appIdentifiersAtom) return resolveOrgId(workspaceId) ?? workspaceId @@ -124,7 +127,7 @@ export const resolvePreferredWorkspaceId = (userId: string | null, orgs?: Org[]) export const selectedOrgQueryAtom = atomWithQuery((get) => { const snapshot = get(appStateSnapshotAtom) - const queryOrgId = snapshot.query["org_id"] + const queryOrgId = snapshot.query["organization_id"] const id = (typeof queryOrgId === "string" && queryOrgId) || get(selectedOrgIdAtom) const userId = (get(userAtom) as User | null)?.id const isWorkspaceRoute = @@ -144,7 +147,7 @@ export const selectedOrgQueryAtom = atomWithQuery((get) => { queryKey: ["selectedOrg", id], queryFn: async () => { if (!id) return null - const org = await fetchSingleOrg({orgId: id}) + const org = await fetchSingleOrg({organizationId: id}) return org }, staleTime: 60_000, diff --git a/web/oss/src/state/project/index.ts b/web/oss/src/state/project/index.ts index dfcb0228c8..2c4dd8faa5 100644 --- a/web/oss/src/state/project/index.ts +++ b/web/oss/src/state/project/index.ts @@ -14,9 +14,9 @@ export const getProjectValues = () => { const store = getDefaultStore() const queryClient = store.get(queryClientAtom) const {selectedOrg} = getOrgValues() - const orgId = selectedOrg?.id + const organizationId = selectedOrg?.id - const queryKey = ["projects", orgId] + const queryKey = ["projects", organizationId] const queryData = queryClient.getQueryData(queryKey) const queryState = queryClient.getQueryState(queryKey) diff --git a/web/oss/src/state/url/auth.ts b/web/oss/src/state/url/auth.ts index 1ab329f82b..b5a2655cdf 100644 --- a/web/oss/src/state/url/auth.ts +++ b/web/oss/src/state/url/auth.ts @@ -17,7 +17,7 @@ const isBrowser = typeof window !== "undefined" export interface InvitePayload { token: string email?: string - org_id?: string + organization_id?: string workspace_id?: string project_id?: string survey?: string @@ -35,7 +35,7 @@ export const parseInviteFromUrl = (url: URL): InvitePayload | null => { const invite: InvitePayload = {token} const fields: (keyof InvitePayload)[] = [ "email", - "org_id", + "organization_id", "workspace_id", "project_id", "survey", @@ -61,7 +61,8 @@ export const readInviteFromStorage = (): InvitePayload | null => { return { token: parsed.token.trim(), email: typeof parsed.email === "string" ? parsed.email.toLowerCase() : undefined, - org_id: typeof parsed.org_id === "string" ? parsed.org_id : undefined, + organization_id: + typeof parsed.organization_id === "string" ? parsed.organization_id : undefined, workspace_id: typeof parsed.workspace_id === "string" ? parsed.workspace_id : undefined, project_id: typeof parsed.project_id === "string" ? parsed.project_id : undefined, @@ -106,10 +107,10 @@ export const syncAuthStateFromUrl = (nextUrl?: string) => { const user = store.get(userAtom) const urlState = store.get(urlAtom) - const resolvedPath = nextUrl ? url.pathname : (appState.pathname ?? url.pathname) + const resolvedPath = nextUrl ? url.pathname : appState.pathname ?? url.pathname const resolvedAsPath = nextUrl ? `${url.pathname}${url.search}${url.hash}` - : (appState.asPath ?? `${url.pathname}${url.search}${url.hash}`) + : appState.asPath ?? `${url.pathname}${url.search}${url.hash}` const path = resolvedPath const asPath = resolvedAsPath const isAuthRoute = path.startsWith("/auth") diff --git a/web/oss/src/state/url/test.ts b/web/oss/src/state/url/test.ts index 8808441fa6..9888f62e69 100644 --- a/web/oss/src/state/url/test.ts +++ b/web/oss/src/state/url/test.ts @@ -6,7 +6,7 @@ import Router from "next/router" import {setLocationAtom, parseRouterState} from "@/oss/state/appState" import {sessionLoadingAtom} from "@/oss/state/session" -import {syncFocusDrawerStateFromUrl} from "@/oss/state/url/focusDrawer" +import focusDrawerState from "@/oss/state/url/focusDrawer" import {syncAuthStateFromUrl} from "./auth" import {syncPlaygroundStateFromUrl} from "./playground" @@ -65,7 +65,10 @@ const syncUrlState = (nextUrl?: string) => { syncAppLocation(store, nextUrl) syncTraceStateFromUrl(nextUrl) syncVariantStateFromUrl(nextUrl) - syncFocusDrawerStateFromUrl(nextUrl) + + if (typeof focusDrawerState?.syncFocusDrawerStateFromUrl === "function") { + focusDrawerState.syncFocusDrawerStateFromUrl(nextUrl) + } syncPlaygroundStateFromUrl(nextUrl) syncAuthStateFromUrl(nextUrl) } diff --git a/web/oss/src/state/workspace/atoms/mutations.ts b/web/oss/src/state/workspace/atoms/mutations.ts index 42a3b7dc2d..9c044932e6 100644 --- a/web/oss/src/state/workspace/atoms/mutations.ts +++ b/web/oss/src/state/workspace/atoms/mutations.ts @@ -15,17 +15,17 @@ import {userAtom} from "../../profile/selectors/user" */ export const updateWorkspaceNameAtom = atomWithMutation< void, - {orgId: string; workspaceId: string; name: string} + {organizationId: string; workspaceId: string; name: string} >((get) => ({ mutationKey: ["updateWorkspaceName"], - mutationFn: async ({orgId, workspaceId, name}) => { + mutationFn: async ({organizationId, workspaceId, name}) => { // Update both workspace and organization in parallel await Promise.all([ - updateWorkspace({orgId, workspaceId, name}), - updateOrganization(orgId, name), + updateWorkspace({organizationId, workspaceId, name}), + updateOrganization(organizationId, name), ]) }, - onSuccess: (_, {name, orgId}) => { + onSuccess: (_, {name, organizationId}) => { // Show success message message.success("Workspace renamed") @@ -59,12 +59,12 @@ export const updateWorkspaceNameActionAtom = atom( get, _set, { - orgId, + organizationId, workspaceId, name, onSuccess, }: { - orgId: string + organizationId: string workspaceId: string name: string onSuccess?: () => void @@ -73,7 +73,7 @@ export const updateWorkspaceNameActionAtom = atom( try { // Execute the mutation using mutateAsync from the mutation atom const {mutateAsync} = get(updateWorkspaceNameAtom) - await mutateAsync({orgId, workspaceId, name}) + await mutateAsync({organizationId, workspaceId, name}) // Call success callback if provided if (onSuccess) { diff --git a/web/package.json b/web/package.json index f8db4efb44..1c1974c6d1 100644 --- a/web/package.json +++ b/web/package.json @@ -1,6 +1,6 @@ { "name": "agenta-web", - "version": "0.59.0", + "version": "0.59.1", "workspaces": [ "ee", "oss",