diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index fa41c1f..5c708fe 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -3,7 +3,7 @@ name: ci on: [push] jobs: compile: - runs-on: ubuntu-20.04 + runs-on: ubuntu-latest steps: - name: Checkout repo uses: actions/checkout@v3 @@ -19,7 +19,7 @@ jobs: - name: Compile run: poetry run mypy . test: - runs-on: ubuntu-20.04 + runs-on: ubuntu-latest steps: - name: Checkout repo uses: actions/checkout@v3 @@ -39,7 +39,7 @@ jobs: publish: needs: [compile, test] if: github.event_name == 'push' && contains(github.ref, 'refs/tags/') - runs-on: ubuntu-20.04 + runs-on: ubuntu-latest steps: - name: Checkout repo uses: actions/checkout@v3 diff --git a/poetry.lock b/poetry.lock index 2e40b52..1f01e60 100644 --- a/poetry.lock +++ b/poetry.lock @@ -85,13 +85,13 @@ files = [ [[package]] name = "httpcore" -version = "1.0.7" +version = "1.0.8" description = "A minimal low-level HTTP client." optional = false python-versions = ">=3.8" files = [ - {file = "httpcore-1.0.7-py3-none-any.whl", hash = "sha256:a3fff8f43dc260d5bd363d9f9cf1830fa3a458b332856f34282de498ed420edd"}, - {file = "httpcore-1.0.7.tar.gz", hash = "sha256:8551cb62a169ec7162ac7be8d4817d561f60e08eaa485234898414bb5a8a0b4c"}, + {file = "httpcore-1.0.8-py3-none-any.whl", hash = "sha256:5254cf149bcb5f75e9d1b2b9f729ea4a4b883d1ad7379fc632b727cec23674be"}, + {file = "httpcore-1.0.8.tar.gz", hash = "sha256:86e94505ed24ea06514883fd44d2bc02d90e77e7979c8eb71b90f41d364a1bad"}, ] [package.dependencies] @@ -212,24 +212,24 @@ reports = ["lxml"] [[package]] name = "mypy-extensions" -version = "1.0.0" +version = "1.1.0" description = "Type system extensions for programs checked with the mypy type checker." optional = false -python-versions = ">=3.5" +python-versions = ">=3.8" files = [ - {file = "mypy_extensions-1.0.0-py3-none-any.whl", hash = "sha256:4392f6c0eb8a5668a69e23d168ffa70f0be9ccfd32b5cc2d26a34ae5b844552d"}, - {file = "mypy_extensions-1.0.0.tar.gz", hash = "sha256:75dbf8955dc00442a438fc4d0666508a9a97b6bd41aa2f0ffe9d2f2725af0782"}, + {file = "mypy_extensions-1.1.0-py3-none-any.whl", hash = "sha256:1be4cccdb0f2482337c4743e60421de3a356cd97508abadd57d47403e94f5505"}, + {file = "mypy_extensions-1.1.0.tar.gz", hash = "sha256:52e68efc3284861e772bbcd66823fde5ae21fd2fdb51c62a211403730b916558"}, ] [[package]] name = "packaging" -version = "24.2" +version = "25.0" description = "Core utilities for Python packages" optional = false python-versions = ">=3.8" files = [ - {file = "packaging-24.2-py3-none-any.whl", hash = "sha256:09abb1bccd265c01f4a3aa3f7a7db064b36514d2cba19a2f694fe6150451a759"}, - {file = "packaging-24.2.tar.gz", hash = "sha256:c228a6dc5e932d346bc5739379109d49e8853dd8223571c7c5b55260edc0b97f"}, + {file = "packaging-25.0-py3-none-any.whl", hash = "sha256:29572ef2b1f17581046b3a2227d5c611fb25ec70ca1ba8554b24b0e69331a484"}, + {file = "packaging-25.0.tar.gz", hash = "sha256:d443872c98d677bf60f6a1f2f8c1cb748e8fe762d2bf9d3148b5599295b0fc4f"}, ] [[package]] @@ -536,13 +536,13 @@ files = [ [[package]] name = "typing-extensions" -version = "4.13.0" +version = "4.13.2" description = "Backported and Experimental Type Hints for Python 3.8+" optional = false python-versions = ">=3.8" files = [ - {file = "typing_extensions-4.13.0-py3-none-any.whl", hash = "sha256:c8dd92cc0d6425a97c18fbb9d1954e5ff92c1ca881a309c45f06ebc0b79058e5"}, - {file = "typing_extensions-4.13.0.tar.gz", hash = "sha256:0a4ac55a5820789d87e297727d229866c9650f6521b64206413c4fbada24d95b"}, + {file = "typing_extensions-4.13.2-py3-none-any.whl", hash = "sha256:a439e7c04b49fec3e5d3e2beaa21755cadbbdc391694e28ccdd36ca4a1408f8c"}, + {file = "typing_extensions-4.13.2.tar.gz", hash = "sha256:e6c81219bd689f51865d9e372991c540bda33a0379d5573cddb9a3a23f7caaef"}, ] [metadata] diff --git a/pyproject.toml b/pyproject.toml index 07e01a1..a6c6866 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -3,7 +3,7 @@ name = "credal" [tool.poetry] name = "credal" -version = "0.0.25" +version = "0.0.26" description = "" readme = "README.md" authors = [] diff --git a/reference.md b/reference.md index 401f13b..2d99608 100644 --- a/reference.md +++ b/reference.md @@ -12,7 +12,7 @@
-Create a new copilot. The API key used will be added to the copilot for future Requests +Create a new agent. The API key used will be added to the agent for future Requests
@@ -34,8 +34,8 @@ client = CredalApi( api_key="YOUR_API_KEY", ) client.copilots.create_copilot( - name="Customer Copilot", - description="This copilot is used to answer customer requests based on internal documentation.", + name="Customer Agent", + description="This agent is used to answer customer requests based on internal documentation.", collaborators=[ Collaborator( email="test@gmail.com", @@ -58,7 +58,7 @@ client.copilots.create_copilot(
-**name:** `str` — A descriptive name for the copilot. +**name:** `str` — A descriptive name for the agent.
@@ -66,7 +66,7 @@ client.copilots.create_copilot(
-**description:** `str` — An in depth name for the copilot's function. Useful for routing requests to the right copilot. +**description:** `str` — An in depth name for the agent's function. Useful for routing requests to the right agent.
@@ -74,7 +74,7 @@ client.copilots.create_copilot(
-**collaborators:** `typing.Sequence[Collaborator]` — A list of collaborator emails and roles that will have access to the copilot. +**collaborators:** `typing.Sequence[Collaborator]` — A list of collaborator emails and roles that will have access to the agent.
@@ -106,7 +106,7 @@ client.copilots.create_copilot(
-OPTIONAL. Create a new conversation with the Copilot. The conversation ID can be used in the `sendMessage` endpoint. The `sendMessage` endpoint automatically creates new conversations upon first request, but calling this endpoint can simplify certain use cases where it is helpful for the application to have the conversation ID before the first message is sent. +OPTIONAL. Create a new conversation with the Agent. The conversation ID can be used in the `sendMessage` endpoint. The `sendMessage` endpoint automatically creates new conversations upon first request, but calling this endpoint can simplify certain use cases where it is helpful for the application to have the conversation ID before the first message is sent.
@@ -149,7 +149,7 @@ client.copilots.create_conversation(
-**agent_id:** `uuid.UUID` — Credal-generated Copilot ID to specify which agent to route the request to. +**agent_id:** `uuid.UUID` — Credal-generated Agent ID to specify which agent to route the request to.
@@ -227,7 +227,7 @@ client.copilots.provide_message_feedback(
-**agent_id:** `uuid.UUID` — Credal-generated Copilot ID to specify which agent to route the request to. +**agent_id:** `uuid.UUID` — Credal-generated Agent ID to specify which agent to route the request to.
@@ -335,7 +335,7 @@ client.copilots.send_message(
-**agent_id:** `uuid.UUID` — Credal-generated Copilot ID to specify which agent to route the request to. +**agent_id:** `uuid.UUID` — Credal-generated Agent ID to specify which agent to route the request to.
@@ -343,7 +343,7 @@ client.copilots.send_message(
-**message:** `str` — The message you want to send to your copilot. +**message:** `str` — The message you want to send to your agent.
@@ -399,7 +399,7 @@ client.copilots.send_message(
-This endpoint allows you to send a message to a specific copilot and get the response back as a streamed set of Server-Sent Events. +This endpoint allows you to send a message to a specific agent and get the response back as a streamed set of Server-Sent Events.
@@ -450,7 +450,7 @@ response = client.copilots.stream_message( ), ], ) -for chunk in response: +for chunk in response.data: yield chunk ``` @@ -467,7 +467,7 @@ for chunk in response:
-**copilot_id:** `uuid.UUID` — Credal-generated Copilot ID to specify which agent to route the request to. +**copilot_id:** `uuid.UUID` — Credal-generated Agent ID to specify which agent to route the request to.
@@ -475,7 +475,7 @@ for chunk in response:
-**message:** `str` — The message you want to send to your copilot. +**message:** `str` — The message you want to send to your agent.
@@ -531,7 +531,7 @@ for chunk in response:
-Link a collection with a copilot. The API Key used must be added to both the collection and the copilot beforehand. +Link a collection with a agent. The API Key used must be added to both the collection and the agent beforehand.
@@ -576,7 +576,7 @@ client.copilots.add_collection_to_copilot(
-**copilot_id:** `uuid.UUID` — Credal-generated copilot ID to add the collection to. +**copilot_id:** `uuid.UUID` — Credal-generated Agent ID to add the collection to.
@@ -616,7 +616,7 @@ client.copilots.add_collection_to_copilot(
-Unlink a collection with a copilot. The API Key used must be added to both the collection and the copilot beforehand. +Unlink a collection with a agent. The API Key used must be added to both the collection and the agent beforehand.
@@ -661,7 +661,7 @@ client.copilots.remove_collection_from_copilot(
-**copilot_id:** `uuid.UUID` — Credal-generated copilot ID to add the collection to. +**copilot_id:** `uuid.UUID` — Credal-generated agent ID to add the collection to.
@@ -701,7 +701,7 @@ client.copilots.remove_collection_from_copilot(
-Update the configuration for a copilot +Update the configuration for a agent
@@ -729,8 +729,8 @@ client.copilots.update_configuration( "82e4b12a-6990-45d4-8ebd-85c00e030c24", ), configuration=Configuration( - name="Customer Copilot", - description="This copilot is used to answer customer requests based on internal documentation.", + name="Customer Agent", + description="This agent is used to answer customer requests based on internal documentation.", prompt="You are a polite, helpful assistant used to answer customer requests.", ai_endpoint_configuration=AiEndpointConfiguration( base_url="https://api.openai.com/v1/", @@ -753,7 +753,7 @@ client.copilots.update_configuration(
-**copilot_id:** `uuid.UUID` — Credal-generated copilot ID to add the collection to. +**copilot_id:** `uuid.UUID` — Credal-generated agent ID to add the collection to.
@@ -1348,7 +1348,7 @@ client.document_collections.remove_documents_from_collection(
-Create a new copilot. The API key used will be added to the copilot for future Requests +Create a new collection. The API key used will be added to the collection for future Requests
@@ -1402,7 +1402,7 @@ client.document_collections.create_collection(
-**description:** `str` — An in depth name for the copilot's function. Useful for routing requests to the right copilot. +**description:** `str` — An in depth name for the agent's function. Useful for routing requests to the right agent.
@@ -1410,7 +1410,7 @@ client.document_collections.create_collection(
-**collaborators:** `typing.Sequence[Collaborator]` — A list of collaborator emails and roles that will have access to the copilot. +**collaborators:** `typing.Sequence[Collaborator]` — A list of collaborator emails and roles that will have access to the agent.
@@ -1516,7 +1516,7 @@ client.document_collections.delete_collection(
-Credal lets you easily sync your MongoDB data for use in Collections and Copilots. Create a new sync from a MongoDB collection to a Credal collection. +Credal lets you easily sync your MongoDB data for use in Collections and Agents. Create a new sync from a MongoDB collection to a Credal collection.
@@ -1622,7 +1622,7 @@ client.document_collections.create_mongo_collection_sync(
-Credal lets you easily sync your MongoDB data for use in Collections and Copilots. Update an existing sync from a MongoDB collection to a Credal collection via the `mongoCredentialId`, to disambiguate between multiple potential syncs to a given collection. +Credal lets you easily sync your MongoDB data for use in Collections and Agents. Update an existing sync from a MongoDB collection to a Credal collection via the `mongoCredentialId`, to disambiguate between multiple potential syncs to a given collection.
diff --git a/src/credal/copilots/client.py b/src/credal/copilots/client.py index 029bab8..844664a 100644 --- a/src/credal/copilots/client.py +++ b/src/credal/copilots/client.py @@ -2,24 +2,20 @@ import typing from ..core.client_wrapper import SyncClientWrapper +from .raw_client import RawCopilotsClient from ..common.types.collaborator import Collaborator from ..core.request_options import RequestOptions from .types.create_copilot_response import CreateCopilotResponse -from ..core.serialization import convert_and_respect_annotation_metadata -from ..core.pydantic_utilities import parse_obj_as -from json.decoder import JSONDecodeError -from ..core.api_error import ApiError import uuid from .types.create_conversation_response import CreateConversationResponse from .types.message_feedback import MessageFeedback from .types.input_variable import InputVariable from .types.send_agent_message_response import SendAgentMessageResponse from .types.streaming_chunk import StreamingChunk -import httpx_sse -import json from .types.configuration import Configuration from .types.delete_copilot_response import DeleteCopilotResponse from ..core.client_wrapper import AsyncClientWrapper +from .raw_client import AsyncRawCopilotsClient # this is used as the default value for optional parameters OMIT = typing.cast(typing.Any, ...) @@ -27,7 +23,18 @@ class CopilotsClient: def __init__(self, *, client_wrapper: SyncClientWrapper): - self._client_wrapper = client_wrapper + self._raw_client = RawCopilotsClient(client_wrapper=client_wrapper) + + @property + def with_raw_response(self) -> RawCopilotsClient: + """ + Retrieves a raw implementation of this client that returns raw responses. + + Returns + ------- + RawCopilotsClient + """ + return self._raw_client def create_copilot( self, @@ -38,18 +45,18 @@ def create_copilot( request_options: typing.Optional[RequestOptions] = None, ) -> CreateCopilotResponse: """ - Create a new copilot. The API key used will be added to the copilot for future Requests + Create a new agent. The API key used will be added to the agent for future Requests Parameters ---------- name : str - A descriptive name for the copilot. + A descriptive name for the agent. description : str - An in depth name for the copilot's function. Useful for routing requests to the right copilot. + An in depth name for the agent's function. Useful for routing requests to the right agent. collaborators : typing.Sequence[Collaborator] - A list of collaborator emails and roles that will have access to the copilot. + A list of collaborator emails and roles that will have access to the agent. request_options : typing.Optional[RequestOptions] Request-specific configuration. @@ -67,8 +74,8 @@ def create_copilot( api_key="YOUR_API_KEY", ) client.copilots.create_copilot( - name="Customer Copilot", - description="This copilot is used to answer customer requests based on internal documentation.", + name="Customer Agent", + description="This agent is used to answer customer requests based on internal documentation.", collaborators=[ Collaborator( email="test@gmail.com", @@ -77,43 +84,21 @@ def create_copilot( ], ) """ - _response = self._client_wrapper.httpx_client.request( - "v0/copilots/createCopilot", - method="POST", - json={ - "name": name, - "description": description, - "collaborators": convert_and_respect_annotation_metadata( - object_=collaborators, annotation=typing.Sequence[Collaborator], direction="write" - ), - }, - request_options=request_options, - omit=OMIT, + response = self._raw_client.create_copilot( + name=name, description=description, collaborators=collaborators, request_options=request_options ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - CreateCopilotResponse, - parse_obj_as( - type_=CreateCopilotResponse, # type: ignore - object_=_response.json(), - ), - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) + return response.data def create_conversation( self, *, agent_id: uuid.UUID, user_email: str, request_options: typing.Optional[RequestOptions] = None ) -> CreateConversationResponse: """ - OPTIONAL. Create a new conversation with the Copilot. The conversation ID can be used in the `sendMessage` endpoint. The `sendMessage` endpoint automatically creates new conversations upon first request, but calling this endpoint can simplify certain use cases where it is helpful for the application to have the conversation ID before the first message is sent. + OPTIONAL. Create a new conversation with the Agent. The conversation ID can be used in the `sendMessage` endpoint. The `sendMessage` endpoint automatically creates new conversations upon first request, but calling this endpoint can simplify certain use cases where it is helpful for the application to have the conversation ID before the first message is sent. Parameters ---------- agent_id : uuid.UUID - Credal-generated Copilot ID to specify which agent to route the request to. + Credal-generated Agent ID to specify which agent to route the request to. user_email : str End-user for the conversation. @@ -141,29 +126,10 @@ def create_conversation( user_email="ravin@credal.ai", ) """ - _response = self._client_wrapper.httpx_client.request( - "v0/copilots/createConversation", - method="POST", - json={ - "agentId": agent_id, - "userEmail": user_email, - }, - request_options=request_options, - omit=OMIT, + response = self._raw_client.create_conversation( + agent_id=agent_id, user_email=user_email, request_options=request_options ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - CreateConversationResponse, - parse_obj_as( - type_=CreateConversationResponse, # type: ignore - object_=_response.json(), - ), - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) + return response.data def provide_message_feedback( self, @@ -178,7 +144,7 @@ def provide_message_feedback( Parameters ---------- agent_id : uuid.UUID - Credal-generated Copilot ID to specify which agent to route the request to. + Credal-generated Agent ID to specify which agent to route the request to. user_email : str The user profile you want to use when providing feedback. @@ -221,27 +187,14 @@ def provide_message_feedback( ), ) """ - _response = self._client_wrapper.httpx_client.request( - "v0/copilots/provideMessageFeedback", - method="POST", - json={ - "agentId": agent_id, - "userEmail": user_email, - "messageId": message_id, - "messageFeedback": convert_and_respect_annotation_metadata( - object_=message_feedback, annotation=MessageFeedback, direction="write" - ), - }, + response = self._raw_client.provide_message_feedback( + agent_id=agent_id, + user_email=user_email, + message_id=message_id, + message_feedback=message_feedback, request_options=request_options, - omit=OMIT, ) - try: - if 200 <= _response.status_code < 300: - return - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) + return response.data def send_message( self, @@ -257,10 +210,10 @@ def send_message( Parameters ---------- agent_id : uuid.UUID - Credal-generated Copilot ID to specify which agent to route the request to. + Credal-generated Agent ID to specify which agent to route the request to. message : str - The message you want to send to your copilot. + The message you want to send to your agent. user_email : str The user profile you want to use when sending the message. @@ -317,34 +270,15 @@ def send_message( ], ) """ - _response = self._client_wrapper.httpx_client.request( - "v0/copilots/sendMessage", - method="POST", - json={ - "agentId": agent_id, - "message": message, - "userEmail": user_email, - "conversationId": conversation_id, - "inputVariables": convert_and_respect_annotation_metadata( - object_=input_variables, annotation=typing.Sequence[InputVariable], direction="write" - ), - }, + response = self._raw_client.send_message( + agent_id=agent_id, + message=message, + user_email=user_email, + conversation_id=conversation_id, + input_variables=input_variables, request_options=request_options, - omit=OMIT, ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - SendAgentMessageResponse, - parse_obj_as( - type_=SendAgentMessageResponse, # type: ignore - object_=_response.json(), - ), - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) + return response.data def stream_message( self, @@ -357,15 +291,15 @@ def stream_message( request_options: typing.Optional[RequestOptions] = None, ) -> typing.Iterator[StreamingChunk]: """ - This endpoint allows you to send a message to a specific copilot and get the response back as a streamed set of Server-Sent Events. + This endpoint allows you to send a message to a specific agent and get the response back as a streamed set of Server-Sent Events. Parameters ---------- copilot_id : uuid.UUID - Credal-generated Copilot ID to specify which agent to route the request to. + Credal-generated Agent ID to specify which agent to route the request to. message : str - The message you want to send to your copilot. + The message you want to send to your agent. email : str The user profile you want to use when sending the message. @@ -425,41 +359,15 @@ def stream_message( for chunk in response: yield chunk """ - with self._client_wrapper.httpx_client.stream( - "v0/copilots/streamMessage", - method="POST", - json={ - "copilotId": copilot_id, - "message": message, - "email": email, - "conversationId": conversation_id, - "inputVariables": convert_and_respect_annotation_metadata( - object_=input_variables, annotation=typing.Sequence[InputVariable], direction="write" - ), - }, + with self._raw_client.stream_message( + copilot_id=copilot_id, + message=message, + email=email, + conversation_id=conversation_id, + input_variables=input_variables, request_options=request_options, - omit=OMIT, - ) as _response: - try: - if 200 <= _response.status_code < 300: - _event_source = httpx_sse.EventSource(_response) - for _sse in _event_source.iter_sse(): - try: - yield typing.cast( - StreamingChunk, - parse_obj_as( - type_=StreamingChunk, # type: ignore - object_=json.loads(_sse.data), - ), - ) - except: - pass - return - _response.read() - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) + ) as r: + yield from r.data def add_collection_to_copilot( self, @@ -469,12 +377,12 @@ def add_collection_to_copilot( request_options: typing.Optional[RequestOptions] = None, ) -> None: """ - Link a collection with a copilot. The API Key used must be added to both the collection and the copilot beforehand. + Link a collection with a agent. The API Key used must be added to both the collection and the agent beforehand. Parameters ---------- copilot_id : uuid.UUID - Credal-generated copilot ID to add the collection to. + Credal-generated Agent ID to add the collection to. collection_id : uuid.UUID Credal-generated collection ID to add. @@ -504,23 +412,10 @@ def add_collection_to_copilot( ), ) """ - _response = self._client_wrapper.httpx_client.request( - "v0/copilots/addCollectionToCopilot", - method="POST", - json={ - "copilotId": copilot_id, - "collectionId": collection_id, - }, - request_options=request_options, - omit=OMIT, + response = self._raw_client.add_collection_to_copilot( + copilot_id=copilot_id, collection_id=collection_id, request_options=request_options ) - try: - if 200 <= _response.status_code < 300: - return - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) + return response.data def remove_collection_from_copilot( self, @@ -530,12 +425,12 @@ def remove_collection_from_copilot( request_options: typing.Optional[RequestOptions] = None, ) -> None: """ - Unlink a collection with a copilot. The API Key used must be added to both the collection and the copilot beforehand. + Unlink a collection with a agent. The API Key used must be added to both the collection and the agent beforehand. Parameters ---------- copilot_id : uuid.UUID - Credal-generated copilot ID to add the collection to. + Credal-generated agent ID to add the collection to. collection_id : uuid.UUID Credal-generated collection ID to add. @@ -565,23 +460,10 @@ def remove_collection_from_copilot( ), ) """ - _response = self._client_wrapper.httpx_client.request( - "v0/copilots/removeCollectionFromCopilot", - method="POST", - json={ - "copilotId": copilot_id, - "collectionId": collection_id, - }, - request_options=request_options, - omit=OMIT, + response = self._raw_client.remove_collection_from_copilot( + copilot_id=copilot_id, collection_id=collection_id, request_options=request_options ) - try: - if 200 <= _response.status_code < 300: - return - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) + return response.data def update_configuration( self, @@ -591,12 +473,12 @@ def update_configuration( request_options: typing.Optional[RequestOptions] = None, ) -> None: """ - Update the configuration for a copilot + Update the configuration for a agent Parameters ---------- copilot_id : uuid.UUID - Credal-generated copilot ID to add the collection to. + Credal-generated agent ID to add the collection to. configuration : Configuration @@ -622,8 +504,8 @@ def update_configuration( "82e4b12a-6990-45d4-8ebd-85c00e030c24", ), configuration=Configuration( - name="Customer Copilot", - description="This copilot is used to answer customer requests based on internal documentation.", + name="Customer Agent", + description="This agent is used to answer customer requests based on internal documentation.", prompt="You are a polite, helpful assistant used to answer customer requests.", ai_endpoint_configuration=AiEndpointConfiguration( base_url="https://api.openai.com/v1/", @@ -632,25 +514,10 @@ def update_configuration( ), ) """ - _response = self._client_wrapper.httpx_client.request( - "v0/copilots/updateConfiguration", - method="POST", - json={ - "copilotId": copilot_id, - "configuration": convert_and_respect_annotation_metadata( - object_=configuration, annotation=Configuration, direction="write" - ), - }, - request_options=request_options, - omit=OMIT, + response = self._raw_client.update_configuration( + copilot_id=copilot_id, configuration=configuration, request_options=request_options ) - try: - if 200 <= _response.status_code < 300: - return - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) + return response.data def delete_copilot( self, *, id: uuid.UUID, request_options: typing.Optional[RequestOptions] = None @@ -683,33 +550,24 @@ def delete_copilot( ), ) """ - _response = self._client_wrapper.httpx_client.request( - "v0/copilots/deleteCopilot", - method="DELETE", - json={ - "id": id, - }, - request_options=request_options, - omit=OMIT, - ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - DeleteCopilotResponse, - parse_obj_as( - type_=DeleteCopilotResponse, # type: ignore - object_=_response.json(), - ), - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) + response = self._raw_client.delete_copilot(id=id, request_options=request_options) + return response.data class AsyncCopilotsClient: def __init__(self, *, client_wrapper: AsyncClientWrapper): - self._client_wrapper = client_wrapper + self._raw_client = AsyncRawCopilotsClient(client_wrapper=client_wrapper) + + @property + def with_raw_response(self) -> AsyncRawCopilotsClient: + """ + Retrieves a raw implementation of this client that returns raw responses. + + Returns + ------- + AsyncRawCopilotsClient + """ + return self._raw_client async def create_copilot( self, @@ -720,18 +578,18 @@ async def create_copilot( request_options: typing.Optional[RequestOptions] = None, ) -> CreateCopilotResponse: """ - Create a new copilot. The API key used will be added to the copilot for future Requests + Create a new agent. The API key used will be added to the agent for future Requests Parameters ---------- name : str - A descriptive name for the copilot. + A descriptive name for the agent. description : str - An in depth name for the copilot's function. Useful for routing requests to the right copilot. + An in depth name for the agent's function. Useful for routing requests to the right agent. collaborators : typing.Sequence[Collaborator] - A list of collaborator emails and roles that will have access to the copilot. + A list of collaborator emails and roles that will have access to the agent. request_options : typing.Optional[RequestOptions] Request-specific configuration. @@ -754,8 +612,8 @@ async def create_copilot( async def main() -> None: await client.copilots.create_copilot( - name="Customer Copilot", - description="This copilot is used to answer customer requests based on internal documentation.", + name="Customer Agent", + description="This agent is used to answer customer requests based on internal documentation.", collaborators=[ Collaborator( email="test@gmail.com", @@ -767,43 +625,21 @@ async def main() -> None: asyncio.run(main()) """ - _response = await self._client_wrapper.httpx_client.request( - "v0/copilots/createCopilot", - method="POST", - json={ - "name": name, - "description": description, - "collaborators": convert_and_respect_annotation_metadata( - object_=collaborators, annotation=typing.Sequence[Collaborator], direction="write" - ), - }, - request_options=request_options, - omit=OMIT, + response = await self._raw_client.create_copilot( + name=name, description=description, collaborators=collaborators, request_options=request_options ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - CreateCopilotResponse, - parse_obj_as( - type_=CreateCopilotResponse, # type: ignore - object_=_response.json(), - ), - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) + return response.data async def create_conversation( self, *, agent_id: uuid.UUID, user_email: str, request_options: typing.Optional[RequestOptions] = None ) -> CreateConversationResponse: """ - OPTIONAL. Create a new conversation with the Copilot. The conversation ID can be used in the `sendMessage` endpoint. The `sendMessage` endpoint automatically creates new conversations upon first request, but calling this endpoint can simplify certain use cases where it is helpful for the application to have the conversation ID before the first message is sent. + OPTIONAL. Create a new conversation with the Agent. The conversation ID can be used in the `sendMessage` endpoint. The `sendMessage` endpoint automatically creates new conversations upon first request, but calling this endpoint can simplify certain use cases where it is helpful for the application to have the conversation ID before the first message is sent. Parameters ---------- agent_id : uuid.UUID - Credal-generated Copilot ID to specify which agent to route the request to. + Credal-generated Agent ID to specify which agent to route the request to. user_email : str End-user for the conversation. @@ -838,29 +674,10 @@ async def main() -> None: asyncio.run(main()) """ - _response = await self._client_wrapper.httpx_client.request( - "v0/copilots/createConversation", - method="POST", - json={ - "agentId": agent_id, - "userEmail": user_email, - }, - request_options=request_options, - omit=OMIT, + response = await self._raw_client.create_conversation( + agent_id=agent_id, user_email=user_email, request_options=request_options ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - CreateConversationResponse, - parse_obj_as( - type_=CreateConversationResponse, # type: ignore - object_=_response.json(), - ), - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) + return response.data async def provide_message_feedback( self, @@ -875,7 +692,7 @@ async def provide_message_feedback( Parameters ---------- agent_id : uuid.UUID - Credal-generated Copilot ID to specify which agent to route the request to. + Credal-generated Agent ID to specify which agent to route the request to. user_email : str The user profile you want to use when providing feedback. @@ -925,27 +742,14 @@ async def main() -> None: asyncio.run(main()) """ - _response = await self._client_wrapper.httpx_client.request( - "v0/copilots/provideMessageFeedback", - method="POST", - json={ - "agentId": agent_id, - "userEmail": user_email, - "messageId": message_id, - "messageFeedback": convert_and_respect_annotation_metadata( - object_=message_feedback, annotation=MessageFeedback, direction="write" - ), - }, + response = await self._raw_client.provide_message_feedback( + agent_id=agent_id, + user_email=user_email, + message_id=message_id, + message_feedback=message_feedback, request_options=request_options, - omit=OMIT, ) - try: - if 200 <= _response.status_code < 300: - return - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) + return response.data async def send_message( self, @@ -961,10 +765,10 @@ async def send_message( Parameters ---------- agent_id : uuid.UUID - Credal-generated Copilot ID to specify which agent to route the request to. + Credal-generated Agent ID to specify which agent to route the request to. message : str - The message you want to send to your copilot. + The message you want to send to your agent. user_email : str The user profile you want to use when sending the message. @@ -1028,34 +832,15 @@ async def main() -> None: asyncio.run(main()) """ - _response = await self._client_wrapper.httpx_client.request( - "v0/copilots/sendMessage", - method="POST", - json={ - "agentId": agent_id, - "message": message, - "userEmail": user_email, - "conversationId": conversation_id, - "inputVariables": convert_and_respect_annotation_metadata( - object_=input_variables, annotation=typing.Sequence[InputVariable], direction="write" - ), - }, + response = await self._raw_client.send_message( + agent_id=agent_id, + message=message, + user_email=user_email, + conversation_id=conversation_id, + input_variables=input_variables, request_options=request_options, - omit=OMIT, ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - SendAgentMessageResponse, - parse_obj_as( - type_=SendAgentMessageResponse, # type: ignore - object_=_response.json(), - ), - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) + return response.data async def stream_message( self, @@ -1068,15 +853,15 @@ async def stream_message( request_options: typing.Optional[RequestOptions] = None, ) -> typing.AsyncIterator[StreamingChunk]: """ - This endpoint allows you to send a message to a specific copilot and get the response back as a streamed set of Server-Sent Events. + This endpoint allows you to send a message to a specific agent and get the response back as a streamed set of Server-Sent Events. Parameters ---------- copilot_id : uuid.UUID - Credal-generated Copilot ID to specify which agent to route the request to. + Credal-generated Agent ID to specify which agent to route the request to. message : str - The message you want to send to your copilot. + The message you want to send to your agent. email : str The user profile you want to use when sending the message. @@ -1143,41 +928,16 @@ async def main() -> None: asyncio.run(main()) """ - async with self._client_wrapper.httpx_client.stream( - "v0/copilots/streamMessage", - method="POST", - json={ - "copilotId": copilot_id, - "message": message, - "email": email, - "conversationId": conversation_id, - "inputVariables": convert_and_respect_annotation_metadata( - object_=input_variables, annotation=typing.Sequence[InputVariable], direction="write" - ), - }, + async with self._raw_client.stream_message( + copilot_id=copilot_id, + message=message, + email=email, + conversation_id=conversation_id, + input_variables=input_variables, request_options=request_options, - omit=OMIT, - ) as _response: - try: - if 200 <= _response.status_code < 300: - _event_source = httpx_sse.EventSource(_response) - async for _sse in _event_source.aiter_sse(): - try: - yield typing.cast( - StreamingChunk, - parse_obj_as( - type_=StreamingChunk, # type: ignore - object_=json.loads(_sse.data), - ), - ) - except: - pass - return - await _response.aread() - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) + ) as r: + async for data in r.data: + yield data async def add_collection_to_copilot( self, @@ -1187,12 +947,12 @@ async def add_collection_to_copilot( request_options: typing.Optional[RequestOptions] = None, ) -> None: """ - Link a collection with a copilot. The API Key used must be added to both the collection and the copilot beforehand. + Link a collection with a agent. The API Key used must be added to both the collection and the agent beforehand. Parameters ---------- copilot_id : uuid.UUID - Credal-generated copilot ID to add the collection to. + Credal-generated Agent ID to add the collection to. collection_id : uuid.UUID Credal-generated collection ID to add. @@ -1229,23 +989,10 @@ async def main() -> None: asyncio.run(main()) """ - _response = await self._client_wrapper.httpx_client.request( - "v0/copilots/addCollectionToCopilot", - method="POST", - json={ - "copilotId": copilot_id, - "collectionId": collection_id, - }, - request_options=request_options, - omit=OMIT, + response = await self._raw_client.add_collection_to_copilot( + copilot_id=copilot_id, collection_id=collection_id, request_options=request_options ) - try: - if 200 <= _response.status_code < 300: - return - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) + return response.data async def remove_collection_from_copilot( self, @@ -1255,12 +1002,12 @@ async def remove_collection_from_copilot( request_options: typing.Optional[RequestOptions] = None, ) -> None: """ - Unlink a collection with a copilot. The API Key used must be added to both the collection and the copilot beforehand. + Unlink a collection with a agent. The API Key used must be added to both the collection and the agent beforehand. Parameters ---------- copilot_id : uuid.UUID - Credal-generated copilot ID to add the collection to. + Credal-generated agent ID to add the collection to. collection_id : uuid.UUID Credal-generated collection ID to add. @@ -1297,23 +1044,10 @@ async def main() -> None: asyncio.run(main()) """ - _response = await self._client_wrapper.httpx_client.request( - "v0/copilots/removeCollectionFromCopilot", - method="POST", - json={ - "copilotId": copilot_id, - "collectionId": collection_id, - }, - request_options=request_options, - omit=OMIT, + response = await self._raw_client.remove_collection_from_copilot( + copilot_id=copilot_id, collection_id=collection_id, request_options=request_options ) - try: - if 200 <= _response.status_code < 300: - return - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) + return response.data async def update_configuration( self, @@ -1323,12 +1057,12 @@ async def update_configuration( request_options: typing.Optional[RequestOptions] = None, ) -> None: """ - Update the configuration for a copilot + Update the configuration for a agent Parameters ---------- copilot_id : uuid.UUID - Credal-generated copilot ID to add the collection to. + Credal-generated agent ID to add the collection to. configuration : Configuration @@ -1358,8 +1092,8 @@ async def main() -> None: "82e4b12a-6990-45d4-8ebd-85c00e030c24", ), configuration=Configuration( - name="Customer Copilot", - description="This copilot is used to answer customer requests based on internal documentation.", + name="Customer Agent", + description="This agent is used to answer customer requests based on internal documentation.", prompt="You are a polite, helpful assistant used to answer customer requests.", ai_endpoint_configuration=AiEndpointConfiguration( base_url="https://api.openai.com/v1/", @@ -1371,25 +1105,10 @@ async def main() -> None: asyncio.run(main()) """ - _response = await self._client_wrapper.httpx_client.request( - "v0/copilots/updateConfiguration", - method="POST", - json={ - "copilotId": copilot_id, - "configuration": convert_and_respect_annotation_metadata( - object_=configuration, annotation=Configuration, direction="write" - ), - }, - request_options=request_options, - omit=OMIT, + response = await self._raw_client.update_configuration( + copilot_id=copilot_id, configuration=configuration, request_options=request_options ) - try: - if 200 <= _response.status_code < 300: - return - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) + return response.data async def delete_copilot( self, *, id: uuid.UUID, request_options: typing.Optional[RequestOptions] = None @@ -1429,25 +1148,5 @@ async def main() -> None: asyncio.run(main()) """ - _response = await self._client_wrapper.httpx_client.request( - "v0/copilots/deleteCopilot", - method="DELETE", - json={ - "id": id, - }, - request_options=request_options, - omit=OMIT, - ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - DeleteCopilotResponse, - parse_obj_as( - type_=DeleteCopilotResponse, # type: ignore - object_=_response.json(), - ), - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) + response = await self._raw_client.delete_copilot(id=id, request_options=request_options) + return response.data diff --git a/src/credal/copilots/raw_client.py b/src/credal/copilots/raw_client.py new file mode 100644 index 0000000..b1c8dd1 --- /dev/null +++ b/src/credal/copilots/raw_client.py @@ -0,0 +1,977 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing +from ..core.client_wrapper import SyncClientWrapper +from ..common.types.collaborator import Collaborator +from ..core.request_options import RequestOptions +from ..core.http_response import HttpResponse +from .types.create_copilot_response import CreateCopilotResponse +from ..core.serialization import convert_and_respect_annotation_metadata +from ..core.pydantic_utilities import parse_obj_as +from json.decoder import JSONDecodeError +from ..core.api_error import ApiError +import uuid +from .types.create_conversation_response import CreateConversationResponse +from .types.message_feedback import MessageFeedback +from .types.input_variable import InputVariable +from .types.send_agent_message_response import SendAgentMessageResponse +from .types.streaming_chunk import StreamingChunk +import httpx_sse +import contextlib +from .types.configuration import Configuration +from .types.delete_copilot_response import DeleteCopilotResponse +from ..core.client_wrapper import AsyncClientWrapper +from ..core.http_response import AsyncHttpResponse + +# this is used as the default value for optional parameters +OMIT = typing.cast(typing.Any, ...) + + +class RawCopilotsClient: + def __init__(self, *, client_wrapper: SyncClientWrapper): + self._client_wrapper = client_wrapper + + def create_copilot( + self, + *, + name: str, + description: str, + collaborators: typing.Sequence[Collaborator], + request_options: typing.Optional[RequestOptions] = None, + ) -> HttpResponse[CreateCopilotResponse]: + """ + Create a new agent. The API key used will be added to the agent for future Requests + + Parameters + ---------- + name : str + A descriptive name for the agent. + + description : str + An in depth name for the agent's function. Useful for routing requests to the right agent. + + collaborators : typing.Sequence[Collaborator] + A list of collaborator emails and roles that will have access to the agent. + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[CreateCopilotResponse] + """ + _response = self._client_wrapper.httpx_client.request( + "v0/copilots/createCopilot", + method="POST", + json={ + "name": name, + "description": description, + "collaborators": convert_and_respect_annotation_metadata( + object_=collaborators, annotation=typing.Sequence[Collaborator], direction="write" + ), + }, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + CreateCopilotResponse, + parse_obj_as( + type_=CreateCopilotResponse, # type: ignore + object_=_response.json(), + ), + ) + return HttpResponse(response=_response, data=_data) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, body=_response.text) + raise ApiError(status_code=_response.status_code, body=_response_json) + + def create_conversation( + self, *, agent_id: uuid.UUID, user_email: str, request_options: typing.Optional[RequestOptions] = None + ) -> HttpResponse[CreateConversationResponse]: + """ + OPTIONAL. Create a new conversation with the Agent. The conversation ID can be used in the `sendMessage` endpoint. The `sendMessage` endpoint automatically creates new conversations upon first request, but calling this endpoint can simplify certain use cases where it is helpful for the application to have the conversation ID before the first message is sent. + + Parameters + ---------- + agent_id : uuid.UUID + Credal-generated Agent ID to specify which agent to route the request to. + + user_email : str + End-user for the conversation. + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[CreateConversationResponse] + """ + _response = self._client_wrapper.httpx_client.request( + "v0/copilots/createConversation", + method="POST", + json={ + "agentId": agent_id, + "userEmail": user_email, + }, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + CreateConversationResponse, + parse_obj_as( + type_=CreateConversationResponse, # type: ignore + object_=_response.json(), + ), + ) + return HttpResponse(response=_response, data=_data) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, body=_response.text) + raise ApiError(status_code=_response.status_code, body=_response_json) + + def provide_message_feedback( + self, + *, + agent_id: uuid.UUID, + user_email: str, + message_id: uuid.UUID, + message_feedback: MessageFeedback, + request_options: typing.Optional[RequestOptions] = None, + ) -> HttpResponse[None]: + """ + Parameters + ---------- + agent_id : uuid.UUID + Credal-generated Agent ID to specify which agent to route the request to. + + user_email : str + The user profile you want to use when providing feedback. + + message_id : uuid.UUID + The message ID for which feedback is being provided. + + message_feedback : MessageFeedback + The feedback provided by the user. + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[None] + """ + _response = self._client_wrapper.httpx_client.request( + "v0/copilots/provideMessageFeedback", + method="POST", + json={ + "agentId": agent_id, + "userEmail": user_email, + "messageId": message_id, + "messageFeedback": convert_and_respect_annotation_metadata( + object_=message_feedback, annotation=MessageFeedback, direction="write" + ), + }, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + return HttpResponse(response=_response, data=None) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, body=_response.text) + raise ApiError(status_code=_response.status_code, body=_response_json) + + def send_message( + self, + *, + agent_id: uuid.UUID, + message: str, + user_email: str, + conversation_id: typing.Optional[uuid.UUID] = OMIT, + input_variables: typing.Optional[typing.Sequence[InputVariable]] = OMIT, + request_options: typing.Optional[RequestOptions] = None, + ) -> HttpResponse[SendAgentMessageResponse]: + """ + Parameters + ---------- + agent_id : uuid.UUID + Credal-generated Agent ID to specify which agent to route the request to. + + message : str + The message you want to send to your agent. + + user_email : str + The user profile you want to use when sending the message. + + conversation_id : typing.Optional[uuid.UUID] + Credal-generated conversation ID for sending follow up messages. Conversation ID is returned after initial message. Optional, to be left off for first messages on new conversations. + + input_variables : typing.Optional[typing.Sequence[InputVariable]] + Optional input variables to be used in the message. Map the name of the variable to a list of urls. + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[SendAgentMessageResponse] + """ + _response = self._client_wrapper.httpx_client.request( + "v0/copilots/sendMessage", + method="POST", + json={ + "agentId": agent_id, + "message": message, + "userEmail": user_email, + "conversationId": conversation_id, + "inputVariables": convert_and_respect_annotation_metadata( + object_=input_variables, annotation=typing.Sequence[InputVariable], direction="write" + ), + }, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + SendAgentMessageResponse, + parse_obj_as( + type_=SendAgentMessageResponse, # type: ignore + object_=_response.json(), + ), + ) + return HttpResponse(response=_response, data=_data) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, body=_response.text) + raise ApiError(status_code=_response.status_code, body=_response_json) + + @contextlib.contextmanager + def stream_message( + self, + *, + copilot_id: uuid.UUID, + message: str, + email: str, + conversation_id: typing.Optional[uuid.UUID] = OMIT, + input_variables: typing.Optional[typing.Sequence[InputVariable]] = OMIT, + request_options: typing.Optional[RequestOptions] = None, + ) -> typing.Iterator[HttpResponse[typing.Iterator[StreamingChunk]]]: + """ + This endpoint allows you to send a message to a specific agent and get the response back as a streamed set of Server-Sent Events. + + Parameters + ---------- + copilot_id : uuid.UUID + Credal-generated Agent ID to specify which agent to route the request to. + + message : str + The message you want to send to your agent. + + email : str + The user profile you want to use when sending the message. + + conversation_id : typing.Optional[uuid.UUID] + Credal-generated conversation ID for sending follow up messages. Conversation ID is returned after initial message. Optional, to be left off for first messages on new conversations. + + input_variables : typing.Optional[typing.Sequence[InputVariable]] + Optional input variables to be used in the message. Map the name of the variable to a list of urls. + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Yields + ------ + typing.Iterator[HttpResponse[typing.Iterator[StreamingChunk]]] + This endpoint returns a stream of server sent events. These can be in two formats - one is an initial event, followed by multiple data chunks, followed by a final chunk, or the other format is just one blocked event. See the examples for more details. + """ + with self._client_wrapper.httpx_client.stream( + "v0/copilots/streamMessage", + method="POST", + json={ + "copilotId": copilot_id, + "message": message, + "email": email, + "conversationId": conversation_id, + "inputVariables": convert_and_respect_annotation_metadata( + object_=input_variables, annotation=typing.Sequence[InputVariable], direction="write" + ), + }, + request_options=request_options, + omit=OMIT, + ) as _response: + + def stream() -> HttpResponse[typing.Iterator[StreamingChunk]]: + try: + if 200 <= _response.status_code < 300: + + def _iter(): + _event_source = httpx_sse.EventSource(_response) + for _sse in _event_source.iter_sse(): + if _sse.data == None: + return + try: + yield _sse.data() + except Exception: + pass + return + + return HttpResponse(response=_response, data=_iter()) + _response.read() + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, body=_response.text) + raise ApiError(status_code=_response.status_code, body=_response_json) + + yield stream() + + def add_collection_to_copilot( + self, + *, + copilot_id: uuid.UUID, + collection_id: uuid.UUID, + request_options: typing.Optional[RequestOptions] = None, + ) -> HttpResponse[None]: + """ + Link a collection with a agent. The API Key used must be added to both the collection and the agent beforehand. + + Parameters + ---------- + copilot_id : uuid.UUID + Credal-generated Agent ID to add the collection to. + + collection_id : uuid.UUID + Credal-generated collection ID to add. + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[None] + """ + _response = self._client_wrapper.httpx_client.request( + "v0/copilots/addCollectionToCopilot", + method="POST", + json={ + "copilotId": copilot_id, + "collectionId": collection_id, + }, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + return HttpResponse(response=_response, data=None) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, body=_response.text) + raise ApiError(status_code=_response.status_code, body=_response_json) + + def remove_collection_from_copilot( + self, + *, + copilot_id: uuid.UUID, + collection_id: uuid.UUID, + request_options: typing.Optional[RequestOptions] = None, + ) -> HttpResponse[None]: + """ + Unlink a collection with a agent. The API Key used must be added to both the collection and the agent beforehand. + + Parameters + ---------- + copilot_id : uuid.UUID + Credal-generated agent ID to add the collection to. + + collection_id : uuid.UUID + Credal-generated collection ID to add. + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[None] + """ + _response = self._client_wrapper.httpx_client.request( + "v0/copilots/removeCollectionFromCopilot", + method="POST", + json={ + "copilotId": copilot_id, + "collectionId": collection_id, + }, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + return HttpResponse(response=_response, data=None) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, body=_response.text) + raise ApiError(status_code=_response.status_code, body=_response_json) + + def update_configuration( + self, + *, + copilot_id: uuid.UUID, + configuration: Configuration, + request_options: typing.Optional[RequestOptions] = None, + ) -> HttpResponse[None]: + """ + Update the configuration for a agent + + Parameters + ---------- + copilot_id : uuid.UUID + Credal-generated agent ID to add the collection to. + + configuration : Configuration + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[None] + """ + _response = self._client_wrapper.httpx_client.request( + "v0/copilots/updateConfiguration", + method="POST", + json={ + "copilotId": copilot_id, + "configuration": convert_and_respect_annotation_metadata( + object_=configuration, annotation=Configuration, direction="write" + ), + }, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + return HttpResponse(response=_response, data=None) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, body=_response.text) + raise ApiError(status_code=_response.status_code, body=_response_json) + + def delete_copilot( + self, *, id: uuid.UUID, request_options: typing.Optional[RequestOptions] = None + ) -> HttpResponse[DeleteCopilotResponse]: + """ + Parameters + ---------- + id : uuid.UUID + Copilot ID + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[DeleteCopilotResponse] + """ + _response = self._client_wrapper.httpx_client.request( + "v0/copilots/deleteCopilot", + method="DELETE", + json={ + "id": id, + }, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + DeleteCopilotResponse, + parse_obj_as( + type_=DeleteCopilotResponse, # type: ignore + object_=_response.json(), + ), + ) + return HttpResponse(response=_response, data=_data) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, body=_response.text) + raise ApiError(status_code=_response.status_code, body=_response_json) + + +class AsyncRawCopilotsClient: + def __init__(self, *, client_wrapper: AsyncClientWrapper): + self._client_wrapper = client_wrapper + + async def create_copilot( + self, + *, + name: str, + description: str, + collaborators: typing.Sequence[Collaborator], + request_options: typing.Optional[RequestOptions] = None, + ) -> AsyncHttpResponse[CreateCopilotResponse]: + """ + Create a new agent. The API key used will be added to the agent for future Requests + + Parameters + ---------- + name : str + A descriptive name for the agent. + + description : str + An in depth name for the agent's function. Useful for routing requests to the right agent. + + collaborators : typing.Sequence[Collaborator] + A list of collaborator emails and roles that will have access to the agent. + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[CreateCopilotResponse] + """ + _response = await self._client_wrapper.httpx_client.request( + "v0/copilots/createCopilot", + method="POST", + json={ + "name": name, + "description": description, + "collaborators": convert_and_respect_annotation_metadata( + object_=collaborators, annotation=typing.Sequence[Collaborator], direction="write" + ), + }, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + CreateCopilotResponse, + parse_obj_as( + type_=CreateCopilotResponse, # type: ignore + object_=_response.json(), + ), + ) + return AsyncHttpResponse(response=_response, data=_data) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, body=_response.text) + raise ApiError(status_code=_response.status_code, body=_response_json) + + async def create_conversation( + self, *, agent_id: uuid.UUID, user_email: str, request_options: typing.Optional[RequestOptions] = None + ) -> AsyncHttpResponse[CreateConversationResponse]: + """ + OPTIONAL. Create a new conversation with the Agent. The conversation ID can be used in the `sendMessage` endpoint. The `sendMessage` endpoint automatically creates new conversations upon first request, but calling this endpoint can simplify certain use cases where it is helpful for the application to have the conversation ID before the first message is sent. + + Parameters + ---------- + agent_id : uuid.UUID + Credal-generated Agent ID to specify which agent to route the request to. + + user_email : str + End-user for the conversation. + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[CreateConversationResponse] + """ + _response = await self._client_wrapper.httpx_client.request( + "v0/copilots/createConversation", + method="POST", + json={ + "agentId": agent_id, + "userEmail": user_email, + }, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + CreateConversationResponse, + parse_obj_as( + type_=CreateConversationResponse, # type: ignore + object_=_response.json(), + ), + ) + return AsyncHttpResponse(response=_response, data=_data) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, body=_response.text) + raise ApiError(status_code=_response.status_code, body=_response_json) + + async def provide_message_feedback( + self, + *, + agent_id: uuid.UUID, + user_email: str, + message_id: uuid.UUID, + message_feedback: MessageFeedback, + request_options: typing.Optional[RequestOptions] = None, + ) -> AsyncHttpResponse[None]: + """ + Parameters + ---------- + agent_id : uuid.UUID + Credal-generated Agent ID to specify which agent to route the request to. + + user_email : str + The user profile you want to use when providing feedback. + + message_id : uuid.UUID + The message ID for which feedback is being provided. + + message_feedback : MessageFeedback + The feedback provided by the user. + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[None] + """ + _response = await self._client_wrapper.httpx_client.request( + "v0/copilots/provideMessageFeedback", + method="POST", + json={ + "agentId": agent_id, + "userEmail": user_email, + "messageId": message_id, + "messageFeedback": convert_and_respect_annotation_metadata( + object_=message_feedback, annotation=MessageFeedback, direction="write" + ), + }, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + return AsyncHttpResponse(response=_response, data=None) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, body=_response.text) + raise ApiError(status_code=_response.status_code, body=_response_json) + + async def send_message( + self, + *, + agent_id: uuid.UUID, + message: str, + user_email: str, + conversation_id: typing.Optional[uuid.UUID] = OMIT, + input_variables: typing.Optional[typing.Sequence[InputVariable]] = OMIT, + request_options: typing.Optional[RequestOptions] = None, + ) -> AsyncHttpResponse[SendAgentMessageResponse]: + """ + Parameters + ---------- + agent_id : uuid.UUID + Credal-generated Agent ID to specify which agent to route the request to. + + message : str + The message you want to send to your agent. + + user_email : str + The user profile you want to use when sending the message. + + conversation_id : typing.Optional[uuid.UUID] + Credal-generated conversation ID for sending follow up messages. Conversation ID is returned after initial message. Optional, to be left off for first messages on new conversations. + + input_variables : typing.Optional[typing.Sequence[InputVariable]] + Optional input variables to be used in the message. Map the name of the variable to a list of urls. + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[SendAgentMessageResponse] + """ + _response = await self._client_wrapper.httpx_client.request( + "v0/copilots/sendMessage", + method="POST", + json={ + "agentId": agent_id, + "message": message, + "userEmail": user_email, + "conversationId": conversation_id, + "inputVariables": convert_and_respect_annotation_metadata( + object_=input_variables, annotation=typing.Sequence[InputVariable], direction="write" + ), + }, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + SendAgentMessageResponse, + parse_obj_as( + type_=SendAgentMessageResponse, # type: ignore + object_=_response.json(), + ), + ) + return AsyncHttpResponse(response=_response, data=_data) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, body=_response.text) + raise ApiError(status_code=_response.status_code, body=_response_json) + + @contextlib.asynccontextmanager + async def stream_message( + self, + *, + copilot_id: uuid.UUID, + message: str, + email: str, + conversation_id: typing.Optional[uuid.UUID] = OMIT, + input_variables: typing.Optional[typing.Sequence[InputVariable]] = OMIT, + request_options: typing.Optional[RequestOptions] = None, + ) -> typing.AsyncIterator[AsyncHttpResponse[typing.AsyncIterator[StreamingChunk]]]: + """ + This endpoint allows you to send a message to a specific agent and get the response back as a streamed set of Server-Sent Events. + + Parameters + ---------- + copilot_id : uuid.UUID + Credal-generated Agent ID to specify which agent to route the request to. + + message : str + The message you want to send to your agent. + + email : str + The user profile you want to use when sending the message. + + conversation_id : typing.Optional[uuid.UUID] + Credal-generated conversation ID for sending follow up messages. Conversation ID is returned after initial message. Optional, to be left off for first messages on new conversations. + + input_variables : typing.Optional[typing.Sequence[InputVariable]] + Optional input variables to be used in the message. Map the name of the variable to a list of urls. + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Yields + ------ + typing.AsyncIterator[AsyncHttpResponse[typing.AsyncIterator[StreamingChunk]]] + This endpoint returns a stream of server sent events. These can be in two formats - one is an initial event, followed by multiple data chunks, followed by a final chunk, or the other format is just one blocked event. See the examples for more details. + """ + async with self._client_wrapper.httpx_client.stream( + "v0/copilots/streamMessage", + method="POST", + json={ + "copilotId": copilot_id, + "message": message, + "email": email, + "conversationId": conversation_id, + "inputVariables": convert_and_respect_annotation_metadata( + object_=input_variables, annotation=typing.Sequence[InputVariable], direction="write" + ), + }, + request_options=request_options, + omit=OMIT, + ) as _response: + + async def stream() -> AsyncHttpResponse[typing.AsyncIterator[StreamingChunk]]: + try: + if 200 <= _response.status_code < 300: + + async def _iter(): + _event_source = httpx_sse.EventSource(_response) + async for _sse in _event_source.aiter_sse(): + if _sse.data == None: + return + try: + yield _sse.data() + except Exception: + pass + return + + return AsyncHttpResponse(response=_response, data=_iter()) + await _response.aread() + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, body=_response.text) + raise ApiError(status_code=_response.status_code, body=_response_json) + + yield await stream() + + async def add_collection_to_copilot( + self, + *, + copilot_id: uuid.UUID, + collection_id: uuid.UUID, + request_options: typing.Optional[RequestOptions] = None, + ) -> AsyncHttpResponse[None]: + """ + Link a collection with a agent. The API Key used must be added to both the collection and the agent beforehand. + + Parameters + ---------- + copilot_id : uuid.UUID + Credal-generated Agent ID to add the collection to. + + collection_id : uuid.UUID + Credal-generated collection ID to add. + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[None] + """ + _response = await self._client_wrapper.httpx_client.request( + "v0/copilots/addCollectionToCopilot", + method="POST", + json={ + "copilotId": copilot_id, + "collectionId": collection_id, + }, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + return AsyncHttpResponse(response=_response, data=None) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, body=_response.text) + raise ApiError(status_code=_response.status_code, body=_response_json) + + async def remove_collection_from_copilot( + self, + *, + copilot_id: uuid.UUID, + collection_id: uuid.UUID, + request_options: typing.Optional[RequestOptions] = None, + ) -> AsyncHttpResponse[None]: + """ + Unlink a collection with a agent. The API Key used must be added to both the collection and the agent beforehand. + + Parameters + ---------- + copilot_id : uuid.UUID + Credal-generated agent ID to add the collection to. + + collection_id : uuid.UUID + Credal-generated collection ID to add. + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[None] + """ + _response = await self._client_wrapper.httpx_client.request( + "v0/copilots/removeCollectionFromCopilot", + method="POST", + json={ + "copilotId": copilot_id, + "collectionId": collection_id, + }, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + return AsyncHttpResponse(response=_response, data=None) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, body=_response.text) + raise ApiError(status_code=_response.status_code, body=_response_json) + + async def update_configuration( + self, + *, + copilot_id: uuid.UUID, + configuration: Configuration, + request_options: typing.Optional[RequestOptions] = None, + ) -> AsyncHttpResponse[None]: + """ + Update the configuration for a agent + + Parameters + ---------- + copilot_id : uuid.UUID + Credal-generated agent ID to add the collection to. + + configuration : Configuration + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[None] + """ + _response = await self._client_wrapper.httpx_client.request( + "v0/copilots/updateConfiguration", + method="POST", + json={ + "copilotId": copilot_id, + "configuration": convert_and_respect_annotation_metadata( + object_=configuration, annotation=Configuration, direction="write" + ), + }, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + return AsyncHttpResponse(response=_response, data=None) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, body=_response.text) + raise ApiError(status_code=_response.status_code, body=_response_json) + + async def delete_copilot( + self, *, id: uuid.UUID, request_options: typing.Optional[RequestOptions] = None + ) -> AsyncHttpResponse[DeleteCopilotResponse]: + """ + Parameters + ---------- + id : uuid.UUID + Copilot ID + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[DeleteCopilotResponse] + """ + _response = await self._client_wrapper.httpx_client.request( + "v0/copilots/deleteCopilot", + method="DELETE", + json={ + "id": id, + }, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + DeleteCopilotResponse, + parse_obj_as( + type_=DeleteCopilotResponse, # type: ignore + object_=_response.json(), + ), + ) + return AsyncHttpResponse(response=_response, data=_data) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, body=_response.text) + raise ApiError(status_code=_response.status_code, body=_response_json) diff --git a/src/credal/core/__init__.py b/src/credal/core/__init__.py index f03aecb..7a7ee41 100644 --- a/src/credal/core/__init__.py +++ b/src/credal/core/__init__.py @@ -5,6 +5,7 @@ from .datetime_utils import serialize_datetime from .file import File, convert_file_dict_to_httpx_tuples, with_content_type from .http_client import AsyncHttpClient, HttpClient +from .http_response import AsyncHttpResponse, HttpResponse from .jsonable_encoder import jsonable_encoder from .pydantic_utilities import ( IS_PYDANTIC_V2, @@ -24,10 +25,12 @@ "ApiError", "AsyncClientWrapper", "AsyncHttpClient", + "AsyncHttpResponse", "BaseClientWrapper", "FieldMetadata", "File", "HttpClient", + "HttpResponse", "IS_PYDANTIC_V2", "RequestOptions", "SyncClientWrapper", diff --git a/src/credal/core/client_wrapper.py b/src/credal/core/client_wrapper.py index 7c29724..de06386 100644 --- a/src/credal/core/client_wrapper.py +++ b/src/credal/core/client_wrapper.py @@ -20,9 +20,10 @@ def __init__( def get_headers(self) -> typing.Dict[str, str]: headers: typing.Dict[str, str] = { + "User-Agent": "credal/0.0.26", "X-Fern-Language": "Python", "X-Fern-SDK-Name": "credal", - "X-Fern-SDK-Version": "0.0.25", + "X-Fern-SDK-Version": "0.0.26", } headers["Authorization"] = f"Bearer {self._get_api_key()}" return headers diff --git a/src/credal/core/http_response.py b/src/credal/core/http_response.py new file mode 100644 index 0000000..c72a913 --- /dev/null +++ b/src/credal/core/http_response.py @@ -0,0 +1,47 @@ +# This file was auto-generated by Fern from our API Definition. + +from typing import Dict, Generic, TypeVar + +import httpx + +T = TypeVar("T") + + +class HttpResponse(Generic[T]): + _response: httpx.Response + _data: T + + def __init__(self, response: httpx.Response, data: T): + self._response = response + self._data = data + + @property + def headers(self) -> Dict[str, str]: + return dict(self._response.headers) + + @property + def data(self) -> T: + return self._data + + def close(self) -> None: + self._response.close() + + +class AsyncHttpResponse(Generic[T]): + _response: httpx.Response + _data: T + + def __init__(self, response: httpx.Response, data: T): + self._response = response + self._data = data + + @property + def headers(self) -> Dict[str, str]: + return dict(self._response.headers) + + @property + def data(self) -> T: + return self._data + + async def close(self) -> None: + await self._response.aclose() diff --git a/src/credal/core/serialization.py b/src/credal/core/serialization.py index e3d17f0..c36e865 100644 --- a/src/credal/core/serialization.py +++ b/src/credal/core/serialization.py @@ -160,7 +160,12 @@ def _convert_mapping( direction: typing.Literal["read", "write"], ) -> typing.Mapping[str, object]: converted_object: typing.Dict[str, object] = {} - annotations = typing_extensions.get_type_hints(expected_type, include_extras=True) + try: + annotations = typing_extensions.get_type_hints(expected_type, include_extras=True) + except NameError: + # The TypedDict contains a circular reference, so + # we use the __annotations__ attribute directly. + annotations = getattr(expected_type, "__annotations__", {}) aliases_to_field_names = _get_alias_to_field_name(annotations) for key, value in object_.items(): if direction == "read" and key in aliases_to_field_names: diff --git a/src/credal/document_catalog/client.py b/src/credal/document_catalog/client.py index 44f2d2f..5b7d19c 100644 --- a/src/credal/document_catalog/client.py +++ b/src/credal/document_catalog/client.py @@ -2,15 +2,13 @@ import typing from ..core.client_wrapper import SyncClientWrapper +from .raw_client import RawDocumentCatalogClient from ..core.request_options import RequestOptions from .types.upload_document_response import UploadDocumentResponse -from ..core.pydantic_utilities import parse_obj_as -from json.decoder import JSONDecodeError -from ..core.api_error import ApiError from .types.sync_source_by_url_response import SyncSourceByUrlResponse from .types.document_metadata_patch import DocumentMetadataPatch -from ..core.serialization import convert_and_respect_annotation_metadata from ..core.client_wrapper import AsyncClientWrapper +from .raw_client import AsyncRawDocumentCatalogClient # this is used as the default value for optional parameters OMIT = typing.cast(typing.Any, ...) @@ -18,7 +16,18 @@ class DocumentCatalogClient: def __init__(self, *, client_wrapper: SyncClientWrapper): - self._client_wrapper = client_wrapper + self._raw_client = RawDocumentCatalogClient(client_wrapper=client_wrapper) + + @property + def with_raw_response(self) -> RawDocumentCatalogClient: + """ + Retrieves a raw implementation of this client that returns raw responses. + + Returns + ------- + RawDocumentCatalogClient + """ + return self._raw_client def upload_document_contents( self, @@ -90,37 +99,20 @@ def upload_document_contents( upload_as_user_email="jack@credal.ai", ) """ - _response = self._client_wrapper.httpx_client.request( - "v0/catalog/uploadDocumentContents", - method="POST", - json={ - "documentName": document_name, - "documentContents": document_contents, - "allowedUsersEmailAddresses": allowed_users_email_addresses, - "uploadAsUserEmail": upload_as_user_email, - "documentExternalId": document_external_id, - "documentExternalUrl": document_external_url, - "customMetadata": custom_metadata, - "collectionId": collection_id, - "forceUpdate": force_update, - "internalPublic": internal_public, - }, + response = self._raw_client.upload_document_contents( + document_name=document_name, + document_contents=document_contents, + allowed_users_email_addresses=allowed_users_email_addresses, + upload_as_user_email=upload_as_user_email, + document_external_id=document_external_id, + document_external_url=document_external_url, + custom_metadata=custom_metadata, + collection_id=collection_id, + force_update=force_update, + internal_public=internal_public, request_options=request_options, - omit=OMIT, ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - UploadDocumentResponse, - parse_obj_as( - type_=UploadDocumentResponse, # type: ignore - object_=_response.json(), - ), - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) + return response.data def sync_source_by_url( self, *, upload_as_user_email: str, source_url: str, request_options: typing.Optional[RequestOptions] = None @@ -153,29 +145,10 @@ def sync_source_by_url( upload_as_user_email="ria@credal.ai", ) """ - _response = self._client_wrapper.httpx_client.request( - "v0/catalog/syncSourceByUrl", - method="POST", - json={ - "uploadAsUserEmail": upload_as_user_email, - "sourceUrl": source_url, - }, - request_options=request_options, - omit=OMIT, + response = self._raw_client.sync_source_by_url( + upload_as_user_email=upload_as_user_email, source_url=source_url, request_options=request_options ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - SyncSourceByUrlResponse, - parse_obj_as( - type_=SyncSourceByUrlResponse, # type: ignore - object_=_response.json(), - ), - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) + return response.data def metadata( self, @@ -229,30 +202,26 @@ def metadata( upload_as_user_email="ben@credal.ai", ) """ - _response = self._client_wrapper.httpx_client.request( - "v0/catalog/metadata", - method="PATCH", - json={ - "sources": convert_and_respect_annotation_metadata( - object_=sources, annotation=typing.Sequence[DocumentMetadataPatch], direction="write" - ), - "uploadAsUserEmail": upload_as_user_email, - }, - request_options=request_options, - omit=OMIT, + response = self._raw_client.metadata( + sources=sources, upload_as_user_email=upload_as_user_email, request_options=request_options ) - try: - if 200 <= _response.status_code < 300: - return - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) + return response.data class AsyncDocumentCatalogClient: def __init__(self, *, client_wrapper: AsyncClientWrapper): - self._client_wrapper = client_wrapper + self._raw_client = AsyncRawDocumentCatalogClient(client_wrapper=client_wrapper) + + @property + def with_raw_response(self) -> AsyncRawDocumentCatalogClient: + """ + Retrieves a raw implementation of this client that returns raw responses. + + Returns + ------- + AsyncRawDocumentCatalogClient + """ + return self._raw_client async def upload_document_contents( self, @@ -332,37 +301,20 @@ async def main() -> None: asyncio.run(main()) """ - _response = await self._client_wrapper.httpx_client.request( - "v0/catalog/uploadDocumentContents", - method="POST", - json={ - "documentName": document_name, - "documentContents": document_contents, - "allowedUsersEmailAddresses": allowed_users_email_addresses, - "uploadAsUserEmail": upload_as_user_email, - "documentExternalId": document_external_id, - "documentExternalUrl": document_external_url, - "customMetadata": custom_metadata, - "collectionId": collection_id, - "forceUpdate": force_update, - "internalPublic": internal_public, - }, + response = await self._raw_client.upload_document_contents( + document_name=document_name, + document_contents=document_contents, + allowed_users_email_addresses=allowed_users_email_addresses, + upload_as_user_email=upload_as_user_email, + document_external_id=document_external_id, + document_external_url=document_external_url, + custom_metadata=custom_metadata, + collection_id=collection_id, + force_update=force_update, + internal_public=internal_public, request_options=request_options, - omit=OMIT, ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - UploadDocumentResponse, - parse_obj_as( - type_=UploadDocumentResponse, # type: ignore - object_=_response.json(), - ), - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) + return response.data async def sync_source_by_url( self, *, upload_as_user_email: str, source_url: str, request_options: typing.Optional[RequestOptions] = None @@ -403,29 +355,10 @@ async def main() -> None: asyncio.run(main()) """ - _response = await self._client_wrapper.httpx_client.request( - "v0/catalog/syncSourceByUrl", - method="POST", - json={ - "uploadAsUserEmail": upload_as_user_email, - "sourceUrl": source_url, - }, - request_options=request_options, - omit=OMIT, + response = await self._raw_client.sync_source_by_url( + upload_as_user_email=upload_as_user_email, source_url=source_url, request_options=request_options ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - SyncSourceByUrlResponse, - parse_obj_as( - type_=SyncSourceByUrlResponse, # type: ignore - object_=_response.json(), - ), - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) + return response.data async def metadata( self, @@ -487,22 +420,7 @@ async def main() -> None: asyncio.run(main()) """ - _response = await self._client_wrapper.httpx_client.request( - "v0/catalog/metadata", - method="PATCH", - json={ - "sources": convert_and_respect_annotation_metadata( - object_=sources, annotation=typing.Sequence[DocumentMetadataPatch], direction="write" - ), - "uploadAsUserEmail": upload_as_user_email, - }, - request_options=request_options, - omit=OMIT, + response = await self._raw_client.metadata( + sources=sources, upload_as_user_email=upload_as_user_email, request_options=request_options ) - try: - if 200 <= _response.status_code < 300: - return - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) + return response.data diff --git a/src/credal/document_catalog/raw_client.py b/src/credal/document_catalog/raw_client.py new file mode 100644 index 0000000..9e293c5 --- /dev/null +++ b/src/credal/document_catalog/raw_client.py @@ -0,0 +1,378 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing +from ..core.client_wrapper import SyncClientWrapper +from ..core.request_options import RequestOptions +from ..core.http_response import HttpResponse +from .types.upload_document_response import UploadDocumentResponse +from ..core.pydantic_utilities import parse_obj_as +from json.decoder import JSONDecodeError +from ..core.api_error import ApiError +from .types.sync_source_by_url_response import SyncSourceByUrlResponse +from .types.document_metadata_patch import DocumentMetadataPatch +from ..core.serialization import convert_and_respect_annotation_metadata +from ..core.client_wrapper import AsyncClientWrapper +from ..core.http_response import AsyncHttpResponse + +# this is used as the default value for optional parameters +OMIT = typing.cast(typing.Any, ...) + + +class RawDocumentCatalogClient: + def __init__(self, *, client_wrapper: SyncClientWrapper): + self._client_wrapper = client_wrapper + + def upload_document_contents( + self, + *, + document_name: str, + document_contents: str, + allowed_users_email_addresses: typing.Sequence[str], + upload_as_user_email: str, + document_external_id: str, + document_external_url: typing.Optional[str] = OMIT, + custom_metadata: typing.Optional[typing.Optional[typing.Any]] = OMIT, + collection_id: typing.Optional[str] = OMIT, + force_update: typing.Optional[bool] = OMIT, + internal_public: typing.Optional[bool] = OMIT, + request_options: typing.Optional[RequestOptions] = None, + ) -> HttpResponse[UploadDocumentResponse]: + """ + Parameters + ---------- + document_name : str + The name of the document you want to upload. + + document_contents : str + The full LLM-formatted text contents of the document you want to upload. + + allowed_users_email_addresses : typing.Sequence[str] + Users allowed to access the document. Unlike Credal's out of the box connectors which reconcile various permissions models from 3rd party software, for custom uploads the caller is responsible for specifying who can access the document and currently flattening groups if applicable. Documents can also be marked as internal public. + + upload_as_user_email : str + [Legacy] The user on behalf of whom the document should be uploaded. In most cases, this can simply be the email of the developer making the API call. This field will be removed in the future in favor of purely specifying permissions via allowedUsersEmailAddresses. + + document_external_id : str + The external ID of the document. This is typically the ID as it exists in its original external system. Uploads to the same external ID will update the document in Credal. + + document_external_url : typing.Optional[str] + The external URL of the document you want to upload. If provided Credal will link to this URL. + + custom_metadata : typing.Optional[typing.Optional[typing.Any]] + Optional JSON representing any custom metdata for this document + + collection_id : typing.Optional[str] + If specified, document will also be added to a particular document collection + + force_update : typing.Optional[bool] + If specified, document contents will be re-uploaded and re-embedded even if the document already exists in Credal + + internal_public : typing.Optional[bool] + If specified, document will be accessible to everyone within the organization of the uploader + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[UploadDocumentResponse] + """ + _response = self._client_wrapper.httpx_client.request( + "v0/catalog/uploadDocumentContents", + method="POST", + json={ + "documentName": document_name, + "documentContents": document_contents, + "allowedUsersEmailAddresses": allowed_users_email_addresses, + "uploadAsUserEmail": upload_as_user_email, + "documentExternalId": document_external_id, + "documentExternalUrl": document_external_url, + "customMetadata": custom_metadata, + "collectionId": collection_id, + "forceUpdate": force_update, + "internalPublic": internal_public, + }, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + UploadDocumentResponse, + parse_obj_as( + type_=UploadDocumentResponse, # type: ignore + object_=_response.json(), + ), + ) + return HttpResponse(response=_response, data=_data) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, body=_response.text) + raise ApiError(status_code=_response.status_code, body=_response_json) + + def sync_source_by_url( + self, *, upload_as_user_email: str, source_url: str, request_options: typing.Optional[RequestOptions] = None + ) -> HttpResponse[SyncSourceByUrlResponse]: + """ + Sync a document from a source URL. Does not support recursive web search. Reach out to a Credal representative for access. + + Parameters + ---------- + upload_as_user_email : str + + source_url : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[SyncSourceByUrlResponse] + """ + _response = self._client_wrapper.httpx_client.request( + "v0/catalog/syncSourceByUrl", + method="POST", + json={ + "uploadAsUserEmail": upload_as_user_email, + "sourceUrl": source_url, + }, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + SyncSourceByUrlResponse, + parse_obj_as( + type_=SyncSourceByUrlResponse, # type: ignore + object_=_response.json(), + ), + ) + return HttpResponse(response=_response, data=_data) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, body=_response.text) + raise ApiError(status_code=_response.status_code, body=_response_json) + + def metadata( + self, + *, + sources: typing.Sequence[DocumentMetadataPatch], + upload_as_user_email: str, + request_options: typing.Optional[RequestOptions] = None, + ) -> HttpResponse[None]: + """ + Bulk patch metadata for documents, synced natively by Credal or manual API uploads + + Parameters + ---------- + sources : typing.Sequence[DocumentMetadataPatch] + + upload_as_user_email : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[None] + """ + _response = self._client_wrapper.httpx_client.request( + "v0/catalog/metadata", + method="PATCH", + json={ + "sources": convert_and_respect_annotation_metadata( + object_=sources, annotation=typing.Sequence[DocumentMetadataPatch], direction="write" + ), + "uploadAsUserEmail": upload_as_user_email, + }, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + return HttpResponse(response=_response, data=None) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, body=_response.text) + raise ApiError(status_code=_response.status_code, body=_response_json) + + +class AsyncRawDocumentCatalogClient: + def __init__(self, *, client_wrapper: AsyncClientWrapper): + self._client_wrapper = client_wrapper + + async def upload_document_contents( + self, + *, + document_name: str, + document_contents: str, + allowed_users_email_addresses: typing.Sequence[str], + upload_as_user_email: str, + document_external_id: str, + document_external_url: typing.Optional[str] = OMIT, + custom_metadata: typing.Optional[typing.Optional[typing.Any]] = OMIT, + collection_id: typing.Optional[str] = OMIT, + force_update: typing.Optional[bool] = OMIT, + internal_public: typing.Optional[bool] = OMIT, + request_options: typing.Optional[RequestOptions] = None, + ) -> AsyncHttpResponse[UploadDocumentResponse]: + """ + Parameters + ---------- + document_name : str + The name of the document you want to upload. + + document_contents : str + The full LLM-formatted text contents of the document you want to upload. + + allowed_users_email_addresses : typing.Sequence[str] + Users allowed to access the document. Unlike Credal's out of the box connectors which reconcile various permissions models from 3rd party software, for custom uploads the caller is responsible for specifying who can access the document and currently flattening groups if applicable. Documents can also be marked as internal public. + + upload_as_user_email : str + [Legacy] The user on behalf of whom the document should be uploaded. In most cases, this can simply be the email of the developer making the API call. This field will be removed in the future in favor of purely specifying permissions via allowedUsersEmailAddresses. + + document_external_id : str + The external ID of the document. This is typically the ID as it exists in its original external system. Uploads to the same external ID will update the document in Credal. + + document_external_url : typing.Optional[str] + The external URL of the document you want to upload. If provided Credal will link to this URL. + + custom_metadata : typing.Optional[typing.Optional[typing.Any]] + Optional JSON representing any custom metdata for this document + + collection_id : typing.Optional[str] + If specified, document will also be added to a particular document collection + + force_update : typing.Optional[bool] + If specified, document contents will be re-uploaded and re-embedded even if the document already exists in Credal + + internal_public : typing.Optional[bool] + If specified, document will be accessible to everyone within the organization of the uploader + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[UploadDocumentResponse] + """ + _response = await self._client_wrapper.httpx_client.request( + "v0/catalog/uploadDocumentContents", + method="POST", + json={ + "documentName": document_name, + "documentContents": document_contents, + "allowedUsersEmailAddresses": allowed_users_email_addresses, + "uploadAsUserEmail": upload_as_user_email, + "documentExternalId": document_external_id, + "documentExternalUrl": document_external_url, + "customMetadata": custom_metadata, + "collectionId": collection_id, + "forceUpdate": force_update, + "internalPublic": internal_public, + }, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + UploadDocumentResponse, + parse_obj_as( + type_=UploadDocumentResponse, # type: ignore + object_=_response.json(), + ), + ) + return AsyncHttpResponse(response=_response, data=_data) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, body=_response.text) + raise ApiError(status_code=_response.status_code, body=_response_json) + + async def sync_source_by_url( + self, *, upload_as_user_email: str, source_url: str, request_options: typing.Optional[RequestOptions] = None + ) -> AsyncHttpResponse[SyncSourceByUrlResponse]: + """ + Sync a document from a source URL. Does not support recursive web search. Reach out to a Credal representative for access. + + Parameters + ---------- + upload_as_user_email : str + + source_url : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[SyncSourceByUrlResponse] + """ + _response = await self._client_wrapper.httpx_client.request( + "v0/catalog/syncSourceByUrl", + method="POST", + json={ + "uploadAsUserEmail": upload_as_user_email, + "sourceUrl": source_url, + }, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + SyncSourceByUrlResponse, + parse_obj_as( + type_=SyncSourceByUrlResponse, # type: ignore + object_=_response.json(), + ), + ) + return AsyncHttpResponse(response=_response, data=_data) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, body=_response.text) + raise ApiError(status_code=_response.status_code, body=_response_json) + + async def metadata( + self, + *, + sources: typing.Sequence[DocumentMetadataPatch], + upload_as_user_email: str, + request_options: typing.Optional[RequestOptions] = None, + ) -> AsyncHttpResponse[None]: + """ + Bulk patch metadata for documents, synced natively by Credal or manual API uploads + + Parameters + ---------- + sources : typing.Sequence[DocumentMetadataPatch] + + upload_as_user_email : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[None] + """ + _response = await self._client_wrapper.httpx_client.request( + "v0/catalog/metadata", + method="PATCH", + json={ + "sources": convert_and_respect_annotation_metadata( + object_=sources, annotation=typing.Sequence[DocumentMetadataPatch], direction="write" + ), + "uploadAsUserEmail": upload_as_user_email, + }, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + return AsyncHttpResponse(response=_response, data=None) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, body=_response.text) + raise ApiError(status_code=_response.status_code, body=_response_json) diff --git a/src/credal/document_collections/client.py b/src/credal/document_collections/client.py index 4f95afd..73a9a00 100644 --- a/src/credal/document_collections/client.py +++ b/src/credal/document_collections/client.py @@ -2,19 +2,17 @@ import typing from ..core.client_wrapper import SyncClientWrapper +from .raw_client import RawDocumentCollectionsClient import uuid from ..common.types.resource_identifier import ResourceIdentifier from ..core.request_options import RequestOptions -from ..core.serialization import convert_and_respect_annotation_metadata -from json.decoder import JSONDecodeError -from ..core.api_error import ApiError from ..common.types.collaborator import Collaborator from .types.create_collection_response import CreateCollectionResponse -from ..core.pydantic_utilities import parse_obj_as from .types.delete_collection_response import DeleteCollectionResponse from .types.mongo_collection_sync_config import MongoCollectionSyncConfig from .types.mongo_collection_sync_response import MongoCollectionSyncResponse from ..core.client_wrapper import AsyncClientWrapper +from .raw_client import AsyncRawDocumentCollectionsClient # this is used as the default value for optional parameters OMIT = typing.cast(typing.Any, ...) @@ -22,7 +20,18 @@ class DocumentCollectionsClient: def __init__(self, *, client_wrapper: SyncClientWrapper): - self._client_wrapper = client_wrapper + self._raw_client = RawDocumentCollectionsClient(client_wrapper=client_wrapper) + + @property + def with_raw_response(self) -> RawDocumentCollectionsClient: + """ + Retrieves a raw implementation of this client that returns raw responses. + + Returns + ------- + RawDocumentCollectionsClient + """ + return self._raw_client def add_documents_to_collection( self, @@ -75,25 +84,10 @@ def add_documents_to_collection( ], ) """ - _response = self._client_wrapper.httpx_client.request( - "v0/documentCollections/addDocumentsToCollection", - method="POST", - json={ - "collectionId": collection_id, - "resourceIdentifiers": convert_and_respect_annotation_metadata( - object_=resource_identifiers, annotation=typing.Sequence[ResourceIdentifier], direction="write" - ), - }, - request_options=request_options, - omit=OMIT, - ) - try: - if 200 <= _response.status_code < 300: - return - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) + response = self._raw_client.add_documents_to_collection( + collection_id=collection_id, resource_identifiers=resource_identifiers, request_options=request_options + ) + return response.data def remove_documents_from_collection( self, @@ -146,25 +140,10 @@ def remove_documents_from_collection( ], ) """ - _response = self._client_wrapper.httpx_client.request( - "v0/documentCollections/removeDocumentsFromCollection", - method="DELETE", - json={ - "collectionId": collection_id, - "resourceIdentifiers": convert_and_respect_annotation_metadata( - object_=resource_identifiers, annotation=typing.Sequence[ResourceIdentifier], direction="write" - ), - }, - request_options=request_options, - omit=OMIT, - ) - try: - if 200 <= _response.status_code < 300: - return - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) + response = self._raw_client.remove_documents_from_collection( + collection_id=collection_id, resource_identifiers=resource_identifiers, request_options=request_options + ) + return response.data def create_collection( self, @@ -175,7 +154,7 @@ def create_collection( request_options: typing.Optional[RequestOptions] = None, ) -> CreateCollectionResponse: """ - Create a new copilot. The API key used will be added to the copilot for future Requests + Create a new collection. The API key used will be added to the collection for future Requests Parameters ---------- @@ -183,10 +162,10 @@ def create_collection( A descriptive name for the collection. description : str - An in depth name for the copilot's function. Useful for routing requests to the right copilot. + An in depth name for the agent's function. Useful for routing requests to the right agent. collaborators : typing.Sequence[Collaborator] - A list of collaborator emails and roles that will have access to the copilot. + A list of collaborator emails and roles that will have access to the agent. request_options : typing.Optional[RequestOptions] Request-specific configuration. @@ -214,32 +193,10 @@ def create_collection( ], ) """ - _response = self._client_wrapper.httpx_client.request( - "v0/documentCollections/createCollection", - method="POST", - json={ - "name": name, - "description": description, - "collaborators": convert_and_respect_annotation_metadata( - object_=collaborators, annotation=typing.Sequence[Collaborator], direction="write" - ), - }, - request_options=request_options, - omit=OMIT, - ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - CreateCollectionResponse, - parse_obj_as( - type_=CreateCollectionResponse, # type: ignore - object_=_response.json(), - ), - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) + response = self._raw_client.create_collection( + name=name, description=description, collaborators=collaborators, request_options=request_options + ) + return response.data def delete_collection( self, *, collection_id: uuid.UUID, request_options: typing.Optional[RequestOptions] = None @@ -273,28 +230,8 @@ def delete_collection( ), ) """ - _response = self._client_wrapper.httpx_client.request( - "v0/documentCollections/deleteCollection", - method="DELETE", - json={ - "collectionId": collection_id, - }, - request_options=request_options, - omit=OMIT, - ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - DeleteCollectionResponse, - parse_obj_as( - type_=DeleteCollectionResponse, # type: ignore - object_=_response.json(), - ), - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) + response = self._raw_client.delete_collection(collection_id=collection_id, request_options=request_options) + return response.data def create_mongo_collection_sync( self, @@ -305,7 +242,7 @@ def create_mongo_collection_sync( request_options: typing.Optional[RequestOptions] = None, ) -> MongoCollectionSyncResponse: """ - Credal lets you easily sync your MongoDB data for use in Collections and Copilots. Create a new sync from a MongoDB collection to a Credal collection. + Credal lets you easily sync your MongoDB data for use in Collections and Agents. Create a new sync from a MongoDB collection to a Credal collection. Parameters ---------- @@ -353,32 +290,10 @@ def create_mongo_collection_sync( ), ) """ - _response = self._client_wrapper.httpx_client.request( - "v0/documentCollections/mongodb/createMongoSync", - method="POST", - json={ - "collectionId": collection_id, - "mongoURI": mongo_uri, - "config": convert_and_respect_annotation_metadata( - object_=config, annotation=MongoCollectionSyncConfig, direction="write" - ), - }, - request_options=request_options, - omit=OMIT, - ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - MongoCollectionSyncResponse, - parse_obj_as( - type_=MongoCollectionSyncResponse, # type: ignore - object_=_response.json(), - ), - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) + response = self._raw_client.create_mongo_collection_sync( + collection_id=collection_id, mongo_uri=mongo_uri, config=config, request_options=request_options + ) + return response.data def update_mongo_collection_sync( self, @@ -389,7 +304,7 @@ def update_mongo_collection_sync( request_options: typing.Optional[RequestOptions] = None, ) -> MongoCollectionSyncResponse: """ - Credal lets you easily sync your MongoDB data for use in Collections and Copilots. Update an existing sync from a MongoDB collection to a Credal collection via the `mongoCredentialId`, to disambiguate between multiple potential syncs to a given collection. + Credal lets you easily sync your MongoDB data for use in Collections and Agents. Update an existing sync from a MongoDB collection to a Credal collection via the `mongoCredentialId`, to disambiguate between multiple potential syncs to a given collection. Parameters ---------- @@ -439,37 +354,26 @@ def update_mongo_collection_sync( ), ) """ - _response = self._client_wrapper.httpx_client.request( - "v0/documentCollections/mongodb/updateMongoSync", - method="POST", - json={ - "mongoCredentialId": mongo_credential_id, - "mongoURI": mongo_uri, - "config": convert_and_respect_annotation_metadata( - object_=config, annotation=MongoCollectionSyncConfig, direction="write" - ), - }, - request_options=request_options, - omit=OMIT, - ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - MongoCollectionSyncResponse, - parse_obj_as( - type_=MongoCollectionSyncResponse, # type: ignore - object_=_response.json(), - ), - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) + response = self._raw_client.update_mongo_collection_sync( + mongo_credential_id=mongo_credential_id, mongo_uri=mongo_uri, config=config, request_options=request_options + ) + return response.data class AsyncDocumentCollectionsClient: def __init__(self, *, client_wrapper: AsyncClientWrapper): - self._client_wrapper = client_wrapper + self._raw_client = AsyncRawDocumentCollectionsClient(client_wrapper=client_wrapper) + + @property + def with_raw_response(self) -> AsyncRawDocumentCollectionsClient: + """ + Retrieves a raw implementation of this client that returns raw responses. + + Returns + ------- + AsyncRawDocumentCollectionsClient + """ + return self._raw_client async def add_documents_to_collection( self, @@ -529,25 +433,10 @@ async def main() -> None: asyncio.run(main()) """ - _response = await self._client_wrapper.httpx_client.request( - "v0/documentCollections/addDocumentsToCollection", - method="POST", - json={ - "collectionId": collection_id, - "resourceIdentifiers": convert_and_respect_annotation_metadata( - object_=resource_identifiers, annotation=typing.Sequence[ResourceIdentifier], direction="write" - ), - }, - request_options=request_options, - omit=OMIT, - ) - try: - if 200 <= _response.status_code < 300: - return - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) + response = await self._raw_client.add_documents_to_collection( + collection_id=collection_id, resource_identifiers=resource_identifiers, request_options=request_options + ) + return response.data async def remove_documents_from_collection( self, @@ -607,25 +496,10 @@ async def main() -> None: asyncio.run(main()) """ - _response = await self._client_wrapper.httpx_client.request( - "v0/documentCollections/removeDocumentsFromCollection", - method="DELETE", - json={ - "collectionId": collection_id, - "resourceIdentifiers": convert_and_respect_annotation_metadata( - object_=resource_identifiers, annotation=typing.Sequence[ResourceIdentifier], direction="write" - ), - }, - request_options=request_options, - omit=OMIT, - ) - try: - if 200 <= _response.status_code < 300: - return - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) + response = await self._raw_client.remove_documents_from_collection( + collection_id=collection_id, resource_identifiers=resource_identifiers, request_options=request_options + ) + return response.data async def create_collection( self, @@ -636,7 +510,7 @@ async def create_collection( request_options: typing.Optional[RequestOptions] = None, ) -> CreateCollectionResponse: """ - Create a new copilot. The API key used will be added to the copilot for future Requests + Create a new collection. The API key used will be added to the collection for future Requests Parameters ---------- @@ -644,10 +518,10 @@ async def create_collection( A descriptive name for the collection. description : str - An in depth name for the copilot's function. Useful for routing requests to the right copilot. + An in depth name for the agent's function. Useful for routing requests to the right agent. collaborators : typing.Sequence[Collaborator] - A list of collaborator emails and roles that will have access to the copilot. + A list of collaborator emails and roles that will have access to the agent. request_options : typing.Optional[RequestOptions] Request-specific configuration. @@ -683,32 +557,10 @@ async def main() -> None: asyncio.run(main()) """ - _response = await self._client_wrapper.httpx_client.request( - "v0/documentCollections/createCollection", - method="POST", - json={ - "name": name, - "description": description, - "collaborators": convert_and_respect_annotation_metadata( - object_=collaborators, annotation=typing.Sequence[Collaborator], direction="write" - ), - }, - request_options=request_options, - omit=OMIT, - ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - CreateCollectionResponse, - parse_obj_as( - type_=CreateCollectionResponse, # type: ignore - object_=_response.json(), - ), - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) + response = await self._raw_client.create_collection( + name=name, description=description, collaborators=collaborators, request_options=request_options + ) + return response.data async def delete_collection( self, *, collection_id: uuid.UUID, request_options: typing.Optional[RequestOptions] = None @@ -749,28 +601,10 @@ async def main() -> None: asyncio.run(main()) """ - _response = await self._client_wrapper.httpx_client.request( - "v0/documentCollections/deleteCollection", - method="DELETE", - json={ - "collectionId": collection_id, - }, - request_options=request_options, - omit=OMIT, - ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - DeleteCollectionResponse, - parse_obj_as( - type_=DeleteCollectionResponse, # type: ignore - object_=_response.json(), - ), - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) + response = await self._raw_client.delete_collection( + collection_id=collection_id, request_options=request_options + ) + return response.data async def create_mongo_collection_sync( self, @@ -781,7 +615,7 @@ async def create_mongo_collection_sync( request_options: typing.Optional[RequestOptions] = None, ) -> MongoCollectionSyncResponse: """ - Credal lets you easily sync your MongoDB data for use in Collections and Copilots. Create a new sync from a MongoDB collection to a Credal collection. + Credal lets you easily sync your MongoDB data for use in Collections and Agents. Create a new sync from a MongoDB collection to a Credal collection. Parameters ---------- @@ -836,32 +670,10 @@ async def main() -> None: asyncio.run(main()) """ - _response = await self._client_wrapper.httpx_client.request( - "v0/documentCollections/mongodb/createMongoSync", - method="POST", - json={ - "collectionId": collection_id, - "mongoURI": mongo_uri, - "config": convert_and_respect_annotation_metadata( - object_=config, annotation=MongoCollectionSyncConfig, direction="write" - ), - }, - request_options=request_options, - omit=OMIT, - ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - MongoCollectionSyncResponse, - parse_obj_as( - type_=MongoCollectionSyncResponse, # type: ignore - object_=_response.json(), - ), - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) + response = await self._raw_client.create_mongo_collection_sync( + collection_id=collection_id, mongo_uri=mongo_uri, config=config, request_options=request_options + ) + return response.data async def update_mongo_collection_sync( self, @@ -872,7 +684,7 @@ async def update_mongo_collection_sync( request_options: typing.Optional[RequestOptions] = None, ) -> MongoCollectionSyncResponse: """ - Credal lets you easily sync your MongoDB data for use in Collections and Copilots. Update an existing sync from a MongoDB collection to a Credal collection via the `mongoCredentialId`, to disambiguate between multiple potential syncs to a given collection. + Credal lets you easily sync your MongoDB data for use in Collections and Agents. Update an existing sync from a MongoDB collection to a Credal collection via the `mongoCredentialId`, to disambiguate between multiple potential syncs to a given collection. Parameters ---------- @@ -929,29 +741,7 @@ async def main() -> None: asyncio.run(main()) """ - _response = await self._client_wrapper.httpx_client.request( - "v0/documentCollections/mongodb/updateMongoSync", - method="POST", - json={ - "mongoCredentialId": mongo_credential_id, - "mongoURI": mongo_uri, - "config": convert_and_respect_annotation_metadata( - object_=config, annotation=MongoCollectionSyncConfig, direction="write" - ), - }, - request_options=request_options, - omit=OMIT, - ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - MongoCollectionSyncResponse, - parse_obj_as( - type_=MongoCollectionSyncResponse, # type: ignore - object_=_response.json(), - ), - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) + response = await self._raw_client.update_mongo_collection_sync( + mongo_credential_id=mongo_credential_id, mongo_uri=mongo_uri, config=config, request_options=request_options + ) + return response.data diff --git a/src/credal/document_collections/raw_client.py b/src/credal/document_collections/raw_client.py new file mode 100644 index 0000000..87d18a3 --- /dev/null +++ b/src/credal/document_collections/raw_client.py @@ -0,0 +1,624 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing +from ..core.client_wrapper import SyncClientWrapper +import uuid +from ..common.types.resource_identifier import ResourceIdentifier +from ..core.request_options import RequestOptions +from ..core.http_response import HttpResponse +from ..core.serialization import convert_and_respect_annotation_metadata +from json.decoder import JSONDecodeError +from ..core.api_error import ApiError +from ..common.types.collaborator import Collaborator +from .types.create_collection_response import CreateCollectionResponse +from ..core.pydantic_utilities import parse_obj_as +from .types.delete_collection_response import DeleteCollectionResponse +from .types.mongo_collection_sync_config import MongoCollectionSyncConfig +from .types.mongo_collection_sync_response import MongoCollectionSyncResponse +from ..core.client_wrapper import AsyncClientWrapper +from ..core.http_response import AsyncHttpResponse + +# this is used as the default value for optional parameters +OMIT = typing.cast(typing.Any, ...) + + +class RawDocumentCollectionsClient: + def __init__(self, *, client_wrapper: SyncClientWrapper): + self._client_wrapper = client_wrapper + + def add_documents_to_collection( + self, + *, + collection_id: uuid.UUID, + resource_identifiers: typing.Sequence[ResourceIdentifier], + request_options: typing.Optional[RequestOptions] = None, + ) -> HttpResponse[None]: + """ + Add documents to a document collection. Note that the documents must already exist in the document catalog to use this endpoint. If you want to upload a new document to a collection, use the `uploadDocumentContents` endpoint. + + Parameters + ---------- + collection_id : uuid.UUID + The ID of the document collection you want to add to. + + resource_identifiers : typing.Sequence[ResourceIdentifier] + The set of resource identifier for which you want to add to the collection. + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[None] + """ + _response = self._client_wrapper.httpx_client.request( + "v0/documentCollections/addDocumentsToCollection", + method="POST", + json={ + "collectionId": collection_id, + "resourceIdentifiers": convert_and_respect_annotation_metadata( + object_=resource_identifiers, annotation=typing.Sequence[ResourceIdentifier], direction="write" + ), + }, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + return HttpResponse(response=_response, data=None) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, body=_response.text) + raise ApiError(status_code=_response.status_code, body=_response_json) + + def remove_documents_from_collection( + self, + *, + collection_id: uuid.UUID, + resource_identifiers: typing.Sequence[ResourceIdentifier], + request_options: typing.Optional[RequestOptions] = None, + ) -> HttpResponse[None]: + """ + Remove documents from a collection + + Parameters + ---------- + collection_id : uuid.UUID + The ID of the document collection you want to add to. + + resource_identifiers : typing.Sequence[ResourceIdentifier] + The set of resource identifier for which you want to remove from the collection + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[None] + """ + _response = self._client_wrapper.httpx_client.request( + "v0/documentCollections/removeDocumentsFromCollection", + method="DELETE", + json={ + "collectionId": collection_id, + "resourceIdentifiers": convert_and_respect_annotation_metadata( + object_=resource_identifiers, annotation=typing.Sequence[ResourceIdentifier], direction="write" + ), + }, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + return HttpResponse(response=_response, data=None) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, body=_response.text) + raise ApiError(status_code=_response.status_code, body=_response_json) + + def create_collection( + self, + *, + name: str, + description: str, + collaborators: typing.Sequence[Collaborator], + request_options: typing.Optional[RequestOptions] = None, + ) -> HttpResponse[CreateCollectionResponse]: + """ + Create a new collection. The API key used will be added to the collection for future Requests + + Parameters + ---------- + name : str + A descriptive name for the collection. + + description : str + An in depth name for the agent's function. Useful for routing requests to the right agent. + + collaborators : typing.Sequence[Collaborator] + A list of collaborator emails and roles that will have access to the agent. + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[CreateCollectionResponse] + """ + _response = self._client_wrapper.httpx_client.request( + "v0/documentCollections/createCollection", + method="POST", + json={ + "name": name, + "description": description, + "collaborators": convert_and_respect_annotation_metadata( + object_=collaborators, annotation=typing.Sequence[Collaborator], direction="write" + ), + }, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + CreateCollectionResponse, + parse_obj_as( + type_=CreateCollectionResponse, # type: ignore + object_=_response.json(), + ), + ) + return HttpResponse(response=_response, data=_data) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, body=_response.text) + raise ApiError(status_code=_response.status_code, body=_response_json) + + def delete_collection( + self, *, collection_id: uuid.UUID, request_options: typing.Optional[RequestOptions] = None + ) -> HttpResponse[DeleteCollectionResponse]: + """ + Delete the collection. + + Parameters + ---------- + collection_id : uuid.UUID + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[DeleteCollectionResponse] + """ + _response = self._client_wrapper.httpx_client.request( + "v0/documentCollections/deleteCollection", + method="DELETE", + json={ + "collectionId": collection_id, + }, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + DeleteCollectionResponse, + parse_obj_as( + type_=DeleteCollectionResponse, # type: ignore + object_=_response.json(), + ), + ) + return HttpResponse(response=_response, data=_data) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, body=_response.text) + raise ApiError(status_code=_response.status_code, body=_response_json) + + def create_mongo_collection_sync( + self, + *, + collection_id: uuid.UUID, + mongo_uri: str, + config: MongoCollectionSyncConfig, + request_options: typing.Optional[RequestOptions] = None, + ) -> HttpResponse[MongoCollectionSyncResponse]: + """ + Credal lets you easily sync your MongoDB data for use in Collections and Agents. Create a new sync from a MongoDB collection to a Credal collection. + + Parameters + ---------- + collection_id : uuid.UUID + + mongo_uri : str + + config : MongoCollectionSyncConfig + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[MongoCollectionSyncResponse] + """ + _response = self._client_wrapper.httpx_client.request( + "v0/documentCollections/mongodb/createMongoSync", + method="POST", + json={ + "collectionId": collection_id, + "mongoURI": mongo_uri, + "config": convert_and_respect_annotation_metadata( + object_=config, annotation=MongoCollectionSyncConfig, direction="write" + ), + }, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + MongoCollectionSyncResponse, + parse_obj_as( + type_=MongoCollectionSyncResponse, # type: ignore + object_=_response.json(), + ), + ) + return HttpResponse(response=_response, data=_data) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, body=_response.text) + raise ApiError(status_code=_response.status_code, body=_response_json) + + def update_mongo_collection_sync( + self, + *, + mongo_credential_id: uuid.UUID, + mongo_uri: str, + config: MongoCollectionSyncConfig, + request_options: typing.Optional[RequestOptions] = None, + ) -> HttpResponse[MongoCollectionSyncResponse]: + """ + Credal lets you easily sync your MongoDB data for use in Collections and Agents. Update an existing sync from a MongoDB collection to a Credal collection via the `mongoCredentialId`, to disambiguate between multiple potential syncs to a given collection. + + Parameters + ---------- + mongo_credential_id : uuid.UUID + + mongo_uri : str + + config : MongoCollectionSyncConfig + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[MongoCollectionSyncResponse] + """ + _response = self._client_wrapper.httpx_client.request( + "v0/documentCollections/mongodb/updateMongoSync", + method="POST", + json={ + "mongoCredentialId": mongo_credential_id, + "mongoURI": mongo_uri, + "config": convert_and_respect_annotation_metadata( + object_=config, annotation=MongoCollectionSyncConfig, direction="write" + ), + }, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + MongoCollectionSyncResponse, + parse_obj_as( + type_=MongoCollectionSyncResponse, # type: ignore + object_=_response.json(), + ), + ) + return HttpResponse(response=_response, data=_data) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, body=_response.text) + raise ApiError(status_code=_response.status_code, body=_response_json) + + +class AsyncRawDocumentCollectionsClient: + def __init__(self, *, client_wrapper: AsyncClientWrapper): + self._client_wrapper = client_wrapper + + async def add_documents_to_collection( + self, + *, + collection_id: uuid.UUID, + resource_identifiers: typing.Sequence[ResourceIdentifier], + request_options: typing.Optional[RequestOptions] = None, + ) -> AsyncHttpResponse[None]: + """ + Add documents to a document collection. Note that the documents must already exist in the document catalog to use this endpoint. If you want to upload a new document to a collection, use the `uploadDocumentContents` endpoint. + + Parameters + ---------- + collection_id : uuid.UUID + The ID of the document collection you want to add to. + + resource_identifiers : typing.Sequence[ResourceIdentifier] + The set of resource identifier for which you want to add to the collection. + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[None] + """ + _response = await self._client_wrapper.httpx_client.request( + "v0/documentCollections/addDocumentsToCollection", + method="POST", + json={ + "collectionId": collection_id, + "resourceIdentifiers": convert_and_respect_annotation_metadata( + object_=resource_identifiers, annotation=typing.Sequence[ResourceIdentifier], direction="write" + ), + }, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + return AsyncHttpResponse(response=_response, data=None) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, body=_response.text) + raise ApiError(status_code=_response.status_code, body=_response_json) + + async def remove_documents_from_collection( + self, + *, + collection_id: uuid.UUID, + resource_identifiers: typing.Sequence[ResourceIdentifier], + request_options: typing.Optional[RequestOptions] = None, + ) -> AsyncHttpResponse[None]: + """ + Remove documents from a collection + + Parameters + ---------- + collection_id : uuid.UUID + The ID of the document collection you want to add to. + + resource_identifiers : typing.Sequence[ResourceIdentifier] + The set of resource identifier for which you want to remove from the collection + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[None] + """ + _response = await self._client_wrapper.httpx_client.request( + "v0/documentCollections/removeDocumentsFromCollection", + method="DELETE", + json={ + "collectionId": collection_id, + "resourceIdentifiers": convert_and_respect_annotation_metadata( + object_=resource_identifiers, annotation=typing.Sequence[ResourceIdentifier], direction="write" + ), + }, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + return AsyncHttpResponse(response=_response, data=None) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, body=_response.text) + raise ApiError(status_code=_response.status_code, body=_response_json) + + async def create_collection( + self, + *, + name: str, + description: str, + collaborators: typing.Sequence[Collaborator], + request_options: typing.Optional[RequestOptions] = None, + ) -> AsyncHttpResponse[CreateCollectionResponse]: + """ + Create a new collection. The API key used will be added to the collection for future Requests + + Parameters + ---------- + name : str + A descriptive name for the collection. + + description : str + An in depth name for the agent's function. Useful for routing requests to the right agent. + + collaborators : typing.Sequence[Collaborator] + A list of collaborator emails and roles that will have access to the agent. + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[CreateCollectionResponse] + """ + _response = await self._client_wrapper.httpx_client.request( + "v0/documentCollections/createCollection", + method="POST", + json={ + "name": name, + "description": description, + "collaborators": convert_and_respect_annotation_metadata( + object_=collaborators, annotation=typing.Sequence[Collaborator], direction="write" + ), + }, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + CreateCollectionResponse, + parse_obj_as( + type_=CreateCollectionResponse, # type: ignore + object_=_response.json(), + ), + ) + return AsyncHttpResponse(response=_response, data=_data) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, body=_response.text) + raise ApiError(status_code=_response.status_code, body=_response_json) + + async def delete_collection( + self, *, collection_id: uuid.UUID, request_options: typing.Optional[RequestOptions] = None + ) -> AsyncHttpResponse[DeleteCollectionResponse]: + """ + Delete the collection. + + Parameters + ---------- + collection_id : uuid.UUID + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[DeleteCollectionResponse] + """ + _response = await self._client_wrapper.httpx_client.request( + "v0/documentCollections/deleteCollection", + method="DELETE", + json={ + "collectionId": collection_id, + }, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + DeleteCollectionResponse, + parse_obj_as( + type_=DeleteCollectionResponse, # type: ignore + object_=_response.json(), + ), + ) + return AsyncHttpResponse(response=_response, data=_data) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, body=_response.text) + raise ApiError(status_code=_response.status_code, body=_response_json) + + async def create_mongo_collection_sync( + self, + *, + collection_id: uuid.UUID, + mongo_uri: str, + config: MongoCollectionSyncConfig, + request_options: typing.Optional[RequestOptions] = None, + ) -> AsyncHttpResponse[MongoCollectionSyncResponse]: + """ + Credal lets you easily sync your MongoDB data for use in Collections and Agents. Create a new sync from a MongoDB collection to a Credal collection. + + Parameters + ---------- + collection_id : uuid.UUID + + mongo_uri : str + + config : MongoCollectionSyncConfig + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[MongoCollectionSyncResponse] + """ + _response = await self._client_wrapper.httpx_client.request( + "v0/documentCollections/mongodb/createMongoSync", + method="POST", + json={ + "collectionId": collection_id, + "mongoURI": mongo_uri, + "config": convert_and_respect_annotation_metadata( + object_=config, annotation=MongoCollectionSyncConfig, direction="write" + ), + }, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + MongoCollectionSyncResponse, + parse_obj_as( + type_=MongoCollectionSyncResponse, # type: ignore + object_=_response.json(), + ), + ) + return AsyncHttpResponse(response=_response, data=_data) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, body=_response.text) + raise ApiError(status_code=_response.status_code, body=_response_json) + + async def update_mongo_collection_sync( + self, + *, + mongo_credential_id: uuid.UUID, + mongo_uri: str, + config: MongoCollectionSyncConfig, + request_options: typing.Optional[RequestOptions] = None, + ) -> AsyncHttpResponse[MongoCollectionSyncResponse]: + """ + Credal lets you easily sync your MongoDB data for use in Collections and Agents. Update an existing sync from a MongoDB collection to a Credal collection via the `mongoCredentialId`, to disambiguate between multiple potential syncs to a given collection. + + Parameters + ---------- + mongo_credential_id : uuid.UUID + + mongo_uri : str + + config : MongoCollectionSyncConfig + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[MongoCollectionSyncResponse] + """ + _response = await self._client_wrapper.httpx_client.request( + "v0/documentCollections/mongodb/updateMongoSync", + method="POST", + json={ + "mongoCredentialId": mongo_credential_id, + "mongoURI": mongo_uri, + "config": convert_and_respect_annotation_metadata( + object_=config, annotation=MongoCollectionSyncConfig, direction="write" + ), + }, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + MongoCollectionSyncResponse, + parse_obj_as( + type_=MongoCollectionSyncResponse, # type: ignore + object_=_response.json(), + ), + ) + return AsyncHttpResponse(response=_response, data=_data) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, body=_response.text) + raise ApiError(status_code=_response.status_code, body=_response_json) diff --git a/src/credal/permissions_service/client.py b/src/credal/permissions_service/client.py index 8d6767f..29635af 100644 --- a/src/credal/permissions_service/client.py +++ b/src/credal/permissions_service/client.py @@ -2,17 +2,15 @@ import typing from ..core.client_wrapper import SyncClientWrapper +from .raw_client import RawPermissionsServiceClient from ..common.types.resource_identifier import ResourceIdentifier from ..core.request_options import RequestOptions from .types.check_resource_authorization_response import CheckResourceAuthorizationResponse -from ..core.serialization import convert_and_respect_annotation_metadata -from ..core.pydantic_utilities import parse_obj_as -from json.decoder import JSONDecodeError -from ..core.api_error import ApiError from .types.check_bulk_resources_authorization_response import CheckBulkResourcesAuthorizationResponse from ..common.types.resource_type import ResourceType from .types.authorized_resource_list_page import AuthorizedResourceListPage from ..core.client_wrapper import AsyncClientWrapper +from .raw_client import AsyncRawPermissionsServiceClient # this is used as the default value for optional parameters OMIT = typing.cast(typing.Any, ...) @@ -20,7 +18,18 @@ class PermissionsServiceClient: def __init__(self, *, client_wrapper: SyncClientWrapper): - self._client_wrapper = client_wrapper + self._raw_client = RawPermissionsServiceClient(client_wrapper=client_wrapper) + + @property + def with_raw_response(self) -> RawPermissionsServiceClient: + """ + Retrieves a raw implementation of this client that returns raw responses. + + Returns + ------- + RawPermissionsServiceClient + """ + return self._raw_client def check_resource_authorization_for_user( self, @@ -67,32 +76,13 @@ def check_resource_authorization_for_user( user_email="john.smith@foo.com", ) """ - _response = self._client_wrapper.httpx_client.request( - "v0/permissions/checkResourceAuthorizationForUser", - method="POST", - json={ - "resourceIdentifier": convert_and_respect_annotation_metadata( - object_=resource_identifier, annotation=ResourceIdentifier, direction="write" - ), - "userEmail": user_email, - "disableCache": disable_cache, - }, + response = self._raw_client.check_resource_authorization_for_user( + resource_identifier=resource_identifier, + user_email=user_email, + disable_cache=disable_cache, request_options=request_options, - omit=OMIT, ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - CheckResourceAuthorizationResponse, - parse_obj_as( - type_=CheckResourceAuthorizationResponse, # type: ignore - object_=_response.json(), - ), - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) + return response.data def check_bulk_resources_authorization_for_user( self, @@ -147,32 +137,13 @@ def check_bulk_resources_authorization_for_user( user_email="john.smith@foo.com", ) """ - _response = self._client_wrapper.httpx_client.request( - "v0/permissions/checkBulkResourcesAuthorizationForUser", - method="POST", - json={ - "resourceIdentifiers": convert_and_respect_annotation_metadata( - object_=resource_identifiers, annotation=typing.Sequence[ResourceIdentifier], direction="write" - ), - "userEmail": user_email, - "disableCache": disable_cache, - }, + response = self._raw_client.check_bulk_resources_authorization_for_user( + resource_identifiers=resource_identifiers, + user_email=user_email, + disable_cache=disable_cache, request_options=request_options, - omit=OMIT, ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - CheckBulkResourcesAuthorizationResponse, - parse_obj_as( - type_=CheckBulkResourcesAuthorizationResponse, # type: ignore - object_=_response.json(), - ), - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) + return response.data def list_cached_authorized_resources_for_user( self, @@ -218,36 +189,30 @@ def list_cached_authorized_resources_for_user( user_email="john.smith@foo.com", ) """ - _response = self._client_wrapper.httpx_client.request( - "v0/permissions/listCachedAuthorizedResourcesForUser", - method="POST", - json={ - "userEmail": user_email, - "resourceType": resource_type, - "limit": limit, - "offset": offset, - }, + response = self._raw_client.list_cached_authorized_resources_for_user( + user_email=user_email, + resource_type=resource_type, + limit=limit, + offset=offset, request_options=request_options, - omit=OMIT, ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - AuthorizedResourceListPage, - parse_obj_as( - type_=AuthorizedResourceListPage, # type: ignore - object_=_response.json(), - ), - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) + return response.data class AsyncPermissionsServiceClient: def __init__(self, *, client_wrapper: AsyncClientWrapper): - self._client_wrapper = client_wrapper + self._raw_client = AsyncRawPermissionsServiceClient(client_wrapper=client_wrapper) + + @property + def with_raw_response(self) -> AsyncRawPermissionsServiceClient: + """ + Retrieves a raw implementation of this client that returns raw responses. + + Returns + ------- + AsyncRawPermissionsServiceClient + """ + return self._raw_client async def check_resource_authorization_for_user( self, @@ -302,32 +267,13 @@ async def main() -> None: asyncio.run(main()) """ - _response = await self._client_wrapper.httpx_client.request( - "v0/permissions/checkResourceAuthorizationForUser", - method="POST", - json={ - "resourceIdentifier": convert_and_respect_annotation_metadata( - object_=resource_identifier, annotation=ResourceIdentifier, direction="write" - ), - "userEmail": user_email, - "disableCache": disable_cache, - }, + response = await self._raw_client.check_resource_authorization_for_user( + resource_identifier=resource_identifier, + user_email=user_email, + disable_cache=disable_cache, request_options=request_options, - omit=OMIT, ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - CheckResourceAuthorizationResponse, - parse_obj_as( - type_=CheckResourceAuthorizationResponse, # type: ignore - object_=_response.json(), - ), - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) + return response.data async def check_bulk_resources_authorization_for_user( self, @@ -390,32 +336,13 @@ async def main() -> None: asyncio.run(main()) """ - _response = await self._client_wrapper.httpx_client.request( - "v0/permissions/checkBulkResourcesAuthorizationForUser", - method="POST", - json={ - "resourceIdentifiers": convert_and_respect_annotation_metadata( - object_=resource_identifiers, annotation=typing.Sequence[ResourceIdentifier], direction="write" - ), - "userEmail": user_email, - "disableCache": disable_cache, - }, + response = await self._raw_client.check_bulk_resources_authorization_for_user( + resource_identifiers=resource_identifiers, + user_email=user_email, + disable_cache=disable_cache, request_options=request_options, - omit=OMIT, ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - CheckBulkResourcesAuthorizationResponse, - parse_obj_as( - type_=CheckBulkResourcesAuthorizationResponse, # type: ignore - object_=_response.json(), - ), - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) + return response.data async def list_cached_authorized_resources_for_user( self, @@ -469,28 +396,11 @@ async def main() -> None: asyncio.run(main()) """ - _response = await self._client_wrapper.httpx_client.request( - "v0/permissions/listCachedAuthorizedResourcesForUser", - method="POST", - json={ - "userEmail": user_email, - "resourceType": resource_type, - "limit": limit, - "offset": offset, - }, + response = await self._raw_client.list_cached_authorized_resources_for_user( + user_email=user_email, + resource_type=resource_type, + limit=limit, + offset=offset, request_options=request_options, - omit=OMIT, ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - AuthorizedResourceListPage, - parse_obj_as( - type_=AuthorizedResourceListPage, # type: ignore - object_=_response.json(), - ), - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) + return response.data diff --git a/src/credal/permissions_service/raw_client.py b/src/credal/permissions_service/raw_client.py new file mode 100644 index 0000000..7689834 --- /dev/null +++ b/src/credal/permissions_service/raw_client.py @@ -0,0 +1,378 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing +from ..core.client_wrapper import SyncClientWrapper +from ..common.types.resource_identifier import ResourceIdentifier +from ..core.request_options import RequestOptions +from ..core.http_response import HttpResponse +from .types.check_resource_authorization_response import CheckResourceAuthorizationResponse +from ..core.serialization import convert_and_respect_annotation_metadata +from ..core.pydantic_utilities import parse_obj_as +from json.decoder import JSONDecodeError +from ..core.api_error import ApiError +from .types.check_bulk_resources_authorization_response import CheckBulkResourcesAuthorizationResponse +from ..common.types.resource_type import ResourceType +from .types.authorized_resource_list_page import AuthorizedResourceListPage +from ..core.client_wrapper import AsyncClientWrapper +from ..core.http_response import AsyncHttpResponse + +# this is used as the default value for optional parameters +OMIT = typing.cast(typing.Any, ...) + + +class RawPermissionsServiceClient: + def __init__(self, *, client_wrapper: SyncClientWrapper): + self._client_wrapper = client_wrapper + + def check_resource_authorization_for_user( + self, + *, + resource_identifier: ResourceIdentifier, + user_email: str, + disable_cache: typing.Optional[bool] = OMIT, + request_options: typing.Optional[RequestOptions] = None, + ) -> HttpResponse[CheckResourceAuthorizationResponse]: + """ + Admin endpoint to check whether the specified user is authorized to read the specified resource. + + Parameters + ---------- + resource_identifier : ResourceIdentifier + The resource identifier for which you want to check authorization. + + user_email : str + The user email to check authorization for. + + disable_cache : typing.Optional[bool] + If specified, Credal will bypass the permissions cache and check current permissions for this resource + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[CheckResourceAuthorizationResponse] + """ + _response = self._client_wrapper.httpx_client.request( + "v0/permissions/checkResourceAuthorizationForUser", + method="POST", + json={ + "resourceIdentifier": convert_and_respect_annotation_metadata( + object_=resource_identifier, annotation=ResourceIdentifier, direction="write" + ), + "userEmail": user_email, + "disableCache": disable_cache, + }, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + CheckResourceAuthorizationResponse, + parse_obj_as( + type_=CheckResourceAuthorizationResponse, # type: ignore + object_=_response.json(), + ), + ) + return HttpResponse(response=_response, data=_data) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, body=_response.text) + raise ApiError(status_code=_response.status_code, body=_response_json) + + def check_bulk_resources_authorization_for_user( + self, + *, + resource_identifiers: typing.Sequence[ResourceIdentifier], + user_email: str, + disable_cache: typing.Optional[bool] = OMIT, + request_options: typing.Optional[RequestOptions] = None, + ) -> HttpResponse[CheckBulkResourcesAuthorizationResponse]: + """ + Admin endpoint to check whether the specified user is authorized to read the specified set of resources. + + Parameters + ---------- + resource_identifiers : typing.Sequence[ResourceIdentifier] + The set of resource identifier for which you want to check authorization. Currently limited to 20 resources. + + user_email : str + The user email to check authorization for. + + disable_cache : typing.Optional[bool] + If specified, Credal will bypass the permissions cache and check current permissions for all resources specified. + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[CheckBulkResourcesAuthorizationResponse] + """ + _response = self._client_wrapper.httpx_client.request( + "v0/permissions/checkBulkResourcesAuthorizationForUser", + method="POST", + json={ + "resourceIdentifiers": convert_and_respect_annotation_metadata( + object_=resource_identifiers, annotation=typing.Sequence[ResourceIdentifier], direction="write" + ), + "userEmail": user_email, + "disableCache": disable_cache, + }, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + CheckBulkResourcesAuthorizationResponse, + parse_obj_as( + type_=CheckBulkResourcesAuthorizationResponse, # type: ignore + object_=_response.json(), + ), + ) + return HttpResponse(response=_response, data=_data) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, body=_response.text) + raise ApiError(status_code=_response.status_code, body=_response_json) + + def list_cached_authorized_resources_for_user( + self, + *, + user_email: str, + resource_type: typing.Optional[ResourceType] = OMIT, + limit: typing.Optional[int] = OMIT, + offset: typing.Optional[int] = OMIT, + request_options: typing.Optional[RequestOptions] = None, + ) -> HttpResponse[AuthorizedResourceListPage]: + """ + Admin endpoint to list all resources that the specified user is authorized to read. Note this endpoint returns cached results and may not be up-to-date. You can use the checkResourceAuthorizationForUser endpoint with disableCache set to true to get the most up-to-date results. + + Parameters + ---------- + user_email : str + The user email to list authorized resources for. + + resource_type : typing.Optional[ResourceType] + The type of resource you want to list. If not specified, all resource types will be listed. + + limit : typing.Optional[int] + The maximum number of resources to return. Defaults to 100. + + offset : typing.Optional[int] + The offset to use for pagination. If not specified, the first page of results will be returned. + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[AuthorizedResourceListPage] + """ + _response = self._client_wrapper.httpx_client.request( + "v0/permissions/listCachedAuthorizedResourcesForUser", + method="POST", + json={ + "userEmail": user_email, + "resourceType": resource_type, + "limit": limit, + "offset": offset, + }, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + AuthorizedResourceListPage, + parse_obj_as( + type_=AuthorizedResourceListPage, # type: ignore + object_=_response.json(), + ), + ) + return HttpResponse(response=_response, data=_data) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, body=_response.text) + raise ApiError(status_code=_response.status_code, body=_response_json) + + +class AsyncRawPermissionsServiceClient: + def __init__(self, *, client_wrapper: AsyncClientWrapper): + self._client_wrapper = client_wrapper + + async def check_resource_authorization_for_user( + self, + *, + resource_identifier: ResourceIdentifier, + user_email: str, + disable_cache: typing.Optional[bool] = OMIT, + request_options: typing.Optional[RequestOptions] = None, + ) -> AsyncHttpResponse[CheckResourceAuthorizationResponse]: + """ + Admin endpoint to check whether the specified user is authorized to read the specified resource. + + Parameters + ---------- + resource_identifier : ResourceIdentifier + The resource identifier for which you want to check authorization. + + user_email : str + The user email to check authorization for. + + disable_cache : typing.Optional[bool] + If specified, Credal will bypass the permissions cache and check current permissions for this resource + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[CheckResourceAuthorizationResponse] + """ + _response = await self._client_wrapper.httpx_client.request( + "v0/permissions/checkResourceAuthorizationForUser", + method="POST", + json={ + "resourceIdentifier": convert_and_respect_annotation_metadata( + object_=resource_identifier, annotation=ResourceIdentifier, direction="write" + ), + "userEmail": user_email, + "disableCache": disable_cache, + }, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + CheckResourceAuthorizationResponse, + parse_obj_as( + type_=CheckResourceAuthorizationResponse, # type: ignore + object_=_response.json(), + ), + ) + return AsyncHttpResponse(response=_response, data=_data) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, body=_response.text) + raise ApiError(status_code=_response.status_code, body=_response_json) + + async def check_bulk_resources_authorization_for_user( + self, + *, + resource_identifiers: typing.Sequence[ResourceIdentifier], + user_email: str, + disable_cache: typing.Optional[bool] = OMIT, + request_options: typing.Optional[RequestOptions] = None, + ) -> AsyncHttpResponse[CheckBulkResourcesAuthorizationResponse]: + """ + Admin endpoint to check whether the specified user is authorized to read the specified set of resources. + + Parameters + ---------- + resource_identifiers : typing.Sequence[ResourceIdentifier] + The set of resource identifier for which you want to check authorization. Currently limited to 20 resources. + + user_email : str + The user email to check authorization for. + + disable_cache : typing.Optional[bool] + If specified, Credal will bypass the permissions cache and check current permissions for all resources specified. + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[CheckBulkResourcesAuthorizationResponse] + """ + _response = await self._client_wrapper.httpx_client.request( + "v0/permissions/checkBulkResourcesAuthorizationForUser", + method="POST", + json={ + "resourceIdentifiers": convert_and_respect_annotation_metadata( + object_=resource_identifiers, annotation=typing.Sequence[ResourceIdentifier], direction="write" + ), + "userEmail": user_email, + "disableCache": disable_cache, + }, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + CheckBulkResourcesAuthorizationResponse, + parse_obj_as( + type_=CheckBulkResourcesAuthorizationResponse, # type: ignore + object_=_response.json(), + ), + ) + return AsyncHttpResponse(response=_response, data=_data) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, body=_response.text) + raise ApiError(status_code=_response.status_code, body=_response_json) + + async def list_cached_authorized_resources_for_user( + self, + *, + user_email: str, + resource_type: typing.Optional[ResourceType] = OMIT, + limit: typing.Optional[int] = OMIT, + offset: typing.Optional[int] = OMIT, + request_options: typing.Optional[RequestOptions] = None, + ) -> AsyncHttpResponse[AuthorizedResourceListPage]: + """ + Admin endpoint to list all resources that the specified user is authorized to read. Note this endpoint returns cached results and may not be up-to-date. You can use the checkResourceAuthorizationForUser endpoint with disableCache set to true to get the most up-to-date results. + + Parameters + ---------- + user_email : str + The user email to list authorized resources for. + + resource_type : typing.Optional[ResourceType] + The type of resource you want to list. If not specified, all resource types will be listed. + + limit : typing.Optional[int] + The maximum number of resources to return. Defaults to 100. + + offset : typing.Optional[int] + The offset to use for pagination. If not specified, the first page of results will be returned. + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[AuthorizedResourceListPage] + """ + _response = await self._client_wrapper.httpx_client.request( + "v0/permissions/listCachedAuthorizedResourcesForUser", + method="POST", + json={ + "userEmail": user_email, + "resourceType": resource_type, + "limit": limit, + "offset": offset, + }, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + AuthorizedResourceListPage, + parse_obj_as( + type_=AuthorizedResourceListPage, # type: ignore + object_=_response.json(), + ), + ) + return AsyncHttpResponse(response=_response, data=_data) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, body=_response.text) + raise ApiError(status_code=_response.status_code, body=_response_json) diff --git a/src/credal/search/client.py b/src/credal/search/client.py index 97168e0..7efeb6e 100644 --- a/src/credal/search/client.py +++ b/src/credal/search/client.py @@ -2,16 +2,14 @@ import typing from ..core.client_wrapper import SyncClientWrapper +from .raw_client import RawSearchClient import uuid from .types.single_field_filter import SingleFieldFilter from .types.document_collection_search_options import DocumentCollectionSearchOptions from ..core.request_options import RequestOptions from .types.search_document_collection_response import SearchDocumentCollectionResponse -from ..core.serialization import convert_and_respect_annotation_metadata -from ..core.pydantic_utilities import parse_obj_as -from json.decoder import JSONDecodeError -from ..core.api_error import ApiError from ..core.client_wrapper import AsyncClientWrapper +from .raw_client import AsyncRawSearchClient # this is used as the default value for optional parameters OMIT = typing.cast(typing.Any, ...) @@ -19,7 +17,18 @@ class SearchClient: def __init__(self, *, client_wrapper: SyncClientWrapper): - self._client_wrapper = client_wrapper + self._raw_client = RawSearchClient(client_wrapper=client_wrapper) + + @property + def with_raw_response(self) -> RawSearchClient: + """ + Retrieves a raw implementation of this client that returns raw responses. + + Returns + ------- + RawSearchClient + """ + return self._raw_client def search_document_collection( self, @@ -92,42 +101,32 @@ def search_document_collection( ), ) """ - _response = self._client_wrapper.httpx_client.request( - "v0/search/searchDocumentCollection", - method="POST", - json={ - "collectionId": collection_id, - "searchQuery": search_query, - "userEmail": user_email, - "structuredQueryFilters": convert_and_respect_annotation_metadata( - object_=structured_query_filters, annotation=typing.Sequence[SingleFieldFilter], direction="write" - ), - "searchOptions": convert_and_respect_annotation_metadata( - object_=search_options, annotation=DocumentCollectionSearchOptions, direction="write" - ), - "metadataFilterExpression": metadata_filter_expression, - }, + response = self._raw_client.search_document_collection( + collection_id=collection_id, + search_query=search_query, + user_email=user_email, + structured_query_filters=structured_query_filters, + search_options=search_options, + metadata_filter_expression=metadata_filter_expression, request_options=request_options, - omit=OMIT, ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - SearchDocumentCollectionResponse, - parse_obj_as( - type_=SearchDocumentCollectionResponse, # type: ignore - object_=_response.json(), - ), - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) + return response.data class AsyncSearchClient: def __init__(self, *, client_wrapper: AsyncClientWrapper): - self._client_wrapper = client_wrapper + self._raw_client = AsyncRawSearchClient(client_wrapper=client_wrapper) + + @property + def with_raw_response(self) -> AsyncRawSearchClient: + """ + Retrieves a raw implementation of this client that returns raw responses. + + Returns + ------- + AsyncRawSearchClient + """ + return self._raw_client async def search_document_collection( self, @@ -207,34 +206,13 @@ async def main() -> None: asyncio.run(main()) """ - _response = await self._client_wrapper.httpx_client.request( - "v0/search/searchDocumentCollection", - method="POST", - json={ - "collectionId": collection_id, - "searchQuery": search_query, - "userEmail": user_email, - "structuredQueryFilters": convert_and_respect_annotation_metadata( - object_=structured_query_filters, annotation=typing.Sequence[SingleFieldFilter], direction="write" - ), - "searchOptions": convert_and_respect_annotation_metadata( - object_=search_options, annotation=DocumentCollectionSearchOptions, direction="write" - ), - "metadataFilterExpression": metadata_filter_expression, - }, + response = await self._raw_client.search_document_collection( + collection_id=collection_id, + search_query=search_query, + user_email=user_email, + structured_query_filters=structured_query_filters, + search_options=search_options, + metadata_filter_expression=metadata_filter_expression, request_options=request_options, - omit=OMIT, ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - SearchDocumentCollectionResponse, - parse_obj_as( - type_=SearchDocumentCollectionResponse, # type: ignore - object_=_response.json(), - ), - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) + return response.data diff --git a/src/credal/search/raw_client.py b/src/credal/search/raw_client.py new file mode 100644 index 0000000..1cd9c24 --- /dev/null +++ b/src/credal/search/raw_client.py @@ -0,0 +1,171 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing +from ..core.client_wrapper import SyncClientWrapper +import uuid +from .types.single_field_filter import SingleFieldFilter +from .types.document_collection_search_options import DocumentCollectionSearchOptions +from ..core.request_options import RequestOptions +from ..core.http_response import HttpResponse +from .types.search_document_collection_response import SearchDocumentCollectionResponse +from ..core.serialization import convert_and_respect_annotation_metadata +from ..core.pydantic_utilities import parse_obj_as +from json.decoder import JSONDecodeError +from ..core.api_error import ApiError +from ..core.client_wrapper import AsyncClientWrapper +from ..core.http_response import AsyncHttpResponse + +# this is used as the default value for optional parameters +OMIT = typing.cast(typing.Any, ...) + + +class RawSearchClient: + def __init__(self, *, client_wrapper: SyncClientWrapper): + self._client_wrapper = client_wrapper + + def search_document_collection( + self, + *, + collection_id: uuid.UUID, + search_query: str, + user_email: str, + structured_query_filters: typing.Optional[typing.Sequence[SingleFieldFilter]] = OMIT, + search_options: typing.Optional[DocumentCollectionSearchOptions] = OMIT, + metadata_filter_expression: typing.Optional[str] = OMIT, + request_options: typing.Optional[RequestOptions] = None, + ) -> HttpResponse[SearchDocumentCollectionResponse]: + """ + Search across all documents in a document collection using the document metadata and contents. + + Parameters + ---------- + collection_id : uuid.UUID + + search_query : str + + user_email : str + The email of the user making the search request for permissions reduction. + + structured_query_filters : typing.Optional[typing.Sequence[SingleFieldFilter]] + The structured query filters to apply to the search query. + + search_options : typing.Optional[DocumentCollectionSearchOptions] + + metadata_filter_expression : typing.Optional[str] + Legacy metadata filter expression to apply to the search query. Use structuredQueryFilters instead. + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[SearchDocumentCollectionResponse] + """ + _response = self._client_wrapper.httpx_client.request( + "v0/search/searchDocumentCollection", + method="POST", + json={ + "collectionId": collection_id, + "searchQuery": search_query, + "userEmail": user_email, + "structuredQueryFilters": convert_and_respect_annotation_metadata( + object_=structured_query_filters, annotation=typing.Sequence[SingleFieldFilter], direction="write" + ), + "searchOptions": convert_and_respect_annotation_metadata( + object_=search_options, annotation=DocumentCollectionSearchOptions, direction="write" + ), + "metadataFilterExpression": metadata_filter_expression, + }, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + SearchDocumentCollectionResponse, + parse_obj_as( + type_=SearchDocumentCollectionResponse, # type: ignore + object_=_response.json(), + ), + ) + return HttpResponse(response=_response, data=_data) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, body=_response.text) + raise ApiError(status_code=_response.status_code, body=_response_json) + + +class AsyncRawSearchClient: + def __init__(self, *, client_wrapper: AsyncClientWrapper): + self._client_wrapper = client_wrapper + + async def search_document_collection( + self, + *, + collection_id: uuid.UUID, + search_query: str, + user_email: str, + structured_query_filters: typing.Optional[typing.Sequence[SingleFieldFilter]] = OMIT, + search_options: typing.Optional[DocumentCollectionSearchOptions] = OMIT, + metadata_filter_expression: typing.Optional[str] = OMIT, + request_options: typing.Optional[RequestOptions] = None, + ) -> AsyncHttpResponse[SearchDocumentCollectionResponse]: + """ + Search across all documents in a document collection using the document metadata and contents. + + Parameters + ---------- + collection_id : uuid.UUID + + search_query : str + + user_email : str + The email of the user making the search request for permissions reduction. + + structured_query_filters : typing.Optional[typing.Sequence[SingleFieldFilter]] + The structured query filters to apply to the search query. + + search_options : typing.Optional[DocumentCollectionSearchOptions] + + metadata_filter_expression : typing.Optional[str] + Legacy metadata filter expression to apply to the search query. Use structuredQueryFilters instead. + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[SearchDocumentCollectionResponse] + """ + _response = await self._client_wrapper.httpx_client.request( + "v0/search/searchDocumentCollection", + method="POST", + json={ + "collectionId": collection_id, + "searchQuery": search_query, + "userEmail": user_email, + "structuredQueryFilters": convert_and_respect_annotation_metadata( + object_=structured_query_filters, annotation=typing.Sequence[SingleFieldFilter], direction="write" + ), + "searchOptions": convert_and_respect_annotation_metadata( + object_=search_options, annotation=DocumentCollectionSearchOptions, direction="write" + ), + "metadataFilterExpression": metadata_filter_expression, + }, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + SearchDocumentCollectionResponse, + parse_obj_as( + type_=SearchDocumentCollectionResponse, # type: ignore + object_=_response.json(), + ), + ) + return AsyncHttpResponse(response=_response, data=_data) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, body=_response.text) + raise ApiError(status_code=_response.status_code, body=_response_json) diff --git a/src/credal/users/client.py b/src/credal/users/client.py index a43e4be..d123305 100644 --- a/src/credal/users/client.py +++ b/src/credal/users/client.py @@ -2,12 +2,11 @@ import typing from ..core.client_wrapper import SyncClientWrapper +from .raw_client import RawUsersClient from .types.user_metadata_patch import UserMetadataPatch from ..core.request_options import RequestOptions -from ..core.serialization import convert_and_respect_annotation_metadata -from json.decoder import JSONDecodeError -from ..core.api_error import ApiError from ..core.client_wrapper import AsyncClientWrapper +from .raw_client import AsyncRawUsersClient # this is used as the default value for optional parameters OMIT = typing.cast(typing.Any, ...) @@ -15,7 +14,18 @@ class UsersClient: def __init__(self, *, client_wrapper: SyncClientWrapper): - self._client_wrapper = client_wrapper + self._raw_client = RawUsersClient(client_wrapper=client_wrapper) + + @property + def with_raw_response(self) -> RawUsersClient: + """ + Retrieves a raw implementation of this client that returns raw responses. + + Returns + ------- + RawUsersClient + """ + return self._raw_client def metadata( self, *, request: typing.Sequence[UserMetadataPatch], request_options: typing.Optional[RequestOptions] = None @@ -55,27 +65,24 @@ def metadata( ], ) """ - _response = self._client_wrapper.httpx_client.request( - "v0/users/metadata", - method="PATCH", - json=convert_and_respect_annotation_metadata( - object_=request, annotation=typing.Sequence[UserMetadataPatch], direction="write" - ), - request_options=request_options, - omit=OMIT, - ) - try: - if 200 <= _response.status_code < 300: - return - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) + response = self._raw_client.metadata(request=request, request_options=request_options) + return response.data class AsyncUsersClient: def __init__(self, *, client_wrapper: AsyncClientWrapper): - self._client_wrapper = client_wrapper + self._raw_client = AsyncRawUsersClient(client_wrapper=client_wrapper) + + @property + def with_raw_response(self) -> AsyncRawUsersClient: + """ + Retrieves a raw implementation of this client that returns raw responses. + + Returns + ------- + AsyncRawUsersClient + """ + return self._raw_client async def metadata( self, *, request: typing.Sequence[UserMetadataPatch], request_options: typing.Optional[RequestOptions] = None @@ -123,19 +130,5 @@ async def main() -> None: asyncio.run(main()) """ - _response = await self._client_wrapper.httpx_client.request( - "v0/users/metadata", - method="PATCH", - json=convert_and_respect_annotation_metadata( - object_=request, annotation=typing.Sequence[UserMetadataPatch], direction="write" - ), - request_options=request_options, - omit=OMIT, - ) - try: - if 200 <= _response.status_code < 300: - return - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) + response = await self._raw_client.metadata(request=request, request_options=request_options) + return response.data diff --git a/src/credal/users/raw_client.py b/src/credal/users/raw_client.py new file mode 100644 index 0000000..10bf58c --- /dev/null +++ b/src/credal/users/raw_client.py @@ -0,0 +1,93 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing +from ..core.client_wrapper import SyncClientWrapper +from .types.user_metadata_patch import UserMetadataPatch +from ..core.request_options import RequestOptions +from ..core.http_response import HttpResponse +from ..core.serialization import convert_and_respect_annotation_metadata +from json.decoder import JSONDecodeError +from ..core.api_error import ApiError +from ..core.client_wrapper import AsyncClientWrapper +from ..core.http_response import AsyncHttpResponse + +# this is used as the default value for optional parameters +OMIT = typing.cast(typing.Any, ...) + + +class RawUsersClient: + def __init__(self, *, client_wrapper: SyncClientWrapper): + self._client_wrapper = client_wrapper + + def metadata( + self, *, request: typing.Sequence[UserMetadataPatch], request_options: typing.Optional[RequestOptions] = None + ) -> HttpResponse[None]: + """ + Bulk patch metadata for users + + Parameters + ---------- + request : typing.Sequence[UserMetadataPatch] + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[None] + """ + _response = self._client_wrapper.httpx_client.request( + "v0/users/metadata", + method="PATCH", + json=convert_and_respect_annotation_metadata( + object_=request, annotation=typing.Sequence[UserMetadataPatch], direction="write" + ), + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + return HttpResponse(response=_response, data=None) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, body=_response.text) + raise ApiError(status_code=_response.status_code, body=_response_json) + + +class AsyncRawUsersClient: + def __init__(self, *, client_wrapper: AsyncClientWrapper): + self._client_wrapper = client_wrapper + + async def metadata( + self, *, request: typing.Sequence[UserMetadataPatch], request_options: typing.Optional[RequestOptions] = None + ) -> AsyncHttpResponse[None]: + """ + Bulk patch metadata for users + + Parameters + ---------- + request : typing.Sequence[UserMetadataPatch] + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[None] + """ + _response = await self._client_wrapper.httpx_client.request( + "v0/users/metadata", + method="PATCH", + json=convert_and_respect_annotation_metadata( + object_=request, annotation=typing.Sequence[UserMetadataPatch], direction="write" + ), + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + return AsyncHttpResponse(response=_response, data=None) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, body=_response.text) + raise ApiError(status_code=_response.status_code, body=_response_json)