From 3ce46caa86ea5cb1eef430cb56157532dda1dbb4 Mon Sep 17 00:00:00 2001 From: stlc-bot Date: Wed, 24 Jun 2026 18:56:16 +0000 Subject: [PATCH 1/2] feat(api): api update --- .stats.yml | 2 +- api.md | 56 +- scripts/mock | 2 +- src/casedev/_client.py | 79 ++ src/casedev/resources/__init__.py | 28 + .../resources/document_templates/__init__.py | 33 + .../document_templates/document_templates.py | 541 ++++++++++ .../document_templates/from_vault_object.py | 136 +++ src/casedev/resources/linc/__init__.py | 33 + src/casedev/resources/linc/linc.py | 102 ++ src/casedev/resources/linc/v1/__init__.py | 33 + src/casedev/resources/linc/v1/sessions.py | 952 ++++++++++++++++++ src/casedev/resources/linc/v1/v1.py | 120 +++ src/casedev/resources/mail/v1/inboxes.py | 8 +- src/casedev/resources/mail/v1/v1.py | 24 +- .../media/v1/transcripts/__init__.py | 14 + .../media/v1/transcripts/retrieve.py | 199 ++++ .../media/v1/transcripts/transcripts.py | 32 + src/casedev/resources/usage/v1/v1.py | 20 + src/casedev/resources/vault/multipart.py | 292 +++++- src/casedev/resources/vault/objects.py | 287 +++++- src/casedev/resources/vault/vault.py | 56 +- .../types/document_templates/__init__.py | 3 + src/casedev/types/linc/__init__.py | 3 + src/casedev/types/linc/v1/__init__.py | 9 + .../types/linc/v1/session_create_params.py | 45 + .../linc/v1/session_ingest_events_params.py | 24 + .../linc/v1/session_retrieve_events_params.py | 24 + .../v1/session_retrieve_messages_params.py | 20 + .../types/linc/v1/session_send_rpc_params.py | 20 + .../types/media/v1/transcripts/__init__.py | 3 + .../v1/transcripts/retrieve_create_params.py | 26 + .../transcripts/retrieve_create_response.py | 37 + src/casedev/types/usage/v1_retrieve_params.py | 12 + src/casedev/types/vault/__init__.py | 8 + .../types/vault/multipart_complete_params.py | 30 + .../types/vault/multipart_init_params.py | 43 + .../types/vault/multipart_init_response.py | 23 + .../types/vault/object_append_params.py | 37 + .../types/vault/object_append_response.py | 36 + src/casedev/types/vault/object_list_params.py | 17 + .../types/vault/object_list_response.py | 3 + .../types/vault/object_retrieve_response.py | 3 + .../types/vault/object_summarize_params.py | 19 + .../types/vault/object_summarize_response.py | 27 + .../types/vault_confirm_upload_params.py | 8 + .../types/vault_confirm_upload_response.py | 15 +- src/casedev/types/vault_upload_params.py | 8 + src/casedev/types/vault_upload_response.py | 3 + .../document_templates/__init__.py | 1 + .../test_from_vault_object.py | 72 ++ tests/api_resources/linc/__init__.py | 1 + tests/api_resources/linc/v1/__init__.py | 1 + tests/api_resources/linc/v1/test_sessions.py | 758 ++++++++++++++ .../media/v1/transcripts/test_retrieve.py | 116 +++ .../api_resources/test_document_templates.py | 426 ++++++++ tests/api_resources/test_vault.py | 4 + tests/api_resources/usage/test_v1.py | 4 + tests/api_resources/vault/test_multipart.py | 283 +++++- tests/api_resources/vault/test_objects.py | 280 +++++- 60 files changed, 5444 insertions(+), 57 deletions(-) create mode 100644 src/casedev/resources/document_templates/__init__.py create mode 100644 src/casedev/resources/document_templates/document_templates.py create mode 100644 src/casedev/resources/document_templates/from_vault_object.py create mode 100644 src/casedev/resources/linc/__init__.py create mode 100644 src/casedev/resources/linc/linc.py create mode 100644 src/casedev/resources/linc/v1/__init__.py create mode 100644 src/casedev/resources/linc/v1/sessions.py create mode 100644 src/casedev/resources/linc/v1/v1.py create mode 100644 src/casedev/resources/media/v1/transcripts/retrieve.py create mode 100644 src/casedev/types/document_templates/__init__.py create mode 100644 src/casedev/types/linc/__init__.py create mode 100644 src/casedev/types/linc/v1/__init__.py create mode 100644 src/casedev/types/linc/v1/session_create_params.py create mode 100644 src/casedev/types/linc/v1/session_ingest_events_params.py create mode 100644 src/casedev/types/linc/v1/session_retrieve_events_params.py create mode 100644 src/casedev/types/linc/v1/session_retrieve_messages_params.py create mode 100644 src/casedev/types/linc/v1/session_send_rpc_params.py create mode 100644 src/casedev/types/media/v1/transcripts/retrieve_create_params.py create mode 100644 src/casedev/types/media/v1/transcripts/retrieve_create_response.py create mode 100644 src/casedev/types/vault/multipart_complete_params.py create mode 100644 src/casedev/types/vault/multipart_init_params.py create mode 100644 src/casedev/types/vault/multipart_init_response.py create mode 100644 src/casedev/types/vault/object_append_params.py create mode 100644 src/casedev/types/vault/object_append_response.py create mode 100644 src/casedev/types/vault/object_list_params.py create mode 100644 src/casedev/types/vault/object_summarize_params.py create mode 100644 src/casedev/types/vault/object_summarize_response.py create mode 100644 tests/api_resources/document_templates/__init__.py create mode 100644 tests/api_resources/document_templates/test_from_vault_object.py create mode 100644 tests/api_resources/linc/__init__.py create mode 100644 tests/api_resources/linc/v1/__init__.py create mode 100644 tests/api_resources/linc/v1/test_sessions.py create mode 100644 tests/api_resources/media/v1/transcripts/test_retrieve.py create mode 100644 tests/api_resources/test_document_templates.py diff --git a/.stats.yml b/.stats.yml index 96d65ef5..9b0d57ec 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1 +1 @@ -configured_endpoints: 199 +configured_endpoints: 219 diff --git a/api.md b/api.md index c078f6b0..0f5f8491 100644 --- a/api.md +++ b/api.md @@ -207,6 +207,23 @@ Methods: - client.database.v1.projects.get_connection(id, \*\*params) -> ProjectGetConnectionResponse - client.database.v1.projects.list_branches(id) -> ProjectListBranchesResponse +# DocumentTemplates + +Methods: + +- client.document_templates.create() -> None +- client.document_templates.retrieve(id) -> None +- client.document_templates.update(id) -> None +- client.document_templates.list() -> None +- client.document_templates.delete(id) -> None +- client.document_templates.confirm(id) -> None + +## FromVaultObject + +Methods: + +- client.document_templates.from_vault_object.create() -> None + # Format ## V1 @@ -277,6 +294,23 @@ Methods: - client.legal.v1.trademark_search(\*\*params) -> V1TrademarkSearchResponse - client.legal.v1.verify(\*\*params) -> V1VerifyResponse +# Linc + +## V1 + +### Sessions + +Methods: + +- client.linc.v1.sessions.create(\*\*params) -> None +- client.linc.v1.sessions.delete(id) -> None +- client.linc.v1.sessions.cancel(id) -> None +- client.linc.v1.sessions.ingest_events(id, \*\*params) -> None +- client.linc.v1.sessions.retrieve_events(id, \*\*params) -> None +- client.linc.v1.sessions.retrieve_messages(id, \*\*params) -> None +- client.linc.v1.sessions.retrieve_state(id) -> None +- client.linc.v1.sessions.send_rpc(path_id, \*\*params) -> None + # Matters ## V1 @@ -445,6 +479,18 @@ Methods: - client.media.v1.transcripts.search.create() -> None +#### Retrieve + +Types: + +```python +from casedev.types.media.v1.transcripts import RetrieveCreateResponse +``` + +Methods: + +- client.media.v1.transcripts.retrieve.create(\*\*params) -> RetrieveCreateResponse + # Ocr ## V1 @@ -676,13 +722,15 @@ Methods: Types: ```python -from casedev.types.vault import MultipartGetPartURLsResponse +from casedev.types.vault import MultipartGetPartURLsResponse, MultipartInitResponse ``` Methods: - client.vault.multipart.abort(id, \*\*params) -> None +- client.vault.multipart.complete(id, \*\*params) -> None - client.vault.multipart.get_part_urls(id, \*\*params) -> MultipartGetPartURLsResponse +- client.vault.multipart.init(id, \*\*params) -> MultipartInitResponse ## Objects @@ -694,12 +742,14 @@ from casedev.types.vault import ( ObjectUpdateResponse, ObjectListResponse, ObjectDeleteResponse, + ObjectAppendResponse, ObjectCreatePresignedURLResponse, ObjectGetChunksResponse, ObjectGetOcrWordsResponse, ObjectGetPagesResponse, ObjectGetSummarizeJobResponse, ObjectGetTextResponse, + ObjectSummarizeResponse, ) ``` @@ -707,8 +757,9 @@ Methods: - client.vault.objects.retrieve(object_id, \*, id) -> ObjectRetrieveResponse - client.vault.objects.update(object_id, \*, id, \*\*params) -> ObjectUpdateResponse -- client.vault.objects.list(id) -> ObjectListResponse +- client.vault.objects.list(id, \*\*params) -> ObjectListResponse - client.vault.objects.delete(object_id, \*, id, \*\*params) -> ObjectDeleteResponse +- client.vault.objects.append(object_id, \*, id, \*\*params) -> ObjectAppendResponse - client.vault.objects.create_presigned_url(object_id, \*, id, \*\*params) -> ObjectCreatePresignedURLResponse - client.vault.objects.download(object_id, \*, id) -> BinaryAPIResponse - client.vault.objects.get_chunks(object_id, \*, id, \*\*params) -> ObjectGetChunksResponse @@ -716,6 +767,7 @@ Methods: - client.vault.objects.get_pages(object_id, \*, id, \*\*params) -> ObjectGetPagesResponse - client.vault.objects.get_summarize_job(job_id, \*, id, object_id) -> ObjectGetSummarizeJobResponse - client.vault.objects.get_text(object_id, \*, id) -> ObjectGetTextResponse +- client.vault.objects.summarize(object_id, \*, id, \*\*params) -> ObjectSummarizeResponse ## Memory diff --git a/scripts/mock b/scripts/mock index 8291c9ea..1ee552a4 100755 --- a/scripts/mock +++ b/scripts/mock @@ -11,7 +11,7 @@ elif [ -n "$STAINLESS_OPENAPI_SPEC_URL" ]; then URL="$STAINLESS_OPENAPI_SPEC_URL" else # Embedded OpenAPI spec (base64-encoded, gzipped) - EMBEDDED_SPEC="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" + EMBEDDED_SPEC="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" SPEC_TMPFILE="$(mktemp)" trap 'rm -f "$SPEC_TMPFILE"' EXIT echo "$EMBEDDED_SPEC" | base64 --decode | gunzip > "$SPEC_TMPFILE" diff --git a/src/casedev/_client.py b/src/casedev/_client.py index 42aa532d..487f628f 100644 --- a/src/casedev/_client.py +++ b/src/casedev/_client.py @@ -38,6 +38,7 @@ from .resources import ( llm, ocr, + linc, mail, agent, legal, @@ -57,10 +58,12 @@ webhooks, privilege, translate, + document_templates, ) from .resources.system import SystemResource, AsyncSystemResource from .resources.llm.llm import LlmResource, AsyncLlmResource from .resources.ocr.ocr import OcrResource, AsyncOcrResource + from .resources.linc.linc import LincResource, AsyncLincResource from .resources.mail.mail import MailResource, AsyncMailResource from .resources.agent.agent import AgentResource, AsyncAgentResource from .resources.legal.legal import LegalResource, AsyncLegalResource @@ -79,6 +82,10 @@ from .resources.webhooks.webhooks import WebhooksResource, AsyncWebhooksResource from .resources.privilege.privilege import PrivilegeResource, AsyncPrivilegeResource from .resources.translate.translate import TranslateResource, AsyncTranslateResource + from .resources.document_templates.document_templates import ( + DocumentTemplatesResource, + AsyncDocumentTemplatesResource, + ) __all__ = [ "ENVIRONMENTS", @@ -211,6 +218,12 @@ def database(self) -> DatabaseResource: return DatabaseResource(self) + @cached_property + def document_templates(self) -> DocumentTemplatesResource: + from .resources.document_templates import DocumentTemplatesResource + + return DocumentTemplatesResource(self) + @cached_property def format(self) -> FormatResource: from .resources.format import FormatResource @@ -223,6 +236,12 @@ def legal(self) -> LegalResource: return LegalResource(self) + @cached_property + def linc(self) -> LincResource: + from .resources.linc import LincResource + + return LincResource(self) + @cached_property def matters(self) -> MattersResource: from .resources.matters import MattersResource @@ -544,6 +563,12 @@ def database(self) -> AsyncDatabaseResource: return AsyncDatabaseResource(self) + @cached_property + def document_templates(self) -> AsyncDocumentTemplatesResource: + from .resources.document_templates import AsyncDocumentTemplatesResource + + return AsyncDocumentTemplatesResource(self) + @cached_property def format(self) -> AsyncFormatResource: from .resources.format import AsyncFormatResource @@ -556,6 +581,12 @@ def legal(self) -> AsyncLegalResource: return AsyncLegalResource(self) + @cached_property + def linc(self) -> AsyncLincResource: + from .resources.linc import AsyncLincResource + + return AsyncLincResource(self) + @cached_property def matters(self) -> AsyncMattersResource: from .resources.matters import AsyncMattersResource @@ -795,6 +826,12 @@ def database(self) -> database.DatabaseResourceWithRawResponse: return DatabaseResourceWithRawResponse(self._client.database) + @cached_property + def document_templates(self) -> document_templates.DocumentTemplatesResourceWithRawResponse: + from .resources.document_templates import DocumentTemplatesResourceWithRawResponse + + return DocumentTemplatesResourceWithRawResponse(self._client.document_templates) + @cached_property def format(self) -> format.FormatResourceWithRawResponse: from .resources.format import FormatResourceWithRawResponse @@ -807,6 +844,12 @@ def legal(self) -> legal.LegalResourceWithRawResponse: return LegalResourceWithRawResponse(self._client.legal) + @cached_property + def linc(self) -> linc.LincResourceWithRawResponse: + from .resources.linc import LincResourceWithRawResponse + + return LincResourceWithRawResponse(self._client.linc) + @cached_property def matters(self) -> matters.MattersResourceWithRawResponse: from .resources.matters import MattersResourceWithRawResponse @@ -932,6 +975,12 @@ def database(self) -> database.AsyncDatabaseResourceWithRawResponse: return AsyncDatabaseResourceWithRawResponse(self._client.database) + @cached_property + def document_templates(self) -> document_templates.AsyncDocumentTemplatesResourceWithRawResponse: + from .resources.document_templates import AsyncDocumentTemplatesResourceWithRawResponse + + return AsyncDocumentTemplatesResourceWithRawResponse(self._client.document_templates) + @cached_property def format(self) -> format.AsyncFormatResourceWithRawResponse: from .resources.format import AsyncFormatResourceWithRawResponse @@ -944,6 +993,12 @@ def legal(self) -> legal.AsyncLegalResourceWithRawResponse: return AsyncLegalResourceWithRawResponse(self._client.legal) + @cached_property + def linc(self) -> linc.AsyncLincResourceWithRawResponse: + from .resources.linc import AsyncLincResourceWithRawResponse + + return AsyncLincResourceWithRawResponse(self._client.linc) + @cached_property def matters(self) -> matters.AsyncMattersResourceWithRawResponse: from .resources.matters import AsyncMattersResourceWithRawResponse @@ -1069,6 +1124,12 @@ def database(self) -> database.DatabaseResourceWithStreamingResponse: return DatabaseResourceWithStreamingResponse(self._client.database) + @cached_property + def document_templates(self) -> document_templates.DocumentTemplatesResourceWithStreamingResponse: + from .resources.document_templates import DocumentTemplatesResourceWithStreamingResponse + + return DocumentTemplatesResourceWithStreamingResponse(self._client.document_templates) + @cached_property def format(self) -> format.FormatResourceWithStreamingResponse: from .resources.format import FormatResourceWithStreamingResponse @@ -1081,6 +1142,12 @@ def legal(self) -> legal.LegalResourceWithStreamingResponse: return LegalResourceWithStreamingResponse(self._client.legal) + @cached_property + def linc(self) -> linc.LincResourceWithStreamingResponse: + from .resources.linc import LincResourceWithStreamingResponse + + return LincResourceWithStreamingResponse(self._client.linc) + @cached_property def matters(self) -> matters.MattersResourceWithStreamingResponse: from .resources.matters import MattersResourceWithStreamingResponse @@ -1206,6 +1273,12 @@ def database(self) -> database.AsyncDatabaseResourceWithStreamingResponse: return AsyncDatabaseResourceWithStreamingResponse(self._client.database) + @cached_property + def document_templates(self) -> document_templates.AsyncDocumentTemplatesResourceWithStreamingResponse: + from .resources.document_templates import AsyncDocumentTemplatesResourceWithStreamingResponse + + return AsyncDocumentTemplatesResourceWithStreamingResponse(self._client.document_templates) + @cached_property def format(self) -> format.AsyncFormatResourceWithStreamingResponse: from .resources.format import AsyncFormatResourceWithStreamingResponse @@ -1218,6 +1291,12 @@ def legal(self) -> legal.AsyncLegalResourceWithStreamingResponse: return AsyncLegalResourceWithStreamingResponse(self._client.legal) + @cached_property + def linc(self) -> linc.AsyncLincResourceWithStreamingResponse: + from .resources.linc import AsyncLincResourceWithStreamingResponse + + return AsyncLincResourceWithStreamingResponse(self._client.linc) + @cached_property def matters(self) -> matters.AsyncMattersResourceWithStreamingResponse: from .resources.matters import AsyncMattersResourceWithStreamingResponse diff --git a/src/casedev/resources/__init__.py b/src/casedev/resources/__init__.py index 0f0b14f6..040fbc50 100644 --- a/src/casedev/resources/__init__.py +++ b/src/casedev/resources/__init__.py @@ -16,6 +16,14 @@ OcrResourceWithStreamingResponse, AsyncOcrResourceWithStreamingResponse, ) +from .linc import ( + LincResource, + AsyncLincResource, + LincResourceWithRawResponse, + AsyncLincResourceWithRawResponse, + LincResourceWithStreamingResponse, + AsyncLincResourceWithStreamingResponse, +) from .mail import ( MailResource, AsyncMailResource, @@ -168,6 +176,14 @@ TranslateResourceWithStreamingResponse, AsyncTranslateResourceWithStreamingResponse, ) +from .document_templates import ( + DocumentTemplatesResource, + AsyncDocumentTemplatesResource, + DocumentTemplatesResourceWithRawResponse, + AsyncDocumentTemplatesResourceWithRawResponse, + DocumentTemplatesResourceWithStreamingResponse, + AsyncDocumentTemplatesResourceWithStreamingResponse, +) __all__ = [ "AgentResource", @@ -194,6 +210,12 @@ "AsyncDatabaseResourceWithRawResponse", "DatabaseResourceWithStreamingResponse", "AsyncDatabaseResourceWithStreamingResponse", + "DocumentTemplatesResource", + "AsyncDocumentTemplatesResource", + "DocumentTemplatesResourceWithRawResponse", + "AsyncDocumentTemplatesResourceWithRawResponse", + "DocumentTemplatesResourceWithStreamingResponse", + "AsyncDocumentTemplatesResourceWithStreamingResponse", "FormatResource", "AsyncFormatResource", "FormatResourceWithRawResponse", @@ -206,6 +228,12 @@ "AsyncLegalResourceWithRawResponse", "LegalResourceWithStreamingResponse", "AsyncLegalResourceWithStreamingResponse", + "LincResource", + "AsyncLincResource", + "LincResourceWithRawResponse", + "AsyncLincResourceWithRawResponse", + "LincResourceWithStreamingResponse", + "AsyncLincResourceWithStreamingResponse", "MattersResource", "AsyncMattersResource", "MattersResourceWithRawResponse", diff --git a/src/casedev/resources/document_templates/__init__.py b/src/casedev/resources/document_templates/__init__.py new file mode 100644 index 00000000..26ec550b --- /dev/null +++ b/src/casedev/resources/document_templates/__init__.py @@ -0,0 +1,33 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from .from_vault_object import ( + FromVaultObjectResource, + AsyncFromVaultObjectResource, + FromVaultObjectResourceWithRawResponse, + AsyncFromVaultObjectResourceWithRawResponse, + FromVaultObjectResourceWithStreamingResponse, + AsyncFromVaultObjectResourceWithStreamingResponse, +) +from .document_templates import ( + DocumentTemplatesResource, + AsyncDocumentTemplatesResource, + DocumentTemplatesResourceWithRawResponse, + AsyncDocumentTemplatesResourceWithRawResponse, + DocumentTemplatesResourceWithStreamingResponse, + AsyncDocumentTemplatesResourceWithStreamingResponse, +) + +__all__ = [ + "FromVaultObjectResource", + "AsyncFromVaultObjectResource", + "FromVaultObjectResourceWithRawResponse", + "AsyncFromVaultObjectResourceWithRawResponse", + "FromVaultObjectResourceWithStreamingResponse", + "AsyncFromVaultObjectResourceWithStreamingResponse", + "DocumentTemplatesResource", + "AsyncDocumentTemplatesResource", + "DocumentTemplatesResourceWithRawResponse", + "AsyncDocumentTemplatesResourceWithRawResponse", + "DocumentTemplatesResourceWithStreamingResponse", + "AsyncDocumentTemplatesResourceWithStreamingResponse", +] diff --git a/src/casedev/resources/document_templates/document_templates.py b/src/casedev/resources/document_templates/document_templates.py new file mode 100644 index 00000000..a0008124 --- /dev/null +++ b/src/casedev/resources/document_templates/document_templates.py @@ -0,0 +1,541 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +import httpx + +from ..._types import Body, Query, Headers, NoneType, NotGiven, not_given +from ..._utils import path_template +from ..._compat import cached_property +from ..._resource import SyncAPIResource, AsyncAPIResource +from ..._response import ( + to_raw_response_wrapper, + to_streamed_response_wrapper, + async_to_raw_response_wrapper, + async_to_streamed_response_wrapper, +) +from ..._base_client import make_request_options +from .from_vault_object import ( + FromVaultObjectResource, + AsyncFromVaultObjectResource, + FromVaultObjectResourceWithRawResponse, + AsyncFromVaultObjectResourceWithRawResponse, + FromVaultObjectResourceWithStreamingResponse, + AsyncFromVaultObjectResourceWithStreamingResponse, +) + +__all__ = ["DocumentTemplatesResource", "AsyncDocumentTemplatesResource"] + + +class DocumentTemplatesResource(SyncAPIResource): + @cached_property + def from_vault_object(self) -> FromVaultObjectResource: + return FromVaultObjectResource(self._client) + + @cached_property + def with_raw_response(self) -> DocumentTemplatesResourceWithRawResponse: + """ + This property can be used as a prefix for any HTTP method call to return + the raw response object instead of the parsed content. + + For more information, see https://www.github.com/CaseMark/casedev-python#accessing-raw-response-data-eg-headers + """ + return DocumentTemplatesResourceWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> DocumentTemplatesResourceWithStreamingResponse: + """ + An alternative to `.with_raw_response` that doesn't eagerly read the response body. + + For more information, see https://www.github.com/CaseMark/casedev-python#with_streaming_response + """ + return DocumentTemplatesResourceWithStreamingResponse(self) + + def create( + self, + *, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> None: + """Create document template upload""" + extra_headers = {"Accept": "*/*", **(extra_headers or {})} + return self._post( + "/document-templates", + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=NoneType, + ) + + def retrieve( + self, + id: str, + *, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> None: + """ + Get document template + + Args: + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + if not id: + raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") + extra_headers = {"Accept": "*/*", **(extra_headers or {})} + return self._get( + path_template("/document-templates/{id}", id=id), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=NoneType, + ) + + def update( + self, + id: str, + *, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> None: + """ + Update document template metadata + + Args: + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + if not id: + raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") + extra_headers = {"Accept": "*/*", **(extra_headers or {})} + return self._patch( + path_template("/document-templates/{id}", id=id), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=NoneType, + ) + + def list( + self, + *, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> None: + """List document templates""" + extra_headers = {"Accept": "*/*", **(extra_headers or {})} + return self._get( + "/document-templates", + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=NoneType, + ) + + def delete( + self, + id: str, + *, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> None: + """ + Delete document template + + Args: + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + if not id: + raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") + extra_headers = {"Accept": "*/*", **(extra_headers or {})} + return self._delete( + path_template("/document-templates/{id}", id=id), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=NoneType, + ) + + def confirm( + self, + id: str, + *, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> None: + """ + Confirm document template upload + + Args: + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + if not id: + raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") + extra_headers = {"Accept": "*/*", **(extra_headers or {})} + return self._post( + path_template("/document-templates/{id}/confirm", id=id), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=NoneType, + ) + + +class AsyncDocumentTemplatesResource(AsyncAPIResource): + @cached_property + def from_vault_object(self) -> AsyncFromVaultObjectResource: + return AsyncFromVaultObjectResource(self._client) + + @cached_property + def with_raw_response(self) -> AsyncDocumentTemplatesResourceWithRawResponse: + """ + This property can be used as a prefix for any HTTP method call to return + the raw response object instead of the parsed content. + + For more information, see https://www.github.com/CaseMark/casedev-python#accessing-raw-response-data-eg-headers + """ + return AsyncDocumentTemplatesResourceWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> AsyncDocumentTemplatesResourceWithStreamingResponse: + """ + An alternative to `.with_raw_response` that doesn't eagerly read the response body. + + For more information, see https://www.github.com/CaseMark/casedev-python#with_streaming_response + """ + return AsyncDocumentTemplatesResourceWithStreamingResponse(self) + + async def create( + self, + *, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> None: + """Create document template upload""" + extra_headers = {"Accept": "*/*", **(extra_headers or {})} + return await self._post( + "/document-templates", + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=NoneType, + ) + + async def retrieve( + self, + id: str, + *, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> None: + """ + Get document template + + Args: + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + if not id: + raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") + extra_headers = {"Accept": "*/*", **(extra_headers or {})} + return await self._get( + path_template("/document-templates/{id}", id=id), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=NoneType, + ) + + async def update( + self, + id: str, + *, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> None: + """ + Update document template metadata + + Args: + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + if not id: + raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") + extra_headers = {"Accept": "*/*", **(extra_headers or {})} + return await self._patch( + path_template("/document-templates/{id}", id=id), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=NoneType, + ) + + async def list( + self, + *, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> None: + """List document templates""" + extra_headers = {"Accept": "*/*", **(extra_headers or {})} + return await self._get( + "/document-templates", + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=NoneType, + ) + + async def delete( + self, + id: str, + *, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> None: + """ + Delete document template + + Args: + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + if not id: + raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") + extra_headers = {"Accept": "*/*", **(extra_headers or {})} + return await self._delete( + path_template("/document-templates/{id}", id=id), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=NoneType, + ) + + async def confirm( + self, + id: str, + *, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> None: + """ + Confirm document template upload + + Args: + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + if not id: + raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") + extra_headers = {"Accept": "*/*", **(extra_headers or {})} + return await self._post( + path_template("/document-templates/{id}/confirm", id=id), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=NoneType, + ) + + +class DocumentTemplatesResourceWithRawResponse: + def __init__(self, document_templates: DocumentTemplatesResource) -> None: + self._document_templates = document_templates + + self.create = to_raw_response_wrapper( + document_templates.create, + ) + self.retrieve = to_raw_response_wrapper( + document_templates.retrieve, + ) + self.update = to_raw_response_wrapper( + document_templates.update, + ) + self.list = to_raw_response_wrapper( + document_templates.list, + ) + self.delete = to_raw_response_wrapper( + document_templates.delete, + ) + self.confirm = to_raw_response_wrapper( + document_templates.confirm, + ) + + @cached_property + def from_vault_object(self) -> FromVaultObjectResourceWithRawResponse: + return FromVaultObjectResourceWithRawResponse(self._document_templates.from_vault_object) + + +class AsyncDocumentTemplatesResourceWithRawResponse: + def __init__(self, document_templates: AsyncDocumentTemplatesResource) -> None: + self._document_templates = document_templates + + self.create = async_to_raw_response_wrapper( + document_templates.create, + ) + self.retrieve = async_to_raw_response_wrapper( + document_templates.retrieve, + ) + self.update = async_to_raw_response_wrapper( + document_templates.update, + ) + self.list = async_to_raw_response_wrapper( + document_templates.list, + ) + self.delete = async_to_raw_response_wrapper( + document_templates.delete, + ) + self.confirm = async_to_raw_response_wrapper( + document_templates.confirm, + ) + + @cached_property + def from_vault_object(self) -> AsyncFromVaultObjectResourceWithRawResponse: + return AsyncFromVaultObjectResourceWithRawResponse(self._document_templates.from_vault_object) + + +class DocumentTemplatesResourceWithStreamingResponse: + def __init__(self, document_templates: DocumentTemplatesResource) -> None: + self._document_templates = document_templates + + self.create = to_streamed_response_wrapper( + document_templates.create, + ) + self.retrieve = to_streamed_response_wrapper( + document_templates.retrieve, + ) + self.update = to_streamed_response_wrapper( + document_templates.update, + ) + self.list = to_streamed_response_wrapper( + document_templates.list, + ) + self.delete = to_streamed_response_wrapper( + document_templates.delete, + ) + self.confirm = to_streamed_response_wrapper( + document_templates.confirm, + ) + + @cached_property + def from_vault_object(self) -> FromVaultObjectResourceWithStreamingResponse: + return FromVaultObjectResourceWithStreamingResponse(self._document_templates.from_vault_object) + + +class AsyncDocumentTemplatesResourceWithStreamingResponse: + def __init__(self, document_templates: AsyncDocumentTemplatesResource) -> None: + self._document_templates = document_templates + + self.create = async_to_streamed_response_wrapper( + document_templates.create, + ) + self.retrieve = async_to_streamed_response_wrapper( + document_templates.retrieve, + ) + self.update = async_to_streamed_response_wrapper( + document_templates.update, + ) + self.list = async_to_streamed_response_wrapper( + document_templates.list, + ) + self.delete = async_to_streamed_response_wrapper( + document_templates.delete, + ) + self.confirm = async_to_streamed_response_wrapper( + document_templates.confirm, + ) + + @cached_property + def from_vault_object(self) -> AsyncFromVaultObjectResourceWithStreamingResponse: + return AsyncFromVaultObjectResourceWithStreamingResponse(self._document_templates.from_vault_object) diff --git a/src/casedev/resources/document_templates/from_vault_object.py b/src/casedev/resources/document_templates/from_vault_object.py new file mode 100644 index 00000000..fdebf262 --- /dev/null +++ b/src/casedev/resources/document_templates/from_vault_object.py @@ -0,0 +1,136 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +import httpx + +from ..._types import Body, Query, Headers, NoneType, NotGiven, not_given +from ..._compat import cached_property +from ..._resource import SyncAPIResource, AsyncAPIResource +from ..._response import ( + to_raw_response_wrapper, + to_streamed_response_wrapper, + async_to_raw_response_wrapper, + async_to_streamed_response_wrapper, +) +from ..._base_client import make_request_options + +__all__ = ["FromVaultObjectResource", "AsyncFromVaultObjectResource"] + + +class FromVaultObjectResource(SyncAPIResource): + @cached_property + def with_raw_response(self) -> FromVaultObjectResourceWithRawResponse: + """ + This property can be used as a prefix for any HTTP method call to return + the raw response object instead of the parsed content. + + For more information, see https://www.github.com/CaseMark/casedev-python#accessing-raw-response-data-eg-headers + """ + return FromVaultObjectResourceWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> FromVaultObjectResourceWithStreamingResponse: + """ + An alternative to `.with_raw_response` that doesn't eagerly read the response body. + + For more information, see https://www.github.com/CaseMark/casedev-python#with_streaming_response + """ + return FromVaultObjectResourceWithStreamingResponse(self) + + def create( + self, + *, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> None: + """Promote vault object to document template""" + extra_headers = {"Accept": "*/*", **(extra_headers or {})} + return self._post( + "/document-templates/from-vault-object", + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=NoneType, + ) + + +class AsyncFromVaultObjectResource(AsyncAPIResource): + @cached_property + def with_raw_response(self) -> AsyncFromVaultObjectResourceWithRawResponse: + """ + This property can be used as a prefix for any HTTP method call to return + the raw response object instead of the parsed content. + + For more information, see https://www.github.com/CaseMark/casedev-python#accessing-raw-response-data-eg-headers + """ + return AsyncFromVaultObjectResourceWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> AsyncFromVaultObjectResourceWithStreamingResponse: + """ + An alternative to `.with_raw_response` that doesn't eagerly read the response body. + + For more information, see https://www.github.com/CaseMark/casedev-python#with_streaming_response + """ + return AsyncFromVaultObjectResourceWithStreamingResponse(self) + + async def create( + self, + *, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> None: + """Promote vault object to document template""" + extra_headers = {"Accept": "*/*", **(extra_headers or {})} + return await self._post( + "/document-templates/from-vault-object", + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=NoneType, + ) + + +class FromVaultObjectResourceWithRawResponse: + def __init__(self, from_vault_object: FromVaultObjectResource) -> None: + self._from_vault_object = from_vault_object + + self.create = to_raw_response_wrapper( + from_vault_object.create, + ) + + +class AsyncFromVaultObjectResourceWithRawResponse: + def __init__(self, from_vault_object: AsyncFromVaultObjectResource) -> None: + self._from_vault_object = from_vault_object + + self.create = async_to_raw_response_wrapper( + from_vault_object.create, + ) + + +class FromVaultObjectResourceWithStreamingResponse: + def __init__(self, from_vault_object: FromVaultObjectResource) -> None: + self._from_vault_object = from_vault_object + + self.create = to_streamed_response_wrapper( + from_vault_object.create, + ) + + +class AsyncFromVaultObjectResourceWithStreamingResponse: + def __init__(self, from_vault_object: AsyncFromVaultObjectResource) -> None: + self._from_vault_object = from_vault_object + + self.create = async_to_streamed_response_wrapper( + from_vault_object.create, + ) diff --git a/src/casedev/resources/linc/__init__.py b/src/casedev/resources/linc/__init__.py new file mode 100644 index 00000000..71fe8770 --- /dev/null +++ b/src/casedev/resources/linc/__init__.py @@ -0,0 +1,33 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from .v1 import ( + V1Resource, + AsyncV1Resource, + V1ResourceWithRawResponse, + AsyncV1ResourceWithRawResponse, + V1ResourceWithStreamingResponse, + AsyncV1ResourceWithStreamingResponse, +) +from .linc import ( + LincResource, + AsyncLincResource, + LincResourceWithRawResponse, + AsyncLincResourceWithRawResponse, + LincResourceWithStreamingResponse, + AsyncLincResourceWithStreamingResponse, +) + +__all__ = [ + "V1Resource", + "AsyncV1Resource", + "V1ResourceWithRawResponse", + "AsyncV1ResourceWithRawResponse", + "V1ResourceWithStreamingResponse", + "AsyncV1ResourceWithStreamingResponse", + "LincResource", + "AsyncLincResource", + "LincResourceWithRawResponse", + "AsyncLincResourceWithRawResponse", + "LincResourceWithStreamingResponse", + "AsyncLincResourceWithStreamingResponse", +] diff --git a/src/casedev/resources/linc/linc.py b/src/casedev/resources/linc/linc.py new file mode 100644 index 00000000..3eedd0b7 --- /dev/null +++ b/src/casedev/resources/linc/linc.py @@ -0,0 +1,102 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from .v1.v1 import ( + V1Resource, + AsyncV1Resource, + V1ResourceWithRawResponse, + AsyncV1ResourceWithRawResponse, + V1ResourceWithStreamingResponse, + AsyncV1ResourceWithStreamingResponse, +) +from ..._compat import cached_property +from ..._resource import SyncAPIResource, AsyncAPIResource + +__all__ = ["LincResource", "AsyncLincResource"] + + +class LincResource(SyncAPIResource): + @cached_property + def v1(self) -> V1Resource: + return V1Resource(self._client) + + @cached_property + def with_raw_response(self) -> LincResourceWithRawResponse: + """ + This property can be used as a prefix for any HTTP method call to return + the raw response object instead of the parsed content. + + For more information, see https://www.github.com/CaseMark/casedev-python#accessing-raw-response-data-eg-headers + """ + return LincResourceWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> LincResourceWithStreamingResponse: + """ + An alternative to `.with_raw_response` that doesn't eagerly read the response body. + + For more information, see https://www.github.com/CaseMark/casedev-python#with_streaming_response + """ + return LincResourceWithStreamingResponse(self) + + +class AsyncLincResource(AsyncAPIResource): + @cached_property + def v1(self) -> AsyncV1Resource: + return AsyncV1Resource(self._client) + + @cached_property + def with_raw_response(self) -> AsyncLincResourceWithRawResponse: + """ + This property can be used as a prefix for any HTTP method call to return + the raw response object instead of the parsed content. + + For more information, see https://www.github.com/CaseMark/casedev-python#accessing-raw-response-data-eg-headers + """ + return AsyncLincResourceWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> AsyncLincResourceWithStreamingResponse: + """ + An alternative to `.with_raw_response` that doesn't eagerly read the response body. + + For more information, see https://www.github.com/CaseMark/casedev-python#with_streaming_response + """ + return AsyncLincResourceWithStreamingResponse(self) + + +class LincResourceWithRawResponse: + def __init__(self, linc: LincResource) -> None: + self._linc = linc + + @cached_property + def v1(self) -> V1ResourceWithRawResponse: + return V1ResourceWithRawResponse(self._linc.v1) + + +class AsyncLincResourceWithRawResponse: + def __init__(self, linc: AsyncLincResource) -> None: + self._linc = linc + + @cached_property + def v1(self) -> AsyncV1ResourceWithRawResponse: + return AsyncV1ResourceWithRawResponse(self._linc.v1) + + +class LincResourceWithStreamingResponse: + def __init__(self, linc: LincResource) -> None: + self._linc = linc + + @cached_property + def v1(self) -> V1ResourceWithStreamingResponse: + return V1ResourceWithStreamingResponse(self._linc.v1) + + +class AsyncLincResourceWithStreamingResponse: + def __init__(self, linc: AsyncLincResource) -> None: + self._linc = linc + + @cached_property + def v1(self) -> AsyncV1ResourceWithStreamingResponse: + return AsyncV1ResourceWithStreamingResponse(self._linc.v1) diff --git a/src/casedev/resources/linc/v1/__init__.py b/src/casedev/resources/linc/v1/__init__.py new file mode 100644 index 00000000..93ec4af8 --- /dev/null +++ b/src/casedev/resources/linc/v1/__init__.py @@ -0,0 +1,33 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from .v1 import ( + V1Resource, + AsyncV1Resource, + V1ResourceWithRawResponse, + AsyncV1ResourceWithRawResponse, + V1ResourceWithStreamingResponse, + AsyncV1ResourceWithStreamingResponse, +) +from .sessions import ( + SessionsResource, + AsyncSessionsResource, + SessionsResourceWithRawResponse, + AsyncSessionsResourceWithRawResponse, + SessionsResourceWithStreamingResponse, + AsyncSessionsResourceWithStreamingResponse, +) + +__all__ = [ + "SessionsResource", + "AsyncSessionsResource", + "SessionsResourceWithRawResponse", + "AsyncSessionsResourceWithRawResponse", + "SessionsResourceWithStreamingResponse", + "AsyncSessionsResourceWithStreamingResponse", + "V1Resource", + "AsyncV1Resource", + "V1ResourceWithRawResponse", + "AsyncV1ResourceWithRawResponse", + "V1ResourceWithStreamingResponse", + "AsyncV1ResourceWithStreamingResponse", +] diff --git a/src/casedev/resources/linc/v1/sessions.py b/src/casedev/resources/linc/v1/sessions.py new file mode 100644 index 00000000..dd5f33e0 --- /dev/null +++ b/src/casedev/resources/linc/v1/sessions.py @@ -0,0 +1,952 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing import Iterable, Optional + +import httpx + +from ...._types import Body, Omit, Query, Headers, NoneType, NotGiven, SequenceNotStr, omit, not_given +from ...._utils import path_template, maybe_transform, async_maybe_transform +from ...._compat import cached_property +from ...._resource import SyncAPIResource, AsyncAPIResource +from ...._response import ( + to_raw_response_wrapper, + to_streamed_response_wrapper, + async_to_raw_response_wrapper, + async_to_streamed_response_wrapper, +) +from ...._base_client import make_request_options +from ....types.linc.v1 import ( + session_create_params, + session_send_rpc_params, + session_ingest_events_params, + session_retrieve_events_params, + session_retrieve_messages_params, +) + +__all__ = ["SessionsResource", "AsyncSessionsResource"] + + +class SessionsResource(SyncAPIResource): + """ + Create, manage, and execute AI agents with tool access, sandbox environments, and async run workflows + """ + + @cached_property + def with_raw_response(self) -> SessionsResourceWithRawResponse: + """ + This property can be used as a prefix for any HTTP method call to return + the raw response object instead of the parsed content. + + For more information, see https://www.github.com/CaseMark/casedev-python#accessing-raw-response-data-eg-headers + """ + return SessionsResourceWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> SessionsResourceWithStreamingResponse: + """ + An alternative to `.with_raw_response` that doesn't eagerly read the response body. + + For more information, see https://www.github.com/CaseMark/casedev-python#with_streaming_response + """ + return SessionsResourceWithStreamingResponse(self) + + def create( + self, + *, + document_template_slugs: Optional[SequenceNotStr[str]] | Omit = omit, + idle_timeout_ms: Optional[int] | Omit = omit, + include_document_templates: Optional[bool] | Omit = omit, + instructions: Optional[str] | Omit = omit, + model: Optional[str] | Omit = omit, + scoped_api_key: Optional[str] | Omit = omit, + skill_slugs: Optional[SequenceNotStr[str]] | Omit = omit, + title: str | Omit = omit, + vault_ids: Optional[SequenceNotStr[str]] | Omit = omit, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> None: + """ + Creates a Daytona-backed native Linc session with scoped Case.dev credentials. + This endpoint starts the sandbox actor only; messages and event replay use + separate endpoints. + + Args: + document_template_slugs: Specific document template slugs to inject into the using-document-templates + skill. + + include_document_templates: When true, inject all active org document templates into the + using-document-templates skill. + + instructions: Privileged C3-only hidden app instructions to append to the sandbox AGENTS.md. + + scoped_api_key: Optional caller-provided scoped Case.dev API key for the runtime. + + skill_slugs: Skills API slugs to install into the runtime sandbox before the native session + starts. + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + extra_headers = {"Accept": "*/*", **(extra_headers or {})} + return self._post( + "/linc/v1/sessions", + body=maybe_transform( + { + "document_template_slugs": document_template_slugs, + "idle_timeout_ms": idle_timeout_ms, + "include_document_templates": include_document_templates, + "instructions": instructions, + "model": model, + "scoped_api_key": scoped_api_key, + "skill_slugs": skill_slugs, + "title": title, + "vault_ids": vault_ids, + }, + session_create_params.SessionCreateParams, + ), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=NoneType, + ) + + def delete( + self, + id: str, + *, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> None: + """ + End native Linc session + + Args: + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + if not id: + raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") + extra_headers = {"Accept": "*/*", **(extra_headers or {})} + return self._delete( + path_template("/linc/v1/sessions/{id}", id=id), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=NoneType, + ) + + def cancel( + self, + id: str, + *, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> None: + """ + Cancel native Linc session turn + + Args: + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + if not id: + raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") + extra_headers = {"Accept": "*/*", **(extra_headers or {})} + return self._post( + path_template("/linc/v1/sessions/{id}/cancel", id=id), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=NoneType, + ) + + def ingest_events( + self, + id: str, + *, + frames: Iterable[session_ingest_events_params.Frame], + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> None: + """Runtime ingest endpoint for sandbox runtimes. + + Frames are persisted for replay; + terminal frames emit the durable Linc session ended webhook. + + Args: + frames: Native Linc event frames to persist for replay. + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + if not id: + raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") + extra_headers = {"Accept": "*/*", **(extra_headers or {})} + return self._post( + path_template("/linc/v1/sessions/{id}/events/ingest", id=id), + body=maybe_transform({"frames": frames}, session_ingest_events_params.SessionIngestEventsParams), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=NoneType, + ) + + def retrieve_events( + self, + id: str, + *, + after_seq: int | Omit = omit, + cursor: int | Omit = omit, + exclude_event_types: SequenceNotStr[str] | Omit = omit, + limit: int | Omit = omit, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> None: + """ + Returns persisted native Pi/Linc event envelopes after the requested cursor. + Live delivery is handled by the Linc stream service. + + Args: + after_seq: Alias for cursor. Ignored when cursor is also provided. + + cursor: Replay events with a sequence number greater than this cursor. + + exclude_event_types: Comma-separated Linc event types to omit from replay. + + limit: Maximum number of events to return. + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + if not id: + raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") + extra_headers = {"Accept": "*/*", **(extra_headers or {})} + return self._get( + path_template("/linc/v1/sessions/{id}/events", id=id), + options=make_request_options( + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + query=maybe_transform( + { + "after_seq": after_seq, + "cursor": cursor, + "exclude_event_types": exclude_event_types, + "limit": limit, + }, + session_retrieve_events_params.SessionRetrieveEventsParams, + ), + ), + cast_to=NoneType, + ) + + def retrieve_messages( + self, + id: str, + *, + after_seq: int | Omit = omit, + cursor: int | Omit = omit, + limit: int | Omit = omit, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> None: + """ + Returns completed Pi/Linc message entries derived from durable native Linc + events. This is the stable session-message read model for callers that need to + persist or recover chat history without depending on a live SSE stream. + + Args: + after_seq: Alias for cursor. Ignored when cursor is also provided. + + cursor: Replay messages with a source event sequence number greater than this cursor. + + limit: Maximum number of source events to scan for completed messages. + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + if not id: + raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") + extra_headers = {"Accept": "*/*", **(extra_headers or {})} + return self._get( + path_template("/linc/v1/sessions/{id}/messages", id=id), + options=make_request_options( + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + query=maybe_transform( + { + "after_seq": after_seq, + "cursor": cursor, + "limit": limit, + }, + session_retrieve_messages_params.SessionRetrieveMessagesParams, + ), + ), + cast_to=NoneType, + ) + + def retrieve_state( + self, + id: str, + *, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> None: + """ + Get native Linc session state + + Args: + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + if not id: + raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") + extra_headers = {"Accept": "*/*", **(extra_headers or {})} + return self._get( + path_template("/linc/v1/sessions/{id}/state", id=id), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=NoneType, + ) + + def send_rpc( + self, + path_id: str, + *, + type: str, + body_id: str | Omit = omit, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> None: + """ + Forwards a native Pi/Linc RPC command object to the sandbox-local Linc bridge + unchanged. The route returns after Pi accepts or rejects the command; native + events are read through the events endpoint. + + Args: + type: Native Pi/Linc RPC command type. Prompt commands also require a string id for + idempotency. + + body_id: Command idempotency key. Required when type is prompt. + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + if not path_id: + raise ValueError(f"Expected a non-empty value for `path_id` but received {path_id!r}") + extra_headers = {"Accept": "*/*", **(extra_headers or {})} + return self._post( + path_template("/linc/v1/sessions/{path_id}/rpc", path_id=path_id), + body=maybe_transform( + { + "type": type, + "body_id": body_id, + }, + session_send_rpc_params.SessionSendRpcParams, + ), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=NoneType, + ) + + +class AsyncSessionsResource(AsyncAPIResource): + """ + Create, manage, and execute AI agents with tool access, sandbox environments, and async run workflows + """ + + @cached_property + def with_raw_response(self) -> AsyncSessionsResourceWithRawResponse: + """ + This property can be used as a prefix for any HTTP method call to return + the raw response object instead of the parsed content. + + For more information, see https://www.github.com/CaseMark/casedev-python#accessing-raw-response-data-eg-headers + """ + return AsyncSessionsResourceWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> AsyncSessionsResourceWithStreamingResponse: + """ + An alternative to `.with_raw_response` that doesn't eagerly read the response body. + + For more information, see https://www.github.com/CaseMark/casedev-python#with_streaming_response + """ + return AsyncSessionsResourceWithStreamingResponse(self) + + async def create( + self, + *, + document_template_slugs: Optional[SequenceNotStr[str]] | Omit = omit, + idle_timeout_ms: Optional[int] | Omit = omit, + include_document_templates: Optional[bool] | Omit = omit, + instructions: Optional[str] | Omit = omit, + model: Optional[str] | Omit = omit, + scoped_api_key: Optional[str] | Omit = omit, + skill_slugs: Optional[SequenceNotStr[str]] | Omit = omit, + title: str | Omit = omit, + vault_ids: Optional[SequenceNotStr[str]] | Omit = omit, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> None: + """ + Creates a Daytona-backed native Linc session with scoped Case.dev credentials. + This endpoint starts the sandbox actor only; messages and event replay use + separate endpoints. + + Args: + document_template_slugs: Specific document template slugs to inject into the using-document-templates + skill. + + include_document_templates: When true, inject all active org document templates into the + using-document-templates skill. + + instructions: Privileged C3-only hidden app instructions to append to the sandbox AGENTS.md. + + scoped_api_key: Optional caller-provided scoped Case.dev API key for the runtime. + + skill_slugs: Skills API slugs to install into the runtime sandbox before the native session + starts. + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + extra_headers = {"Accept": "*/*", **(extra_headers or {})} + return await self._post( + "/linc/v1/sessions", + body=await async_maybe_transform( + { + "document_template_slugs": document_template_slugs, + "idle_timeout_ms": idle_timeout_ms, + "include_document_templates": include_document_templates, + "instructions": instructions, + "model": model, + "scoped_api_key": scoped_api_key, + "skill_slugs": skill_slugs, + "title": title, + "vault_ids": vault_ids, + }, + session_create_params.SessionCreateParams, + ), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=NoneType, + ) + + async def delete( + self, + id: str, + *, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> None: + """ + End native Linc session + + Args: + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + if not id: + raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") + extra_headers = {"Accept": "*/*", **(extra_headers or {})} + return await self._delete( + path_template("/linc/v1/sessions/{id}", id=id), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=NoneType, + ) + + async def cancel( + self, + id: str, + *, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> None: + """ + Cancel native Linc session turn + + Args: + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + if not id: + raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") + extra_headers = {"Accept": "*/*", **(extra_headers or {})} + return await self._post( + path_template("/linc/v1/sessions/{id}/cancel", id=id), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=NoneType, + ) + + async def ingest_events( + self, + id: str, + *, + frames: Iterable[session_ingest_events_params.Frame], + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> None: + """Runtime ingest endpoint for sandbox runtimes. + + Frames are persisted for replay; + terminal frames emit the durable Linc session ended webhook. + + Args: + frames: Native Linc event frames to persist for replay. + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + if not id: + raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") + extra_headers = {"Accept": "*/*", **(extra_headers or {})} + return await self._post( + path_template("/linc/v1/sessions/{id}/events/ingest", id=id), + body=await async_maybe_transform( + {"frames": frames}, session_ingest_events_params.SessionIngestEventsParams + ), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=NoneType, + ) + + async def retrieve_events( + self, + id: str, + *, + after_seq: int | Omit = omit, + cursor: int | Omit = omit, + exclude_event_types: SequenceNotStr[str] | Omit = omit, + limit: int | Omit = omit, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> None: + """ + Returns persisted native Pi/Linc event envelopes after the requested cursor. + Live delivery is handled by the Linc stream service. + + Args: + after_seq: Alias for cursor. Ignored when cursor is also provided. + + cursor: Replay events with a sequence number greater than this cursor. + + exclude_event_types: Comma-separated Linc event types to omit from replay. + + limit: Maximum number of events to return. + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + if not id: + raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") + extra_headers = {"Accept": "*/*", **(extra_headers or {})} + return await self._get( + path_template("/linc/v1/sessions/{id}/events", id=id), + options=make_request_options( + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + query=await async_maybe_transform( + { + "after_seq": after_seq, + "cursor": cursor, + "exclude_event_types": exclude_event_types, + "limit": limit, + }, + session_retrieve_events_params.SessionRetrieveEventsParams, + ), + ), + cast_to=NoneType, + ) + + async def retrieve_messages( + self, + id: str, + *, + after_seq: int | Omit = omit, + cursor: int | Omit = omit, + limit: int | Omit = omit, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> None: + """ + Returns completed Pi/Linc message entries derived from durable native Linc + events. This is the stable session-message read model for callers that need to + persist or recover chat history without depending on a live SSE stream. + + Args: + after_seq: Alias for cursor. Ignored when cursor is also provided. + + cursor: Replay messages with a source event sequence number greater than this cursor. + + limit: Maximum number of source events to scan for completed messages. + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + if not id: + raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") + extra_headers = {"Accept": "*/*", **(extra_headers or {})} + return await self._get( + path_template("/linc/v1/sessions/{id}/messages", id=id), + options=make_request_options( + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + query=await async_maybe_transform( + { + "after_seq": after_seq, + "cursor": cursor, + "limit": limit, + }, + session_retrieve_messages_params.SessionRetrieveMessagesParams, + ), + ), + cast_to=NoneType, + ) + + async def retrieve_state( + self, + id: str, + *, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> None: + """ + Get native Linc session state + + Args: + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + if not id: + raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") + extra_headers = {"Accept": "*/*", **(extra_headers or {})} + return await self._get( + path_template("/linc/v1/sessions/{id}/state", id=id), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=NoneType, + ) + + async def send_rpc( + self, + path_id: str, + *, + type: str, + body_id: str | Omit = omit, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> None: + """ + Forwards a native Pi/Linc RPC command object to the sandbox-local Linc bridge + unchanged. The route returns after Pi accepts or rejects the command; native + events are read through the events endpoint. + + Args: + type: Native Pi/Linc RPC command type. Prompt commands also require a string id for + idempotency. + + body_id: Command idempotency key. Required when type is prompt. + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + if not path_id: + raise ValueError(f"Expected a non-empty value for `path_id` but received {path_id!r}") + extra_headers = {"Accept": "*/*", **(extra_headers or {})} + return await self._post( + path_template("/linc/v1/sessions/{path_id}/rpc", path_id=path_id), + body=await async_maybe_transform( + { + "type": type, + "body_id": body_id, + }, + session_send_rpc_params.SessionSendRpcParams, + ), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=NoneType, + ) + + +class SessionsResourceWithRawResponse: + def __init__(self, sessions: SessionsResource) -> None: + self._sessions = sessions + + self.create = to_raw_response_wrapper( + sessions.create, + ) + self.delete = to_raw_response_wrapper( + sessions.delete, + ) + self.cancel = to_raw_response_wrapper( + sessions.cancel, + ) + self.ingest_events = to_raw_response_wrapper( + sessions.ingest_events, + ) + self.retrieve_events = to_raw_response_wrapper( + sessions.retrieve_events, + ) + self.retrieve_messages = to_raw_response_wrapper( + sessions.retrieve_messages, + ) + self.retrieve_state = to_raw_response_wrapper( + sessions.retrieve_state, + ) + self.send_rpc = to_raw_response_wrapper( + sessions.send_rpc, + ) + + +class AsyncSessionsResourceWithRawResponse: + def __init__(self, sessions: AsyncSessionsResource) -> None: + self._sessions = sessions + + self.create = async_to_raw_response_wrapper( + sessions.create, + ) + self.delete = async_to_raw_response_wrapper( + sessions.delete, + ) + self.cancel = async_to_raw_response_wrapper( + sessions.cancel, + ) + self.ingest_events = async_to_raw_response_wrapper( + sessions.ingest_events, + ) + self.retrieve_events = async_to_raw_response_wrapper( + sessions.retrieve_events, + ) + self.retrieve_messages = async_to_raw_response_wrapper( + sessions.retrieve_messages, + ) + self.retrieve_state = async_to_raw_response_wrapper( + sessions.retrieve_state, + ) + self.send_rpc = async_to_raw_response_wrapper( + sessions.send_rpc, + ) + + +class SessionsResourceWithStreamingResponse: + def __init__(self, sessions: SessionsResource) -> None: + self._sessions = sessions + + self.create = to_streamed_response_wrapper( + sessions.create, + ) + self.delete = to_streamed_response_wrapper( + sessions.delete, + ) + self.cancel = to_streamed_response_wrapper( + sessions.cancel, + ) + self.ingest_events = to_streamed_response_wrapper( + sessions.ingest_events, + ) + self.retrieve_events = to_streamed_response_wrapper( + sessions.retrieve_events, + ) + self.retrieve_messages = to_streamed_response_wrapper( + sessions.retrieve_messages, + ) + self.retrieve_state = to_streamed_response_wrapper( + sessions.retrieve_state, + ) + self.send_rpc = to_streamed_response_wrapper( + sessions.send_rpc, + ) + + +class AsyncSessionsResourceWithStreamingResponse: + def __init__(self, sessions: AsyncSessionsResource) -> None: + self._sessions = sessions + + self.create = async_to_streamed_response_wrapper( + sessions.create, + ) + self.delete = async_to_streamed_response_wrapper( + sessions.delete, + ) + self.cancel = async_to_streamed_response_wrapper( + sessions.cancel, + ) + self.ingest_events = async_to_streamed_response_wrapper( + sessions.ingest_events, + ) + self.retrieve_events = async_to_streamed_response_wrapper( + sessions.retrieve_events, + ) + self.retrieve_messages = async_to_streamed_response_wrapper( + sessions.retrieve_messages, + ) + self.retrieve_state = async_to_streamed_response_wrapper( + sessions.retrieve_state, + ) + self.send_rpc = async_to_streamed_response_wrapper( + sessions.send_rpc, + ) diff --git a/src/casedev/resources/linc/v1/v1.py b/src/casedev/resources/linc/v1/v1.py new file mode 100644 index 00000000..88df7a3f --- /dev/null +++ b/src/casedev/resources/linc/v1/v1.py @@ -0,0 +1,120 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from .sessions import ( + SessionsResource, + AsyncSessionsResource, + SessionsResourceWithRawResponse, + AsyncSessionsResourceWithRawResponse, + SessionsResourceWithStreamingResponse, + AsyncSessionsResourceWithStreamingResponse, +) +from ...._compat import cached_property +from ...._resource import SyncAPIResource, AsyncAPIResource + +__all__ = ["V1Resource", "AsyncV1Resource"] + + +class V1Resource(SyncAPIResource): + @cached_property + def sessions(self) -> SessionsResource: + """ + Create, manage, and execute AI agents with tool access, sandbox environments, and async run workflows + """ + return SessionsResource(self._client) + + @cached_property + def with_raw_response(self) -> V1ResourceWithRawResponse: + """ + This property can be used as a prefix for any HTTP method call to return + the raw response object instead of the parsed content. + + For more information, see https://www.github.com/CaseMark/casedev-python#accessing-raw-response-data-eg-headers + """ + return V1ResourceWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> V1ResourceWithStreamingResponse: + """ + An alternative to `.with_raw_response` that doesn't eagerly read the response body. + + For more information, see https://www.github.com/CaseMark/casedev-python#with_streaming_response + """ + return V1ResourceWithStreamingResponse(self) + + +class AsyncV1Resource(AsyncAPIResource): + @cached_property + def sessions(self) -> AsyncSessionsResource: + """ + Create, manage, and execute AI agents with tool access, sandbox environments, and async run workflows + """ + return AsyncSessionsResource(self._client) + + @cached_property + def with_raw_response(self) -> AsyncV1ResourceWithRawResponse: + """ + This property can be used as a prefix for any HTTP method call to return + the raw response object instead of the parsed content. + + For more information, see https://www.github.com/CaseMark/casedev-python#accessing-raw-response-data-eg-headers + """ + return AsyncV1ResourceWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> AsyncV1ResourceWithStreamingResponse: + """ + An alternative to `.with_raw_response` that doesn't eagerly read the response body. + + For more information, see https://www.github.com/CaseMark/casedev-python#with_streaming_response + """ + return AsyncV1ResourceWithStreamingResponse(self) + + +class V1ResourceWithRawResponse: + def __init__(self, v1: V1Resource) -> None: + self._v1 = v1 + + @cached_property + def sessions(self) -> SessionsResourceWithRawResponse: + """ + Create, manage, and execute AI agents with tool access, sandbox environments, and async run workflows + """ + return SessionsResourceWithRawResponse(self._v1.sessions) + + +class AsyncV1ResourceWithRawResponse: + def __init__(self, v1: AsyncV1Resource) -> None: + self._v1 = v1 + + @cached_property + def sessions(self) -> AsyncSessionsResourceWithRawResponse: + """ + Create, manage, and execute AI agents with tool access, sandbox environments, and async run workflows + """ + return AsyncSessionsResourceWithRawResponse(self._v1.sessions) + + +class V1ResourceWithStreamingResponse: + def __init__(self, v1: V1Resource) -> None: + self._v1 = v1 + + @cached_property + def sessions(self) -> SessionsResourceWithStreamingResponse: + """ + Create, manage, and execute AI agents with tool access, sandbox environments, and async run workflows + """ + return SessionsResourceWithStreamingResponse(self._v1.sessions) + + +class AsyncV1ResourceWithStreamingResponse: + def __init__(self, v1: AsyncV1Resource) -> None: + self._v1 = v1 + + @cached_property + def sessions(self) -> AsyncSessionsResourceWithStreamingResponse: + """ + Create, manage, and execute AI agents with tool access, sandbox environments, and async run workflows + """ + return AsyncSessionsResourceWithStreamingResponse(self._v1.sessions) diff --git a/src/casedev/resources/mail/v1/inboxes.py b/src/casedev/resources/mail/v1/inboxes.py index c55c95a3..70027683 100644 --- a/src/casedev/resources/mail/v1/inboxes.py +++ b/src/casedev/resources/mail/v1/inboxes.py @@ -21,9 +21,7 @@ class InboxesResource(SyncAPIResource): - """ - Create, manage, and execute AI agents with tool access, sandbox environments, and async run workflows - """ + """Managed inboxes for agent email workflows""" @cached_property def with_raw_response(self) -> InboxesResourceWithRawResponse: @@ -461,9 +459,7 @@ def set_policy( class AsyncInboxesResource(AsyncAPIResource): - """ - Create, manage, and execute AI agents with tool access, sandbox environments, and async run workflows - """ + """Managed inboxes for agent email workflows""" @cached_property def with_raw_response(self) -> AsyncInboxesResourceWithRawResponse: diff --git a/src/casedev/resources/mail/v1/v1.py b/src/casedev/resources/mail/v1/v1.py index 2bdc9298..391267a2 100644 --- a/src/casedev/resources/mail/v1/v1.py +++ b/src/casedev/resources/mail/v1/v1.py @@ -19,9 +19,7 @@ class V1Resource(SyncAPIResource): @cached_property def inboxes(self) -> InboxesResource: - """ - Create, manage, and execute AI agents with tool access, sandbox environments, and async run workflows - """ + """Managed inboxes for agent email workflows""" return InboxesResource(self._client) @cached_property @@ -47,9 +45,7 @@ def with_streaming_response(self) -> V1ResourceWithStreamingResponse: class AsyncV1Resource(AsyncAPIResource): @cached_property def inboxes(self) -> AsyncInboxesResource: - """ - Create, manage, and execute AI agents with tool access, sandbox environments, and async run workflows - """ + """Managed inboxes for agent email workflows""" return AsyncInboxesResource(self._client) @cached_property @@ -78,9 +74,7 @@ def __init__(self, v1: V1Resource) -> None: @cached_property def inboxes(self) -> InboxesResourceWithRawResponse: - """ - Create, manage, and execute AI agents with tool access, sandbox environments, and async run workflows - """ + """Managed inboxes for agent email workflows""" return InboxesResourceWithRawResponse(self._v1.inboxes) @@ -90,9 +84,7 @@ def __init__(self, v1: AsyncV1Resource) -> None: @cached_property def inboxes(self) -> AsyncInboxesResourceWithRawResponse: - """ - Create, manage, and execute AI agents with tool access, sandbox environments, and async run workflows - """ + """Managed inboxes for agent email workflows""" return AsyncInboxesResourceWithRawResponse(self._v1.inboxes) @@ -102,9 +94,7 @@ def __init__(self, v1: V1Resource) -> None: @cached_property def inboxes(self) -> InboxesResourceWithStreamingResponse: - """ - Create, manage, and execute AI agents with tool access, sandbox environments, and async run workflows - """ + """Managed inboxes for agent email workflows""" return InboxesResourceWithStreamingResponse(self._v1.inboxes) @@ -114,7 +104,5 @@ def __init__(self, v1: AsyncV1Resource) -> None: @cached_property def inboxes(self) -> AsyncInboxesResourceWithStreamingResponse: - """ - Create, manage, and execute AI agents with tool access, sandbox environments, and async run workflows - """ + """Managed inboxes for agent email workflows""" return AsyncInboxesResourceWithStreamingResponse(self._v1.inboxes) diff --git a/src/casedev/resources/media/v1/transcripts/__init__.py b/src/casedev/resources/media/v1/transcripts/__init__.py index f957041b..33a94bae 100644 --- a/src/casedev/resources/media/v1/transcripts/__init__.py +++ b/src/casedev/resources/media/v1/transcripts/__init__.py @@ -8,6 +8,14 @@ SearchResourceWithStreamingResponse, AsyncSearchResourceWithStreamingResponse, ) +from .retrieve import ( + RetrieveResource, + AsyncRetrieveResource, + RetrieveResourceWithRawResponse, + AsyncRetrieveResourceWithRawResponse, + RetrieveResourceWithStreamingResponse, + AsyncRetrieveResourceWithStreamingResponse, +) from .transcripts import ( TranscriptsResource, AsyncTranscriptsResource, @@ -24,6 +32,12 @@ "AsyncSearchResourceWithRawResponse", "SearchResourceWithStreamingResponse", "AsyncSearchResourceWithStreamingResponse", + "RetrieveResource", + "AsyncRetrieveResource", + "RetrieveResourceWithRawResponse", + "AsyncRetrieveResourceWithRawResponse", + "RetrieveResourceWithStreamingResponse", + "AsyncRetrieveResourceWithStreamingResponse", "TranscriptsResource", "AsyncTranscriptsResource", "TranscriptsResourceWithRawResponse", diff --git a/src/casedev/resources/media/v1/transcripts/retrieve.py b/src/casedev/resources/media/v1/transcripts/retrieve.py new file mode 100644 index 00000000..0d98dc68 --- /dev/null +++ b/src/casedev/resources/media/v1/transcripts/retrieve.py @@ -0,0 +1,199 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +import httpx + +from ....._types import Body, Omit, Query, Headers, NotGiven, omit, not_given +from ....._utils import maybe_transform, async_maybe_transform +from ....._compat import cached_property +from ....._resource import SyncAPIResource, AsyncAPIResource +from ....._response import ( + to_raw_response_wrapper, + to_streamed_response_wrapper, + async_to_raw_response_wrapper, + async_to_streamed_response_wrapper, +) +from ....._base_client import make_request_options +from .....types.media.v1.transcripts import retrieve_create_params +from .....types.media.v1.transcripts.retrieve_create_response import RetrieveCreateResponse + +__all__ = ["RetrieveResource", "AsyncRetrieveResource"] + + +class RetrieveResource(SyncAPIResource): + @cached_property + def with_raw_response(self) -> RetrieveResourceWithRawResponse: + """ + This property can be used as a prefix for any HTTP method call to return + the raw response object instead of the parsed content. + + For more information, see https://www.github.com/CaseMark/casedev-python#accessing-raw-response-data-eg-headers + """ + return RetrieveResourceWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> RetrieveResourceWithStreamingResponse: + """ + An alternative to `.with_raw_response` that doesn't eagerly read the response body. + + For more information, see https://www.github.com/CaseMark/casedev-python#with_streaming_response + """ + return RetrieveResourceWithStreamingResponse(self) + + def create( + self, + *, + object_id: str, + vault_id: str, + transcript: retrieve_create_params.Transcript | Omit = omit, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> RetrieveCreateResponse: + """ + Retrieves the full transcript text for a vault transcript object or an + audio/video source object with a completed transcription job. When object_id is + a source media object, access to that source object grants access to its + generated transcript artifact. + + Args: + object_id: Object ID for either the source audio/video file or transcript artifact. + + vault_id: Vault ID containing the source media or transcript object. + + transcript: Alternative nested transcript object reference. + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + return self._post( + "/media/v1/transcripts/retrieve", + body=maybe_transform( + { + "object_id": object_id, + "vault_id": vault_id, + "transcript": transcript, + }, + retrieve_create_params.RetrieveCreateParams, + ), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=RetrieveCreateResponse, + ) + + +class AsyncRetrieveResource(AsyncAPIResource): + @cached_property + def with_raw_response(self) -> AsyncRetrieveResourceWithRawResponse: + """ + This property can be used as a prefix for any HTTP method call to return + the raw response object instead of the parsed content. + + For more information, see https://www.github.com/CaseMark/casedev-python#accessing-raw-response-data-eg-headers + """ + return AsyncRetrieveResourceWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> AsyncRetrieveResourceWithStreamingResponse: + """ + An alternative to `.with_raw_response` that doesn't eagerly read the response body. + + For more information, see https://www.github.com/CaseMark/casedev-python#with_streaming_response + """ + return AsyncRetrieveResourceWithStreamingResponse(self) + + async def create( + self, + *, + object_id: str, + vault_id: str, + transcript: retrieve_create_params.Transcript | Omit = omit, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> RetrieveCreateResponse: + """ + Retrieves the full transcript text for a vault transcript object or an + audio/video source object with a completed transcription job. When object_id is + a source media object, access to that source object grants access to its + generated transcript artifact. + + Args: + object_id: Object ID for either the source audio/video file or transcript artifact. + + vault_id: Vault ID containing the source media or transcript object. + + transcript: Alternative nested transcript object reference. + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + return await self._post( + "/media/v1/transcripts/retrieve", + body=await async_maybe_transform( + { + "object_id": object_id, + "vault_id": vault_id, + "transcript": transcript, + }, + retrieve_create_params.RetrieveCreateParams, + ), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=RetrieveCreateResponse, + ) + + +class RetrieveResourceWithRawResponse: + def __init__(self, retrieve: RetrieveResource) -> None: + self._retrieve = retrieve + + self.create = to_raw_response_wrapper( + retrieve.create, + ) + + +class AsyncRetrieveResourceWithRawResponse: + def __init__(self, retrieve: AsyncRetrieveResource) -> None: + self._retrieve = retrieve + + self.create = async_to_raw_response_wrapper( + retrieve.create, + ) + + +class RetrieveResourceWithStreamingResponse: + def __init__(self, retrieve: RetrieveResource) -> None: + self._retrieve = retrieve + + self.create = to_streamed_response_wrapper( + retrieve.create, + ) + + +class AsyncRetrieveResourceWithStreamingResponse: + def __init__(self, retrieve: AsyncRetrieveResource) -> None: + self._retrieve = retrieve + + self.create = async_to_streamed_response_wrapper( + retrieve.create, + ) diff --git a/src/casedev/resources/media/v1/transcripts/transcripts.py b/src/casedev/resources/media/v1/transcripts/transcripts.py index f5423428..bf6ffb70 100644 --- a/src/casedev/resources/media/v1/transcripts/transcripts.py +++ b/src/casedev/resources/media/v1/transcripts/transcripts.py @@ -10,6 +10,14 @@ SearchResourceWithStreamingResponse, AsyncSearchResourceWithStreamingResponse, ) +from .retrieve import ( + RetrieveResource, + AsyncRetrieveResource, + RetrieveResourceWithRawResponse, + AsyncRetrieveResourceWithRawResponse, + RetrieveResourceWithStreamingResponse, + AsyncRetrieveResourceWithStreamingResponse, +) from ....._compat import cached_property from ....._resource import SyncAPIResource, AsyncAPIResource @@ -21,6 +29,10 @@ class TranscriptsResource(SyncAPIResource): def search(self) -> SearchResource: return SearchResource(self._client) + @cached_property + def retrieve(self) -> RetrieveResource: + return RetrieveResource(self._client) + @cached_property def with_raw_response(self) -> TranscriptsResourceWithRawResponse: """ @@ -46,6 +58,10 @@ class AsyncTranscriptsResource(AsyncAPIResource): def search(self) -> AsyncSearchResource: return AsyncSearchResource(self._client) + @cached_property + def retrieve(self) -> AsyncRetrieveResource: + return AsyncRetrieveResource(self._client) + @cached_property def with_raw_response(self) -> AsyncTranscriptsResourceWithRawResponse: """ @@ -74,6 +90,10 @@ def __init__(self, transcripts: TranscriptsResource) -> None: def search(self) -> SearchResourceWithRawResponse: return SearchResourceWithRawResponse(self._transcripts.search) + @cached_property + def retrieve(self) -> RetrieveResourceWithRawResponse: + return RetrieveResourceWithRawResponse(self._transcripts.retrieve) + class AsyncTranscriptsResourceWithRawResponse: def __init__(self, transcripts: AsyncTranscriptsResource) -> None: @@ -83,6 +103,10 @@ def __init__(self, transcripts: AsyncTranscriptsResource) -> None: def search(self) -> AsyncSearchResourceWithRawResponse: return AsyncSearchResourceWithRawResponse(self._transcripts.search) + @cached_property + def retrieve(self) -> AsyncRetrieveResourceWithRawResponse: + return AsyncRetrieveResourceWithRawResponse(self._transcripts.retrieve) + class TranscriptsResourceWithStreamingResponse: def __init__(self, transcripts: TranscriptsResource) -> None: @@ -92,6 +116,10 @@ def __init__(self, transcripts: TranscriptsResource) -> None: def search(self) -> SearchResourceWithStreamingResponse: return SearchResourceWithStreamingResponse(self._transcripts.search) + @cached_property + def retrieve(self) -> RetrieveResourceWithStreamingResponse: + return RetrieveResourceWithStreamingResponse(self._transcripts.retrieve) + class AsyncTranscriptsResourceWithStreamingResponse: def __init__(self, transcripts: AsyncTranscriptsResource) -> None: @@ -100,3 +128,7 @@ def __init__(self, transcripts: AsyncTranscriptsResource) -> None: @cached_property def search(self) -> AsyncSearchResourceWithStreamingResponse: return AsyncSearchResourceWithStreamingResponse(self._transcripts.search) + + @cached_property + def retrieve(self) -> AsyncRetrieveResourceWithStreamingResponse: + return AsyncRetrieveResourceWithStreamingResponse(self._transcripts.retrieve) diff --git a/src/casedev/resources/usage/v1/v1.py b/src/casedev/resources/usage/v1/v1.py index 2bf86174..f8e3571f 100644 --- a/src/casedev/resources/usage/v1/v1.py +++ b/src/casedev/resources/usage/v1/v1.py @@ -63,6 +63,8 @@ def retrieve( self, *, granularity: Literal["summary", "daily"] | Omit = omit, + group_by: Literal["lincSessionId"] | Omit = omit, + linc_session_id: str | Omit = omit, period_end: Union[str, datetime] | Omit = omit, period_start: Union[str, datetime] | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. @@ -81,6 +83,12 @@ def retrieve( Args: granularity: Whether to return period totals only or include daily buckets. + group_by: Optionally include usage groups keyed by native Linc session id. Only + Linc-session-attributable usage is grouped. + + linc_session_id: Restrict usage to a native Linc session. The session must belong to the + authenticated organization. + period_end: Period end date. Defaults to now. period_start: Period start date. Defaults to the start of the current calendar month. @@ -104,6 +112,8 @@ def retrieve( query=maybe_transform( { "granularity": granularity, + "group_by": group_by, + "linc_session_id": linc_session_id, "period_end": period_end, "period_start": period_start, }, @@ -145,6 +155,8 @@ async def retrieve( self, *, granularity: Literal["summary", "daily"] | Omit = omit, + group_by: Literal["lincSessionId"] | Omit = omit, + linc_session_id: str | Omit = omit, period_end: Union[str, datetime] | Omit = omit, period_start: Union[str, datetime] | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. @@ -163,6 +175,12 @@ async def retrieve( Args: granularity: Whether to return period totals only or include daily buckets. + group_by: Optionally include usage groups keyed by native Linc session id. Only + Linc-session-attributable usage is grouped. + + linc_session_id: Restrict usage to a native Linc session. The session must belong to the + authenticated organization. + period_end: Period end date. Defaults to now. period_start: Period start date. Defaults to the start of the current calendar month. @@ -186,6 +204,8 @@ async def retrieve( query=await async_maybe_transform( { "granularity": granularity, + "group_by": group_by, + "linc_session_id": linc_session_id, "period_end": period_end, "period_start": period_start, }, diff --git a/src/casedev/resources/vault/multipart.py b/src/casedev/resources/vault/multipart.py index 04a8989a..208a0c44 100644 --- a/src/casedev/resources/vault/multipart.py +++ b/src/casedev/resources/vault/multipart.py @@ -6,7 +6,7 @@ import httpx -from ..._types import Body, Query, Headers, NoneType, NotGiven, not_given +from ..._types import Body, Omit, Query, Headers, NoneType, NotGiven, omit, not_given from ..._utils import path_template, maybe_transform, async_maybe_transform from ..._compat import cached_property from ..._resource import SyncAPIResource, AsyncAPIResource @@ -16,8 +16,14 @@ async_to_raw_response_wrapper, async_to_streamed_response_wrapper, ) -from ...types.vault import multipart_abort_params, multipart_get_part_urls_params +from ...types.vault import ( + multipart_init_params, + multipart_abort_params, + multipart_complete_params, + multipart_get_part_urls_params, +) from ..._base_client import make_request_options +from ...types.vault.multipart_init_response import MultipartInitResponse from ...types.vault.multipart_get_part_urls_response import MultipartGetPartURLsResponse __all__ = ["MultipartResource", "AsyncMultipartResource"] @@ -92,6 +98,58 @@ def abort( cast_to=NoneType, ) + def complete( + self, + id: str, + *, + object_id: str, + parts: Iterable[multipart_complete_params.Part], + size_bytes: int, + upload_id: str, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> None: + """ + Complete a multipart upload by providing the list of part numbers and ETags + (live). Single PUT uploads are capped at 5GB; multipart default max is 16GB + (configurable). + + Args: + size_bytes: File size in bytes (default max 16GB). Configure via + VAULT_MULTIPART_MAX_FILE_SIZE_BYTES. + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + if not id: + raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") + extra_headers = {"Accept": "*/*", **(extra_headers or {})} + return self._post( + path_template("/vault/{id}/multipart/complete", id=id), + body=maybe_transform( + { + "object_id": object_id, + "parts": parts, + "size_bytes": size_bytes, + "upload_id": upload_id, + }, + multipart_complete_params.MultipartCompleteParams, + ), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=NoneType, + ) + def get_part_urls( self, id: str, @@ -142,6 +200,83 @@ def get_part_urls( cast_to=MultipartGetPartURLsResponse, ) + def init( + self, + id: str, + *, + content_type: str, + filename: str, + size_bytes: int, + auto_index: bool | Omit = omit, + is_ai_generated: bool | Omit = omit, + metadata: object | Omit = omit, + part_size_bytes: int | Omit = omit, + path: str | Omit = omit, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> MultipartInitResponse: + """Initiate a multipart upload for large files (>5GB). + + Single PUT uploads are + capped at 5GB; multipart default max is 16GB (configurable). Multipart uploads + are supported in production. Returns an uploadId and object metadata. Use part + URLs endpoint to upload parts and complete endpoint to finalize. + + Args: + content_type: MIME type of the file + + filename: Name of the file to upload + + size_bytes: File size in bytes (required, default max 16GB). Configure via + VAULT_MULTIPART_MAX_FILE_SIZE_BYTES. + + auto_index: Whether to automatically process and index the file for search + + is_ai_generated: Marks the file as AI-generated work product (e.g. uploaded by an agent) rather + than a user-provided source document. Persisted on the object and returned by + object listings so clients can distinguish provenance. + + metadata: Additional metadata to associate with the file + + part_size_bytes: Multipart part size in bytes (min 5MB, max 5GB). Defaults to 64MB. + + path: Optional folder path for hierarchy preservation + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + if not id: + raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") + return self._post( + path_template("/vault/{id}/multipart/init", id=id), + body=maybe_transform( + { + "content_type": content_type, + "filename": filename, + "size_bytes": size_bytes, + "auto_index": auto_index, + "is_ai_generated": is_ai_generated, + "metadata": metadata, + "part_size_bytes": part_size_bytes, + "path": path, + }, + multipart_init_params.MultipartInitParams, + ), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=MultipartInitResponse, + ) + class AsyncMultipartResource(AsyncAPIResource): """Secure document storage with semantic search and GraphRAG""" @@ -212,6 +347,58 @@ async def abort( cast_to=NoneType, ) + async def complete( + self, + id: str, + *, + object_id: str, + parts: Iterable[multipart_complete_params.Part], + size_bytes: int, + upload_id: str, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> None: + """ + Complete a multipart upload by providing the list of part numbers and ETags + (live). Single PUT uploads are capped at 5GB; multipart default max is 16GB + (configurable). + + Args: + size_bytes: File size in bytes (default max 16GB). Configure via + VAULT_MULTIPART_MAX_FILE_SIZE_BYTES. + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + if not id: + raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") + extra_headers = {"Accept": "*/*", **(extra_headers or {})} + return await self._post( + path_template("/vault/{id}/multipart/complete", id=id), + body=await async_maybe_transform( + { + "object_id": object_id, + "parts": parts, + "size_bytes": size_bytes, + "upload_id": upload_id, + }, + multipart_complete_params.MultipartCompleteParams, + ), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=NoneType, + ) + async def get_part_urls( self, id: str, @@ -262,6 +449,83 @@ async def get_part_urls( cast_to=MultipartGetPartURLsResponse, ) + async def init( + self, + id: str, + *, + content_type: str, + filename: str, + size_bytes: int, + auto_index: bool | Omit = omit, + is_ai_generated: bool | Omit = omit, + metadata: object | Omit = omit, + part_size_bytes: int | Omit = omit, + path: str | Omit = omit, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> MultipartInitResponse: + """Initiate a multipart upload for large files (>5GB). + + Single PUT uploads are + capped at 5GB; multipart default max is 16GB (configurable). Multipart uploads + are supported in production. Returns an uploadId and object metadata. Use part + URLs endpoint to upload parts and complete endpoint to finalize. + + Args: + content_type: MIME type of the file + + filename: Name of the file to upload + + size_bytes: File size in bytes (required, default max 16GB). Configure via + VAULT_MULTIPART_MAX_FILE_SIZE_BYTES. + + auto_index: Whether to automatically process and index the file for search + + is_ai_generated: Marks the file as AI-generated work product (e.g. uploaded by an agent) rather + than a user-provided source document. Persisted on the object and returned by + object listings so clients can distinguish provenance. + + metadata: Additional metadata to associate with the file + + part_size_bytes: Multipart part size in bytes (min 5MB, max 5GB). Defaults to 64MB. + + path: Optional folder path for hierarchy preservation + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + if not id: + raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") + return await self._post( + path_template("/vault/{id}/multipart/init", id=id), + body=await async_maybe_transform( + { + "content_type": content_type, + "filename": filename, + "size_bytes": size_bytes, + "auto_index": auto_index, + "is_ai_generated": is_ai_generated, + "metadata": metadata, + "part_size_bytes": part_size_bytes, + "path": path, + }, + multipart_init_params.MultipartInitParams, + ), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=MultipartInitResponse, + ) + class MultipartResourceWithRawResponse: def __init__(self, multipart: MultipartResource) -> None: @@ -270,9 +534,15 @@ def __init__(self, multipart: MultipartResource) -> None: self.abort = to_raw_response_wrapper( multipart.abort, ) + self.complete = to_raw_response_wrapper( + multipart.complete, + ) self.get_part_urls = to_raw_response_wrapper( multipart.get_part_urls, ) + self.init = to_raw_response_wrapper( + multipart.init, + ) class AsyncMultipartResourceWithRawResponse: @@ -282,9 +552,15 @@ def __init__(self, multipart: AsyncMultipartResource) -> None: self.abort = async_to_raw_response_wrapper( multipart.abort, ) + self.complete = async_to_raw_response_wrapper( + multipart.complete, + ) self.get_part_urls = async_to_raw_response_wrapper( multipart.get_part_urls, ) + self.init = async_to_raw_response_wrapper( + multipart.init, + ) class MultipartResourceWithStreamingResponse: @@ -294,9 +570,15 @@ def __init__(self, multipart: MultipartResource) -> None: self.abort = to_streamed_response_wrapper( multipart.abort, ) + self.complete = to_streamed_response_wrapper( + multipart.complete, + ) self.get_part_urls = to_streamed_response_wrapper( multipart.get_part_urls, ) + self.init = to_streamed_response_wrapper( + multipart.init, + ) class AsyncMultipartResourceWithStreamingResponse: @@ -306,6 +588,12 @@ def __init__(self, multipart: AsyncMultipartResource) -> None: self.abort = async_to_streamed_response_wrapper( multipart.abort, ) + self.complete = async_to_streamed_response_wrapper( + multipart.complete, + ) self.get_part_urls = async_to_streamed_response_wrapper( multipart.get_part_urls, ) + self.init = async_to_streamed_response_wrapper( + multipart.init, + ) diff --git a/src/casedev/resources/vault/objects.py b/src/casedev/resources/vault/objects.py index 91c0f099..40dfccba 100644 --- a/src/casedev/resources/vault/objects.py +++ b/src/casedev/resources/vault/objects.py @@ -7,7 +7,7 @@ import httpx -from ..._types import Body, Omit, Query, Headers, NotGiven, omit, not_given +from ..._types import Body, Omit, Query, Headers, NotGiven, SequenceNotStr, omit, not_given from ..._utils import path_template, maybe_transform, async_maybe_transform from ..._compat import cached_property from ..._resource import SyncAPIResource, AsyncAPIResource @@ -26,20 +26,25 @@ async_to_custom_streamed_response_wrapper, ) from ...types.vault import ( + object_list_params, + object_append_params, object_delete_params, object_update_params, object_get_pages_params, + object_summarize_params, object_get_chunks_params, object_get_ocr_words_params, object_create_presigned_url_params, ) from ..._base_client import make_request_options from ...types.vault.object_list_response import ObjectListResponse +from ...types.vault.object_append_response import ObjectAppendResponse from ...types.vault.object_delete_response import ObjectDeleteResponse from ...types.vault.object_update_response import ObjectUpdateResponse from ...types.vault.object_get_text_response import ObjectGetTextResponse from ...types.vault.object_retrieve_response import ObjectRetrieveResponse from ...types.vault.object_get_pages_response import ObjectGetPagesResponse +from ...types.vault.object_summarize_response import ObjectSummarizeResponse from ...types.vault.object_get_chunks_response import ObjectGetChunksResponse from ...types.vault.object_get_ocr_words_response import ObjectGetOcrWordsResponse from ...types.vault.object_get_summarize_job_response import ObjectGetSummarizeJobResponse @@ -169,6 +174,7 @@ def list( self, id: str, *, + include_unconfirmed: bool | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, @@ -181,6 +187,9 @@ def list( ingestion status, and processing statistics. Args: + include_unconfirmed: Include placeholders for uploads that were never completed (awaiting_upload) or + were cancelled (aborted). Excluded by default. + extra_headers: Send extra headers extra_query: Add additional query parameters to the request @@ -194,7 +203,13 @@ def list( return self._get( path_template("/vault/{id}/objects", id=id), options=make_request_options( - extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + query=maybe_transform( + {"include_unconfirmed": include_unconfirmed}, object_list_params.ObjectListParams + ), ), cast_to=ObjectListResponse, ) @@ -244,6 +259,71 @@ def delete( cast_to=ObjectDeleteResponse, ) + def append( + self, + object_id: str, + *, + id: str, + append_object_ids: SequenceNotStr[str], + back_links: bool | Omit = omit, + back_links_text: str | Omit = omit, + rewrite_links: bool | Omit = omit, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> ObjectAppendResponse: + """ + Merges one or more PDF vault objects onto the end of an existing PDF vault + object, overwriting the target in place before returning. Optionally rewrites + citation links in the original target into internal PDF jumps and adds back + links on appended pages. The target object’s ingestion state is not affected; + appended pages are not searchable. + + Args: + append_object_ids: Vault object IDs whose pages will be appended onto the target object, in order. + Must not include the target object itself. + + back_links: Adds back links on appended pages + + back_links_text: Label text for the back link. Used only when backLinks is true and rendered + centered at the bottom of each appended page. + + rewrite_links: When true, rewrites links in the target object to internal PDF jumps when the + URL contains exactly one appended object ID as a standalone query parameter + value or decoded path segment. + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + if not id: + raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") + if not object_id: + raise ValueError(f"Expected a non-empty value for `object_id` but received {object_id!r}") + return self._post( + path_template("/vault/{id}/objects/{object_id}/append", id=id, object_id=object_id), + body=maybe_transform( + { + "append_object_ids": append_object_ids, + "back_links": back_links, + "back_links_text": back_links_text, + "rewrite_links": rewrite_links, + }, + object_append_params.ObjectAppendParams, + ), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=ObjectAppendResponse, + ) + def create_presigned_url( self, object_id: str, @@ -609,6 +689,57 @@ def get_text( cast_to=ObjectGetTextResponse, ) + def summarize( + self, + object_id: str, + *, + id: str, + output_format: Literal["PDF", "WORD"] | Omit = omit, + workflow_type: str | Omit = omit, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> ObjectSummarizeResponse: + """ + Triggers a CaseMark AI workflow to summarize or analyze a document stored in the + vault. The workflow processes the document asynchronously and stores the result + as a new object in the same vault, linked to the original document. + + Args: + output_format: Output format for the summary document + + workflow_type: Type of CaseMark workflow to run + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + if not id: + raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") + if not object_id: + raise ValueError(f"Expected a non-empty value for `object_id` but received {object_id!r}") + return self._post( + path_template("/vault/{id}/objects/{object_id}/summarize", id=id, object_id=object_id), + body=maybe_transform( + { + "output_format": output_format, + "workflow_type": workflow_type, + }, + object_summarize_params.ObjectSummarizeParams, + ), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=ObjectSummarizeResponse, + ) + class AsyncObjectsResource(AsyncAPIResource): """Secure document storage with semantic search and GraphRAG""" @@ -731,6 +862,7 @@ async def list( self, id: str, *, + include_unconfirmed: bool | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, @@ -743,6 +875,9 @@ async def list( ingestion status, and processing statistics. Args: + include_unconfirmed: Include placeholders for uploads that were never completed (awaiting_upload) or + were cancelled (aborted). Excluded by default. + extra_headers: Send extra headers extra_query: Add additional query parameters to the request @@ -756,7 +891,13 @@ async def list( return await self._get( path_template("/vault/{id}/objects", id=id), options=make_request_options( - extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + query=await async_maybe_transform( + {"include_unconfirmed": include_unconfirmed}, object_list_params.ObjectListParams + ), ), cast_to=ObjectListResponse, ) @@ -806,6 +947,71 @@ async def delete( cast_to=ObjectDeleteResponse, ) + async def append( + self, + object_id: str, + *, + id: str, + append_object_ids: SequenceNotStr[str], + back_links: bool | Omit = omit, + back_links_text: str | Omit = omit, + rewrite_links: bool | Omit = omit, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> ObjectAppendResponse: + """ + Merges one or more PDF vault objects onto the end of an existing PDF vault + object, overwriting the target in place before returning. Optionally rewrites + citation links in the original target into internal PDF jumps and adds back + links on appended pages. The target object’s ingestion state is not affected; + appended pages are not searchable. + + Args: + append_object_ids: Vault object IDs whose pages will be appended onto the target object, in order. + Must not include the target object itself. + + back_links: Adds back links on appended pages + + back_links_text: Label text for the back link. Used only when backLinks is true and rendered + centered at the bottom of each appended page. + + rewrite_links: When true, rewrites links in the target object to internal PDF jumps when the + URL contains exactly one appended object ID as a standalone query parameter + value or decoded path segment. + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + if not id: + raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") + if not object_id: + raise ValueError(f"Expected a non-empty value for `object_id` but received {object_id!r}") + return await self._post( + path_template("/vault/{id}/objects/{object_id}/append", id=id, object_id=object_id), + body=await async_maybe_transform( + { + "append_object_ids": append_object_ids, + "back_links": back_links, + "back_links_text": back_links_text, + "rewrite_links": rewrite_links, + }, + object_append_params.ObjectAppendParams, + ), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=ObjectAppendResponse, + ) + async def create_presigned_url( self, object_id: str, @@ -1171,6 +1377,57 @@ async def get_text( cast_to=ObjectGetTextResponse, ) + async def summarize( + self, + object_id: str, + *, + id: str, + output_format: Literal["PDF", "WORD"] | Omit = omit, + workflow_type: str | Omit = omit, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> ObjectSummarizeResponse: + """ + Triggers a CaseMark AI workflow to summarize or analyze a document stored in the + vault. The workflow processes the document asynchronously and stores the result + as a new object in the same vault, linked to the original document. + + Args: + output_format: Output format for the summary document + + workflow_type: Type of CaseMark workflow to run + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + if not id: + raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") + if not object_id: + raise ValueError(f"Expected a non-empty value for `object_id` but received {object_id!r}") + return await self._post( + path_template("/vault/{id}/objects/{object_id}/summarize", id=id, object_id=object_id), + body=await async_maybe_transform( + { + "output_format": output_format, + "workflow_type": workflow_type, + }, + object_summarize_params.ObjectSummarizeParams, + ), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=ObjectSummarizeResponse, + ) + class ObjectsResourceWithRawResponse: def __init__(self, objects: ObjectsResource) -> None: @@ -1188,6 +1445,9 @@ def __init__(self, objects: ObjectsResource) -> None: self.delete = to_raw_response_wrapper( objects.delete, ) + self.append = to_raw_response_wrapper( + objects.append, + ) self.create_presigned_url = to_raw_response_wrapper( objects.create_presigned_url, ) @@ -1210,6 +1470,9 @@ def __init__(self, objects: ObjectsResource) -> None: self.get_text = to_raw_response_wrapper( objects.get_text, ) + self.summarize = to_raw_response_wrapper( + objects.summarize, + ) class AsyncObjectsResourceWithRawResponse: @@ -1228,6 +1491,9 @@ def __init__(self, objects: AsyncObjectsResource) -> None: self.delete = async_to_raw_response_wrapper( objects.delete, ) + self.append = async_to_raw_response_wrapper( + objects.append, + ) self.create_presigned_url = async_to_raw_response_wrapper( objects.create_presigned_url, ) @@ -1250,6 +1516,9 @@ def __init__(self, objects: AsyncObjectsResource) -> None: self.get_text = async_to_raw_response_wrapper( objects.get_text, ) + self.summarize = async_to_raw_response_wrapper( + objects.summarize, + ) class ObjectsResourceWithStreamingResponse: @@ -1268,6 +1537,9 @@ def __init__(self, objects: ObjectsResource) -> None: self.delete = to_streamed_response_wrapper( objects.delete, ) + self.append = to_streamed_response_wrapper( + objects.append, + ) self.create_presigned_url = to_streamed_response_wrapper( objects.create_presigned_url, ) @@ -1290,6 +1562,9 @@ def __init__(self, objects: ObjectsResource) -> None: self.get_text = to_streamed_response_wrapper( objects.get_text, ) + self.summarize = to_streamed_response_wrapper( + objects.summarize, + ) class AsyncObjectsResourceWithStreamingResponse: @@ -1308,6 +1583,9 @@ def __init__(self, objects: AsyncObjectsResource) -> None: self.delete = async_to_streamed_response_wrapper( objects.delete, ) + self.append = async_to_streamed_response_wrapper( + objects.append, + ) self.create_presigned_url = async_to_streamed_response_wrapper( objects.create_presigned_url, ) @@ -1330,3 +1608,6 @@ def __init__(self, objects: AsyncObjectsResource) -> None: self.get_text = async_to_streamed_response_wrapper( objects.get_text, ) + self.summarize = async_to_streamed_response_wrapper( + objects.summarize, + ) diff --git a/src/casedev/resources/vault/vault.py b/src/casedev/resources/vault/vault.py index cd252ba8..2220a868 100644 --- a/src/casedev/resources/vault/vault.py +++ b/src/casedev/resources/vault/vault.py @@ -391,6 +391,7 @@ def confirm_upload( id: str, size_bytes: int, success: Literal[True], + auto_ingest: bool | Omit = omit, etag: str | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. @@ -410,6 +411,11 @@ def confirm_upload( success: Whether the upload succeeded + auto_ingest: When true and the object was uploaded with auto_index, trigger ingestion + immediately after a successful confirmation (no separate ingest call needed). + The ingest outcome is reported in the `ingest` response field; an ingest failure + does not fail the confirmation. + etag: S3 ETag for the uploaded object (optional if client cannot access ETag header) extra_headers: Send extra headers @@ -469,6 +475,7 @@ def confirm_upload( id: str, size_bytes: int | Omit = omit, success: Literal[True] | Literal[False], + auto_ingest: bool | Omit = omit, etag: str | Omit = omit, error_code: str | Omit = omit, error_message: str | Omit = omit, @@ -489,6 +496,7 @@ def confirm_upload( { "size_bytes": size_bytes, "success": success, + "auto_ingest": auto_ingest, "etag": etag, "error_code": error_code, "error_message": error_message, @@ -515,13 +523,13 @@ def ingest( ) -> VaultIngestResponse: """ Triggers ingestion workflow for a vault object to extract text, generate chunks, - and create embeddings. For supported file types (PDF, DOCX, PPTX, TXT, RTF, XML, - HTML, Markdown, CSV/TSV, JSON/YAML/TOML, common source code files, ZIP, audio, - video), processing happens asynchronously. ZIP archives are unpacked recursively - up to 5 levels, and each extracted file is created as an independent vault - object and ingested via the normal pipeline. For unsupported types (images, - etc.), the file is marked as completed immediately without text extraction. - GraphRAG indexing must be triggered separately via POST + and create embeddings. For supported file types (PDF, DOCX, PPTX, XLSX, TXT, + RTF, XML, HTML, Markdown, CSV/TSV, JSON/YAML/TOML, common source code files, + ZIP, audio, video), processing happens asynchronously. ZIP archives are unpacked + recursively up to 5 levels, and each extracted file is created as an independent + vault object and ingested via the normal pipeline. For unsupported types + (images, etc.), the file is marked as completed immediately without text + extraction. GraphRAG indexing must be triggered separately via POST /vault/:id/graphrag/:objectId. Args: @@ -611,6 +619,7 @@ def upload( content_type: str, filename: str, auto_index: bool | Omit = omit, + is_ai_generated: bool | Omit = omit, metadata: object | Omit = omit, path: str | Omit = omit, size_bytes: int | Omit = omit, @@ -633,6 +642,10 @@ def upload( auto_index: Whether to automatically process and index the file for search + is_ai_generated: Marks the file as AI-generated work product (e.g. uploaded by an agent) rather + than a user-provided source document. Persisted on the object and returned by + object listings so clients can distinguish provenance. + metadata: Additional metadata to associate with the file path: Optional folder path for hierarchy preservation. Allows integrations to maintain @@ -659,6 +672,7 @@ def upload( "content_type": content_type, "filename": filename, "auto_index": auto_index, + "is_ai_generated": is_ai_generated, "metadata": metadata, "path": path, "size_bytes": size_bytes, @@ -976,6 +990,7 @@ async def confirm_upload( id: str, size_bytes: int, success: Literal[True], + auto_ingest: bool | Omit = omit, etag: str | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. @@ -995,6 +1010,11 @@ async def confirm_upload( success: Whether the upload succeeded + auto_ingest: When true and the object was uploaded with auto_index, trigger ingestion + immediately after a successful confirmation (no separate ingest call needed). + The ingest outcome is reported in the `ingest` response field; an ingest failure + does not fail the confirmation. + etag: S3 ETag for the uploaded object (optional if client cannot access ETag header) extra_headers: Send extra headers @@ -1054,6 +1074,7 @@ async def confirm_upload( id: str, size_bytes: int | Omit = omit, success: Literal[True] | Literal[False], + auto_ingest: bool | Omit = omit, etag: str | Omit = omit, error_code: str | Omit = omit, error_message: str | Omit = omit, @@ -1074,6 +1095,7 @@ async def confirm_upload( { "size_bytes": size_bytes, "success": success, + "auto_ingest": auto_ingest, "etag": etag, "error_code": error_code, "error_message": error_message, @@ -1100,13 +1122,13 @@ async def ingest( ) -> VaultIngestResponse: """ Triggers ingestion workflow for a vault object to extract text, generate chunks, - and create embeddings. For supported file types (PDF, DOCX, PPTX, TXT, RTF, XML, - HTML, Markdown, CSV/TSV, JSON/YAML/TOML, common source code files, ZIP, audio, - video), processing happens asynchronously. ZIP archives are unpacked recursively - up to 5 levels, and each extracted file is created as an independent vault - object and ingested via the normal pipeline. For unsupported types (images, - etc.), the file is marked as completed immediately without text extraction. - GraphRAG indexing must be triggered separately via POST + and create embeddings. For supported file types (PDF, DOCX, PPTX, XLSX, TXT, + RTF, XML, HTML, Markdown, CSV/TSV, JSON/YAML/TOML, common source code files, + ZIP, audio, video), processing happens asynchronously. ZIP archives are unpacked + recursively up to 5 levels, and each extracted file is created as an independent + vault object and ingested via the normal pipeline. For unsupported types + (images, etc.), the file is marked as completed immediately without text + extraction. GraphRAG indexing must be triggered separately via POST /vault/:id/graphrag/:objectId. Args: @@ -1196,6 +1218,7 @@ async def upload( content_type: str, filename: str, auto_index: bool | Omit = omit, + is_ai_generated: bool | Omit = omit, metadata: object | Omit = omit, path: str | Omit = omit, size_bytes: int | Omit = omit, @@ -1218,6 +1241,10 @@ async def upload( auto_index: Whether to automatically process and index the file for search + is_ai_generated: Marks the file as AI-generated work product (e.g. uploaded by an agent) rather + than a user-provided source document. Persisted on the object and returned by + object listings so clients can distinguish provenance. + metadata: Additional metadata to associate with the file path: Optional folder path for hierarchy preservation. Allows integrations to maintain @@ -1244,6 +1271,7 @@ async def upload( "content_type": content_type, "filename": filename, "auto_index": auto_index, + "is_ai_generated": is_ai_generated, "metadata": metadata, "path": path, "size_bytes": size_bytes, diff --git a/src/casedev/types/document_templates/__init__.py b/src/casedev/types/document_templates/__init__.py new file mode 100644 index 00000000..f8ee8b14 --- /dev/null +++ b/src/casedev/types/document_templates/__init__.py @@ -0,0 +1,3 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations diff --git a/src/casedev/types/linc/__init__.py b/src/casedev/types/linc/__init__.py new file mode 100644 index 00000000..f8ee8b14 --- /dev/null +++ b/src/casedev/types/linc/__init__.py @@ -0,0 +1,3 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations diff --git a/src/casedev/types/linc/v1/__init__.py b/src/casedev/types/linc/v1/__init__.py new file mode 100644 index 00000000..8d55b574 --- /dev/null +++ b/src/casedev/types/linc/v1/__init__.py @@ -0,0 +1,9 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from .session_create_params import SessionCreateParams as SessionCreateParams +from .session_send_rpc_params import SessionSendRpcParams as SessionSendRpcParams +from .session_ingest_events_params import SessionIngestEventsParams as SessionIngestEventsParams +from .session_retrieve_events_params import SessionRetrieveEventsParams as SessionRetrieveEventsParams +from .session_retrieve_messages_params import SessionRetrieveMessagesParams as SessionRetrieveMessagesParams diff --git a/src/casedev/types/linc/v1/session_create_params.py b/src/casedev/types/linc/v1/session_create_params.py new file mode 100644 index 00000000..44f10ac8 --- /dev/null +++ b/src/casedev/types/linc/v1/session_create_params.py @@ -0,0 +1,45 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing import Optional +from typing_extensions import Annotated, TypedDict + +from ...._types import SequenceNotStr +from ...._utils import PropertyInfo + +__all__ = ["SessionCreateParams"] + + +class SessionCreateParams(TypedDict, total=False): + document_template_slugs: Annotated[Optional[SequenceNotStr[str]], PropertyInfo(alias="documentTemplateSlugs")] + """ + Specific document template slugs to inject into the using-document-templates + skill. + """ + + idle_timeout_ms: Annotated[Optional[int], PropertyInfo(alias="idleTimeoutMs")] + + include_document_templates: Annotated[Optional[bool], PropertyInfo(alias="includeDocumentTemplates")] + """ + When true, inject all active org document templates into the + using-document-templates skill. + """ + + instructions: Optional[str] + """Privileged C3-only hidden app instructions to append to the sandbox AGENTS.md.""" + + model: Optional[str] + + scoped_api_key: Annotated[Optional[str], PropertyInfo(alias="scopedApiKey")] + """Optional caller-provided scoped Case.dev API key for the runtime.""" + + skill_slugs: Annotated[Optional[SequenceNotStr[str]], PropertyInfo(alias="skillSlugs")] + """ + Skills API slugs to install into the runtime sandbox before the native session + starts. + """ + + title: str + + vault_ids: Annotated[Optional[SequenceNotStr[str]], PropertyInfo(alias="vaultIds")] diff --git a/src/casedev/types/linc/v1/session_ingest_events_params.py b/src/casedev/types/linc/v1/session_ingest_events_params.py new file mode 100644 index 00000000..d2bcc9a4 --- /dev/null +++ b/src/casedev/types/linc/v1/session_ingest_events_params.py @@ -0,0 +1,24 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing import Dict, Iterable +from typing_extensions import Required, TypedDict + +__all__ = ["SessionIngestEventsParams", "Frame"] + + +class SessionIngestEventsParams(TypedDict, total=False): + frames: Required[Iterable[Frame]] + """Native Linc event frames to persist for replay.""" + + +class Frame(TypedDict, total=False): + event: Required[Dict[str, object]] + """Native Linc event payload.""" + + seq: Required[int] + """Monotonic native event sequence number.""" + + type: Required[str] + """Native Linc event type.""" diff --git a/src/casedev/types/linc/v1/session_retrieve_events_params.py b/src/casedev/types/linc/v1/session_retrieve_events_params.py new file mode 100644 index 00000000..290bb90d --- /dev/null +++ b/src/casedev/types/linc/v1/session_retrieve_events_params.py @@ -0,0 +1,24 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing_extensions import Annotated, TypedDict + +from ...._types import SequenceNotStr +from ...._utils import PropertyInfo + +__all__ = ["SessionRetrieveEventsParams"] + + +class SessionRetrieveEventsParams(TypedDict, total=False): + after_seq: Annotated[int, PropertyInfo(alias="afterSeq")] + """Alias for cursor. Ignored when cursor is also provided.""" + + cursor: int + """Replay events with a sequence number greater than this cursor.""" + + exclude_event_types: Annotated[SequenceNotStr[str], PropertyInfo(alias="excludeEventTypes")] + """Comma-separated Linc event types to omit from replay.""" + + limit: int + """Maximum number of events to return.""" diff --git a/src/casedev/types/linc/v1/session_retrieve_messages_params.py b/src/casedev/types/linc/v1/session_retrieve_messages_params.py new file mode 100644 index 00000000..5135b75b --- /dev/null +++ b/src/casedev/types/linc/v1/session_retrieve_messages_params.py @@ -0,0 +1,20 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing_extensions import Annotated, TypedDict + +from ...._utils import PropertyInfo + +__all__ = ["SessionRetrieveMessagesParams"] + + +class SessionRetrieveMessagesParams(TypedDict, total=False): + after_seq: Annotated[int, PropertyInfo(alias="afterSeq")] + """Alias for cursor. Ignored when cursor is also provided.""" + + cursor: int + """Replay messages with a source event sequence number greater than this cursor.""" + + limit: int + """Maximum number of source events to scan for completed messages.""" diff --git a/src/casedev/types/linc/v1/session_send_rpc_params.py b/src/casedev/types/linc/v1/session_send_rpc_params.py new file mode 100644 index 00000000..1abe5398 --- /dev/null +++ b/src/casedev/types/linc/v1/session_send_rpc_params.py @@ -0,0 +1,20 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing_extensions import Required, Annotated, TypedDict + +from ...._utils import PropertyInfo + +__all__ = ["SessionSendRpcParams"] + + +class SessionSendRpcParams(TypedDict, total=False): + type: Required[str] + """Native Pi/Linc RPC command type. + + Prompt commands also require a string id for idempotency. + """ + + body_id: Annotated[str, PropertyInfo(alias="id")] + """Command idempotency key. Required when type is prompt.""" diff --git a/src/casedev/types/media/v1/transcripts/__init__.py b/src/casedev/types/media/v1/transcripts/__init__.py index f8ee8b14..ad7efe60 100644 --- a/src/casedev/types/media/v1/transcripts/__init__.py +++ b/src/casedev/types/media/v1/transcripts/__init__.py @@ -1,3 +1,6 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations + +from .retrieve_create_params import RetrieveCreateParams as RetrieveCreateParams +from .retrieve_create_response import RetrieveCreateResponse as RetrieveCreateResponse diff --git a/src/casedev/types/media/v1/transcripts/retrieve_create_params.py b/src/casedev/types/media/v1/transcripts/retrieve_create_params.py new file mode 100644 index 00000000..3e31cb3b --- /dev/null +++ b/src/casedev/types/media/v1/transcripts/retrieve_create_params.py @@ -0,0 +1,26 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing_extensions import Required, TypedDict + +__all__ = ["RetrieveCreateParams", "Transcript"] + + +class RetrieveCreateParams(TypedDict, total=False): + object_id: Required[str] + """Object ID for either the source audio/video file or transcript artifact.""" + + vault_id: Required[str] + """Vault ID containing the source media or transcript object.""" + + transcript: Transcript + """Alternative nested transcript object reference.""" + + +class Transcript(TypedDict, total=False): + """Alternative nested transcript object reference.""" + + object_id: str + + vault_id: str diff --git a/src/casedev/types/media/v1/transcripts/retrieve_create_response.py b/src/casedev/types/media/v1/transcripts/retrieve_create_response.py new file mode 100644 index 00000000..714f7c55 --- /dev/null +++ b/src/casedev/types/media/v1/transcripts/retrieve_create_response.py @@ -0,0 +1,37 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import Optional +from typing_extensions import Literal + +from ....._models import BaseModel + +__all__ = ["RetrieveCreateResponse"] + + +class RetrieveCreateResponse(BaseModel): + object_id: str + """Requested object ID.""" + + status: Literal["completed"] + + text: str + """Full transcript text.""" + + vault_id: str + + audio_duration: Optional[int] = None + + confidence: Optional[int] = None + + filename: Optional[str] = None + + source_object_id: Optional[str] = None + """Source media object ID when known.""" + + transcript_object_id: Optional[str] = None + """Transcript object ID when known.""" + + transcription_job_id: Optional[str] = None + """Transcription job ID when known.""" + + word_count: Optional[int] = None diff --git a/src/casedev/types/usage/v1_retrieve_params.py b/src/casedev/types/usage/v1_retrieve_params.py index bc0d74d9..26aae1a3 100644 --- a/src/casedev/types/usage/v1_retrieve_params.py +++ b/src/casedev/types/usage/v1_retrieve_params.py @@ -15,6 +15,18 @@ class V1RetrieveParams(TypedDict, total=False): granularity: Literal["summary", "daily"] """Whether to return period totals only or include daily buckets.""" + group_by: Annotated[Literal["lincSessionId"], PropertyInfo(alias="groupBy")] + """Optionally include usage groups keyed by native Linc session id. + + Only Linc-session-attributable usage is grouped. + """ + + linc_session_id: Annotated[str, PropertyInfo(alias="lincSessionId")] + """Restrict usage to a native Linc session. + + The session must belong to the authenticated organization. + """ + period_end: Annotated[Union[str, datetime], PropertyInfo(alias="periodEnd", format="iso8601")] """Period end date. Defaults to now.""" diff --git a/src/casedev/types/vault/__init__.py b/src/casedev/types/vault/__init__.py index 04f8aead..3847c97b 100644 --- a/src/casedev/types/vault/__init__.py +++ b/src/casedev/types/vault/__init__.py @@ -2,26 +2,34 @@ from __future__ import annotations +from .object_list_params import ObjectListParams as ObjectListParams from .group_create_params import GroupCreateParams as GroupCreateParams from .group_update_params import GroupUpdateParams as GroupUpdateParams from .memory_create_params import MemoryCreateParams as MemoryCreateParams from .memory_list_response import MemoryListResponse as MemoryListResponse from .memory_search_params import MemorySearchParams as MemorySearchParams from .memory_update_params import MemoryUpdateParams as MemoryUpdateParams +from .object_append_params import ObjectAppendParams as ObjectAppendParams from .object_delete_params import ObjectDeleteParams as ObjectDeleteParams from .object_list_response import ObjectListResponse as ObjectListResponse from .object_update_params import ObjectUpdateParams as ObjectUpdateParams +from .multipart_init_params import MultipartInitParams as MultipartInitParams from .graphrag_init_response import GraphragInitResponse as GraphragInitResponse from .memory_create_response import MemoryCreateResponse as MemoryCreateResponse from .memory_search_response import MemorySearchResponse as MemorySearchResponse from .multipart_abort_params import MultipartAbortParams as MultipartAbortParams +from .object_append_response import ObjectAppendResponse as ObjectAppendResponse from .object_delete_response import ObjectDeleteResponse as ObjectDeleteResponse from .object_update_response import ObjectUpdateResponse as ObjectUpdateResponse +from .multipart_init_response import MultipartInitResponse as MultipartInitResponse from .object_get_pages_params import ObjectGetPagesParams as ObjectGetPagesParams +from .object_summarize_params import ObjectSummarizeParams as ObjectSummarizeParams from .object_get_chunks_params import ObjectGetChunksParams as ObjectGetChunksParams from .object_get_text_response import ObjectGetTextResponse as ObjectGetTextResponse from .object_retrieve_response import ObjectRetrieveResponse as ObjectRetrieveResponse +from .multipart_complete_params import MultipartCompleteParams as MultipartCompleteParams from .object_get_pages_response import ObjectGetPagesResponse as ObjectGetPagesResponse +from .object_summarize_response import ObjectSummarizeResponse as ObjectSummarizeResponse from .object_get_chunks_response import ObjectGetChunksResponse as ObjectGetChunksResponse from .graphrag_get_stats_response import GraphragGetStatsResponse as GraphragGetStatsResponse from .object_get_ocr_words_params import ObjectGetOcrWordsParams as ObjectGetOcrWordsParams diff --git a/src/casedev/types/vault/multipart_complete_params.py b/src/casedev/types/vault/multipart_complete_params.py new file mode 100644 index 00000000..a3ec147f --- /dev/null +++ b/src/casedev/types/vault/multipart_complete_params.py @@ -0,0 +1,30 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing import Iterable +from typing_extensions import Required, Annotated, TypedDict + +from ..._utils import PropertyInfo + +__all__ = ["MultipartCompleteParams", "Part"] + + +class MultipartCompleteParams(TypedDict, total=False): + object_id: Required[Annotated[str, PropertyInfo(alias="objectId")]] + + parts: Required[Iterable[Part]] + + size_bytes: Required[Annotated[int, PropertyInfo(alias="sizeBytes")]] + """File size in bytes (default max 16GB). + + Configure via VAULT_MULTIPART_MAX_FILE_SIZE_BYTES. + """ + + upload_id: Required[Annotated[str, PropertyInfo(alias="uploadId")]] + + +class Part(TypedDict, total=False): + etag: Required[str] + + part_number: Required[Annotated[int, PropertyInfo(alias="partNumber")]] diff --git a/src/casedev/types/vault/multipart_init_params.py b/src/casedev/types/vault/multipart_init_params.py new file mode 100644 index 00000000..83dc21a6 --- /dev/null +++ b/src/casedev/types/vault/multipart_init_params.py @@ -0,0 +1,43 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing_extensions import Required, Annotated, TypedDict + +from ..._utils import PropertyInfo + +__all__ = ["MultipartInitParams"] + + +class MultipartInitParams(TypedDict, total=False): + content_type: Required[Annotated[str, PropertyInfo(alias="contentType")]] + """MIME type of the file""" + + filename: Required[str] + """Name of the file to upload""" + + size_bytes: Required[Annotated[int, PropertyInfo(alias="sizeBytes")]] + """File size in bytes (required, default max 16GB). + + Configure via VAULT_MULTIPART_MAX_FILE_SIZE_BYTES. + """ + + auto_index: bool + """Whether to automatically process and index the file for search""" + + is_ai_generated: bool + """Marks the file as AI-generated work product (e.g. + + uploaded by an agent) rather than a user-provided source document. Persisted on + the object and returned by object listings so clients can distinguish + provenance. + """ + + metadata: object + """Additional metadata to associate with the file""" + + part_size_bytes: Annotated[int, PropertyInfo(alias="partSizeBytes")] + """Multipart part size in bytes (min 5MB, max 5GB). Defaults to 64MB.""" + + path: str + """Optional folder path for hierarchy preservation""" diff --git a/src/casedev/types/vault/multipart_init_response.py b/src/casedev/types/vault/multipart_init_response.py new file mode 100644 index 00000000..2ec7c9b6 --- /dev/null +++ b/src/casedev/types/vault/multipart_init_response.py @@ -0,0 +1,23 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import Optional + +from pydantic import Field as FieldInfo + +from ..._models import BaseModel + +__all__ = ["MultipartInitResponse"] + + +class MultipartInitResponse(BaseModel): + next_step: Optional[str] = None + + object_id: Optional[str] = FieldInfo(alias="objectId", default=None) + + part_count: Optional[int] = FieldInfo(alias="partCount", default=None) + + part_size_bytes: Optional[int] = FieldInfo(alias="partSizeBytes", default=None) + + s3_key: Optional[str] = FieldInfo(alias="s3Key", default=None) + + upload_id: Optional[str] = FieldInfo(alias="uploadId", default=None) diff --git a/src/casedev/types/vault/object_append_params.py b/src/casedev/types/vault/object_append_params.py new file mode 100644 index 00000000..7be67633 --- /dev/null +++ b/src/casedev/types/vault/object_append_params.py @@ -0,0 +1,37 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing_extensions import Required, Annotated, TypedDict + +from ..._types import SequenceNotStr +from ..._utils import PropertyInfo + +__all__ = ["ObjectAppendParams"] + + +class ObjectAppendParams(TypedDict, total=False): + id: Required[str] + + append_object_ids: Required[Annotated[SequenceNotStr[str], PropertyInfo(alias="appendObjectIds")]] + """Vault object IDs whose pages will be appended onto the target object, in order. + + Must not include the target object itself. + """ + + back_links: Annotated[bool, PropertyInfo(alias="backLinks")] + """Adds back links on appended pages""" + + back_links_text: Annotated[str, PropertyInfo(alias="backLinksText")] + """Label text for the back link. + + Used only when backLinks is true and rendered centered at the bottom of each + appended page. + """ + + rewrite_links: Annotated[bool, PropertyInfo(alias="rewriteLinks")] + """ + When true, rewrites links in the target object to internal PDF jumps when the + URL contains exactly one appended object ID as a standalone query parameter + value or decoded path segment. + """ diff --git a/src/casedev/types/vault/object_append_response.py b/src/casedev/types/vault/object_append_response.py new file mode 100644 index 00000000..c038e0b3 --- /dev/null +++ b/src/casedev/types/vault/object_append_response.py @@ -0,0 +1,36 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import Optional +from datetime import datetime + +from pydantic import Field as FieldInfo + +from ..._models import BaseModel + +__all__ = ["ObjectAppendResponse"] + + +class ObjectAppendResponse(BaseModel): + id: Optional[str] = None + + checksum: Optional[str] = None + + content_type: Optional[str] = FieldInfo(alias="contentType", default=None) + + created_at: Optional[datetime] = FieldInfo(alias="createdAt", default=None) + + download_url: Optional[str] = FieldInfo(alias="downloadUrl", default=None) + + expires_in: Optional[int] = FieldInfo(alias="expiresIn", default=None) + + filename: Optional[str] = None + + ingestion_status: Optional[str] = FieldInfo(alias="ingestionStatus", default=None) + + metadata: Optional[object] = None + + page_count: Optional[int] = FieldInfo(alias="pageCount", default=None) + + size_bytes: Optional[int] = FieldInfo(alias="sizeBytes", default=None) + + vault_id: Optional[str] = FieldInfo(alias="vaultId", default=None) diff --git a/src/casedev/types/vault/object_list_params.py b/src/casedev/types/vault/object_list_params.py new file mode 100644 index 00000000..76d13deb --- /dev/null +++ b/src/casedev/types/vault/object_list_params.py @@ -0,0 +1,17 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing_extensions import Annotated, TypedDict + +from ..._utils import PropertyInfo + +__all__ = ["ObjectListParams"] + + +class ObjectListParams(TypedDict, total=False): + include_unconfirmed: Annotated[bool, PropertyInfo(alias="includeUnconfirmed")] + """ + Include placeholders for uploads that were never completed (awaiting_upload) or + were cancelled (aborted). Excluded by default. + """ diff --git a/src/casedev/types/vault/object_list_response.py b/src/casedev/types/vault/object_list_response.py index c057ee51..8e350e94 100644 --- a/src/casedev/types/vault/object_list_response.py +++ b/src/casedev/types/vault/object_list_response.py @@ -41,6 +41,9 @@ class Object(BaseModel): ingestion_workflow_id: Optional[str] = FieldInfo(alias="ingestionWorkflowId", default=None) """Durable workflow run ID for the active or last ingestion attempt""" + is_ai_generated: Optional[bool] = None + """Whether the file was marked as AI-generated work product at upload time""" + metadata: Optional[object] = None """Custom metadata associated with the document""" diff --git a/src/casedev/types/vault/object_retrieve_response.py b/src/casedev/types/vault/object_retrieve_response.py index 72eeccc8..df9be6bf 100644 --- a/src/casedev/types/vault/object_retrieve_response.py +++ b/src/casedev/types/vault/object_retrieve_response.py @@ -41,6 +41,9 @@ class ObjectRetrieveResponse(BaseModel): ingestion_error: Optional[str] = FieldInfo(alias="ingestionError", default=None) """Error details when ingestion fails""" + is_ai_generated: Optional[bool] = None + """Whether the file was marked as AI-generated work product at upload time""" + metadata: Optional[object] = None """Additional metadata""" diff --git a/src/casedev/types/vault/object_summarize_params.py b/src/casedev/types/vault/object_summarize_params.py new file mode 100644 index 00000000..7dfc29d7 --- /dev/null +++ b/src/casedev/types/vault/object_summarize_params.py @@ -0,0 +1,19 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing_extensions import Literal, Required, Annotated, TypedDict + +from ..._utils import PropertyInfo + +__all__ = ["ObjectSummarizeParams"] + + +class ObjectSummarizeParams(TypedDict, total=False): + id: Required[str] + + output_format: Annotated[Literal["PDF", "WORD"], PropertyInfo(alias="outputFormat")] + """Output format for the summary document""" + + workflow_type: Annotated[str, PropertyInfo(alias="workflowType")] + """Type of CaseMark workflow to run""" diff --git a/src/casedev/types/vault/object_summarize_response.py b/src/casedev/types/vault/object_summarize_response.py new file mode 100644 index 00000000..d7205994 --- /dev/null +++ b/src/casedev/types/vault/object_summarize_response.py @@ -0,0 +1,27 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import Optional +from typing_extensions import Literal + +from pydantic import Field as FieldInfo + +from ..._models import BaseModel + +__all__ = ["ObjectSummarizeResponse"] + + +class ObjectSummarizeResponse(BaseModel): + casemark_workflow_id: Optional[str] = FieldInfo(alias="casemarkWorkflowId", default=None) + """CaseMark workflow ID""" + + job_id: Optional[str] = FieldInfo(alias="jobId", default=None) + """Case.dev job ID for tracking""" + + status: Optional[Literal["pending", "processing", "completed", "failed"]] = None + """Current job status""" + + status_url: Optional[str] = FieldInfo(alias="statusUrl", default=None) + """URL to check job status""" + + workflow_type: Optional[str] = FieldInfo(alias="workflowType", default=None) + """Type of workflow being executed""" diff --git a/src/casedev/types/vault_confirm_upload_params.py b/src/casedev/types/vault_confirm_upload_params.py index f71b18a5..f094a8a9 100644 --- a/src/casedev/types/vault_confirm_upload_params.py +++ b/src/casedev/types/vault_confirm_upload_params.py @@ -19,6 +19,14 @@ class VaultConfirmUploadSuccess(TypedDict, total=False): success: Required[Literal[True]] """Whether the upload succeeded""" + auto_ingest: Annotated[bool, PropertyInfo(alias="autoIngest")] + """ + When true and the object was uploaded with auto_index, trigger ingestion + immediately after a successful confirmation (no separate ingest call needed). + The ingest outcome is reported in the `ingest` response field; an ingest failure + does not fail the confirmation. + """ + etag: str """S3 ETag for the uploaded object (optional if client cannot access ETag header)""" diff --git a/src/casedev/types/vault_confirm_upload_response.py b/src/casedev/types/vault_confirm_upload_response.py index 697110ca..0c790222 100644 --- a/src/casedev/types/vault_confirm_upload_response.py +++ b/src/casedev/types/vault_confirm_upload_response.py @@ -7,12 +7,25 @@ from .._models import BaseModel -__all__ = ["VaultConfirmUploadResponse"] +__all__ = ["VaultConfirmUploadResponse", "Ingest"] + + +class Ingest(BaseModel): + """Present when autoIngest was requested on a successful confirmation""" + + error: Optional[str] = None + + triggered: Optional[bool] = None + + workflow_id: Optional[str] = FieldInfo(alias="workflowId", default=None) class VaultConfirmUploadResponse(BaseModel): already_confirmed: Optional[bool] = FieldInfo(alias="alreadyConfirmed", default=None) + ingest: Optional[Ingest] = None + """Present when autoIngest was requested on a successful confirmation""" + object_id: Optional[str] = FieldInfo(alias="objectId", default=None) status: Optional[Literal["completed", "failed"]] = None diff --git a/src/casedev/types/vault_upload_params.py b/src/casedev/types/vault_upload_params.py index d3bcdcc1..034db6bc 100644 --- a/src/casedev/types/vault_upload_params.py +++ b/src/casedev/types/vault_upload_params.py @@ -19,6 +19,14 @@ class VaultUploadParams(TypedDict, total=False): auto_index: bool """Whether to automatically process and index the file for search""" + is_ai_generated: bool + """Marks the file as AI-generated work product (e.g. + + uploaded by an agent) rather than a user-provided source document. Persisted on + the object and returned by object listings so clients can distinguish + provenance. + """ + metadata: object """Additional metadata to associate with the file""" diff --git a/src/casedev/types/vault_upload_response.py b/src/casedev/types/vault_upload_response.py index d4ae7fa1..aba99367 100644 --- a/src/casedev/types/vault_upload_response.py +++ b/src/casedev/types/vault_upload_response.py @@ -29,6 +29,9 @@ class VaultUploadResponse(BaseModel): instructions: Optional[Instructions] = None + is_ai_generated: Optional[bool] = None + """Whether the file is marked as AI-generated work product""" + next_step: Optional[str] = None """Next API endpoint to call for processing""" diff --git a/tests/api_resources/document_templates/__init__.py b/tests/api_resources/document_templates/__init__.py new file mode 100644 index 00000000..fd8019a9 --- /dev/null +++ b/tests/api_resources/document_templates/__init__.py @@ -0,0 +1 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. diff --git a/tests/api_resources/document_templates/test_from_vault_object.py b/tests/api_resources/document_templates/test_from_vault_object.py new file mode 100644 index 00000000..39a95ca2 --- /dev/null +++ b/tests/api_resources/document_templates/test_from_vault_object.py @@ -0,0 +1,72 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +import os +from typing import Any, cast + +import pytest + +from casedev import Casedev, AsyncCasedev + +base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") + + +class TestFromVaultObject: + parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"]) + + @parametrize + def test_method_create(self, client: Casedev) -> None: + from_vault_object = client.document_templates.from_vault_object.create() + assert from_vault_object is None + + @parametrize + def test_raw_response_create(self, client: Casedev) -> None: + response = client.document_templates.from_vault_object.with_raw_response.create() + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + from_vault_object = response.parse() + assert from_vault_object is None + + @parametrize + def test_streaming_response_create(self, client: Casedev) -> None: + with client.document_templates.from_vault_object.with_streaming_response.create() as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + from_vault_object = response.parse() + assert from_vault_object is None + + assert cast(Any, response.is_closed) is True + + +class TestAsyncFromVaultObject: + parametrize = pytest.mark.parametrize( + "async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"] + ) + + @parametrize + async def test_method_create(self, async_client: AsyncCasedev) -> None: + from_vault_object = await async_client.document_templates.from_vault_object.create() + assert from_vault_object is None + + @parametrize + async def test_raw_response_create(self, async_client: AsyncCasedev) -> None: + response = await async_client.document_templates.from_vault_object.with_raw_response.create() + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + from_vault_object = await response.parse() + assert from_vault_object is None + + @parametrize + async def test_streaming_response_create(self, async_client: AsyncCasedev) -> None: + async with async_client.document_templates.from_vault_object.with_streaming_response.create() as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + from_vault_object = await response.parse() + assert from_vault_object is None + + assert cast(Any, response.is_closed) is True diff --git a/tests/api_resources/linc/__init__.py b/tests/api_resources/linc/__init__.py new file mode 100644 index 00000000..fd8019a9 --- /dev/null +++ b/tests/api_resources/linc/__init__.py @@ -0,0 +1 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. diff --git a/tests/api_resources/linc/v1/__init__.py b/tests/api_resources/linc/v1/__init__.py new file mode 100644 index 00000000..fd8019a9 --- /dev/null +++ b/tests/api_resources/linc/v1/__init__.py @@ -0,0 +1 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. diff --git a/tests/api_resources/linc/v1/test_sessions.py b/tests/api_resources/linc/v1/test_sessions.py new file mode 100644 index 00000000..6cf63563 --- /dev/null +++ b/tests/api_resources/linc/v1/test_sessions.py @@ -0,0 +1,758 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +import os +from typing import Any, cast + +import pytest + +from casedev import Casedev, AsyncCasedev + +base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") + + +class TestSessions: + parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"]) + + @parametrize + def test_method_create(self, client: Casedev) -> None: + session = client.linc.v1.sessions.create() + assert session is None + + @parametrize + def test_method_create_with_all_params(self, client: Casedev) -> None: + session = client.linc.v1.sessions.create( + document_template_slugs=["string"], + idle_timeout_ms=0, + include_document_templates=True, + instructions="instructions", + model="model", + scoped_api_key="scopedApiKey", + skill_slugs=["string"], + title="title", + vault_ids=["string"], + ) + assert session is None + + @parametrize + def test_raw_response_create(self, client: Casedev) -> None: + response = client.linc.v1.sessions.with_raw_response.create() + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + session = response.parse() + assert session is None + + @parametrize + def test_streaming_response_create(self, client: Casedev) -> None: + with client.linc.v1.sessions.with_streaming_response.create() as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + session = response.parse() + assert session is None + + assert cast(Any, response.is_closed) is True + + @parametrize + def test_method_delete(self, client: Casedev) -> None: + session = client.linc.v1.sessions.delete( + "id", + ) + assert session is None + + @parametrize + def test_raw_response_delete(self, client: Casedev) -> None: + response = client.linc.v1.sessions.with_raw_response.delete( + "id", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + session = response.parse() + assert session is None + + @parametrize + def test_streaming_response_delete(self, client: Casedev) -> None: + with client.linc.v1.sessions.with_streaming_response.delete( + "id", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + session = response.parse() + assert session is None + + assert cast(Any, response.is_closed) is True + + @parametrize + def test_path_params_delete(self, client: Casedev) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): + client.linc.v1.sessions.with_raw_response.delete( + "", + ) + + @parametrize + def test_method_cancel(self, client: Casedev) -> None: + session = client.linc.v1.sessions.cancel( + "id", + ) + assert session is None + + @parametrize + def test_raw_response_cancel(self, client: Casedev) -> None: + response = client.linc.v1.sessions.with_raw_response.cancel( + "id", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + session = response.parse() + assert session is None + + @parametrize + def test_streaming_response_cancel(self, client: Casedev) -> None: + with client.linc.v1.sessions.with_streaming_response.cancel( + "id", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + session = response.parse() + assert session is None + + assert cast(Any, response.is_closed) is True + + @parametrize + def test_path_params_cancel(self, client: Casedev) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): + client.linc.v1.sessions.with_raw_response.cancel( + "", + ) + + @parametrize + def test_method_ingest_events(self, client: Casedev) -> None: + session = client.linc.v1.sessions.ingest_events( + id="id", + frames=[ + { + "event": {"foo": "bar"}, + "seq": 1, + "type": "type", + } + ], + ) + assert session is None + + @parametrize + def test_raw_response_ingest_events(self, client: Casedev) -> None: + response = client.linc.v1.sessions.with_raw_response.ingest_events( + id="id", + frames=[ + { + "event": {"foo": "bar"}, + "seq": 1, + "type": "type", + } + ], + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + session = response.parse() + assert session is None + + @parametrize + def test_streaming_response_ingest_events(self, client: Casedev) -> None: + with client.linc.v1.sessions.with_streaming_response.ingest_events( + id="id", + frames=[ + { + "event": {"foo": "bar"}, + "seq": 1, + "type": "type", + } + ], + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + session = response.parse() + assert session is None + + assert cast(Any, response.is_closed) is True + + @parametrize + def test_path_params_ingest_events(self, client: Casedev) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): + client.linc.v1.sessions.with_raw_response.ingest_events( + id="", + frames=[ + { + "event": {"foo": "bar"}, + "seq": 1, + "type": "type", + } + ], + ) + + @parametrize + def test_method_retrieve_events(self, client: Casedev) -> None: + session = client.linc.v1.sessions.retrieve_events( + id="id", + ) + assert session is None + + @parametrize + def test_method_retrieve_events_with_all_params(self, client: Casedev) -> None: + session = client.linc.v1.sessions.retrieve_events( + id="id", + after_seq=0, + cursor=0, + exclude_event_types=["string"], + limit=1, + ) + assert session is None + + @parametrize + def test_raw_response_retrieve_events(self, client: Casedev) -> None: + response = client.linc.v1.sessions.with_raw_response.retrieve_events( + id="id", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + session = response.parse() + assert session is None + + @parametrize + def test_streaming_response_retrieve_events(self, client: Casedev) -> None: + with client.linc.v1.sessions.with_streaming_response.retrieve_events( + id="id", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + session = response.parse() + assert session is None + + assert cast(Any, response.is_closed) is True + + @parametrize + def test_path_params_retrieve_events(self, client: Casedev) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): + client.linc.v1.sessions.with_raw_response.retrieve_events( + id="", + ) + + @parametrize + def test_method_retrieve_messages(self, client: Casedev) -> None: + session = client.linc.v1.sessions.retrieve_messages( + id="id", + ) + assert session is None + + @parametrize + def test_method_retrieve_messages_with_all_params(self, client: Casedev) -> None: + session = client.linc.v1.sessions.retrieve_messages( + id="id", + after_seq=0, + cursor=0, + limit=1, + ) + assert session is None + + @parametrize + def test_raw_response_retrieve_messages(self, client: Casedev) -> None: + response = client.linc.v1.sessions.with_raw_response.retrieve_messages( + id="id", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + session = response.parse() + assert session is None + + @parametrize + def test_streaming_response_retrieve_messages(self, client: Casedev) -> None: + with client.linc.v1.sessions.with_streaming_response.retrieve_messages( + id="id", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + session = response.parse() + assert session is None + + assert cast(Any, response.is_closed) is True + + @parametrize + def test_path_params_retrieve_messages(self, client: Casedev) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): + client.linc.v1.sessions.with_raw_response.retrieve_messages( + id="", + ) + + @parametrize + def test_method_retrieve_state(self, client: Casedev) -> None: + session = client.linc.v1.sessions.retrieve_state( + "id", + ) + assert session is None + + @parametrize + def test_raw_response_retrieve_state(self, client: Casedev) -> None: + response = client.linc.v1.sessions.with_raw_response.retrieve_state( + "id", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + session = response.parse() + assert session is None + + @parametrize + def test_streaming_response_retrieve_state(self, client: Casedev) -> None: + with client.linc.v1.sessions.with_streaming_response.retrieve_state( + "id", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + session = response.parse() + assert session is None + + assert cast(Any, response.is_closed) is True + + @parametrize + def test_path_params_retrieve_state(self, client: Casedev) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): + client.linc.v1.sessions.with_raw_response.retrieve_state( + "", + ) + + @parametrize + def test_method_send_rpc(self, client: Casedev) -> None: + session = client.linc.v1.sessions.send_rpc( + path_id="id", + type="type", + ) + assert session is None + + @parametrize + def test_method_send_rpc_with_all_params(self, client: Casedev) -> None: + session = client.linc.v1.sessions.send_rpc( + path_id="id", + type="type", + body_id="id", + ) + assert session is None + + @parametrize + def test_raw_response_send_rpc(self, client: Casedev) -> None: + response = client.linc.v1.sessions.with_raw_response.send_rpc( + path_id="id", + type="type", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + session = response.parse() + assert session is None + + @parametrize + def test_streaming_response_send_rpc(self, client: Casedev) -> None: + with client.linc.v1.sessions.with_streaming_response.send_rpc( + path_id="id", + type="type", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + session = response.parse() + assert session is None + + assert cast(Any, response.is_closed) is True + + @parametrize + def test_path_params_send_rpc(self, client: Casedev) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `path_id` but received ''"): + client.linc.v1.sessions.with_raw_response.send_rpc( + path_id="", + type="type", + ) + + +class TestAsyncSessions: + parametrize = pytest.mark.parametrize( + "async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"] + ) + + @parametrize + async def test_method_create(self, async_client: AsyncCasedev) -> None: + session = await async_client.linc.v1.sessions.create() + assert session is None + + @parametrize + async def test_method_create_with_all_params(self, async_client: AsyncCasedev) -> None: + session = await async_client.linc.v1.sessions.create( + document_template_slugs=["string"], + idle_timeout_ms=0, + include_document_templates=True, + instructions="instructions", + model="model", + scoped_api_key="scopedApiKey", + skill_slugs=["string"], + title="title", + vault_ids=["string"], + ) + assert session is None + + @parametrize + async def test_raw_response_create(self, async_client: AsyncCasedev) -> None: + response = await async_client.linc.v1.sessions.with_raw_response.create() + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + session = await response.parse() + assert session is None + + @parametrize + async def test_streaming_response_create(self, async_client: AsyncCasedev) -> None: + async with async_client.linc.v1.sessions.with_streaming_response.create() as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + session = await response.parse() + assert session is None + + assert cast(Any, response.is_closed) is True + + @parametrize + async def test_method_delete(self, async_client: AsyncCasedev) -> None: + session = await async_client.linc.v1.sessions.delete( + "id", + ) + assert session is None + + @parametrize + async def test_raw_response_delete(self, async_client: AsyncCasedev) -> None: + response = await async_client.linc.v1.sessions.with_raw_response.delete( + "id", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + session = await response.parse() + assert session is None + + @parametrize + async def test_streaming_response_delete(self, async_client: AsyncCasedev) -> None: + async with async_client.linc.v1.sessions.with_streaming_response.delete( + "id", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + session = await response.parse() + assert session is None + + assert cast(Any, response.is_closed) is True + + @parametrize + async def test_path_params_delete(self, async_client: AsyncCasedev) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): + await async_client.linc.v1.sessions.with_raw_response.delete( + "", + ) + + @parametrize + async def test_method_cancel(self, async_client: AsyncCasedev) -> None: + session = await async_client.linc.v1.sessions.cancel( + "id", + ) + assert session is None + + @parametrize + async def test_raw_response_cancel(self, async_client: AsyncCasedev) -> None: + response = await async_client.linc.v1.sessions.with_raw_response.cancel( + "id", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + session = await response.parse() + assert session is None + + @parametrize + async def test_streaming_response_cancel(self, async_client: AsyncCasedev) -> None: + async with async_client.linc.v1.sessions.with_streaming_response.cancel( + "id", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + session = await response.parse() + assert session is None + + assert cast(Any, response.is_closed) is True + + @parametrize + async def test_path_params_cancel(self, async_client: AsyncCasedev) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): + await async_client.linc.v1.sessions.with_raw_response.cancel( + "", + ) + + @parametrize + async def test_method_ingest_events(self, async_client: AsyncCasedev) -> None: + session = await async_client.linc.v1.sessions.ingest_events( + id="id", + frames=[ + { + "event": {"foo": "bar"}, + "seq": 1, + "type": "type", + } + ], + ) + assert session is None + + @parametrize + async def test_raw_response_ingest_events(self, async_client: AsyncCasedev) -> None: + response = await async_client.linc.v1.sessions.with_raw_response.ingest_events( + id="id", + frames=[ + { + "event": {"foo": "bar"}, + "seq": 1, + "type": "type", + } + ], + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + session = await response.parse() + assert session is None + + @parametrize + async def test_streaming_response_ingest_events(self, async_client: AsyncCasedev) -> None: + async with async_client.linc.v1.sessions.with_streaming_response.ingest_events( + id="id", + frames=[ + { + "event": {"foo": "bar"}, + "seq": 1, + "type": "type", + } + ], + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + session = await response.parse() + assert session is None + + assert cast(Any, response.is_closed) is True + + @parametrize + async def test_path_params_ingest_events(self, async_client: AsyncCasedev) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): + await async_client.linc.v1.sessions.with_raw_response.ingest_events( + id="", + frames=[ + { + "event": {"foo": "bar"}, + "seq": 1, + "type": "type", + } + ], + ) + + @parametrize + async def test_method_retrieve_events(self, async_client: AsyncCasedev) -> None: + session = await async_client.linc.v1.sessions.retrieve_events( + id="id", + ) + assert session is None + + @parametrize + async def test_method_retrieve_events_with_all_params(self, async_client: AsyncCasedev) -> None: + session = await async_client.linc.v1.sessions.retrieve_events( + id="id", + after_seq=0, + cursor=0, + exclude_event_types=["string"], + limit=1, + ) + assert session is None + + @parametrize + async def test_raw_response_retrieve_events(self, async_client: AsyncCasedev) -> None: + response = await async_client.linc.v1.sessions.with_raw_response.retrieve_events( + id="id", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + session = await response.parse() + assert session is None + + @parametrize + async def test_streaming_response_retrieve_events(self, async_client: AsyncCasedev) -> None: + async with async_client.linc.v1.sessions.with_streaming_response.retrieve_events( + id="id", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + session = await response.parse() + assert session is None + + assert cast(Any, response.is_closed) is True + + @parametrize + async def test_path_params_retrieve_events(self, async_client: AsyncCasedev) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): + await async_client.linc.v1.sessions.with_raw_response.retrieve_events( + id="", + ) + + @parametrize + async def test_method_retrieve_messages(self, async_client: AsyncCasedev) -> None: + session = await async_client.linc.v1.sessions.retrieve_messages( + id="id", + ) + assert session is None + + @parametrize + async def test_method_retrieve_messages_with_all_params(self, async_client: AsyncCasedev) -> None: + session = await async_client.linc.v1.sessions.retrieve_messages( + id="id", + after_seq=0, + cursor=0, + limit=1, + ) + assert session is None + + @parametrize + async def test_raw_response_retrieve_messages(self, async_client: AsyncCasedev) -> None: + response = await async_client.linc.v1.sessions.with_raw_response.retrieve_messages( + id="id", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + session = await response.parse() + assert session is None + + @parametrize + async def test_streaming_response_retrieve_messages(self, async_client: AsyncCasedev) -> None: + async with async_client.linc.v1.sessions.with_streaming_response.retrieve_messages( + id="id", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + session = await response.parse() + assert session is None + + assert cast(Any, response.is_closed) is True + + @parametrize + async def test_path_params_retrieve_messages(self, async_client: AsyncCasedev) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): + await async_client.linc.v1.sessions.with_raw_response.retrieve_messages( + id="", + ) + + @parametrize + async def test_method_retrieve_state(self, async_client: AsyncCasedev) -> None: + session = await async_client.linc.v1.sessions.retrieve_state( + "id", + ) + assert session is None + + @parametrize + async def test_raw_response_retrieve_state(self, async_client: AsyncCasedev) -> None: + response = await async_client.linc.v1.sessions.with_raw_response.retrieve_state( + "id", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + session = await response.parse() + assert session is None + + @parametrize + async def test_streaming_response_retrieve_state(self, async_client: AsyncCasedev) -> None: + async with async_client.linc.v1.sessions.with_streaming_response.retrieve_state( + "id", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + session = await response.parse() + assert session is None + + assert cast(Any, response.is_closed) is True + + @parametrize + async def test_path_params_retrieve_state(self, async_client: AsyncCasedev) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): + await async_client.linc.v1.sessions.with_raw_response.retrieve_state( + "", + ) + + @parametrize + async def test_method_send_rpc(self, async_client: AsyncCasedev) -> None: + session = await async_client.linc.v1.sessions.send_rpc( + path_id="id", + type="type", + ) + assert session is None + + @parametrize + async def test_method_send_rpc_with_all_params(self, async_client: AsyncCasedev) -> None: + session = await async_client.linc.v1.sessions.send_rpc( + path_id="id", + type="type", + body_id="id", + ) + assert session is None + + @parametrize + async def test_raw_response_send_rpc(self, async_client: AsyncCasedev) -> None: + response = await async_client.linc.v1.sessions.with_raw_response.send_rpc( + path_id="id", + type="type", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + session = await response.parse() + assert session is None + + @parametrize + async def test_streaming_response_send_rpc(self, async_client: AsyncCasedev) -> None: + async with async_client.linc.v1.sessions.with_streaming_response.send_rpc( + path_id="id", + type="type", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + session = await response.parse() + assert session is None + + assert cast(Any, response.is_closed) is True + + @parametrize + async def test_path_params_send_rpc(self, async_client: AsyncCasedev) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `path_id` but received ''"): + await async_client.linc.v1.sessions.with_raw_response.send_rpc( + path_id="", + type="type", + ) diff --git a/tests/api_resources/media/v1/transcripts/test_retrieve.py b/tests/api_resources/media/v1/transcripts/test_retrieve.py new file mode 100644 index 00000000..aba332cc --- /dev/null +++ b/tests/api_resources/media/v1/transcripts/test_retrieve.py @@ -0,0 +1,116 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +import os +from typing import Any, cast + +import pytest + +from casedev import Casedev, AsyncCasedev +from tests.utils import assert_matches_type +from casedev.types.media.v1.transcripts import RetrieveCreateResponse + +base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") + + +class TestRetrieve: + parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"]) + + @parametrize + def test_method_create(self, client: Casedev) -> None: + retrieve = client.media.v1.transcripts.retrieve.create( + object_id="object_id", + vault_id="vault_id", + ) + assert_matches_type(RetrieveCreateResponse, retrieve, path=["response"]) + + @parametrize + def test_method_create_with_all_params(self, client: Casedev) -> None: + retrieve = client.media.v1.transcripts.retrieve.create( + object_id="object_id", + vault_id="vault_id", + transcript={ + "object_id": "object_id", + "vault_id": "vault_id", + }, + ) + assert_matches_type(RetrieveCreateResponse, retrieve, path=["response"]) + + @parametrize + def test_raw_response_create(self, client: Casedev) -> None: + response = client.media.v1.transcripts.retrieve.with_raw_response.create( + object_id="object_id", + vault_id="vault_id", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + retrieve = response.parse() + assert_matches_type(RetrieveCreateResponse, retrieve, path=["response"]) + + @parametrize + def test_streaming_response_create(self, client: Casedev) -> None: + with client.media.v1.transcripts.retrieve.with_streaming_response.create( + object_id="object_id", + vault_id="vault_id", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + retrieve = response.parse() + assert_matches_type(RetrieveCreateResponse, retrieve, path=["response"]) + + assert cast(Any, response.is_closed) is True + + +class TestAsyncRetrieve: + parametrize = pytest.mark.parametrize( + "async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"] + ) + + @parametrize + async def test_method_create(self, async_client: AsyncCasedev) -> None: + retrieve = await async_client.media.v1.transcripts.retrieve.create( + object_id="object_id", + vault_id="vault_id", + ) + assert_matches_type(RetrieveCreateResponse, retrieve, path=["response"]) + + @parametrize + async def test_method_create_with_all_params(self, async_client: AsyncCasedev) -> None: + retrieve = await async_client.media.v1.transcripts.retrieve.create( + object_id="object_id", + vault_id="vault_id", + transcript={ + "object_id": "object_id", + "vault_id": "vault_id", + }, + ) + assert_matches_type(RetrieveCreateResponse, retrieve, path=["response"]) + + @parametrize + async def test_raw_response_create(self, async_client: AsyncCasedev) -> None: + response = await async_client.media.v1.transcripts.retrieve.with_raw_response.create( + object_id="object_id", + vault_id="vault_id", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + retrieve = await response.parse() + assert_matches_type(RetrieveCreateResponse, retrieve, path=["response"]) + + @parametrize + async def test_streaming_response_create(self, async_client: AsyncCasedev) -> None: + async with async_client.media.v1.transcripts.retrieve.with_streaming_response.create( + object_id="object_id", + vault_id="vault_id", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + retrieve = await response.parse() + assert_matches_type(RetrieveCreateResponse, retrieve, path=["response"]) + + assert cast(Any, response.is_closed) is True diff --git a/tests/api_resources/test_document_templates.py b/tests/api_resources/test_document_templates.py new file mode 100644 index 00000000..2b839a26 --- /dev/null +++ b/tests/api_resources/test_document_templates.py @@ -0,0 +1,426 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +import os +from typing import Any, cast + +import pytest + +from casedev import Casedev, AsyncCasedev + +base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") + + +class TestDocumentTemplates: + parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"]) + + @parametrize + def test_method_create(self, client: Casedev) -> None: + document_template = client.document_templates.create() + assert document_template is None + + @parametrize + def test_raw_response_create(self, client: Casedev) -> None: + response = client.document_templates.with_raw_response.create() + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + document_template = response.parse() + assert document_template is None + + @parametrize + def test_streaming_response_create(self, client: Casedev) -> None: + with client.document_templates.with_streaming_response.create() as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + document_template = response.parse() + assert document_template is None + + assert cast(Any, response.is_closed) is True + + @parametrize + def test_method_retrieve(self, client: Casedev) -> None: + document_template = client.document_templates.retrieve( + "id", + ) + assert document_template is None + + @parametrize + def test_raw_response_retrieve(self, client: Casedev) -> None: + response = client.document_templates.with_raw_response.retrieve( + "id", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + document_template = response.parse() + assert document_template is None + + @parametrize + def test_streaming_response_retrieve(self, client: Casedev) -> None: + with client.document_templates.with_streaming_response.retrieve( + "id", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + document_template = response.parse() + assert document_template is None + + assert cast(Any, response.is_closed) is True + + @parametrize + def test_path_params_retrieve(self, client: Casedev) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): + client.document_templates.with_raw_response.retrieve( + "", + ) + + @parametrize + def test_method_update(self, client: Casedev) -> None: + document_template = client.document_templates.update( + "id", + ) + assert document_template is None + + @parametrize + def test_raw_response_update(self, client: Casedev) -> None: + response = client.document_templates.with_raw_response.update( + "id", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + document_template = response.parse() + assert document_template is None + + @parametrize + def test_streaming_response_update(self, client: Casedev) -> None: + with client.document_templates.with_streaming_response.update( + "id", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + document_template = response.parse() + assert document_template is None + + assert cast(Any, response.is_closed) is True + + @parametrize + def test_path_params_update(self, client: Casedev) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): + client.document_templates.with_raw_response.update( + "", + ) + + @parametrize + def test_method_list(self, client: Casedev) -> None: + document_template = client.document_templates.list() + assert document_template is None + + @parametrize + def test_raw_response_list(self, client: Casedev) -> None: + response = client.document_templates.with_raw_response.list() + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + document_template = response.parse() + assert document_template is None + + @parametrize + def test_streaming_response_list(self, client: Casedev) -> None: + with client.document_templates.with_streaming_response.list() as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + document_template = response.parse() + assert document_template is None + + assert cast(Any, response.is_closed) is True + + @parametrize + def test_method_delete(self, client: Casedev) -> None: + document_template = client.document_templates.delete( + "id", + ) + assert document_template is None + + @parametrize + def test_raw_response_delete(self, client: Casedev) -> None: + response = client.document_templates.with_raw_response.delete( + "id", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + document_template = response.parse() + assert document_template is None + + @parametrize + def test_streaming_response_delete(self, client: Casedev) -> None: + with client.document_templates.with_streaming_response.delete( + "id", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + document_template = response.parse() + assert document_template is None + + assert cast(Any, response.is_closed) is True + + @parametrize + def test_path_params_delete(self, client: Casedev) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): + client.document_templates.with_raw_response.delete( + "", + ) + + @parametrize + def test_method_confirm(self, client: Casedev) -> None: + document_template = client.document_templates.confirm( + "id", + ) + assert document_template is None + + @parametrize + def test_raw_response_confirm(self, client: Casedev) -> None: + response = client.document_templates.with_raw_response.confirm( + "id", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + document_template = response.parse() + assert document_template is None + + @parametrize + def test_streaming_response_confirm(self, client: Casedev) -> None: + with client.document_templates.with_streaming_response.confirm( + "id", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + document_template = response.parse() + assert document_template is None + + assert cast(Any, response.is_closed) is True + + @parametrize + def test_path_params_confirm(self, client: Casedev) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): + client.document_templates.with_raw_response.confirm( + "", + ) + + +class TestAsyncDocumentTemplates: + parametrize = pytest.mark.parametrize( + "async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"] + ) + + @parametrize + async def test_method_create(self, async_client: AsyncCasedev) -> None: + document_template = await async_client.document_templates.create() + assert document_template is None + + @parametrize + async def test_raw_response_create(self, async_client: AsyncCasedev) -> None: + response = await async_client.document_templates.with_raw_response.create() + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + document_template = await response.parse() + assert document_template is None + + @parametrize + async def test_streaming_response_create(self, async_client: AsyncCasedev) -> None: + async with async_client.document_templates.with_streaming_response.create() as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + document_template = await response.parse() + assert document_template is None + + assert cast(Any, response.is_closed) is True + + @parametrize + async def test_method_retrieve(self, async_client: AsyncCasedev) -> None: + document_template = await async_client.document_templates.retrieve( + "id", + ) + assert document_template is None + + @parametrize + async def test_raw_response_retrieve(self, async_client: AsyncCasedev) -> None: + response = await async_client.document_templates.with_raw_response.retrieve( + "id", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + document_template = await response.parse() + assert document_template is None + + @parametrize + async def test_streaming_response_retrieve(self, async_client: AsyncCasedev) -> None: + async with async_client.document_templates.with_streaming_response.retrieve( + "id", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + document_template = await response.parse() + assert document_template is None + + assert cast(Any, response.is_closed) is True + + @parametrize + async def test_path_params_retrieve(self, async_client: AsyncCasedev) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): + await async_client.document_templates.with_raw_response.retrieve( + "", + ) + + @parametrize + async def test_method_update(self, async_client: AsyncCasedev) -> None: + document_template = await async_client.document_templates.update( + "id", + ) + assert document_template is None + + @parametrize + async def test_raw_response_update(self, async_client: AsyncCasedev) -> None: + response = await async_client.document_templates.with_raw_response.update( + "id", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + document_template = await response.parse() + assert document_template is None + + @parametrize + async def test_streaming_response_update(self, async_client: AsyncCasedev) -> None: + async with async_client.document_templates.with_streaming_response.update( + "id", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + document_template = await response.parse() + assert document_template is None + + assert cast(Any, response.is_closed) is True + + @parametrize + async def test_path_params_update(self, async_client: AsyncCasedev) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): + await async_client.document_templates.with_raw_response.update( + "", + ) + + @parametrize + async def test_method_list(self, async_client: AsyncCasedev) -> None: + document_template = await async_client.document_templates.list() + assert document_template is None + + @parametrize + async def test_raw_response_list(self, async_client: AsyncCasedev) -> None: + response = await async_client.document_templates.with_raw_response.list() + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + document_template = await response.parse() + assert document_template is None + + @parametrize + async def test_streaming_response_list(self, async_client: AsyncCasedev) -> None: + async with async_client.document_templates.with_streaming_response.list() as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + document_template = await response.parse() + assert document_template is None + + assert cast(Any, response.is_closed) is True + + @parametrize + async def test_method_delete(self, async_client: AsyncCasedev) -> None: + document_template = await async_client.document_templates.delete( + "id", + ) + assert document_template is None + + @parametrize + async def test_raw_response_delete(self, async_client: AsyncCasedev) -> None: + response = await async_client.document_templates.with_raw_response.delete( + "id", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + document_template = await response.parse() + assert document_template is None + + @parametrize + async def test_streaming_response_delete(self, async_client: AsyncCasedev) -> None: + async with async_client.document_templates.with_streaming_response.delete( + "id", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + document_template = await response.parse() + assert document_template is None + + assert cast(Any, response.is_closed) is True + + @parametrize + async def test_path_params_delete(self, async_client: AsyncCasedev) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): + await async_client.document_templates.with_raw_response.delete( + "", + ) + + @parametrize + async def test_method_confirm(self, async_client: AsyncCasedev) -> None: + document_template = await async_client.document_templates.confirm( + "id", + ) + assert document_template is None + + @parametrize + async def test_raw_response_confirm(self, async_client: AsyncCasedev) -> None: + response = await async_client.document_templates.with_raw_response.confirm( + "id", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + document_template = await response.parse() + assert document_template is None + + @parametrize + async def test_streaming_response_confirm(self, async_client: AsyncCasedev) -> None: + async with async_client.document_templates.with_streaming_response.confirm( + "id", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + document_template = await response.parse() + assert document_template is None + + assert cast(Any, response.is_closed) is True + + @parametrize + async def test_path_params_confirm(self, async_client: AsyncCasedev) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): + await async_client.document_templates.with_raw_response.confirm( + "", + ) diff --git a/tests/api_resources/test_vault.py b/tests/api_resources/test_vault.py index dbf210d8..79c54352 100644 --- a/tests/api_resources/test_vault.py +++ b/tests/api_resources/test_vault.py @@ -249,6 +249,7 @@ def test_method_confirm_upload_with_all_params_overload_1(self, client: Casedev) id="id", size_bytes=1, success=True, + auto_ingest=True, etag="etag", ) assert_matches_type(VaultConfirmUploadResponse, vault, path=["response"]) @@ -481,6 +482,7 @@ def test_method_upload_with_all_params(self, client: Casedev) -> None: content_type="contentType", filename="filename", auto_index=True, + is_ai_generated=True, metadata={}, path="path", size_bytes=1, @@ -752,6 +754,7 @@ async def test_method_confirm_upload_with_all_params_overload_1(self, async_clie id="id", size_bytes=1, success=True, + auto_ingest=True, etag="etag", ) assert_matches_type(VaultConfirmUploadResponse, vault, path=["response"]) @@ -984,6 +987,7 @@ async def test_method_upload_with_all_params(self, async_client: AsyncCasedev) - content_type="contentType", filename="filename", auto_index=True, + is_ai_generated=True, metadata={}, path="path", size_bytes=1, diff --git a/tests/api_resources/usage/test_v1.py b/tests/api_resources/usage/test_v1.py index b793596a..4ee2a1f1 100644 --- a/tests/api_resources/usage/test_v1.py +++ b/tests/api_resources/usage/test_v1.py @@ -25,6 +25,8 @@ def test_method_retrieve(self, client: Casedev) -> None: def test_method_retrieve_with_all_params(self, client: Casedev) -> None: v1 = client.usage.v1.retrieve( granularity="summary", + group_by="lincSessionId", + linc_session_id="lincSessionId", period_end=parse_datetime("2019-12-27T18:11:19.117Z"), period_start=parse_datetime("2019-12-27T18:11:19.117Z"), ) @@ -65,6 +67,8 @@ async def test_method_retrieve(self, async_client: AsyncCasedev) -> None: async def test_method_retrieve_with_all_params(self, async_client: AsyncCasedev) -> None: v1 = await async_client.usage.v1.retrieve( granularity="summary", + group_by="lincSessionId", + linc_session_id="lincSessionId", period_end=parse_datetime("2019-12-27T18:11:19.117Z"), period_start=parse_datetime("2019-12-27T18:11:19.117Z"), ) diff --git a/tests/api_resources/vault/test_multipart.py b/tests/api_resources/vault/test_multipart.py index 14eac091..29e3a5d8 100644 --- a/tests/api_resources/vault/test_multipart.py +++ b/tests/api_resources/vault/test_multipart.py @@ -9,7 +9,10 @@ from casedev import Casedev, AsyncCasedev from tests.utils import assert_matches_type -from casedev.types.vault import MultipartGetPartURLsResponse +from casedev.types.vault import ( + MultipartInitResponse, + MultipartGetPartURLsResponse, +) base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") @@ -63,6 +66,80 @@ def test_path_params_abort(self, client: Casedev) -> None: upload_id="uploadId", ) + @parametrize + def test_method_complete(self, client: Casedev) -> None: + multipart = client.vault.multipart.complete( + id="id", + object_id="objectId", + parts=[ + { + "etag": "etag", + "part_number": 1, + } + ], + size_bytes=1, + upload_id="uploadId", + ) + assert multipart is None + + @parametrize + def test_raw_response_complete(self, client: Casedev) -> None: + response = client.vault.multipart.with_raw_response.complete( + id="id", + object_id="objectId", + parts=[ + { + "etag": "etag", + "part_number": 1, + } + ], + size_bytes=1, + upload_id="uploadId", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + multipart = response.parse() + assert multipart is None + + @parametrize + def test_streaming_response_complete(self, client: Casedev) -> None: + with client.vault.multipart.with_streaming_response.complete( + id="id", + object_id="objectId", + parts=[ + { + "etag": "etag", + "part_number": 1, + } + ], + size_bytes=1, + upload_id="uploadId", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + multipart = response.parse() + assert multipart is None + + assert cast(Any, response.is_closed) is True + + @parametrize + def test_path_params_complete(self, client: Casedev) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): + client.vault.multipart.with_raw_response.complete( + id="", + object_id="objectId", + parts=[ + { + "etag": "etag", + "part_number": 1, + } + ], + size_bytes=1, + upload_id="uploadId", + ) + @parametrize def test_method_get_part_urls(self, client: Casedev) -> None: multipart = client.vault.multipart.get_part_urls( @@ -133,6 +210,71 @@ def test_path_params_get_part_urls(self, client: Casedev) -> None: upload_id="uploadId", ) + @parametrize + def test_method_init(self, client: Casedev) -> None: + multipart = client.vault.multipart.init( + id="id", + content_type="contentType", + filename="filename", + size_bytes=1, + ) + assert_matches_type(MultipartInitResponse, multipart, path=["response"]) + + @parametrize + def test_method_init_with_all_params(self, client: Casedev) -> None: + multipart = client.vault.multipart.init( + id="id", + content_type="contentType", + filename="filename", + size_bytes=1, + auto_index=True, + is_ai_generated=True, + metadata={}, + part_size_bytes=5242880, + path="path", + ) + assert_matches_type(MultipartInitResponse, multipart, path=["response"]) + + @parametrize + def test_raw_response_init(self, client: Casedev) -> None: + response = client.vault.multipart.with_raw_response.init( + id="id", + content_type="contentType", + filename="filename", + size_bytes=1, + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + multipart = response.parse() + assert_matches_type(MultipartInitResponse, multipart, path=["response"]) + + @parametrize + def test_streaming_response_init(self, client: Casedev) -> None: + with client.vault.multipart.with_streaming_response.init( + id="id", + content_type="contentType", + filename="filename", + size_bytes=1, + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + multipart = response.parse() + assert_matches_type(MultipartInitResponse, multipart, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @parametrize + def test_path_params_init(self, client: Casedev) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): + client.vault.multipart.with_raw_response.init( + id="", + content_type="contentType", + filename="filename", + size_bytes=1, + ) + class TestAsyncMultipart: parametrize = pytest.mark.parametrize( @@ -185,6 +327,80 @@ async def test_path_params_abort(self, async_client: AsyncCasedev) -> None: upload_id="uploadId", ) + @parametrize + async def test_method_complete(self, async_client: AsyncCasedev) -> None: + multipart = await async_client.vault.multipart.complete( + id="id", + object_id="objectId", + parts=[ + { + "etag": "etag", + "part_number": 1, + } + ], + size_bytes=1, + upload_id="uploadId", + ) + assert multipart is None + + @parametrize + async def test_raw_response_complete(self, async_client: AsyncCasedev) -> None: + response = await async_client.vault.multipart.with_raw_response.complete( + id="id", + object_id="objectId", + parts=[ + { + "etag": "etag", + "part_number": 1, + } + ], + size_bytes=1, + upload_id="uploadId", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + multipart = await response.parse() + assert multipart is None + + @parametrize + async def test_streaming_response_complete(self, async_client: AsyncCasedev) -> None: + async with async_client.vault.multipart.with_streaming_response.complete( + id="id", + object_id="objectId", + parts=[ + { + "etag": "etag", + "part_number": 1, + } + ], + size_bytes=1, + upload_id="uploadId", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + multipart = await response.parse() + assert multipart is None + + assert cast(Any, response.is_closed) is True + + @parametrize + async def test_path_params_complete(self, async_client: AsyncCasedev) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): + await async_client.vault.multipart.with_raw_response.complete( + id="", + object_id="objectId", + parts=[ + { + "etag": "etag", + "part_number": 1, + } + ], + size_bytes=1, + upload_id="uploadId", + ) + @parametrize async def test_method_get_part_urls(self, async_client: AsyncCasedev) -> None: multipart = await async_client.vault.multipart.get_part_urls( @@ -254,3 +470,68 @@ async def test_path_params_get_part_urls(self, async_client: AsyncCasedev) -> No ], upload_id="uploadId", ) + + @parametrize + async def test_method_init(self, async_client: AsyncCasedev) -> None: + multipart = await async_client.vault.multipart.init( + id="id", + content_type="contentType", + filename="filename", + size_bytes=1, + ) + assert_matches_type(MultipartInitResponse, multipart, path=["response"]) + + @parametrize + async def test_method_init_with_all_params(self, async_client: AsyncCasedev) -> None: + multipart = await async_client.vault.multipart.init( + id="id", + content_type="contentType", + filename="filename", + size_bytes=1, + auto_index=True, + is_ai_generated=True, + metadata={}, + part_size_bytes=5242880, + path="path", + ) + assert_matches_type(MultipartInitResponse, multipart, path=["response"]) + + @parametrize + async def test_raw_response_init(self, async_client: AsyncCasedev) -> None: + response = await async_client.vault.multipart.with_raw_response.init( + id="id", + content_type="contentType", + filename="filename", + size_bytes=1, + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + multipart = await response.parse() + assert_matches_type(MultipartInitResponse, multipart, path=["response"]) + + @parametrize + async def test_streaming_response_init(self, async_client: AsyncCasedev) -> None: + async with async_client.vault.multipart.with_streaming_response.init( + id="id", + content_type="contentType", + filename="filename", + size_bytes=1, + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + multipart = await response.parse() + assert_matches_type(MultipartInitResponse, multipart, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @parametrize + async def test_path_params_init(self, async_client: AsyncCasedev) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): + await async_client.vault.multipart.with_raw_response.init( + id="", + content_type="contentType", + filename="filename", + size_bytes=1, + ) diff --git a/tests/api_resources/vault/test_objects.py b/tests/api_resources/vault/test_objects.py index ddf0e8bf..aef6d4e7 100644 --- a/tests/api_resources/vault/test_objects.py +++ b/tests/api_resources/vault/test_objects.py @@ -19,12 +19,14 @@ ) from casedev.types.vault import ( ObjectListResponse, + ObjectAppendResponse, ObjectDeleteResponse, ObjectUpdateResponse, ObjectGetTextResponse, ObjectGetPagesResponse, ObjectRetrieveResponse, ObjectGetChunksResponse, + ObjectSummarizeResponse, ObjectGetOcrWordsResponse, ObjectGetSummarizeJobResponse, ObjectCreatePresignedURLResponse, @@ -146,14 +148,22 @@ def test_path_params_update(self, client: Casedev) -> None: @parametrize def test_method_list(self, client: Casedev) -> None: object_ = client.vault.objects.list( - "id", + id="id", + ) + assert_matches_type(ObjectListResponse, object_, path=["response"]) + + @parametrize + def test_method_list_with_all_params(self, client: Casedev) -> None: + object_ = client.vault.objects.list( + id="id", + include_unconfirmed=True, ) assert_matches_type(ObjectListResponse, object_, path=["response"]) @parametrize def test_raw_response_list(self, client: Casedev) -> None: response = client.vault.objects.with_raw_response.list( - "id", + id="id", ) assert response.is_closed is True @@ -164,7 +174,7 @@ def test_raw_response_list(self, client: Casedev) -> None: @parametrize def test_streaming_response_list(self, client: Casedev) -> None: with client.vault.objects.with_streaming_response.list( - "id", + id="id", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" @@ -178,7 +188,7 @@ def test_streaming_response_list(self, client: Casedev) -> None: def test_path_params_list(self, client: Casedev) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): client.vault.objects.with_raw_response.list( - "", + id="", ) @parametrize @@ -238,6 +248,71 @@ def test_path_params_delete(self, client: Casedev) -> None: id="id", ) + @parametrize + def test_method_append(self, client: Casedev) -> None: + object_ = client.vault.objects.append( + object_id="objectId", + id="id", + append_object_ids=["string"], + ) + assert_matches_type(ObjectAppendResponse, object_, path=["response"]) + + @parametrize + def test_method_append_with_all_params(self, client: Casedev) -> None: + object_ = client.vault.objects.append( + object_id="objectId", + id="id", + append_object_ids=["string"], + back_links=True, + back_links_text="backLinksText", + rewrite_links=True, + ) + assert_matches_type(ObjectAppendResponse, object_, path=["response"]) + + @parametrize + def test_raw_response_append(self, client: Casedev) -> None: + response = client.vault.objects.with_raw_response.append( + object_id="objectId", + id="id", + append_object_ids=["string"], + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + object_ = response.parse() + assert_matches_type(ObjectAppendResponse, object_, path=["response"]) + + @parametrize + def test_streaming_response_append(self, client: Casedev) -> None: + with client.vault.objects.with_streaming_response.append( + object_id="objectId", + id="id", + append_object_ids=["string"], + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + object_ = response.parse() + assert_matches_type(ObjectAppendResponse, object_, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @parametrize + def test_path_params_append(self, client: Casedev) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): + client.vault.objects.with_raw_response.append( + object_id="objectId", + id="", + append_object_ids=["string"], + ) + + with pytest.raises(ValueError, match=r"Expected a non-empty value for `object_id` but received ''"): + client.vault.objects.with_raw_response.append( + object_id="", + id="id", + append_object_ids=["string"], + ) + @parametrize def test_method_create_presigned_url(self, client: Casedev) -> None: object_ = client.vault.objects.create_presigned_url( @@ -647,6 +722,64 @@ def test_path_params_get_text(self, client: Casedev) -> None: id="id", ) + @parametrize + def test_method_summarize(self, client: Casedev) -> None: + object_ = client.vault.objects.summarize( + object_id="objectId", + id="id", + ) + assert_matches_type(ObjectSummarizeResponse, object_, path=["response"]) + + @parametrize + def test_method_summarize_with_all_params(self, client: Casedev) -> None: + object_ = client.vault.objects.summarize( + object_id="objectId", + id="id", + output_format="PDF", + workflow_type="workflowType", + ) + assert_matches_type(ObjectSummarizeResponse, object_, path=["response"]) + + @parametrize + def test_raw_response_summarize(self, client: Casedev) -> None: + response = client.vault.objects.with_raw_response.summarize( + object_id="objectId", + id="id", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + object_ = response.parse() + assert_matches_type(ObjectSummarizeResponse, object_, path=["response"]) + + @parametrize + def test_streaming_response_summarize(self, client: Casedev) -> None: + with client.vault.objects.with_streaming_response.summarize( + object_id="objectId", + id="id", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + object_ = response.parse() + assert_matches_type(ObjectSummarizeResponse, object_, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @parametrize + def test_path_params_summarize(self, client: Casedev) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): + client.vault.objects.with_raw_response.summarize( + object_id="objectId", + id="", + ) + + with pytest.raises(ValueError, match=r"Expected a non-empty value for `object_id` but received ''"): + client.vault.objects.with_raw_response.summarize( + object_id="", + id="id", + ) + class TestAsyncObjects: parametrize = pytest.mark.parametrize( @@ -763,14 +896,22 @@ async def test_path_params_update(self, async_client: AsyncCasedev) -> None: @parametrize async def test_method_list(self, async_client: AsyncCasedev) -> None: object_ = await async_client.vault.objects.list( - "id", + id="id", + ) + assert_matches_type(ObjectListResponse, object_, path=["response"]) + + @parametrize + async def test_method_list_with_all_params(self, async_client: AsyncCasedev) -> None: + object_ = await async_client.vault.objects.list( + id="id", + include_unconfirmed=True, ) assert_matches_type(ObjectListResponse, object_, path=["response"]) @parametrize async def test_raw_response_list(self, async_client: AsyncCasedev) -> None: response = await async_client.vault.objects.with_raw_response.list( - "id", + id="id", ) assert response.is_closed is True @@ -781,7 +922,7 @@ async def test_raw_response_list(self, async_client: AsyncCasedev) -> None: @parametrize async def test_streaming_response_list(self, async_client: AsyncCasedev) -> None: async with async_client.vault.objects.with_streaming_response.list( - "id", + id="id", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" @@ -795,7 +936,7 @@ async def test_streaming_response_list(self, async_client: AsyncCasedev) -> None async def test_path_params_list(self, async_client: AsyncCasedev) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): await async_client.vault.objects.with_raw_response.list( - "", + id="", ) @parametrize @@ -855,6 +996,71 @@ async def test_path_params_delete(self, async_client: AsyncCasedev) -> None: id="id", ) + @parametrize + async def test_method_append(self, async_client: AsyncCasedev) -> None: + object_ = await async_client.vault.objects.append( + object_id="objectId", + id="id", + append_object_ids=["string"], + ) + assert_matches_type(ObjectAppendResponse, object_, path=["response"]) + + @parametrize + async def test_method_append_with_all_params(self, async_client: AsyncCasedev) -> None: + object_ = await async_client.vault.objects.append( + object_id="objectId", + id="id", + append_object_ids=["string"], + back_links=True, + back_links_text="backLinksText", + rewrite_links=True, + ) + assert_matches_type(ObjectAppendResponse, object_, path=["response"]) + + @parametrize + async def test_raw_response_append(self, async_client: AsyncCasedev) -> None: + response = await async_client.vault.objects.with_raw_response.append( + object_id="objectId", + id="id", + append_object_ids=["string"], + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + object_ = await response.parse() + assert_matches_type(ObjectAppendResponse, object_, path=["response"]) + + @parametrize + async def test_streaming_response_append(self, async_client: AsyncCasedev) -> None: + async with async_client.vault.objects.with_streaming_response.append( + object_id="objectId", + id="id", + append_object_ids=["string"], + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + object_ = await response.parse() + assert_matches_type(ObjectAppendResponse, object_, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @parametrize + async def test_path_params_append(self, async_client: AsyncCasedev) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): + await async_client.vault.objects.with_raw_response.append( + object_id="objectId", + id="", + append_object_ids=["string"], + ) + + with pytest.raises(ValueError, match=r"Expected a non-empty value for `object_id` but received ''"): + await async_client.vault.objects.with_raw_response.append( + object_id="", + id="id", + append_object_ids=["string"], + ) + @parametrize async def test_method_create_presigned_url(self, async_client: AsyncCasedev) -> None: object_ = await async_client.vault.objects.create_presigned_url( @@ -1263,3 +1469,61 @@ async def test_path_params_get_text(self, async_client: AsyncCasedev) -> None: object_id="", id="id", ) + + @parametrize + async def test_method_summarize(self, async_client: AsyncCasedev) -> None: + object_ = await async_client.vault.objects.summarize( + object_id="objectId", + id="id", + ) + assert_matches_type(ObjectSummarizeResponse, object_, path=["response"]) + + @parametrize + async def test_method_summarize_with_all_params(self, async_client: AsyncCasedev) -> None: + object_ = await async_client.vault.objects.summarize( + object_id="objectId", + id="id", + output_format="PDF", + workflow_type="workflowType", + ) + assert_matches_type(ObjectSummarizeResponse, object_, path=["response"]) + + @parametrize + async def test_raw_response_summarize(self, async_client: AsyncCasedev) -> None: + response = await async_client.vault.objects.with_raw_response.summarize( + object_id="objectId", + id="id", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + object_ = await response.parse() + assert_matches_type(ObjectSummarizeResponse, object_, path=["response"]) + + @parametrize + async def test_streaming_response_summarize(self, async_client: AsyncCasedev) -> None: + async with async_client.vault.objects.with_streaming_response.summarize( + object_id="objectId", + id="id", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + object_ = await response.parse() + assert_matches_type(ObjectSummarizeResponse, object_, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @parametrize + async def test_path_params_summarize(self, async_client: AsyncCasedev) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): + await async_client.vault.objects.with_raw_response.summarize( + object_id="objectId", + id="", + ) + + with pytest.raises(ValueError, match=r"Expected a non-empty value for `object_id` but received ''"): + await async_client.vault.objects.with_raw_response.summarize( + object_id="", + id="id", + ) From dae33c41e85756a36de2a47a0cc1ddefea68ff89 Mon Sep 17 00:00:00 2001 From: Dante Danelian <101446519+dantedanelian@users.noreply.github.com> Date: Tue, 4 Aug 2026 21:56:11 -0400 Subject: [PATCH 2/2] feat(api): api update (#6) Co-authored-by: stlc-bot --- .stats.yml | 2 +- README.md | 29 +- api.md | 220 +--- scripts/lint | 2 +- scripts/mock | 2 +- src/casedev/_client.py | 233 +--- src/casedev/_files.py | 2 +- src/casedev/resources/__init__.py | 96 +- src/casedev/resources/agent/v1/__init__.py | 61 - src/casedev/resources/agent/v1/execute.py | 279 ----- src/casedev/resources/agent/v1/run.py | 888 -------------- src/casedev/resources/agent/v1/v1.py | 220 ---- .../{agent => connectors}/__init__.py | 26 +- .../agent.py => connectors/connectors.py} | 60 +- .../resources/connectors/v1/__init__.py | 61 + .../v1/connections.py} | 581 ++++----- .../connectors/v1/installations/__init__.py | 33 + .../v1/installations/installations.py | 330 ++++++ .../v1/installations/vaults.py} | 274 +++-- .../v1/links.py} | 395 ++++--- src/casedev/resources/connectors/v1/v1.py | 439 +++++++ src/casedev/resources/database/__init__.py | 33 - src/casedev/resources/database/database.py | 108 -- src/casedev/resources/database/v1/__init__.py | 33 - src/casedev/resources/database/v1/projects.py | 775 ------------ src/casedev/resources/database/v1/v1.py | 185 --- .../resources/document_templates/__init__.py | 33 - .../document_templates/from_vault_object.py | 136 --- src/casedev/resources/format/__init__.py | 33 - src/casedev/resources/format/format.py | 108 -- src/casedev/resources/format/v1/__init__.py | 33 - src/casedev/resources/format/v1/templates.py | 421 ------- src/casedev/resources/format/v1/v1.py | 260 ---- src/casedev/resources/legal/v1.py | 184 +-- src/casedev/resources/linc/v1/sessions.py | 48 +- src/casedev/resources/linc/v1/v1.py | 24 +- src/casedev/resources/llm/v1/chat.py | 10 +- src/casedev/resources/mail/__init__.py | 33 - src/casedev/resources/mail/mail.py | 102 -- src/casedev/resources/mail/v1/__init__.py | 33 - src/casedev/resources/mail/v1/inboxes.py | 1052 ----------------- src/casedev/resources/mail/v1/v1.py | 108 -- .../resources/matters/v1/work_items.py | 106 +- src/casedev/resources/media/v1/clips.py | 4 + .../media/v1/transcripts/retrieve.py | 4 + .../resources/media/v1/transcripts/search.py | 4 + .../media/v1/transcripts/transcripts.py | 12 + src/casedev/resources/media/v1/v1.py | 6 + src/casedev/resources/ocr/v1.py | 12 +- src/casedev/resources/search/search.py | 12 +- src/casedev/resources/search/v1.py | 253 +--- src/casedev/resources/superdoc/__init__.py | 33 - src/casedev/resources/superdoc/superdoc.py | 108 -- src/casedev/resources/superdoc/v1.py | 356 ------ src/casedev/resources/translate/translate.py | 6 + src/casedev/resources/translate/v1.py | 168 ++- src/casedev/resources/vault/__init__.py | 14 - src/casedev/resources/vault/events/events.py | 12 +- .../resources/vault/events/subscriptions.py | 4 +- src/casedev/resources/vault/memory.py | 4 +- src/casedev/resources/vault/objects.py | 237 ++-- src/casedev/resources/vault/vault.py | 236 +--- src/casedev/resources/voice/transcription.py | 20 +- src/casedev/types/agent/v1/__init__.py | 26 - .../types/agent/v1/agent_create_params.py | 59 - .../types/agent/v1/agent_create_response.py | 34 - .../types/agent/v1/agent_delete_response.py | 11 - .../types/agent/v1/agent_list_params.py | 18 - .../types/agent/v1/agent_list_response.py | 37 - .../types/agent/v1/agent_retrieve_response.py | 36 - .../types/agent/v1/agent_update_params.py | 48 - .../types/agent/v1/agent_update_response.py | 38 - .../types/agent/v1/execute_create_params.py | 62 - .../types/agent/v1/execute_create_response.py | 26 - .../types/agent/v1/run_cancel_response.py | 17 - .../types/agent/v1/run_create_params.py | 39 - .../types/agent/v1/run_create_response.py | 23 - .../types/agent/v1/run_events_params.py | 14 - .../types/agent/v1/run_events_response.py | 7 - .../types/agent/v1/run_exec_response.py | 21 - .../agent/v1/run_get_details_response.py | 176 --- .../types/agent/v1/run_get_status_response.py | 24 - src/casedev/types/agent/v1/run_list_params.py | 26 - .../types/agent/v1/run_list_response.py | 39 - .../types/agent/v1/run_watch_params.py | 14 - .../types/agent/v1/run_watch_response.py | 15 - src/casedev/types/connectors/__init__.py | 8 + src/casedev/types/connectors/v1/__init__.py | 17 + .../connectors/v1/connection_browse_params.py | 25 + .../v1/connection_browse_response.py | 36 + .../connectors/v1/connection_create_params.py | 17 + .../v1/connection_create_response.py | 15 + .../connectors/v1/connection_delete_params.py | 11 + .../connectors/v1/connection_list_params.py | 13 + .../connectors/v1/connection_list_response.py | 19 + .../v1/installation_ensure_params.py | 15 + .../connectors/v1/installation_list_params.py | 13 + .../v1/installations}/__init__.py | 2 + .../v1/installations/vault_grant_params.py | 21 + .../types/connectors/v1/link_delete_params.py | 11 + .../connectors/v1/link_list_objects_params.py | 13 + .../types/connectors/v1/link_list_params.py | 21 + .../types/connectors/v1/link_update_params.py | 15 + .../types/connectors/v1_sync_link_params.py | 48 + .../types/connectors/v1_sync_link_response.py | 11 + .../types/connectors/v1_transfer_params.py | 50 + .../types/connectors/v1_transfer_response.py | 11 + src/casedev/types/database/__init__.py | 5 - src/casedev/types/database/v1/__init__.py | 14 - .../v1/project_create_branch_params.py | 17 - .../v1/project_create_branch_response.py | 30 - .../database/v1/project_create_params.py | 27 - .../database/v1/project_create_response.py | 47 - .../database/v1/project_delete_response.py | 13 - .../v1/project_get_connection_params.py | 15 - .../v1/project_get_connection_response.py | 18 - .../v1/project_list_branches_response.py | 37 - .../database/v1/project_list_response.py | 64 - .../database/v1/project_retrieve_response.py | 100 -- .../types/database/v1_get_usage_response.py | 116 -- .../types/document_templates/__init__.py | 3 - src/casedev/types/format/__init__.py | 5 - src/casedev/types/format/v1/__init__.py | 9 - .../types/format/v1/template_create_params.py | 32 - .../format/v1/template_create_response.py | 27 - .../types/format/v1/template_list_params.py | 12 - .../types/format/v1/template_list_response.py | 40 - .../format/v1/template_retrieve_response.py | 33 - .../types/format/v1_create_document_params.py | 50 - src/casedev/types/legal/__init__.py | 2 - src/casedev/types/legal/v1_docket_params.py | 5 +- src/casedev/types/legal/v1_draft_params.py | 62 - src/casedev/types/legal/v1_draft_response.py | 20 - src/casedev/types/linc/v1/__init__.py | 1 + .../types/linc/v1/session_cancel_params.py | 21 + .../types/linc/v1/session_create_params.py | 8 +- .../llm/v1/chat_create_completion_params.py | 5 +- src/casedev/types/mail/__init__.py | 3 - src/casedev/types/mail/v1/__init__.py | 6 - .../types/mail/v1/inbox_create_params.py | 15 - .../types/mail/v1/inbox_set_policy_params.py | 32 - .../matters/v1/work_item_decide_params.py | 4 +- src/casedev/types/ocr/v1_process_params.py | 6 +- src/casedev/types/ocr/v1_retrieve_params.py | 2 +- src/casedev/types/ocr/v1_retrieve_response.py | 2 +- src/casedev/types/search/__init__.py | 4 - .../types/search/v1_research_params.py | 23 - .../types/search/v1_research_response.py | 20 - .../search/v1_retrieve_research_params.py | 15 - .../search/v1_retrieve_research_response.py | 74 -- src/casedev/types/superdoc/__init__.py | 6 - .../types/superdoc/v1_annotate_params.py | 56 - .../types/superdoc/v1_convert_params.py | 23 - src/casedev/types/translate/__init__.py | 1 + .../translate/v1_translate_document_params.py | 20 + src/casedev/types/vault/__init__.py | 8 +- .../vault/graphrag_get_stats_response.py | 31 - .../types/vault/graphrag_init_response.py | 17 - .../vault/graphrag_process_object_response.py | 45 - .../types/vault/object_append_params.py | 26 +- .../types/vault/object_append_response.py | 4 + .../object_get_summarize_job_response.py | 40 - .../types/vault/object_merge_params.py | 36 + .../types/vault/object_merge_response.py | 20 + .../types/vault/object_summarize_params.py | 19 - .../types/vault/object_summarize_response.py | 27 - .../types/vault_confirm_upload_params.py | 36 +- src/casedev/types/vault_ingest_response.py | 5 +- src/casedev/types/vault_search_params.py | 6 +- src/casedev/types/vault_upload_params.py | 2 + src/casedev/types/vault_upload_response.py | 3 + .../voice/transcription_create_response.py | 10 +- .../voice/transcription_retrieve_response.py | 10 +- tests/api_resources/agent/v1/test_agents.py | 460 ------- tests/api_resources/agent/v1/test_execute.py | 122 -- tests/api_resources/agent/v1/test_run.py | 672 ----------- .../{agent => connectors}/__init__.py | 0 tests/api_resources/connectors/test_v1.py | 282 +++++ .../{agent => connectors}/v1/__init__.py | 0 .../v1/installations}/__init__.py | 0 .../v1/installations/test_vaults.py | 316 +++++ .../connectors/v1/test_connections.py | 450 +++++++ .../connectors/v1/test_installations.py | 156 +++ .../v1/test_links.py} | 372 +++--- tests/api_resources/database/test_v1.py | 74 -- tests/api_resources/database/v1/__init__.py | 1 - .../database/v1/test_projects.py | 586 --------- .../document_templates/__init__.py | 1 - .../test_from_vault_object.py | 72 -- tests/api_resources/format/__init__.py | 1 - tests/api_resources/format/test_v1.py | 170 --- tests/api_resources/format/v1/__init__.py | 1 - .../api_resources/format/v1/test_templates.py | 268 ----- tests/api_resources/legal/test_v1.py | 107 -- tests/api_resources/linc/v1/test_sessions.py | 34 +- tests/api_resources/mail/__init__.py | 1 - tests/api_resources/mail/v1/__init__.py | 1 - tests/api_resources/mail/v1/test_inboxes.py | 930 --------------- .../matters/v1/test_work_items.py | 98 -- tests/api_resources/search/test_v1.py | 178 --- tests/api_resources/superdoc/__init__.py | 1 - tests/api_resources/superdoc/test_v1.py | 320 ----- tests/api_resources/test_vault.py | 166 +-- tests/api_resources/translate/test_v1.py | 130 ++ tests/api_resources/vault/test_graphrag.py | 272 ----- tests/api_resources/vault/test_objects.py | 273 ++--- 206 files changed, 4331 insertions(+), 14477 deletions(-) delete mode 100644 src/casedev/resources/agent/v1/__init__.py delete mode 100644 src/casedev/resources/agent/v1/execute.py delete mode 100644 src/casedev/resources/agent/v1/run.py delete mode 100644 src/casedev/resources/agent/v1/v1.py rename src/casedev/resources/{agent => connectors}/__init__.py (50%) rename src/casedev/resources/{agent/agent.py => connectors/connectors.py} (50%) create mode 100644 src/casedev/resources/connectors/v1/__init__.py rename src/casedev/resources/{agent/v1/agents.py => connectors/v1/connections.py} (51%) create mode 100644 src/casedev/resources/connectors/v1/installations/__init__.py create mode 100644 src/casedev/resources/connectors/v1/installations/installations.py rename src/casedev/resources/{vault/graphrag.py => connectors/v1/installations/vaults.py} (53%) rename src/casedev/resources/{document_templates/document_templates.py => connectors/v1/links.py} (57%) create mode 100644 src/casedev/resources/connectors/v1/v1.py delete mode 100644 src/casedev/resources/database/__init__.py delete mode 100644 src/casedev/resources/database/database.py delete mode 100644 src/casedev/resources/database/v1/__init__.py delete mode 100644 src/casedev/resources/database/v1/projects.py delete mode 100644 src/casedev/resources/database/v1/v1.py delete mode 100644 src/casedev/resources/document_templates/__init__.py delete mode 100644 src/casedev/resources/document_templates/from_vault_object.py delete mode 100644 src/casedev/resources/format/__init__.py delete mode 100644 src/casedev/resources/format/format.py delete mode 100644 src/casedev/resources/format/v1/__init__.py delete mode 100644 src/casedev/resources/format/v1/templates.py delete mode 100644 src/casedev/resources/format/v1/v1.py delete mode 100644 src/casedev/resources/mail/__init__.py delete mode 100644 src/casedev/resources/mail/mail.py delete mode 100644 src/casedev/resources/mail/v1/__init__.py delete mode 100644 src/casedev/resources/mail/v1/inboxes.py delete mode 100644 src/casedev/resources/mail/v1/v1.py delete mode 100644 src/casedev/resources/superdoc/__init__.py delete mode 100644 src/casedev/resources/superdoc/superdoc.py delete mode 100644 src/casedev/resources/superdoc/v1.py delete mode 100644 src/casedev/types/agent/v1/__init__.py delete mode 100644 src/casedev/types/agent/v1/agent_create_params.py delete mode 100644 src/casedev/types/agent/v1/agent_create_response.py delete mode 100644 src/casedev/types/agent/v1/agent_delete_response.py delete mode 100644 src/casedev/types/agent/v1/agent_list_params.py delete mode 100644 src/casedev/types/agent/v1/agent_list_response.py delete mode 100644 src/casedev/types/agent/v1/agent_retrieve_response.py delete mode 100644 src/casedev/types/agent/v1/agent_update_params.py delete mode 100644 src/casedev/types/agent/v1/agent_update_response.py delete mode 100644 src/casedev/types/agent/v1/execute_create_params.py delete mode 100644 src/casedev/types/agent/v1/execute_create_response.py delete mode 100644 src/casedev/types/agent/v1/run_cancel_response.py delete mode 100644 src/casedev/types/agent/v1/run_create_params.py delete mode 100644 src/casedev/types/agent/v1/run_create_response.py delete mode 100644 src/casedev/types/agent/v1/run_events_params.py delete mode 100644 src/casedev/types/agent/v1/run_events_response.py delete mode 100644 src/casedev/types/agent/v1/run_exec_response.py delete mode 100644 src/casedev/types/agent/v1/run_get_details_response.py delete mode 100644 src/casedev/types/agent/v1/run_get_status_response.py delete mode 100644 src/casedev/types/agent/v1/run_list_params.py delete mode 100644 src/casedev/types/agent/v1/run_list_response.py delete mode 100644 src/casedev/types/agent/v1/run_watch_params.py delete mode 100644 src/casedev/types/agent/v1/run_watch_response.py create mode 100644 src/casedev/types/connectors/__init__.py create mode 100644 src/casedev/types/connectors/v1/__init__.py create mode 100644 src/casedev/types/connectors/v1/connection_browse_params.py create mode 100644 src/casedev/types/connectors/v1/connection_browse_response.py create mode 100644 src/casedev/types/connectors/v1/connection_create_params.py create mode 100644 src/casedev/types/connectors/v1/connection_create_response.py create mode 100644 src/casedev/types/connectors/v1/connection_delete_params.py create mode 100644 src/casedev/types/connectors/v1/connection_list_params.py create mode 100644 src/casedev/types/connectors/v1/connection_list_response.py create mode 100644 src/casedev/types/connectors/v1/installation_ensure_params.py create mode 100644 src/casedev/types/connectors/v1/installation_list_params.py rename src/casedev/types/{agent => connectors/v1/installations}/__init__.py (63%) create mode 100644 src/casedev/types/connectors/v1/installations/vault_grant_params.py create mode 100644 src/casedev/types/connectors/v1/link_delete_params.py create mode 100644 src/casedev/types/connectors/v1/link_list_objects_params.py create mode 100644 src/casedev/types/connectors/v1/link_list_params.py create mode 100644 src/casedev/types/connectors/v1/link_update_params.py create mode 100644 src/casedev/types/connectors/v1_sync_link_params.py create mode 100644 src/casedev/types/connectors/v1_sync_link_response.py create mode 100644 src/casedev/types/connectors/v1_transfer_params.py create mode 100644 src/casedev/types/connectors/v1_transfer_response.py delete mode 100644 src/casedev/types/database/__init__.py delete mode 100644 src/casedev/types/database/v1/__init__.py delete mode 100644 src/casedev/types/database/v1/project_create_branch_params.py delete mode 100644 src/casedev/types/database/v1/project_create_branch_response.py delete mode 100644 src/casedev/types/database/v1/project_create_params.py delete mode 100644 src/casedev/types/database/v1/project_create_response.py delete mode 100644 src/casedev/types/database/v1/project_delete_response.py delete mode 100644 src/casedev/types/database/v1/project_get_connection_params.py delete mode 100644 src/casedev/types/database/v1/project_get_connection_response.py delete mode 100644 src/casedev/types/database/v1/project_list_branches_response.py delete mode 100644 src/casedev/types/database/v1/project_list_response.py delete mode 100644 src/casedev/types/database/v1/project_retrieve_response.py delete mode 100644 src/casedev/types/database/v1_get_usage_response.py delete mode 100644 src/casedev/types/document_templates/__init__.py delete mode 100644 src/casedev/types/format/__init__.py delete mode 100644 src/casedev/types/format/v1/__init__.py delete mode 100644 src/casedev/types/format/v1/template_create_params.py delete mode 100644 src/casedev/types/format/v1/template_create_response.py delete mode 100644 src/casedev/types/format/v1/template_list_params.py delete mode 100644 src/casedev/types/format/v1/template_list_response.py delete mode 100644 src/casedev/types/format/v1/template_retrieve_response.py delete mode 100644 src/casedev/types/format/v1_create_document_params.py delete mode 100644 src/casedev/types/legal/v1_draft_params.py delete mode 100644 src/casedev/types/legal/v1_draft_response.py create mode 100644 src/casedev/types/linc/v1/session_cancel_params.py delete mode 100644 src/casedev/types/mail/__init__.py delete mode 100644 src/casedev/types/mail/v1/__init__.py delete mode 100644 src/casedev/types/mail/v1/inbox_create_params.py delete mode 100644 src/casedev/types/mail/v1/inbox_set_policy_params.py delete mode 100644 src/casedev/types/search/v1_research_params.py delete mode 100644 src/casedev/types/search/v1_research_response.py delete mode 100644 src/casedev/types/search/v1_retrieve_research_params.py delete mode 100644 src/casedev/types/search/v1_retrieve_research_response.py delete mode 100644 src/casedev/types/superdoc/__init__.py delete mode 100644 src/casedev/types/superdoc/v1_annotate_params.py delete mode 100644 src/casedev/types/superdoc/v1_convert_params.py create mode 100644 src/casedev/types/translate/v1_translate_document_params.py delete mode 100644 src/casedev/types/vault/graphrag_get_stats_response.py delete mode 100644 src/casedev/types/vault/graphrag_init_response.py delete mode 100644 src/casedev/types/vault/graphrag_process_object_response.py delete mode 100644 src/casedev/types/vault/object_get_summarize_job_response.py create mode 100644 src/casedev/types/vault/object_merge_params.py create mode 100644 src/casedev/types/vault/object_merge_response.py delete mode 100644 src/casedev/types/vault/object_summarize_params.py delete mode 100644 src/casedev/types/vault/object_summarize_response.py delete mode 100644 tests/api_resources/agent/v1/test_agents.py delete mode 100644 tests/api_resources/agent/v1/test_execute.py delete mode 100644 tests/api_resources/agent/v1/test_run.py rename tests/api_resources/{agent => connectors}/__init__.py (100%) create mode 100644 tests/api_resources/connectors/test_v1.py rename tests/api_resources/{agent => connectors}/v1/__init__.py (100%) rename tests/api_resources/{database => connectors/v1/installations}/__init__.py (100%) create mode 100644 tests/api_resources/connectors/v1/installations/test_vaults.py create mode 100644 tests/api_resources/connectors/v1/test_connections.py create mode 100644 tests/api_resources/connectors/v1/test_installations.py rename tests/api_resources/{test_document_templates.py => connectors/v1/test_links.py} (50%) delete mode 100644 tests/api_resources/database/test_v1.py delete mode 100644 tests/api_resources/database/v1/__init__.py delete mode 100644 tests/api_resources/database/v1/test_projects.py delete mode 100644 tests/api_resources/document_templates/__init__.py delete mode 100644 tests/api_resources/document_templates/test_from_vault_object.py delete mode 100644 tests/api_resources/format/__init__.py delete mode 100644 tests/api_resources/format/test_v1.py delete mode 100644 tests/api_resources/format/v1/__init__.py delete mode 100644 tests/api_resources/format/v1/test_templates.py delete mode 100644 tests/api_resources/mail/__init__.py delete mode 100644 tests/api_resources/mail/v1/__init__.py delete mode 100644 tests/api_resources/mail/v1/test_inboxes.py delete mode 100644 tests/api_resources/superdoc/__init__.py delete mode 100644 tests/api_resources/superdoc/test_v1.py delete mode 100644 tests/api_resources/vault/test_graphrag.py diff --git a/.stats.yml b/.stats.yml index 9b0d57ec..83b7ea96 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1 +1 @@ -configured_endpoints: 219 +configured_endpoints: 183 diff --git a/README.md b/README.md index fd26910b..6863a3ed 100644 --- a/README.md +++ b/README.md @@ -140,14 +140,33 @@ from casedev import Casedev client = Casedev() -agent = client.agent.v1.agents.create( - instructions="instructions", - name="name", - sandbox={}, +response = client.connectors.v1.sync_link( + connection_id="connection_id", + direction="import", + remote={"folder_id": "folder_id"}, + vault_id="vault_id", ) -print(agent.sandbox) +print(response.remote) ``` +## File uploads + +Request parameters that correspond to file uploads can be passed as `bytes`, or a [`PathLike`](https://docs.python.org/3/library/os.html#os.PathLike) instance or a tuple of `(filename, contents, media type)`. + +```python +from pathlib import Path +from casedev import Casedev + +client = Casedev() + +client.translate.v1.translate_document( + file=Path("/path/to/file"), + target="es", +) +``` + +The async client uses the exact same interface. If you pass a [`PathLike`](https://docs.python.org/3/library/os.html#os.PathLike) instance, the file contents will be read asynchronously automatically. + ## Handling errors When the library is unable to connect to the API (for example, due to network connection problems or a timeout), a subclass of `casedev.APIConnectionError` is raised. diff --git a/api.md b/api.md index 0f5f8491..fa2a630a 100644 --- a/api.md +++ b/api.md @@ -1,68 +1,62 @@ -# Agent +# Connectors ## V1 -### Agents - Types: ```python -from casedev.types.agent.v1 import ( - AgentCreateResponse, - AgentRetrieveResponse, - AgentUpdateResponse, - AgentListResponse, - AgentDeleteResponse, -) +from casedev.types.connectors import V1SyncLinkResponse, V1TransferResponse ``` Methods: -- client.agent.v1.agents.create(\*\*params) -> AgentCreateResponse -- client.agent.v1.agents.retrieve(id) -> AgentRetrieveResponse -- client.agent.v1.agents.update(id, \*\*params) -> AgentUpdateResponse -- client.agent.v1.agents.list(\*\*params) -> AgentListResponse -- client.agent.v1.agents.delete(id) -> AgentDeleteResponse +- client.connectors.v1.sync_link(\*\*params) -> V1SyncLinkResponse +- client.connectors.v1.transfer(\*\*params) -> V1TransferResponse -### Run +### Installations -Types: +Methods: -```python -from casedev.types.agent.v1 import ( - RunCreateResponse, - RunListResponse, - RunCancelResponse, - RunEventsResponse, - RunExecResponse, - RunGetDetailsResponse, - RunGetStatusResponse, - RunWatchResponse, -) -``` +- client.connectors.v1.installations.list(\*\*params) -> None +- client.connectors.v1.installations.ensure(\*\*params) -> None + +#### Vaults Methods: -- client.agent.v1.run.create(\*\*params) -> RunCreateResponse -- client.agent.v1.run.list(\*\*params) -> RunListResponse -- client.agent.v1.run.cancel(id) -> RunCancelResponse -- client.agent.v1.run.events(id, \*\*params) -> str -- client.agent.v1.run.exec(id) -> RunExecResponse -- client.agent.v1.run.get_details(id) -> RunGetDetailsResponse -- client.agent.v1.run.get_status(id) -> RunGetStatusResponse -- client.agent.v1.run.watch(id, \*\*params) -> RunWatchResponse +- client.connectors.v1.installations.vaults.list(id) -> None +- client.connectors.v1.installations.vaults.grant(vault_id, \*, id, \*\*params) -> None +- client.connectors.v1.installations.vaults.revoke(vault_id, \*, id) -> None -### Execute +### Connections Types: ```python -from casedev.types.agent.v1 import ExecuteCreateResponse +from casedev.types.connectors.v1 import ( + ConnectionCreateResponse, + ConnectionListResponse, + ConnectionBrowseResponse, +) ``` Methods: -- client.agent.v1.execute.create(\*\*params) -> ExecuteCreateResponse +- client.connectors.v1.connections.create(\*\*params) -> ConnectionCreateResponse +- client.connectors.v1.connections.retrieve(id) -> None +- client.connectors.v1.connections.list(\*\*params) -> ConnectionListResponse +- client.connectors.v1.connections.delete(id, \*\*params) -> None +- client.connectors.v1.connections.browse(id, \*\*params) -> ConnectionBrowseResponse + +### Links + +Methods: + +- client.connectors.v1.links.retrieve(id) -> None +- client.connectors.v1.links.update(id, \*\*params) -> None +- client.connectors.v1.links.list(\*\*params) -> None +- client.connectors.v1.links.delete(id, \*\*params) -> None +- client.connectors.v1.links.list_objects(id, \*\*params) -> None # System @@ -167,89 +161,6 @@ Methods: - client.compute.v1.secrets.retrieve_group(group, \*\*params) -> SecretRetrieveGroupResponse - client.compute.v1.secrets.update_group(group, \*\*params) -> SecretUpdateGroupResponse -# Database - -## V1 - -Types: - -```python -from casedev.types.database import V1GetUsageResponse -``` - -Methods: - -- client.database.v1.get_usage() -> V1GetUsageResponse - -### Projects - -Types: - -```python -from casedev.types.database.v1 import ( - ProjectCreateResponse, - ProjectRetrieveResponse, - ProjectListResponse, - ProjectDeleteResponse, - ProjectCreateBranchResponse, - ProjectGetConnectionResponse, - ProjectListBranchesResponse, -) -``` - -Methods: - -- client.database.v1.projects.create(\*\*params) -> ProjectCreateResponse -- client.database.v1.projects.retrieve(id) -> ProjectRetrieveResponse -- client.database.v1.projects.list() -> ProjectListResponse -- client.database.v1.projects.delete(id) -> ProjectDeleteResponse -- client.database.v1.projects.create_branch(id, \*\*params) -> ProjectCreateBranchResponse -- client.database.v1.projects.get_connection(id, \*\*params) -> ProjectGetConnectionResponse -- client.database.v1.projects.list_branches(id) -> ProjectListBranchesResponse - -# DocumentTemplates - -Methods: - -- client.document_templates.create() -> None -- client.document_templates.retrieve(id) -> None -- client.document_templates.update(id) -> None -- client.document_templates.list() -> None -- client.document_templates.delete(id) -> None -- client.document_templates.confirm(id) -> None - -## FromVaultObject - -Methods: - -- client.document_templates.from_vault_object.create() -> None - -# Format - -## V1 - -Methods: - -- client.format.v1.create_document(\*\*params) -> BinaryAPIResponse - -### Templates - -Types: - -```python -from casedev.types.format.v1 import ( - TemplateCreateResponse, - TemplateRetrieveResponse, - TemplateListResponse, -) -``` - -Methods: - -- client.format.v1.templates.create(\*\*params) -> TemplateCreateResponse -- client.format.v1.templates.retrieve(id) -> TemplateRetrieveResponse -- client.format.v1.templates.list(\*\*params) -> TemplateListResponse - # Legal ## V1 @@ -261,7 +172,6 @@ from casedev.types.legal import ( DocketDetail, DocketSearchResult, V1DocketResponse, - V1DraftResponse, V1FindResponse, V1GetCitationsResponse, V1GetCitationsFromURLResponse, @@ -280,7 +190,6 @@ from casedev.types.legal import ( Methods: - client.legal.v1.docket(\*\*params) -> V1DocketResponse -- client.legal.v1.draft(\*\*params) -> V1DraftResponse - client.legal.v1.find(\*\*params) -> V1FindResponse - client.legal.v1.get_citations(\*\*params) -> V1GetCitationsResponse - client.legal.v1.get_citations_from_url(\*\*params) -> V1GetCitationsFromURLResponse @@ -304,7 +213,7 @@ Methods: - client.linc.v1.sessions.create(\*\*params) -> None - client.linc.v1.sessions.delete(id) -> None -- client.linc.v1.sessions.cancel(id) -> None +- client.linc.v1.sessions.cancel(id, \*\*params) -> None - client.linc.v1.sessions.ingest_events(id, \*\*params) -> None - client.linc.v1.sessions.retrieve_events(id, \*\*params) -> None - client.linc.v1.sessions.retrieve_messages(id, \*\*params) -> None @@ -395,7 +304,6 @@ Methods: - client.matters.v1.work_items.update(work_item_id, \*, id, \*\*params) -> None - client.matters.v1.work_items.list(id, \*\*params) -> None - client.matters.v1.work_items.decide(work_item_id, \*, id, \*\*params) -> None -- client.matters.v1.work_items.list_executions(work_item_id, \*, id) -> None # Llm @@ -521,26 +429,6 @@ Methods: - client.privilege.v1.detect(\*\*params) -> V1DetectResponse -# Mail - -## V1 - -### Inboxes - -Methods: - -- client.mail.v1.inboxes.create(\*\*params) -> None -- client.mail.v1.inboxes.retrieve(inbox_id) -> None -- client.mail.v1.inboxes.list() -> None -- client.mail.v1.inboxes.delete(inbox_id) -> None -- client.mail.v1.inboxes.get_attachment(attachment_id, \*, inbox_id, message_id) -> None -- client.mail.v1.inboxes.get_message(message_id, \*, inbox_id) -> None -- client.mail.v1.inboxes.get_policy(inbox_id) -> None -- client.mail.v1.inboxes.list_messages(inbox_id) -> None -- client.mail.v1.inboxes.reply(message_id, \*, inbox_id) -> None -- client.mail.v1.inboxes.send(inbox_id) -> None -- client.mail.v1.inboxes.set_policy(inbox_id, \*\*params) -> None - # Skills Types: @@ -589,8 +477,6 @@ Types: from casedev.types.search import ( V1AnswerResponse, V1ContentsResponse, - V1ResearchResponse, - V1RetrieveResearchResponse, V1SearchResponse, V1SimilarResponse, ) @@ -600,20 +486,9 @@ Methods: - client.search.v1.answer(\*\*params) -> V1AnswerResponse - client.search.v1.contents(\*\*params) -> V1ContentsResponse -- client.search.v1.research(\*\*params) -> V1ResearchResponse -- client.search.v1.retrieve_research(id, \*\*params) -> V1RetrieveResearchResponse - client.search.v1.search(\*\*params) -> V1SearchResponse - client.search.v1.similar(\*\*params) -> V1SimilarResponse -# Superdoc - -## V1 - -Methods: - -- client.superdoc.v1.annotate(\*\*params) -> BinaryAPIResponse -- client.superdoc.v1.convert(\*\*params) -> BinaryAPIResponse - # Translate ## V1 @@ -629,6 +504,7 @@ Methods: - client.translate.v1.detect(\*\*params) -> V1DetectResponse - client.translate.v1.list_languages(\*\*params) -> V1ListLanguagesResponse - client.translate.v1.translate(\*\*params) -> V1TranslateResponse +- client.translate.v1.translate_document(\*\*params) -> BinaryAPIResponse # Usage @@ -690,24 +566,6 @@ Methods: - client.vault.events.subscriptions.delete(subscription_id, \*, id) -> None - client.vault.events.subscriptions.test(subscription_id, \*, id, \*\*params) -> None -## Graphrag - -Types: - -```python -from casedev.types.vault import ( - GraphragGetStatsResponse, - GraphragInitResponse, - GraphragProcessObjectResponse, -) -``` - -Methods: - -- client.vault.graphrag.get_stats(id) -> GraphragGetStatsResponse -- client.vault.graphrag.init(id) -> GraphragInitResponse -- client.vault.graphrag.process_object(object_id, \*, id) -> GraphragProcessObjectResponse - ## Groups Methods: @@ -747,9 +605,8 @@ from casedev.types.vault import ( ObjectGetChunksResponse, ObjectGetOcrWordsResponse, ObjectGetPagesResponse, - ObjectGetSummarizeJobResponse, ObjectGetTextResponse, - ObjectSummarizeResponse, + ObjectMergeResponse, ) ``` @@ -765,9 +622,8 @@ Methods: - client.vault.objects.get_chunks(object_id, \*, id, \*\*params) -> ObjectGetChunksResponse - client.vault.objects.get_ocr_words(object_id, \*, id, \*\*params) -> ObjectGetOcrWordsResponse - client.vault.objects.get_pages(object_id, \*, id, \*\*params) -> ObjectGetPagesResponse -- client.vault.objects.get_summarize_job(job_id, \*, id, object_id) -> ObjectGetSummarizeJobResponse - client.vault.objects.get_text(object_id, \*, id) -> ObjectGetTextResponse -- client.vault.objects.summarize(object_id, \*, id, \*\*params) -> ObjectSummarizeResponse +- client.vault.objects.merge(id, \*\*params) -> ObjectMergeResponse ## Memory diff --git a/scripts/lint b/scripts/lint index 6532679b..580a84ed 100755 --- a/scripts/lint +++ b/scripts/lint @@ -13,7 +13,7 @@ else fi echo "==> Running pyright" -uv run pyright +uv run pyright -p . echo "==> Running mypy" uv run mypy . diff --git a/scripts/mock b/scripts/mock index 1ee552a4..515631dc 100755 --- a/scripts/mock +++ b/scripts/mock @@ -11,7 +11,7 @@ elif [ -n "$STAINLESS_OPENAPI_SPEC_URL" ]; then URL="$STAINLESS_OPENAPI_SPEC_URL" else # Embedded OpenAPI spec (base64-encoded, gzipped) - EMBEDDED_SPEC="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" + EMBEDDED_SPEC="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" SPEC_TMPFILE="$(mktemp)" trap 'rm -f "$SPEC_TMPFILE"' EXIT echo "$EMBEDDED_SPEC" | base64 --decode | gunzip > "$SPEC_TMPFILE" diff --git a/src/casedev/_client.py b/src/casedev/_client.py index 487f628f..e418969f 100644 --- a/src/casedev/_client.py +++ b/src/casedev/_client.py @@ -39,53 +39,40 @@ llm, ocr, linc, - mail, - agent, legal, media, usage, vault, voice, - format, memory, search, skills, system, compute, matters, - database, - superdoc, webhooks, privilege, translate, - document_templates, + connectors, ) from .resources.system import SystemResource, AsyncSystemResource from .resources.llm.llm import LlmResource, AsyncLlmResource from .resources.ocr.ocr import OcrResource, AsyncOcrResource from .resources.linc.linc import LincResource, AsyncLincResource - from .resources.mail.mail import MailResource, AsyncMailResource - from .resources.agent.agent import AgentResource, AsyncAgentResource from .resources.legal.legal import LegalResource, AsyncLegalResource from .resources.media.media import MediaResource, AsyncMediaResource from .resources.usage.usage import UsageResource, AsyncUsageResource from .resources.vault.vault import VaultResource, AsyncVaultResource from .resources.voice.voice import VoiceResource, AsyncVoiceResource - from .resources.format.format import FormatResource, AsyncFormatResource from .resources.memory.memory import MemoryResource, AsyncMemoryResource from .resources.search.search import SearchResource, AsyncSearchResource from .resources.skills.skills import SkillsResource, AsyncSkillsResource from .resources.compute.compute import ComputeResource, AsyncComputeResource from .resources.matters.matters import MattersResource, AsyncMattersResource - from .resources.database.database import DatabaseResource, AsyncDatabaseResource - from .resources.superdoc.superdoc import SuperdocResource, AsyncSuperdocResource from .resources.webhooks.webhooks import WebhooksResource, AsyncWebhooksResource from .resources.privilege.privilege import PrivilegeResource, AsyncPrivilegeResource from .resources.translate.translate import TranslateResource, AsyncTranslateResource - from .resources.document_templates.document_templates import ( - DocumentTemplatesResource, - AsyncDocumentTemplatesResource, - ) + from .resources.connectors.connectors import ConnectorsResource, AsyncConnectorsResource __all__ = [ "ENVIRONMENTS", @@ -194,10 +181,10 @@ def __init__( ) @cached_property - def agent(self) -> AgentResource: - from .resources.agent import AgentResource + def connectors(self) -> ConnectorsResource: + from .resources.connectors import ConnectorsResource - return AgentResource(self) + return ConnectorsResource(self) @cached_property def system(self) -> SystemResource: @@ -212,24 +199,6 @@ def compute(self) -> ComputeResource: return ComputeResource(self) - @cached_property - def database(self) -> DatabaseResource: - from .resources.database import DatabaseResource - - return DatabaseResource(self) - - @cached_property - def document_templates(self) -> DocumentTemplatesResource: - from .resources.document_templates import DocumentTemplatesResource - - return DocumentTemplatesResource(self) - - @cached_property - def format(self) -> FormatResource: - from .resources.format import FormatResource - - return FormatResource(self) - @cached_property def legal(self) -> LegalResource: from .resources.legal import LegalResource @@ -279,12 +248,6 @@ def privilege(self) -> PrivilegeResource: return PrivilegeResource(self) - @cached_property - def mail(self) -> MailResource: - from .resources.mail import MailResource - - return MailResource(self) - @cached_property def skills(self) -> SkillsResource: """Search and read legal AI skills for agents""" @@ -298,12 +261,6 @@ def search(self) -> SearchResource: return SearchResource(self) - @cached_property - def superdoc(self) -> SuperdocResource: - from .resources.superdoc import SuperdocResource - - return SuperdocResource(self) - @cached_property def translate(self) -> TranslateResource: from .resources.translate import TranslateResource @@ -539,10 +496,10 @@ def __init__( ) @cached_property - def agent(self) -> AsyncAgentResource: - from .resources.agent import AsyncAgentResource + def connectors(self) -> AsyncConnectorsResource: + from .resources.connectors import AsyncConnectorsResource - return AsyncAgentResource(self) + return AsyncConnectorsResource(self) @cached_property def system(self) -> AsyncSystemResource: @@ -557,24 +514,6 @@ def compute(self) -> AsyncComputeResource: return AsyncComputeResource(self) - @cached_property - def database(self) -> AsyncDatabaseResource: - from .resources.database import AsyncDatabaseResource - - return AsyncDatabaseResource(self) - - @cached_property - def document_templates(self) -> AsyncDocumentTemplatesResource: - from .resources.document_templates import AsyncDocumentTemplatesResource - - return AsyncDocumentTemplatesResource(self) - - @cached_property - def format(self) -> AsyncFormatResource: - from .resources.format import AsyncFormatResource - - return AsyncFormatResource(self) - @cached_property def legal(self) -> AsyncLegalResource: from .resources.legal import AsyncLegalResource @@ -624,12 +563,6 @@ def privilege(self) -> AsyncPrivilegeResource: return AsyncPrivilegeResource(self) - @cached_property - def mail(self) -> AsyncMailResource: - from .resources.mail import AsyncMailResource - - return AsyncMailResource(self) - @cached_property def skills(self) -> AsyncSkillsResource: """Search and read legal AI skills for agents""" @@ -643,12 +576,6 @@ def search(self) -> AsyncSearchResource: return AsyncSearchResource(self) - @cached_property - def superdoc(self) -> AsyncSuperdocResource: - from .resources.superdoc import AsyncSuperdocResource - - return AsyncSuperdocResource(self) - @cached_property def translate(self) -> AsyncTranslateResource: from .resources.translate import AsyncTranslateResource @@ -802,10 +729,10 @@ def __init__(self, client: Casedev) -> None: self._client = client @cached_property - def agent(self) -> agent.AgentResourceWithRawResponse: - from .resources.agent import AgentResourceWithRawResponse + def connectors(self) -> connectors.ConnectorsResourceWithRawResponse: + from .resources.connectors import ConnectorsResourceWithRawResponse - return AgentResourceWithRawResponse(self._client.agent) + return ConnectorsResourceWithRawResponse(self._client.connectors) @cached_property def system(self) -> system.SystemResourceWithRawResponse: @@ -820,24 +747,6 @@ def compute(self) -> compute.ComputeResourceWithRawResponse: return ComputeResourceWithRawResponse(self._client.compute) - @cached_property - def database(self) -> database.DatabaseResourceWithRawResponse: - from .resources.database import DatabaseResourceWithRawResponse - - return DatabaseResourceWithRawResponse(self._client.database) - - @cached_property - def document_templates(self) -> document_templates.DocumentTemplatesResourceWithRawResponse: - from .resources.document_templates import DocumentTemplatesResourceWithRawResponse - - return DocumentTemplatesResourceWithRawResponse(self._client.document_templates) - - @cached_property - def format(self) -> format.FormatResourceWithRawResponse: - from .resources.format import FormatResourceWithRawResponse - - return FormatResourceWithRawResponse(self._client.format) - @cached_property def legal(self) -> legal.LegalResourceWithRawResponse: from .resources.legal import LegalResourceWithRawResponse @@ -887,12 +796,6 @@ def privilege(self) -> privilege.PrivilegeResourceWithRawResponse: return PrivilegeResourceWithRawResponse(self._client.privilege) - @cached_property - def mail(self) -> mail.MailResourceWithRawResponse: - from .resources.mail import MailResourceWithRawResponse - - return MailResourceWithRawResponse(self._client.mail) - @cached_property def skills(self) -> skills.SkillsResourceWithRawResponse: """Search and read legal AI skills for agents""" @@ -906,12 +809,6 @@ def search(self) -> search.SearchResourceWithRawResponse: return SearchResourceWithRawResponse(self._client.search) - @cached_property - def superdoc(self) -> superdoc.SuperdocResourceWithRawResponse: - from .resources.superdoc import SuperdocResourceWithRawResponse - - return SuperdocResourceWithRawResponse(self._client.superdoc) - @cached_property def translate(self) -> translate.TranslateResourceWithRawResponse: from .resources.translate import TranslateResourceWithRawResponse @@ -951,10 +848,10 @@ def __init__(self, client: AsyncCasedev) -> None: self._client = client @cached_property - def agent(self) -> agent.AsyncAgentResourceWithRawResponse: - from .resources.agent import AsyncAgentResourceWithRawResponse + def connectors(self) -> connectors.AsyncConnectorsResourceWithRawResponse: + from .resources.connectors import AsyncConnectorsResourceWithRawResponse - return AsyncAgentResourceWithRawResponse(self._client.agent) + return AsyncConnectorsResourceWithRawResponse(self._client.connectors) @cached_property def system(self) -> system.AsyncSystemResourceWithRawResponse: @@ -969,24 +866,6 @@ def compute(self) -> compute.AsyncComputeResourceWithRawResponse: return AsyncComputeResourceWithRawResponse(self._client.compute) - @cached_property - def database(self) -> database.AsyncDatabaseResourceWithRawResponse: - from .resources.database import AsyncDatabaseResourceWithRawResponse - - return AsyncDatabaseResourceWithRawResponse(self._client.database) - - @cached_property - def document_templates(self) -> document_templates.AsyncDocumentTemplatesResourceWithRawResponse: - from .resources.document_templates import AsyncDocumentTemplatesResourceWithRawResponse - - return AsyncDocumentTemplatesResourceWithRawResponse(self._client.document_templates) - - @cached_property - def format(self) -> format.AsyncFormatResourceWithRawResponse: - from .resources.format import AsyncFormatResourceWithRawResponse - - return AsyncFormatResourceWithRawResponse(self._client.format) - @cached_property def legal(self) -> legal.AsyncLegalResourceWithRawResponse: from .resources.legal import AsyncLegalResourceWithRawResponse @@ -1036,12 +915,6 @@ def privilege(self) -> privilege.AsyncPrivilegeResourceWithRawResponse: return AsyncPrivilegeResourceWithRawResponse(self._client.privilege) - @cached_property - def mail(self) -> mail.AsyncMailResourceWithRawResponse: - from .resources.mail import AsyncMailResourceWithRawResponse - - return AsyncMailResourceWithRawResponse(self._client.mail) - @cached_property def skills(self) -> skills.AsyncSkillsResourceWithRawResponse: """Search and read legal AI skills for agents""" @@ -1055,12 +928,6 @@ def search(self) -> search.AsyncSearchResourceWithRawResponse: return AsyncSearchResourceWithRawResponse(self._client.search) - @cached_property - def superdoc(self) -> superdoc.AsyncSuperdocResourceWithRawResponse: - from .resources.superdoc import AsyncSuperdocResourceWithRawResponse - - return AsyncSuperdocResourceWithRawResponse(self._client.superdoc) - @cached_property def translate(self) -> translate.AsyncTranslateResourceWithRawResponse: from .resources.translate import AsyncTranslateResourceWithRawResponse @@ -1100,10 +967,10 @@ def __init__(self, client: Casedev) -> None: self._client = client @cached_property - def agent(self) -> agent.AgentResourceWithStreamingResponse: - from .resources.agent import AgentResourceWithStreamingResponse + def connectors(self) -> connectors.ConnectorsResourceWithStreamingResponse: + from .resources.connectors import ConnectorsResourceWithStreamingResponse - return AgentResourceWithStreamingResponse(self._client.agent) + return ConnectorsResourceWithStreamingResponse(self._client.connectors) @cached_property def system(self) -> system.SystemResourceWithStreamingResponse: @@ -1118,24 +985,6 @@ def compute(self) -> compute.ComputeResourceWithStreamingResponse: return ComputeResourceWithStreamingResponse(self._client.compute) - @cached_property - def database(self) -> database.DatabaseResourceWithStreamingResponse: - from .resources.database import DatabaseResourceWithStreamingResponse - - return DatabaseResourceWithStreamingResponse(self._client.database) - - @cached_property - def document_templates(self) -> document_templates.DocumentTemplatesResourceWithStreamingResponse: - from .resources.document_templates import DocumentTemplatesResourceWithStreamingResponse - - return DocumentTemplatesResourceWithStreamingResponse(self._client.document_templates) - - @cached_property - def format(self) -> format.FormatResourceWithStreamingResponse: - from .resources.format import FormatResourceWithStreamingResponse - - return FormatResourceWithStreamingResponse(self._client.format) - @cached_property def legal(self) -> legal.LegalResourceWithStreamingResponse: from .resources.legal import LegalResourceWithStreamingResponse @@ -1185,12 +1034,6 @@ def privilege(self) -> privilege.PrivilegeResourceWithStreamingResponse: return PrivilegeResourceWithStreamingResponse(self._client.privilege) - @cached_property - def mail(self) -> mail.MailResourceWithStreamingResponse: - from .resources.mail import MailResourceWithStreamingResponse - - return MailResourceWithStreamingResponse(self._client.mail) - @cached_property def skills(self) -> skills.SkillsResourceWithStreamingResponse: """Search and read legal AI skills for agents""" @@ -1204,12 +1047,6 @@ def search(self) -> search.SearchResourceWithStreamingResponse: return SearchResourceWithStreamingResponse(self._client.search) - @cached_property - def superdoc(self) -> superdoc.SuperdocResourceWithStreamingResponse: - from .resources.superdoc import SuperdocResourceWithStreamingResponse - - return SuperdocResourceWithStreamingResponse(self._client.superdoc) - @cached_property def translate(self) -> translate.TranslateResourceWithStreamingResponse: from .resources.translate import TranslateResourceWithStreamingResponse @@ -1249,10 +1086,10 @@ def __init__(self, client: AsyncCasedev) -> None: self._client = client @cached_property - def agent(self) -> agent.AsyncAgentResourceWithStreamingResponse: - from .resources.agent import AsyncAgentResourceWithStreamingResponse + def connectors(self) -> connectors.AsyncConnectorsResourceWithStreamingResponse: + from .resources.connectors import AsyncConnectorsResourceWithStreamingResponse - return AsyncAgentResourceWithStreamingResponse(self._client.agent) + return AsyncConnectorsResourceWithStreamingResponse(self._client.connectors) @cached_property def system(self) -> system.AsyncSystemResourceWithStreamingResponse: @@ -1267,24 +1104,6 @@ def compute(self) -> compute.AsyncComputeResourceWithStreamingResponse: return AsyncComputeResourceWithStreamingResponse(self._client.compute) - @cached_property - def database(self) -> database.AsyncDatabaseResourceWithStreamingResponse: - from .resources.database import AsyncDatabaseResourceWithStreamingResponse - - return AsyncDatabaseResourceWithStreamingResponse(self._client.database) - - @cached_property - def document_templates(self) -> document_templates.AsyncDocumentTemplatesResourceWithStreamingResponse: - from .resources.document_templates import AsyncDocumentTemplatesResourceWithStreamingResponse - - return AsyncDocumentTemplatesResourceWithStreamingResponse(self._client.document_templates) - - @cached_property - def format(self) -> format.AsyncFormatResourceWithStreamingResponse: - from .resources.format import AsyncFormatResourceWithStreamingResponse - - return AsyncFormatResourceWithStreamingResponse(self._client.format) - @cached_property def legal(self) -> legal.AsyncLegalResourceWithStreamingResponse: from .resources.legal import AsyncLegalResourceWithStreamingResponse @@ -1334,12 +1153,6 @@ def privilege(self) -> privilege.AsyncPrivilegeResourceWithStreamingResponse: return AsyncPrivilegeResourceWithStreamingResponse(self._client.privilege) - @cached_property - def mail(self) -> mail.AsyncMailResourceWithStreamingResponse: - from .resources.mail import AsyncMailResourceWithStreamingResponse - - return AsyncMailResourceWithStreamingResponse(self._client.mail) - @cached_property def skills(self) -> skills.AsyncSkillsResourceWithStreamingResponse: """Search and read legal AI skills for agents""" @@ -1353,12 +1166,6 @@ def search(self) -> search.AsyncSearchResourceWithStreamingResponse: return AsyncSearchResourceWithStreamingResponse(self._client.search) - @cached_property - def superdoc(self) -> superdoc.AsyncSuperdocResourceWithStreamingResponse: - from .resources.superdoc import AsyncSuperdocResourceWithStreamingResponse - - return AsyncSuperdocResourceWithStreamingResponse(self._client.superdoc) - @cached_property def translate(self) -> translate.AsyncTranslateResourceWithStreamingResponse: from .resources.translate import AsyncTranslateResourceWithStreamingResponse diff --git a/src/casedev/_files.py b/src/casedev/_files.py index 76da9e08..9aee1659 100644 --- a/src/casedev/_files.py +++ b/src/casedev/_files.py @@ -36,7 +36,7 @@ def assert_is_file_content(obj: object, *, key: str | None = None) -> None: if not is_file_content(obj): prefix = f"Expected entry at `{key}`" if key is not None else f"Expected file input `{obj!r}`" raise RuntimeError( - f"{prefix} to be bytes, an io.IOBase instance, PathLike or a tuple but received {type(obj)} instead." + f"{prefix} to be bytes, an io.IOBase instance, PathLike or a tuple but received {type(obj)} instead. See https://github.com/CaseMark/casedev-python/tree/main#file-uploads" ) from None diff --git a/src/casedev/resources/__init__.py b/src/casedev/resources/__init__.py index 040fbc50..84699412 100644 --- a/src/casedev/resources/__init__.py +++ b/src/casedev/resources/__init__.py @@ -24,22 +24,6 @@ LincResourceWithStreamingResponse, AsyncLincResourceWithStreamingResponse, ) -from .mail import ( - MailResource, - AsyncMailResource, - MailResourceWithRawResponse, - AsyncMailResourceWithRawResponse, - MailResourceWithStreamingResponse, - AsyncMailResourceWithStreamingResponse, -) -from .agent import ( - AgentResource, - AsyncAgentResource, - AgentResourceWithRawResponse, - AsyncAgentResourceWithRawResponse, - AgentResourceWithStreamingResponse, - AsyncAgentResourceWithStreamingResponse, -) from .legal import ( LegalResource, AsyncLegalResource, @@ -80,14 +64,6 @@ VoiceResourceWithStreamingResponse, AsyncVoiceResourceWithStreamingResponse, ) -from .format import ( - FormatResource, - AsyncFormatResource, - FormatResourceWithRawResponse, - AsyncFormatResourceWithRawResponse, - FormatResourceWithStreamingResponse, - AsyncFormatResourceWithStreamingResponse, -) from .memory import ( MemoryResource, AsyncMemoryResource, @@ -136,22 +112,6 @@ MattersResourceWithStreamingResponse, AsyncMattersResourceWithStreamingResponse, ) -from .database import ( - DatabaseResource, - AsyncDatabaseResource, - DatabaseResourceWithRawResponse, - AsyncDatabaseResourceWithRawResponse, - DatabaseResourceWithStreamingResponse, - AsyncDatabaseResourceWithStreamingResponse, -) -from .superdoc import ( - SuperdocResource, - AsyncSuperdocResource, - SuperdocResourceWithRawResponse, - AsyncSuperdocResourceWithRawResponse, - SuperdocResourceWithStreamingResponse, - AsyncSuperdocResourceWithStreamingResponse, -) from .webhooks import ( WebhooksResource, AsyncWebhooksResource, @@ -176,22 +136,22 @@ TranslateResourceWithStreamingResponse, AsyncTranslateResourceWithStreamingResponse, ) -from .document_templates import ( - DocumentTemplatesResource, - AsyncDocumentTemplatesResource, - DocumentTemplatesResourceWithRawResponse, - AsyncDocumentTemplatesResourceWithRawResponse, - DocumentTemplatesResourceWithStreamingResponse, - AsyncDocumentTemplatesResourceWithStreamingResponse, +from .connectors import ( + ConnectorsResource, + AsyncConnectorsResource, + ConnectorsResourceWithRawResponse, + AsyncConnectorsResourceWithRawResponse, + ConnectorsResourceWithStreamingResponse, + AsyncConnectorsResourceWithStreamingResponse, ) __all__ = [ - "AgentResource", - "AsyncAgentResource", - "AgentResourceWithRawResponse", - "AsyncAgentResourceWithRawResponse", - "AgentResourceWithStreamingResponse", - "AsyncAgentResourceWithStreamingResponse", + "ConnectorsResource", + "AsyncConnectorsResource", + "ConnectorsResourceWithRawResponse", + "AsyncConnectorsResourceWithRawResponse", + "ConnectorsResourceWithStreamingResponse", + "AsyncConnectorsResourceWithStreamingResponse", "SystemResource", "AsyncSystemResource", "SystemResourceWithRawResponse", @@ -204,24 +164,6 @@ "AsyncComputeResourceWithRawResponse", "ComputeResourceWithStreamingResponse", "AsyncComputeResourceWithStreamingResponse", - "DatabaseResource", - "AsyncDatabaseResource", - "DatabaseResourceWithRawResponse", - "AsyncDatabaseResourceWithRawResponse", - "DatabaseResourceWithStreamingResponse", - "AsyncDatabaseResourceWithStreamingResponse", - "DocumentTemplatesResource", - "AsyncDocumentTemplatesResource", - "DocumentTemplatesResourceWithRawResponse", - "AsyncDocumentTemplatesResourceWithRawResponse", - "DocumentTemplatesResourceWithStreamingResponse", - "AsyncDocumentTemplatesResourceWithStreamingResponse", - "FormatResource", - "AsyncFormatResource", - "FormatResourceWithRawResponse", - "AsyncFormatResourceWithRawResponse", - "FormatResourceWithStreamingResponse", - "AsyncFormatResourceWithStreamingResponse", "LegalResource", "AsyncLegalResource", "LegalResourceWithRawResponse", @@ -270,12 +212,6 @@ "AsyncPrivilegeResourceWithRawResponse", "PrivilegeResourceWithStreamingResponse", "AsyncPrivilegeResourceWithStreamingResponse", - "MailResource", - "AsyncMailResource", - "MailResourceWithRawResponse", - "AsyncMailResourceWithRawResponse", - "MailResourceWithStreamingResponse", - "AsyncMailResourceWithStreamingResponse", "SkillsResource", "AsyncSkillsResource", "SkillsResourceWithRawResponse", @@ -288,12 +224,6 @@ "AsyncSearchResourceWithRawResponse", "SearchResourceWithStreamingResponse", "AsyncSearchResourceWithStreamingResponse", - "SuperdocResource", - "AsyncSuperdocResource", - "SuperdocResourceWithRawResponse", - "AsyncSuperdocResourceWithRawResponse", - "SuperdocResourceWithStreamingResponse", - "AsyncSuperdocResourceWithStreamingResponse", "TranslateResource", "AsyncTranslateResource", "TranslateResourceWithRawResponse", diff --git a/src/casedev/resources/agent/v1/__init__.py b/src/casedev/resources/agent/v1/__init__.py deleted file mode 100644 index 1c3608c6..00000000 --- a/src/casedev/resources/agent/v1/__init__.py +++ /dev/null @@ -1,61 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from .v1 import ( - V1Resource, - AsyncV1Resource, - V1ResourceWithRawResponse, - AsyncV1ResourceWithRawResponse, - V1ResourceWithStreamingResponse, - AsyncV1ResourceWithStreamingResponse, -) -from .run import ( - RunResource, - AsyncRunResource, - RunResourceWithRawResponse, - AsyncRunResourceWithRawResponse, - RunResourceWithStreamingResponse, - AsyncRunResourceWithStreamingResponse, -) -from .agents import ( - AgentsResource, - AsyncAgentsResource, - AgentsResourceWithRawResponse, - AsyncAgentsResourceWithRawResponse, - AgentsResourceWithStreamingResponse, - AsyncAgentsResourceWithStreamingResponse, -) -from .execute import ( - ExecuteResource, - AsyncExecuteResource, - ExecuteResourceWithRawResponse, - AsyncExecuteResourceWithRawResponse, - ExecuteResourceWithStreamingResponse, - AsyncExecuteResourceWithStreamingResponse, -) - -__all__ = [ - "AgentsResource", - "AsyncAgentsResource", - "AgentsResourceWithRawResponse", - "AsyncAgentsResourceWithRawResponse", - "AgentsResourceWithStreamingResponse", - "AsyncAgentsResourceWithStreamingResponse", - "RunResource", - "AsyncRunResource", - "RunResourceWithRawResponse", - "AsyncRunResourceWithRawResponse", - "RunResourceWithStreamingResponse", - "AsyncRunResourceWithStreamingResponse", - "ExecuteResource", - "AsyncExecuteResource", - "ExecuteResourceWithRawResponse", - "AsyncExecuteResourceWithRawResponse", - "ExecuteResourceWithStreamingResponse", - "AsyncExecuteResourceWithStreamingResponse", - "V1Resource", - "AsyncV1Resource", - "V1ResourceWithRawResponse", - "AsyncV1ResourceWithRawResponse", - "V1ResourceWithStreamingResponse", - "AsyncV1ResourceWithStreamingResponse", -] diff --git a/src/casedev/resources/agent/v1/execute.py b/src/casedev/resources/agent/v1/execute.py deleted file mode 100644 index e78aafba..00000000 --- a/src/casedev/resources/agent/v1/execute.py +++ /dev/null @@ -1,279 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from __future__ import annotations - -from typing import Optional - -import httpx - -from ...._types import Body, Omit, Query, Headers, NotGiven, SequenceNotStr, omit, not_given -from ...._utils import maybe_transform, async_maybe_transform -from ...._compat import cached_property -from ...._resource import SyncAPIResource, AsyncAPIResource -from ...._response import ( - to_raw_response_wrapper, - to_streamed_response_wrapper, - async_to_raw_response_wrapper, - async_to_streamed_response_wrapper, -) -from ...._base_client import make_request_options -from ....types.agent.v1 import execute_create_params -from ....types.agent.v1.execute_create_response import ExecuteCreateResponse - -__all__ = ["ExecuteResource", "AsyncExecuteResource"] - - -class ExecuteResource(SyncAPIResource): - """ - Create, manage, and execute AI agents with tool access, sandbox environments, and async run workflows - """ - - @cached_property - def with_raw_response(self) -> ExecuteResourceWithRawResponse: - """ - This property can be used as a prefix for any HTTP method call to return - the raw response object instead of the parsed content. - - For more information, see https://www.github.com/CaseMark/casedev-python#accessing-raw-response-data-eg-headers - """ - return ExecuteResourceWithRawResponse(self) - - @cached_property - def with_streaming_response(self) -> ExecuteResourceWithStreamingResponse: - """ - An alternative to `.with_raw_response` that doesn't eagerly read the response body. - - For more information, see https://www.github.com/CaseMark/casedev-python#with_streaming_response - """ - return ExecuteResourceWithStreamingResponse(self) - - def create( - self, - *, - prompt: str, - disabled_tools: Optional[SequenceNotStr[str]] | Omit = omit, - enabled_tools: Optional[SequenceNotStr[str]] | Omit = omit, - guidance: Optional[str] | Omit = omit, - instructions: str | Omit = omit, - model: str | Omit = omit, - object_ids: Optional[SequenceNotStr[str]] | Omit = omit, - sandbox: Optional[execute_create_params.Sandbox] | Omit = omit, - vault_ids: Optional[SequenceNotStr[str]] | Omit = omit, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> ExecuteCreateResponse: - """Creates an ephemeral agent and immediately executes a run. - - Returns the run ID - for polling status and results. This is the fastest way to run an agent without - managing agent lifecycle. - - **Ephemeral agent lifecycle:** The agent created by this endpoint is - automatically soft-deleted and its scoped API key revoked when the run completes - (whether it succeeds, fails, or times out). Ephemeral agents do not appear in - GET /agent/v1/agents listings. The returned agentId is valid only for the - duration of the run — do not store it for reuse. For persistent, reusable - agents, use POST /agent/v1/agents instead. - - Args: - prompt: Task prompt for the agent - - disabled_tools: Denylist of tools the agent cannot use. Mutually exclusive with enabledTools — - set one or the other, not both. - - enabled_tools: Allowlist of tools the agent can use. Mutually exclusive with disabledTools — - set one or the other, not both. - - guidance: Additional context or constraints for this run - - instructions: System instructions. Defaults to a general-purpose legal assistant prompt if not - provided. - - model: LLM model identifier. Defaults to anthropic/claude-sonnet-4.6 - - object_ids: Scope this run to specific vault object IDs. The agent will only access these - objects. - - sandbox: Custom sandbox resources (cpu, memoryMiB) - - vault_ids: Restrict agent to specific vault IDs - - extra_headers: Send extra headers - - extra_query: Add additional query parameters to the request - - extra_body: Add additional JSON properties to the request - - timeout: Override the client-level default timeout for this request, in seconds - """ - return self._post( - "/agent/v1/execute", - body=maybe_transform( - { - "prompt": prompt, - "disabled_tools": disabled_tools, - "enabled_tools": enabled_tools, - "guidance": guidance, - "instructions": instructions, - "model": model, - "object_ids": object_ids, - "sandbox": sandbox, - "vault_ids": vault_ids, - }, - execute_create_params.ExecuteCreateParams, - ), - options=make_request_options( - extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout - ), - cast_to=ExecuteCreateResponse, - ) - - -class AsyncExecuteResource(AsyncAPIResource): - """ - Create, manage, and execute AI agents with tool access, sandbox environments, and async run workflows - """ - - @cached_property - def with_raw_response(self) -> AsyncExecuteResourceWithRawResponse: - """ - This property can be used as a prefix for any HTTP method call to return - the raw response object instead of the parsed content. - - For more information, see https://www.github.com/CaseMark/casedev-python#accessing-raw-response-data-eg-headers - """ - return AsyncExecuteResourceWithRawResponse(self) - - @cached_property - def with_streaming_response(self) -> AsyncExecuteResourceWithStreamingResponse: - """ - An alternative to `.with_raw_response` that doesn't eagerly read the response body. - - For more information, see https://www.github.com/CaseMark/casedev-python#with_streaming_response - """ - return AsyncExecuteResourceWithStreamingResponse(self) - - async def create( - self, - *, - prompt: str, - disabled_tools: Optional[SequenceNotStr[str]] | Omit = omit, - enabled_tools: Optional[SequenceNotStr[str]] | Omit = omit, - guidance: Optional[str] | Omit = omit, - instructions: str | Omit = omit, - model: str | Omit = omit, - object_ids: Optional[SequenceNotStr[str]] | Omit = omit, - sandbox: Optional[execute_create_params.Sandbox] | Omit = omit, - vault_ids: Optional[SequenceNotStr[str]] | Omit = omit, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> ExecuteCreateResponse: - """Creates an ephemeral agent and immediately executes a run. - - Returns the run ID - for polling status and results. This is the fastest way to run an agent without - managing agent lifecycle. - - **Ephemeral agent lifecycle:** The agent created by this endpoint is - automatically soft-deleted and its scoped API key revoked when the run completes - (whether it succeeds, fails, or times out). Ephemeral agents do not appear in - GET /agent/v1/agents listings. The returned agentId is valid only for the - duration of the run — do not store it for reuse. For persistent, reusable - agents, use POST /agent/v1/agents instead. - - Args: - prompt: Task prompt for the agent - - disabled_tools: Denylist of tools the agent cannot use. Mutually exclusive with enabledTools — - set one or the other, not both. - - enabled_tools: Allowlist of tools the agent can use. Mutually exclusive with disabledTools — - set one or the other, not both. - - guidance: Additional context or constraints for this run - - instructions: System instructions. Defaults to a general-purpose legal assistant prompt if not - provided. - - model: LLM model identifier. Defaults to anthropic/claude-sonnet-4.6 - - object_ids: Scope this run to specific vault object IDs. The agent will only access these - objects. - - sandbox: Custom sandbox resources (cpu, memoryMiB) - - vault_ids: Restrict agent to specific vault IDs - - extra_headers: Send extra headers - - extra_query: Add additional query parameters to the request - - extra_body: Add additional JSON properties to the request - - timeout: Override the client-level default timeout for this request, in seconds - """ - return await self._post( - "/agent/v1/execute", - body=await async_maybe_transform( - { - "prompt": prompt, - "disabled_tools": disabled_tools, - "enabled_tools": enabled_tools, - "guidance": guidance, - "instructions": instructions, - "model": model, - "object_ids": object_ids, - "sandbox": sandbox, - "vault_ids": vault_ids, - }, - execute_create_params.ExecuteCreateParams, - ), - options=make_request_options( - extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout - ), - cast_to=ExecuteCreateResponse, - ) - - -class ExecuteResourceWithRawResponse: - def __init__(self, execute: ExecuteResource) -> None: - self._execute = execute - - self.create = to_raw_response_wrapper( - execute.create, - ) - - -class AsyncExecuteResourceWithRawResponse: - def __init__(self, execute: AsyncExecuteResource) -> None: - self._execute = execute - - self.create = async_to_raw_response_wrapper( - execute.create, - ) - - -class ExecuteResourceWithStreamingResponse: - def __init__(self, execute: ExecuteResource) -> None: - self._execute = execute - - self.create = to_streamed_response_wrapper( - execute.create, - ) - - -class AsyncExecuteResourceWithStreamingResponse: - def __init__(self, execute: AsyncExecuteResource) -> None: - self._execute = execute - - self.create = async_to_streamed_response_wrapper( - execute.create, - ) diff --git a/src/casedev/resources/agent/v1/run.py b/src/casedev/resources/agent/v1/run.py deleted file mode 100644 index c70c8fc8..00000000 --- a/src/casedev/resources/agent/v1/run.py +++ /dev/null @@ -1,888 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from __future__ import annotations - -from typing import Optional -from typing_extensions import Literal - -import httpx - -from ...._types import Body, Omit, Query, Headers, NotGiven, SequenceNotStr, omit, not_given -from ...._utils import path_template, maybe_transform, async_maybe_transform -from ...._compat import cached_property -from ...._resource import SyncAPIResource, AsyncAPIResource -from ...._response import ( - to_raw_response_wrapper, - to_streamed_response_wrapper, - async_to_raw_response_wrapper, - async_to_streamed_response_wrapper, -) -from ...._streaming import Stream, AsyncStream -from ...._base_client import make_request_options -from ....types.agent.v1 import run_list_params, run_watch_params, run_create_params, run_events_params -from ....types.agent.v1.run_exec_response import RunExecResponse -from ....types.agent.v1.run_list_response import RunListResponse -from ....types.agent.v1.run_watch_response import RunWatchResponse -from ....types.agent.v1.run_cancel_response import RunCancelResponse -from ....types.agent.v1.run_create_response import RunCreateResponse -from ....types.agent.v1.run_events_response import RunEventsResponse -from ....types.agent.v1.run_get_status_response import RunGetStatusResponse -from ....types.agent.v1.run_get_details_response import RunGetDetailsResponse - -__all__ = ["RunResource", "AsyncRunResource"] - - -class RunResource(SyncAPIResource): - """ - Create, manage, and execute AI agents with tool access, sandbox environments, and async run workflows - """ - - @cached_property - def with_raw_response(self) -> RunResourceWithRawResponse: - """ - This property can be used as a prefix for any HTTP method call to return - the raw response object instead of the parsed content. - - For more information, see https://www.github.com/CaseMark/casedev-python#accessing-raw-response-data-eg-headers - """ - return RunResourceWithRawResponse(self) - - @cached_property - def with_streaming_response(self) -> RunResourceWithStreamingResponse: - """ - An alternative to `.with_raw_response` that doesn't eagerly read the response body. - - For more information, see https://www.github.com/CaseMark/casedev-python#with_streaming_response - """ - return RunResourceWithStreamingResponse(self) - - def create( - self, - *, - agent_id: str, - prompt: str, - callback_url: Optional[str] | Omit = omit, - guidance: Optional[str] | Omit = omit, - model: Optional[str] | Omit = omit, - object_ids: Optional[SequenceNotStr[str]] | Omit = omit, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> RunCreateResponse: - """Creates a run in queued state. - - Call POST /agent/v1/run/:id/exec to start - execution. - - Args: - agent_id: ID of the agent to run - - prompt: Task prompt for the agent - - callback_url: HTTPS callback URL to receive a notification when the run completes. Registered - atomically with the run — eliminates the race condition of calling /watch after - /exec. Additional watchers can still be added via POST /run/:id/watch. - - guidance: Additional guidance for this run - - model: Override the agent default model for this run - - object_ids: Scope this run to specific vault object IDs. The agent will only be able to - access these objects during execution. - - extra_headers: Send extra headers - - extra_query: Add additional query parameters to the request - - extra_body: Add additional JSON properties to the request - - timeout: Override the client-level default timeout for this request, in seconds - """ - return self._post( - "/agent/v1/run", - body=maybe_transform( - { - "agent_id": agent_id, - "prompt": prompt, - "callback_url": callback_url, - "guidance": guidance, - "model": model, - "object_ids": object_ids, - }, - run_create_params.RunCreateParams, - ), - options=make_request_options( - extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout - ), - cast_to=RunCreateResponse, - ) - - def list( - self, - *, - agent_id: str | Omit = omit, - cursor: str | Omit = omit, - limit: int | Omit = omit, - status: Literal["queued", "running", "completed", "failed", "cancelled"] | Omit = omit, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> RunListResponse: - """Lists agent runs for the authenticated organization. - - Supports filtering by - agent, status, and cursor-based pagination. - - Args: - agent_id: Filter by agent ID - - cursor: Pagination cursor (run ID from previous page). Returns runs created before this - run. - - limit: Maximum number of runs to return (default 50, max 250) - - status: Filter by run status - - extra_headers: Send extra headers - - extra_query: Add additional query parameters to the request - - extra_body: Add additional JSON properties to the request - - timeout: Override the client-level default timeout for this request, in seconds - """ - return self._get( - "/agent/v1/run", - options=make_request_options( - extra_headers=extra_headers, - extra_query=extra_query, - extra_body=extra_body, - timeout=timeout, - query=maybe_transform( - { - "agent_id": agent_id, - "cursor": cursor, - "limit": limit, - "status": status, - }, - run_list_params.RunListParams, - ), - ), - cast_to=RunListResponse, - ) - - def cancel( - self, - id: str, - *, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> RunCancelResponse: - """Cancels a running or queued run. - - Idempotent — cancelling a finished run returns - its current status. - - Args: - extra_headers: Send extra headers - - extra_query: Add additional query parameters to the request - - extra_body: Add additional JSON properties to the request - - timeout: Override the client-level default timeout for this request, in seconds - """ - if not id: - raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") - return self._post( - path_template("/agent/v1/run/{id}/cancel", id=id), - options=make_request_options( - extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout - ), - cast_to=RunCancelResponse, - ) - - def events( - self, - id: str, - *, - last_event_id: int | Omit = omit, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> Stream[RunEventsResponse]: - """Streams real-time run events over SSE. - - Supports replay using Last-Event-ID. - - Args: - last_event_id: Replay events after this sequence number - - extra_headers: Send extra headers - - extra_query: Add additional query parameters to the request - - extra_body: Add additional JSON properties to the request - - timeout: Override the client-level default timeout for this request, in seconds - """ - if not id: - raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") - extra_headers = {"Accept": "text/event-stream", **(extra_headers or {})} - return self._get( - path_template("/agent/v1/run/{id}/events", id=id), - options=make_request_options( - extra_headers=extra_headers, - extra_query=extra_query, - extra_body=extra_body, - timeout=timeout, - query=maybe_transform({"last_event_id": last_event_id}, run_events_params.RunEventsParams), - ), - cast_to=str, - stream=True, - stream_cls=Stream[RunEventsResponse], - ) - - def exec( - self, - id: str, - *, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> RunExecResponse: - """Starts execution of a queued run. - - The agent runs in a durable workflow — poll - /run/:id/status for progress. - - Args: - extra_headers: Send extra headers - - extra_query: Add additional query parameters to the request - - extra_body: Add additional JSON properties to the request - - timeout: Override the client-level default timeout for this request, in seconds - """ - if not id: - raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") - return self._post( - path_template("/agent/v1/run/{id}/exec", id=id), - options=make_request_options( - extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout - ), - cast_to=RunExecResponse, - ) - - def get_details( - self, - id: str, - *, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> RunGetDetailsResponse: - """ - Full audit trail for a run including output, steps (tool calls, text), and token - usage. - - Args: - extra_headers: Send extra headers - - extra_query: Add additional query parameters to the request - - extra_body: Add additional JSON properties to the request - - timeout: Override the client-level default timeout for this request, in seconds - """ - if not id: - raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") - return self._get( - path_template("/agent/v1/run/{id}/details", id=id), - options=make_request_options( - extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout - ), - cast_to=RunGetDetailsResponse, - ) - - def get_status( - self, - id: str, - *, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> RunGetStatusResponse: - """Lightweight status poll for a run. - - Use /run/:id/details for the full audit - trail. - - Args: - extra_headers: Send extra headers - - extra_query: Add additional query parameters to the request - - extra_body: Add additional JSON properties to the request - - timeout: Override the client-level default timeout for this request, in seconds - """ - if not id: - raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") - return self._get( - path_template("/agent/v1/run/{id}/status", id=id), - options=make_request_options( - extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout - ), - cast_to=RunGetStatusResponse, - ) - - def watch( - self, - id: str, - *, - callback_url: str, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> RunWatchResponse: - """Register a callback URL to receive notifications when the run completes. - - URL - must use https and must not point to a private network. - - Args: - callback_url: HTTPS URL to receive completion callback - - extra_headers: Send extra headers - - extra_query: Add additional query parameters to the request - - extra_body: Add additional JSON properties to the request - - timeout: Override the client-level default timeout for this request, in seconds - """ - if not id: - raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") - return self._post( - path_template("/agent/v1/run/{id}/watch", id=id), - body=maybe_transform({"callback_url": callback_url}, run_watch_params.RunWatchParams), - options=make_request_options( - extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout - ), - cast_to=RunWatchResponse, - ) - - -class AsyncRunResource(AsyncAPIResource): - """ - Create, manage, and execute AI agents with tool access, sandbox environments, and async run workflows - """ - - @cached_property - def with_raw_response(self) -> AsyncRunResourceWithRawResponse: - """ - This property can be used as a prefix for any HTTP method call to return - the raw response object instead of the parsed content. - - For more information, see https://www.github.com/CaseMark/casedev-python#accessing-raw-response-data-eg-headers - """ - return AsyncRunResourceWithRawResponse(self) - - @cached_property - def with_streaming_response(self) -> AsyncRunResourceWithStreamingResponse: - """ - An alternative to `.with_raw_response` that doesn't eagerly read the response body. - - For more information, see https://www.github.com/CaseMark/casedev-python#with_streaming_response - """ - return AsyncRunResourceWithStreamingResponse(self) - - async def create( - self, - *, - agent_id: str, - prompt: str, - callback_url: Optional[str] | Omit = omit, - guidance: Optional[str] | Omit = omit, - model: Optional[str] | Omit = omit, - object_ids: Optional[SequenceNotStr[str]] | Omit = omit, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> RunCreateResponse: - """Creates a run in queued state. - - Call POST /agent/v1/run/:id/exec to start - execution. - - Args: - agent_id: ID of the agent to run - - prompt: Task prompt for the agent - - callback_url: HTTPS callback URL to receive a notification when the run completes. Registered - atomically with the run — eliminates the race condition of calling /watch after - /exec. Additional watchers can still be added via POST /run/:id/watch. - - guidance: Additional guidance for this run - - model: Override the agent default model for this run - - object_ids: Scope this run to specific vault object IDs. The agent will only be able to - access these objects during execution. - - extra_headers: Send extra headers - - extra_query: Add additional query parameters to the request - - extra_body: Add additional JSON properties to the request - - timeout: Override the client-level default timeout for this request, in seconds - """ - return await self._post( - "/agent/v1/run", - body=await async_maybe_transform( - { - "agent_id": agent_id, - "prompt": prompt, - "callback_url": callback_url, - "guidance": guidance, - "model": model, - "object_ids": object_ids, - }, - run_create_params.RunCreateParams, - ), - options=make_request_options( - extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout - ), - cast_to=RunCreateResponse, - ) - - async def list( - self, - *, - agent_id: str | Omit = omit, - cursor: str | Omit = omit, - limit: int | Omit = omit, - status: Literal["queued", "running", "completed", "failed", "cancelled"] | Omit = omit, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> RunListResponse: - """Lists agent runs for the authenticated organization. - - Supports filtering by - agent, status, and cursor-based pagination. - - Args: - agent_id: Filter by agent ID - - cursor: Pagination cursor (run ID from previous page). Returns runs created before this - run. - - limit: Maximum number of runs to return (default 50, max 250) - - status: Filter by run status - - extra_headers: Send extra headers - - extra_query: Add additional query parameters to the request - - extra_body: Add additional JSON properties to the request - - timeout: Override the client-level default timeout for this request, in seconds - """ - return await self._get( - "/agent/v1/run", - options=make_request_options( - extra_headers=extra_headers, - extra_query=extra_query, - extra_body=extra_body, - timeout=timeout, - query=await async_maybe_transform( - { - "agent_id": agent_id, - "cursor": cursor, - "limit": limit, - "status": status, - }, - run_list_params.RunListParams, - ), - ), - cast_to=RunListResponse, - ) - - async def cancel( - self, - id: str, - *, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> RunCancelResponse: - """Cancels a running or queued run. - - Idempotent — cancelling a finished run returns - its current status. - - Args: - extra_headers: Send extra headers - - extra_query: Add additional query parameters to the request - - extra_body: Add additional JSON properties to the request - - timeout: Override the client-level default timeout for this request, in seconds - """ - if not id: - raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") - return await self._post( - path_template("/agent/v1/run/{id}/cancel", id=id), - options=make_request_options( - extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout - ), - cast_to=RunCancelResponse, - ) - - async def events( - self, - id: str, - *, - last_event_id: int | Omit = omit, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> AsyncStream[RunEventsResponse]: - """Streams real-time run events over SSE. - - Supports replay using Last-Event-ID. - - Args: - last_event_id: Replay events after this sequence number - - extra_headers: Send extra headers - - extra_query: Add additional query parameters to the request - - extra_body: Add additional JSON properties to the request - - timeout: Override the client-level default timeout for this request, in seconds - """ - if not id: - raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") - extra_headers = {"Accept": "text/event-stream", **(extra_headers or {})} - return await self._get( - path_template("/agent/v1/run/{id}/events", id=id), - options=make_request_options( - extra_headers=extra_headers, - extra_query=extra_query, - extra_body=extra_body, - timeout=timeout, - query=await async_maybe_transform({"last_event_id": last_event_id}, run_events_params.RunEventsParams), - ), - cast_to=str, - stream=True, - stream_cls=AsyncStream[RunEventsResponse], - ) - - async def exec( - self, - id: str, - *, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> RunExecResponse: - """Starts execution of a queued run. - - The agent runs in a durable workflow — poll - /run/:id/status for progress. - - Args: - extra_headers: Send extra headers - - extra_query: Add additional query parameters to the request - - extra_body: Add additional JSON properties to the request - - timeout: Override the client-level default timeout for this request, in seconds - """ - if not id: - raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") - return await self._post( - path_template("/agent/v1/run/{id}/exec", id=id), - options=make_request_options( - extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout - ), - cast_to=RunExecResponse, - ) - - async def get_details( - self, - id: str, - *, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> RunGetDetailsResponse: - """ - Full audit trail for a run including output, steps (tool calls, text), and token - usage. - - Args: - extra_headers: Send extra headers - - extra_query: Add additional query parameters to the request - - extra_body: Add additional JSON properties to the request - - timeout: Override the client-level default timeout for this request, in seconds - """ - if not id: - raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") - return await self._get( - path_template("/agent/v1/run/{id}/details", id=id), - options=make_request_options( - extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout - ), - cast_to=RunGetDetailsResponse, - ) - - async def get_status( - self, - id: str, - *, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> RunGetStatusResponse: - """Lightweight status poll for a run. - - Use /run/:id/details for the full audit - trail. - - Args: - extra_headers: Send extra headers - - extra_query: Add additional query parameters to the request - - extra_body: Add additional JSON properties to the request - - timeout: Override the client-level default timeout for this request, in seconds - """ - if not id: - raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") - return await self._get( - path_template("/agent/v1/run/{id}/status", id=id), - options=make_request_options( - extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout - ), - cast_to=RunGetStatusResponse, - ) - - async def watch( - self, - id: str, - *, - callback_url: str, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> RunWatchResponse: - """Register a callback URL to receive notifications when the run completes. - - URL - must use https and must not point to a private network. - - Args: - callback_url: HTTPS URL to receive completion callback - - extra_headers: Send extra headers - - extra_query: Add additional query parameters to the request - - extra_body: Add additional JSON properties to the request - - timeout: Override the client-level default timeout for this request, in seconds - """ - if not id: - raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") - return await self._post( - path_template("/agent/v1/run/{id}/watch", id=id), - body=await async_maybe_transform({"callback_url": callback_url}, run_watch_params.RunWatchParams), - options=make_request_options( - extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout - ), - cast_to=RunWatchResponse, - ) - - -class RunResourceWithRawResponse: - def __init__(self, run: RunResource) -> None: - self._run = run - - self.create = to_raw_response_wrapper( - run.create, - ) - self.list = to_raw_response_wrapper( - run.list, - ) - self.cancel = to_raw_response_wrapper( - run.cancel, - ) - self.events = to_raw_response_wrapper( - run.events, - ) - self.exec = to_raw_response_wrapper( - run.exec, - ) - self.get_details = to_raw_response_wrapper( - run.get_details, - ) - self.get_status = to_raw_response_wrapper( - run.get_status, - ) - self.watch = to_raw_response_wrapper( - run.watch, - ) - - -class AsyncRunResourceWithRawResponse: - def __init__(self, run: AsyncRunResource) -> None: - self._run = run - - self.create = async_to_raw_response_wrapper( - run.create, - ) - self.list = async_to_raw_response_wrapper( - run.list, - ) - self.cancel = async_to_raw_response_wrapper( - run.cancel, - ) - self.events = async_to_raw_response_wrapper( - run.events, - ) - self.exec = async_to_raw_response_wrapper( - run.exec, - ) - self.get_details = async_to_raw_response_wrapper( - run.get_details, - ) - self.get_status = async_to_raw_response_wrapper( - run.get_status, - ) - self.watch = async_to_raw_response_wrapper( - run.watch, - ) - - -class RunResourceWithStreamingResponse: - def __init__(self, run: RunResource) -> None: - self._run = run - - self.create = to_streamed_response_wrapper( - run.create, - ) - self.list = to_streamed_response_wrapper( - run.list, - ) - self.cancel = to_streamed_response_wrapper( - run.cancel, - ) - self.events = to_streamed_response_wrapper( - run.events, - ) - self.exec = to_streamed_response_wrapper( - run.exec, - ) - self.get_details = to_streamed_response_wrapper( - run.get_details, - ) - self.get_status = to_streamed_response_wrapper( - run.get_status, - ) - self.watch = to_streamed_response_wrapper( - run.watch, - ) - - -class AsyncRunResourceWithStreamingResponse: - def __init__(self, run: AsyncRunResource) -> None: - self._run = run - - self.create = async_to_streamed_response_wrapper( - run.create, - ) - self.list = async_to_streamed_response_wrapper( - run.list, - ) - self.cancel = async_to_streamed_response_wrapper( - run.cancel, - ) - self.events = async_to_streamed_response_wrapper( - run.events, - ) - self.exec = async_to_streamed_response_wrapper( - run.exec, - ) - self.get_details = async_to_streamed_response_wrapper( - run.get_details, - ) - self.get_status = async_to_streamed_response_wrapper( - run.get_status, - ) - self.watch = async_to_streamed_response_wrapper( - run.watch, - ) diff --git a/src/casedev/resources/agent/v1/v1.py b/src/casedev/resources/agent/v1/v1.py deleted file mode 100644 index 5d84bf0b..00000000 --- a/src/casedev/resources/agent/v1/v1.py +++ /dev/null @@ -1,220 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from __future__ import annotations - -from .run import ( - RunResource, - AsyncRunResource, - RunResourceWithRawResponse, - AsyncRunResourceWithRawResponse, - RunResourceWithStreamingResponse, - AsyncRunResourceWithStreamingResponse, -) -from .agents import ( - AgentsResource, - AsyncAgentsResource, - AgentsResourceWithRawResponse, - AsyncAgentsResourceWithRawResponse, - AgentsResourceWithStreamingResponse, - AsyncAgentsResourceWithStreamingResponse, -) -from .execute import ( - ExecuteResource, - AsyncExecuteResource, - ExecuteResourceWithRawResponse, - AsyncExecuteResourceWithRawResponse, - ExecuteResourceWithStreamingResponse, - AsyncExecuteResourceWithStreamingResponse, -) -from ...._compat import cached_property -from ...._resource import SyncAPIResource, AsyncAPIResource - -__all__ = ["V1Resource", "AsyncV1Resource"] - - -class V1Resource(SyncAPIResource): - @cached_property - def agents(self) -> AgentsResource: - """ - Create, manage, and execute AI agents with tool access, sandbox environments, and async run workflows - """ - return AgentsResource(self._client) - - @cached_property - def run(self) -> RunResource: - """ - Create, manage, and execute AI agents with tool access, sandbox environments, and async run workflows - """ - return RunResource(self._client) - - @cached_property - def execute(self) -> ExecuteResource: - """ - Create, manage, and execute AI agents with tool access, sandbox environments, and async run workflows - """ - return ExecuteResource(self._client) - - @cached_property - def with_raw_response(self) -> V1ResourceWithRawResponse: - """ - This property can be used as a prefix for any HTTP method call to return - the raw response object instead of the parsed content. - - For more information, see https://www.github.com/CaseMark/casedev-python#accessing-raw-response-data-eg-headers - """ - return V1ResourceWithRawResponse(self) - - @cached_property - def with_streaming_response(self) -> V1ResourceWithStreamingResponse: - """ - An alternative to `.with_raw_response` that doesn't eagerly read the response body. - - For more information, see https://www.github.com/CaseMark/casedev-python#with_streaming_response - """ - return V1ResourceWithStreamingResponse(self) - - -class AsyncV1Resource(AsyncAPIResource): - @cached_property - def agents(self) -> AsyncAgentsResource: - """ - Create, manage, and execute AI agents with tool access, sandbox environments, and async run workflows - """ - return AsyncAgentsResource(self._client) - - @cached_property - def run(self) -> AsyncRunResource: - """ - Create, manage, and execute AI agents with tool access, sandbox environments, and async run workflows - """ - return AsyncRunResource(self._client) - - @cached_property - def execute(self) -> AsyncExecuteResource: - """ - Create, manage, and execute AI agents with tool access, sandbox environments, and async run workflows - """ - return AsyncExecuteResource(self._client) - - @cached_property - def with_raw_response(self) -> AsyncV1ResourceWithRawResponse: - """ - This property can be used as a prefix for any HTTP method call to return - the raw response object instead of the parsed content. - - For more information, see https://www.github.com/CaseMark/casedev-python#accessing-raw-response-data-eg-headers - """ - return AsyncV1ResourceWithRawResponse(self) - - @cached_property - def with_streaming_response(self) -> AsyncV1ResourceWithStreamingResponse: - """ - An alternative to `.with_raw_response` that doesn't eagerly read the response body. - - For more information, see https://www.github.com/CaseMark/casedev-python#with_streaming_response - """ - return AsyncV1ResourceWithStreamingResponse(self) - - -class V1ResourceWithRawResponse: - def __init__(self, v1: V1Resource) -> None: - self._v1 = v1 - - @cached_property - def agents(self) -> AgentsResourceWithRawResponse: - """ - Create, manage, and execute AI agents with tool access, sandbox environments, and async run workflows - """ - return AgentsResourceWithRawResponse(self._v1.agents) - - @cached_property - def run(self) -> RunResourceWithRawResponse: - """ - Create, manage, and execute AI agents with tool access, sandbox environments, and async run workflows - """ - return RunResourceWithRawResponse(self._v1.run) - - @cached_property - def execute(self) -> ExecuteResourceWithRawResponse: - """ - Create, manage, and execute AI agents with tool access, sandbox environments, and async run workflows - """ - return ExecuteResourceWithRawResponse(self._v1.execute) - - -class AsyncV1ResourceWithRawResponse: - def __init__(self, v1: AsyncV1Resource) -> None: - self._v1 = v1 - - @cached_property - def agents(self) -> AsyncAgentsResourceWithRawResponse: - """ - Create, manage, and execute AI agents with tool access, sandbox environments, and async run workflows - """ - return AsyncAgentsResourceWithRawResponse(self._v1.agents) - - @cached_property - def run(self) -> AsyncRunResourceWithRawResponse: - """ - Create, manage, and execute AI agents with tool access, sandbox environments, and async run workflows - """ - return AsyncRunResourceWithRawResponse(self._v1.run) - - @cached_property - def execute(self) -> AsyncExecuteResourceWithRawResponse: - """ - Create, manage, and execute AI agents with tool access, sandbox environments, and async run workflows - """ - return AsyncExecuteResourceWithRawResponse(self._v1.execute) - - -class V1ResourceWithStreamingResponse: - def __init__(self, v1: V1Resource) -> None: - self._v1 = v1 - - @cached_property - def agents(self) -> AgentsResourceWithStreamingResponse: - """ - Create, manage, and execute AI agents with tool access, sandbox environments, and async run workflows - """ - return AgentsResourceWithStreamingResponse(self._v1.agents) - - @cached_property - def run(self) -> RunResourceWithStreamingResponse: - """ - Create, manage, and execute AI agents with tool access, sandbox environments, and async run workflows - """ - return RunResourceWithStreamingResponse(self._v1.run) - - @cached_property - def execute(self) -> ExecuteResourceWithStreamingResponse: - """ - Create, manage, and execute AI agents with tool access, sandbox environments, and async run workflows - """ - return ExecuteResourceWithStreamingResponse(self._v1.execute) - - -class AsyncV1ResourceWithStreamingResponse: - def __init__(self, v1: AsyncV1Resource) -> None: - self._v1 = v1 - - @cached_property - def agents(self) -> AsyncAgentsResourceWithStreamingResponse: - """ - Create, manage, and execute AI agents with tool access, sandbox environments, and async run workflows - """ - return AsyncAgentsResourceWithStreamingResponse(self._v1.agents) - - @cached_property - def run(self) -> AsyncRunResourceWithStreamingResponse: - """ - Create, manage, and execute AI agents with tool access, sandbox environments, and async run workflows - """ - return AsyncRunResourceWithStreamingResponse(self._v1.run) - - @cached_property - def execute(self) -> AsyncExecuteResourceWithStreamingResponse: - """ - Create, manage, and execute AI agents with tool access, sandbox environments, and async run workflows - """ - return AsyncExecuteResourceWithStreamingResponse(self._v1.execute) diff --git a/src/casedev/resources/agent/__init__.py b/src/casedev/resources/connectors/__init__.py similarity index 50% rename from src/casedev/resources/agent/__init__.py rename to src/casedev/resources/connectors/__init__.py index 1c506f86..a0e9329f 100644 --- a/src/casedev/resources/agent/__init__.py +++ b/src/casedev/resources/connectors/__init__.py @@ -8,13 +8,13 @@ V1ResourceWithStreamingResponse, AsyncV1ResourceWithStreamingResponse, ) -from .agent import ( - AgentResource, - AsyncAgentResource, - AgentResourceWithRawResponse, - AsyncAgentResourceWithRawResponse, - AgentResourceWithStreamingResponse, - AsyncAgentResourceWithStreamingResponse, +from .connectors import ( + ConnectorsResource, + AsyncConnectorsResource, + ConnectorsResourceWithRawResponse, + AsyncConnectorsResourceWithRawResponse, + ConnectorsResourceWithStreamingResponse, + AsyncConnectorsResourceWithStreamingResponse, ) __all__ = [ @@ -24,10 +24,10 @@ "AsyncV1ResourceWithRawResponse", "V1ResourceWithStreamingResponse", "AsyncV1ResourceWithStreamingResponse", - "AgentResource", - "AsyncAgentResource", - "AgentResourceWithRawResponse", - "AsyncAgentResourceWithRawResponse", - "AgentResourceWithStreamingResponse", - "AsyncAgentResourceWithStreamingResponse", + "ConnectorsResource", + "AsyncConnectorsResource", + "ConnectorsResourceWithRawResponse", + "AsyncConnectorsResourceWithRawResponse", + "ConnectorsResourceWithStreamingResponse", + "AsyncConnectorsResourceWithStreamingResponse", ] diff --git a/src/casedev/resources/agent/agent.py b/src/casedev/resources/connectors/connectors.py similarity index 50% rename from src/casedev/resources/agent/agent.py rename to src/casedev/resources/connectors/connectors.py index 4da17b0d..087107f9 100644 --- a/src/casedev/resources/agent/agent.py +++ b/src/casedev/resources/connectors/connectors.py @@ -13,90 +13,96 @@ from ..._compat import cached_property from ..._resource import SyncAPIResource, AsyncAPIResource -__all__ = ["AgentResource", "AsyncAgentResource"] +__all__ = ["ConnectorsResource", "AsyncConnectorsResource"] -class AgentResource(SyncAPIResource): +class ConnectorsResource(SyncAPIResource): @cached_property def v1(self) -> V1Resource: + """Import and export between provider folders (Google Drive) and vaults""" return V1Resource(self._client) @cached_property - def with_raw_response(self) -> AgentResourceWithRawResponse: + def with_raw_response(self) -> ConnectorsResourceWithRawResponse: """ This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. For more information, see https://www.github.com/CaseMark/casedev-python#accessing-raw-response-data-eg-headers """ - return AgentResourceWithRawResponse(self) + return ConnectorsResourceWithRawResponse(self) @cached_property - def with_streaming_response(self) -> AgentResourceWithStreamingResponse: + def with_streaming_response(self) -> ConnectorsResourceWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. For more information, see https://www.github.com/CaseMark/casedev-python#with_streaming_response """ - return AgentResourceWithStreamingResponse(self) + return ConnectorsResourceWithStreamingResponse(self) -class AsyncAgentResource(AsyncAPIResource): +class AsyncConnectorsResource(AsyncAPIResource): @cached_property def v1(self) -> AsyncV1Resource: + """Import and export between provider folders (Google Drive) and vaults""" return AsyncV1Resource(self._client) @cached_property - def with_raw_response(self) -> AsyncAgentResourceWithRawResponse: + def with_raw_response(self) -> AsyncConnectorsResourceWithRawResponse: """ This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. For more information, see https://www.github.com/CaseMark/casedev-python#accessing-raw-response-data-eg-headers """ - return AsyncAgentResourceWithRawResponse(self) + return AsyncConnectorsResourceWithRawResponse(self) @cached_property - def with_streaming_response(self) -> AsyncAgentResourceWithStreamingResponse: + def with_streaming_response(self) -> AsyncConnectorsResourceWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. For more information, see https://www.github.com/CaseMark/casedev-python#with_streaming_response """ - return AsyncAgentResourceWithStreamingResponse(self) + return AsyncConnectorsResourceWithStreamingResponse(self) -class AgentResourceWithRawResponse: - def __init__(self, agent: AgentResource) -> None: - self._agent = agent +class ConnectorsResourceWithRawResponse: + def __init__(self, connectors: ConnectorsResource) -> None: + self._connectors = connectors @cached_property def v1(self) -> V1ResourceWithRawResponse: - return V1ResourceWithRawResponse(self._agent.v1) + """Import and export between provider folders (Google Drive) and vaults""" + return V1ResourceWithRawResponse(self._connectors.v1) -class AsyncAgentResourceWithRawResponse: - def __init__(self, agent: AsyncAgentResource) -> None: - self._agent = agent +class AsyncConnectorsResourceWithRawResponse: + def __init__(self, connectors: AsyncConnectorsResource) -> None: + self._connectors = connectors @cached_property def v1(self) -> AsyncV1ResourceWithRawResponse: - return AsyncV1ResourceWithRawResponse(self._agent.v1) + """Import and export between provider folders (Google Drive) and vaults""" + return AsyncV1ResourceWithRawResponse(self._connectors.v1) -class AgentResourceWithStreamingResponse: - def __init__(self, agent: AgentResource) -> None: - self._agent = agent +class ConnectorsResourceWithStreamingResponse: + def __init__(self, connectors: ConnectorsResource) -> None: + self._connectors = connectors @cached_property def v1(self) -> V1ResourceWithStreamingResponse: - return V1ResourceWithStreamingResponse(self._agent.v1) + """Import and export between provider folders (Google Drive) and vaults""" + return V1ResourceWithStreamingResponse(self._connectors.v1) -class AsyncAgentResourceWithStreamingResponse: - def __init__(self, agent: AsyncAgentResource) -> None: - self._agent = agent +class AsyncConnectorsResourceWithStreamingResponse: + def __init__(self, connectors: AsyncConnectorsResource) -> None: + self._connectors = connectors @cached_property def v1(self) -> AsyncV1ResourceWithStreamingResponse: - return AsyncV1ResourceWithStreamingResponse(self._agent.v1) + """Import and export between provider folders (Google Drive) and vaults""" + return AsyncV1ResourceWithStreamingResponse(self._connectors.v1) diff --git a/src/casedev/resources/connectors/v1/__init__.py b/src/casedev/resources/connectors/v1/__init__.py new file mode 100644 index 00000000..ea1a7d08 --- /dev/null +++ b/src/casedev/resources/connectors/v1/__init__.py @@ -0,0 +1,61 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from .v1 import ( + V1Resource, + AsyncV1Resource, + V1ResourceWithRawResponse, + AsyncV1ResourceWithRawResponse, + V1ResourceWithStreamingResponse, + AsyncV1ResourceWithStreamingResponse, +) +from .links import ( + LinksResource, + AsyncLinksResource, + LinksResourceWithRawResponse, + AsyncLinksResourceWithRawResponse, + LinksResourceWithStreamingResponse, + AsyncLinksResourceWithStreamingResponse, +) +from .connections import ( + ConnectionsResource, + AsyncConnectionsResource, + ConnectionsResourceWithRawResponse, + AsyncConnectionsResourceWithRawResponse, + ConnectionsResourceWithStreamingResponse, + AsyncConnectionsResourceWithStreamingResponse, +) +from .installations import ( + InstallationsResource, + AsyncInstallationsResource, + InstallationsResourceWithRawResponse, + AsyncInstallationsResourceWithRawResponse, + InstallationsResourceWithStreamingResponse, + AsyncInstallationsResourceWithStreamingResponse, +) + +__all__ = [ + "InstallationsResource", + "AsyncInstallationsResource", + "InstallationsResourceWithRawResponse", + "AsyncInstallationsResourceWithRawResponse", + "InstallationsResourceWithStreamingResponse", + "AsyncInstallationsResourceWithStreamingResponse", + "ConnectionsResource", + "AsyncConnectionsResource", + "ConnectionsResourceWithRawResponse", + "AsyncConnectionsResourceWithRawResponse", + "ConnectionsResourceWithStreamingResponse", + "AsyncConnectionsResourceWithStreamingResponse", + "LinksResource", + "AsyncLinksResource", + "LinksResourceWithRawResponse", + "AsyncLinksResourceWithRawResponse", + "LinksResourceWithStreamingResponse", + "AsyncLinksResourceWithStreamingResponse", + "V1Resource", + "AsyncV1Resource", + "V1ResourceWithRawResponse", + "AsyncV1ResourceWithRawResponse", + "V1ResourceWithStreamingResponse", + "AsyncV1ResourceWithStreamingResponse", +] diff --git a/src/casedev/resources/agent/v1/agents.py b/src/casedev/resources/connectors/v1/connections.py similarity index 51% rename from src/casedev/resources/agent/v1/agents.py rename to src/casedev/resources/connectors/v1/connections.py index b2c64567..5799a5ff 100644 --- a/src/casedev/resources/agent/v1/agents.py +++ b/src/casedev/resources/connectors/v1/connections.py @@ -2,11 +2,11 @@ from __future__ import annotations -from typing import Optional +from typing_extensions import Literal import httpx -from ...._types import Body, Omit, Query, Headers, NotGiven, SequenceNotStr, omit, not_given +from ...._types import Body, Omit, Query, Headers, NoneType, NotGiven, omit, not_given from ...._utils import path_template, maybe_transform, async_maybe_transform from ...._compat import cached_property from ...._resource import SyncAPIResource, AsyncAPIResource @@ -17,85 +17,63 @@ async_to_streamed_response_wrapper, ) from ...._base_client import make_request_options -from ....types.agent.v1 import agent_list_params, agent_create_params, agent_update_params -from ....types.agent.v1.agent_list_response import AgentListResponse -from ....types.agent.v1.agent_create_response import AgentCreateResponse -from ....types.agent.v1.agent_delete_response import AgentDeleteResponse -from ....types.agent.v1.agent_update_response import AgentUpdateResponse -from ....types.agent.v1.agent_retrieve_response import AgentRetrieveResponse +from ....types.connectors.v1 import ( + connection_list_params, + connection_browse_params, + connection_create_params, + connection_delete_params, +) +from ....types.connectors.v1.connection_list_response import ConnectionListResponse +from ....types.connectors.v1.connection_browse_response import ConnectionBrowseResponse +from ....types.connectors.v1.connection_create_response import ConnectionCreateResponse -__all__ = ["AgentsResource", "AsyncAgentsResource"] +__all__ = ["ConnectionsResource", "AsyncConnectionsResource"] -class AgentsResource(SyncAPIResource): - """ - Create, manage, and execute AI agents with tool access, sandbox environments, and async run workflows - """ +class ConnectionsResource(SyncAPIResource): + """Import and export between provider folders (Google Drive) and vaults""" @cached_property - def with_raw_response(self) -> AgentsResourceWithRawResponse: + def with_raw_response(self) -> ConnectionsResourceWithRawResponse: """ This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. For more information, see https://www.github.com/CaseMark/casedev-python#accessing-raw-response-data-eg-headers """ - return AgentsResourceWithRawResponse(self) + return ConnectionsResourceWithRawResponse(self) @cached_property - def with_streaming_response(self) -> AgentsResourceWithStreamingResponse: + def with_streaming_response(self) -> ConnectionsResourceWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. For more information, see https://www.github.com/CaseMark/casedev-python#with_streaming_response """ - return AgentsResourceWithStreamingResponse(self) + return ConnectionsResourceWithStreamingResponse(self) def create( self, *, - instructions: str, - name: str, - description: str | Omit = omit, - disabled_tools: Optional[SequenceNotStr[str]] | Omit = omit, - enabled_tools: Optional[SequenceNotStr[str]] | Omit = omit, - model: str | Omit = omit, - sandbox: Optional[agent_create_params.Sandbox] | Omit = omit, - vault_groups: Optional[SequenceNotStr[str]] | Omit = omit, - vault_ids: Optional[SequenceNotStr[str]] | Omit = omit, + provider: Literal["clio", "gdrive", "microsoft"], + return_url: str, + scope_tier: Literal["clio.us", "drive", "microsoft.read"] | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> AgentCreateResponse: - """Creates a new agent definition with a scoped API key. - - The agent can then be used - to create and execute runs. + ) -> ConnectionCreateResponse: + """ + Create a pending provider connection and return a one-time connect_url for the + hosted OAuth flow. The user completes provider consent at connect_url and is + redirected to return_url with ?connection_id=. Args: - instructions: System instructions that define agent behavior - - name: Display name for the agent - - description: Optional description of the agent - - disabled_tools: Denylist of tools the agent cannot use. Mutually exclusive with enabledTools — - set one or the other, not both. - - enabled_tools: Allowlist of tools the agent can use. Mutually exclusive with disabledTools — - set one or the other, not both. - - model: LLM model identifier (e.g. anthropic/claude-sonnet-4.6). Defaults to - anthropic/claude-sonnet-4.6 - - sandbox: Custom sandbox configuration (cpu, memoryMiB) - - vault_groups: Restrict agent to vaults within specific vault group IDs + return_url: HTTPS URL the user is sent back to after consent. - vault_ids: Restrict agent to specific vault IDs + scope_tier: Provider-specific OAuth permission tier. Omit to use the provider's default. extra_headers: Send extra headers @@ -106,25 +84,19 @@ def create( timeout: Override the client-level default timeout for this request, in seconds """ return self._post( - "/agent/v1/agents", + "/connectors/v1/connections", body=maybe_transform( { - "instructions": instructions, - "name": name, - "description": description, - "disabled_tools": disabled_tools, - "enabled_tools": enabled_tools, - "model": model, - "sandbox": sandbox, - "vault_groups": vault_groups, - "vault_ids": vault_ids, + "provider": provider, + "return_url": return_url, + "scope_tier": scope_tier, }, - agent_create_params.AgentCreateParams, + connection_create_params.ConnectionCreateParams, ), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), - cast_to=AgentCreateResponse, + cast_to=ConnectionCreateResponse, ) def retrieve( @@ -137,9 +109,9 @@ def retrieve( extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> AgentRetrieveResponse: + ) -> None: """ - Retrieves a single agent definition by ID. + Retrieve one provider connection, including account identity and health. Args: extra_headers: Send extra headers @@ -152,59 +124,31 @@ def retrieve( """ if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") + extra_headers = {"Accept": "*/*", **(extra_headers or {})} return self._get( - path_template("/agent/v1/agents/{id}", id=id), + path_template("/connectors/v1/connections/{id}", id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), - cast_to=AgentRetrieveResponse, + cast_to=NoneType, ) - def update( + def list( self, - id: str, *, - description: Optional[str] | Omit = omit, - disabled_tools: Optional[SequenceNotStr[str]] | Omit = omit, - enabled_tools: Optional[SequenceNotStr[str]] | Omit = omit, - instructions: str | Omit = omit, - model: str | Omit = omit, - name: str | Omit = omit, - sandbox: Optional[object] | Omit = omit, - vault_groups: Optional[SequenceNotStr[str]] | Omit = omit, - vault_ids: Optional[SequenceNotStr[str]] | Omit = omit, + provider: str | Omit = omit, + status: Literal["pending", "healthy", "reauth_required", "revoked", "throttled"] | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> AgentUpdateResponse: - """Updates an agent definition. - - Only provided fields are changed. + ) -> ConnectionListResponse: + """ + List provider connections for the organization, with health status. Args: - description: Updated agent description. Pass null to clear if supported by the client. - - disabled_tools: Denylist of tools the agent cannot use. Mutually exclusive with enabledTools — - set one or the other, not both. Pass null to clear. - - enabled_tools: Allowlist of tools the agent can use. Mutually exclusive with disabledTools — - set one or the other, not both. Pass null to clear. - - instructions: Updated system instructions that guide agent behavior - - model: Model identifier the agent should use for future runs - - name: Updated agent display name - - sandbox: Sandbox configuration override for future agent runs. Pass null to clear. - - vault_groups: Vault group IDs the agent can access. Pass null to clear. - - vault_ids: Vault IDs the agent can access directly. Pass null to clear. - extra_headers: Send extra headers extra_query: Add additional query parameters to the request @@ -213,51 +157,41 @@ def update( timeout: Override the client-level default timeout for this request, in seconds """ - if not id: - raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") - return self._patch( - path_template("/agent/v1/agents/{id}", id=id), - body=maybe_transform( - { - "description": description, - "disabled_tools": disabled_tools, - "enabled_tools": enabled_tools, - "instructions": instructions, - "model": model, - "name": name, - "sandbox": sandbox, - "vault_groups": vault_groups, - "vault_ids": vault_ids, - }, - agent_update_params.AgentUpdateParams, - ), + return self._get( + "/connectors/v1/connections", options=make_request_options( - extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + query=maybe_transform( + { + "provider": provider, + "status": status, + }, + connection_list_params.ConnectionListParams, + ), ), - cast_to=AgentUpdateResponse, + cast_to=ConnectionListResponse, ) - def list( + def delete( self, + id: str, *, - cursor: str | Omit = omit, - limit: int | Omit = omit, + purge: bool | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> AgentListResponse: + ) -> None: """ - Lists all active agents for the authenticated organization. + Unlink a provider account: revoke tokens at the provider and delete them. + purge=true additionally deletes the vault documents its import links brought in. Args: - cursor: Pagination cursor (agent ID from previous page). Returns agents created before - this agent. - - limit: Maximum number of agents to return (default 50, max 250) - extra_headers: Send extra headers extra_query: Add additional query parameters to the request @@ -266,39 +200,54 @@ def list( timeout: Override the client-level default timeout for this request, in seconds """ - return self._get( - "/agent/v1/agents", + if not id: + raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") + extra_headers = {"Accept": "*/*", **(extra_headers or {})} + return self._delete( + path_template("/connectors/v1/connections/{id}", id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout, - query=maybe_transform( - { - "cursor": cursor, - "limit": limit, - }, - agent_list_params.AgentListParams, - ), + query=maybe_transform({"purge": purge}, connection_delete_params.ConnectionDeleteParams), ), - cast_to=AgentListResponse, + cast_to=NoneType, ) - def delete( + def browse( self, id: str, *, + container: str | Omit = omit, + cursor: str | Omit = omit, + page_size: int | Omit = omit, + parent: str | Omit = omit, + query: str | Omit = omit, + site: str | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> AgentDeleteResponse: - """ - Soft-deletes an agent and revokes its scoped API key. + ) -> ConnectionBrowseResponse: + """Browse the provider one level at a time. + + Without a site, container, or parent, + returns top-level resources. Pass the stable browse_ref fields returned by one + response to navigate into the next level. Returns 403 + provider_scope_insufficient when the connection scope cannot browse server-side. Args: + container: Container id to list, or the container containing parent + + parent: Folder id to list + + query: Optional provider-supported search text + + site: Site id to list + extra_headers: Send extra headers extra_query: Add additional query parameters to the request @@ -309,84 +258,73 @@ def delete( """ if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") - return self._delete( - path_template("/agent/v1/agents/{id}", id=id), + return self._get( + path_template("/connectors/v1/connections/{id}/browse", id=id), options=make_request_options( - extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + query=maybe_transform( + { + "container": container, + "cursor": cursor, + "page_size": page_size, + "parent": parent, + "query": query, + "site": site, + }, + connection_browse_params.ConnectionBrowseParams, + ), ), - cast_to=AgentDeleteResponse, + cast_to=ConnectionBrowseResponse, ) -class AsyncAgentsResource(AsyncAPIResource): - """ - Create, manage, and execute AI agents with tool access, sandbox environments, and async run workflows - """ +class AsyncConnectionsResource(AsyncAPIResource): + """Import and export between provider folders (Google Drive) and vaults""" @cached_property - def with_raw_response(self) -> AsyncAgentsResourceWithRawResponse: + def with_raw_response(self) -> AsyncConnectionsResourceWithRawResponse: """ This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. For more information, see https://www.github.com/CaseMark/casedev-python#accessing-raw-response-data-eg-headers """ - return AsyncAgentsResourceWithRawResponse(self) + return AsyncConnectionsResourceWithRawResponse(self) @cached_property - def with_streaming_response(self) -> AsyncAgentsResourceWithStreamingResponse: + def with_streaming_response(self) -> AsyncConnectionsResourceWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. For more information, see https://www.github.com/CaseMark/casedev-python#with_streaming_response """ - return AsyncAgentsResourceWithStreamingResponse(self) + return AsyncConnectionsResourceWithStreamingResponse(self) async def create( self, *, - instructions: str, - name: str, - description: str | Omit = omit, - disabled_tools: Optional[SequenceNotStr[str]] | Omit = omit, - enabled_tools: Optional[SequenceNotStr[str]] | Omit = omit, - model: str | Omit = omit, - sandbox: Optional[agent_create_params.Sandbox] | Omit = omit, - vault_groups: Optional[SequenceNotStr[str]] | Omit = omit, - vault_ids: Optional[SequenceNotStr[str]] | Omit = omit, + provider: Literal["clio", "gdrive", "microsoft"], + return_url: str, + scope_tier: Literal["clio.us", "drive", "microsoft.read"] | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> AgentCreateResponse: - """Creates a new agent definition with a scoped API key. - - The agent can then be used - to create and execute runs. + ) -> ConnectionCreateResponse: + """ + Create a pending provider connection and return a one-time connect_url for the + hosted OAuth flow. The user completes provider consent at connect_url and is + redirected to return_url with ?connection_id=. Args: - instructions: System instructions that define agent behavior - - name: Display name for the agent - - description: Optional description of the agent + return_url: HTTPS URL the user is sent back to after consent. - disabled_tools: Denylist of tools the agent cannot use. Mutually exclusive with enabledTools — - set one or the other, not both. - - enabled_tools: Allowlist of tools the agent can use. Mutually exclusive with disabledTools — - set one or the other, not both. - - model: LLM model identifier (e.g. anthropic/claude-sonnet-4.6). Defaults to - anthropic/claude-sonnet-4.6 - - sandbox: Custom sandbox configuration (cpu, memoryMiB) - - vault_groups: Restrict agent to vaults within specific vault group IDs - - vault_ids: Restrict agent to specific vault IDs + scope_tier: Provider-specific OAuth permission tier. Omit to use the provider's default. extra_headers: Send extra headers @@ -397,25 +335,19 @@ async def create( timeout: Override the client-level default timeout for this request, in seconds """ return await self._post( - "/agent/v1/agents", + "/connectors/v1/connections", body=await async_maybe_transform( { - "instructions": instructions, - "name": name, - "description": description, - "disabled_tools": disabled_tools, - "enabled_tools": enabled_tools, - "model": model, - "sandbox": sandbox, - "vault_groups": vault_groups, - "vault_ids": vault_ids, + "provider": provider, + "return_url": return_url, + "scope_tier": scope_tier, }, - agent_create_params.AgentCreateParams, + connection_create_params.ConnectionCreateParams, ), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), - cast_to=AgentCreateResponse, + cast_to=ConnectionCreateResponse, ) async def retrieve( @@ -428,9 +360,9 @@ async def retrieve( extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> AgentRetrieveResponse: + ) -> None: """ - Retrieves a single agent definition by ID. + Retrieve one provider connection, including account identity and health. Args: extra_headers: Send extra headers @@ -443,59 +375,31 @@ async def retrieve( """ if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") + extra_headers = {"Accept": "*/*", **(extra_headers or {})} return await self._get( - path_template("/agent/v1/agents/{id}", id=id), + path_template("/connectors/v1/connections/{id}", id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), - cast_to=AgentRetrieveResponse, + cast_to=NoneType, ) - async def update( + async def list( self, - id: str, *, - description: Optional[str] | Omit = omit, - disabled_tools: Optional[SequenceNotStr[str]] | Omit = omit, - enabled_tools: Optional[SequenceNotStr[str]] | Omit = omit, - instructions: str | Omit = omit, - model: str | Omit = omit, - name: str | Omit = omit, - sandbox: Optional[object] | Omit = omit, - vault_groups: Optional[SequenceNotStr[str]] | Omit = omit, - vault_ids: Optional[SequenceNotStr[str]] | Omit = omit, + provider: str | Omit = omit, + status: Literal["pending", "healthy", "reauth_required", "revoked", "throttled"] | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> AgentUpdateResponse: - """Updates an agent definition. - - Only provided fields are changed. + ) -> ConnectionListResponse: + """ + List provider connections for the organization, with health status. Args: - description: Updated agent description. Pass null to clear if supported by the client. - - disabled_tools: Denylist of tools the agent cannot use. Mutually exclusive with enabledTools — - set one or the other, not both. Pass null to clear. - - enabled_tools: Allowlist of tools the agent can use. Mutually exclusive with disabledTools — - set one or the other, not both. Pass null to clear. - - instructions: Updated system instructions that guide agent behavior - - model: Model identifier the agent should use for future runs - - name: Updated agent display name - - sandbox: Sandbox configuration override for future agent runs. Pass null to clear. - - vault_groups: Vault group IDs the agent can access. Pass null to clear. - - vault_ids: Vault IDs the agent can access directly. Pass null to clear. - extra_headers: Send extra headers extra_query: Add additional query parameters to the request @@ -504,51 +408,41 @@ async def update( timeout: Override the client-level default timeout for this request, in seconds """ - if not id: - raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") - return await self._patch( - path_template("/agent/v1/agents/{id}", id=id), - body=await async_maybe_transform( - { - "description": description, - "disabled_tools": disabled_tools, - "enabled_tools": enabled_tools, - "instructions": instructions, - "model": model, - "name": name, - "sandbox": sandbox, - "vault_groups": vault_groups, - "vault_ids": vault_ids, - }, - agent_update_params.AgentUpdateParams, - ), + return await self._get( + "/connectors/v1/connections", options=make_request_options( - extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + query=await async_maybe_transform( + { + "provider": provider, + "status": status, + }, + connection_list_params.ConnectionListParams, + ), ), - cast_to=AgentUpdateResponse, + cast_to=ConnectionListResponse, ) - async def list( + async def delete( self, + id: str, *, - cursor: str | Omit = omit, - limit: int | Omit = omit, + purge: bool | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> AgentListResponse: + ) -> None: """ - Lists all active agents for the authenticated organization. + Unlink a provider account: revoke tokens at the provider and delete them. + purge=true additionally deletes the vault documents its import links brought in. Args: - cursor: Pagination cursor (agent ID from previous page). Returns agents created before - this agent. - - limit: Maximum number of agents to return (default 50, max 250) - extra_headers: Send extra headers extra_query: Add additional query parameters to the request @@ -557,39 +451,54 @@ async def list( timeout: Override the client-level default timeout for this request, in seconds """ - return await self._get( - "/agent/v1/agents", + if not id: + raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") + extra_headers = {"Accept": "*/*", **(extra_headers or {})} + return await self._delete( + path_template("/connectors/v1/connections/{id}", id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout, - query=await async_maybe_transform( - { - "cursor": cursor, - "limit": limit, - }, - agent_list_params.AgentListParams, - ), + query=await async_maybe_transform({"purge": purge}, connection_delete_params.ConnectionDeleteParams), ), - cast_to=AgentListResponse, + cast_to=NoneType, ) - async def delete( + async def browse( self, id: str, *, + container: str | Omit = omit, + cursor: str | Omit = omit, + page_size: int | Omit = omit, + parent: str | Omit = omit, + query: str | Omit = omit, + site: str | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> AgentDeleteResponse: - """ - Soft-deletes an agent and revokes its scoped API key. + ) -> ConnectionBrowseResponse: + """Browse the provider one level at a time. + + Without a site, container, or parent, + returns top-level resources. Pass the stable browse_ref fields returned by one + response to navigate into the next level. Returns 403 + provider_scope_insufficient when the connection scope cannot browse server-side. Args: + container: Container id to list, or the container containing parent + + parent: Folder id to list + + query: Optional provider-supported search text + + site: Site id to list + extra_headers: Send extra headers extra_query: Add additional query parameters to the request @@ -600,94 +509,108 @@ async def delete( """ if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") - return await self._delete( - path_template("/agent/v1/agents/{id}", id=id), + return await self._get( + path_template("/connectors/v1/connections/{id}/browse", id=id), options=make_request_options( - extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + query=await async_maybe_transform( + { + "container": container, + "cursor": cursor, + "page_size": page_size, + "parent": parent, + "query": query, + "site": site, + }, + connection_browse_params.ConnectionBrowseParams, + ), ), - cast_to=AgentDeleteResponse, + cast_to=ConnectionBrowseResponse, ) -class AgentsResourceWithRawResponse: - def __init__(self, agents: AgentsResource) -> None: - self._agents = agents +class ConnectionsResourceWithRawResponse: + def __init__(self, connections: ConnectionsResource) -> None: + self._connections = connections self.create = to_raw_response_wrapper( - agents.create, + connections.create, ) self.retrieve = to_raw_response_wrapper( - agents.retrieve, - ) - self.update = to_raw_response_wrapper( - agents.update, + connections.retrieve, ) self.list = to_raw_response_wrapper( - agents.list, + connections.list, ) self.delete = to_raw_response_wrapper( - agents.delete, + connections.delete, + ) + self.browse = to_raw_response_wrapper( + connections.browse, ) -class AsyncAgentsResourceWithRawResponse: - def __init__(self, agents: AsyncAgentsResource) -> None: - self._agents = agents +class AsyncConnectionsResourceWithRawResponse: + def __init__(self, connections: AsyncConnectionsResource) -> None: + self._connections = connections self.create = async_to_raw_response_wrapper( - agents.create, + connections.create, ) self.retrieve = async_to_raw_response_wrapper( - agents.retrieve, - ) - self.update = async_to_raw_response_wrapper( - agents.update, + connections.retrieve, ) self.list = async_to_raw_response_wrapper( - agents.list, + connections.list, ) self.delete = async_to_raw_response_wrapper( - agents.delete, + connections.delete, + ) + self.browse = async_to_raw_response_wrapper( + connections.browse, ) -class AgentsResourceWithStreamingResponse: - def __init__(self, agents: AgentsResource) -> None: - self._agents = agents +class ConnectionsResourceWithStreamingResponse: + def __init__(self, connections: ConnectionsResource) -> None: + self._connections = connections self.create = to_streamed_response_wrapper( - agents.create, + connections.create, ) self.retrieve = to_streamed_response_wrapper( - agents.retrieve, - ) - self.update = to_streamed_response_wrapper( - agents.update, + connections.retrieve, ) self.list = to_streamed_response_wrapper( - agents.list, + connections.list, ) self.delete = to_streamed_response_wrapper( - agents.delete, + connections.delete, + ) + self.browse = to_streamed_response_wrapper( + connections.browse, ) -class AsyncAgentsResourceWithStreamingResponse: - def __init__(self, agents: AsyncAgentsResource) -> None: - self._agents = agents +class AsyncConnectionsResourceWithStreamingResponse: + def __init__(self, connections: AsyncConnectionsResource) -> None: + self._connections = connections self.create = async_to_streamed_response_wrapper( - agents.create, + connections.create, ) self.retrieve = async_to_streamed_response_wrapper( - agents.retrieve, - ) - self.update = async_to_streamed_response_wrapper( - agents.update, + connections.retrieve, ) self.list = async_to_streamed_response_wrapper( - agents.list, + connections.list, ) self.delete = async_to_streamed_response_wrapper( - agents.delete, + connections.delete, + ) + self.browse = async_to_streamed_response_wrapper( + connections.browse, ) diff --git a/src/casedev/resources/connectors/v1/installations/__init__.py b/src/casedev/resources/connectors/v1/installations/__init__.py new file mode 100644 index 00000000..5a4ab57a --- /dev/null +++ b/src/casedev/resources/connectors/v1/installations/__init__.py @@ -0,0 +1,33 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from .vaults import ( + VaultsResource, + AsyncVaultsResource, + VaultsResourceWithRawResponse, + AsyncVaultsResourceWithRawResponse, + VaultsResourceWithStreamingResponse, + AsyncVaultsResourceWithStreamingResponse, +) +from .installations import ( + InstallationsResource, + AsyncInstallationsResource, + InstallationsResourceWithRawResponse, + AsyncInstallationsResourceWithRawResponse, + InstallationsResourceWithStreamingResponse, + AsyncInstallationsResourceWithStreamingResponse, +) + +__all__ = [ + "VaultsResource", + "AsyncVaultsResource", + "VaultsResourceWithRawResponse", + "AsyncVaultsResourceWithRawResponse", + "VaultsResourceWithStreamingResponse", + "AsyncVaultsResourceWithStreamingResponse", + "InstallationsResource", + "AsyncInstallationsResource", + "InstallationsResourceWithRawResponse", + "AsyncInstallationsResourceWithRawResponse", + "InstallationsResourceWithStreamingResponse", + "AsyncInstallationsResourceWithStreamingResponse", +] diff --git a/src/casedev/resources/connectors/v1/installations/installations.py b/src/casedev/resources/connectors/v1/installations/installations.py new file mode 100644 index 00000000..e7e51664 --- /dev/null +++ b/src/casedev/resources/connectors/v1/installations/installations.py @@ -0,0 +1,330 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +import httpx + +from .vaults import ( + VaultsResource, + AsyncVaultsResource, + VaultsResourceWithRawResponse, + AsyncVaultsResourceWithRawResponse, + VaultsResourceWithStreamingResponse, + AsyncVaultsResourceWithStreamingResponse, +) +from ....._types import Body, Omit, Query, Headers, NoneType, NotGiven, omit, not_given +from ....._utils import maybe_transform, async_maybe_transform +from ....._compat import cached_property +from ....._resource import SyncAPIResource, AsyncAPIResource +from ....._response import ( + to_raw_response_wrapper, + to_streamed_response_wrapper, + async_to_raw_response_wrapper, + async_to_streamed_response_wrapper, +) +from ....._base_client import make_request_options +from .....types.connectors.v1 import installation_list_params, installation_ensure_params + +__all__ = ["InstallationsResource", "AsyncInstallationsResource"] + + +class InstallationsResource(SyncAPIResource): + """Import and export between provider folders (Google Drive) and vaults""" + + @cached_property + def vaults(self) -> VaultsResource: + """Import and export between provider folders (Google Drive) and vaults""" + return VaultsResource(self._client) + + @cached_property + def with_raw_response(self) -> InstallationsResourceWithRawResponse: + """ + This property can be used as a prefix for any HTTP method call to return + the raw response object instead of the parsed content. + + For more information, see https://www.github.com/CaseMark/casedev-python#accessing-raw-response-data-eg-headers + """ + return InstallationsResourceWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> InstallationsResourceWithStreamingResponse: + """ + An alternative to `.with_raw_response` that doesn't eagerly read the response body. + + For more information, see https://www.github.com/CaseMark/casedev-python#with_streaming_response + """ + return InstallationsResourceWithStreamingResponse(self) + + def list( + self, + *, + application: str | Omit = omit, + external_tenant_id: str | Omit = omit, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> None: + """ + List application installations (tenants) in this organization. + + Args: + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + extra_headers = {"Accept": "*/*", **(extra_headers or {})} + return self._get( + "/connectors/v1/installations", + options=make_request_options( + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + query=maybe_transform( + { + "application": application, + "external_tenant_id": external_tenant_id, + }, + installation_list_params.InstallationListParams, + ), + ), + cast_to=NoneType, + ) + + def ensure( + self, + *, + application: str, + external_tenant_id: str, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> None: + """ + Idempotently create (or return) the installation for (application, + external_tenant_id) in this organization. Send the returned installation id as + X-Case-Installation-Id on connector requests to scope them to this tenant. + + Args: + application: Consuming application key (e.g. "p3"). + + external_tenant_id: The application's own tenant identifier (e.g. a P3 organization id). + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + extra_headers = {"Accept": "*/*", **(extra_headers or {})} + return self._post( + "/connectors/v1/installations", + body=maybe_transform( + { + "application": application, + "external_tenant_id": external_tenant_id, + }, + installation_ensure_params.InstallationEnsureParams, + ), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=NoneType, + ) + + +class AsyncInstallationsResource(AsyncAPIResource): + """Import and export between provider folders (Google Drive) and vaults""" + + @cached_property + def vaults(self) -> AsyncVaultsResource: + """Import and export between provider folders (Google Drive) and vaults""" + return AsyncVaultsResource(self._client) + + @cached_property + def with_raw_response(self) -> AsyncInstallationsResourceWithRawResponse: + """ + This property can be used as a prefix for any HTTP method call to return + the raw response object instead of the parsed content. + + For more information, see https://www.github.com/CaseMark/casedev-python#accessing-raw-response-data-eg-headers + """ + return AsyncInstallationsResourceWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> AsyncInstallationsResourceWithStreamingResponse: + """ + An alternative to `.with_raw_response` that doesn't eagerly read the response body. + + For more information, see https://www.github.com/CaseMark/casedev-python#with_streaming_response + """ + return AsyncInstallationsResourceWithStreamingResponse(self) + + async def list( + self, + *, + application: str | Omit = omit, + external_tenant_id: str | Omit = omit, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> None: + """ + List application installations (tenants) in this organization. + + Args: + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + extra_headers = {"Accept": "*/*", **(extra_headers or {})} + return await self._get( + "/connectors/v1/installations", + options=make_request_options( + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + query=await async_maybe_transform( + { + "application": application, + "external_tenant_id": external_tenant_id, + }, + installation_list_params.InstallationListParams, + ), + ), + cast_to=NoneType, + ) + + async def ensure( + self, + *, + application: str, + external_tenant_id: str, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> None: + """ + Idempotently create (or return) the installation for (application, + external_tenant_id) in this organization. Send the returned installation id as + X-Case-Installation-Id on connector requests to scope them to this tenant. + + Args: + application: Consuming application key (e.g. "p3"). + + external_tenant_id: The application's own tenant identifier (e.g. a P3 organization id). + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + extra_headers = {"Accept": "*/*", **(extra_headers or {})} + return await self._post( + "/connectors/v1/installations", + body=await async_maybe_transform( + { + "application": application, + "external_tenant_id": external_tenant_id, + }, + installation_ensure_params.InstallationEnsureParams, + ), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=NoneType, + ) + + +class InstallationsResourceWithRawResponse: + def __init__(self, installations: InstallationsResource) -> None: + self._installations = installations + + self.list = to_raw_response_wrapper( + installations.list, + ) + self.ensure = to_raw_response_wrapper( + installations.ensure, + ) + + @cached_property + def vaults(self) -> VaultsResourceWithRawResponse: + """Import and export between provider folders (Google Drive) and vaults""" + return VaultsResourceWithRawResponse(self._installations.vaults) + + +class AsyncInstallationsResourceWithRawResponse: + def __init__(self, installations: AsyncInstallationsResource) -> None: + self._installations = installations + + self.list = async_to_raw_response_wrapper( + installations.list, + ) + self.ensure = async_to_raw_response_wrapper( + installations.ensure, + ) + + @cached_property + def vaults(self) -> AsyncVaultsResourceWithRawResponse: + """Import and export between provider folders (Google Drive) and vaults""" + return AsyncVaultsResourceWithRawResponse(self._installations.vaults) + + +class InstallationsResourceWithStreamingResponse: + def __init__(self, installations: InstallationsResource) -> None: + self._installations = installations + + self.list = to_streamed_response_wrapper( + installations.list, + ) + self.ensure = to_streamed_response_wrapper( + installations.ensure, + ) + + @cached_property + def vaults(self) -> VaultsResourceWithStreamingResponse: + """Import and export between provider folders (Google Drive) and vaults""" + return VaultsResourceWithStreamingResponse(self._installations.vaults) + + +class AsyncInstallationsResourceWithStreamingResponse: + def __init__(self, installations: AsyncInstallationsResource) -> None: + self._installations = installations + + self.list = async_to_streamed_response_wrapper( + installations.list, + ) + self.ensure = async_to_streamed_response_wrapper( + installations.ensure, + ) + + @cached_property + def vaults(self) -> AsyncVaultsResourceWithStreamingResponse: + """Import and export between provider folders (Google Drive) and vaults""" + return AsyncVaultsResourceWithStreamingResponse(self._installations.vaults) diff --git a/src/casedev/resources/vault/graphrag.py b/src/casedev/resources/connectors/v1/installations/vaults.py similarity index 53% rename from src/casedev/resources/vault/graphrag.py rename to src/casedev/resources/connectors/v1/installations/vaults.py index 7e214417..eef851eb 100644 --- a/src/casedev/resources/vault/graphrag.py +++ b/src/casedev/resources/connectors/v1/installations/vaults.py @@ -2,49 +2,49 @@ from __future__ import annotations +from typing_extensions import Literal + import httpx -from ..._types import Body, Query, Headers, NotGiven, not_given -from ..._utils import path_template -from ..._compat import cached_property -from ..._resource import SyncAPIResource, AsyncAPIResource -from ..._response import ( +from ....._types import Body, Omit, Query, Headers, NoneType, NotGiven, omit, not_given +from ....._utils import path_template, maybe_transform, async_maybe_transform +from ....._compat import cached_property +from ....._resource import SyncAPIResource, AsyncAPIResource +from ....._response import ( to_raw_response_wrapper, to_streamed_response_wrapper, async_to_raw_response_wrapper, async_to_streamed_response_wrapper, ) -from ..._base_client import make_request_options -from ...types.vault.graphrag_init_response import GraphragInitResponse -from ...types.vault.graphrag_get_stats_response import GraphragGetStatsResponse -from ...types.vault.graphrag_process_object_response import GraphragProcessObjectResponse +from ....._base_client import make_request_options +from .....types.connectors.v1.installations import vault_grant_params -__all__ = ["GraphragResource", "AsyncGraphragResource"] +__all__ = ["VaultsResource", "AsyncVaultsResource"] -class GraphragResource(SyncAPIResource): - """Secure document storage with semantic search and GraphRAG""" +class VaultsResource(SyncAPIResource): + """Import and export between provider folders (Google Drive) and vaults""" @cached_property - def with_raw_response(self) -> GraphragResourceWithRawResponse: + def with_raw_response(self) -> VaultsResourceWithRawResponse: """ This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. For more information, see https://www.github.com/CaseMark/casedev-python#accessing-raw-response-data-eg-headers """ - return GraphragResourceWithRawResponse(self) + return VaultsResourceWithRawResponse(self) @cached_property - def with_streaming_response(self) -> GraphragResourceWithStreamingResponse: + def with_streaming_response(self) -> VaultsResourceWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. For more information, see https://www.github.com/CaseMark/casedev-python#with_streaming_response """ - return GraphragResourceWithStreamingResponse(self) + return VaultsResourceWithStreamingResponse(self) - def get_stats( + def list( self, id: str, *, @@ -54,12 +54,9 @@ def get_stats( extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> GraphragGetStatsResponse: + ) -> None: """ - Retrieve GraphRAG (Graph Retrieval-Augmented Generation) statistics for a - specific vault. This includes metrics about the knowledge graph structure, - entity relationships, and processing status that enable advanced semantic search - and AI-powered document analysis. + List the vaults an installation may use, with capabilities and revocation state. Args: extra_headers: Send extra headers @@ -72,30 +69,37 @@ def get_stats( """ if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") + extra_headers = {"Accept": "*/*", **(extra_headers or {})} return self._get( - path_template("/vault/{id}/graphrag/stats", id=id), + path_template("/connectors/v1/installations/{id}/vaults", id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), - cast_to=GraphragGetStatsResponse, + cast_to=NoneType, ) - def init( + def grant( self, - id: str, + vault_id: str, *, + id: str, + can_manage: bool | Omit = omit, + can_read: bool | Omit = omit, + can_write: bool | Omit = omit, + relationship: Literal["owned", "shared"] | Omit = omit, + source: Literal["provisioning", "lazy_reconcile", "explicit_share"] | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> GraphragInitResponse: - """ - Initialize a GraphRAG workspace for a vault to enable advanced knowledge graph - and retrieval-augmented generation capabilities. This creates the necessary - infrastructure for semantic document analysis and graph-based querying within - the vault. + ) -> None: + """Grant (or update) an installation's access to a vault. + + Re-granting a revoked + vault reactivates it. Import links need can_write; export links need can_read; + mirror deletion and purge need can_manage. Args: extra_headers: Send extra headers @@ -108,17 +112,30 @@ def init( """ if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") - return self._post( - path_template("/vault/{id}/graphrag/init", id=id), + if not vault_id: + raise ValueError(f"Expected a non-empty value for `vault_id` but received {vault_id!r}") + extra_headers = {"Accept": "*/*", **(extra_headers or {})} + return self._put( + path_template("/connectors/v1/installations/{id}/vaults/{vault_id}", id=id, vault_id=vault_id), + body=maybe_transform( + { + "can_manage": can_manage, + "can_read": can_read, + "can_write": can_write, + "relationship": relationship, + "source": source, + }, + vault_grant_params.VaultGrantParams, + ), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), - cast_to=GraphragInitResponse, + cast_to=NoneType, ) - def process_object( + def revoke( self, - object_id: str, + vault_id: str, *, id: str, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. @@ -127,12 +144,11 @@ def process_object( extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> GraphragProcessObjectResponse: - """Manually trigger GraphRAG indexing for a vault object. + ) -> None: + """Revoke an installation's access to a vault. - The object must already - be ingested (completed status). This extracts entities, relationships, and - communities from the document for advanced knowledge graph queries. + Links using the vault pause at their + next run; nothing is deleted. Args: extra_headers: Send extra headers @@ -145,40 +161,41 @@ def process_object( """ if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") - if not object_id: - raise ValueError(f"Expected a non-empty value for `object_id` but received {object_id!r}") - return self._post( - path_template("/vault/{id}/graphrag/{object_id}", id=id, object_id=object_id), + if not vault_id: + raise ValueError(f"Expected a non-empty value for `vault_id` but received {vault_id!r}") + extra_headers = {"Accept": "*/*", **(extra_headers or {})} + return self._delete( + path_template("/connectors/v1/installations/{id}/vaults/{vault_id}", id=id, vault_id=vault_id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), - cast_to=GraphragProcessObjectResponse, + cast_to=NoneType, ) -class AsyncGraphragResource(AsyncAPIResource): - """Secure document storage with semantic search and GraphRAG""" +class AsyncVaultsResource(AsyncAPIResource): + """Import and export between provider folders (Google Drive) and vaults""" @cached_property - def with_raw_response(self) -> AsyncGraphragResourceWithRawResponse: + def with_raw_response(self) -> AsyncVaultsResourceWithRawResponse: """ This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. For more information, see https://www.github.com/CaseMark/casedev-python#accessing-raw-response-data-eg-headers """ - return AsyncGraphragResourceWithRawResponse(self) + return AsyncVaultsResourceWithRawResponse(self) @cached_property - def with_streaming_response(self) -> AsyncGraphragResourceWithStreamingResponse: + def with_streaming_response(self) -> AsyncVaultsResourceWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. For more information, see https://www.github.com/CaseMark/casedev-python#with_streaming_response """ - return AsyncGraphragResourceWithStreamingResponse(self) + return AsyncVaultsResourceWithStreamingResponse(self) - async def get_stats( + async def list( self, id: str, *, @@ -188,12 +205,9 @@ async def get_stats( extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> GraphragGetStatsResponse: + ) -> None: """ - Retrieve GraphRAG (Graph Retrieval-Augmented Generation) statistics for a - specific vault. This includes metrics about the knowledge graph structure, - entity relationships, and processing status that enable advanced semantic search - and AI-powered document analysis. + List the vaults an installation may use, with capabilities and revocation state. Args: extra_headers: Send extra headers @@ -206,30 +220,37 @@ async def get_stats( """ if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") + extra_headers = {"Accept": "*/*", **(extra_headers or {})} return await self._get( - path_template("/vault/{id}/graphrag/stats", id=id), + path_template("/connectors/v1/installations/{id}/vaults", id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), - cast_to=GraphragGetStatsResponse, + cast_to=NoneType, ) - async def init( + async def grant( self, - id: str, + vault_id: str, *, + id: str, + can_manage: bool | Omit = omit, + can_read: bool | Omit = omit, + can_write: bool | Omit = omit, + relationship: Literal["owned", "shared"] | Omit = omit, + source: Literal["provisioning", "lazy_reconcile", "explicit_share"] | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> GraphragInitResponse: - """ - Initialize a GraphRAG workspace for a vault to enable advanced knowledge graph - and retrieval-augmented generation capabilities. This creates the necessary - infrastructure for semantic document analysis and graph-based querying within - the vault. + ) -> None: + """Grant (or update) an installation's access to a vault. + + Re-granting a revoked + vault reactivates it. Import links need can_write; export links need can_read; + mirror deletion and purge need can_manage. Args: extra_headers: Send extra headers @@ -242,17 +263,30 @@ async def init( """ if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") - return await self._post( - path_template("/vault/{id}/graphrag/init", id=id), + if not vault_id: + raise ValueError(f"Expected a non-empty value for `vault_id` but received {vault_id!r}") + extra_headers = {"Accept": "*/*", **(extra_headers or {})} + return await self._put( + path_template("/connectors/v1/installations/{id}/vaults/{vault_id}", id=id, vault_id=vault_id), + body=await async_maybe_transform( + { + "can_manage": can_manage, + "can_read": can_read, + "can_write": can_write, + "relationship": relationship, + "source": source, + }, + vault_grant_params.VaultGrantParams, + ), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), - cast_to=GraphragInitResponse, + cast_to=NoneType, ) - async def process_object( + async def revoke( self, - object_id: str, + vault_id: str, *, id: str, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. @@ -261,12 +295,11 @@ async def process_object( extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> GraphragProcessObjectResponse: - """Manually trigger GraphRAG indexing for a vault object. + ) -> None: + """Revoke an installation's access to a vault. - The object must already - be ingested (completed status). This extracts entities, relationships, and - communities from the document for advanced knowledge graph queries. + Links using the vault pause at their + next run; nothing is deleted. Args: extra_headers: Send extra headers @@ -279,72 +312,73 @@ async def process_object( """ if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") - if not object_id: - raise ValueError(f"Expected a non-empty value for `object_id` but received {object_id!r}") - return await self._post( - path_template("/vault/{id}/graphrag/{object_id}", id=id, object_id=object_id), + if not vault_id: + raise ValueError(f"Expected a non-empty value for `vault_id` but received {vault_id!r}") + extra_headers = {"Accept": "*/*", **(extra_headers or {})} + return await self._delete( + path_template("/connectors/v1/installations/{id}/vaults/{vault_id}", id=id, vault_id=vault_id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), - cast_to=GraphragProcessObjectResponse, + cast_to=NoneType, ) -class GraphragResourceWithRawResponse: - def __init__(self, graphrag: GraphragResource) -> None: - self._graphrag = graphrag +class VaultsResourceWithRawResponse: + def __init__(self, vaults: VaultsResource) -> None: + self._vaults = vaults - self.get_stats = to_raw_response_wrapper( - graphrag.get_stats, + self.list = to_raw_response_wrapper( + vaults.list, ) - self.init = to_raw_response_wrapper( - graphrag.init, + self.grant = to_raw_response_wrapper( + vaults.grant, ) - self.process_object = to_raw_response_wrapper( - graphrag.process_object, + self.revoke = to_raw_response_wrapper( + vaults.revoke, ) -class AsyncGraphragResourceWithRawResponse: - def __init__(self, graphrag: AsyncGraphragResource) -> None: - self._graphrag = graphrag +class AsyncVaultsResourceWithRawResponse: + def __init__(self, vaults: AsyncVaultsResource) -> None: + self._vaults = vaults - self.get_stats = async_to_raw_response_wrapper( - graphrag.get_stats, + self.list = async_to_raw_response_wrapper( + vaults.list, ) - self.init = async_to_raw_response_wrapper( - graphrag.init, + self.grant = async_to_raw_response_wrapper( + vaults.grant, ) - self.process_object = async_to_raw_response_wrapper( - graphrag.process_object, + self.revoke = async_to_raw_response_wrapper( + vaults.revoke, ) -class GraphragResourceWithStreamingResponse: - def __init__(self, graphrag: GraphragResource) -> None: - self._graphrag = graphrag +class VaultsResourceWithStreamingResponse: + def __init__(self, vaults: VaultsResource) -> None: + self._vaults = vaults - self.get_stats = to_streamed_response_wrapper( - graphrag.get_stats, + self.list = to_streamed_response_wrapper( + vaults.list, ) - self.init = to_streamed_response_wrapper( - graphrag.init, + self.grant = to_streamed_response_wrapper( + vaults.grant, ) - self.process_object = to_streamed_response_wrapper( - graphrag.process_object, + self.revoke = to_streamed_response_wrapper( + vaults.revoke, ) -class AsyncGraphragResourceWithStreamingResponse: - def __init__(self, graphrag: AsyncGraphragResource) -> None: - self._graphrag = graphrag +class AsyncVaultsResourceWithStreamingResponse: + def __init__(self, vaults: AsyncVaultsResource) -> None: + self._vaults = vaults - self.get_stats = async_to_streamed_response_wrapper( - graphrag.get_stats, + self.list = async_to_streamed_response_wrapper( + vaults.list, ) - self.init = async_to_streamed_response_wrapper( - graphrag.init, + self.grant = async_to_streamed_response_wrapper( + vaults.grant, ) - self.process_object = async_to_streamed_response_wrapper( - graphrag.process_object, + self.revoke = async_to_streamed_response_wrapper( + vaults.revoke, ) diff --git a/src/casedev/resources/document_templates/document_templates.py b/src/casedev/resources/connectors/v1/links.py similarity index 57% rename from src/casedev/resources/document_templates/document_templates.py rename to src/casedev/resources/connectors/v1/links.py index a0008124..7c93bbb4 100644 --- a/src/casedev/resources/document_templates/document_templates.py +++ b/src/casedev/resources/connectors/v1/links.py @@ -2,74 +2,47 @@ from __future__ import annotations +from typing_extensions import Literal + import httpx -from ..._types import Body, Query, Headers, NoneType, NotGiven, not_given -from ..._utils import path_template -from ..._compat import cached_property -from ..._resource import SyncAPIResource, AsyncAPIResource -from ..._response import ( +from ...._types import Body, Omit, Query, Headers, NoneType, NotGiven, omit, not_given +from ...._utils import path_template, maybe_transform, async_maybe_transform +from ...._compat import cached_property +from ...._resource import SyncAPIResource, AsyncAPIResource +from ...._response import ( to_raw_response_wrapper, to_streamed_response_wrapper, async_to_raw_response_wrapper, async_to_streamed_response_wrapper, ) -from ..._base_client import make_request_options -from .from_vault_object import ( - FromVaultObjectResource, - AsyncFromVaultObjectResource, - FromVaultObjectResourceWithRawResponse, - AsyncFromVaultObjectResourceWithRawResponse, - FromVaultObjectResourceWithStreamingResponse, - AsyncFromVaultObjectResourceWithStreamingResponse, -) +from ...._base_client import make_request_options +from ....types.connectors.v1 import link_list_params, link_delete_params, link_update_params, link_list_objects_params -__all__ = ["DocumentTemplatesResource", "AsyncDocumentTemplatesResource"] +__all__ = ["LinksResource", "AsyncLinksResource"] -class DocumentTemplatesResource(SyncAPIResource): - @cached_property - def from_vault_object(self) -> FromVaultObjectResource: - return FromVaultObjectResource(self._client) +class LinksResource(SyncAPIResource): + """Import and export between provider folders (Google Drive) and vaults""" @cached_property - def with_raw_response(self) -> DocumentTemplatesResourceWithRawResponse: + def with_raw_response(self) -> LinksResourceWithRawResponse: """ This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. For more information, see https://www.github.com/CaseMark/casedev-python#accessing-raw-response-data-eg-headers """ - return DocumentTemplatesResourceWithRawResponse(self) + return LinksResourceWithRawResponse(self) @cached_property - def with_streaming_response(self) -> DocumentTemplatesResourceWithStreamingResponse: + def with_streaming_response(self) -> LinksResourceWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. For more information, see https://www.github.com/CaseMark/casedev-python#with_streaming_response """ - return DocumentTemplatesResourceWithStreamingResponse(self) - - def create( - self, - *, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> None: - """Create document template upload""" - extra_headers = {"Accept": "*/*", **(extra_headers or {})} - return self._post( - "/document-templates", - options=make_request_options( - extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout - ), - cast_to=NoneType, - ) + return LinksResourceWithStreamingResponse(self) def retrieve( self, @@ -82,8 +55,10 @@ def retrieve( extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> None: - """ - Get document template + """Retrieve one link: state, counts, and embedded active_run/last_run. + + Poll this + after POST /transfer. Args: extra_headers: Send extra headers @@ -98,7 +73,7 @@ def retrieve( raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") extra_headers = {"Accept": "*/*", **(extra_headers or {})} return self._get( - path_template("/document-templates/{id}", id=id), + path_template("/connectors/v1/links/{id}", id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -109,6 +84,9 @@ def update( self, id: str, *, + mode: Literal["once", "synced"] | Omit = omit, + policy: object | Omit = omit, + state: Literal["paused", "ready"] | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, @@ -117,7 +95,8 @@ def update( timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> None: """ - Update document template metadata + Pause/resume a link (state "paused" | "ready"), change its mode (synced -> once + is the sync downgrade), or edit its policy in place. Args: extra_headers: Send extra headers @@ -132,7 +111,15 @@ def update( raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") extra_headers = {"Accept": "*/*", **(extra_headers or {})} return self._patch( - path_template("/document-templates/{id}", id=id), + path_template("/connectors/v1/links/{id}", id=id), + body=maybe_transform( + { + "mode": mode, + "policy": policy, + "state": state, + }, + link_update_params.LinkUpdateParams, + ), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -142,6 +129,12 @@ def update( def list( self, *, + connection_id: str | Omit = omit, + direction: Literal["import", "export"] | Omit = omit, + mode: Literal["once", "synced"] | Omit = omit, + pair_id: str | Omit = omit, + state: Literal["ready", "running", "active", "paused", "orphaned", "error"] | Omit = omit, + vault_id: str | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, @@ -149,12 +142,38 @@ def list( extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> None: - """List document templates""" + """ + List transfer links, filterable by vault, connection, direction, mode, and + state. + + Args: + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ extra_headers = {"Accept": "*/*", **(extra_headers or {})} return self._get( - "/document-templates", + "/connectors/v1/links", options=make_request_options( - extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + query=maybe_transform( + { + "connection_id": connection_id, + "direction": direction, + "mode": mode, + "pair_id": pair_id, + "state": state, + "vault_id": vault_id, + }, + link_list_params.LinkListParams, + ), ), cast_to=NoneType, ) @@ -163,6 +182,7 @@ def delete( self, id: str, *, + vault_docs: Literal["keep", "delete"] | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, @@ -170,8 +190,10 @@ def delete( extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> None: - """ - Delete document template + """Delete a link and its ledger. + + vault_docs=delete additionally removes the vault + documents an import link brought in (default: keep). Args: extra_headers: Send extra headers @@ -186,17 +208,24 @@ def delete( raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") extra_headers = {"Accept": "*/*", **(extra_headers or {})} return self._delete( - path_template("/document-templates/{id}", id=id), + path_template("/connectors/v1/links/{id}", id=id), options=make_request_options( - extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + query=maybe_transform({"vault_docs": vault_docs}, link_delete_params.LinkDeleteParams), ), cast_to=NoneType, ) - def confirm( + def list_objects( self, id: str, *, + cursor: str | Omit = omit, + state: Literal["pending", "transferring", "ingesting", "synced", "skipped", "failed", "tombstoned"] + | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, @@ -205,7 +234,8 @@ def confirm( timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> None: """ - Confirm document template upload + Per-file transfer ledger for a link: provider item, vault object, path, content + version, state, and error. Args: extra_headers: Send extra headers @@ -219,58 +249,46 @@ def confirm( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") extra_headers = {"Accept": "*/*", **(extra_headers or {})} - return self._post( - path_template("/document-templates/{id}/confirm", id=id), + return self._get( + path_template("/connectors/v1/links/{id}/objects", id=id), options=make_request_options( - extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + query=maybe_transform( + { + "cursor": cursor, + "state": state, + }, + link_list_objects_params.LinkListObjectsParams, + ), ), cast_to=NoneType, ) -class AsyncDocumentTemplatesResource(AsyncAPIResource): - @cached_property - def from_vault_object(self) -> AsyncFromVaultObjectResource: - return AsyncFromVaultObjectResource(self._client) +class AsyncLinksResource(AsyncAPIResource): + """Import and export between provider folders (Google Drive) and vaults""" @cached_property - def with_raw_response(self) -> AsyncDocumentTemplatesResourceWithRawResponse: + def with_raw_response(self) -> AsyncLinksResourceWithRawResponse: """ This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. For more information, see https://www.github.com/CaseMark/casedev-python#accessing-raw-response-data-eg-headers """ - return AsyncDocumentTemplatesResourceWithRawResponse(self) + return AsyncLinksResourceWithRawResponse(self) @cached_property - def with_streaming_response(self) -> AsyncDocumentTemplatesResourceWithStreamingResponse: + def with_streaming_response(self) -> AsyncLinksResourceWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. For more information, see https://www.github.com/CaseMark/casedev-python#with_streaming_response """ - return AsyncDocumentTemplatesResourceWithStreamingResponse(self) - - async def create( - self, - *, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> None: - """Create document template upload""" - extra_headers = {"Accept": "*/*", **(extra_headers or {})} - return await self._post( - "/document-templates", - options=make_request_options( - extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout - ), - cast_to=NoneType, - ) + return AsyncLinksResourceWithStreamingResponse(self) async def retrieve( self, @@ -283,8 +301,10 @@ async def retrieve( extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> None: - """ - Get document template + """Retrieve one link: state, counts, and embedded active_run/last_run. + + Poll this + after POST /transfer. Args: extra_headers: Send extra headers @@ -299,7 +319,7 @@ async def retrieve( raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") extra_headers = {"Accept": "*/*", **(extra_headers or {})} return await self._get( - path_template("/document-templates/{id}", id=id), + path_template("/connectors/v1/links/{id}", id=id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -310,6 +330,9 @@ async def update( self, id: str, *, + mode: Literal["once", "synced"] | Omit = omit, + policy: object | Omit = omit, + state: Literal["paused", "ready"] | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, @@ -318,7 +341,8 @@ async def update( timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> None: """ - Update document template metadata + Pause/resume a link (state "paused" | "ready"), change its mode (synced -> once + is the sync downgrade), or edit its policy in place. Args: extra_headers: Send extra headers @@ -333,7 +357,15 @@ async def update( raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") extra_headers = {"Accept": "*/*", **(extra_headers or {})} return await self._patch( - path_template("/document-templates/{id}", id=id), + path_template("/connectors/v1/links/{id}", id=id), + body=await async_maybe_transform( + { + "mode": mode, + "policy": policy, + "state": state, + }, + link_update_params.LinkUpdateParams, + ), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -343,6 +375,12 @@ async def update( async def list( self, *, + connection_id: str | Omit = omit, + direction: Literal["import", "export"] | Omit = omit, + mode: Literal["once", "synced"] | Omit = omit, + pair_id: str | Omit = omit, + state: Literal["ready", "running", "active", "paused", "orphaned", "error"] | Omit = omit, + vault_id: str | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, @@ -350,12 +388,38 @@ async def list( extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> None: - """List document templates""" + """ + List transfer links, filterable by vault, connection, direction, mode, and + state. + + Args: + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ extra_headers = {"Accept": "*/*", **(extra_headers or {})} return await self._get( - "/document-templates", + "/connectors/v1/links", options=make_request_options( - extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + query=await async_maybe_transform( + { + "connection_id": connection_id, + "direction": direction, + "mode": mode, + "pair_id": pair_id, + "state": state, + "vault_id": vault_id, + }, + link_list_params.LinkListParams, + ), ), cast_to=NoneType, ) @@ -364,6 +428,7 @@ async def delete( self, id: str, *, + vault_docs: Literal["keep", "delete"] | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, @@ -371,8 +436,10 @@ async def delete( extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> None: - """ - Delete document template + """Delete a link and its ledger. + + vault_docs=delete additionally removes the vault + documents an import link brought in (default: keep). Args: extra_headers: Send extra headers @@ -387,17 +454,24 @@ async def delete( raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") extra_headers = {"Accept": "*/*", **(extra_headers or {})} return await self._delete( - path_template("/document-templates/{id}", id=id), + path_template("/connectors/v1/links/{id}", id=id), options=make_request_options( - extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + query=await async_maybe_transform({"vault_docs": vault_docs}, link_delete_params.LinkDeleteParams), ), cast_to=NoneType, ) - async def confirm( + async def list_objects( self, id: str, *, + cursor: str | Omit = omit, + state: Literal["pending", "transferring", "ingesting", "synced", "skipped", "failed", "tombstoned"] + | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, @@ -406,7 +480,8 @@ async def confirm( timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> None: """ - Confirm document template upload + Per-file transfer ledger for a link: provider item, vault object, path, content + version, state, and error. Args: extra_headers: Send extra headers @@ -420,122 +495,104 @@ async def confirm( if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") extra_headers = {"Accept": "*/*", **(extra_headers or {})} - return await self._post( - path_template("/document-templates/{id}/confirm", id=id), + return await self._get( + path_template("/connectors/v1/links/{id}/objects", id=id), options=make_request_options( - extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + query=await async_maybe_transform( + { + "cursor": cursor, + "state": state, + }, + link_list_objects_params.LinkListObjectsParams, + ), ), cast_to=NoneType, ) -class DocumentTemplatesResourceWithRawResponse: - def __init__(self, document_templates: DocumentTemplatesResource) -> None: - self._document_templates = document_templates +class LinksResourceWithRawResponse: + def __init__(self, links: LinksResource) -> None: + self._links = links - self.create = to_raw_response_wrapper( - document_templates.create, - ) self.retrieve = to_raw_response_wrapper( - document_templates.retrieve, + links.retrieve, ) self.update = to_raw_response_wrapper( - document_templates.update, + links.update, ) self.list = to_raw_response_wrapper( - document_templates.list, + links.list, ) self.delete = to_raw_response_wrapper( - document_templates.delete, + links.delete, ) - self.confirm = to_raw_response_wrapper( - document_templates.confirm, + self.list_objects = to_raw_response_wrapper( + links.list_objects, ) - @cached_property - def from_vault_object(self) -> FromVaultObjectResourceWithRawResponse: - return FromVaultObjectResourceWithRawResponse(self._document_templates.from_vault_object) - -class AsyncDocumentTemplatesResourceWithRawResponse: - def __init__(self, document_templates: AsyncDocumentTemplatesResource) -> None: - self._document_templates = document_templates +class AsyncLinksResourceWithRawResponse: + def __init__(self, links: AsyncLinksResource) -> None: + self._links = links - self.create = async_to_raw_response_wrapper( - document_templates.create, - ) self.retrieve = async_to_raw_response_wrapper( - document_templates.retrieve, + links.retrieve, ) self.update = async_to_raw_response_wrapper( - document_templates.update, + links.update, ) self.list = async_to_raw_response_wrapper( - document_templates.list, + links.list, ) self.delete = async_to_raw_response_wrapper( - document_templates.delete, + links.delete, ) - self.confirm = async_to_raw_response_wrapper( - document_templates.confirm, + self.list_objects = async_to_raw_response_wrapper( + links.list_objects, ) - @cached_property - def from_vault_object(self) -> AsyncFromVaultObjectResourceWithRawResponse: - return AsyncFromVaultObjectResourceWithRawResponse(self._document_templates.from_vault_object) - -class DocumentTemplatesResourceWithStreamingResponse: - def __init__(self, document_templates: DocumentTemplatesResource) -> None: - self._document_templates = document_templates +class LinksResourceWithStreamingResponse: + def __init__(self, links: LinksResource) -> None: + self._links = links - self.create = to_streamed_response_wrapper( - document_templates.create, - ) self.retrieve = to_streamed_response_wrapper( - document_templates.retrieve, + links.retrieve, ) self.update = to_streamed_response_wrapper( - document_templates.update, + links.update, ) self.list = to_streamed_response_wrapper( - document_templates.list, + links.list, ) self.delete = to_streamed_response_wrapper( - document_templates.delete, + links.delete, ) - self.confirm = to_streamed_response_wrapper( - document_templates.confirm, + self.list_objects = to_streamed_response_wrapper( + links.list_objects, ) - @cached_property - def from_vault_object(self) -> FromVaultObjectResourceWithStreamingResponse: - return FromVaultObjectResourceWithStreamingResponse(self._document_templates.from_vault_object) - -class AsyncDocumentTemplatesResourceWithStreamingResponse: - def __init__(self, document_templates: AsyncDocumentTemplatesResource) -> None: - self._document_templates = document_templates +class AsyncLinksResourceWithStreamingResponse: + def __init__(self, links: AsyncLinksResource) -> None: + self._links = links - self.create = async_to_streamed_response_wrapper( - document_templates.create, - ) self.retrieve = async_to_streamed_response_wrapper( - document_templates.retrieve, + links.retrieve, ) self.update = async_to_streamed_response_wrapper( - document_templates.update, + links.update, ) self.list = async_to_streamed_response_wrapper( - document_templates.list, + links.list, ) self.delete = async_to_streamed_response_wrapper( - document_templates.delete, + links.delete, ) - self.confirm = async_to_streamed_response_wrapper( - document_templates.confirm, + self.list_objects = async_to_streamed_response_wrapper( + links.list_objects, ) - - @cached_property - def from_vault_object(self) -> AsyncFromVaultObjectResourceWithStreamingResponse: - return AsyncFromVaultObjectResourceWithStreamingResponse(self._document_templates.from_vault_object) diff --git a/src/casedev/resources/connectors/v1/v1.py b/src/casedev/resources/connectors/v1/v1.py new file mode 100644 index 00000000..cff90974 --- /dev/null +++ b/src/casedev/resources/connectors/v1/v1.py @@ -0,0 +1,439 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing import Optional +from typing_extensions import Literal + +import httpx + +from .links import ( + LinksResource, + AsyncLinksResource, + LinksResourceWithRawResponse, + AsyncLinksResourceWithRawResponse, + LinksResourceWithStreamingResponse, + AsyncLinksResourceWithStreamingResponse, +) +from ...._types import Body, Omit, Query, Headers, NotGiven, omit, not_given +from ...._utils import maybe_transform, async_maybe_transform +from ...._compat import cached_property +from .connections import ( + ConnectionsResource, + AsyncConnectionsResource, + ConnectionsResourceWithRawResponse, + AsyncConnectionsResourceWithRawResponse, + ConnectionsResourceWithStreamingResponse, + AsyncConnectionsResourceWithStreamingResponse, +) +from ...._resource import SyncAPIResource, AsyncAPIResource +from ...._response import ( + to_raw_response_wrapper, + to_streamed_response_wrapper, + async_to_raw_response_wrapper, + async_to_streamed_response_wrapper, +) +from ...._base_client import make_request_options +from ....types.connectors import v1_transfer_params, v1_sync_link_params +from .installations.installations import ( + InstallationsResource, + AsyncInstallationsResource, + InstallationsResourceWithRawResponse, + AsyncInstallationsResourceWithRawResponse, + InstallationsResourceWithStreamingResponse, + AsyncInstallationsResourceWithStreamingResponse, +) +from ....types.connectors.v1_transfer_response import V1TransferResponse +from ....types.connectors.v1_sync_link_response import V1SyncLinkResponse + +__all__ = ["V1Resource", "AsyncV1Resource"] + + +class V1Resource(SyncAPIResource): + """Import and export between provider folders (Google Drive) and vaults""" + + @cached_property + def installations(self) -> InstallationsResource: + """Import and export between provider folders (Google Drive) and vaults""" + return InstallationsResource(self._client) + + @cached_property + def connections(self) -> ConnectionsResource: + """Import and export between provider folders (Google Drive) and vaults""" + return ConnectionsResource(self._client) + + @cached_property + def links(self) -> LinksResource: + """Import and export between provider folders (Google Drive) and vaults""" + return LinksResource(self._client) + + @cached_property + def with_raw_response(self) -> V1ResourceWithRawResponse: + """ + This property can be used as a prefix for any HTTP method call to return + the raw response object instead of the parsed content. + + For more information, see https://www.github.com/CaseMark/casedev-python#accessing-raw-response-data-eg-headers + """ + return V1ResourceWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> V1ResourceWithStreamingResponse: + """ + An alternative to `.with_raw_response` that doesn't eagerly read the response body. + + For more information, see https://www.github.com/CaseMark/casedev-python#with_streaming_response + """ + return V1ResourceWithStreamingResponse(self) + + def sync_link( + self, + *, + connection_id: str, + direction: Literal["import", "export"], + remote: v1_sync_link_params.Remote, + vault_id: str, + matter_id: Optional[str] | Omit = omit, + policy: v1_sync_link_params.Policy | Omit = omit, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> V1SyncLinkResponse: + """ + Standing promise: backfill now, then stay current (the sync sweeper re-runs + synced links on a schedule). Same body as /transfer minus run_mode. Upserts the + link identified by (connection_id, direction, remote, vault_id); an existing + once-link is upgraded in place with its ledger and cursor preserved. Downgrade + or pause via PATCH /links/{id}. + + Args: + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + return self._post( + "/connectors/v1/sync-link", + body=maybe_transform( + { + "connection_id": connection_id, + "direction": direction, + "remote": remote, + "vault_id": vault_id, + "matter_id": matter_id, + "policy": policy, + }, + v1_sync_link_params.V1SyncLinkParams, + ), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=V1SyncLinkResponse, + ) + + def transfer( + self, + *, + connection_id: str, + direction: Literal["import", "export"], + remote: v1_transfer_params.Remote, + vault_id: str, + matter_id: Optional[str] | Omit = omit, + policy: v1_transfer_params.Policy | Omit = omit, + run_mode: Literal["auto", "full_reconcile"] | Omit = omit, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> V1TransferResponse: + """ + One-shot import (provider folder → vault) or export (vault → provider folder). + Upserts the link identified by (connection_id, direction, remote, vault_id): + first call backfills, later calls move only new/changed files via the ledger. + Poll GET /links/{id} → active_run for progress. + + Args: + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + return self._post( + "/connectors/v1/transfer", + body=maybe_transform( + { + "connection_id": connection_id, + "direction": direction, + "remote": remote, + "vault_id": vault_id, + "matter_id": matter_id, + "policy": policy, + "run_mode": run_mode, + }, + v1_transfer_params.V1TransferParams, + ), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=V1TransferResponse, + ) + + +class AsyncV1Resource(AsyncAPIResource): + """Import and export between provider folders (Google Drive) and vaults""" + + @cached_property + def installations(self) -> AsyncInstallationsResource: + """Import and export between provider folders (Google Drive) and vaults""" + return AsyncInstallationsResource(self._client) + + @cached_property + def connections(self) -> AsyncConnectionsResource: + """Import and export between provider folders (Google Drive) and vaults""" + return AsyncConnectionsResource(self._client) + + @cached_property + def links(self) -> AsyncLinksResource: + """Import and export between provider folders (Google Drive) and vaults""" + return AsyncLinksResource(self._client) + + @cached_property + def with_raw_response(self) -> AsyncV1ResourceWithRawResponse: + """ + This property can be used as a prefix for any HTTP method call to return + the raw response object instead of the parsed content. + + For more information, see https://www.github.com/CaseMark/casedev-python#accessing-raw-response-data-eg-headers + """ + return AsyncV1ResourceWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> AsyncV1ResourceWithStreamingResponse: + """ + An alternative to `.with_raw_response` that doesn't eagerly read the response body. + + For more information, see https://www.github.com/CaseMark/casedev-python#with_streaming_response + """ + return AsyncV1ResourceWithStreamingResponse(self) + + async def sync_link( + self, + *, + connection_id: str, + direction: Literal["import", "export"], + remote: v1_sync_link_params.Remote, + vault_id: str, + matter_id: Optional[str] | Omit = omit, + policy: v1_sync_link_params.Policy | Omit = omit, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> V1SyncLinkResponse: + """ + Standing promise: backfill now, then stay current (the sync sweeper re-runs + synced links on a schedule). Same body as /transfer minus run_mode. Upserts the + link identified by (connection_id, direction, remote, vault_id); an existing + once-link is upgraded in place with its ledger and cursor preserved. Downgrade + or pause via PATCH /links/{id}. + + Args: + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + return await self._post( + "/connectors/v1/sync-link", + body=await async_maybe_transform( + { + "connection_id": connection_id, + "direction": direction, + "remote": remote, + "vault_id": vault_id, + "matter_id": matter_id, + "policy": policy, + }, + v1_sync_link_params.V1SyncLinkParams, + ), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=V1SyncLinkResponse, + ) + + async def transfer( + self, + *, + connection_id: str, + direction: Literal["import", "export"], + remote: v1_transfer_params.Remote, + vault_id: str, + matter_id: Optional[str] | Omit = omit, + policy: v1_transfer_params.Policy | Omit = omit, + run_mode: Literal["auto", "full_reconcile"] | Omit = omit, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> V1TransferResponse: + """ + One-shot import (provider folder → vault) or export (vault → provider folder). + Upserts the link identified by (connection_id, direction, remote, vault_id): + first call backfills, later calls move only new/changed files via the ledger. + Poll GET /links/{id} → active_run for progress. + + Args: + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + return await self._post( + "/connectors/v1/transfer", + body=await async_maybe_transform( + { + "connection_id": connection_id, + "direction": direction, + "remote": remote, + "vault_id": vault_id, + "matter_id": matter_id, + "policy": policy, + "run_mode": run_mode, + }, + v1_transfer_params.V1TransferParams, + ), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=V1TransferResponse, + ) + + +class V1ResourceWithRawResponse: + def __init__(self, v1: V1Resource) -> None: + self._v1 = v1 + + self.sync_link = to_raw_response_wrapper( + v1.sync_link, + ) + self.transfer = to_raw_response_wrapper( + v1.transfer, + ) + + @cached_property + def installations(self) -> InstallationsResourceWithRawResponse: + """Import and export between provider folders (Google Drive) and vaults""" + return InstallationsResourceWithRawResponse(self._v1.installations) + + @cached_property + def connections(self) -> ConnectionsResourceWithRawResponse: + """Import and export between provider folders (Google Drive) and vaults""" + return ConnectionsResourceWithRawResponse(self._v1.connections) + + @cached_property + def links(self) -> LinksResourceWithRawResponse: + """Import and export between provider folders (Google Drive) and vaults""" + return LinksResourceWithRawResponse(self._v1.links) + + +class AsyncV1ResourceWithRawResponse: + def __init__(self, v1: AsyncV1Resource) -> None: + self._v1 = v1 + + self.sync_link = async_to_raw_response_wrapper( + v1.sync_link, + ) + self.transfer = async_to_raw_response_wrapper( + v1.transfer, + ) + + @cached_property + def installations(self) -> AsyncInstallationsResourceWithRawResponse: + """Import and export between provider folders (Google Drive) and vaults""" + return AsyncInstallationsResourceWithRawResponse(self._v1.installations) + + @cached_property + def connections(self) -> AsyncConnectionsResourceWithRawResponse: + """Import and export between provider folders (Google Drive) and vaults""" + return AsyncConnectionsResourceWithRawResponse(self._v1.connections) + + @cached_property + def links(self) -> AsyncLinksResourceWithRawResponse: + """Import and export between provider folders (Google Drive) and vaults""" + return AsyncLinksResourceWithRawResponse(self._v1.links) + + +class V1ResourceWithStreamingResponse: + def __init__(self, v1: V1Resource) -> None: + self._v1 = v1 + + self.sync_link = to_streamed_response_wrapper( + v1.sync_link, + ) + self.transfer = to_streamed_response_wrapper( + v1.transfer, + ) + + @cached_property + def installations(self) -> InstallationsResourceWithStreamingResponse: + """Import and export between provider folders (Google Drive) and vaults""" + return InstallationsResourceWithStreamingResponse(self._v1.installations) + + @cached_property + def connections(self) -> ConnectionsResourceWithStreamingResponse: + """Import and export between provider folders (Google Drive) and vaults""" + return ConnectionsResourceWithStreamingResponse(self._v1.connections) + + @cached_property + def links(self) -> LinksResourceWithStreamingResponse: + """Import and export between provider folders (Google Drive) and vaults""" + return LinksResourceWithStreamingResponse(self._v1.links) + + +class AsyncV1ResourceWithStreamingResponse: + def __init__(self, v1: AsyncV1Resource) -> None: + self._v1 = v1 + + self.sync_link = async_to_streamed_response_wrapper( + v1.sync_link, + ) + self.transfer = async_to_streamed_response_wrapper( + v1.transfer, + ) + + @cached_property + def installations(self) -> AsyncInstallationsResourceWithStreamingResponse: + """Import and export between provider folders (Google Drive) and vaults""" + return AsyncInstallationsResourceWithStreamingResponse(self._v1.installations) + + @cached_property + def connections(self) -> AsyncConnectionsResourceWithStreamingResponse: + """Import and export between provider folders (Google Drive) and vaults""" + return AsyncConnectionsResourceWithStreamingResponse(self._v1.connections) + + @cached_property + def links(self) -> AsyncLinksResourceWithStreamingResponse: + """Import and export between provider folders (Google Drive) and vaults""" + return AsyncLinksResourceWithStreamingResponse(self._v1.links) diff --git a/src/casedev/resources/database/__init__.py b/src/casedev/resources/database/__init__.py deleted file mode 100644 index 02eed9d2..00000000 --- a/src/casedev/resources/database/__init__.py +++ /dev/null @@ -1,33 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from .v1 import ( - V1Resource, - AsyncV1Resource, - V1ResourceWithRawResponse, - AsyncV1ResourceWithRawResponse, - V1ResourceWithStreamingResponse, - AsyncV1ResourceWithStreamingResponse, -) -from .database import ( - DatabaseResource, - AsyncDatabaseResource, - DatabaseResourceWithRawResponse, - AsyncDatabaseResourceWithRawResponse, - DatabaseResourceWithStreamingResponse, - AsyncDatabaseResourceWithStreamingResponse, -) - -__all__ = [ - "V1Resource", - "AsyncV1Resource", - "V1ResourceWithRawResponse", - "AsyncV1ResourceWithRawResponse", - "V1ResourceWithStreamingResponse", - "AsyncV1ResourceWithStreamingResponse", - "DatabaseResource", - "AsyncDatabaseResource", - "DatabaseResourceWithRawResponse", - "AsyncDatabaseResourceWithRawResponse", - "DatabaseResourceWithStreamingResponse", - "AsyncDatabaseResourceWithStreamingResponse", -] diff --git a/src/casedev/resources/database/database.py b/src/casedev/resources/database/database.py deleted file mode 100644 index 7c1f0e2f..00000000 --- a/src/casedev/resources/database/database.py +++ /dev/null @@ -1,108 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from __future__ import annotations - -from .v1.v1 import ( - V1Resource, - AsyncV1Resource, - V1ResourceWithRawResponse, - AsyncV1ResourceWithRawResponse, - V1ResourceWithStreamingResponse, - AsyncV1ResourceWithStreamingResponse, -) -from ..._compat import cached_property -from ..._resource import SyncAPIResource, AsyncAPIResource - -__all__ = ["DatabaseResource", "AsyncDatabaseResource"] - - -class DatabaseResource(SyncAPIResource): - @cached_property - def v1(self) -> V1Resource: - """Serverless PostgreSQL databases with instant branching""" - return V1Resource(self._client) - - @cached_property - def with_raw_response(self) -> DatabaseResourceWithRawResponse: - """ - This property can be used as a prefix for any HTTP method call to return - the raw response object instead of the parsed content. - - For more information, see https://www.github.com/CaseMark/casedev-python#accessing-raw-response-data-eg-headers - """ - return DatabaseResourceWithRawResponse(self) - - @cached_property - def with_streaming_response(self) -> DatabaseResourceWithStreamingResponse: - """ - An alternative to `.with_raw_response` that doesn't eagerly read the response body. - - For more information, see https://www.github.com/CaseMark/casedev-python#with_streaming_response - """ - return DatabaseResourceWithStreamingResponse(self) - - -class AsyncDatabaseResource(AsyncAPIResource): - @cached_property - def v1(self) -> AsyncV1Resource: - """Serverless PostgreSQL databases with instant branching""" - return AsyncV1Resource(self._client) - - @cached_property - def with_raw_response(self) -> AsyncDatabaseResourceWithRawResponse: - """ - This property can be used as a prefix for any HTTP method call to return - the raw response object instead of the parsed content. - - For more information, see https://www.github.com/CaseMark/casedev-python#accessing-raw-response-data-eg-headers - """ - return AsyncDatabaseResourceWithRawResponse(self) - - @cached_property - def with_streaming_response(self) -> AsyncDatabaseResourceWithStreamingResponse: - """ - An alternative to `.with_raw_response` that doesn't eagerly read the response body. - - For more information, see https://www.github.com/CaseMark/casedev-python#with_streaming_response - """ - return AsyncDatabaseResourceWithStreamingResponse(self) - - -class DatabaseResourceWithRawResponse: - def __init__(self, database: DatabaseResource) -> None: - self._database = database - - @cached_property - def v1(self) -> V1ResourceWithRawResponse: - """Serverless PostgreSQL databases with instant branching""" - return V1ResourceWithRawResponse(self._database.v1) - - -class AsyncDatabaseResourceWithRawResponse: - def __init__(self, database: AsyncDatabaseResource) -> None: - self._database = database - - @cached_property - def v1(self) -> AsyncV1ResourceWithRawResponse: - """Serverless PostgreSQL databases with instant branching""" - return AsyncV1ResourceWithRawResponse(self._database.v1) - - -class DatabaseResourceWithStreamingResponse: - def __init__(self, database: DatabaseResource) -> None: - self._database = database - - @cached_property - def v1(self) -> V1ResourceWithStreamingResponse: - """Serverless PostgreSQL databases with instant branching""" - return V1ResourceWithStreamingResponse(self._database.v1) - - -class AsyncDatabaseResourceWithStreamingResponse: - def __init__(self, database: AsyncDatabaseResource) -> None: - self._database = database - - @cached_property - def v1(self) -> AsyncV1ResourceWithStreamingResponse: - """Serverless PostgreSQL databases with instant branching""" - return AsyncV1ResourceWithStreamingResponse(self._database.v1) diff --git a/src/casedev/resources/database/v1/__init__.py b/src/casedev/resources/database/v1/__init__.py deleted file mode 100644 index 56e28d44..00000000 --- a/src/casedev/resources/database/v1/__init__.py +++ /dev/null @@ -1,33 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from .v1 import ( - V1Resource, - AsyncV1Resource, - V1ResourceWithRawResponse, - AsyncV1ResourceWithRawResponse, - V1ResourceWithStreamingResponse, - AsyncV1ResourceWithStreamingResponse, -) -from .projects import ( - ProjectsResource, - AsyncProjectsResource, - ProjectsResourceWithRawResponse, - AsyncProjectsResourceWithRawResponse, - ProjectsResourceWithStreamingResponse, - AsyncProjectsResourceWithStreamingResponse, -) - -__all__ = [ - "ProjectsResource", - "AsyncProjectsResource", - "ProjectsResourceWithRawResponse", - "AsyncProjectsResourceWithRawResponse", - "ProjectsResourceWithStreamingResponse", - "AsyncProjectsResourceWithStreamingResponse", - "V1Resource", - "AsyncV1Resource", - "V1ResourceWithRawResponse", - "AsyncV1ResourceWithRawResponse", - "V1ResourceWithStreamingResponse", - "AsyncV1ResourceWithStreamingResponse", -] diff --git a/src/casedev/resources/database/v1/projects.py b/src/casedev/resources/database/v1/projects.py deleted file mode 100644 index 8b33fa40..00000000 --- a/src/casedev/resources/database/v1/projects.py +++ /dev/null @@ -1,775 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from __future__ import annotations - -from typing_extensions import Literal - -import httpx - -from ...._types import Body, Omit, Query, Headers, NotGiven, omit, not_given -from ...._utils import path_template, maybe_transform, async_maybe_transform -from ...._compat import cached_property -from ...._resource import SyncAPIResource, AsyncAPIResource -from ...._response import ( - to_raw_response_wrapper, - to_streamed_response_wrapper, - async_to_raw_response_wrapper, - async_to_streamed_response_wrapper, -) -from ...._base_client import make_request_options -from ....types.database.v1 import project_create_params, project_create_branch_params, project_get_connection_params -from ....types.database.v1.project_list_response import ProjectListResponse -from ....types.database.v1.project_create_response import ProjectCreateResponse -from ....types.database.v1.project_delete_response import ProjectDeleteResponse -from ....types.database.v1.project_retrieve_response import ProjectRetrieveResponse -from ....types.database.v1.project_create_branch_response import ProjectCreateBranchResponse -from ....types.database.v1.project_list_branches_response import ProjectListBranchesResponse -from ....types.database.v1.project_get_connection_response import ProjectGetConnectionResponse - -__all__ = ["ProjectsResource", "AsyncProjectsResource"] - - -class ProjectsResource(SyncAPIResource): - """Serverless PostgreSQL databases with instant branching""" - - @cached_property - def with_raw_response(self) -> ProjectsResourceWithRawResponse: - """ - This property can be used as a prefix for any HTTP method call to return - the raw response object instead of the parsed content. - - For more information, see https://www.github.com/CaseMark/casedev-python#accessing-raw-response-data-eg-headers - """ - return ProjectsResourceWithRawResponse(self) - - @cached_property - def with_streaming_response(self) -> ProjectsResourceWithStreamingResponse: - """ - An alternative to `.with_raw_response` that doesn't eagerly read the response body. - - For more information, see https://www.github.com/CaseMark/casedev-python#with_streaming_response - """ - return ProjectsResourceWithStreamingResponse(self) - - def create( - self, - *, - name: str, - description: str | Omit = omit, - region: Literal[ - "aws-us-east-1", - "aws-us-east-2", - "aws-us-west-2", - "aws-eu-central-1", - "aws-eu-west-1", - "aws-eu-west-2", - "aws-ap-southeast-1", - "aws-ap-southeast-2", - ] - | Omit = omit, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> ProjectCreateResponse: - """Creates a new serverless Postgres database project powered by Neon. - - Includes - automatic scaling, connection pooling, and a default 'main' branch with 'neondb' - database. Supports branching for isolated dev/staging environments. Perfect for - case management applications, document workflows, and litigation support - systems. - - Args: - name: Project name (letters, numbers, hyphens, underscores only) - - description: Optional project description - - region: AWS region for database deployment - - extra_headers: Send extra headers - - extra_query: Add additional query parameters to the request - - extra_body: Add additional JSON properties to the request - - timeout: Override the client-level default timeout for this request, in seconds - """ - return self._post( - "/database/v1/projects", - body=maybe_transform( - { - "name": name, - "description": description, - "region": region, - }, - project_create_params.ProjectCreateParams, - ), - options=make_request_options( - extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout - ), - cast_to=ProjectCreateResponse, - ) - - def retrieve( - self, - id: str, - *, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> ProjectRetrieveResponse: - """ - Retrieves detailed information about a specific database project including - branches, databases, storage/compute metrics, connection host, and linked - deployments. Fetches live usage statistics from Neon API. - - Args: - extra_headers: Send extra headers - - extra_query: Add additional query parameters to the request - - extra_body: Add additional JSON properties to the request - - timeout: Override the client-level default timeout for this request, in seconds - """ - if not id: - raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") - return self._get( - path_template("/database/v1/projects/{id}", id=id), - options=make_request_options( - extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout - ), - cast_to=ProjectRetrieveResponse, - ) - - def list( - self, - *, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> ProjectListResponse: - """ - Retrieves all serverless Postgres database projects for the authenticated - organization. Includes storage and compute metrics, plus linked application - deployments and Compute instances. - """ - return self._get( - "/database/v1/projects", - options=make_request_options( - extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout - ), - cast_to=ProjectListResponse, - ) - - def delete( - self, - id: str, - *, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> ProjectDeleteResponse: - """ - Permanently deletes a database project from Neon and marks it as deleted in - Case.dev. This action cannot be undone and will destroy all data including - branches and databases. Use with caution. - - Args: - extra_headers: Send extra headers - - extra_query: Add additional query parameters to the request - - extra_body: Add additional JSON properties to the request - - timeout: Override the client-level default timeout for this request, in seconds - """ - if not id: - raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") - return self._delete( - path_template("/database/v1/projects/{id}", id=id), - options=make_request_options( - extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout - ), - cast_to=ProjectDeleteResponse, - ) - - def create_branch( - self, - id: str, - *, - name: str, - parent_branch_id: str | Omit = omit, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> ProjectCreateBranchResponse: - """Creates a new branch from the specified parent branch (or default 'main' - branch). - - Branches provide instant point-in-time clones of your database for - isolated development, staging, testing, or feature work. Perfect for testing - schema changes, running migrations safely, or creating ephemeral preview - environments. - - Args: - name: Branch name (letters, numbers, hyphens, underscores only) - - parent_branch_id: Parent branch ID to clone from (defaults to main branch) - - extra_headers: Send extra headers - - extra_query: Add additional query parameters to the request - - extra_body: Add additional JSON properties to the request - - timeout: Override the client-level default timeout for this request, in seconds - """ - if not id: - raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") - return self._post( - path_template("/database/v1/projects/{id}/branches", id=id), - body=maybe_transform( - { - "name": name, - "parent_branch_id": parent_branch_id, - }, - project_create_branch_params.ProjectCreateBranchParams, - ), - options=make_request_options( - extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout - ), - cast_to=ProjectCreateBranchResponse, - ) - - def get_connection( - self, - id: str, - *, - branch: str | Omit = omit, - pooled: bool | Omit = omit, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> ProjectGetConnectionResponse: - """Retrieves the PostgreSQL connection URI for a database project. - - Supports - selecting specific branches and pooled vs direct connections. Connection strings - include credentials and should be stored securely. Use for configuring - applications and deployment environments. - - Args: - branch: Branch name (defaults to 'main') - - pooled: Use pooled connection (PgBouncer) - - extra_headers: Send extra headers - - extra_query: Add additional query parameters to the request - - extra_body: Add additional JSON properties to the request - - timeout: Override the client-level default timeout for this request, in seconds - """ - if not id: - raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") - return self._get( - path_template("/database/v1/projects/{id}/connection", id=id), - options=make_request_options( - extra_headers=extra_headers, - extra_query=extra_query, - extra_body=extra_body, - timeout=timeout, - query=maybe_transform( - { - "branch": branch, - "pooled": pooled, - }, - project_get_connection_params.ProjectGetConnectionParams, - ), - ), - cast_to=ProjectGetConnectionResponse, - ) - - def list_branches( - self, - id: str, - *, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> ProjectListBranchesResponse: - """Retrieves all branches for a database project. - - Branches enable isolated - development and testing environments with instant point-in-time cloning. Each - branch includes the default branch and any custom branches created for staging, - testing, or feature development. - - Args: - extra_headers: Send extra headers - - extra_query: Add additional query parameters to the request - - extra_body: Add additional JSON properties to the request - - timeout: Override the client-level default timeout for this request, in seconds - """ - if not id: - raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") - return self._get( - path_template("/database/v1/projects/{id}/branches", id=id), - options=make_request_options( - extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout - ), - cast_to=ProjectListBranchesResponse, - ) - - -class AsyncProjectsResource(AsyncAPIResource): - """Serverless PostgreSQL databases with instant branching""" - - @cached_property - def with_raw_response(self) -> AsyncProjectsResourceWithRawResponse: - """ - This property can be used as a prefix for any HTTP method call to return - the raw response object instead of the parsed content. - - For more information, see https://www.github.com/CaseMark/casedev-python#accessing-raw-response-data-eg-headers - """ - return AsyncProjectsResourceWithRawResponse(self) - - @cached_property - def with_streaming_response(self) -> AsyncProjectsResourceWithStreamingResponse: - """ - An alternative to `.with_raw_response` that doesn't eagerly read the response body. - - For more information, see https://www.github.com/CaseMark/casedev-python#with_streaming_response - """ - return AsyncProjectsResourceWithStreamingResponse(self) - - async def create( - self, - *, - name: str, - description: str | Omit = omit, - region: Literal[ - "aws-us-east-1", - "aws-us-east-2", - "aws-us-west-2", - "aws-eu-central-1", - "aws-eu-west-1", - "aws-eu-west-2", - "aws-ap-southeast-1", - "aws-ap-southeast-2", - ] - | Omit = omit, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> ProjectCreateResponse: - """Creates a new serverless Postgres database project powered by Neon. - - Includes - automatic scaling, connection pooling, and a default 'main' branch with 'neondb' - database. Supports branching for isolated dev/staging environments. Perfect for - case management applications, document workflows, and litigation support - systems. - - Args: - name: Project name (letters, numbers, hyphens, underscores only) - - description: Optional project description - - region: AWS region for database deployment - - extra_headers: Send extra headers - - extra_query: Add additional query parameters to the request - - extra_body: Add additional JSON properties to the request - - timeout: Override the client-level default timeout for this request, in seconds - """ - return await self._post( - "/database/v1/projects", - body=await async_maybe_transform( - { - "name": name, - "description": description, - "region": region, - }, - project_create_params.ProjectCreateParams, - ), - options=make_request_options( - extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout - ), - cast_to=ProjectCreateResponse, - ) - - async def retrieve( - self, - id: str, - *, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> ProjectRetrieveResponse: - """ - Retrieves detailed information about a specific database project including - branches, databases, storage/compute metrics, connection host, and linked - deployments. Fetches live usage statistics from Neon API. - - Args: - extra_headers: Send extra headers - - extra_query: Add additional query parameters to the request - - extra_body: Add additional JSON properties to the request - - timeout: Override the client-level default timeout for this request, in seconds - """ - if not id: - raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") - return await self._get( - path_template("/database/v1/projects/{id}", id=id), - options=make_request_options( - extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout - ), - cast_to=ProjectRetrieveResponse, - ) - - async def list( - self, - *, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> ProjectListResponse: - """ - Retrieves all serverless Postgres database projects for the authenticated - organization. Includes storage and compute metrics, plus linked application - deployments and Compute instances. - """ - return await self._get( - "/database/v1/projects", - options=make_request_options( - extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout - ), - cast_to=ProjectListResponse, - ) - - async def delete( - self, - id: str, - *, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> ProjectDeleteResponse: - """ - Permanently deletes a database project from Neon and marks it as deleted in - Case.dev. This action cannot be undone and will destroy all data including - branches and databases. Use with caution. - - Args: - extra_headers: Send extra headers - - extra_query: Add additional query parameters to the request - - extra_body: Add additional JSON properties to the request - - timeout: Override the client-level default timeout for this request, in seconds - """ - if not id: - raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") - return await self._delete( - path_template("/database/v1/projects/{id}", id=id), - options=make_request_options( - extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout - ), - cast_to=ProjectDeleteResponse, - ) - - async def create_branch( - self, - id: str, - *, - name: str, - parent_branch_id: str | Omit = omit, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> ProjectCreateBranchResponse: - """Creates a new branch from the specified parent branch (or default 'main' - branch). - - Branches provide instant point-in-time clones of your database for - isolated development, staging, testing, or feature work. Perfect for testing - schema changes, running migrations safely, or creating ephemeral preview - environments. - - Args: - name: Branch name (letters, numbers, hyphens, underscores only) - - parent_branch_id: Parent branch ID to clone from (defaults to main branch) - - extra_headers: Send extra headers - - extra_query: Add additional query parameters to the request - - extra_body: Add additional JSON properties to the request - - timeout: Override the client-level default timeout for this request, in seconds - """ - if not id: - raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") - return await self._post( - path_template("/database/v1/projects/{id}/branches", id=id), - body=await async_maybe_transform( - { - "name": name, - "parent_branch_id": parent_branch_id, - }, - project_create_branch_params.ProjectCreateBranchParams, - ), - options=make_request_options( - extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout - ), - cast_to=ProjectCreateBranchResponse, - ) - - async def get_connection( - self, - id: str, - *, - branch: str | Omit = omit, - pooled: bool | Omit = omit, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> ProjectGetConnectionResponse: - """Retrieves the PostgreSQL connection URI for a database project. - - Supports - selecting specific branches and pooled vs direct connections. Connection strings - include credentials and should be stored securely. Use for configuring - applications and deployment environments. - - Args: - branch: Branch name (defaults to 'main') - - pooled: Use pooled connection (PgBouncer) - - extra_headers: Send extra headers - - extra_query: Add additional query parameters to the request - - extra_body: Add additional JSON properties to the request - - timeout: Override the client-level default timeout for this request, in seconds - """ - if not id: - raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") - return await self._get( - path_template("/database/v1/projects/{id}/connection", id=id), - options=make_request_options( - extra_headers=extra_headers, - extra_query=extra_query, - extra_body=extra_body, - timeout=timeout, - query=await async_maybe_transform( - { - "branch": branch, - "pooled": pooled, - }, - project_get_connection_params.ProjectGetConnectionParams, - ), - ), - cast_to=ProjectGetConnectionResponse, - ) - - async def list_branches( - self, - id: str, - *, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> ProjectListBranchesResponse: - """Retrieves all branches for a database project. - - Branches enable isolated - development and testing environments with instant point-in-time cloning. Each - branch includes the default branch and any custom branches created for staging, - testing, or feature development. - - Args: - extra_headers: Send extra headers - - extra_query: Add additional query parameters to the request - - extra_body: Add additional JSON properties to the request - - timeout: Override the client-level default timeout for this request, in seconds - """ - if not id: - raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") - return await self._get( - path_template("/database/v1/projects/{id}/branches", id=id), - options=make_request_options( - extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout - ), - cast_to=ProjectListBranchesResponse, - ) - - -class ProjectsResourceWithRawResponse: - def __init__(self, projects: ProjectsResource) -> None: - self._projects = projects - - self.create = to_raw_response_wrapper( - projects.create, - ) - self.retrieve = to_raw_response_wrapper( - projects.retrieve, - ) - self.list = to_raw_response_wrapper( - projects.list, - ) - self.delete = to_raw_response_wrapper( - projects.delete, - ) - self.create_branch = to_raw_response_wrapper( - projects.create_branch, - ) - self.get_connection = to_raw_response_wrapper( - projects.get_connection, - ) - self.list_branches = to_raw_response_wrapper( - projects.list_branches, - ) - - -class AsyncProjectsResourceWithRawResponse: - def __init__(self, projects: AsyncProjectsResource) -> None: - self._projects = projects - - self.create = async_to_raw_response_wrapper( - projects.create, - ) - self.retrieve = async_to_raw_response_wrapper( - projects.retrieve, - ) - self.list = async_to_raw_response_wrapper( - projects.list, - ) - self.delete = async_to_raw_response_wrapper( - projects.delete, - ) - self.create_branch = async_to_raw_response_wrapper( - projects.create_branch, - ) - self.get_connection = async_to_raw_response_wrapper( - projects.get_connection, - ) - self.list_branches = async_to_raw_response_wrapper( - projects.list_branches, - ) - - -class ProjectsResourceWithStreamingResponse: - def __init__(self, projects: ProjectsResource) -> None: - self._projects = projects - - self.create = to_streamed_response_wrapper( - projects.create, - ) - self.retrieve = to_streamed_response_wrapper( - projects.retrieve, - ) - self.list = to_streamed_response_wrapper( - projects.list, - ) - self.delete = to_streamed_response_wrapper( - projects.delete, - ) - self.create_branch = to_streamed_response_wrapper( - projects.create_branch, - ) - self.get_connection = to_streamed_response_wrapper( - projects.get_connection, - ) - self.list_branches = to_streamed_response_wrapper( - projects.list_branches, - ) - - -class AsyncProjectsResourceWithStreamingResponse: - def __init__(self, projects: AsyncProjectsResource) -> None: - self._projects = projects - - self.create = async_to_streamed_response_wrapper( - projects.create, - ) - self.retrieve = async_to_streamed_response_wrapper( - projects.retrieve, - ) - self.list = async_to_streamed_response_wrapper( - projects.list, - ) - self.delete = async_to_streamed_response_wrapper( - projects.delete, - ) - self.create_branch = async_to_streamed_response_wrapper( - projects.create_branch, - ) - self.get_connection = async_to_streamed_response_wrapper( - projects.get_connection, - ) - self.list_branches = async_to_streamed_response_wrapper( - projects.list_branches, - ) diff --git a/src/casedev/resources/database/v1/v1.py b/src/casedev/resources/database/v1/v1.py deleted file mode 100644 index 85259d30..00000000 --- a/src/casedev/resources/database/v1/v1.py +++ /dev/null @@ -1,185 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from __future__ import annotations - -import httpx - -from .projects import ( - ProjectsResource, - AsyncProjectsResource, - ProjectsResourceWithRawResponse, - AsyncProjectsResourceWithRawResponse, - ProjectsResourceWithStreamingResponse, - AsyncProjectsResourceWithStreamingResponse, -) -from ...._types import Body, Query, Headers, NotGiven, not_given -from ...._compat import cached_property -from ...._resource import SyncAPIResource, AsyncAPIResource -from ...._response import ( - to_raw_response_wrapper, - to_streamed_response_wrapper, - async_to_raw_response_wrapper, - async_to_streamed_response_wrapper, -) -from ...._base_client import make_request_options -from ....types.database.v1_get_usage_response import V1GetUsageResponse - -__all__ = ["V1Resource", "AsyncV1Resource"] - - -class V1Resource(SyncAPIResource): - """Serverless PostgreSQL databases with instant branching""" - - @cached_property - def projects(self) -> ProjectsResource: - """Serverless PostgreSQL databases with instant branching""" - return ProjectsResource(self._client) - - @cached_property - def with_raw_response(self) -> V1ResourceWithRawResponse: - """ - This property can be used as a prefix for any HTTP method call to return - the raw response object instead of the parsed content. - - For more information, see https://www.github.com/CaseMark/casedev-python#accessing-raw-response-data-eg-headers - """ - return V1ResourceWithRawResponse(self) - - @cached_property - def with_streaming_response(self) -> V1ResourceWithStreamingResponse: - """ - An alternative to `.with_raw_response` that doesn't eagerly read the response body. - - For more information, see https://www.github.com/CaseMark/casedev-python#with_streaming_response - """ - return V1ResourceWithStreamingResponse(self) - - def get_usage( - self, - *, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> V1GetUsageResponse: - """ - Returns detailed database usage statistics and billing information for the - current billing period. Includes compute hours, storage, data transfer, and - branch counts with associated costs broken down by project. - """ - return self._get( - "/database/v1/usage", - options=make_request_options( - extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout - ), - cast_to=V1GetUsageResponse, - ) - - -class AsyncV1Resource(AsyncAPIResource): - """Serverless PostgreSQL databases with instant branching""" - - @cached_property - def projects(self) -> AsyncProjectsResource: - """Serverless PostgreSQL databases with instant branching""" - return AsyncProjectsResource(self._client) - - @cached_property - def with_raw_response(self) -> AsyncV1ResourceWithRawResponse: - """ - This property can be used as a prefix for any HTTP method call to return - the raw response object instead of the parsed content. - - For more information, see https://www.github.com/CaseMark/casedev-python#accessing-raw-response-data-eg-headers - """ - return AsyncV1ResourceWithRawResponse(self) - - @cached_property - def with_streaming_response(self) -> AsyncV1ResourceWithStreamingResponse: - """ - An alternative to `.with_raw_response` that doesn't eagerly read the response body. - - For more information, see https://www.github.com/CaseMark/casedev-python#with_streaming_response - """ - return AsyncV1ResourceWithStreamingResponse(self) - - async def get_usage( - self, - *, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> V1GetUsageResponse: - """ - Returns detailed database usage statistics and billing information for the - current billing period. Includes compute hours, storage, data transfer, and - branch counts with associated costs broken down by project. - """ - return await self._get( - "/database/v1/usage", - options=make_request_options( - extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout - ), - cast_to=V1GetUsageResponse, - ) - - -class V1ResourceWithRawResponse: - def __init__(self, v1: V1Resource) -> None: - self._v1 = v1 - - self.get_usage = to_raw_response_wrapper( - v1.get_usage, - ) - - @cached_property - def projects(self) -> ProjectsResourceWithRawResponse: - """Serverless PostgreSQL databases with instant branching""" - return ProjectsResourceWithRawResponse(self._v1.projects) - - -class AsyncV1ResourceWithRawResponse: - def __init__(self, v1: AsyncV1Resource) -> None: - self._v1 = v1 - - self.get_usage = async_to_raw_response_wrapper( - v1.get_usage, - ) - - @cached_property - def projects(self) -> AsyncProjectsResourceWithRawResponse: - """Serverless PostgreSQL databases with instant branching""" - return AsyncProjectsResourceWithRawResponse(self._v1.projects) - - -class V1ResourceWithStreamingResponse: - def __init__(self, v1: V1Resource) -> None: - self._v1 = v1 - - self.get_usage = to_streamed_response_wrapper( - v1.get_usage, - ) - - @cached_property - def projects(self) -> ProjectsResourceWithStreamingResponse: - """Serverless PostgreSQL databases with instant branching""" - return ProjectsResourceWithStreamingResponse(self._v1.projects) - - -class AsyncV1ResourceWithStreamingResponse: - def __init__(self, v1: AsyncV1Resource) -> None: - self._v1 = v1 - - self.get_usage = async_to_streamed_response_wrapper( - v1.get_usage, - ) - - @cached_property - def projects(self) -> AsyncProjectsResourceWithStreamingResponse: - """Serverless PostgreSQL databases with instant branching""" - return AsyncProjectsResourceWithStreamingResponse(self._v1.projects) diff --git a/src/casedev/resources/document_templates/__init__.py b/src/casedev/resources/document_templates/__init__.py deleted file mode 100644 index 26ec550b..00000000 --- a/src/casedev/resources/document_templates/__init__.py +++ /dev/null @@ -1,33 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from .from_vault_object import ( - FromVaultObjectResource, - AsyncFromVaultObjectResource, - FromVaultObjectResourceWithRawResponse, - AsyncFromVaultObjectResourceWithRawResponse, - FromVaultObjectResourceWithStreamingResponse, - AsyncFromVaultObjectResourceWithStreamingResponse, -) -from .document_templates import ( - DocumentTemplatesResource, - AsyncDocumentTemplatesResource, - DocumentTemplatesResourceWithRawResponse, - AsyncDocumentTemplatesResourceWithRawResponse, - DocumentTemplatesResourceWithStreamingResponse, - AsyncDocumentTemplatesResourceWithStreamingResponse, -) - -__all__ = [ - "FromVaultObjectResource", - "AsyncFromVaultObjectResource", - "FromVaultObjectResourceWithRawResponse", - "AsyncFromVaultObjectResourceWithRawResponse", - "FromVaultObjectResourceWithStreamingResponse", - "AsyncFromVaultObjectResourceWithStreamingResponse", - "DocumentTemplatesResource", - "AsyncDocumentTemplatesResource", - "DocumentTemplatesResourceWithRawResponse", - "AsyncDocumentTemplatesResourceWithRawResponse", - "DocumentTemplatesResourceWithStreamingResponse", - "AsyncDocumentTemplatesResourceWithStreamingResponse", -] diff --git a/src/casedev/resources/document_templates/from_vault_object.py b/src/casedev/resources/document_templates/from_vault_object.py deleted file mode 100644 index fdebf262..00000000 --- a/src/casedev/resources/document_templates/from_vault_object.py +++ /dev/null @@ -1,136 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from __future__ import annotations - -import httpx - -from ..._types import Body, Query, Headers, NoneType, NotGiven, not_given -from ..._compat import cached_property -from ..._resource import SyncAPIResource, AsyncAPIResource -from ..._response import ( - to_raw_response_wrapper, - to_streamed_response_wrapper, - async_to_raw_response_wrapper, - async_to_streamed_response_wrapper, -) -from ..._base_client import make_request_options - -__all__ = ["FromVaultObjectResource", "AsyncFromVaultObjectResource"] - - -class FromVaultObjectResource(SyncAPIResource): - @cached_property - def with_raw_response(self) -> FromVaultObjectResourceWithRawResponse: - """ - This property can be used as a prefix for any HTTP method call to return - the raw response object instead of the parsed content. - - For more information, see https://www.github.com/CaseMark/casedev-python#accessing-raw-response-data-eg-headers - """ - return FromVaultObjectResourceWithRawResponse(self) - - @cached_property - def with_streaming_response(self) -> FromVaultObjectResourceWithStreamingResponse: - """ - An alternative to `.with_raw_response` that doesn't eagerly read the response body. - - For more information, see https://www.github.com/CaseMark/casedev-python#with_streaming_response - """ - return FromVaultObjectResourceWithStreamingResponse(self) - - def create( - self, - *, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> None: - """Promote vault object to document template""" - extra_headers = {"Accept": "*/*", **(extra_headers or {})} - return self._post( - "/document-templates/from-vault-object", - options=make_request_options( - extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout - ), - cast_to=NoneType, - ) - - -class AsyncFromVaultObjectResource(AsyncAPIResource): - @cached_property - def with_raw_response(self) -> AsyncFromVaultObjectResourceWithRawResponse: - """ - This property can be used as a prefix for any HTTP method call to return - the raw response object instead of the parsed content. - - For more information, see https://www.github.com/CaseMark/casedev-python#accessing-raw-response-data-eg-headers - """ - return AsyncFromVaultObjectResourceWithRawResponse(self) - - @cached_property - def with_streaming_response(self) -> AsyncFromVaultObjectResourceWithStreamingResponse: - """ - An alternative to `.with_raw_response` that doesn't eagerly read the response body. - - For more information, see https://www.github.com/CaseMark/casedev-python#with_streaming_response - """ - return AsyncFromVaultObjectResourceWithStreamingResponse(self) - - async def create( - self, - *, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> None: - """Promote vault object to document template""" - extra_headers = {"Accept": "*/*", **(extra_headers or {})} - return await self._post( - "/document-templates/from-vault-object", - options=make_request_options( - extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout - ), - cast_to=NoneType, - ) - - -class FromVaultObjectResourceWithRawResponse: - def __init__(self, from_vault_object: FromVaultObjectResource) -> None: - self._from_vault_object = from_vault_object - - self.create = to_raw_response_wrapper( - from_vault_object.create, - ) - - -class AsyncFromVaultObjectResourceWithRawResponse: - def __init__(self, from_vault_object: AsyncFromVaultObjectResource) -> None: - self._from_vault_object = from_vault_object - - self.create = async_to_raw_response_wrapper( - from_vault_object.create, - ) - - -class FromVaultObjectResourceWithStreamingResponse: - def __init__(self, from_vault_object: FromVaultObjectResource) -> None: - self._from_vault_object = from_vault_object - - self.create = to_streamed_response_wrapper( - from_vault_object.create, - ) - - -class AsyncFromVaultObjectResourceWithStreamingResponse: - def __init__(self, from_vault_object: AsyncFromVaultObjectResource) -> None: - self._from_vault_object = from_vault_object - - self.create = async_to_streamed_response_wrapper( - from_vault_object.create, - ) diff --git a/src/casedev/resources/format/__init__.py b/src/casedev/resources/format/__init__.py deleted file mode 100644 index c3ff26ae..00000000 --- a/src/casedev/resources/format/__init__.py +++ /dev/null @@ -1,33 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from .v1 import ( - V1Resource, - AsyncV1Resource, - V1ResourceWithRawResponse, - AsyncV1ResourceWithRawResponse, - V1ResourceWithStreamingResponse, - AsyncV1ResourceWithStreamingResponse, -) -from .format import ( - FormatResource, - AsyncFormatResource, - FormatResourceWithRawResponse, - AsyncFormatResourceWithRawResponse, - FormatResourceWithStreamingResponse, - AsyncFormatResourceWithStreamingResponse, -) - -__all__ = [ - "V1Resource", - "AsyncV1Resource", - "V1ResourceWithRawResponse", - "AsyncV1ResourceWithRawResponse", - "V1ResourceWithStreamingResponse", - "AsyncV1ResourceWithStreamingResponse", - "FormatResource", - "AsyncFormatResource", - "FormatResourceWithRawResponse", - "AsyncFormatResourceWithRawResponse", - "FormatResourceWithStreamingResponse", - "AsyncFormatResourceWithStreamingResponse", -] diff --git a/src/casedev/resources/format/format.py b/src/casedev/resources/format/format.py deleted file mode 100644 index e3c7ea24..00000000 --- a/src/casedev/resources/format/format.py +++ /dev/null @@ -1,108 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from __future__ import annotations - -from .v1.v1 import ( - V1Resource, - AsyncV1Resource, - V1ResourceWithRawResponse, - AsyncV1ResourceWithRawResponse, - V1ResourceWithStreamingResponse, - AsyncV1ResourceWithStreamingResponse, -) -from ..._compat import cached_property -from ..._resource import SyncAPIResource, AsyncAPIResource - -__all__ = ["FormatResource", "AsyncFormatResource"] - - -class FormatResource(SyncAPIResource): - @cached_property - def v1(self) -> V1Resource: - """Document formatting and template rendering (MD/JSON to PDF/DOCX)""" - return V1Resource(self._client) - - @cached_property - def with_raw_response(self) -> FormatResourceWithRawResponse: - """ - This property can be used as a prefix for any HTTP method call to return - the raw response object instead of the parsed content. - - For more information, see https://www.github.com/CaseMark/casedev-python#accessing-raw-response-data-eg-headers - """ - return FormatResourceWithRawResponse(self) - - @cached_property - def with_streaming_response(self) -> FormatResourceWithStreamingResponse: - """ - An alternative to `.with_raw_response` that doesn't eagerly read the response body. - - For more information, see https://www.github.com/CaseMark/casedev-python#with_streaming_response - """ - return FormatResourceWithStreamingResponse(self) - - -class AsyncFormatResource(AsyncAPIResource): - @cached_property - def v1(self) -> AsyncV1Resource: - """Document formatting and template rendering (MD/JSON to PDF/DOCX)""" - return AsyncV1Resource(self._client) - - @cached_property - def with_raw_response(self) -> AsyncFormatResourceWithRawResponse: - """ - This property can be used as a prefix for any HTTP method call to return - the raw response object instead of the parsed content. - - For more information, see https://www.github.com/CaseMark/casedev-python#accessing-raw-response-data-eg-headers - """ - return AsyncFormatResourceWithRawResponse(self) - - @cached_property - def with_streaming_response(self) -> AsyncFormatResourceWithStreamingResponse: - """ - An alternative to `.with_raw_response` that doesn't eagerly read the response body. - - For more information, see https://www.github.com/CaseMark/casedev-python#with_streaming_response - """ - return AsyncFormatResourceWithStreamingResponse(self) - - -class FormatResourceWithRawResponse: - def __init__(self, format: FormatResource) -> None: - self._format = format - - @cached_property - def v1(self) -> V1ResourceWithRawResponse: - """Document formatting and template rendering (MD/JSON to PDF/DOCX)""" - return V1ResourceWithRawResponse(self._format.v1) - - -class AsyncFormatResourceWithRawResponse: - def __init__(self, format: AsyncFormatResource) -> None: - self._format = format - - @cached_property - def v1(self) -> AsyncV1ResourceWithRawResponse: - """Document formatting and template rendering (MD/JSON to PDF/DOCX)""" - return AsyncV1ResourceWithRawResponse(self._format.v1) - - -class FormatResourceWithStreamingResponse: - def __init__(self, format: FormatResource) -> None: - self._format = format - - @cached_property - def v1(self) -> V1ResourceWithStreamingResponse: - """Document formatting and template rendering (MD/JSON to PDF/DOCX)""" - return V1ResourceWithStreamingResponse(self._format.v1) - - -class AsyncFormatResourceWithStreamingResponse: - def __init__(self, format: AsyncFormatResource) -> None: - self._format = format - - @cached_property - def v1(self) -> AsyncV1ResourceWithStreamingResponse: - """Document formatting and template rendering (MD/JSON to PDF/DOCX)""" - return AsyncV1ResourceWithStreamingResponse(self._format.v1) diff --git a/src/casedev/resources/format/v1/__init__.py b/src/casedev/resources/format/v1/__init__.py deleted file mode 100644 index 368db88d..00000000 --- a/src/casedev/resources/format/v1/__init__.py +++ /dev/null @@ -1,33 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from .v1 import ( - V1Resource, - AsyncV1Resource, - V1ResourceWithRawResponse, - AsyncV1ResourceWithRawResponse, - V1ResourceWithStreamingResponse, - AsyncV1ResourceWithStreamingResponse, -) -from .templates import ( - TemplatesResource, - AsyncTemplatesResource, - TemplatesResourceWithRawResponse, - AsyncTemplatesResourceWithRawResponse, - TemplatesResourceWithStreamingResponse, - AsyncTemplatesResourceWithStreamingResponse, -) - -__all__ = [ - "TemplatesResource", - "AsyncTemplatesResource", - "TemplatesResourceWithRawResponse", - "AsyncTemplatesResourceWithRawResponse", - "TemplatesResourceWithStreamingResponse", - "AsyncTemplatesResourceWithStreamingResponse", - "V1Resource", - "AsyncV1Resource", - "V1ResourceWithRawResponse", - "AsyncV1ResourceWithRawResponse", - "V1ResourceWithStreamingResponse", - "AsyncV1ResourceWithStreamingResponse", -] diff --git a/src/casedev/resources/format/v1/templates.py b/src/casedev/resources/format/v1/templates.py deleted file mode 100644 index 09364955..00000000 --- a/src/casedev/resources/format/v1/templates.py +++ /dev/null @@ -1,421 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from __future__ import annotations - -from typing_extensions import Literal - -import httpx - -from ...._types import Body, Omit, Query, Headers, NotGiven, SequenceNotStr, omit, not_given -from ...._utils import path_template, maybe_transform, async_maybe_transform -from ...._compat import cached_property -from ...._resource import SyncAPIResource, AsyncAPIResource -from ...._response import ( - to_raw_response_wrapper, - to_streamed_response_wrapper, - async_to_raw_response_wrapper, - async_to_streamed_response_wrapper, -) -from ...._base_client import make_request_options -from ....types.format.v1 import template_list_params, template_create_params -from ....types.format.v1.template_list_response import TemplateListResponse -from ....types.format.v1.template_create_response import TemplateCreateResponse -from ....types.format.v1.template_retrieve_response import TemplateRetrieveResponse - -__all__ = ["TemplatesResource", "AsyncTemplatesResource"] - - -class TemplatesResource(SyncAPIResource): - """Document formatting and template rendering (MD/JSON to PDF/DOCX)""" - - @cached_property - def with_raw_response(self) -> TemplatesResourceWithRawResponse: - """ - This property can be used as a prefix for any HTTP method call to return - the raw response object instead of the parsed content. - - For more information, see https://www.github.com/CaseMark/casedev-python#accessing-raw-response-data-eg-headers - """ - return TemplatesResourceWithRawResponse(self) - - @cached_property - def with_streaming_response(self) -> TemplatesResourceWithStreamingResponse: - """ - An alternative to `.with_raw_response` that doesn't eagerly read the response body. - - For more information, see https://www.github.com/CaseMark/casedev-python#with_streaming_response - """ - return TemplatesResourceWithStreamingResponse(self) - - def create( - self, - *, - content: str, - name: str, - type: Literal["caption", "signature", "letterhead", "certificate", "footer", "custom"], - description: str | Omit = omit, - styles: object | Omit = omit, - tags: SequenceNotStr[str] | Omit = omit, - variables: SequenceNotStr[str] | Omit = omit, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> TemplateCreateResponse: - """Create a new format template for document formatting. - - Templates support - variables using `{{variable}}` syntax and can be used for captions, signatures, - letterheads, certificates, footers, or custom formatting needs. - - Args: - content: Template content with {{variable}} placeholders - - name: Template name - - type: Template type - - description: Template description - - styles: CSS styles for the template - - tags: Template tags for organization - - variables: Template variables (auto-detected if not provided) - - extra_headers: Send extra headers - - extra_query: Add additional query parameters to the request - - extra_body: Add additional JSON properties to the request - - timeout: Override the client-level default timeout for this request, in seconds - """ - return self._post( - "/format/v1/templates", - body=maybe_transform( - { - "content": content, - "name": name, - "type": type, - "description": description, - "styles": styles, - "tags": tags, - "variables": variables, - }, - template_create_params.TemplateCreateParams, - ), - options=make_request_options( - extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout - ), - cast_to=TemplateCreateResponse, - ) - - def retrieve( - self, - id: str, - *, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> TemplateRetrieveResponse: - """Retrieve a specific document format template by ID. - - Format templates define how - documents should be structured and formatted for specific legal use cases such - as contracts, briefs, or pleadings. - - Args: - extra_headers: Send extra headers - - extra_query: Add additional query parameters to the request - - extra_body: Add additional JSON properties to the request - - timeout: Override the client-level default timeout for this request, in seconds - """ - if not id: - raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") - return self._get( - path_template("/format/v1/templates/{id}", id=id), - options=make_request_options( - extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout - ), - cast_to=TemplateRetrieveResponse, - ) - - def list( - self, - *, - type: str | Omit = omit, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> TemplateListResponse: - """Retrieve all format templates for the organization. - - Templates define reusable - document formatting patterns with customizable variables for consistent legal - document generation. - - Filter by type to get specific template categories like contracts, pleadings, or - correspondence. - - Args: - type: Filter templates by type (e.g., contract, pleading, letter) - - extra_headers: Send extra headers - - extra_query: Add additional query parameters to the request - - extra_body: Add additional JSON properties to the request - - timeout: Override the client-level default timeout for this request, in seconds - """ - return self._get( - "/format/v1/templates", - options=make_request_options( - extra_headers=extra_headers, - extra_query=extra_query, - extra_body=extra_body, - timeout=timeout, - query=maybe_transform({"type": type}, template_list_params.TemplateListParams), - ), - cast_to=TemplateListResponse, - ) - - -class AsyncTemplatesResource(AsyncAPIResource): - """Document formatting and template rendering (MD/JSON to PDF/DOCX)""" - - @cached_property - def with_raw_response(self) -> AsyncTemplatesResourceWithRawResponse: - """ - This property can be used as a prefix for any HTTP method call to return - the raw response object instead of the parsed content. - - For more information, see https://www.github.com/CaseMark/casedev-python#accessing-raw-response-data-eg-headers - """ - return AsyncTemplatesResourceWithRawResponse(self) - - @cached_property - def with_streaming_response(self) -> AsyncTemplatesResourceWithStreamingResponse: - """ - An alternative to `.with_raw_response` that doesn't eagerly read the response body. - - For more information, see https://www.github.com/CaseMark/casedev-python#with_streaming_response - """ - return AsyncTemplatesResourceWithStreamingResponse(self) - - async def create( - self, - *, - content: str, - name: str, - type: Literal["caption", "signature", "letterhead", "certificate", "footer", "custom"], - description: str | Omit = omit, - styles: object | Omit = omit, - tags: SequenceNotStr[str] | Omit = omit, - variables: SequenceNotStr[str] | Omit = omit, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> TemplateCreateResponse: - """Create a new format template for document formatting. - - Templates support - variables using `{{variable}}` syntax and can be used for captions, signatures, - letterheads, certificates, footers, or custom formatting needs. - - Args: - content: Template content with {{variable}} placeholders - - name: Template name - - type: Template type - - description: Template description - - styles: CSS styles for the template - - tags: Template tags for organization - - variables: Template variables (auto-detected if not provided) - - extra_headers: Send extra headers - - extra_query: Add additional query parameters to the request - - extra_body: Add additional JSON properties to the request - - timeout: Override the client-level default timeout for this request, in seconds - """ - return await self._post( - "/format/v1/templates", - body=await async_maybe_transform( - { - "content": content, - "name": name, - "type": type, - "description": description, - "styles": styles, - "tags": tags, - "variables": variables, - }, - template_create_params.TemplateCreateParams, - ), - options=make_request_options( - extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout - ), - cast_to=TemplateCreateResponse, - ) - - async def retrieve( - self, - id: str, - *, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> TemplateRetrieveResponse: - """Retrieve a specific document format template by ID. - - Format templates define how - documents should be structured and formatted for specific legal use cases such - as contracts, briefs, or pleadings. - - Args: - extra_headers: Send extra headers - - extra_query: Add additional query parameters to the request - - extra_body: Add additional JSON properties to the request - - timeout: Override the client-level default timeout for this request, in seconds - """ - if not id: - raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") - return await self._get( - path_template("/format/v1/templates/{id}", id=id), - options=make_request_options( - extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout - ), - cast_to=TemplateRetrieveResponse, - ) - - async def list( - self, - *, - type: str | Omit = omit, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> TemplateListResponse: - """Retrieve all format templates for the organization. - - Templates define reusable - document formatting patterns with customizable variables for consistent legal - document generation. - - Filter by type to get specific template categories like contracts, pleadings, or - correspondence. - - Args: - type: Filter templates by type (e.g., contract, pleading, letter) - - extra_headers: Send extra headers - - extra_query: Add additional query parameters to the request - - extra_body: Add additional JSON properties to the request - - timeout: Override the client-level default timeout for this request, in seconds - """ - return await self._get( - "/format/v1/templates", - options=make_request_options( - extra_headers=extra_headers, - extra_query=extra_query, - extra_body=extra_body, - timeout=timeout, - query=await async_maybe_transform({"type": type}, template_list_params.TemplateListParams), - ), - cast_to=TemplateListResponse, - ) - - -class TemplatesResourceWithRawResponse: - def __init__(self, templates: TemplatesResource) -> None: - self._templates = templates - - self.create = to_raw_response_wrapper( - templates.create, - ) - self.retrieve = to_raw_response_wrapper( - templates.retrieve, - ) - self.list = to_raw_response_wrapper( - templates.list, - ) - - -class AsyncTemplatesResourceWithRawResponse: - def __init__(self, templates: AsyncTemplatesResource) -> None: - self._templates = templates - - self.create = async_to_raw_response_wrapper( - templates.create, - ) - self.retrieve = async_to_raw_response_wrapper( - templates.retrieve, - ) - self.list = async_to_raw_response_wrapper( - templates.list, - ) - - -class TemplatesResourceWithStreamingResponse: - def __init__(self, templates: TemplatesResource) -> None: - self._templates = templates - - self.create = to_streamed_response_wrapper( - templates.create, - ) - self.retrieve = to_streamed_response_wrapper( - templates.retrieve, - ) - self.list = to_streamed_response_wrapper( - templates.list, - ) - - -class AsyncTemplatesResourceWithStreamingResponse: - def __init__(self, templates: AsyncTemplatesResource) -> None: - self._templates = templates - - self.create = async_to_streamed_response_wrapper( - templates.create, - ) - self.retrieve = async_to_streamed_response_wrapper( - templates.retrieve, - ) - self.list = async_to_streamed_response_wrapper( - templates.list, - ) diff --git a/src/casedev/resources/format/v1/v1.py b/src/casedev/resources/format/v1/v1.py deleted file mode 100644 index 166fe1ce..00000000 --- a/src/casedev/resources/format/v1/v1.py +++ /dev/null @@ -1,260 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from __future__ import annotations - -from typing_extensions import Literal - -import httpx - -from ...._types import Body, Omit, Query, Headers, NotGiven, omit, not_given -from ...._utils import maybe_transform, async_maybe_transform -from .templates import ( - TemplatesResource, - AsyncTemplatesResource, - TemplatesResourceWithRawResponse, - AsyncTemplatesResourceWithRawResponse, - TemplatesResourceWithStreamingResponse, - AsyncTemplatesResourceWithStreamingResponse, -) -from ...._compat import cached_property -from ...._resource import SyncAPIResource, AsyncAPIResource -from ...._response import ( - BinaryAPIResponse, - AsyncBinaryAPIResponse, - StreamedBinaryAPIResponse, - AsyncStreamedBinaryAPIResponse, - to_custom_raw_response_wrapper, - to_custom_streamed_response_wrapper, - async_to_custom_raw_response_wrapper, - async_to_custom_streamed_response_wrapper, -) -from ...._base_client import make_request_options -from ....types.format import v1_create_document_params - -__all__ = ["V1Resource", "AsyncV1Resource"] - - -class V1Resource(SyncAPIResource): - """Document formatting and template rendering (MD/JSON to PDF/DOCX)""" - - @cached_property - def templates(self) -> TemplatesResource: - """Document formatting and template rendering (MD/JSON to PDF/DOCX)""" - return TemplatesResource(self._client) - - @cached_property - def with_raw_response(self) -> V1ResourceWithRawResponse: - """ - This property can be used as a prefix for any HTTP method call to return - the raw response object instead of the parsed content. - - For more information, see https://www.github.com/CaseMark/casedev-python#accessing-raw-response-data-eg-headers - """ - return V1ResourceWithRawResponse(self) - - @cached_property - def with_streaming_response(self) -> V1ResourceWithStreamingResponse: - """ - An alternative to `.with_raw_response` that doesn't eagerly read the response body. - - For more information, see https://www.github.com/CaseMark/casedev-python#with_streaming_response - """ - return V1ResourceWithStreamingResponse(self) - - def create_document( - self, - *, - content: str, - output_format: Literal["pdf", "docx", "html_preview"], - input_format: Literal["md", "json", "text"] | Omit = omit, - options: v1_create_document_params.Options | Omit = omit, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> BinaryAPIResponse: - """ - Convert Markdown, JSON, or text content to professionally formatted PDF, DOCX, - or HTML documents. Supports template components with variable interpolation for - creating consistent legal documents like contracts, briefs, and reports. - - Args: - content: The source content to format - - output_format: Desired output format - - input_format: Format of the input content - - options: Optional template composition and styling settings used during document - generation - - extra_headers: Send extra headers - - extra_query: Add additional query parameters to the request - - extra_body: Add additional JSON properties to the request - - timeout: Override the client-level default timeout for this request, in seconds - """ - extra_headers = {"Accept": "application/pdf", **(extra_headers or {})} - return self._post( - "/format/v1/document", - body=maybe_transform( - { - "content": content, - "output_format": output_format, - "input_format": input_format, - "options": options, - }, - v1_create_document_params.V1CreateDocumentParams, - ), - options=make_request_options( - extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout - ), - cast_to=BinaryAPIResponse, - ) - - -class AsyncV1Resource(AsyncAPIResource): - """Document formatting and template rendering (MD/JSON to PDF/DOCX)""" - - @cached_property - def templates(self) -> AsyncTemplatesResource: - """Document formatting and template rendering (MD/JSON to PDF/DOCX)""" - return AsyncTemplatesResource(self._client) - - @cached_property - def with_raw_response(self) -> AsyncV1ResourceWithRawResponse: - """ - This property can be used as a prefix for any HTTP method call to return - the raw response object instead of the parsed content. - - For more information, see https://www.github.com/CaseMark/casedev-python#accessing-raw-response-data-eg-headers - """ - return AsyncV1ResourceWithRawResponse(self) - - @cached_property - def with_streaming_response(self) -> AsyncV1ResourceWithStreamingResponse: - """ - An alternative to `.with_raw_response` that doesn't eagerly read the response body. - - For more information, see https://www.github.com/CaseMark/casedev-python#with_streaming_response - """ - return AsyncV1ResourceWithStreamingResponse(self) - - async def create_document( - self, - *, - content: str, - output_format: Literal["pdf", "docx", "html_preview"], - input_format: Literal["md", "json", "text"] | Omit = omit, - options: v1_create_document_params.Options | Omit = omit, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> AsyncBinaryAPIResponse: - """ - Convert Markdown, JSON, or text content to professionally formatted PDF, DOCX, - or HTML documents. Supports template components with variable interpolation for - creating consistent legal documents like contracts, briefs, and reports. - - Args: - content: The source content to format - - output_format: Desired output format - - input_format: Format of the input content - - options: Optional template composition and styling settings used during document - generation - - extra_headers: Send extra headers - - extra_query: Add additional query parameters to the request - - extra_body: Add additional JSON properties to the request - - timeout: Override the client-level default timeout for this request, in seconds - """ - extra_headers = {"Accept": "application/pdf", **(extra_headers or {})} - return await self._post( - "/format/v1/document", - body=await async_maybe_transform( - { - "content": content, - "output_format": output_format, - "input_format": input_format, - "options": options, - }, - v1_create_document_params.V1CreateDocumentParams, - ), - options=make_request_options( - extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout - ), - cast_to=AsyncBinaryAPIResponse, - ) - - -class V1ResourceWithRawResponse: - def __init__(self, v1: V1Resource) -> None: - self._v1 = v1 - - self.create_document = to_custom_raw_response_wrapper( - v1.create_document, - BinaryAPIResponse, - ) - - @cached_property - def templates(self) -> TemplatesResourceWithRawResponse: - """Document formatting and template rendering (MD/JSON to PDF/DOCX)""" - return TemplatesResourceWithRawResponse(self._v1.templates) - - -class AsyncV1ResourceWithRawResponse: - def __init__(self, v1: AsyncV1Resource) -> None: - self._v1 = v1 - - self.create_document = async_to_custom_raw_response_wrapper( - v1.create_document, - AsyncBinaryAPIResponse, - ) - - @cached_property - def templates(self) -> AsyncTemplatesResourceWithRawResponse: - """Document formatting and template rendering (MD/JSON to PDF/DOCX)""" - return AsyncTemplatesResourceWithRawResponse(self._v1.templates) - - -class V1ResourceWithStreamingResponse: - def __init__(self, v1: V1Resource) -> None: - self._v1 = v1 - - self.create_document = to_custom_streamed_response_wrapper( - v1.create_document, - StreamedBinaryAPIResponse, - ) - - @cached_property - def templates(self) -> TemplatesResourceWithStreamingResponse: - """Document formatting and template rendering (MD/JSON to PDF/DOCX)""" - return TemplatesResourceWithStreamingResponse(self._v1.templates) - - -class AsyncV1ResourceWithStreamingResponse: - def __init__(self, v1: AsyncV1Resource) -> None: - self._v1 = v1 - - self.create_document = async_to_custom_streamed_response_wrapper( - v1.create_document, - AsyncStreamedBinaryAPIResponse, - ) - - @cached_property - def templates(self) -> AsyncTemplatesResourceWithStreamingResponse: - """Document formatting and template rendering (MD/JSON to PDF/DOCX)""" - return AsyncTemplatesResourceWithStreamingResponse(self._v1.templates) diff --git a/src/casedev/resources/legal/v1.py b/src/casedev/resources/legal/v1.py index 92f34cc6..6775550c 100644 --- a/src/casedev/resources/legal/v1.py +++ b/src/casedev/resources/legal/v1.py @@ -2,7 +2,7 @@ from __future__ import annotations -from typing import Union, Optional +from typing import Union from datetime import date from typing_extensions import Literal @@ -20,7 +20,6 @@ ) from ...types.legal import ( v1_find_params, - v1_draft_params, v1_docket_params, v1_verify_params, v1_similar_params, @@ -36,7 +35,6 @@ ) from ..._base_client import make_request_options from ...types.legal.v1_find_response import V1FindResponse -from ...types.legal.v1_draft_response import V1DraftResponse from ...types.legal.v1_docket_response import V1DocketResponse from ...types.legal.v1_verify_response import V1VerifyResponse from ...types.legal.v1_similar_response import V1SimilarResponse @@ -124,7 +122,8 @@ def docket( acknowledgePacerFees: true. PACER charges up to $3.00 per docket sheet plus a $0.05 service fee. Only valid with type: "lookup". - offset: Offset for search results or entry list + offset: Offset for search results or entry list (maximum 200 when including lookup + entries) query: Case name or party name search query (required for search) @@ -160,87 +159,6 @@ def docket( cast_to=V1DocketResponse, ) - def draft( - self, - *, - instructions: str, - vault_id: str, - citations: bool | Omit = omit, - format: Optional[str] | Omit = omit, - length: Optional[v1_draft_params.Length] | Omit = omit, - model: Optional[str] | Omit = omit, - object_ids: Optional[SequenceNotStr[str]] | Omit = omit, - output_name: Optional[str] | Omit = omit, - output_type: Literal["pdf", "docx", "xlsx", "pptx", "md"] | Omit = omit, - verified: bool | Omit = omit, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> V1DraftResponse: - """Generate a legal document with structured inputs. - - Powered by an agent that - handles research, formatting, citation verification, and vault upload. Returns a - run ID for polling. - - Args: - instructions: What to draft — the core task. E.g., "Motion to compel defendant to produce - discovery responses" - - vault_id: Vault ID where the final document will be uploaded - - citations: Research and include legal citations - - format: Court or jurisdiction formatting hint. Triggers a legal-skills search. E.g., - "California Superior Court", "SDNY", "federal pleading" - - length: Target document length - - model: LLM model override. Defaults to anthropic/claude-sonnet-4.6 - - object_ids: Vault object IDs to use as source/reference documents - - output_name: Filename for the output document. Auto-generated if omitted. - - output_type: Output file format - - verified: Verify all citations in a loop — re-run verification and repair bad citations - until they pass - - extra_headers: Send extra headers - - extra_query: Add additional query parameters to the request - - extra_body: Add additional JSON properties to the request - - timeout: Override the client-level default timeout for this request, in seconds - """ - return self._post( - "/legal/v1/draft", - body=maybe_transform( - { - "instructions": instructions, - "vault_id": vault_id, - "citations": citations, - "format": format, - "length": length, - "model": model, - "object_ids": object_ids, - "output_name": output_name, - "output_type": output_type, - "verified": verified, - }, - v1_draft_params.V1DraftParams, - ), - options=make_request_options( - extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout - ), - cast_to=V1DraftResponse, - ) - def find( self, *, @@ -948,7 +866,8 @@ async def docket( acknowledgePacerFees: true. PACER charges up to $3.00 per docket sheet plus a $0.05 service fee. Only valid with type: "lookup". - offset: Offset for search results or entry list + offset: Offset for search results or entry list (maximum 200 when including lookup + entries) query: Case name or party name search query (required for search) @@ -984,87 +903,6 @@ async def docket( cast_to=V1DocketResponse, ) - async def draft( - self, - *, - instructions: str, - vault_id: str, - citations: bool | Omit = omit, - format: Optional[str] | Omit = omit, - length: Optional[v1_draft_params.Length] | Omit = omit, - model: Optional[str] | Omit = omit, - object_ids: Optional[SequenceNotStr[str]] | Omit = omit, - output_name: Optional[str] | Omit = omit, - output_type: Literal["pdf", "docx", "xlsx", "pptx", "md"] | Omit = omit, - verified: bool | Omit = omit, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> V1DraftResponse: - """Generate a legal document with structured inputs. - - Powered by an agent that - handles research, formatting, citation verification, and vault upload. Returns a - run ID for polling. - - Args: - instructions: What to draft — the core task. E.g., "Motion to compel defendant to produce - discovery responses" - - vault_id: Vault ID where the final document will be uploaded - - citations: Research and include legal citations - - format: Court or jurisdiction formatting hint. Triggers a legal-skills search. E.g., - "California Superior Court", "SDNY", "federal pleading" - - length: Target document length - - model: LLM model override. Defaults to anthropic/claude-sonnet-4.6 - - object_ids: Vault object IDs to use as source/reference documents - - output_name: Filename for the output document. Auto-generated if omitted. - - output_type: Output file format - - verified: Verify all citations in a loop — re-run verification and repair bad citations - until they pass - - extra_headers: Send extra headers - - extra_query: Add additional query parameters to the request - - extra_body: Add additional JSON properties to the request - - timeout: Override the client-level default timeout for this request, in seconds - """ - return await self._post( - "/legal/v1/draft", - body=await async_maybe_transform( - { - "instructions": instructions, - "vault_id": vault_id, - "citations": citations, - "format": format, - "length": length, - "model": model, - "object_ids": object_ids, - "output_name": output_name, - "output_type": output_type, - "verified": verified, - }, - v1_draft_params.V1DraftParams, - ), - options=make_request_options( - extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout - ), - cast_to=V1DraftResponse, - ) - async def find( self, *, @@ -1710,9 +1548,6 @@ def __init__(self, v1: V1Resource) -> None: self.docket = to_raw_response_wrapper( v1.docket, ) - self.draft = to_raw_response_wrapper( - v1.draft, - ) self.find = to_raw_response_wrapper( v1.find, ) @@ -1758,9 +1593,6 @@ def __init__(self, v1: AsyncV1Resource) -> None: self.docket = async_to_raw_response_wrapper( v1.docket, ) - self.draft = async_to_raw_response_wrapper( - v1.draft, - ) self.find = async_to_raw_response_wrapper( v1.find, ) @@ -1806,9 +1638,6 @@ def __init__(self, v1: V1Resource) -> None: self.docket = to_streamed_response_wrapper( v1.docket, ) - self.draft = to_streamed_response_wrapper( - v1.draft, - ) self.find = to_streamed_response_wrapper( v1.find, ) @@ -1854,9 +1683,6 @@ def __init__(self, v1: AsyncV1Resource) -> None: self.docket = async_to_streamed_response_wrapper( v1.docket, ) - self.draft = async_to_streamed_response_wrapper( - v1.draft, - ) self.find = async_to_streamed_response_wrapper( v1.find, ) diff --git a/src/casedev/resources/linc/v1/sessions.py b/src/casedev/resources/linc/v1/sessions.py index dd5f33e0..4a9ce336 100644 --- a/src/casedev/resources/linc/v1/sessions.py +++ b/src/casedev/resources/linc/v1/sessions.py @@ -3,6 +3,7 @@ from __future__ import annotations from typing import Iterable, Optional +from typing_extensions import Literal import httpx @@ -18,6 +19,7 @@ ) from ...._base_client import make_request_options from ....types.linc.v1 import ( + session_cancel_params, session_create_params, session_send_rpc_params, session_ingest_events_params, @@ -29,9 +31,7 @@ class SessionsResource(SyncAPIResource): - """ - Create, manage, and execute AI agents with tool access, sandbox environments, and async run workflows - """ + """Durable, stateful legal agent sessions with sandboxed tools and files""" @cached_property def with_raw_response(self) -> SessionsResourceWithRawResponse: @@ -61,6 +61,7 @@ def create( instructions: Optional[str] | Omit = omit, model: Optional[str] | Omit = omit, scoped_api_key: Optional[str] | Omit = omit, + service_tier: Literal["default", "priority"] | Omit = omit, skill_slugs: Optional[SequenceNotStr[str]] | Omit = omit, title: str | Omit = omit, vault_ids: Optional[SequenceNotStr[str]] | Omit = omit, @@ -87,6 +88,9 @@ def create( scoped_api_key: Optional caller-provided scoped Case.dev API key for the runtime. + service_tier: Processing tier for eligible OpenAI GPT models. Priority provides lower latency + at premium cost. + skill_slugs: Skills API slugs to install into the runtime sandbox before the native session starts. @@ -109,6 +113,7 @@ def create( "instructions": instructions, "model": model, "scoped_api_key": scoped_api_key, + "service_tier": service_tier, "skill_slugs": skill_slugs, "title": title, "vault_ids": vault_ids, @@ -159,6 +164,7 @@ def cancel( self, id: str, *, + clear_queue: bool | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, @@ -167,9 +173,19 @@ def cancel( timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> None: """ - Cancel native Linc session turn + Sends an abort RPC to the session runtime, ending the current turn while keeping + the session alive. Body handling is intentionally lenient — cancel is a stop + control, so unknown fields are ignored and an invalid or missing body is treated + as empty rather than rejected. Args: + clear_queue: Also clear queued steering/follow-up messages so the abort leaves the agent + fully idle. Cleared texts are returned in the `response.data.clearedQueue` field + of the response body. Without it, messages still queued when the abort settles + are auto-continued as a new run. Runtimes older than the Linc release that + supports this flag ignore it: the abort still happens but the queue is left + untouched. + extra_headers: Send extra headers extra_query: Add additional query parameters to the request @@ -183,6 +199,7 @@ def cancel( extra_headers = {"Accept": "*/*", **(extra_headers or {})} return self._post( path_template("/linc/v1/sessions/{id}/cancel", id=id), + body=maybe_transform({"clear_queue": clear_queue}, session_cancel_params.SessionCancelParams), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -430,9 +447,7 @@ def send_rpc( class AsyncSessionsResource(AsyncAPIResource): - """ - Create, manage, and execute AI agents with tool access, sandbox environments, and async run workflows - """ + """Durable, stateful legal agent sessions with sandboxed tools and files""" @cached_property def with_raw_response(self) -> AsyncSessionsResourceWithRawResponse: @@ -462,6 +477,7 @@ async def create( instructions: Optional[str] | Omit = omit, model: Optional[str] | Omit = omit, scoped_api_key: Optional[str] | Omit = omit, + service_tier: Literal["default", "priority"] | Omit = omit, skill_slugs: Optional[SequenceNotStr[str]] | Omit = omit, title: str | Omit = omit, vault_ids: Optional[SequenceNotStr[str]] | Omit = omit, @@ -488,6 +504,9 @@ async def create( scoped_api_key: Optional caller-provided scoped Case.dev API key for the runtime. + service_tier: Processing tier for eligible OpenAI GPT models. Priority provides lower latency + at premium cost. + skill_slugs: Skills API slugs to install into the runtime sandbox before the native session starts. @@ -510,6 +529,7 @@ async def create( "instructions": instructions, "model": model, "scoped_api_key": scoped_api_key, + "service_tier": service_tier, "skill_slugs": skill_slugs, "title": title, "vault_ids": vault_ids, @@ -560,6 +580,7 @@ async def cancel( self, id: str, *, + clear_queue: bool | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, @@ -568,9 +589,19 @@ async def cancel( timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> None: """ - Cancel native Linc session turn + Sends an abort RPC to the session runtime, ending the current turn while keeping + the session alive. Body handling is intentionally lenient — cancel is a stop + control, so unknown fields are ignored and an invalid or missing body is treated + as empty rather than rejected. Args: + clear_queue: Also clear queued steering/follow-up messages so the abort leaves the agent + fully idle. Cleared texts are returned in the `response.data.clearedQueue` field + of the response body. Without it, messages still queued when the abort settles + are auto-continued as a new run. Runtimes older than the Linc release that + supports this flag ignore it: the abort still happens but the queue is left + untouched. + extra_headers: Send extra headers extra_query: Add additional query parameters to the request @@ -584,6 +615,7 @@ async def cancel( extra_headers = {"Accept": "*/*", **(extra_headers or {})} return await self._post( path_template("/linc/v1/sessions/{id}/cancel", id=id), + body=await async_maybe_transform({"clear_queue": clear_queue}, session_cancel_params.SessionCancelParams), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), diff --git a/src/casedev/resources/linc/v1/v1.py b/src/casedev/resources/linc/v1/v1.py index 88df7a3f..6e356c43 100644 --- a/src/casedev/resources/linc/v1/v1.py +++ b/src/casedev/resources/linc/v1/v1.py @@ -19,9 +19,7 @@ class V1Resource(SyncAPIResource): @cached_property def sessions(self) -> SessionsResource: - """ - Create, manage, and execute AI agents with tool access, sandbox environments, and async run workflows - """ + """Durable, stateful legal agent sessions with sandboxed tools and files""" return SessionsResource(self._client) @cached_property @@ -47,9 +45,7 @@ def with_streaming_response(self) -> V1ResourceWithStreamingResponse: class AsyncV1Resource(AsyncAPIResource): @cached_property def sessions(self) -> AsyncSessionsResource: - """ - Create, manage, and execute AI agents with tool access, sandbox environments, and async run workflows - """ + """Durable, stateful legal agent sessions with sandboxed tools and files""" return AsyncSessionsResource(self._client) @cached_property @@ -78,9 +74,7 @@ def __init__(self, v1: V1Resource) -> None: @cached_property def sessions(self) -> SessionsResourceWithRawResponse: - """ - Create, manage, and execute AI agents with tool access, sandbox environments, and async run workflows - """ + """Durable, stateful legal agent sessions with sandboxed tools and files""" return SessionsResourceWithRawResponse(self._v1.sessions) @@ -90,9 +84,7 @@ def __init__(self, v1: AsyncV1Resource) -> None: @cached_property def sessions(self) -> AsyncSessionsResourceWithRawResponse: - """ - Create, manage, and execute AI agents with tool access, sandbox environments, and async run workflows - """ + """Durable, stateful legal agent sessions with sandboxed tools and files""" return AsyncSessionsResourceWithRawResponse(self._v1.sessions) @@ -102,9 +94,7 @@ def __init__(self, v1: V1Resource) -> None: @cached_property def sessions(self) -> SessionsResourceWithStreamingResponse: - """ - Create, manage, and execute AI agents with tool access, sandbox environments, and async run workflows - """ + """Durable, stateful legal agent sessions with sandboxed tools and files""" return SessionsResourceWithStreamingResponse(self._v1.sessions) @@ -114,7 +104,5 @@ def __init__(self, v1: AsyncV1Resource) -> None: @cached_property def sessions(self) -> AsyncSessionsResourceWithStreamingResponse: - """ - Create, manage, and execute AI agents with tool access, sandbox environments, and async run workflows - """ + """Durable, stateful legal agent sessions with sandboxed tools and files""" return AsyncSessionsResourceWithStreamingResponse(self._v1.sessions) diff --git a/src/casedev/resources/llm/v1/chat.py b/src/casedev/resources/llm/v1/chat.py index 10f4bde3..55a9d098 100644 --- a/src/casedev/resources/llm/v1/chat.py +++ b/src/casedev/resources/llm/v1/chat.py @@ -74,8 +74,9 @@ def create_completion( Args: messages: List of messages comprising the conversation - casemark_show_reasoning: CaseMark-only: when true, allows reasoning fields in responses. Defaults to - false (reasoning is suppressed). + casemark_show_reasoning: CaseMark-only: controls whether reasoning fields appear in responses. Defaults + to false (suppressed) for most CaseMark models; defaults to true for + casemark/core-potassium. frequency_penalty: Frequency penalty parameter @@ -173,8 +174,9 @@ async def create_completion( Args: messages: List of messages comprising the conversation - casemark_show_reasoning: CaseMark-only: when true, allows reasoning fields in responses. Defaults to - false (reasoning is suppressed). + casemark_show_reasoning: CaseMark-only: controls whether reasoning fields appear in responses. Defaults + to false (suppressed) for most CaseMark models; defaults to true for + casemark/core-potassium. frequency_penalty: Frequency penalty parameter diff --git a/src/casedev/resources/mail/__init__.py b/src/casedev/resources/mail/__init__.py deleted file mode 100644 index 35f6ebf0..00000000 --- a/src/casedev/resources/mail/__init__.py +++ /dev/null @@ -1,33 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from .v1 import ( - V1Resource, - AsyncV1Resource, - V1ResourceWithRawResponse, - AsyncV1ResourceWithRawResponse, - V1ResourceWithStreamingResponse, - AsyncV1ResourceWithStreamingResponse, -) -from .mail import ( - MailResource, - AsyncMailResource, - MailResourceWithRawResponse, - AsyncMailResourceWithRawResponse, - MailResourceWithStreamingResponse, - AsyncMailResourceWithStreamingResponse, -) - -__all__ = [ - "V1Resource", - "AsyncV1Resource", - "V1ResourceWithRawResponse", - "AsyncV1ResourceWithRawResponse", - "V1ResourceWithStreamingResponse", - "AsyncV1ResourceWithStreamingResponse", - "MailResource", - "AsyncMailResource", - "MailResourceWithRawResponse", - "AsyncMailResourceWithRawResponse", - "MailResourceWithStreamingResponse", - "AsyncMailResourceWithStreamingResponse", -] diff --git a/src/casedev/resources/mail/mail.py b/src/casedev/resources/mail/mail.py deleted file mode 100644 index c97214b9..00000000 --- a/src/casedev/resources/mail/mail.py +++ /dev/null @@ -1,102 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from __future__ import annotations - -from .v1.v1 import ( - V1Resource, - AsyncV1Resource, - V1ResourceWithRawResponse, - AsyncV1ResourceWithRawResponse, - V1ResourceWithStreamingResponse, - AsyncV1ResourceWithStreamingResponse, -) -from ..._compat import cached_property -from ..._resource import SyncAPIResource, AsyncAPIResource - -__all__ = ["MailResource", "AsyncMailResource"] - - -class MailResource(SyncAPIResource): - @cached_property - def v1(self) -> V1Resource: - return V1Resource(self._client) - - @cached_property - def with_raw_response(self) -> MailResourceWithRawResponse: - """ - This property can be used as a prefix for any HTTP method call to return - the raw response object instead of the parsed content. - - For more information, see https://www.github.com/CaseMark/casedev-python#accessing-raw-response-data-eg-headers - """ - return MailResourceWithRawResponse(self) - - @cached_property - def with_streaming_response(self) -> MailResourceWithStreamingResponse: - """ - An alternative to `.with_raw_response` that doesn't eagerly read the response body. - - For more information, see https://www.github.com/CaseMark/casedev-python#with_streaming_response - """ - return MailResourceWithStreamingResponse(self) - - -class AsyncMailResource(AsyncAPIResource): - @cached_property - def v1(self) -> AsyncV1Resource: - return AsyncV1Resource(self._client) - - @cached_property - def with_raw_response(self) -> AsyncMailResourceWithRawResponse: - """ - This property can be used as a prefix for any HTTP method call to return - the raw response object instead of the parsed content. - - For more information, see https://www.github.com/CaseMark/casedev-python#accessing-raw-response-data-eg-headers - """ - return AsyncMailResourceWithRawResponse(self) - - @cached_property - def with_streaming_response(self) -> AsyncMailResourceWithStreamingResponse: - """ - An alternative to `.with_raw_response` that doesn't eagerly read the response body. - - For more information, see https://www.github.com/CaseMark/casedev-python#with_streaming_response - """ - return AsyncMailResourceWithStreamingResponse(self) - - -class MailResourceWithRawResponse: - def __init__(self, mail: MailResource) -> None: - self._mail = mail - - @cached_property - def v1(self) -> V1ResourceWithRawResponse: - return V1ResourceWithRawResponse(self._mail.v1) - - -class AsyncMailResourceWithRawResponse: - def __init__(self, mail: AsyncMailResource) -> None: - self._mail = mail - - @cached_property - def v1(self) -> AsyncV1ResourceWithRawResponse: - return AsyncV1ResourceWithRawResponse(self._mail.v1) - - -class MailResourceWithStreamingResponse: - def __init__(self, mail: MailResource) -> None: - self._mail = mail - - @cached_property - def v1(self) -> V1ResourceWithStreamingResponse: - return V1ResourceWithStreamingResponse(self._mail.v1) - - -class AsyncMailResourceWithStreamingResponse: - def __init__(self, mail: AsyncMailResource) -> None: - self._mail = mail - - @cached_property - def v1(self) -> AsyncV1ResourceWithStreamingResponse: - return AsyncV1ResourceWithStreamingResponse(self._mail.v1) diff --git a/src/casedev/resources/mail/v1/__init__.py b/src/casedev/resources/mail/v1/__init__.py deleted file mode 100644 index fd8876c6..00000000 --- a/src/casedev/resources/mail/v1/__init__.py +++ /dev/null @@ -1,33 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from .v1 import ( - V1Resource, - AsyncV1Resource, - V1ResourceWithRawResponse, - AsyncV1ResourceWithRawResponse, - V1ResourceWithStreamingResponse, - AsyncV1ResourceWithStreamingResponse, -) -from .inboxes import ( - InboxesResource, - AsyncInboxesResource, - InboxesResourceWithRawResponse, - AsyncInboxesResourceWithRawResponse, - InboxesResourceWithStreamingResponse, - AsyncInboxesResourceWithStreamingResponse, -) - -__all__ = [ - "InboxesResource", - "AsyncInboxesResource", - "InboxesResourceWithRawResponse", - "AsyncInboxesResourceWithRawResponse", - "InboxesResourceWithStreamingResponse", - "AsyncInboxesResourceWithStreamingResponse", - "V1Resource", - "AsyncV1Resource", - "V1ResourceWithRawResponse", - "AsyncV1ResourceWithRawResponse", - "V1ResourceWithStreamingResponse", - "AsyncV1ResourceWithStreamingResponse", -] diff --git a/src/casedev/resources/mail/v1/inboxes.py b/src/casedev/resources/mail/v1/inboxes.py deleted file mode 100644 index 70027683..00000000 --- a/src/casedev/resources/mail/v1/inboxes.py +++ /dev/null @@ -1,1052 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from __future__ import annotations - -import httpx - -from ...._types import Body, Omit, Query, Headers, NoneType, NotGiven, SequenceNotStr, omit, not_given -from ...._utils import path_template, maybe_transform, async_maybe_transform -from ...._compat import cached_property -from ...._resource import SyncAPIResource, AsyncAPIResource -from ...._response import ( - to_raw_response_wrapper, - to_streamed_response_wrapper, - async_to_raw_response_wrapper, - async_to_streamed_response_wrapper, -) -from ...._base_client import make_request_options -from ....types.mail.v1 import inbox_create_params, inbox_set_policy_params - -__all__ = ["InboxesResource", "AsyncInboxesResource"] - - -class InboxesResource(SyncAPIResource): - """Managed inboxes for agent email workflows""" - - @cached_property - def with_raw_response(self) -> InboxesResourceWithRawResponse: - """ - This property can be used as a prefix for any HTTP method call to return - the raw response object instead of the parsed content. - - For more information, see https://www.github.com/CaseMark/casedev-python#accessing-raw-response-data-eg-headers - """ - return InboxesResourceWithRawResponse(self) - - @cached_property - def with_streaming_response(self) -> InboxesResourceWithStreamingResponse: - """ - An alternative to `.with_raw_response` that doesn't eagerly read the response body. - - For more information, see https://www.github.com/CaseMark/casedev-python#with_streaming_response - """ - return InboxesResourceWithStreamingResponse(self) - - def create( - self, - *, - address: str | Omit = omit, - display_name: str | Omit = omit, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> None: - """ - Create an inbox owned by the authenticated organization. - - Args: - extra_headers: Send extra headers - - extra_query: Add additional query parameters to the request - - extra_body: Add additional JSON properties to the request - - timeout: Override the client-level default timeout for this request, in seconds - """ - extra_headers = {"Accept": "*/*", **(extra_headers or {})} - return self._post( - "/mail/v1/inboxes", - body=maybe_transform( - { - "address": address, - "display_name": display_name, - }, - inbox_create_params.InboxCreateParams, - ), - options=make_request_options( - extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout - ), - cast_to=NoneType, - ) - - def retrieve( - self, - inbox_id: str, - *, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> None: - """ - Get an inbox owned by the authenticated organization. - - Args: - extra_headers: Send extra headers - - extra_query: Add additional query parameters to the request - - extra_body: Add additional JSON properties to the request - - timeout: Override the client-level default timeout for this request, in seconds - """ - if not inbox_id: - raise ValueError(f"Expected a non-empty value for `inbox_id` but received {inbox_id!r}") - extra_headers = {"Accept": "*/*", **(extra_headers or {})} - return self._get( - path_template("/mail/v1/inboxes/{inbox_id}", inbox_id=inbox_id), - options=make_request_options( - extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout - ), - cast_to=NoneType, - ) - - def list( - self, - *, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> None: - """List inboxes owned by the authenticated organization.""" - extra_headers = {"Accept": "*/*", **(extra_headers or {})} - return self._get( - "/mail/v1/inboxes", - options=make_request_options( - extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout - ), - cast_to=NoneType, - ) - - def delete( - self, - inbox_id: str, - *, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> None: - """ - Delete an inbox owned by the authenticated organization. - - Args: - extra_headers: Send extra headers - - extra_query: Add additional query parameters to the request - - extra_body: Add additional JSON properties to the request - - timeout: Override the client-level default timeout for this request, in seconds - """ - if not inbox_id: - raise ValueError(f"Expected a non-empty value for `inbox_id` but received {inbox_id!r}") - extra_headers = {"Accept": "*/*", **(extra_headers or {})} - return self._delete( - path_template("/mail/v1/inboxes/{inbox_id}", inbox_id=inbox_id), - options=make_request_options( - extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout - ), - cast_to=NoneType, - ) - - def get_attachment( - self, - attachment_id: str, - *, - inbox_id: str, - message_id: str, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> None: - """ - Get attachment metadata for a message in an inbox owned by the authenticated - organization. - - Args: - extra_headers: Send extra headers - - extra_query: Add additional query parameters to the request - - extra_body: Add additional JSON properties to the request - - timeout: Override the client-level default timeout for this request, in seconds - """ - if not inbox_id: - raise ValueError(f"Expected a non-empty value for `inbox_id` but received {inbox_id!r}") - if not message_id: - raise ValueError(f"Expected a non-empty value for `message_id` but received {message_id!r}") - if not attachment_id: - raise ValueError(f"Expected a non-empty value for `attachment_id` but received {attachment_id!r}") - extra_headers = {"Accept": "*/*", **(extra_headers or {})} - return self._get( - path_template( - "/mail/v1/inboxes/{inbox_id}/messages/{message_id}/attachments/{attachment_id}", - inbox_id=inbox_id, - message_id=message_id, - attachment_id=attachment_id, - ), - options=make_request_options( - extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout - ), - cast_to=NoneType, - ) - - def get_message( - self, - message_id: str, - *, - inbox_id: str, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> None: - """ - Get a message for an inbox owned by the authenticated organization. - - Args: - extra_headers: Send extra headers - - extra_query: Add additional query parameters to the request - - extra_body: Add additional JSON properties to the request - - timeout: Override the client-level default timeout for this request, in seconds - """ - if not inbox_id: - raise ValueError(f"Expected a non-empty value for `inbox_id` but received {inbox_id!r}") - if not message_id: - raise ValueError(f"Expected a non-empty value for `message_id` but received {message_id!r}") - extra_headers = {"Accept": "*/*", **(extra_headers or {})} - return self._get( - path_template( - "/mail/v1/inboxes/{inbox_id}/messages/{message_id}", inbox_id=inbox_id, message_id=message_id - ), - options=make_request_options( - extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout - ), - cast_to=NoneType, - ) - - def get_policy( - self, - inbox_id: str, - *, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> None: - """ - Get the sender allowlist and send/reply/read access rules for an inbox owned by - the authenticated organization. - - Args: - extra_headers: Send extra headers - - extra_query: Add additional query parameters to the request - - extra_body: Add additional JSON properties to the request - - timeout: Override the client-level default timeout for this request, in seconds - """ - if not inbox_id: - raise ValueError(f"Expected a non-empty value for `inbox_id` but received {inbox_id!r}") - extra_headers = {"Accept": "*/*", **(extra_headers or {})} - return self._get( - path_template("/mail/v1/inboxes/{inbox_id}/policy", inbox_id=inbox_id), - options=make_request_options( - extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout - ), - cast_to=NoneType, - ) - - def list_messages( - self, - inbox_id: str, - *, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> None: - """ - List messages for an inbox owned by the authenticated organization. - - Args: - extra_headers: Send extra headers - - extra_query: Add additional query parameters to the request - - extra_body: Add additional JSON properties to the request - - timeout: Override the client-level default timeout for this request, in seconds - """ - if not inbox_id: - raise ValueError(f"Expected a non-empty value for `inbox_id` but received {inbox_id!r}") - extra_headers = {"Accept": "*/*", **(extra_headers or {})} - return self._get( - path_template("/mail/v1/inboxes/{inbox_id}/messages", inbox_id=inbox_id), - options=make_request_options( - extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout - ), - cast_to=NoneType, - ) - - def reply( - self, - message_id: str, - *, - inbox_id: str, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> None: - """ - Reply to a message in an inbox owned by the authenticated organization. - - Args: - extra_headers: Send extra headers - - extra_query: Add additional query parameters to the request - - extra_body: Add additional JSON properties to the request - - timeout: Override the client-level default timeout for this request, in seconds - """ - if not inbox_id: - raise ValueError(f"Expected a non-empty value for `inbox_id` but received {inbox_id!r}") - if not message_id: - raise ValueError(f"Expected a non-empty value for `message_id` but received {message_id!r}") - extra_headers = {"Accept": "*/*", **(extra_headers or {})} - return self._post( - path_template( - "/mail/v1/inboxes/{inbox_id}/messages/{message_id}/reply", inbox_id=inbox_id, message_id=message_id - ), - options=make_request_options( - extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout - ), - cast_to=NoneType, - ) - - def send( - self, - inbox_id: str, - *, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> None: - """ - Send a message from an inbox owned by the authenticated organization. - - Args: - extra_headers: Send extra headers - - extra_query: Add additional query parameters to the request - - extra_body: Add additional JSON properties to the request - - timeout: Override the client-level default timeout for this request, in seconds - """ - if not inbox_id: - raise ValueError(f"Expected a non-empty value for `inbox_id` but received {inbox_id!r}") - extra_headers = {"Accept": "*/*", **(extra_headers or {})} - return self._post( - path_template("/mail/v1/inboxes/{inbox_id}/messages/send", inbox_id=inbox_id), - options=make_request_options( - extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout - ), - cast_to=NoneType, - ) - - def set_policy( - self, - inbox_id: str, - *, - allowed_sender_patterns: SequenceNotStr[str] | Omit = omit, - enforce_sender_allowlist: bool | Omit = omit, - read_access_rules: SequenceNotStr[str] | Omit = omit, - reply_access_rules: SequenceNotStr[str] | Omit = omit, - send_access_rules: SequenceNotStr[str] | Omit = omit, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> None: - """ - Set the sender allowlist and send/reply/read access rules for an inbox owned by - the authenticated organization. - - Args: - allowed_sender_patterns: Exact emails, @domain rules, or \\** - - read_access_rules: Rules like organization, operator, user:, api_key, api_key:, - clerk_session, or \\** - - reply_access_rules: Rules like organization, operator, user:, api_key, api_key:, - clerk_session, or \\** - - send_access_rules: Rules like organization, user:, api_key, api_key:, clerk_session, or \\** - - extra_headers: Send extra headers - - extra_query: Add additional query parameters to the request - - extra_body: Add additional JSON properties to the request - - timeout: Override the client-level default timeout for this request, in seconds - """ - if not inbox_id: - raise ValueError(f"Expected a non-empty value for `inbox_id` but received {inbox_id!r}") - extra_headers = {"Accept": "*/*", **(extra_headers or {})} - return self._put( - path_template("/mail/v1/inboxes/{inbox_id}/policy", inbox_id=inbox_id), - body=maybe_transform( - { - "allowed_sender_patterns": allowed_sender_patterns, - "enforce_sender_allowlist": enforce_sender_allowlist, - "read_access_rules": read_access_rules, - "reply_access_rules": reply_access_rules, - "send_access_rules": send_access_rules, - }, - inbox_set_policy_params.InboxSetPolicyParams, - ), - options=make_request_options( - extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout - ), - cast_to=NoneType, - ) - - -class AsyncInboxesResource(AsyncAPIResource): - """Managed inboxes for agent email workflows""" - - @cached_property - def with_raw_response(self) -> AsyncInboxesResourceWithRawResponse: - """ - This property can be used as a prefix for any HTTP method call to return - the raw response object instead of the parsed content. - - For more information, see https://www.github.com/CaseMark/casedev-python#accessing-raw-response-data-eg-headers - """ - return AsyncInboxesResourceWithRawResponse(self) - - @cached_property - def with_streaming_response(self) -> AsyncInboxesResourceWithStreamingResponse: - """ - An alternative to `.with_raw_response` that doesn't eagerly read the response body. - - For more information, see https://www.github.com/CaseMark/casedev-python#with_streaming_response - """ - return AsyncInboxesResourceWithStreamingResponse(self) - - async def create( - self, - *, - address: str | Omit = omit, - display_name: str | Omit = omit, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> None: - """ - Create an inbox owned by the authenticated organization. - - Args: - extra_headers: Send extra headers - - extra_query: Add additional query parameters to the request - - extra_body: Add additional JSON properties to the request - - timeout: Override the client-level default timeout for this request, in seconds - """ - extra_headers = {"Accept": "*/*", **(extra_headers or {})} - return await self._post( - "/mail/v1/inboxes", - body=await async_maybe_transform( - { - "address": address, - "display_name": display_name, - }, - inbox_create_params.InboxCreateParams, - ), - options=make_request_options( - extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout - ), - cast_to=NoneType, - ) - - async def retrieve( - self, - inbox_id: str, - *, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> None: - """ - Get an inbox owned by the authenticated organization. - - Args: - extra_headers: Send extra headers - - extra_query: Add additional query parameters to the request - - extra_body: Add additional JSON properties to the request - - timeout: Override the client-level default timeout for this request, in seconds - """ - if not inbox_id: - raise ValueError(f"Expected a non-empty value for `inbox_id` but received {inbox_id!r}") - extra_headers = {"Accept": "*/*", **(extra_headers or {})} - return await self._get( - path_template("/mail/v1/inboxes/{inbox_id}", inbox_id=inbox_id), - options=make_request_options( - extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout - ), - cast_to=NoneType, - ) - - async def list( - self, - *, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> None: - """List inboxes owned by the authenticated organization.""" - extra_headers = {"Accept": "*/*", **(extra_headers or {})} - return await self._get( - "/mail/v1/inboxes", - options=make_request_options( - extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout - ), - cast_to=NoneType, - ) - - async def delete( - self, - inbox_id: str, - *, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> None: - """ - Delete an inbox owned by the authenticated organization. - - Args: - extra_headers: Send extra headers - - extra_query: Add additional query parameters to the request - - extra_body: Add additional JSON properties to the request - - timeout: Override the client-level default timeout for this request, in seconds - """ - if not inbox_id: - raise ValueError(f"Expected a non-empty value for `inbox_id` but received {inbox_id!r}") - extra_headers = {"Accept": "*/*", **(extra_headers or {})} - return await self._delete( - path_template("/mail/v1/inboxes/{inbox_id}", inbox_id=inbox_id), - options=make_request_options( - extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout - ), - cast_to=NoneType, - ) - - async def get_attachment( - self, - attachment_id: str, - *, - inbox_id: str, - message_id: str, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> None: - """ - Get attachment metadata for a message in an inbox owned by the authenticated - organization. - - Args: - extra_headers: Send extra headers - - extra_query: Add additional query parameters to the request - - extra_body: Add additional JSON properties to the request - - timeout: Override the client-level default timeout for this request, in seconds - """ - if not inbox_id: - raise ValueError(f"Expected a non-empty value for `inbox_id` but received {inbox_id!r}") - if not message_id: - raise ValueError(f"Expected a non-empty value for `message_id` but received {message_id!r}") - if not attachment_id: - raise ValueError(f"Expected a non-empty value for `attachment_id` but received {attachment_id!r}") - extra_headers = {"Accept": "*/*", **(extra_headers or {})} - return await self._get( - path_template( - "/mail/v1/inboxes/{inbox_id}/messages/{message_id}/attachments/{attachment_id}", - inbox_id=inbox_id, - message_id=message_id, - attachment_id=attachment_id, - ), - options=make_request_options( - extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout - ), - cast_to=NoneType, - ) - - async def get_message( - self, - message_id: str, - *, - inbox_id: str, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> None: - """ - Get a message for an inbox owned by the authenticated organization. - - Args: - extra_headers: Send extra headers - - extra_query: Add additional query parameters to the request - - extra_body: Add additional JSON properties to the request - - timeout: Override the client-level default timeout for this request, in seconds - """ - if not inbox_id: - raise ValueError(f"Expected a non-empty value for `inbox_id` but received {inbox_id!r}") - if not message_id: - raise ValueError(f"Expected a non-empty value for `message_id` but received {message_id!r}") - extra_headers = {"Accept": "*/*", **(extra_headers or {})} - return await self._get( - path_template( - "/mail/v1/inboxes/{inbox_id}/messages/{message_id}", inbox_id=inbox_id, message_id=message_id - ), - options=make_request_options( - extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout - ), - cast_to=NoneType, - ) - - async def get_policy( - self, - inbox_id: str, - *, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> None: - """ - Get the sender allowlist and send/reply/read access rules for an inbox owned by - the authenticated organization. - - Args: - extra_headers: Send extra headers - - extra_query: Add additional query parameters to the request - - extra_body: Add additional JSON properties to the request - - timeout: Override the client-level default timeout for this request, in seconds - """ - if not inbox_id: - raise ValueError(f"Expected a non-empty value for `inbox_id` but received {inbox_id!r}") - extra_headers = {"Accept": "*/*", **(extra_headers or {})} - return await self._get( - path_template("/mail/v1/inboxes/{inbox_id}/policy", inbox_id=inbox_id), - options=make_request_options( - extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout - ), - cast_to=NoneType, - ) - - async def list_messages( - self, - inbox_id: str, - *, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> None: - """ - List messages for an inbox owned by the authenticated organization. - - Args: - extra_headers: Send extra headers - - extra_query: Add additional query parameters to the request - - extra_body: Add additional JSON properties to the request - - timeout: Override the client-level default timeout for this request, in seconds - """ - if not inbox_id: - raise ValueError(f"Expected a non-empty value for `inbox_id` but received {inbox_id!r}") - extra_headers = {"Accept": "*/*", **(extra_headers or {})} - return await self._get( - path_template("/mail/v1/inboxes/{inbox_id}/messages", inbox_id=inbox_id), - options=make_request_options( - extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout - ), - cast_to=NoneType, - ) - - async def reply( - self, - message_id: str, - *, - inbox_id: str, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> None: - """ - Reply to a message in an inbox owned by the authenticated organization. - - Args: - extra_headers: Send extra headers - - extra_query: Add additional query parameters to the request - - extra_body: Add additional JSON properties to the request - - timeout: Override the client-level default timeout for this request, in seconds - """ - if not inbox_id: - raise ValueError(f"Expected a non-empty value for `inbox_id` but received {inbox_id!r}") - if not message_id: - raise ValueError(f"Expected a non-empty value for `message_id` but received {message_id!r}") - extra_headers = {"Accept": "*/*", **(extra_headers or {})} - return await self._post( - path_template( - "/mail/v1/inboxes/{inbox_id}/messages/{message_id}/reply", inbox_id=inbox_id, message_id=message_id - ), - options=make_request_options( - extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout - ), - cast_to=NoneType, - ) - - async def send( - self, - inbox_id: str, - *, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> None: - """ - Send a message from an inbox owned by the authenticated organization. - - Args: - extra_headers: Send extra headers - - extra_query: Add additional query parameters to the request - - extra_body: Add additional JSON properties to the request - - timeout: Override the client-level default timeout for this request, in seconds - """ - if not inbox_id: - raise ValueError(f"Expected a non-empty value for `inbox_id` but received {inbox_id!r}") - extra_headers = {"Accept": "*/*", **(extra_headers or {})} - return await self._post( - path_template("/mail/v1/inboxes/{inbox_id}/messages/send", inbox_id=inbox_id), - options=make_request_options( - extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout - ), - cast_to=NoneType, - ) - - async def set_policy( - self, - inbox_id: str, - *, - allowed_sender_patterns: SequenceNotStr[str] | Omit = omit, - enforce_sender_allowlist: bool | Omit = omit, - read_access_rules: SequenceNotStr[str] | Omit = omit, - reply_access_rules: SequenceNotStr[str] | Omit = omit, - send_access_rules: SequenceNotStr[str] | Omit = omit, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> None: - """ - Set the sender allowlist and send/reply/read access rules for an inbox owned by - the authenticated organization. - - Args: - allowed_sender_patterns: Exact emails, @domain rules, or \\** - - read_access_rules: Rules like organization, operator, user:, api_key, api_key:, - clerk_session, or \\** - - reply_access_rules: Rules like organization, operator, user:, api_key, api_key:, - clerk_session, or \\** - - send_access_rules: Rules like organization, user:, api_key, api_key:, clerk_session, or \\** - - extra_headers: Send extra headers - - extra_query: Add additional query parameters to the request - - extra_body: Add additional JSON properties to the request - - timeout: Override the client-level default timeout for this request, in seconds - """ - if not inbox_id: - raise ValueError(f"Expected a non-empty value for `inbox_id` but received {inbox_id!r}") - extra_headers = {"Accept": "*/*", **(extra_headers or {})} - return await self._put( - path_template("/mail/v1/inboxes/{inbox_id}/policy", inbox_id=inbox_id), - body=await async_maybe_transform( - { - "allowed_sender_patterns": allowed_sender_patterns, - "enforce_sender_allowlist": enforce_sender_allowlist, - "read_access_rules": read_access_rules, - "reply_access_rules": reply_access_rules, - "send_access_rules": send_access_rules, - }, - inbox_set_policy_params.InboxSetPolicyParams, - ), - options=make_request_options( - extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout - ), - cast_to=NoneType, - ) - - -class InboxesResourceWithRawResponse: - def __init__(self, inboxes: InboxesResource) -> None: - self._inboxes = inboxes - - self.create = to_raw_response_wrapper( - inboxes.create, - ) - self.retrieve = to_raw_response_wrapper( - inboxes.retrieve, - ) - self.list = to_raw_response_wrapper( - inboxes.list, - ) - self.delete = to_raw_response_wrapper( - inboxes.delete, - ) - self.get_attachment = to_raw_response_wrapper( - inboxes.get_attachment, - ) - self.get_message = to_raw_response_wrapper( - inboxes.get_message, - ) - self.get_policy = to_raw_response_wrapper( - inboxes.get_policy, - ) - self.list_messages = to_raw_response_wrapper( - inboxes.list_messages, - ) - self.reply = to_raw_response_wrapper( - inboxes.reply, - ) - self.send = to_raw_response_wrapper( - inboxes.send, - ) - self.set_policy = to_raw_response_wrapper( - inboxes.set_policy, - ) - - -class AsyncInboxesResourceWithRawResponse: - def __init__(self, inboxes: AsyncInboxesResource) -> None: - self._inboxes = inboxes - - self.create = async_to_raw_response_wrapper( - inboxes.create, - ) - self.retrieve = async_to_raw_response_wrapper( - inboxes.retrieve, - ) - self.list = async_to_raw_response_wrapper( - inboxes.list, - ) - self.delete = async_to_raw_response_wrapper( - inboxes.delete, - ) - self.get_attachment = async_to_raw_response_wrapper( - inboxes.get_attachment, - ) - self.get_message = async_to_raw_response_wrapper( - inboxes.get_message, - ) - self.get_policy = async_to_raw_response_wrapper( - inboxes.get_policy, - ) - self.list_messages = async_to_raw_response_wrapper( - inboxes.list_messages, - ) - self.reply = async_to_raw_response_wrapper( - inboxes.reply, - ) - self.send = async_to_raw_response_wrapper( - inboxes.send, - ) - self.set_policy = async_to_raw_response_wrapper( - inboxes.set_policy, - ) - - -class InboxesResourceWithStreamingResponse: - def __init__(self, inboxes: InboxesResource) -> None: - self._inboxes = inboxes - - self.create = to_streamed_response_wrapper( - inboxes.create, - ) - self.retrieve = to_streamed_response_wrapper( - inboxes.retrieve, - ) - self.list = to_streamed_response_wrapper( - inboxes.list, - ) - self.delete = to_streamed_response_wrapper( - inboxes.delete, - ) - self.get_attachment = to_streamed_response_wrapper( - inboxes.get_attachment, - ) - self.get_message = to_streamed_response_wrapper( - inboxes.get_message, - ) - self.get_policy = to_streamed_response_wrapper( - inboxes.get_policy, - ) - self.list_messages = to_streamed_response_wrapper( - inboxes.list_messages, - ) - self.reply = to_streamed_response_wrapper( - inboxes.reply, - ) - self.send = to_streamed_response_wrapper( - inboxes.send, - ) - self.set_policy = to_streamed_response_wrapper( - inboxes.set_policy, - ) - - -class AsyncInboxesResourceWithStreamingResponse: - def __init__(self, inboxes: AsyncInboxesResource) -> None: - self._inboxes = inboxes - - self.create = async_to_streamed_response_wrapper( - inboxes.create, - ) - self.retrieve = async_to_streamed_response_wrapper( - inboxes.retrieve, - ) - self.list = async_to_streamed_response_wrapper( - inboxes.list, - ) - self.delete = async_to_streamed_response_wrapper( - inboxes.delete, - ) - self.get_attachment = async_to_streamed_response_wrapper( - inboxes.get_attachment, - ) - self.get_message = async_to_streamed_response_wrapper( - inboxes.get_message, - ) - self.get_policy = async_to_streamed_response_wrapper( - inboxes.get_policy, - ) - self.list_messages = async_to_streamed_response_wrapper( - inboxes.list_messages, - ) - self.reply = async_to_streamed_response_wrapper( - inboxes.reply, - ) - self.send = async_to_streamed_response_wrapper( - inboxes.send, - ) - self.set_policy = async_to_streamed_response_wrapper( - inboxes.set_policy, - ) diff --git a/src/casedev/resources/mail/v1/v1.py b/src/casedev/resources/mail/v1/v1.py deleted file mode 100644 index 391267a2..00000000 --- a/src/casedev/resources/mail/v1/v1.py +++ /dev/null @@ -1,108 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from __future__ import annotations - -from .inboxes import ( - InboxesResource, - AsyncInboxesResource, - InboxesResourceWithRawResponse, - AsyncInboxesResourceWithRawResponse, - InboxesResourceWithStreamingResponse, - AsyncInboxesResourceWithStreamingResponse, -) -from ...._compat import cached_property -from ...._resource import SyncAPIResource, AsyncAPIResource - -__all__ = ["V1Resource", "AsyncV1Resource"] - - -class V1Resource(SyncAPIResource): - @cached_property - def inboxes(self) -> InboxesResource: - """Managed inboxes for agent email workflows""" - return InboxesResource(self._client) - - @cached_property - def with_raw_response(self) -> V1ResourceWithRawResponse: - """ - This property can be used as a prefix for any HTTP method call to return - the raw response object instead of the parsed content. - - For more information, see https://www.github.com/CaseMark/casedev-python#accessing-raw-response-data-eg-headers - """ - return V1ResourceWithRawResponse(self) - - @cached_property - def with_streaming_response(self) -> V1ResourceWithStreamingResponse: - """ - An alternative to `.with_raw_response` that doesn't eagerly read the response body. - - For more information, see https://www.github.com/CaseMark/casedev-python#with_streaming_response - """ - return V1ResourceWithStreamingResponse(self) - - -class AsyncV1Resource(AsyncAPIResource): - @cached_property - def inboxes(self) -> AsyncInboxesResource: - """Managed inboxes for agent email workflows""" - return AsyncInboxesResource(self._client) - - @cached_property - def with_raw_response(self) -> AsyncV1ResourceWithRawResponse: - """ - This property can be used as a prefix for any HTTP method call to return - the raw response object instead of the parsed content. - - For more information, see https://www.github.com/CaseMark/casedev-python#accessing-raw-response-data-eg-headers - """ - return AsyncV1ResourceWithRawResponse(self) - - @cached_property - def with_streaming_response(self) -> AsyncV1ResourceWithStreamingResponse: - """ - An alternative to `.with_raw_response` that doesn't eagerly read the response body. - - For more information, see https://www.github.com/CaseMark/casedev-python#with_streaming_response - """ - return AsyncV1ResourceWithStreamingResponse(self) - - -class V1ResourceWithRawResponse: - def __init__(self, v1: V1Resource) -> None: - self._v1 = v1 - - @cached_property - def inboxes(self) -> InboxesResourceWithRawResponse: - """Managed inboxes for agent email workflows""" - return InboxesResourceWithRawResponse(self._v1.inboxes) - - -class AsyncV1ResourceWithRawResponse: - def __init__(self, v1: AsyncV1Resource) -> None: - self._v1 = v1 - - @cached_property - def inboxes(self) -> AsyncInboxesResourceWithRawResponse: - """Managed inboxes for agent email workflows""" - return AsyncInboxesResourceWithRawResponse(self._v1.inboxes) - - -class V1ResourceWithStreamingResponse: - def __init__(self, v1: V1Resource) -> None: - self._v1 = v1 - - @cached_property - def inboxes(self) -> InboxesResourceWithStreamingResponse: - """Managed inboxes for agent email workflows""" - return InboxesResourceWithStreamingResponse(self._v1.inboxes) - - -class AsyncV1ResourceWithStreamingResponse: - def __init__(self, v1: AsyncV1Resource) -> None: - self._v1 = v1 - - @cached_property - def inboxes(self) -> AsyncInboxesResourceWithStreamingResponse: - """Managed inboxes for agent email workflows""" - return AsyncInboxesResourceWithStreamingResponse(self._v1.inboxes) diff --git a/src/casedev/resources/matters/v1/work_items.py b/src/casedev/resources/matters/v1/work_items.py index 9057488e..8a56f1fd 100644 --- a/src/casedev/resources/matters/v1/work_items.py +++ b/src/casedev/resources/matters/v1/work_items.py @@ -269,8 +269,7 @@ def decide( work_item_id: str, *, id: str, - decision: Literal["approve", "revise", "block", "reassign"], - agent_type_id: Optional[str] | Omit = omit, + decision: Literal["approve", "block"], metadata: Dict[str, object] | Omit = omit, reason: Optional[str] | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. @@ -280,10 +279,8 @@ def decide( extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> None: - """Approve, revise, block, or reassign a work item. - - Used by humans or agents to - move work items through their lifecycle. + """ + Approve or block a work item. Args: extra_headers: Send extra headers @@ -304,7 +301,6 @@ def decide( body=maybe_transform( { "decision": decision, - "agent_type_id": agent_type_id, "metadata": metadata, "reason": reason, }, @@ -316,43 +312,6 @@ def decide( cast_to=NoneType, ) - def list_executions( - self, - work_item_id: str, - *, - id: str, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> None: - """ - List execution attempts for a work item, including agent and run linkage. - - Args: - extra_headers: Send extra headers - - extra_query: Add additional query parameters to the request - - extra_body: Add additional JSON properties to the request - - timeout: Override the client-level default timeout for this request, in seconds - """ - if not id: - raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") - if not work_item_id: - raise ValueError(f"Expected a non-empty value for `work_item_id` but received {work_item_id!r}") - extra_headers = {"Accept": "*/*", **(extra_headers or {})} - return self._get( - path_template("/matters/v1/{id}/work-items/{work_item_id}/executions", id=id, work_item_id=work_item_id), - options=make_request_options( - extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout - ), - cast_to=NoneType, - ) - class AsyncWorkItemsResource(AsyncAPIResource): """Matter-native legal workspaces and orchestration primitives""" @@ -594,8 +553,7 @@ async def decide( work_item_id: str, *, id: str, - decision: Literal["approve", "revise", "block", "reassign"], - agent_type_id: Optional[str] | Omit = omit, + decision: Literal["approve", "block"], metadata: Dict[str, object] | Omit = omit, reason: Optional[str] | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. @@ -605,10 +563,8 @@ async def decide( extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> None: - """Approve, revise, block, or reassign a work item. - - Used by humans or agents to - move work items through their lifecycle. + """ + Approve or block a work item. Args: extra_headers: Send extra headers @@ -629,7 +585,6 @@ async def decide( body=await async_maybe_transform( { "decision": decision, - "agent_type_id": agent_type_id, "metadata": metadata, "reason": reason, }, @@ -641,43 +596,6 @@ async def decide( cast_to=NoneType, ) - async def list_executions( - self, - work_item_id: str, - *, - id: str, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> None: - """ - List execution attempts for a work item, including agent and run linkage. - - Args: - extra_headers: Send extra headers - - extra_query: Add additional query parameters to the request - - extra_body: Add additional JSON properties to the request - - timeout: Override the client-level default timeout for this request, in seconds - """ - if not id: - raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") - if not work_item_id: - raise ValueError(f"Expected a non-empty value for `work_item_id` but received {work_item_id!r}") - extra_headers = {"Accept": "*/*", **(extra_headers or {})} - return await self._get( - path_template("/matters/v1/{id}/work-items/{work_item_id}/executions", id=id, work_item_id=work_item_id), - options=make_request_options( - extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout - ), - cast_to=NoneType, - ) - class WorkItemsResourceWithRawResponse: def __init__(self, work_items: WorkItemsResource) -> None: @@ -698,9 +616,6 @@ def __init__(self, work_items: WorkItemsResource) -> None: self.decide = to_raw_response_wrapper( work_items.decide, ) - self.list_executions = to_raw_response_wrapper( - work_items.list_executions, - ) class AsyncWorkItemsResourceWithRawResponse: @@ -722,9 +637,6 @@ def __init__(self, work_items: AsyncWorkItemsResource) -> None: self.decide = async_to_raw_response_wrapper( work_items.decide, ) - self.list_executions = async_to_raw_response_wrapper( - work_items.list_executions, - ) class WorkItemsResourceWithStreamingResponse: @@ -746,9 +658,6 @@ def __init__(self, work_items: WorkItemsResource) -> None: self.decide = to_streamed_response_wrapper( work_items.decide, ) - self.list_executions = to_streamed_response_wrapper( - work_items.list_executions, - ) class AsyncWorkItemsResourceWithStreamingResponse: @@ -770,6 +679,3 @@ def __init__(self, work_items: AsyncWorkItemsResource) -> None: self.decide = async_to_streamed_response_wrapper( work_items.decide, ) - self.list_executions = async_to_streamed_response_wrapper( - work_items.list_executions, - ) diff --git a/src/casedev/resources/media/v1/clips.py b/src/casedev/resources/media/v1/clips.py index eb973be0..f8bfd21c 100644 --- a/src/casedev/resources/media/v1/clips.py +++ b/src/casedev/resources/media/v1/clips.py @@ -20,6 +20,8 @@ class ClipsResource(SyncAPIResource): + """Transcript retrieval and captioned media clip generation""" + @cached_property def with_raw_response(self) -> ClipsResourceWithRawResponse: """ @@ -95,6 +97,8 @@ def retrieve( class AsyncClipsResource(AsyncAPIResource): + """Transcript retrieval and captioned media clip generation""" + @cached_property def with_raw_response(self) -> AsyncClipsResourceWithRawResponse: """ diff --git a/src/casedev/resources/media/v1/transcripts/retrieve.py b/src/casedev/resources/media/v1/transcripts/retrieve.py index 0d98dc68..72615a57 100644 --- a/src/casedev/resources/media/v1/transcripts/retrieve.py +++ b/src/casedev/resources/media/v1/transcripts/retrieve.py @@ -22,6 +22,8 @@ class RetrieveResource(SyncAPIResource): + """Transcript retrieval and captioned media clip generation""" + @cached_property def with_raw_response(self) -> RetrieveResourceWithRawResponse: """ @@ -93,6 +95,8 @@ def create( class AsyncRetrieveResource(AsyncAPIResource): + """Transcript retrieval and captioned media clip generation""" + @cached_property def with_raw_response(self) -> AsyncRetrieveResourceWithRawResponse: """ diff --git a/src/casedev/resources/media/v1/transcripts/search.py b/src/casedev/resources/media/v1/transcripts/search.py index 6e5854ca..5375797c 100644 --- a/src/casedev/resources/media/v1/transcripts/search.py +++ b/src/casedev/resources/media/v1/transcripts/search.py @@ -19,6 +19,8 @@ class SearchResource(SyncAPIResource): + """Transcript retrieval and captioned media clip generation""" + @cached_property def with_raw_response(self) -> SearchResourceWithRawResponse: """ @@ -60,6 +62,8 @@ def create( class AsyncSearchResource(AsyncAPIResource): + """Transcript retrieval and captioned media clip generation""" + @cached_property def with_raw_response(self) -> AsyncSearchResourceWithRawResponse: """ diff --git a/src/casedev/resources/media/v1/transcripts/transcripts.py b/src/casedev/resources/media/v1/transcripts/transcripts.py index bf6ffb70..f3a14fca 100644 --- a/src/casedev/resources/media/v1/transcripts/transcripts.py +++ b/src/casedev/resources/media/v1/transcripts/transcripts.py @@ -27,10 +27,12 @@ class TranscriptsResource(SyncAPIResource): @cached_property def search(self) -> SearchResource: + """Transcript retrieval and captioned media clip generation""" return SearchResource(self._client) @cached_property def retrieve(self) -> RetrieveResource: + """Transcript retrieval and captioned media clip generation""" return RetrieveResource(self._client) @cached_property @@ -56,10 +58,12 @@ def with_streaming_response(self) -> TranscriptsResourceWithStreamingResponse: class AsyncTranscriptsResource(AsyncAPIResource): @cached_property def search(self) -> AsyncSearchResource: + """Transcript retrieval and captioned media clip generation""" return AsyncSearchResource(self._client) @cached_property def retrieve(self) -> AsyncRetrieveResource: + """Transcript retrieval and captioned media clip generation""" return AsyncRetrieveResource(self._client) @cached_property @@ -88,10 +92,12 @@ def __init__(self, transcripts: TranscriptsResource) -> None: @cached_property def search(self) -> SearchResourceWithRawResponse: + """Transcript retrieval and captioned media clip generation""" return SearchResourceWithRawResponse(self._transcripts.search) @cached_property def retrieve(self) -> RetrieveResourceWithRawResponse: + """Transcript retrieval and captioned media clip generation""" return RetrieveResourceWithRawResponse(self._transcripts.retrieve) @@ -101,10 +107,12 @@ def __init__(self, transcripts: AsyncTranscriptsResource) -> None: @cached_property def search(self) -> AsyncSearchResourceWithRawResponse: + """Transcript retrieval and captioned media clip generation""" return AsyncSearchResourceWithRawResponse(self._transcripts.search) @cached_property def retrieve(self) -> AsyncRetrieveResourceWithRawResponse: + """Transcript retrieval and captioned media clip generation""" return AsyncRetrieveResourceWithRawResponse(self._transcripts.retrieve) @@ -114,10 +122,12 @@ def __init__(self, transcripts: TranscriptsResource) -> None: @cached_property def search(self) -> SearchResourceWithStreamingResponse: + """Transcript retrieval and captioned media clip generation""" return SearchResourceWithStreamingResponse(self._transcripts.search) @cached_property def retrieve(self) -> RetrieveResourceWithStreamingResponse: + """Transcript retrieval and captioned media clip generation""" return RetrieveResourceWithStreamingResponse(self._transcripts.retrieve) @@ -127,8 +137,10 @@ def __init__(self, transcripts: AsyncTranscriptsResource) -> None: @cached_property def search(self) -> AsyncSearchResourceWithStreamingResponse: + """Transcript retrieval and captioned media clip generation""" return AsyncSearchResourceWithStreamingResponse(self._transcripts.search) @cached_property def retrieve(self) -> AsyncRetrieveResourceWithStreamingResponse: + """Transcript retrieval and captioned media clip generation""" return AsyncRetrieveResourceWithStreamingResponse(self._transcripts.retrieve) diff --git a/src/casedev/resources/media/v1/v1.py b/src/casedev/resources/media/v1/v1.py index b506b4bc..b05a90d7 100644 --- a/src/casedev/resources/media/v1/v1.py +++ b/src/casedev/resources/media/v1/v1.py @@ -27,6 +27,7 @@ class V1Resource(SyncAPIResource): @cached_property def clips(self) -> ClipsResource: + """Transcript retrieval and captioned media clip generation""" return ClipsResource(self._client) @cached_property @@ -56,6 +57,7 @@ def with_streaming_response(self) -> V1ResourceWithStreamingResponse: class AsyncV1Resource(AsyncAPIResource): @cached_property def clips(self) -> AsyncClipsResource: + """Transcript retrieval and captioned media clip generation""" return AsyncClipsResource(self._client) @cached_property @@ -88,6 +90,7 @@ def __init__(self, v1: V1Resource) -> None: @cached_property def clips(self) -> ClipsResourceWithRawResponse: + """Transcript retrieval and captioned media clip generation""" return ClipsResourceWithRawResponse(self._v1.clips) @cached_property @@ -101,6 +104,7 @@ def __init__(self, v1: AsyncV1Resource) -> None: @cached_property def clips(self) -> AsyncClipsResourceWithRawResponse: + """Transcript retrieval and captioned media clip generation""" return AsyncClipsResourceWithRawResponse(self._v1.clips) @cached_property @@ -114,6 +118,7 @@ def __init__(self, v1: V1Resource) -> None: @cached_property def clips(self) -> ClipsResourceWithStreamingResponse: + """Transcript retrieval and captioned media clip generation""" return ClipsResourceWithStreamingResponse(self._v1.clips) @cached_property @@ -127,6 +132,7 @@ def __init__(self, v1: AsyncV1Resource) -> None: @cached_property def clips(self) -> AsyncClipsResourceWithStreamingResponse: + """Transcript retrieval and captioned media clip generation""" return AsyncClipsResourceWithStreamingResponse(self._v1.clips) @cached_property diff --git a/src/casedev/resources/ocr/v1.py b/src/casedev/resources/ocr/v1.py index 0b727b62..8ccb4e78 100644 --- a/src/casedev/resources/ocr/v1.py +++ b/src/casedev/resources/ocr/v1.py @@ -68,11 +68,11 @@ def retrieve( ) -> V1RetrieveResponse: """Retrieve the status and results of an OCR job. - Returns job progress, extracted - text, and metadata when processing is complete. + Returns job progress and + metadata; full extracted text is included only when include_text=true. Args: - include_text: Include full OCR text in completed responses (default: true) + include_text: Include full OCR text in completed responses (default: false) extra_headers: Send extra headers @@ -236,11 +236,11 @@ async def retrieve( ) -> V1RetrieveResponse: """Retrieve the status and results of an OCR job. - Returns job progress, extracted - text, and metadata when processing is complete. + Returns job progress and + metadata; full extracted text is included only when include_text=true. Args: - include_text: Include full OCR text in completed responses (default: true) + include_text: Include full OCR text in completed responses (default: false) extra_headers: Send extra headers diff --git a/src/casedev/resources/search/search.py b/src/casedev/resources/search/search.py index d1cab2aa..28dbc2ba 100644 --- a/src/casedev/resources/search/search.py +++ b/src/casedev/resources/search/search.py @@ -19,7 +19,7 @@ class SearchResource(SyncAPIResource): @cached_property def v1(self) -> V1Resource: - """Web search, AI answers, and deep research""" + """Web search and AI answers""" return V1Resource(self._client) @cached_property @@ -45,7 +45,7 @@ def with_streaming_response(self) -> SearchResourceWithStreamingResponse: class AsyncSearchResource(AsyncAPIResource): @cached_property def v1(self) -> AsyncV1Resource: - """Web search, AI answers, and deep research""" + """Web search and AI answers""" return AsyncV1Resource(self._client) @cached_property @@ -74,7 +74,7 @@ def __init__(self, search: SearchResource) -> None: @cached_property def v1(self) -> V1ResourceWithRawResponse: - """Web search, AI answers, and deep research""" + """Web search and AI answers""" return V1ResourceWithRawResponse(self._search.v1) @@ -84,7 +84,7 @@ def __init__(self, search: AsyncSearchResource) -> None: @cached_property def v1(self) -> AsyncV1ResourceWithRawResponse: - """Web search, AI answers, and deep research""" + """Web search and AI answers""" return AsyncV1ResourceWithRawResponse(self._search.v1) @@ -94,7 +94,7 @@ def __init__(self, search: SearchResource) -> None: @cached_property def v1(self) -> V1ResourceWithStreamingResponse: - """Web search, AI answers, and deep research""" + """Web search and AI answers""" return V1ResourceWithStreamingResponse(self._search.v1) @@ -104,5 +104,5 @@ def __init__(self, search: AsyncSearchResource) -> None: @cached_property def v1(self) -> AsyncV1ResourceWithStreamingResponse: - """Web search, AI answers, and deep research""" + """Web search and AI answers""" return AsyncV1ResourceWithStreamingResponse(self._search.v1) diff --git a/src/casedev/resources/search/v1.py b/src/casedev/resources/search/v1.py index 2a55097f..a45aac49 100644 --- a/src/casedev/resources/search/v1.py +++ b/src/casedev/resources/search/v1.py @@ -9,7 +9,7 @@ import httpx from ..._types import Body, Omit, Query, Headers, NotGiven, SequenceNotStr, omit, not_given -from ..._utils import path_template, maybe_transform, async_maybe_transform +from ..._utils import maybe_transform, async_maybe_transform from ..._compat import cached_property from ..._resource import SyncAPIResource, AsyncAPIResource from ..._response import ( @@ -19,26 +19,17 @@ async_to_streamed_response_wrapper, ) from ..._base_client import make_request_options -from ...types.search import ( - v1_answer_params, - v1_search_params, - v1_similar_params, - v1_contents_params, - v1_research_params, - v1_retrieve_research_params, -) +from ...types.search import v1_answer_params, v1_search_params, v1_similar_params, v1_contents_params from ...types.search.v1_answer_response import V1AnswerResponse from ...types.search.v1_search_response import V1SearchResponse from ...types.search.v1_similar_response import V1SimilarResponse from ...types.search.v1_contents_response import V1ContentsResponse -from ...types.search.v1_research_response import V1ResearchResponse -from ...types.search.v1_retrieve_research_response import V1RetrieveResearchResponse __all__ = ["V1Resource", "AsyncV1Resource"] class V1Resource(SyncAPIResource): - """Web search, AI answers, and deep research""" + """Web search and AI answers""" @cached_property def with_raw_response(self) -> V1ResourceWithRawResponse: @@ -220,112 +211,6 @@ def contents( cast_to=V1ContentsResponse, ) - def research( - self, - *, - instructions: str, - model: Literal["fast", "normal", "pro"] | Omit = omit, - output_schema: object | Omit = omit, - query: str | Omit = omit, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> V1ResearchResponse: - """ - Performs deep research by conducting multi-step analysis, gathering information - from multiple sources, and providing comprehensive insights. Ideal for legal - research, case analysis, and due diligence investigations. - - Args: - instructions: Research instructions or query - - model: Research quality level - fast (quick), normal (balanced), pro (comprehensive) - - output_schema: Optional JSON schema to structure the research output - - query: Alias for instructions (for convenience) - - extra_headers: Send extra headers - - extra_query: Add additional query parameters to the request - - extra_body: Add additional JSON properties to the request - - timeout: Override the client-level default timeout for this request, in seconds - """ - return self._post( - "/search/v1/research", - body=maybe_transform( - { - "instructions": instructions, - "model": model, - "output_schema": output_schema, - "query": query, - }, - v1_research_params.V1ResearchParams, - ), - options=make_request_options( - extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout - ), - cast_to=V1ResearchResponse, - ) - - def retrieve_research( - self, - id: str, - *, - events: str | Omit = omit, - stream: bool | Omit = omit, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> V1RetrieveResearchResponse: - """Retrieve the status and results of a deep research task by ID. - - Supports both - standard JSON responses and streaming for real-time updates as the research - progresses. Research tasks analyze topics comprehensively using web search and - AI synthesis. - - Args: - events: Filter specific event types for streaming - - stream: Enable streaming for real-time updates - - extra_headers: Send extra headers - - extra_query: Add additional query parameters to the request - - extra_body: Add additional JSON properties to the request - - timeout: Override the client-level default timeout for this request, in seconds - """ - if not id: - raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") - return self._get( - path_template("/search/v1/research/{id}", id=id), - options=make_request_options( - extra_headers=extra_headers, - extra_query=extra_query, - extra_body=extra_body, - timeout=timeout, - query=maybe_transform( - { - "events": events, - "stream": stream, - }, - v1_retrieve_research_params.V1RetrieveResearchParams, - ), - ), - cast_to=V1RetrieveResearchResponse, - ) - def search( self, *, @@ -499,7 +384,7 @@ def similar( class AsyncV1Resource(AsyncAPIResource): - """Web search, AI answers, and deep research""" + """Web search and AI answers""" @cached_property def with_raw_response(self) -> AsyncV1ResourceWithRawResponse: @@ -681,112 +566,6 @@ async def contents( cast_to=V1ContentsResponse, ) - async def research( - self, - *, - instructions: str, - model: Literal["fast", "normal", "pro"] | Omit = omit, - output_schema: object | Omit = omit, - query: str | Omit = omit, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> V1ResearchResponse: - """ - Performs deep research by conducting multi-step analysis, gathering information - from multiple sources, and providing comprehensive insights. Ideal for legal - research, case analysis, and due diligence investigations. - - Args: - instructions: Research instructions or query - - model: Research quality level - fast (quick), normal (balanced), pro (comprehensive) - - output_schema: Optional JSON schema to structure the research output - - query: Alias for instructions (for convenience) - - extra_headers: Send extra headers - - extra_query: Add additional query parameters to the request - - extra_body: Add additional JSON properties to the request - - timeout: Override the client-level default timeout for this request, in seconds - """ - return await self._post( - "/search/v1/research", - body=await async_maybe_transform( - { - "instructions": instructions, - "model": model, - "output_schema": output_schema, - "query": query, - }, - v1_research_params.V1ResearchParams, - ), - options=make_request_options( - extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout - ), - cast_to=V1ResearchResponse, - ) - - async def retrieve_research( - self, - id: str, - *, - events: str | Omit = omit, - stream: bool | Omit = omit, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> V1RetrieveResearchResponse: - """Retrieve the status and results of a deep research task by ID. - - Supports both - standard JSON responses and streaming for real-time updates as the research - progresses. Research tasks analyze topics comprehensively using web search and - AI synthesis. - - Args: - events: Filter specific event types for streaming - - stream: Enable streaming for real-time updates - - extra_headers: Send extra headers - - extra_query: Add additional query parameters to the request - - extra_body: Add additional JSON properties to the request - - timeout: Override the client-level default timeout for this request, in seconds - """ - if not id: - raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") - return await self._get( - path_template("/search/v1/research/{id}", id=id), - options=make_request_options( - extra_headers=extra_headers, - extra_query=extra_query, - extra_body=extra_body, - timeout=timeout, - query=await async_maybe_transform( - { - "events": events, - "stream": stream, - }, - v1_retrieve_research_params.V1RetrieveResearchParams, - ), - ), - cast_to=V1RetrieveResearchResponse, - ) - async def search( self, *, @@ -969,12 +748,6 @@ def __init__(self, v1: V1Resource) -> None: self.contents = to_raw_response_wrapper( v1.contents, ) - self.research = to_raw_response_wrapper( - v1.research, - ) - self.retrieve_research = to_raw_response_wrapper( - v1.retrieve_research, - ) self.search = to_raw_response_wrapper( v1.search, ) @@ -993,12 +766,6 @@ def __init__(self, v1: AsyncV1Resource) -> None: self.contents = async_to_raw_response_wrapper( v1.contents, ) - self.research = async_to_raw_response_wrapper( - v1.research, - ) - self.retrieve_research = async_to_raw_response_wrapper( - v1.retrieve_research, - ) self.search = async_to_raw_response_wrapper( v1.search, ) @@ -1017,12 +784,6 @@ def __init__(self, v1: V1Resource) -> None: self.contents = to_streamed_response_wrapper( v1.contents, ) - self.research = to_streamed_response_wrapper( - v1.research, - ) - self.retrieve_research = to_streamed_response_wrapper( - v1.retrieve_research, - ) self.search = to_streamed_response_wrapper( v1.search, ) @@ -1041,12 +802,6 @@ def __init__(self, v1: AsyncV1Resource) -> None: self.contents = async_to_streamed_response_wrapper( v1.contents, ) - self.research = async_to_streamed_response_wrapper( - v1.research, - ) - self.retrieve_research = async_to_streamed_response_wrapper( - v1.retrieve_research, - ) self.search = async_to_streamed_response_wrapper( v1.search, ) diff --git a/src/casedev/resources/superdoc/__init__.py b/src/casedev/resources/superdoc/__init__.py deleted file mode 100644 index 18e3a98c..00000000 --- a/src/casedev/resources/superdoc/__init__.py +++ /dev/null @@ -1,33 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from .v1 import ( - V1Resource, - AsyncV1Resource, - V1ResourceWithRawResponse, - AsyncV1ResourceWithRawResponse, - V1ResourceWithStreamingResponse, - AsyncV1ResourceWithStreamingResponse, -) -from .superdoc import ( - SuperdocResource, - AsyncSuperdocResource, - SuperdocResourceWithRawResponse, - AsyncSuperdocResourceWithRawResponse, - SuperdocResourceWithStreamingResponse, - AsyncSuperdocResourceWithStreamingResponse, -) - -__all__ = [ - "V1Resource", - "AsyncV1Resource", - "V1ResourceWithRawResponse", - "AsyncV1ResourceWithRawResponse", - "V1ResourceWithStreamingResponse", - "AsyncV1ResourceWithStreamingResponse", - "SuperdocResource", - "AsyncSuperdocResource", - "SuperdocResourceWithRawResponse", - "AsyncSuperdocResourceWithRawResponse", - "SuperdocResourceWithStreamingResponse", - "AsyncSuperdocResourceWithStreamingResponse", -] diff --git a/src/casedev/resources/superdoc/superdoc.py b/src/casedev/resources/superdoc/superdoc.py deleted file mode 100644 index 560543a1..00000000 --- a/src/casedev/resources/superdoc/superdoc.py +++ /dev/null @@ -1,108 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from __future__ import annotations - -from .v1 import ( - V1Resource, - AsyncV1Resource, - V1ResourceWithRawResponse, - AsyncV1ResourceWithRawResponse, - V1ResourceWithStreamingResponse, - AsyncV1ResourceWithStreamingResponse, -) -from ..._compat import cached_property -from ..._resource import SyncAPIResource, AsyncAPIResource - -__all__ = ["SuperdocResource", "AsyncSuperdocResource"] - - -class SuperdocResource(SyncAPIResource): - @cached_property - def v1(self) -> V1Resource: - """Document conversion and template automation""" - return V1Resource(self._client) - - @cached_property - def with_raw_response(self) -> SuperdocResourceWithRawResponse: - """ - This property can be used as a prefix for any HTTP method call to return - the raw response object instead of the parsed content. - - For more information, see https://www.github.com/CaseMark/casedev-python#accessing-raw-response-data-eg-headers - """ - return SuperdocResourceWithRawResponse(self) - - @cached_property - def with_streaming_response(self) -> SuperdocResourceWithStreamingResponse: - """ - An alternative to `.with_raw_response` that doesn't eagerly read the response body. - - For more information, see https://www.github.com/CaseMark/casedev-python#with_streaming_response - """ - return SuperdocResourceWithStreamingResponse(self) - - -class AsyncSuperdocResource(AsyncAPIResource): - @cached_property - def v1(self) -> AsyncV1Resource: - """Document conversion and template automation""" - return AsyncV1Resource(self._client) - - @cached_property - def with_raw_response(self) -> AsyncSuperdocResourceWithRawResponse: - """ - This property can be used as a prefix for any HTTP method call to return - the raw response object instead of the parsed content. - - For more information, see https://www.github.com/CaseMark/casedev-python#accessing-raw-response-data-eg-headers - """ - return AsyncSuperdocResourceWithRawResponse(self) - - @cached_property - def with_streaming_response(self) -> AsyncSuperdocResourceWithStreamingResponse: - """ - An alternative to `.with_raw_response` that doesn't eagerly read the response body. - - For more information, see https://www.github.com/CaseMark/casedev-python#with_streaming_response - """ - return AsyncSuperdocResourceWithStreamingResponse(self) - - -class SuperdocResourceWithRawResponse: - def __init__(self, superdoc: SuperdocResource) -> None: - self._superdoc = superdoc - - @cached_property - def v1(self) -> V1ResourceWithRawResponse: - """Document conversion and template automation""" - return V1ResourceWithRawResponse(self._superdoc.v1) - - -class AsyncSuperdocResourceWithRawResponse: - def __init__(self, superdoc: AsyncSuperdocResource) -> None: - self._superdoc = superdoc - - @cached_property - def v1(self) -> AsyncV1ResourceWithRawResponse: - """Document conversion and template automation""" - return AsyncV1ResourceWithRawResponse(self._superdoc.v1) - - -class SuperdocResourceWithStreamingResponse: - def __init__(self, superdoc: SuperdocResource) -> None: - self._superdoc = superdoc - - @cached_property - def v1(self) -> V1ResourceWithStreamingResponse: - """Document conversion and template automation""" - return V1ResourceWithStreamingResponse(self._superdoc.v1) - - -class AsyncSuperdocResourceWithStreamingResponse: - def __init__(self, superdoc: AsyncSuperdocResource) -> None: - self._superdoc = superdoc - - @cached_property - def v1(self) -> AsyncV1ResourceWithStreamingResponse: - """Document conversion and template automation""" - return AsyncV1ResourceWithStreamingResponse(self._superdoc.v1) diff --git a/src/casedev/resources/superdoc/v1.py b/src/casedev/resources/superdoc/v1.py deleted file mode 100644 index 9192d6cb..00000000 --- a/src/casedev/resources/superdoc/v1.py +++ /dev/null @@ -1,356 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from __future__ import annotations - -from typing import Mapping, Iterable, cast -from typing_extensions import Literal - -import httpx - -from ..._files import deepcopy_with_paths -from ..._types import Body, Omit, Query, Headers, NotGiven, omit, not_given -from ..._utils import extract_files, maybe_transform, async_maybe_transform -from ..._compat import cached_property -from ..._resource import SyncAPIResource, AsyncAPIResource -from ..._response import ( - BinaryAPIResponse, - AsyncBinaryAPIResponse, - StreamedBinaryAPIResponse, - AsyncStreamedBinaryAPIResponse, - to_custom_raw_response_wrapper, - to_custom_streamed_response_wrapper, - async_to_custom_raw_response_wrapper, - async_to_custom_streamed_response_wrapper, -) -from ..._base_client import make_request_options -from ...types.superdoc import v1_convert_params, v1_annotate_params - -__all__ = ["V1Resource", "AsyncV1Resource"] - - -class V1Resource(SyncAPIResource): - """Document conversion and template automation""" - - @cached_property - def with_raw_response(self) -> V1ResourceWithRawResponse: - """ - This property can be used as a prefix for any HTTP method call to return - the raw response object instead of the parsed content. - - For more information, see https://www.github.com/CaseMark/casedev-python#accessing-raw-response-data-eg-headers - """ - return V1ResourceWithRawResponse(self) - - @cached_property - def with_streaming_response(self) -> V1ResourceWithStreamingResponse: - """ - An alternative to `.with_raw_response` that doesn't eagerly read the response body. - - For more information, see https://www.github.com/CaseMark/casedev-python#with_streaming_response - """ - return V1ResourceWithStreamingResponse(self) - - def annotate( - self, - *, - document: v1_annotate_params.Document, - fields: Iterable[v1_annotate_params.Field], - output_format: Literal["docx", "pdf"] | Omit = omit, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> BinaryAPIResponse: - """Populate fields inside a DOCX template using SuperDoc annotations. - - Supports - text, images, dates, and numbers. Can target individual fields by ID or multiple - fields by group. - - Args: - document: Document source - provide either URL or base64 - - fields: Fields to populate in the template - - output_format: Output format for the annotated document - - extra_headers: Send extra headers - - extra_query: Add additional query parameters to the request - - extra_body: Add additional JSON properties to the request - - timeout: Override the client-level default timeout for this request, in seconds - """ - extra_headers = {"Accept": "application/pdf", **(extra_headers or {})} - return self._post( - "/superdoc/v1/annotate", - body=maybe_transform( - { - "document": document, - "fields": fields, - "output_format": output_format, - }, - v1_annotate_params.V1AnnotateParams, - ), - options=make_request_options( - extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout - ), - cast_to=BinaryAPIResponse, - ) - - def convert( - self, - *, - from_: Literal["docx", "md", "html"], - document_base64: str | Omit = omit, - document_url: str | Omit = omit, - to: Literal["pdf", "docx"] | Omit = omit, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> BinaryAPIResponse: - """Convert documents between formats using SuperDoc. - - Supports DOCX to PDF, Markdown - to DOCX, and HTML to DOCX conversions. - - Args: - from_: Source format of the document - - document_base64: Base64-encoded document content - - document_url: URL to the document to convert - - to: Target format for conversion - - extra_headers: Send extra headers - - extra_query: Add additional query parameters to the request - - extra_body: Add additional JSON properties to the request - - timeout: Override the client-level default timeout for this request, in seconds - """ - extra_headers = {"Accept": "application/pdf", **(extra_headers or {})} - body = deepcopy_with_paths( - { - "from_": from_, - "document_base64": document_base64, - "document_url": document_url, - "to": to, - }, - [["file"]], - ) - files = extract_files(cast(Mapping[str, object], body), paths=[["file"]]) - if files: - # It should be noted that the actual Content-Type header that will be - # sent to the server will contain a `boundary` parameter, e.g. - # multipart/form-data; boundary=---abc-- - extra_headers = {"Content-Type": "multipart/form-data", **(extra_headers or {})} - return self._post( - "/superdoc/v1/convert", - body=maybe_transform(body, v1_convert_params.V1ConvertParams), - files=files, - options=make_request_options( - extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout - ), - cast_to=BinaryAPIResponse, - ) - - -class AsyncV1Resource(AsyncAPIResource): - """Document conversion and template automation""" - - @cached_property - def with_raw_response(self) -> AsyncV1ResourceWithRawResponse: - """ - This property can be used as a prefix for any HTTP method call to return - the raw response object instead of the parsed content. - - For more information, see https://www.github.com/CaseMark/casedev-python#accessing-raw-response-data-eg-headers - """ - return AsyncV1ResourceWithRawResponse(self) - - @cached_property - def with_streaming_response(self) -> AsyncV1ResourceWithStreamingResponse: - """ - An alternative to `.with_raw_response` that doesn't eagerly read the response body. - - For more information, see https://www.github.com/CaseMark/casedev-python#with_streaming_response - """ - return AsyncV1ResourceWithStreamingResponse(self) - - async def annotate( - self, - *, - document: v1_annotate_params.Document, - fields: Iterable[v1_annotate_params.Field], - output_format: Literal["docx", "pdf"] | Omit = omit, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> AsyncBinaryAPIResponse: - """Populate fields inside a DOCX template using SuperDoc annotations. - - Supports - text, images, dates, and numbers. Can target individual fields by ID or multiple - fields by group. - - Args: - document: Document source - provide either URL or base64 - - fields: Fields to populate in the template - - output_format: Output format for the annotated document - - extra_headers: Send extra headers - - extra_query: Add additional query parameters to the request - - extra_body: Add additional JSON properties to the request - - timeout: Override the client-level default timeout for this request, in seconds - """ - extra_headers = {"Accept": "application/pdf", **(extra_headers or {})} - return await self._post( - "/superdoc/v1/annotate", - body=await async_maybe_transform( - { - "document": document, - "fields": fields, - "output_format": output_format, - }, - v1_annotate_params.V1AnnotateParams, - ), - options=make_request_options( - extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout - ), - cast_to=AsyncBinaryAPIResponse, - ) - - async def convert( - self, - *, - from_: Literal["docx", "md", "html"], - document_base64: str | Omit = omit, - document_url: str | Omit = omit, - to: Literal["pdf", "docx"] | Omit = omit, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> AsyncBinaryAPIResponse: - """Convert documents between formats using SuperDoc. - - Supports DOCX to PDF, Markdown - to DOCX, and HTML to DOCX conversions. - - Args: - from_: Source format of the document - - document_base64: Base64-encoded document content - - document_url: URL to the document to convert - - to: Target format for conversion - - extra_headers: Send extra headers - - extra_query: Add additional query parameters to the request - - extra_body: Add additional JSON properties to the request - - timeout: Override the client-level default timeout for this request, in seconds - """ - extra_headers = {"Accept": "application/pdf", **(extra_headers or {})} - body = deepcopy_with_paths( - { - "from_": from_, - "document_base64": document_base64, - "document_url": document_url, - "to": to, - }, - [["file"]], - ) - files = extract_files(cast(Mapping[str, object], body), paths=[["file"]]) - if files: - # It should be noted that the actual Content-Type header that will be - # sent to the server will contain a `boundary` parameter, e.g. - # multipart/form-data; boundary=---abc-- - extra_headers = {"Content-Type": "multipart/form-data", **(extra_headers or {})} - return await self._post( - "/superdoc/v1/convert", - body=await async_maybe_transform(body, v1_convert_params.V1ConvertParams), - files=files, - options=make_request_options( - extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout - ), - cast_to=AsyncBinaryAPIResponse, - ) - - -class V1ResourceWithRawResponse: - def __init__(self, v1: V1Resource) -> None: - self._v1 = v1 - - self.annotate = to_custom_raw_response_wrapper( - v1.annotate, - BinaryAPIResponse, - ) - self.convert = to_custom_raw_response_wrapper( - v1.convert, - BinaryAPIResponse, - ) - - -class AsyncV1ResourceWithRawResponse: - def __init__(self, v1: AsyncV1Resource) -> None: - self._v1 = v1 - - self.annotate = async_to_custom_raw_response_wrapper( - v1.annotate, - AsyncBinaryAPIResponse, - ) - self.convert = async_to_custom_raw_response_wrapper( - v1.convert, - AsyncBinaryAPIResponse, - ) - - -class V1ResourceWithStreamingResponse: - def __init__(self, v1: V1Resource) -> None: - self._v1 = v1 - - self.annotate = to_custom_streamed_response_wrapper( - v1.annotate, - StreamedBinaryAPIResponse, - ) - self.convert = to_custom_streamed_response_wrapper( - v1.convert, - StreamedBinaryAPIResponse, - ) - - -class AsyncV1ResourceWithStreamingResponse: - def __init__(self, v1: AsyncV1Resource) -> None: - self._v1 = v1 - - self.annotate = async_to_custom_streamed_response_wrapper( - v1.annotate, - AsyncStreamedBinaryAPIResponse, - ) - self.convert = async_to_custom_streamed_response_wrapper( - v1.convert, - AsyncStreamedBinaryAPIResponse, - ) diff --git a/src/casedev/resources/translate/translate.py b/src/casedev/resources/translate/translate.py index 05d4e741..6a061c71 100644 --- a/src/casedev/resources/translate/translate.py +++ b/src/casedev/resources/translate/translate.py @@ -19,6 +19,7 @@ class TranslateResource(SyncAPIResource): @cached_property def v1(self) -> V1Resource: + """Language detection and translation for multilingual legal workflows""" return V1Resource(self._client) @cached_property @@ -44,6 +45,7 @@ def with_streaming_response(self) -> TranslateResourceWithStreamingResponse: class AsyncTranslateResource(AsyncAPIResource): @cached_property def v1(self) -> AsyncV1Resource: + """Language detection and translation for multilingual legal workflows""" return AsyncV1Resource(self._client) @cached_property @@ -72,6 +74,7 @@ def __init__(self, translate: TranslateResource) -> None: @cached_property def v1(self) -> V1ResourceWithRawResponse: + """Language detection and translation for multilingual legal workflows""" return V1ResourceWithRawResponse(self._translate.v1) @@ -81,6 +84,7 @@ def __init__(self, translate: AsyncTranslateResource) -> None: @cached_property def v1(self) -> AsyncV1ResourceWithRawResponse: + """Language detection and translation for multilingual legal workflows""" return AsyncV1ResourceWithRawResponse(self._translate.v1) @@ -90,6 +94,7 @@ def __init__(self, translate: TranslateResource) -> None: @cached_property def v1(self) -> V1ResourceWithStreamingResponse: + """Language detection and translation for multilingual legal workflows""" return V1ResourceWithStreamingResponse(self._translate.v1) @@ -99,4 +104,5 @@ def __init__(self, translate: AsyncTranslateResource) -> None: @cached_property def v1(self) -> AsyncV1ResourceWithStreamingResponse: + """Language detection and translation for multilingual legal workflows""" return AsyncV1ResourceWithStreamingResponse(self._translate.v1) diff --git a/src/casedev/resources/translate/v1.py b/src/casedev/resources/translate/v1.py index 9fc9b92e..a25eb671 100644 --- a/src/casedev/resources/translate/v1.py +++ b/src/casedev/resources/translate/v1.py @@ -2,23 +2,47 @@ from __future__ import annotations -from typing import Union +from typing import Union, Mapping, cast from typing_extensions import Literal import httpx -from ..._types import Body, Omit, Query, Headers, NotGiven, SequenceNotStr, omit, not_given -from ..._utils import maybe_transform, async_maybe_transform +from ..._files import deepcopy_with_paths +from ..._types import ( + Body, + Omit, + Query, + Headers, + NotGiven, + FileTypes, + SequenceNotStr, + omit, + not_given, +) +from ..._utils import extract_files, maybe_transform, async_maybe_transform from ..._compat import cached_property from ..._resource import SyncAPIResource, AsyncAPIResource from ..._response import ( + BinaryAPIResponse, + AsyncBinaryAPIResponse, + StreamedBinaryAPIResponse, + AsyncStreamedBinaryAPIResponse, to_raw_response_wrapper, to_streamed_response_wrapper, async_to_raw_response_wrapper, + to_custom_raw_response_wrapper, async_to_streamed_response_wrapper, + to_custom_streamed_response_wrapper, + async_to_custom_raw_response_wrapper, + async_to_custom_streamed_response_wrapper, ) from ..._base_client import make_request_options -from ...types.translate import v1_detect_params, v1_translate_params, v1_list_languages_params +from ...types.translate import ( + v1_detect_params, + v1_translate_params, + v1_list_languages_params, + v1_translate_document_params, +) from ...types.translate.v1_detect_response import V1DetectResponse from ...types.translate.v1_translate_response import V1TranslateResponse from ...types.translate.v1_list_languages_response import V1ListLanguagesResponse @@ -27,6 +51,8 @@ class V1Resource(SyncAPIResource): + """Language detection and translation for multilingual legal workflows""" + @cached_property def with_raw_response(self) -> V1ResourceWithRawResponse: """ @@ -191,8 +217,68 @@ def translate( cast_to=V1TranslateResponse, ) + def translate_document( + self, + *, + file: FileTypes, + target: str, + source: str | Omit = omit, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> BinaryAPIResponse: + """Translate one TXT, DOCX, or searchable PDF document. + + DOCX and PDF translations + preserve the source document format and retain as much layout and formatting as + possible. + + Args: + file: TXT, DOCX, or searchable PDF document (max 20MB) + + target: Target BCP-47 language code + + source: Optional source BCP-47 language code. Auto-detected when omitted. + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + extra_headers = {"Accept": "application/octet-stream", **(extra_headers or {})} + body = deepcopy_with_paths( + { + "file": file, + "target": target, + "source": source, + }, + [["file"]], + ) + files = extract_files(cast(Mapping[str, object], body), paths=[["file"]]) + # It should be noted that the actual Content-Type header that will be + # sent to the server will contain a `boundary` parameter, e.g. + # multipart/form-data; boundary=---abc-- + extra_headers = {"Content-Type": "multipart/form-data", **(extra_headers or {})} + return self._post( + "/translate/v1/document", + body=maybe_transform(body, v1_translate_document_params.V1TranslateDocumentParams), + files=files, + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=BinaryAPIResponse, + ) + class AsyncV1Resource(AsyncAPIResource): + """Language detection and translation for multilingual legal workflows""" + @cached_property def with_raw_response(self) -> AsyncV1ResourceWithRawResponse: """ @@ -357,6 +443,64 @@ async def translate( cast_to=V1TranslateResponse, ) + async def translate_document( + self, + *, + file: FileTypes, + target: str, + source: str | Omit = omit, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> AsyncBinaryAPIResponse: + """Translate one TXT, DOCX, or searchable PDF document. + + DOCX and PDF translations + preserve the source document format and retain as much layout and formatting as + possible. + + Args: + file: TXT, DOCX, or searchable PDF document (max 20MB) + + target: Target BCP-47 language code + + source: Optional source BCP-47 language code. Auto-detected when omitted. + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + extra_headers = {"Accept": "application/octet-stream", **(extra_headers or {})} + body = deepcopy_with_paths( + { + "file": file, + "target": target, + "source": source, + }, + [["file"]], + ) + files = extract_files(cast(Mapping[str, object], body), paths=[["file"]]) + # It should be noted that the actual Content-Type header that will be + # sent to the server will contain a `boundary` parameter, e.g. + # multipart/form-data; boundary=---abc-- + extra_headers = {"Content-Type": "multipart/form-data", **(extra_headers or {})} + return await self._post( + "/translate/v1/document", + body=await async_maybe_transform(body, v1_translate_document_params.V1TranslateDocumentParams), + files=files, + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=AsyncBinaryAPIResponse, + ) + class V1ResourceWithRawResponse: def __init__(self, v1: V1Resource) -> None: @@ -371,6 +515,10 @@ def __init__(self, v1: V1Resource) -> None: self.translate = to_raw_response_wrapper( v1.translate, ) + self.translate_document = to_custom_raw_response_wrapper( + v1.translate_document, + BinaryAPIResponse, + ) class AsyncV1ResourceWithRawResponse: @@ -386,6 +534,10 @@ def __init__(self, v1: AsyncV1Resource) -> None: self.translate = async_to_raw_response_wrapper( v1.translate, ) + self.translate_document = async_to_custom_raw_response_wrapper( + v1.translate_document, + AsyncBinaryAPIResponse, + ) class V1ResourceWithStreamingResponse: @@ -401,6 +553,10 @@ def __init__(self, v1: V1Resource) -> None: self.translate = to_streamed_response_wrapper( v1.translate, ) + self.translate_document = to_custom_streamed_response_wrapper( + v1.translate_document, + StreamedBinaryAPIResponse, + ) class AsyncV1ResourceWithStreamingResponse: @@ -416,3 +572,7 @@ def __init__(self, v1: AsyncV1Resource) -> None: self.translate = async_to_streamed_response_wrapper( v1.translate, ) + self.translate_document = async_to_custom_streamed_response_wrapper( + v1.translate_document, + AsyncStreamedBinaryAPIResponse, + ) diff --git a/src/casedev/resources/vault/__init__.py b/src/casedev/resources/vault/__init__.py index 89502278..228888f6 100644 --- a/src/casedev/resources/vault/__init__.py +++ b/src/casedev/resources/vault/__init__.py @@ -40,14 +40,6 @@ ObjectsResourceWithStreamingResponse, AsyncObjectsResourceWithStreamingResponse, ) -from .graphrag import ( - GraphragResource, - AsyncGraphragResource, - GraphragResourceWithRawResponse, - AsyncGraphragResourceWithRawResponse, - GraphragResourceWithStreamingResponse, - AsyncGraphragResourceWithStreamingResponse, -) from .multipart import ( MultipartResource, AsyncMultipartResource, @@ -64,12 +56,6 @@ "AsyncEventsResourceWithRawResponse", "EventsResourceWithStreamingResponse", "AsyncEventsResourceWithStreamingResponse", - "GraphragResource", - "AsyncGraphragResource", - "GraphragResourceWithRawResponse", - "AsyncGraphragResourceWithRawResponse", - "GraphragResourceWithStreamingResponse", - "AsyncGraphragResourceWithStreamingResponse", "GroupsResource", "AsyncGroupsResource", "GroupsResourceWithRawResponse", diff --git a/src/casedev/resources/vault/events/events.py b/src/casedev/resources/vault/events/events.py index 99f36d96..e4e9be8e 100644 --- a/src/casedev/resources/vault/events/events.py +++ b/src/casedev/resources/vault/events/events.py @@ -19,7 +19,7 @@ class EventsResource(SyncAPIResource): @cached_property def subscriptions(self) -> SubscriptionsResource: - """Secure document storage with semantic search and GraphRAG""" + """Vault-scoped event subscriptions and delivery testing""" return SubscriptionsResource(self._client) @cached_property @@ -45,7 +45,7 @@ def with_streaming_response(self) -> EventsResourceWithStreamingResponse: class AsyncEventsResource(AsyncAPIResource): @cached_property def subscriptions(self) -> AsyncSubscriptionsResource: - """Secure document storage with semantic search and GraphRAG""" + """Vault-scoped event subscriptions and delivery testing""" return AsyncSubscriptionsResource(self._client) @cached_property @@ -74,7 +74,7 @@ def __init__(self, events: EventsResource) -> None: @cached_property def subscriptions(self) -> SubscriptionsResourceWithRawResponse: - """Secure document storage with semantic search and GraphRAG""" + """Vault-scoped event subscriptions and delivery testing""" return SubscriptionsResourceWithRawResponse(self._events.subscriptions) @@ -84,7 +84,7 @@ def __init__(self, events: AsyncEventsResource) -> None: @cached_property def subscriptions(self) -> AsyncSubscriptionsResourceWithRawResponse: - """Secure document storage with semantic search and GraphRAG""" + """Vault-scoped event subscriptions and delivery testing""" return AsyncSubscriptionsResourceWithRawResponse(self._events.subscriptions) @@ -94,7 +94,7 @@ def __init__(self, events: EventsResource) -> None: @cached_property def subscriptions(self) -> SubscriptionsResourceWithStreamingResponse: - """Secure document storage with semantic search and GraphRAG""" + """Vault-scoped event subscriptions and delivery testing""" return SubscriptionsResourceWithStreamingResponse(self._events.subscriptions) @@ -104,5 +104,5 @@ def __init__(self, events: AsyncEventsResource) -> None: @cached_property def subscriptions(self) -> AsyncSubscriptionsResourceWithStreamingResponse: - """Secure document storage with semantic search and GraphRAG""" + """Vault-scoped event subscriptions and delivery testing""" return AsyncSubscriptionsResourceWithStreamingResponse(self._events.subscriptions) diff --git a/src/casedev/resources/vault/events/subscriptions.py b/src/casedev/resources/vault/events/subscriptions.py index 8dd48cdd..22d1a550 100644 --- a/src/casedev/resources/vault/events/subscriptions.py +++ b/src/casedev/resources/vault/events/subscriptions.py @@ -23,7 +23,7 @@ class SubscriptionsResource(SyncAPIResource): - """Secure document storage with semantic search and GraphRAG""" + """Vault-scoped event subscriptions and delivery testing""" @cached_property def with_raw_response(self) -> SubscriptionsResourceWithRawResponse: @@ -301,7 +301,7 @@ def test( class AsyncSubscriptionsResource(AsyncAPIResource): - """Secure document storage with semantic search and GraphRAG""" + """Vault-scoped event subscriptions and delivery testing""" @cached_property def with_raw_response(self) -> AsyncSubscriptionsResourceWithRawResponse: diff --git a/src/casedev/resources/vault/memory.py b/src/casedev/resources/vault/memory.py index 96f66bc5..051458a5 100644 --- a/src/casedev/resources/vault/memory.py +++ b/src/casedev/resources/vault/memory.py @@ -27,7 +27,7 @@ class MemoryResource(SyncAPIResource): - """Secure document storage with semantic search and GraphRAG""" + """Vault-scoped persistent memory and semantic retrieval""" @cached_property def with_raw_response(self) -> MemoryResourceWithRawResponse: @@ -261,7 +261,7 @@ def search( class AsyncMemoryResource(AsyncAPIResource): - """Secure document storage with semantic search and GraphRAG""" + """Vault-scoped persistent memory and semantic retrieval""" @cached_property def with_raw_response(self) -> AsyncMemoryResourceWithRawResponse: diff --git a/src/casedev/resources/vault/objects.py b/src/casedev/resources/vault/objects.py index 40dfccba..159a8f62 100644 --- a/src/casedev/resources/vault/objects.py +++ b/src/casedev/resources/vault/objects.py @@ -27,34 +27,33 @@ ) from ...types.vault import ( object_list_params, + object_merge_params, object_append_params, object_delete_params, object_update_params, object_get_pages_params, - object_summarize_params, object_get_chunks_params, object_get_ocr_words_params, object_create_presigned_url_params, ) from ..._base_client import make_request_options from ...types.vault.object_list_response import ObjectListResponse +from ...types.vault.object_merge_response import ObjectMergeResponse from ...types.vault.object_append_response import ObjectAppendResponse from ...types.vault.object_delete_response import ObjectDeleteResponse from ...types.vault.object_update_response import ObjectUpdateResponse from ...types.vault.object_get_text_response import ObjectGetTextResponse from ...types.vault.object_retrieve_response import ObjectRetrieveResponse from ...types.vault.object_get_pages_response import ObjectGetPagesResponse -from ...types.vault.object_summarize_response import ObjectSummarizeResponse from ...types.vault.object_get_chunks_response import ObjectGetChunksResponse from ...types.vault.object_get_ocr_words_response import ObjectGetOcrWordsResponse -from ...types.vault.object_get_summarize_job_response import ObjectGetSummarizeJobResponse from ...types.vault.object_create_presigned_url_response import ObjectCreatePresignedURLResponse __all__ = ["ObjectsResource", "AsyncObjectsResource"] class ObjectsResource(SyncAPIResource): - """Secure document storage with semantic search and GraphRAG""" + """Vault object management, content access, and document operations""" @cached_property def with_raw_response(self) -> ObjectsResourceWithRawResponse: @@ -267,6 +266,7 @@ def append( append_object_ids: SequenceNotStr[str], back_links: bool | Omit = omit, back_links_text: str | Omit = omit, + bates: object_append_params.Bates | Omit = omit, rewrite_links: bool | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. @@ -291,6 +291,9 @@ def append( back_links_text: Label text for the back link. Used only when backLinks is true and rendered centered at the bottom of each appended page. + bates: Optional Bates stamping for appended source PDFs. Numbering is deterministic + across appendObjectIds order and does not stamp the target report pages. + rewrite_links: When true, rewrites links in the target object to internal PDF jumps when the URL contains exactly one appended object ID as a standalone query parameter value or decoded path segment. @@ -314,6 +317,7 @@ def append( "append_object_ids": append_object_ids, "back_links": back_links, "back_links_text": back_links_text, + "bates": bates, "rewrite_links": rewrite_links, }, object_append_params.ObjectAppendParams, @@ -609,47 +613,6 @@ def get_pages( cast_to=ObjectGetPagesResponse, ) - def get_summarize_job( - self, - job_id: str, - *, - id: str, - object_id: str, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> ObjectGetSummarizeJobResponse: - """ - Get the status of a CaseMark summary workflow job. - - Args: - extra_headers: Send extra headers - - extra_query: Add additional query parameters to the request - - extra_body: Add additional JSON properties to the request - - timeout: Override the client-level default timeout for this request, in seconds - """ - if not id: - raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") - if not object_id: - raise ValueError(f"Expected a non-empty value for `object_id` but received {object_id!r}") - if not job_id: - raise ValueError(f"Expected a non-empty value for `job_id` but received {job_id!r}") - return self._get( - path_template( - "/vault/{id}/objects/{object_id}/summarize/{job_id}", id=id, object_id=object_id, job_id=job_id - ), - options=make_request_options( - extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout - ), - cast_to=ObjectGetSummarizeJobResponse, - ) - def get_text( self, object_id: str, @@ -662,11 +625,11 @@ def get_text( extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> ObjectGetTextResponse: - """Retrieves the full extracted text content from a processed vault object. - - Returns - the concatenated text from all chunks, useful for document review, analysis, or - export. The object must have completed processing before text can be retrieved. + """ + Retrieves the full extracted text content from a processed vault object, + page-numbered (--- Page N --- markers) when the source document is paginated. + Useful for document review, analysis, or export. The object must have completed + processing before text can be retrieved. Args: extra_headers: Send extra headers @@ -689,29 +652,33 @@ def get_text( cast_to=ObjectGetTextResponse, ) - def summarize( + def merge( self, - object_id: str, - *, id: str, - output_format: Literal["PDF", "WORD"] | Omit = omit, - workflow_type: str | Omit = omit, + *, + filename: str, + source_object_ids: SequenceNotStr[str], + source_rendition: Literal["original", "searchable_pdf"], + idempotency_key: str, + bates: object_merge_params.Bates | Omit = omit, + client_reference: str | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> ObjectSummarizeResponse: - """ - Triggers a CaseMark AI workflow to summarize or analyze a document stored in the - vault. The workflow processes the document asynchronously and stores the result - as a new object in the same vault, linked to the original document. + ) -> ObjectMergeResponse: + """Starts an asynchronous merge that creates a new PDF vault object. + + Source objects + are unchanged. Missing searchable PDF renditions are generated on demand before + combining. Completion is reported through vault.object.merge webhooks. Args: - output_format: Output format for the summary document + filename: Output PDF filename - workflow_type: Type of CaseMark workflow to run + source_object_ids: Source object IDs in output order extra_headers: Send extra headers @@ -723,26 +690,28 @@ def summarize( """ if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") - if not object_id: - raise ValueError(f"Expected a non-empty value for `object_id` but received {object_id!r}") + extra_headers = {"Idempotency-Key": idempotency_key, **(extra_headers or {})} return self._post( - path_template("/vault/{id}/objects/{object_id}/summarize", id=id, object_id=object_id), + path_template("/vault/{id}/objects/merge", id=id), body=maybe_transform( { - "output_format": output_format, - "workflow_type": workflow_type, + "filename": filename, + "source_object_ids": source_object_ids, + "source_rendition": source_rendition, + "bates": bates, + "client_reference": client_reference, }, - object_summarize_params.ObjectSummarizeParams, + object_merge_params.ObjectMergeParams, ), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), - cast_to=ObjectSummarizeResponse, + cast_to=ObjectMergeResponse, ) class AsyncObjectsResource(AsyncAPIResource): - """Secure document storage with semantic search and GraphRAG""" + """Vault object management, content access, and document operations""" @cached_property def with_raw_response(self) -> AsyncObjectsResourceWithRawResponse: @@ -955,6 +924,7 @@ async def append( append_object_ids: SequenceNotStr[str], back_links: bool | Omit = omit, back_links_text: str | Omit = omit, + bates: object_append_params.Bates | Omit = omit, rewrite_links: bool | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. @@ -979,6 +949,9 @@ async def append( back_links_text: Label text for the back link. Used only when backLinks is true and rendered centered at the bottom of each appended page. + bates: Optional Bates stamping for appended source PDFs. Numbering is deterministic + across appendObjectIds order and does not stamp the target report pages. + rewrite_links: When true, rewrites links in the target object to internal PDF jumps when the URL contains exactly one appended object ID as a standalone query parameter value or decoded path segment. @@ -1002,6 +975,7 @@ async def append( "append_object_ids": append_object_ids, "back_links": back_links, "back_links_text": back_links_text, + "bates": bates, "rewrite_links": rewrite_links, }, object_append_params.ObjectAppendParams, @@ -1297,47 +1271,6 @@ async def get_pages( cast_to=ObjectGetPagesResponse, ) - async def get_summarize_job( - self, - job_id: str, - *, - id: str, - object_id: str, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> ObjectGetSummarizeJobResponse: - """ - Get the status of a CaseMark summary workflow job. - - Args: - extra_headers: Send extra headers - - extra_query: Add additional query parameters to the request - - extra_body: Add additional JSON properties to the request - - timeout: Override the client-level default timeout for this request, in seconds - """ - if not id: - raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") - if not object_id: - raise ValueError(f"Expected a non-empty value for `object_id` but received {object_id!r}") - if not job_id: - raise ValueError(f"Expected a non-empty value for `job_id` but received {job_id!r}") - return await self._get( - path_template( - "/vault/{id}/objects/{object_id}/summarize/{job_id}", id=id, object_id=object_id, job_id=job_id - ), - options=make_request_options( - extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout - ), - cast_to=ObjectGetSummarizeJobResponse, - ) - async def get_text( self, object_id: str, @@ -1350,11 +1283,11 @@ async def get_text( extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> ObjectGetTextResponse: - """Retrieves the full extracted text content from a processed vault object. - - Returns - the concatenated text from all chunks, useful for document review, analysis, or - export. The object must have completed processing before text can be retrieved. + """ + Retrieves the full extracted text content from a processed vault object, + page-numbered (--- Page N --- markers) when the source document is paginated. + Useful for document review, analysis, or export. The object must have completed + processing before text can be retrieved. Args: extra_headers: Send extra headers @@ -1377,29 +1310,33 @@ async def get_text( cast_to=ObjectGetTextResponse, ) - async def summarize( + async def merge( self, - object_id: str, - *, id: str, - output_format: Literal["PDF", "WORD"] | Omit = omit, - workflow_type: str | Omit = omit, + *, + filename: str, + source_object_ids: SequenceNotStr[str], + source_rendition: Literal["original", "searchable_pdf"], + idempotency_key: str, + bates: object_merge_params.Bates | Omit = omit, + client_reference: str | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> ObjectSummarizeResponse: - """ - Triggers a CaseMark AI workflow to summarize or analyze a document stored in the - vault. The workflow processes the document asynchronously and stores the result - as a new object in the same vault, linked to the original document. + ) -> ObjectMergeResponse: + """Starts an asynchronous merge that creates a new PDF vault object. + + Source objects + are unchanged. Missing searchable PDF renditions are generated on demand before + combining. Completion is reported through vault.object.merge webhooks. Args: - output_format: Output format for the summary document + filename: Output PDF filename - workflow_type: Type of CaseMark workflow to run + source_object_ids: Source object IDs in output order extra_headers: Send extra headers @@ -1411,21 +1348,23 @@ async def summarize( """ if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") - if not object_id: - raise ValueError(f"Expected a non-empty value for `object_id` but received {object_id!r}") + extra_headers = {"Idempotency-Key": idempotency_key, **(extra_headers or {})} return await self._post( - path_template("/vault/{id}/objects/{object_id}/summarize", id=id, object_id=object_id), + path_template("/vault/{id}/objects/merge", id=id), body=await async_maybe_transform( { - "output_format": output_format, - "workflow_type": workflow_type, + "filename": filename, + "source_object_ids": source_object_ids, + "source_rendition": source_rendition, + "bates": bates, + "client_reference": client_reference, }, - object_summarize_params.ObjectSummarizeParams, + object_merge_params.ObjectMergeParams, ), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), - cast_to=ObjectSummarizeResponse, + cast_to=ObjectMergeResponse, ) @@ -1464,14 +1403,11 @@ def __init__(self, objects: ObjectsResource) -> None: self.get_pages = to_raw_response_wrapper( objects.get_pages, ) - self.get_summarize_job = to_raw_response_wrapper( - objects.get_summarize_job, - ) self.get_text = to_raw_response_wrapper( objects.get_text, ) - self.summarize = to_raw_response_wrapper( - objects.summarize, + self.merge = to_raw_response_wrapper( + objects.merge, ) @@ -1510,14 +1446,11 @@ def __init__(self, objects: AsyncObjectsResource) -> None: self.get_pages = async_to_raw_response_wrapper( objects.get_pages, ) - self.get_summarize_job = async_to_raw_response_wrapper( - objects.get_summarize_job, - ) self.get_text = async_to_raw_response_wrapper( objects.get_text, ) - self.summarize = async_to_raw_response_wrapper( - objects.summarize, + self.merge = async_to_raw_response_wrapper( + objects.merge, ) @@ -1556,14 +1489,11 @@ def __init__(self, objects: ObjectsResource) -> None: self.get_pages = to_streamed_response_wrapper( objects.get_pages, ) - self.get_summarize_job = to_streamed_response_wrapper( - objects.get_summarize_job, - ) self.get_text = to_streamed_response_wrapper( objects.get_text, ) - self.summarize = to_streamed_response_wrapper( - objects.summarize, + self.merge = to_streamed_response_wrapper( + objects.merge, ) @@ -1602,12 +1532,9 @@ def __init__(self, objects: AsyncObjectsResource) -> None: self.get_pages = async_to_streamed_response_wrapper( objects.get_pages, ) - self.get_summarize_job = async_to_streamed_response_wrapper( - objects.get_summarize_job, - ) self.get_text = async_to_streamed_response_wrapper( objects.get_text, ) - self.summarize = async_to_streamed_response_wrapper( - objects.summarize, + self.merge = async_to_streamed_response_wrapper( + objects.merge, ) diff --git a/src/casedev/resources/vault/vault.py b/src/casedev/resources/vault/vault.py index 2220a868..3298dd52 100644 --- a/src/casedev/resources/vault/vault.py +++ b/src/casedev/resources/vault/vault.py @@ -3,7 +3,7 @@ from __future__ import annotations from typing import Optional -from typing_extensions import Literal, overload +from typing_extensions import Literal import httpx @@ -40,15 +40,7 @@ AsyncObjectsResourceWithStreamingResponse, ) from ..._types import Body, Omit, Query, Headers, NotGiven, omit, not_given -from ..._utils import path_template, required_args, maybe_transform, async_maybe_transform -from .graphrag import ( - GraphragResource, - AsyncGraphragResource, - GraphragResourceWithRawResponse, - AsyncGraphragResourceWithRawResponse, - GraphragResourceWithStreamingResponse, - AsyncGraphragResourceWithStreamingResponse, -) +from ..._utils import path_template, maybe_transform, strip_not_given, async_maybe_transform from ..._compat import cached_property from .multipart import ( MultipartResource, @@ -94,11 +86,6 @@ class VaultResource(SyncAPIResource): def events(self) -> EventsResource: return EventsResource(self._client) - @cached_property - def graphrag(self) -> GraphragResource: - """Secure document storage with semantic search and GraphRAG""" - return GraphragResource(self._client) - @cached_property def groups(self) -> GroupsResource: """Secure document storage with semantic search and GraphRAG""" @@ -111,12 +98,12 @@ def multipart(self) -> MultipartResource: @cached_property def objects(self) -> ObjectsResource: - """Secure document storage with semantic search and GraphRAG""" + """Vault object management, content access, and document operations""" return ObjectsResource(self._client) @cached_property def memory(self) -> MemoryResource: - """Secure document storage with semantic search and GraphRAG""" + """Vault-scoped persistent memory and semantic retrieval""" return MemoryResource(self._client) @cached_property @@ -383,16 +370,17 @@ def delete( cast_to=VaultDeleteResponse, ) - @overload def confirm_upload( self, object_id: str, *, id: str, - size_bytes: int, - success: Literal[True], + success: bool, auto_ingest: bool | Omit = omit, + error_code: str | Omit = omit, + error_message: str | Omit = omit, etag: str | Omit = omit, + size_bytes: int | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, @@ -404,11 +392,11 @@ def confirm_upload( This endpoint emits vault.upload.completed or vault.upload.failed events and is idempotent for - repeated confirmations. + repeated confirmations. Conditional fields: when success=true, sizeBytes is + required; when success=false, errorCode and errorMessage are required. These + rules are enforced server-side with specific 400 responses. Args: - size_bytes: Uploaded file size in bytes - success: Whether the upload succeeded auto_ingest: When true and the object was uploaded with auto_index, trigger ingestion @@ -416,46 +404,14 @@ def confirm_upload( The ingest outcome is reported in the `ingest` response field; an ingest failure does not fail the confirmation. - etag: S3 ETag for the uploaded object (optional if client cannot access ETag header) - - extra_headers: Send extra headers - - extra_query: Add additional query parameters to the request - - extra_body: Add additional JSON properties to the request - - timeout: Override the client-level default timeout for this request, in seconds - """ - ... - - @overload - def confirm_upload( - self, - object_id: str, - *, - id: str, - error_code: str, - error_message: str, - success: Literal[False], - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> VaultConfirmUploadResponse: - """Confirm whether a direct-to-S3 vault upload succeeded or failed. - - This endpoint - emits vault.upload.completed or vault.upload.failed events and is idempotent for - repeated confirmations. + error_code: Client-side error code. Required when success=false. - Args: - error_code: Client-side error code + error_message: Client-side error message. Required when success=false. - error_message: Client-side error message + etag: S3 ETag for the uploaded object (optional if client cannot access ETag header). + Only meaningful when success=true. - success: Whether the upload succeeded + size_bytes: Uploaded file size in bytes. Required when success=true. extra_headers: Send extra headers @@ -465,27 +421,6 @@ def confirm_upload( timeout: Override the client-level default timeout for this request, in seconds """ - ... - - @required_args(["id", "size_bytes", "success"], ["id", "error_code", "error_message", "success"]) - def confirm_upload( - self, - object_id: str, - *, - id: str, - size_bytes: int | Omit = omit, - success: Literal[True] | Literal[False], - auto_ingest: bool | Omit = omit, - etag: str | Omit = omit, - error_code: str | Omit = omit, - error_message: str | Omit = omit, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> VaultConfirmUploadResponse: if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") if not object_id: @@ -494,12 +429,12 @@ def confirm_upload( path_template("/vault/{id}/upload/{object_id}/confirm", id=id, object_id=object_id), body=maybe_transform( { - "size_bytes": size_bytes, "success": success, "auto_ingest": auto_ingest, - "etag": etag, "error_code": error_code, "error_message": error_message, + "etag": etag, + "size_bytes": size_bytes, }, vault_confirm_upload_params.VaultConfirmUploadParams, ), @@ -529,8 +464,7 @@ def ingest( recursively up to 5 levels, and each extracted file is created as an independent vault object and ingested via the normal pipeline. For unsupported types (images, etc.), the file is marked as completed immediately without text - extraction. GraphRAG indexing must be triggered separately via POST - /vault/:id/graphrag/:objectId. + extraction. Args: extra_headers: Send extra headers @@ -623,6 +557,7 @@ def upload( metadata: object | Omit = omit, path: str | Omit = omit, size_bytes: int | Omit = omit, + idempotency_key: str | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, @@ -665,6 +600,7 @@ def upload( """ if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") + extra_headers = {**strip_not_given({"Idempotency-Key": idempotency_key}), **(extra_headers or {})} return self._post( path_template("/vault/{id}/upload", id=id), body=maybe_transform( @@ -693,11 +629,6 @@ class AsyncVaultResource(AsyncAPIResource): def events(self) -> AsyncEventsResource: return AsyncEventsResource(self._client) - @cached_property - def graphrag(self) -> AsyncGraphragResource: - """Secure document storage with semantic search and GraphRAG""" - return AsyncGraphragResource(self._client) - @cached_property def groups(self) -> AsyncGroupsResource: """Secure document storage with semantic search and GraphRAG""" @@ -710,12 +641,12 @@ def multipart(self) -> AsyncMultipartResource: @cached_property def objects(self) -> AsyncObjectsResource: - """Secure document storage with semantic search and GraphRAG""" + """Vault object management, content access, and document operations""" return AsyncObjectsResource(self._client) @cached_property def memory(self) -> AsyncMemoryResource: - """Secure document storage with semantic search and GraphRAG""" + """Vault-scoped persistent memory and semantic retrieval""" return AsyncMemoryResource(self._client) @cached_property @@ -982,16 +913,17 @@ async def delete( cast_to=VaultDeleteResponse, ) - @overload async def confirm_upload( self, object_id: str, *, id: str, - size_bytes: int, - success: Literal[True], + success: bool, auto_ingest: bool | Omit = omit, + error_code: str | Omit = omit, + error_message: str | Omit = omit, etag: str | Omit = omit, + size_bytes: int | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, @@ -1003,11 +935,11 @@ async def confirm_upload( This endpoint emits vault.upload.completed or vault.upload.failed events and is idempotent for - repeated confirmations. + repeated confirmations. Conditional fields: when success=true, sizeBytes is + required; when success=false, errorCode and errorMessage are required. These + rules are enforced server-side with specific 400 responses. Args: - size_bytes: Uploaded file size in bytes - success: Whether the upload succeeded auto_ingest: When true and the object was uploaded with auto_index, trigger ingestion @@ -1015,46 +947,14 @@ async def confirm_upload( The ingest outcome is reported in the `ingest` response field; an ingest failure does not fail the confirmation. - etag: S3 ETag for the uploaded object (optional if client cannot access ETag header) + error_code: Client-side error code. Required when success=false. - extra_headers: Send extra headers + error_message: Client-side error message. Required when success=false. - extra_query: Add additional query parameters to the request - - extra_body: Add additional JSON properties to the request + etag: S3 ETag for the uploaded object (optional if client cannot access ETag header). + Only meaningful when success=true. - timeout: Override the client-level default timeout for this request, in seconds - """ - ... - - @overload - async def confirm_upload( - self, - object_id: str, - *, - id: str, - error_code: str, - error_message: str, - success: Literal[False], - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> VaultConfirmUploadResponse: - """Confirm whether a direct-to-S3 vault upload succeeded or failed. - - This endpoint - emits vault.upload.completed or vault.upload.failed events and is idempotent for - repeated confirmations. - - Args: - error_code: Client-side error code - - error_message: Client-side error message - - success: Whether the upload succeeded + size_bytes: Uploaded file size in bytes. Required when success=true. extra_headers: Send extra headers @@ -1064,27 +964,6 @@ async def confirm_upload( timeout: Override the client-level default timeout for this request, in seconds """ - ... - - @required_args(["id", "size_bytes", "success"], ["id", "error_code", "error_message", "success"]) - async def confirm_upload( - self, - object_id: str, - *, - id: str, - size_bytes: int | Omit = omit, - success: Literal[True] | Literal[False], - auto_ingest: bool | Omit = omit, - etag: str | Omit = omit, - error_code: str | Omit = omit, - error_message: str | Omit = omit, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> VaultConfirmUploadResponse: if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") if not object_id: @@ -1093,12 +972,12 @@ async def confirm_upload( path_template("/vault/{id}/upload/{object_id}/confirm", id=id, object_id=object_id), body=await async_maybe_transform( { - "size_bytes": size_bytes, "success": success, "auto_ingest": auto_ingest, - "etag": etag, "error_code": error_code, "error_message": error_message, + "etag": etag, + "size_bytes": size_bytes, }, vault_confirm_upload_params.VaultConfirmUploadParams, ), @@ -1128,8 +1007,7 @@ async def ingest( recursively up to 5 levels, and each extracted file is created as an independent vault object and ingested via the normal pipeline. For unsupported types (images, etc.), the file is marked as completed immediately without text - extraction. GraphRAG indexing must be triggered separately via POST - /vault/:id/graphrag/:objectId. + extraction. Args: extra_headers: Send extra headers @@ -1222,6 +1100,7 @@ async def upload( metadata: object | Omit = omit, path: str | Omit = omit, size_bytes: int | Omit = omit, + idempotency_key: str | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, @@ -1264,6 +1143,7 @@ async def upload( """ if not id: raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") + extra_headers = {**strip_not_given({"Idempotency-Key": idempotency_key}), **(extra_headers or {})} return await self._post( path_template("/vault/{id}/upload", id=id), body=await async_maybe_transform( @@ -1321,11 +1201,6 @@ def __init__(self, vault: VaultResource) -> None: def events(self) -> EventsResourceWithRawResponse: return EventsResourceWithRawResponse(self._vault.events) - @cached_property - def graphrag(self) -> GraphragResourceWithRawResponse: - """Secure document storage with semantic search and GraphRAG""" - return GraphragResourceWithRawResponse(self._vault.graphrag) - @cached_property def groups(self) -> GroupsResourceWithRawResponse: """Secure document storage with semantic search and GraphRAG""" @@ -1338,12 +1213,12 @@ def multipart(self) -> MultipartResourceWithRawResponse: @cached_property def objects(self) -> ObjectsResourceWithRawResponse: - """Secure document storage with semantic search and GraphRAG""" + """Vault object management, content access, and document operations""" return ObjectsResourceWithRawResponse(self._vault.objects) @cached_property def memory(self) -> MemoryResourceWithRawResponse: - """Secure document storage with semantic search and GraphRAG""" + """Vault-scoped persistent memory and semantic retrieval""" return MemoryResourceWithRawResponse(self._vault.memory) @@ -1383,11 +1258,6 @@ def __init__(self, vault: AsyncVaultResource) -> None: def events(self) -> AsyncEventsResourceWithRawResponse: return AsyncEventsResourceWithRawResponse(self._vault.events) - @cached_property - def graphrag(self) -> AsyncGraphragResourceWithRawResponse: - """Secure document storage with semantic search and GraphRAG""" - return AsyncGraphragResourceWithRawResponse(self._vault.graphrag) - @cached_property def groups(self) -> AsyncGroupsResourceWithRawResponse: """Secure document storage with semantic search and GraphRAG""" @@ -1400,12 +1270,12 @@ def multipart(self) -> AsyncMultipartResourceWithRawResponse: @cached_property def objects(self) -> AsyncObjectsResourceWithRawResponse: - """Secure document storage with semantic search and GraphRAG""" + """Vault object management, content access, and document operations""" return AsyncObjectsResourceWithRawResponse(self._vault.objects) @cached_property def memory(self) -> AsyncMemoryResourceWithRawResponse: - """Secure document storage with semantic search and GraphRAG""" + """Vault-scoped persistent memory and semantic retrieval""" return AsyncMemoryResourceWithRawResponse(self._vault.memory) @@ -1445,11 +1315,6 @@ def __init__(self, vault: VaultResource) -> None: def events(self) -> EventsResourceWithStreamingResponse: return EventsResourceWithStreamingResponse(self._vault.events) - @cached_property - def graphrag(self) -> GraphragResourceWithStreamingResponse: - """Secure document storage with semantic search and GraphRAG""" - return GraphragResourceWithStreamingResponse(self._vault.graphrag) - @cached_property def groups(self) -> GroupsResourceWithStreamingResponse: """Secure document storage with semantic search and GraphRAG""" @@ -1462,12 +1327,12 @@ def multipart(self) -> MultipartResourceWithStreamingResponse: @cached_property def objects(self) -> ObjectsResourceWithStreamingResponse: - """Secure document storage with semantic search and GraphRAG""" + """Vault object management, content access, and document operations""" return ObjectsResourceWithStreamingResponse(self._vault.objects) @cached_property def memory(self) -> MemoryResourceWithStreamingResponse: - """Secure document storage with semantic search and GraphRAG""" + """Vault-scoped persistent memory and semantic retrieval""" return MemoryResourceWithStreamingResponse(self._vault.memory) @@ -1507,11 +1372,6 @@ def __init__(self, vault: AsyncVaultResource) -> None: def events(self) -> AsyncEventsResourceWithStreamingResponse: return AsyncEventsResourceWithStreamingResponse(self._vault.events) - @cached_property - def graphrag(self) -> AsyncGraphragResourceWithStreamingResponse: - """Secure document storage with semantic search and GraphRAG""" - return AsyncGraphragResourceWithStreamingResponse(self._vault.graphrag) - @cached_property def groups(self) -> AsyncGroupsResourceWithStreamingResponse: """Secure document storage with semantic search and GraphRAG""" @@ -1524,10 +1384,10 @@ def multipart(self) -> AsyncMultipartResourceWithStreamingResponse: @cached_property def objects(self) -> AsyncObjectsResourceWithStreamingResponse: - """Secure document storage with semantic search and GraphRAG""" + """Vault object management, content access, and document operations""" return AsyncObjectsResourceWithStreamingResponse(self._vault.objects) @cached_property def memory(self) -> AsyncMemoryResourceWithStreamingResponse: - """Secure document storage with semantic search and GraphRAG""" + """Vault-scoped persistent memory and semantic retrieval""" return AsyncMemoryResourceWithStreamingResponse(self._vault.memory) diff --git a/src/casedev/resources/voice/transcription.py b/src/casedev/resources/voice/transcription.py index b59a94e1..5abd518d 100644 --- a/src/casedev/resources/voice/transcription.py +++ b/src/casedev/resources/voice/transcription.py @@ -71,13 +71,15 @@ def create( extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> TranscriptionCreateResponse: - """Creates an asynchronous transcription job for audio files. + """Creates an asynchronous transcription job for audio or video files. - Supports two modes: + Supports two + modes: **Vault-based (recommended)**: Pass `vault_id` and `object_id` to transcribe - audio from your vault. The transcript will automatically be saved back to the - vault when complete. + media from your vault. Large videos are converted to an internal MP3 derivative + before transcription while the original video remains the transcript source. The + transcript is automatically saved back to the vault when complete. **Direct URL (legacy)**: Pass `audio_url` for direct transcription without automatic storage. @@ -280,13 +282,15 @@ async def create( extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> TranscriptionCreateResponse: - """Creates an asynchronous transcription job for audio files. + """Creates an asynchronous transcription job for audio or video files. - Supports two modes: + Supports two + modes: **Vault-based (recommended)**: Pass `vault_id` and `object_id` to transcribe - audio from your vault. The transcript will automatically be saved back to the - vault when complete. + media from your vault. Large videos are converted to an internal MP3 derivative + before transcription while the original video remains the transcript source. The + transcript is automatically saved back to the vault when complete. **Direct URL (legacy)**: Pass `audio_url` for direct transcription without automatic storage. diff --git a/src/casedev/types/agent/v1/__init__.py b/src/casedev/types/agent/v1/__init__.py deleted file mode 100644 index 0945cf54..00000000 --- a/src/casedev/types/agent/v1/__init__.py +++ /dev/null @@ -1,26 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from __future__ import annotations - -from .run_list_params import RunListParams as RunListParams -from .run_watch_params import RunWatchParams as RunWatchParams -from .agent_list_params import AgentListParams as AgentListParams -from .run_create_params import RunCreateParams as RunCreateParams -from .run_events_params import RunEventsParams as RunEventsParams -from .run_exec_response import RunExecResponse as RunExecResponse -from .run_list_response import RunListResponse as RunListResponse -from .run_watch_response import RunWatchResponse as RunWatchResponse -from .agent_create_params import AgentCreateParams as AgentCreateParams -from .agent_list_response import AgentListResponse as AgentListResponse -from .agent_update_params import AgentUpdateParams as AgentUpdateParams -from .run_cancel_response import RunCancelResponse as RunCancelResponse -from .run_create_response import RunCreateResponse as RunCreateResponse -from .run_events_response import RunEventsResponse as RunEventsResponse -from .agent_create_response import AgentCreateResponse as AgentCreateResponse -from .agent_delete_response import AgentDeleteResponse as AgentDeleteResponse -from .agent_update_response import AgentUpdateResponse as AgentUpdateResponse -from .execute_create_params import ExecuteCreateParams as ExecuteCreateParams -from .agent_retrieve_response import AgentRetrieveResponse as AgentRetrieveResponse -from .execute_create_response import ExecuteCreateResponse as ExecuteCreateResponse -from .run_get_status_response import RunGetStatusResponse as RunGetStatusResponse -from .run_get_details_response import RunGetDetailsResponse as RunGetDetailsResponse diff --git a/src/casedev/types/agent/v1/agent_create_params.py b/src/casedev/types/agent/v1/agent_create_params.py deleted file mode 100644 index 35829b58..00000000 --- a/src/casedev/types/agent/v1/agent_create_params.py +++ /dev/null @@ -1,59 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from __future__ import annotations - -from typing import Optional -from typing_extensions import Required, Annotated, TypedDict - -from ...._types import SequenceNotStr -from ...._utils import PropertyInfo - -__all__ = ["AgentCreateParams", "Sandbox"] - - -class AgentCreateParams(TypedDict, total=False): - instructions: Required[str] - """System instructions that define agent behavior""" - - name: Required[str] - """Display name for the agent""" - - description: str - """Optional description of the agent""" - - disabled_tools: Annotated[Optional[SequenceNotStr[str]], PropertyInfo(alias="disabledTools")] - """Denylist of tools the agent cannot use. - - Mutually exclusive with enabledTools — set one or the other, not both. - """ - - enabled_tools: Annotated[Optional[SequenceNotStr[str]], PropertyInfo(alias="enabledTools")] - """Allowlist of tools the agent can use. - - Mutually exclusive with disabledTools — set one or the other, not both. - """ - - model: str - """LLM model identifier (e.g. - - anthropic/claude-sonnet-4.6). Defaults to anthropic/claude-sonnet-4.6 - """ - - sandbox: Optional[Sandbox] - """Custom sandbox configuration (cpu, memoryMiB)""" - - vault_groups: Annotated[Optional[SequenceNotStr[str]], PropertyInfo(alias="vaultGroups")] - """Restrict agent to vaults within specific vault group IDs""" - - vault_ids: Annotated[Optional[SequenceNotStr[str]], PropertyInfo(alias="vaultIds")] - """Restrict agent to specific vault IDs""" - - -class Sandbox(TypedDict, total=False): - """Custom sandbox configuration (cpu, memoryMiB)""" - - cpu: int - """Number of CPUs""" - - memory_mi_b: Annotated[int, PropertyInfo(alias="memoryMiB")] - """Memory in MiB""" diff --git a/src/casedev/types/agent/v1/agent_create_response.py b/src/casedev/types/agent/v1/agent_create_response.py deleted file mode 100644 index e905bb0c..00000000 --- a/src/casedev/types/agent/v1/agent_create_response.py +++ /dev/null @@ -1,34 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from typing import List, Optional -from datetime import datetime - -from pydantic import Field as FieldInfo - -from ...._models import BaseModel - -__all__ = ["AgentCreateResponse"] - - -class AgentCreateResponse(BaseModel): - id: Optional[str] = None - - created_at: Optional[datetime] = FieldInfo(alias="createdAt", default=None) - - description: Optional[str] = None - - disabled_tools: Optional[List[str]] = FieldInfo(alias="disabledTools", default=None) - - enabled_tools: Optional[List[str]] = FieldInfo(alias="enabledTools", default=None) - - instructions: Optional[str] = None - - model: Optional[str] = None - - name: Optional[str] = None - - sandbox: Optional[object] = None - - updated_at: Optional[datetime] = FieldInfo(alias="updatedAt", default=None) - - vault_ids: Optional[List[str]] = FieldInfo(alias="vaultIds", default=None) diff --git a/src/casedev/types/agent/v1/agent_delete_response.py b/src/casedev/types/agent/v1/agent_delete_response.py deleted file mode 100644 index 148d8f52..00000000 --- a/src/casedev/types/agent/v1/agent_delete_response.py +++ /dev/null @@ -1,11 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from typing import Optional - -from ...._models import BaseModel - -__all__ = ["AgentDeleteResponse"] - - -class AgentDeleteResponse(BaseModel): - ok: Optional[bool] = None diff --git a/src/casedev/types/agent/v1/agent_list_params.py b/src/casedev/types/agent/v1/agent_list_params.py deleted file mode 100644 index f41fc45d..00000000 --- a/src/casedev/types/agent/v1/agent_list_params.py +++ /dev/null @@ -1,18 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from __future__ import annotations - -from typing_extensions import TypedDict - -__all__ = ["AgentListParams"] - - -class AgentListParams(TypedDict, total=False): - cursor: str - """Pagination cursor (agent ID from previous page). - - Returns agents created before this agent. - """ - - limit: int - """Maximum number of agents to return (default 50, max 250)""" diff --git a/src/casedev/types/agent/v1/agent_list_response.py b/src/casedev/types/agent/v1/agent_list_response.py deleted file mode 100644 index cba2c4b1..00000000 --- a/src/casedev/types/agent/v1/agent_list_response.py +++ /dev/null @@ -1,37 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from typing import List, Optional -from datetime import datetime - -from pydantic import Field as FieldInfo - -from ...._models import BaseModel - -__all__ = ["AgentListResponse", "Agent"] - - -class Agent(BaseModel): - id: Optional[str] = None - - created_at: Optional[datetime] = FieldInfo(alias="createdAt", default=None) - - description: Optional[str] = None - - is_active: Optional[bool] = FieldInfo(alias="isActive", default=None) - - model: Optional[str] = None - - name: Optional[str] = None - - updated_at: Optional[datetime] = FieldInfo(alias="updatedAt", default=None) - - vault_ids: Optional[List[str]] = FieldInfo(alias="vaultIds", default=None) - - -class AgentListResponse(BaseModel): - agents: Optional[List[Agent]] = None - - has_more: Optional[bool] = FieldInfo(alias="hasMore", default=None) - - next_cursor: Optional[str] = FieldInfo(alias="nextCursor", default=None) - """Pass as cursor to fetch the next page""" diff --git a/src/casedev/types/agent/v1/agent_retrieve_response.py b/src/casedev/types/agent/v1/agent_retrieve_response.py deleted file mode 100644 index 4c8fc445..00000000 --- a/src/casedev/types/agent/v1/agent_retrieve_response.py +++ /dev/null @@ -1,36 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from typing import List, Optional -from datetime import datetime - -from pydantic import Field as FieldInfo - -from ...._models import BaseModel - -__all__ = ["AgentRetrieveResponse"] - - -class AgentRetrieveResponse(BaseModel): - id: Optional[str] = None - - created_at: Optional[datetime] = FieldInfo(alias="createdAt", default=None) - - description: Optional[str] = None - - disabled_tools: Optional[List[str]] = FieldInfo(alias="disabledTools", default=None) - - enabled_tools: Optional[List[str]] = FieldInfo(alias="enabledTools", default=None) - - instructions: Optional[str] = None - - is_active: Optional[bool] = FieldInfo(alias="isActive", default=None) - - model: Optional[str] = None - - name: Optional[str] = None - - sandbox: Optional[object] = None - - updated_at: Optional[datetime] = FieldInfo(alias="updatedAt", default=None) - - vault_ids: Optional[List[str]] = FieldInfo(alias="vaultIds", default=None) diff --git a/src/casedev/types/agent/v1/agent_update_params.py b/src/casedev/types/agent/v1/agent_update_params.py deleted file mode 100644 index 5084402d..00000000 --- a/src/casedev/types/agent/v1/agent_update_params.py +++ /dev/null @@ -1,48 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from __future__ import annotations - -from typing import Optional -from typing_extensions import Annotated, TypedDict - -from ...._types import SequenceNotStr -from ...._utils import PropertyInfo - -__all__ = ["AgentUpdateParams"] - - -class AgentUpdateParams(TypedDict, total=False): - description: Optional[str] - """Updated agent description. Pass null to clear if supported by the client.""" - - disabled_tools: Annotated[Optional[SequenceNotStr[str]], PropertyInfo(alias="disabledTools")] - """Denylist of tools the agent cannot use. - - Mutually exclusive with enabledTools — set one or the other, not both. Pass null - to clear. - """ - - enabled_tools: Annotated[Optional[SequenceNotStr[str]], PropertyInfo(alias="enabledTools")] - """Allowlist of tools the agent can use. - - Mutually exclusive with disabledTools — set one or the other, not both. Pass - null to clear. - """ - - instructions: str - """Updated system instructions that guide agent behavior""" - - model: str - """Model identifier the agent should use for future runs""" - - name: str - """Updated agent display name""" - - sandbox: Optional[object] - """Sandbox configuration override for future agent runs. Pass null to clear.""" - - vault_groups: Annotated[Optional[SequenceNotStr[str]], PropertyInfo(alias="vaultGroups")] - """Vault group IDs the agent can access. Pass null to clear.""" - - vault_ids: Annotated[Optional[SequenceNotStr[str]], PropertyInfo(alias="vaultIds")] - """Vault IDs the agent can access directly. Pass null to clear.""" diff --git a/src/casedev/types/agent/v1/agent_update_response.py b/src/casedev/types/agent/v1/agent_update_response.py deleted file mode 100644 index 8f6ddb17..00000000 --- a/src/casedev/types/agent/v1/agent_update_response.py +++ /dev/null @@ -1,38 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from typing import List, Optional -from datetime import datetime - -from pydantic import Field as FieldInfo - -from ...._models import BaseModel - -__all__ = ["AgentUpdateResponse"] - - -class AgentUpdateResponse(BaseModel): - id: Optional[str] = None - - created_at: Optional[datetime] = FieldInfo(alias="createdAt", default=None) - - description: Optional[str] = None - - disabled_tools: Optional[List[str]] = FieldInfo(alias="disabledTools", default=None) - - enabled_tools: Optional[List[str]] = FieldInfo(alias="enabledTools", default=None) - - instructions: Optional[str] = None - - is_active: Optional[bool] = FieldInfo(alias="isActive", default=None) - - model: Optional[str] = None - - name: Optional[str] = None - - sandbox: Optional[object] = None - - updated_at: Optional[datetime] = FieldInfo(alias="updatedAt", default=None) - - vault_groups: Optional[List[str]] = FieldInfo(alias="vaultGroups", default=None) - - vault_ids: Optional[List[str]] = FieldInfo(alias="vaultIds", default=None) diff --git a/src/casedev/types/agent/v1/execute_create_params.py b/src/casedev/types/agent/v1/execute_create_params.py deleted file mode 100644 index de00ee22..00000000 --- a/src/casedev/types/agent/v1/execute_create_params.py +++ /dev/null @@ -1,62 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from __future__ import annotations - -from typing import Optional -from typing_extensions import Required, Annotated, TypedDict - -from ...._types import SequenceNotStr -from ...._utils import PropertyInfo - -__all__ = ["ExecuteCreateParams", "Sandbox"] - - -class ExecuteCreateParams(TypedDict, total=False): - prompt: Required[str] - """Task prompt for the agent""" - - disabled_tools: Annotated[Optional[SequenceNotStr[str]], PropertyInfo(alias="disabledTools")] - """Denylist of tools the agent cannot use. - - Mutually exclusive with enabledTools — set one or the other, not both. - """ - - enabled_tools: Annotated[Optional[SequenceNotStr[str]], PropertyInfo(alias="enabledTools")] - """Allowlist of tools the agent can use. - - Mutually exclusive with disabledTools — set one or the other, not both. - """ - - guidance: Optional[str] - """Additional context or constraints for this run""" - - instructions: str - """System instructions. - - Defaults to a general-purpose legal assistant prompt if not provided. - """ - - model: str - """LLM model identifier. Defaults to anthropic/claude-sonnet-4.6""" - - object_ids: Annotated[Optional[SequenceNotStr[str]], PropertyInfo(alias="objectIds")] - """Scope this run to specific vault object IDs. - - The agent will only access these objects. - """ - - sandbox: Optional[Sandbox] - """Custom sandbox resources (cpu, memoryMiB)""" - - vault_ids: Annotated[Optional[SequenceNotStr[str]], PropertyInfo(alias="vaultIds")] - """Restrict agent to specific vault IDs""" - - -class Sandbox(TypedDict, total=False): - """Custom sandbox resources (cpu, memoryMiB)""" - - cpu: int - """Number of CPUs""" - - memory_mi_b: Annotated[int, PropertyInfo(alias="memoryMiB")] - """Memory in MiB""" diff --git a/src/casedev/types/agent/v1/execute_create_response.py b/src/casedev/types/agent/v1/execute_create_response.py deleted file mode 100644 index 018d200a..00000000 --- a/src/casedev/types/agent/v1/execute_create_response.py +++ /dev/null @@ -1,26 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from typing import Optional -from typing_extensions import Literal - -from pydantic import Field as FieldInfo - -from ...._models import BaseModel - -__all__ = ["ExecuteCreateResponse"] - - -class ExecuteCreateResponse(BaseModel): - agent_id: Optional[str] = FieldInfo(alias="agentId", default=None) - """Ephemeral agent ID (auto-created). - - This agent is soft-deleted when the run completes and should not be stored for - reuse. - """ - - message: Optional[str] = None - - run_id: Optional[str] = FieldInfo(alias="runId", default=None) - """Run ID — poll /agent/v1/run/:id/status""" - - status: Optional[Literal["running"]] = None diff --git a/src/casedev/types/agent/v1/run_cancel_response.py b/src/casedev/types/agent/v1/run_cancel_response.py deleted file mode 100644 index bffdcd26..00000000 --- a/src/casedev/types/agent/v1/run_cancel_response.py +++ /dev/null @@ -1,17 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from typing import Optional -from typing_extensions import Literal - -from ...._models import BaseModel - -__all__ = ["RunCancelResponse"] - - -class RunCancelResponse(BaseModel): - id: Optional[str] = None - - message: Optional[str] = None - """Present if run was already finished""" - - status: Optional[Literal["cancelled", "completed", "failed"]] = None diff --git a/src/casedev/types/agent/v1/run_create_params.py b/src/casedev/types/agent/v1/run_create_params.py deleted file mode 100644 index d6a462f1..00000000 --- a/src/casedev/types/agent/v1/run_create_params.py +++ /dev/null @@ -1,39 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from __future__ import annotations - -from typing import Optional -from typing_extensions import Required, Annotated, TypedDict - -from ...._types import SequenceNotStr -from ...._utils import PropertyInfo - -__all__ = ["RunCreateParams"] - - -class RunCreateParams(TypedDict, total=False): - agent_id: Required[Annotated[str, PropertyInfo(alias="agentId")]] - """ID of the agent to run""" - - prompt: Required[str] - """Task prompt for the agent""" - - callback_url: Annotated[Optional[str], PropertyInfo(alias="callbackUrl")] - """HTTPS callback URL to receive a notification when the run completes. - - Registered atomically with the run — eliminates the race condition of calling - /watch after /exec. Additional watchers can still be added via POST - /run/:id/watch. - """ - - guidance: Optional[str] - """Additional guidance for this run""" - - model: Optional[str] - """Override the agent default model for this run""" - - object_ids: Annotated[Optional[SequenceNotStr[str]], PropertyInfo(alias="objectIds")] - """Scope this run to specific vault object IDs. - - The agent will only be able to access these objects during execution. - """ diff --git a/src/casedev/types/agent/v1/run_create_response.py b/src/casedev/types/agent/v1/run_create_response.py deleted file mode 100644 index 94c9e9c9..00000000 --- a/src/casedev/types/agent/v1/run_create_response.py +++ /dev/null @@ -1,23 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from typing import List, Optional -from datetime import datetime -from typing_extensions import Literal - -from pydantic import Field as FieldInfo - -from ...._models import BaseModel - -__all__ = ["RunCreateResponse"] - - -class RunCreateResponse(BaseModel): - id: Optional[str] = None - - agent_id: Optional[str] = FieldInfo(alias="agentId", default=None) - - created_at: Optional[datetime] = FieldInfo(alias="createdAt", default=None) - - object_ids: Optional[List[str]] = FieldInfo(alias="objectIds", default=None) - - status: Optional[Literal["queued"]] = None diff --git a/src/casedev/types/agent/v1/run_events_params.py b/src/casedev/types/agent/v1/run_events_params.py deleted file mode 100644 index d84c2f53..00000000 --- a/src/casedev/types/agent/v1/run_events_params.py +++ /dev/null @@ -1,14 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from __future__ import annotations - -from typing_extensions import Annotated, TypedDict - -from ...._utils import PropertyInfo - -__all__ = ["RunEventsParams"] - - -class RunEventsParams(TypedDict, total=False): - last_event_id: Annotated[int, PropertyInfo(alias="lastEventId")] - """Replay events after this sequence number""" diff --git a/src/casedev/types/agent/v1/run_events_response.py b/src/casedev/types/agent/v1/run_events_response.py deleted file mode 100644 index 2f6d8654..00000000 --- a/src/casedev/types/agent/v1/run_events_response.py +++ /dev/null @@ -1,7 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from typing_extensions import TypeAlias - -__all__ = ["RunEventsResponse"] - -RunEventsResponse: TypeAlias = str diff --git a/src/casedev/types/agent/v1/run_exec_response.py b/src/casedev/types/agent/v1/run_exec_response.py deleted file mode 100644 index 75d7a5f0..00000000 --- a/src/casedev/types/agent/v1/run_exec_response.py +++ /dev/null @@ -1,21 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from typing import Optional -from typing_extensions import Literal - -from pydantic import Field as FieldInfo - -from ...._models import BaseModel - -__all__ = ["RunExecResponse"] - - -class RunExecResponse(BaseModel): - id: Optional[str] = None - - message: Optional[str] = None - - status: Optional[Literal["running"]] = None - - workflow_id: Optional[str] = FieldInfo(alias="workflowId", default=None) - """Durable workflow run ID""" diff --git a/src/casedev/types/agent/v1/run_get_details_response.py b/src/casedev/types/agent/v1/run_get_details_response.py deleted file mode 100644 index eb56113f..00000000 --- a/src/casedev/types/agent/v1/run_get_details_response.py +++ /dev/null @@ -1,176 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from typing import List, Optional -from datetime import datetime -from typing_extensions import Literal - -from pydantic import Field as FieldInfo - -from ...._models import BaseModel - -__all__ = [ - "RunGetDetailsResponse", - "Result", - "ResultFinalResponse", - "ResultLogs", - "Step", - "Usage", - "UsageEntry", - "UsageSummary", -] - - -class ResultFinalResponse(BaseModel): - """Compact agent-facing result summary and execution issues""" - - created_object_ids: Optional[List[str]] = FieldInfo(alias="createdObjectIds", default=None) - - issues: Optional[List[str]] = None - - summary: Optional[str] = None - - -class ResultLogs(BaseModel): - """Sandbox execution logs (runtime server + runner script)""" - - opencode: Optional[str] = None - """Legacy runtime server stdout/stderr""" - - runner: Optional[str] = None - """Runner script stdout/stderr""" - - runtime: Optional[str] = None - """Runtime server stdout/stderr""" - - -class Result(BaseModel): - """Final output from the agent""" - - final_response: Optional[ResultFinalResponse] = FieldInfo(alias="finalResponse", default=None) - """Compact agent-facing result summary and execution issues""" - - logs: Optional[ResultLogs] = None - """Sandbox execution logs (runtime server + runner script)""" - - output: Optional[str] = None - - output_object_ids: Optional[List[str]] = FieldInfo(alias="outputObjectIds", default=None) - - -class Step(BaseModel): - id: Optional[str] = None - - content: Optional[str] = None - - duration_ms: Optional[int] = FieldInfo(alias="durationMs", default=None) - - timestamp: Optional[datetime] = None - - tool_input: Optional[object] = FieldInfo(alias="toolInput", default=None) - - tool_name: Optional[str] = FieldInfo(alias="toolName", default=None) - - tool_output: Optional[object] = FieldInfo(alias="toolOutput", default=None) - - type: Optional[Literal["output", "thinking", "tool_call", "tool_result"]] = None - - -class UsageEntry(BaseModel): - id: Optional[str] = None - - completion_tokens: Optional[int] = FieldInfo(alias="completionTokens", default=None) - - cost_micros: Optional[int] = FieldInfo(alias="costMicros", default=None) - - endpoint: Optional[str] = None - - kind: Optional[Literal["llm", "api"]] = None - - metadata: Optional[object] = None - - method: Optional[str] = None - - model: Optional[str] = None - - prompt_tokens: Optional[int] = FieldInfo(alias="promptTokens", default=None) - - service: Optional[str] = None - - status_code: Optional[int] = FieldInfo(alias="statusCode", default=None) - - timestamp: Optional[datetime] = None - - total_tokens: Optional[int] = FieldInfo(alias="totalTokens", default=None) - - -class UsageSummary(BaseModel): - cost_micros: Optional[int] = FieldInfo(alias="costMicros", default=None) - - total_input_tokens: Optional[int] = FieldInfo(alias="totalInputTokens", default=None) - - total_output_tokens: Optional[int] = FieldInfo(alias="totalOutputTokens", default=None) - - total_tokens: Optional[int] = FieldInfo(alias="totalTokens", default=None) - - -class Usage(BaseModel): - """Token usage statistics""" - - duration_ms: Optional[int] = FieldInfo(alias="durationMs", default=None) - - entries: Optional[List[UsageEntry]] = None - - input_tokens: Optional[int] = FieldInfo(alias="inputTokens", default=None) - - model: Optional[str] = None - - output_tokens: Optional[int] = FieldInfo(alias="outputTokens", default=None) - - summary: Optional[UsageSummary] = None - - tool_calls: Optional[int] = FieldInfo(alias="toolCalls", default=None) - - -class RunGetDetailsResponse(BaseModel): - id: Optional[str] = None - - agent_id: Optional[str] = FieldInfo(alias="agentId", default=None) - - completed_at: Optional[datetime] = FieldInfo(alias="completedAt", default=None) - - created_at: Optional[datetime] = FieldInfo(alias="createdAt", default=None) - - guidance: Optional[str] = None - - modal_sandbox_id: Optional[str] = FieldInfo(alias="modalSandboxId", default=None) - """Deprecated legacy Modal sandbox ID. Prefer `provider` and `runtimeId`.""" - - model: Optional[str] = None - - prompt: Optional[str] = None - - provider: Optional[Literal["daytona", "vercel"]] = None - """Runtime provider for this run""" - - result: Optional[Result] = None - """Final output from the agent""" - - runtime_id: Optional[str] = FieldInfo(alias="runtimeId", default=None) - """Provider-specific runtime identifier""" - - runtime_state: Optional[Literal["running", "stopped", "archived", "ended", "error"]] = FieldInfo( - alias="runtimeState", default=None - ) - """Current runtime state, when available""" - - started_at: Optional[datetime] = FieldInfo(alias="startedAt", default=None) - - status: Optional[Literal["queued", "running", "completed", "failed", "cancelled"]] = None - - steps: Optional[List[Step]] = None - - usage: Optional[Usage] = None - """Token usage statistics""" - - workflow_id: Optional[str] = FieldInfo(alias="workflowId", default=None) - """Durable workflow run ID""" diff --git a/src/casedev/types/agent/v1/run_get_status_response.py b/src/casedev/types/agent/v1/run_get_status_response.py deleted file mode 100644 index 4bb9a677..00000000 --- a/src/casedev/types/agent/v1/run_get_status_response.py +++ /dev/null @@ -1,24 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from typing import Optional -from datetime import datetime -from typing_extensions import Literal - -from pydantic import Field as FieldInfo - -from ...._models import BaseModel - -__all__ = ["RunGetStatusResponse"] - - -class RunGetStatusResponse(BaseModel): - id: Optional[str] = None - - completed_at: Optional[datetime] = FieldInfo(alias="completedAt", default=None) - - duration_ms: Optional[int] = FieldInfo(alias="durationMs", default=None) - """Elapsed time in milliseconds""" - - started_at: Optional[datetime] = FieldInfo(alias="startedAt", default=None) - - status: Optional[Literal["queued", "running", "completed", "failed", "cancelled"]] = None diff --git a/src/casedev/types/agent/v1/run_list_params.py b/src/casedev/types/agent/v1/run_list_params.py deleted file mode 100644 index b38a400b..00000000 --- a/src/casedev/types/agent/v1/run_list_params.py +++ /dev/null @@ -1,26 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from __future__ import annotations - -from typing_extensions import Literal, Annotated, TypedDict - -from ...._utils import PropertyInfo - -__all__ = ["RunListParams"] - - -class RunListParams(TypedDict, total=False): - agent_id: Annotated[str, PropertyInfo(alias="agentId")] - """Filter by agent ID""" - - cursor: str - """Pagination cursor (run ID from previous page). - - Returns runs created before this run. - """ - - limit: int - """Maximum number of runs to return (default 50, max 250)""" - - status: Literal["queued", "running", "completed", "failed", "cancelled"] - """Filter by run status""" diff --git a/src/casedev/types/agent/v1/run_list_response.py b/src/casedev/types/agent/v1/run_list_response.py deleted file mode 100644 index 94ce4842..00000000 --- a/src/casedev/types/agent/v1/run_list_response.py +++ /dev/null @@ -1,39 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from typing import List, Optional -from datetime import datetime -from typing_extensions import Literal - -from pydantic import Field as FieldInfo - -from ...._models import BaseModel - -__all__ = ["RunListResponse", "Run"] - - -class Run(BaseModel): - id: Optional[str] = None - - agent_id: Optional[str] = FieldInfo(alias="agentId", default=None) - - completed_at: Optional[datetime] = FieldInfo(alias="completedAt", default=None) - - created_at: Optional[datetime] = FieldInfo(alias="createdAt", default=None) - - model: Optional[str] = None - - prompt: Optional[str] = None - """Truncated to first 200 characters""" - - started_at: Optional[datetime] = FieldInfo(alias="startedAt", default=None) - - status: Optional[Literal["queued", "running", "completed", "failed", "cancelled"]] = None - - -class RunListResponse(BaseModel): - has_more: Optional[bool] = FieldInfo(alias="hasMore", default=None) - - next_cursor: Optional[str] = FieldInfo(alias="nextCursor", default=None) - """Pass as cursor to fetch the next page""" - - runs: Optional[List[Run]] = None diff --git a/src/casedev/types/agent/v1/run_watch_params.py b/src/casedev/types/agent/v1/run_watch_params.py deleted file mode 100644 index 8b80a795..00000000 --- a/src/casedev/types/agent/v1/run_watch_params.py +++ /dev/null @@ -1,14 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from __future__ import annotations - -from typing_extensions import Required, Annotated, TypedDict - -from ...._utils import PropertyInfo - -__all__ = ["RunWatchParams"] - - -class RunWatchParams(TypedDict, total=False): - callback_url: Required[Annotated[str, PropertyInfo(alias="callbackUrl")]] - """HTTPS URL to receive completion callback""" diff --git a/src/casedev/types/agent/v1/run_watch_response.py b/src/casedev/types/agent/v1/run_watch_response.py deleted file mode 100644 index bf336e5d..00000000 --- a/src/casedev/types/agent/v1/run_watch_response.py +++ /dev/null @@ -1,15 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from typing import Optional - -from pydantic import Field as FieldInfo - -from ...._models import BaseModel - -__all__ = ["RunWatchResponse"] - - -class RunWatchResponse(BaseModel): - callback_url: Optional[str] = FieldInfo(alias="callbackUrl", default=None) - - ok: Optional[bool] = None diff --git a/src/casedev/types/connectors/__init__.py b/src/casedev/types/connectors/__init__.py new file mode 100644 index 00000000..bac598e1 --- /dev/null +++ b/src/casedev/types/connectors/__init__.py @@ -0,0 +1,8 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from .v1_transfer_params import V1TransferParams as V1TransferParams +from .v1_sync_link_params import V1SyncLinkParams as V1SyncLinkParams +from .v1_transfer_response import V1TransferResponse as V1TransferResponse +from .v1_sync_link_response import V1SyncLinkResponse as V1SyncLinkResponse diff --git a/src/casedev/types/connectors/v1/__init__.py b/src/casedev/types/connectors/v1/__init__.py new file mode 100644 index 00000000..70a6e820 --- /dev/null +++ b/src/casedev/types/connectors/v1/__init__.py @@ -0,0 +1,17 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from .link_list_params import LinkListParams as LinkListParams +from .link_delete_params import LinkDeleteParams as LinkDeleteParams +from .link_update_params import LinkUpdateParams as LinkUpdateParams +from .connection_list_params import ConnectionListParams as ConnectionListParams +from .connection_browse_params import ConnectionBrowseParams as ConnectionBrowseParams +from .connection_create_params import ConnectionCreateParams as ConnectionCreateParams +from .connection_delete_params import ConnectionDeleteParams as ConnectionDeleteParams +from .connection_list_response import ConnectionListResponse as ConnectionListResponse +from .installation_list_params import InstallationListParams as InstallationListParams +from .link_list_objects_params import LinkListObjectsParams as LinkListObjectsParams +from .connection_browse_response import ConnectionBrowseResponse as ConnectionBrowseResponse +from .connection_create_response import ConnectionCreateResponse as ConnectionCreateResponse +from .installation_ensure_params import InstallationEnsureParams as InstallationEnsureParams diff --git a/src/casedev/types/connectors/v1/connection_browse_params.py b/src/casedev/types/connectors/v1/connection_browse_params.py new file mode 100644 index 00000000..a59e7886 --- /dev/null +++ b/src/casedev/types/connectors/v1/connection_browse_params.py @@ -0,0 +1,25 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing_extensions import TypedDict + +__all__ = ["ConnectionBrowseParams"] + + +class ConnectionBrowseParams(TypedDict, total=False): + container: str + """Container id to list, or the container containing parent""" + + cursor: str + + page_size: int + + parent: str + """Folder id to list""" + + query: str + """Optional provider-supported search text""" + + site: str + """Site id to list""" diff --git a/src/casedev/types/connectors/v1/connection_browse_response.py b/src/casedev/types/connectors/v1/connection_browse_response.py new file mode 100644 index 00000000..e6f59a9b --- /dev/null +++ b/src/casedev/types/connectors/v1/connection_browse_response.py @@ -0,0 +1,36 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import List, Optional +from typing_extensions import Literal + +from ...._models import BaseModel + +__all__ = ["ConnectionBrowseResponse", "Item"] + + +class Item(BaseModel): + id: Optional[str] = None + + browse_ref: Optional[object] = None + + container_id: Optional[str] = None + + kind: Optional[Literal["my_drive", "shared_drive", "matter", "site", "document_library", "folder", "file"]] = None + + mime_type: Optional[str] = None + + modified_at: Optional[str] = None + + name: Optional[str] = None + + parent_ids: Optional[List[str]] = None + + path: Optional[str] = None + + size_bytes: Optional[int] = None + + +class ConnectionBrowseResponse(BaseModel): + cursor: Optional[str] = None + + items: Optional[List[Item]] = None diff --git a/src/casedev/types/connectors/v1/connection_create_params.py b/src/casedev/types/connectors/v1/connection_create_params.py new file mode 100644 index 00000000..3a497030 --- /dev/null +++ b/src/casedev/types/connectors/v1/connection_create_params.py @@ -0,0 +1,17 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing_extensions import Literal, Required, TypedDict + +__all__ = ["ConnectionCreateParams"] + + +class ConnectionCreateParams(TypedDict, total=False): + provider: Required[Literal["clio", "gdrive", "microsoft"]] + + return_url: Required[str] + """HTTPS URL the user is sent back to after consent.""" + + scope_tier: Literal["clio.us", "drive", "microsoft.read"] + """Provider-specific OAuth permission tier. Omit to use the provider's default.""" diff --git a/src/casedev/types/connectors/v1/connection_create_response.py b/src/casedev/types/connectors/v1/connection_create_response.py new file mode 100644 index 00000000..35cb8354 --- /dev/null +++ b/src/casedev/types/connectors/v1/connection_create_response.py @@ -0,0 +1,15 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import Optional + +from ...._models import BaseModel + +__all__ = ["ConnectionCreateResponse"] + + +class ConnectionCreateResponse(BaseModel): + connect_url: Optional[str] = None + + connection_id: Optional[str] = None + + expires_at: Optional[str] = None diff --git a/src/casedev/types/connectors/v1/connection_delete_params.py b/src/casedev/types/connectors/v1/connection_delete_params.py new file mode 100644 index 00000000..3d9393fc --- /dev/null +++ b/src/casedev/types/connectors/v1/connection_delete_params.py @@ -0,0 +1,11 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing_extensions import TypedDict + +__all__ = ["ConnectionDeleteParams"] + + +class ConnectionDeleteParams(TypedDict, total=False): + purge: bool diff --git a/src/casedev/types/connectors/v1/connection_list_params.py b/src/casedev/types/connectors/v1/connection_list_params.py new file mode 100644 index 00000000..499dad23 --- /dev/null +++ b/src/casedev/types/connectors/v1/connection_list_params.py @@ -0,0 +1,13 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing_extensions import Literal, TypedDict + +__all__ = ["ConnectionListParams"] + + +class ConnectionListParams(TypedDict, total=False): + provider: str + + status: Literal["pending", "healthy", "reauth_required", "revoked", "throttled"] diff --git a/src/casedev/types/connectors/v1/connection_list_response.py b/src/casedev/types/connectors/v1/connection_list_response.py new file mode 100644 index 00000000..b757da49 --- /dev/null +++ b/src/casedev/types/connectors/v1/connection_list_response.py @@ -0,0 +1,19 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import List, Optional + +from ...._models import BaseModel + +__all__ = ["ConnectionListResponse", "Capabilities"] + + +class Capabilities(BaseModel): + google_drive_folder_mirroring: Optional[bool] = None + + +class ConnectionListResponse(BaseModel): + capabilities: Optional[Capabilities] = None + + connections: Optional[List[object]] = None + + cursor: Optional[str] = None diff --git a/src/casedev/types/connectors/v1/installation_ensure_params.py b/src/casedev/types/connectors/v1/installation_ensure_params.py new file mode 100644 index 00000000..67838149 --- /dev/null +++ b/src/casedev/types/connectors/v1/installation_ensure_params.py @@ -0,0 +1,15 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing_extensions import Required, TypedDict + +__all__ = ["InstallationEnsureParams"] + + +class InstallationEnsureParams(TypedDict, total=False): + application: Required[str] + """Consuming application key (e.g. "p3").""" + + external_tenant_id: Required[str] + """The application's own tenant identifier (e.g. a P3 organization id).""" diff --git a/src/casedev/types/connectors/v1/installation_list_params.py b/src/casedev/types/connectors/v1/installation_list_params.py new file mode 100644 index 00000000..127b7ef9 --- /dev/null +++ b/src/casedev/types/connectors/v1/installation_list_params.py @@ -0,0 +1,13 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing_extensions import TypedDict + +__all__ = ["InstallationListParams"] + + +class InstallationListParams(TypedDict, total=False): + application: str + + external_tenant_id: str diff --git a/src/casedev/types/agent/__init__.py b/src/casedev/types/connectors/v1/installations/__init__.py similarity index 63% rename from src/casedev/types/agent/__init__.py rename to src/casedev/types/connectors/v1/installations/__init__.py index f8ee8b14..c5bb68eb 100644 --- a/src/casedev/types/agent/__init__.py +++ b/src/casedev/types/connectors/v1/installations/__init__.py @@ -1,3 +1,5 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations + +from .vault_grant_params import VaultGrantParams as VaultGrantParams diff --git a/src/casedev/types/connectors/v1/installations/vault_grant_params.py b/src/casedev/types/connectors/v1/installations/vault_grant_params.py new file mode 100644 index 00000000..8080f447 --- /dev/null +++ b/src/casedev/types/connectors/v1/installations/vault_grant_params.py @@ -0,0 +1,21 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing_extensions import Literal, Required, TypedDict + +__all__ = ["VaultGrantParams"] + + +class VaultGrantParams(TypedDict, total=False): + id: Required[str] + + can_manage: bool + + can_read: bool + + can_write: bool + + relationship: Literal["owned", "shared"] + + source: Literal["provisioning", "lazy_reconcile", "explicit_share"] diff --git a/src/casedev/types/connectors/v1/link_delete_params.py b/src/casedev/types/connectors/v1/link_delete_params.py new file mode 100644 index 00000000..d8261f30 --- /dev/null +++ b/src/casedev/types/connectors/v1/link_delete_params.py @@ -0,0 +1,11 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing_extensions import Literal, TypedDict + +__all__ = ["LinkDeleteParams"] + + +class LinkDeleteParams(TypedDict, total=False): + vault_docs: Literal["keep", "delete"] diff --git a/src/casedev/types/connectors/v1/link_list_objects_params.py b/src/casedev/types/connectors/v1/link_list_objects_params.py new file mode 100644 index 00000000..fac7dcde --- /dev/null +++ b/src/casedev/types/connectors/v1/link_list_objects_params.py @@ -0,0 +1,13 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing_extensions import Literal, TypedDict + +__all__ = ["LinkListObjectsParams"] + + +class LinkListObjectsParams(TypedDict, total=False): + cursor: str + + state: Literal["pending", "transferring", "ingesting", "synced", "skipped", "failed", "tombstoned"] diff --git a/src/casedev/types/connectors/v1/link_list_params.py b/src/casedev/types/connectors/v1/link_list_params.py new file mode 100644 index 00000000..2e82a4ff --- /dev/null +++ b/src/casedev/types/connectors/v1/link_list_params.py @@ -0,0 +1,21 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing_extensions import Literal, TypedDict + +__all__ = ["LinkListParams"] + + +class LinkListParams(TypedDict, total=False): + connection_id: str + + direction: Literal["import", "export"] + + mode: Literal["once", "synced"] + + pair_id: str + + state: Literal["ready", "running", "active", "paused", "orphaned", "error"] + + vault_id: str diff --git a/src/casedev/types/connectors/v1/link_update_params.py b/src/casedev/types/connectors/v1/link_update_params.py new file mode 100644 index 00000000..4221a094 --- /dev/null +++ b/src/casedev/types/connectors/v1/link_update_params.py @@ -0,0 +1,15 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing_extensions import Literal, TypedDict + +__all__ = ["LinkUpdateParams"] + + +class LinkUpdateParams(TypedDict, total=False): + mode: Literal["once", "synced"] + + policy: object + + state: Literal["paused", "ready"] diff --git a/src/casedev/types/connectors/v1_sync_link_params.py b/src/casedev/types/connectors/v1_sync_link_params.py new file mode 100644 index 00000000..2e2bf0fd --- /dev/null +++ b/src/casedev/types/connectors/v1_sync_link_params.py @@ -0,0 +1,48 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing import Optional +from typing_extensions import Literal, Required, TypedDict + +from ..._types import SequenceNotStr + +__all__ = ["V1SyncLinkParams", "Remote", "Policy", "PolicyFilters"] + + +class V1SyncLinkParams(TypedDict, total=False): + connection_id: Required[str] + + direction: Required[Literal["import", "export"]] + + remote: Required[Remote] + + vault_id: Required[str] + + matter_id: Optional[str] + + policy: Policy + + +class Remote(TypedDict, total=False): + folder_id: Required[str] + + container_id: str + + path: str + + site_id: str + + +class PolicyFilters(TypedDict, total=False): + exclude_mime: SequenceNotStr[str] + + max_size_bytes: int + + +class Policy(TypedDict, total=False): + collisions: Literal["version", "overwrite", "skip"] + + deletes: Literal["mirror", "preserve"] + + filters: PolicyFilters diff --git a/src/casedev/types/connectors/v1_sync_link_response.py b/src/casedev/types/connectors/v1_sync_link_response.py new file mode 100644 index 00000000..fcf33cfb --- /dev/null +++ b/src/casedev/types/connectors/v1_sync_link_response.py @@ -0,0 +1,11 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import List, Optional + +from ..._models import BaseModel + +__all__ = ["V1SyncLinkResponse"] + + +class V1SyncLinkResponse(BaseModel): + links: Optional[List[object]] = None diff --git a/src/casedev/types/connectors/v1_transfer_params.py b/src/casedev/types/connectors/v1_transfer_params.py new file mode 100644 index 00000000..638e7f88 --- /dev/null +++ b/src/casedev/types/connectors/v1_transfer_params.py @@ -0,0 +1,50 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing import Optional +from typing_extensions import Literal, Required, TypedDict + +from ..._types import SequenceNotStr + +__all__ = ["V1TransferParams", "Remote", "Policy", "PolicyFilters"] + + +class V1TransferParams(TypedDict, total=False): + connection_id: Required[str] + + direction: Required[Literal["import", "export"]] + + remote: Required[Remote] + + vault_id: Required[str] + + matter_id: Optional[str] + + policy: Policy + + run_mode: Literal["auto", "full_reconcile"] + + +class Remote(TypedDict, total=False): + folder_id: Required[str] + + container_id: str + + path: str + + site_id: str + + +class PolicyFilters(TypedDict, total=False): + exclude_mime: SequenceNotStr[str] + + max_size_bytes: int + + +class Policy(TypedDict, total=False): + collisions: Literal["version", "overwrite", "skip"] + + deletes: Literal["mirror", "preserve"] + + filters: PolicyFilters diff --git a/src/casedev/types/connectors/v1_transfer_response.py b/src/casedev/types/connectors/v1_transfer_response.py new file mode 100644 index 00000000..c8fd8844 --- /dev/null +++ b/src/casedev/types/connectors/v1_transfer_response.py @@ -0,0 +1,11 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import List, Optional + +from ..._models import BaseModel + +__all__ = ["V1TransferResponse"] + + +class V1TransferResponse(BaseModel): + links: Optional[List[object]] = None diff --git a/src/casedev/types/database/__init__.py b/src/casedev/types/database/__init__.py deleted file mode 100644 index 60ca5082..00000000 --- a/src/casedev/types/database/__init__.py +++ /dev/null @@ -1,5 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from __future__ import annotations - -from .v1_get_usage_response import V1GetUsageResponse as V1GetUsageResponse diff --git a/src/casedev/types/database/v1/__init__.py b/src/casedev/types/database/v1/__init__.py deleted file mode 100644 index 7281d0bc..00000000 --- a/src/casedev/types/database/v1/__init__.py +++ /dev/null @@ -1,14 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from __future__ import annotations - -from .project_create_params import ProjectCreateParams as ProjectCreateParams -from .project_list_response import ProjectListResponse as ProjectListResponse -from .project_create_response import ProjectCreateResponse as ProjectCreateResponse -from .project_delete_response import ProjectDeleteResponse as ProjectDeleteResponse -from .project_retrieve_response import ProjectRetrieveResponse as ProjectRetrieveResponse -from .project_create_branch_params import ProjectCreateBranchParams as ProjectCreateBranchParams -from .project_get_connection_params import ProjectGetConnectionParams as ProjectGetConnectionParams -from .project_create_branch_response import ProjectCreateBranchResponse as ProjectCreateBranchResponse -from .project_list_branches_response import ProjectListBranchesResponse as ProjectListBranchesResponse -from .project_get_connection_response import ProjectGetConnectionResponse as ProjectGetConnectionResponse diff --git a/src/casedev/types/database/v1/project_create_branch_params.py b/src/casedev/types/database/v1/project_create_branch_params.py deleted file mode 100644 index 859540a7..00000000 --- a/src/casedev/types/database/v1/project_create_branch_params.py +++ /dev/null @@ -1,17 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from __future__ import annotations - -from typing_extensions import Required, Annotated, TypedDict - -from ...._utils import PropertyInfo - -__all__ = ["ProjectCreateBranchParams"] - - -class ProjectCreateBranchParams(TypedDict, total=False): - name: Required[str] - """Branch name (letters, numbers, hyphens, underscores only)""" - - parent_branch_id: Annotated[str, PropertyInfo(alias="parentBranchId")] - """Parent branch ID to clone from (defaults to main branch)""" diff --git a/src/casedev/types/database/v1/project_create_branch_response.py b/src/casedev/types/database/v1/project_create_branch_response.py deleted file mode 100644 index d05ea15c..00000000 --- a/src/casedev/types/database/v1/project_create_branch_response.py +++ /dev/null @@ -1,30 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from typing import Optional -from datetime import datetime - -from pydantic import Field as FieldInfo - -from ...._models import BaseModel - -__all__ = ["ProjectCreateBranchResponse"] - - -class ProjectCreateBranchResponse(BaseModel): - id: str - """Branch ID""" - - created_at: datetime = FieldInfo(alias="createdAt") - """Branch creation timestamp""" - - is_default: bool = FieldInfo(alias="isDefault") - """Whether this is the default branch (always false for new branches)""" - - name: str - """Branch name""" - - parent_branch_id: Optional[str] = FieldInfo(alias="parentBranchId", default=None) - """Parent branch ID""" - - status: str - """Branch status""" diff --git a/src/casedev/types/database/v1/project_create_params.py b/src/casedev/types/database/v1/project_create_params.py deleted file mode 100644 index b713f720..00000000 --- a/src/casedev/types/database/v1/project_create_params.py +++ /dev/null @@ -1,27 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from __future__ import annotations - -from typing_extensions import Literal, Required, TypedDict - -__all__ = ["ProjectCreateParams"] - - -class ProjectCreateParams(TypedDict, total=False): - name: Required[str] - """Project name (letters, numbers, hyphens, underscores only)""" - - description: str - """Optional project description""" - - region: Literal[ - "aws-us-east-1", - "aws-us-east-2", - "aws-us-west-2", - "aws-eu-central-1", - "aws-eu-west-1", - "aws-eu-west-2", - "aws-ap-southeast-1", - "aws-ap-southeast-2", - ] - """AWS region for database deployment""" diff --git a/src/casedev/types/database/v1/project_create_response.py b/src/casedev/types/database/v1/project_create_response.py deleted file mode 100644 index e2a04e93..00000000 --- a/src/casedev/types/database/v1/project_create_response.py +++ /dev/null @@ -1,47 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from typing import Optional -from datetime import datetime -from typing_extensions import Literal - -from pydantic import Field as FieldInfo - -from ...._models import BaseModel - -__all__ = ["ProjectCreateResponse", "DefaultBranch"] - - -class DefaultBranch(BaseModel): - """Default 'main' branch details""" - - id: Optional[str] = None - """Branch ID""" - - name: Optional[str] = None - """Branch name""" - - -class ProjectCreateResponse(BaseModel): - id: str - """Project ID""" - - created_at: datetime = FieldInfo(alias="createdAt") - """Project creation timestamp""" - - default_branch: DefaultBranch = FieldInfo(alias="defaultBranch") - """Default 'main' branch details""" - - name: str - """Project name""" - - pg_version: int = FieldInfo(alias="pgVersion") - """PostgreSQL major version""" - - region: str - """AWS region""" - - status: Literal["active", "suspended", "deleted"] - """Project status""" - - description: Optional[str] = None - """Project description""" diff --git a/src/casedev/types/database/v1/project_delete_response.py b/src/casedev/types/database/v1/project_delete_response.py deleted file mode 100644 index 2b1640fa..00000000 --- a/src/casedev/types/database/v1/project_delete_response.py +++ /dev/null @@ -1,13 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from ...._models import BaseModel - -__all__ = ["ProjectDeleteResponse"] - - -class ProjectDeleteResponse(BaseModel): - message: str - """Confirmation message""" - - success: bool - """Deletion success indicator""" diff --git a/src/casedev/types/database/v1/project_get_connection_params.py b/src/casedev/types/database/v1/project_get_connection_params.py deleted file mode 100644 index a4c7c895..00000000 --- a/src/casedev/types/database/v1/project_get_connection_params.py +++ /dev/null @@ -1,15 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from __future__ import annotations - -from typing_extensions import TypedDict - -__all__ = ["ProjectGetConnectionParams"] - - -class ProjectGetConnectionParams(TypedDict, total=False): - branch: str - """Branch name (defaults to 'main')""" - - pooled: bool - """Use pooled connection (PgBouncer)""" diff --git a/src/casedev/types/database/v1/project_get_connection_response.py b/src/casedev/types/database/v1/project_get_connection_response.py deleted file mode 100644 index 1d0cbf20..00000000 --- a/src/casedev/types/database/v1/project_get_connection_response.py +++ /dev/null @@ -1,18 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from pydantic import Field as FieldInfo - -from ...._models import BaseModel - -__all__ = ["ProjectGetConnectionResponse"] - - -class ProjectGetConnectionResponse(BaseModel): - branch: str - """Branch name for this connection""" - - connection_uri: str = FieldInfo(alias="connectionUri") - """PostgreSQL connection string (includes credentials)""" - - pooled: bool - """Whether this is a pooled connection""" diff --git a/src/casedev/types/database/v1/project_list_branches_response.py b/src/casedev/types/database/v1/project_list_branches_response.py deleted file mode 100644 index 66c12778..00000000 --- a/src/casedev/types/database/v1/project_list_branches_response.py +++ /dev/null @@ -1,37 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from typing import List, Optional -from datetime import datetime - -from pydantic import Field as FieldInfo - -from ...._models import BaseModel - -__all__ = ["ProjectListBranchesResponse", "Branch"] - - -class Branch(BaseModel): - id: Optional[str] = None - """Branch ID""" - - created_at: Optional[datetime] = FieldInfo(alias="createdAt", default=None) - """Branch creation timestamp""" - - is_default: Optional[bool] = FieldInfo(alias="isDefault", default=None) - """Whether this is the default branch""" - - name: Optional[str] = None - """Branch name""" - - parent_branch_id: Optional[str] = FieldInfo(alias="parentBranchId", default=None) - """Parent branch ID (null for default branch)""" - - status: Optional[str] = None - """Branch status""" - - updated_at: Optional[datetime] = FieldInfo(alias="updatedAt", default=None) - """Branch last update timestamp""" - - -class ProjectListBranchesResponse(BaseModel): - branches: List[Branch] diff --git a/src/casedev/types/database/v1/project_list_response.py b/src/casedev/types/database/v1/project_list_response.py deleted file mode 100644 index 18af984c..00000000 --- a/src/casedev/types/database/v1/project_list_response.py +++ /dev/null @@ -1,64 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from typing import List, Optional -from datetime import datetime -from typing_extensions import Literal - -from pydantic import Field as FieldInfo - -from ...._models import BaseModel - -__all__ = ["ProjectListResponse", "Project", "ProjectLinkedDeployment"] - - -class ProjectLinkedDeployment(BaseModel): - id: Optional[str] = None - """Deployment ID""" - - name: Optional[str] = None - """Deployment name""" - - type: Optional[Literal["compute"]] = None - """Type of deployment""" - - url: Optional[str] = None - """Deployment URL""" - - -class Project(BaseModel): - id: Optional[str] = None - """Project ID""" - - compute_time_seconds: Optional[float] = FieldInfo(alias="computeTimeSeconds", default=None) - """Total compute time consumed in seconds""" - - created_at: Optional[datetime] = FieldInfo(alias="createdAt", default=None) - """Project creation timestamp""" - - description: Optional[str] = None - """Project description""" - - linked_deployments: Optional[List[ProjectLinkedDeployment]] = FieldInfo(alias="linkedDeployments", default=None) - """Linked application deployments using this database""" - - name: Optional[str] = None - """Project name""" - - pg_version: Optional[int] = FieldInfo(alias="pgVersion", default=None) - """PostgreSQL major version""" - - region: Optional[str] = None - """AWS region where database is deployed""" - - status: Optional[Literal["active", "suspended", "deleted"]] = None - """Current project status""" - - storage_size_bytes: Optional[float] = FieldInfo(alias="storageSizeBytes", default=None) - """Current storage usage in bytes""" - - updated_at: Optional[datetime] = FieldInfo(alias="updatedAt", default=None) - """Project last update timestamp""" - - -class ProjectListResponse(BaseModel): - projects: List[Project] diff --git a/src/casedev/types/database/v1/project_retrieve_response.py b/src/casedev/types/database/v1/project_retrieve_response.py deleted file mode 100644 index 789cd9c0..00000000 --- a/src/casedev/types/database/v1/project_retrieve_response.py +++ /dev/null @@ -1,100 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from typing import List, Optional -from datetime import datetime -from typing_extensions import Literal - -from pydantic import Field as FieldInfo - -from ...._models import BaseModel - -__all__ = ["ProjectRetrieveResponse", "Branch", "Database", "LinkedDeployment"] - - -class Branch(BaseModel): - id: Optional[str] = None - """Branch ID""" - - created_at: Optional[datetime] = FieldInfo(alias="createdAt", default=None) - """Branch creation timestamp""" - - is_default: Optional[bool] = FieldInfo(alias="isDefault", default=None) - """Whether this is the default branch""" - - name: Optional[str] = None - """Branch name""" - - status: Optional[str] = None - """Branch status""" - - -class Database(BaseModel): - id: Optional[str] = None - """Database ID""" - - name: Optional[str] = None - """Database name""" - - owner_name: Optional[str] = FieldInfo(alias="ownerName", default=None) - """Database owner role name""" - - -class LinkedDeployment(BaseModel): - id: Optional[str] = None - """Deployment ID""" - - env_var_name: Optional[str] = FieldInfo(alias="envVarName", default=None) - """Environment variable name for connection string""" - - name: Optional[str] = None - """Deployment name""" - - type: Optional[Literal["compute"]] = None - """Deployment type""" - - url: Optional[str] = None - """Deployment URL""" - - -class ProjectRetrieveResponse(BaseModel): - id: str - """Project ID""" - - branches: List[Branch] - """All branches in this project""" - - compute_time_seconds: float = FieldInfo(alias="computeTimeSeconds") - """Total compute time consumed in seconds""" - - connection_host: str = FieldInfo(alias="connectionHost") - """Database connection hostname (masked for security)""" - - created_at: datetime = FieldInfo(alias="createdAt") - """Project creation timestamp""" - - databases: List[Database] - """Databases in the default branch""" - - linked_deployments: List[LinkedDeployment] = FieldInfo(alias="linkedDeployments") - """Linked deployments using this database""" - - name: str - """Project name""" - - pg_version: int = FieldInfo(alias="pgVersion") - """PostgreSQL major version""" - - region: str - """AWS region""" - - status: Literal["active", "suspended", "deleted"] - """Project status""" - - storage_size_bytes: float = FieldInfo(alias="storageSizeBytes") - """Current storage usage in bytes""" - - updated_at: datetime = FieldInfo(alias="updatedAt") - """Project last update timestamp""" - - description: Optional[str] = None - """Project description""" diff --git a/src/casedev/types/database/v1_get_usage_response.py b/src/casedev/types/database/v1_get_usage_response.py deleted file mode 100644 index dc44fec6..00000000 --- a/src/casedev/types/database/v1_get_usage_response.py +++ /dev/null @@ -1,116 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from typing import List, Optional -from datetime import datetime - -from pydantic import Field as FieldInfo - -from ..._models import BaseModel - -__all__ = ["V1GetUsageResponse", "Period", "Pricing", "Project", "ProjectCosts", "Totals"] - - -class Period(BaseModel): - end: Optional[datetime] = None - """End of the billing period""" - - start: Optional[datetime] = None - """Start of the billing period""" - - -class Pricing(BaseModel): - """Current pricing rates""" - - branch_per_month: Optional[float] = FieldInfo(alias="branchPerMonth", default=None) - """Cost per branch per month in dollars""" - - compute_per_cu_hour: Optional[float] = FieldInfo(alias="computePerCuHour", default=None) - """Cost per compute unit hour in dollars""" - - free_branches: Optional[int] = FieldInfo(alias="freeBranches", default=None) - """Number of free branches included""" - - storage_per_gb_month: Optional[float] = FieldInfo(alias="storagePerGbMonth", default=None) - """Cost per GB of storage per month in dollars""" - - transfer_per_gb: Optional[float] = FieldInfo(alias="transferPerGb", default=None) - """Cost per GB of data transfer in dollars""" - - -class ProjectCosts(BaseModel): - branches: Optional[str] = None - - compute: Optional[str] = None - - storage: Optional[str] = None - - total: Optional[str] = None - - transfer: Optional[str] = None - - -class Project(BaseModel): - id: Optional[str] = None - - branch_count: Optional[int] = FieldInfo(alias="branchCount", default=None) - - compute_cu_hours: Optional[float] = FieldInfo(alias="computeCuHours", default=None) - - costs: Optional[ProjectCosts] = None - - last_updated: Optional[datetime] = FieldInfo(alias="lastUpdated", default=None) - - project_id: Optional[str] = FieldInfo(alias="projectId", default=None) - - project_name: Optional[str] = FieldInfo(alias="projectName", default=None) - - storage_gb_months: Optional[float] = FieldInfo(alias="storageGbMonths", default=None) - - transfer_gb: Optional[float] = FieldInfo(alias="transferGb", default=None) - - -class Totals(BaseModel): - """Aggregated totals across all projects""" - - branch_cost_dollars: Optional[str] = FieldInfo(alias="branchCostDollars", default=None) - """Total branch cost formatted as dollars""" - - compute_cost_dollars: Optional[str] = FieldInfo(alias="computeCostDollars", default=None) - """Total compute cost formatted as dollars""" - - compute_cu_hours: Optional[float] = FieldInfo(alias="computeCuHours", default=None) - """Total compute unit hours""" - - storage_cost_dollars: Optional[str] = FieldInfo(alias="storageCostDollars", default=None) - """Total storage cost formatted as dollars""" - - storage_gb_months: Optional[float] = FieldInfo(alias="storageGbMonths", default=None) - """Total storage in GB-months""" - - total_branches: Optional[int] = FieldInfo(alias="totalBranches", default=None) - """Total number of branches""" - - total_cost_dollars: Optional[str] = FieldInfo(alias="totalCostDollars", default=None) - """Total cost formatted as dollars""" - - transfer_cost_dollars: Optional[str] = FieldInfo(alias="transferCostDollars", default=None) - """Total transfer cost formatted as dollars""" - - transfer_gb: Optional[float] = FieldInfo(alias="transferGb", default=None) - """Total data transfer in GB""" - - -class V1GetUsageResponse(BaseModel): - period: Optional[Period] = None - - pricing: Optional[Pricing] = None - """Current pricing rates""" - - project_count: Optional[int] = FieldInfo(alias="projectCount", default=None) - """Total number of projects with usage""" - - projects: Optional[List[Project]] = None - """Usage breakdown by project""" - - totals: Optional[Totals] = None - """Aggregated totals across all projects""" diff --git a/src/casedev/types/document_templates/__init__.py b/src/casedev/types/document_templates/__init__.py deleted file mode 100644 index f8ee8b14..00000000 --- a/src/casedev/types/document_templates/__init__.py +++ /dev/null @@ -1,3 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from __future__ import annotations diff --git a/src/casedev/types/format/__init__.py b/src/casedev/types/format/__init__.py deleted file mode 100644 index 287e51d3..00000000 --- a/src/casedev/types/format/__init__.py +++ /dev/null @@ -1,5 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from __future__ import annotations - -from .v1_create_document_params import V1CreateDocumentParams as V1CreateDocumentParams diff --git a/src/casedev/types/format/v1/__init__.py b/src/casedev/types/format/v1/__init__.py deleted file mode 100644 index 351ac658..00000000 --- a/src/casedev/types/format/v1/__init__.py +++ /dev/null @@ -1,9 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from __future__ import annotations - -from .template_list_params import TemplateListParams as TemplateListParams -from .template_create_params import TemplateCreateParams as TemplateCreateParams -from .template_list_response import TemplateListResponse as TemplateListResponse -from .template_create_response import TemplateCreateResponse as TemplateCreateResponse -from .template_retrieve_response import TemplateRetrieveResponse as TemplateRetrieveResponse diff --git a/src/casedev/types/format/v1/template_create_params.py b/src/casedev/types/format/v1/template_create_params.py deleted file mode 100644 index f8316608..00000000 --- a/src/casedev/types/format/v1/template_create_params.py +++ /dev/null @@ -1,32 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from __future__ import annotations - -from typing_extensions import Literal, Required, TypedDict - -from ...._types import SequenceNotStr - -__all__ = ["TemplateCreateParams"] - - -class TemplateCreateParams(TypedDict, total=False): - content: Required[str] - """Template content with {{variable}} placeholders""" - - name: Required[str] - """Template name""" - - type: Required[Literal["caption", "signature", "letterhead", "certificate", "footer", "custom"]] - """Template type""" - - description: str - """Template description""" - - styles: object - """CSS styles for the template""" - - tags: SequenceNotStr[str] - """Template tags for organization""" - - variables: SequenceNotStr[str] - """Template variables (auto-detected if not provided)""" diff --git a/src/casedev/types/format/v1/template_create_response.py b/src/casedev/types/format/v1/template_create_response.py deleted file mode 100644 index ee7c7a6d..00000000 --- a/src/casedev/types/format/v1/template_create_response.py +++ /dev/null @@ -1,27 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from typing import List, Optional -from datetime import datetime - -from pydantic import Field as FieldInfo - -from ...._models import BaseModel - -__all__ = ["TemplateCreateResponse"] - - -class TemplateCreateResponse(BaseModel): - id: Optional[str] = None - """Template ID""" - - created_at: Optional[datetime] = FieldInfo(alias="createdAt", default=None) - """Creation timestamp""" - - name: Optional[str] = None - """Template name""" - - type: Optional[str] = None - """Template type""" - - variables: Optional[List[str]] = None - """Detected template variables""" diff --git a/src/casedev/types/format/v1/template_list_params.py b/src/casedev/types/format/v1/template_list_params.py deleted file mode 100644 index a134cd7e..00000000 --- a/src/casedev/types/format/v1/template_list_params.py +++ /dev/null @@ -1,12 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from __future__ import annotations - -from typing_extensions import TypedDict - -__all__ = ["TemplateListParams"] - - -class TemplateListParams(TypedDict, total=False): - type: str - """Filter templates by type (e.g., contract, pleading, letter)""" diff --git a/src/casedev/types/format/v1/template_list_response.py b/src/casedev/types/format/v1/template_list_response.py deleted file mode 100644 index b5efddfc..00000000 --- a/src/casedev/types/format/v1/template_list_response.py +++ /dev/null @@ -1,40 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from typing import List, Optional -from datetime import datetime - -from pydantic import Field as FieldInfo - -from ...._models import BaseModel - -__all__ = ["TemplateListResponse", "Template"] - - -class Template(BaseModel): - id: Optional[str] = None - """Unique template identifier""" - - created_at: Optional[datetime] = FieldInfo(alias="createdAt", default=None) - """Template creation timestamp""" - - description: Optional[str] = None - """Template description""" - - name: Optional[str] = None - """Template name""" - - tags: Optional[List[object]] = None - """Template tags for organization""" - - type: Optional[str] = None - """Template type/category""" - - usage_count: Optional[int] = FieldInfo(alias="usageCount", default=None) - """Number of times template has been used""" - - variables: Optional[List[object]] = None - """Template variables for customization""" - - -class TemplateListResponse(BaseModel): - templates: Optional[List[Template]] = None diff --git a/src/casedev/types/format/v1/template_retrieve_response.py b/src/casedev/types/format/v1/template_retrieve_response.py deleted file mode 100644 index e51ca387..00000000 --- a/src/casedev/types/format/v1/template_retrieve_response.py +++ /dev/null @@ -1,33 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from typing import Optional -from datetime import datetime - -from pydantic import Field as FieldInfo - -from ...._models import BaseModel - -__all__ = ["TemplateRetrieveResponse"] - - -class TemplateRetrieveResponse(BaseModel): - id: Optional[str] = None - """Unique template identifier""" - - content: Optional[object] = None - """Template formatting rules and structure""" - - created_at: Optional[datetime] = FieldInfo(alias="createdAt", default=None) - """Template creation timestamp""" - - description: Optional[str] = None - """Template description""" - - name: Optional[str] = None - """Template name""" - - organization_id: Optional[str] = FieldInfo(alias="organizationId", default=None) - """Organization ID that owns the template""" - - updated_at: Optional[datetime] = FieldInfo(alias="updatedAt", default=None) - """Template last modification timestamp""" diff --git a/src/casedev/types/format/v1_create_document_params.py b/src/casedev/types/format/v1_create_document_params.py deleted file mode 100644 index 462456ab..00000000 --- a/src/casedev/types/format/v1_create_document_params.py +++ /dev/null @@ -1,50 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from __future__ import annotations - -from typing import Iterable -from typing_extensions import Literal, Required, Annotated, TypedDict - -from ..._utils import PropertyInfo - -__all__ = ["V1CreateDocumentParams", "Options", "OptionsComponent"] - - -class V1CreateDocumentParams(TypedDict, total=False): - content: Required[str] - """The source content to format""" - - output_format: Required[Literal["pdf", "docx", "html_preview"]] - """Desired output format""" - - input_format: Literal["md", "json", "text"] - """Format of the input content""" - - options: Options - """ - Optional template composition and styling settings used during document - generation - """ - - -class OptionsComponent(TypedDict, total=False): - content: str - """Inline template content""" - - styles: object - """Custom styling options""" - - template_id: Annotated[str, PropertyInfo(alias="templateId")] - """ID of saved template component""" - - variables: object - """Variables for template interpolation""" - - -class Options(TypedDict, total=False): - """ - Optional template composition and styling settings used during document generation - """ - - components: Iterable[OptionsComponent] - """Template components with variables""" diff --git a/src/casedev/types/legal/__init__.py b/src/casedev/types/legal/__init__.py index 57bc1a81..e4b2d87b 100644 --- a/src/casedev/types/legal/__init__.py +++ b/src/casedev/types/legal/__init__.py @@ -4,11 +4,9 @@ from .docket_detail import DocketDetail as DocketDetail from .v1_find_params import V1FindParams as V1FindParams -from .v1_draft_params import V1DraftParams as V1DraftParams from .v1_docket_params import V1DocketParams as V1DocketParams from .v1_find_response import V1FindResponse as V1FindResponse from .v1_verify_params import V1VerifyParams as V1VerifyParams -from .v1_draft_response import V1DraftResponse as V1DraftResponse from .v1_similar_params import V1SimilarParams as V1SimilarParams from .v1_docket_response import V1DocketResponse as V1DocketResponse from .v1_research_params import V1ResearchParams as V1ResearchParams diff --git a/src/casedev/types/legal/v1_docket_params.py b/src/casedev/types/legal/v1_docket_params.py index 523a7ee0..893ca6d3 100644 --- a/src/casedev/types/legal/v1_docket_params.py +++ b/src/casedev/types/legal/v1_docket_params.py @@ -54,7 +54,10 @@ class V1DocketParams(TypedDict, total=False): """ offset: int - """Offset for search results or entry list""" + """ + Offset for search results or entry list (maximum 200 when including lookup + entries) + """ query: str """Case name or party name search query (required for search)""" diff --git a/src/casedev/types/legal/v1_draft_params.py b/src/casedev/types/legal/v1_draft_params.py deleted file mode 100644 index 83711fbb..00000000 --- a/src/casedev/types/legal/v1_draft_params.py +++ /dev/null @@ -1,62 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from __future__ import annotations - -from typing import Optional -from typing_extensions import Literal, Required, TypedDict - -from ..._types import SequenceNotStr - -__all__ = ["V1DraftParams", "Length"] - - -class V1DraftParams(TypedDict, total=False): - instructions: Required[str] - """What to draft — the core task. - - E.g., "Motion to compel defendant to produce discovery responses" - """ - - vault_id: Required[str] - """Vault ID where the final document will be uploaded""" - - citations: bool - """Research and include legal citations""" - - format: Optional[str] - """Court or jurisdiction formatting hint. - - Triggers a legal-skills search. E.g., "California Superior Court", "SDNY", - "federal pleading" - """ - - length: Optional[Length] - """Target document length""" - - model: Optional[str] - """LLM model override. Defaults to anthropic/claude-sonnet-4.6""" - - object_ids: Optional[SequenceNotStr[str]] - """Vault object IDs to use as source/reference documents""" - - output_name: Optional[str] - """Filename for the output document. Auto-generated if omitted.""" - - output_type: Literal["pdf", "docx", "xlsx", "pptx", "md"] - """Output file format""" - - verified: bool - """ - Verify all citations in a loop — re-run verification and repair bad citations - until they pass - """ - - -class Length(TypedDict, total=False): - """Target document length""" - - target: float - """Target value (e.g., 2000 words or 5 pages)""" - - unit: Literal["words", "pages"] - """Whether the target length is measured in words or pages""" diff --git a/src/casedev/types/legal/v1_draft_response.py b/src/casedev/types/legal/v1_draft_response.py deleted file mode 100644 index b462f709..00000000 --- a/src/casedev/types/legal/v1_draft_response.py +++ /dev/null @@ -1,20 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from typing import Optional -from typing_extensions import Literal - -from ..._models import BaseModel - -__all__ = ["V1DraftResponse"] - - -class V1DraftResponse(BaseModel): - agent_id: Optional[str] = None - """Ephemeral agent ID""" - - message: Optional[str] = None - - run_id: Optional[str] = None - """Run ID — poll /agent/v1/run/:id/status for progress""" - - status: Optional[Literal["running"]] = None diff --git a/src/casedev/types/linc/v1/__init__.py b/src/casedev/types/linc/v1/__init__.py index 8d55b574..3629df9e 100644 --- a/src/casedev/types/linc/v1/__init__.py +++ b/src/casedev/types/linc/v1/__init__.py @@ -2,6 +2,7 @@ from __future__ import annotations +from .session_cancel_params import SessionCancelParams as SessionCancelParams from .session_create_params import SessionCreateParams as SessionCreateParams from .session_send_rpc_params import SessionSendRpcParams as SessionSendRpcParams from .session_ingest_events_params import SessionIngestEventsParams as SessionIngestEventsParams diff --git a/src/casedev/types/linc/v1/session_cancel_params.py b/src/casedev/types/linc/v1/session_cancel_params.py new file mode 100644 index 00000000..aea535a3 --- /dev/null +++ b/src/casedev/types/linc/v1/session_cancel_params.py @@ -0,0 +1,21 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing_extensions import Annotated, TypedDict + +from ...._utils import PropertyInfo + +__all__ = ["SessionCancelParams"] + + +class SessionCancelParams(TypedDict, total=False): + clear_queue: Annotated[bool, PropertyInfo(alias="clearQueue")] + """ + Also clear queued steering/follow-up messages so the abort leaves the agent + fully idle. Cleared texts are returned in the `response.data.clearedQueue` field + of the response body. Without it, messages still queued when the abort settles + are auto-continued as a new run. Runtimes older than the Linc release that + supports this flag ignore it: the abort still happens but the queue is left + untouched. + """ diff --git a/src/casedev/types/linc/v1/session_create_params.py b/src/casedev/types/linc/v1/session_create_params.py index 44f10ac8..2d58fd18 100644 --- a/src/casedev/types/linc/v1/session_create_params.py +++ b/src/casedev/types/linc/v1/session_create_params.py @@ -3,7 +3,7 @@ from __future__ import annotations from typing import Optional -from typing_extensions import Annotated, TypedDict +from typing_extensions import Literal, Annotated, TypedDict from ...._types import SequenceNotStr from ...._utils import PropertyInfo @@ -34,6 +34,12 @@ class SessionCreateParams(TypedDict, total=False): scoped_api_key: Annotated[Optional[str], PropertyInfo(alias="scopedApiKey")] """Optional caller-provided scoped Case.dev API key for the runtime.""" + service_tier: Annotated[Literal["default", "priority"], PropertyInfo(alias="serviceTier")] + """Processing tier for eligible OpenAI GPT models. + + Priority provides lower latency at premium cost. + """ + skill_slugs: Annotated[Optional[SequenceNotStr[str]], PropertyInfo(alias="skillSlugs")] """ Skills API slugs to install into the runtime sandbox before the native session diff --git a/src/casedev/types/llm/v1/chat_create_completion_params.py b/src/casedev/types/llm/v1/chat_create_completion_params.py index ea53c526..47093d9a 100644 --- a/src/casedev/types/llm/v1/chat_create_completion_params.py +++ b/src/casedev/types/llm/v1/chat_create_completion_params.py @@ -13,9 +13,10 @@ class ChatCreateCompletionParams(TypedDict, total=False): """List of messages comprising the conversation""" casemark_show_reasoning: bool - """CaseMark-only: when true, allows reasoning fields in responses. + """CaseMark-only: controls whether reasoning fields appear in responses. - Defaults to false (reasoning is suppressed). + Defaults to false (suppressed) for most CaseMark models; defaults to true for + casemark/core-potassium. """ frequency_penalty: float diff --git a/src/casedev/types/mail/__init__.py b/src/casedev/types/mail/__init__.py deleted file mode 100644 index f8ee8b14..00000000 --- a/src/casedev/types/mail/__init__.py +++ /dev/null @@ -1,3 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from __future__ import annotations diff --git a/src/casedev/types/mail/v1/__init__.py b/src/casedev/types/mail/v1/__init__.py deleted file mode 100644 index edd97ad1..00000000 --- a/src/casedev/types/mail/v1/__init__.py +++ /dev/null @@ -1,6 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from __future__ import annotations - -from .inbox_create_params import InboxCreateParams as InboxCreateParams -from .inbox_set_policy_params import InboxSetPolicyParams as InboxSetPolicyParams diff --git a/src/casedev/types/mail/v1/inbox_create_params.py b/src/casedev/types/mail/v1/inbox_create_params.py deleted file mode 100644 index 405bd5fa..00000000 --- a/src/casedev/types/mail/v1/inbox_create_params.py +++ /dev/null @@ -1,15 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from __future__ import annotations - -from typing_extensions import Annotated, TypedDict - -from ...._utils import PropertyInfo - -__all__ = ["InboxCreateParams"] - - -class InboxCreateParams(TypedDict, total=False): - address: str - - display_name: Annotated[str, PropertyInfo(alias="displayName")] diff --git a/src/casedev/types/mail/v1/inbox_set_policy_params.py b/src/casedev/types/mail/v1/inbox_set_policy_params.py deleted file mode 100644 index 743ad80a..00000000 --- a/src/casedev/types/mail/v1/inbox_set_policy_params.py +++ /dev/null @@ -1,32 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from __future__ import annotations - -from typing_extensions import Annotated, TypedDict - -from ...._types import SequenceNotStr -from ...._utils import PropertyInfo - -__all__ = ["InboxSetPolicyParams"] - - -class InboxSetPolicyParams(TypedDict, total=False): - allowed_sender_patterns: Annotated[SequenceNotStr[str], PropertyInfo(alias="allowedSenderPatterns")] - """Exact emails, @domain rules, or \\**""" - - enforce_sender_allowlist: Annotated[bool, PropertyInfo(alias="enforceSenderAllowlist")] - - read_access_rules: Annotated[SequenceNotStr[str], PropertyInfo(alias="readAccessRules")] - """ - Rules like organization, operator, user:, api_key, api_key:, - clerk_session, or \\** - """ - - reply_access_rules: Annotated[SequenceNotStr[str], PropertyInfo(alias="replyAccessRules")] - """ - Rules like organization, operator, user:, api_key, api_key:, - clerk_session, or \\** - """ - - send_access_rules: Annotated[SequenceNotStr[str], PropertyInfo(alias="sendAccessRules")] - """Rules like organization, user:, api_key, api_key:, clerk_session, or \\**""" diff --git a/src/casedev/types/matters/v1/work_item_decide_params.py b/src/casedev/types/matters/v1/work_item_decide_params.py index 1f6e042f..dc78435b 100644 --- a/src/casedev/types/matters/v1/work_item_decide_params.py +++ b/src/casedev/types/matters/v1/work_item_decide_params.py @@ -11,9 +11,7 @@ class WorkItemDecideParams(TypedDict, total=False): id: Required[str] - decision: Required[Literal["approve", "revise", "block", "reassign"]] - - agent_type_id: Optional[str] + decision: Required[Literal["approve", "block"]] metadata: Dict[str, object] diff --git a/src/casedev/types/ocr/v1_process_params.py b/src/casedev/types/ocr/v1_process_params.py index 7f6e99c4..f3f863eb 100644 --- a/src/casedev/types/ocr/v1_process_params.py +++ b/src/casedev/types/ocr/v1_process_params.py @@ -31,7 +31,11 @@ class V1ProcessParams(TypedDict, total=False): """S3 key prefix for results""" -class FeaturesTables(TypedDict, total=False, extra_items=object): # type: ignore[call-arg] +class FeaturesTables( # type: ignore[call-arg] + TypedDict, + total=False, + extra_items=object, # pyright: ignore[reportGeneralTypeIssues] +): """Extract tables as structured data""" format: Literal["csv", "json"] diff --git a/src/casedev/types/ocr/v1_retrieve_params.py b/src/casedev/types/ocr/v1_retrieve_params.py index 65ba0218..d5b674bf 100644 --- a/src/casedev/types/ocr/v1_retrieve_params.py +++ b/src/casedev/types/ocr/v1_retrieve_params.py @@ -9,4 +9,4 @@ class V1RetrieveParams(TypedDict, total=False): include_text: Literal["true", "false"] - """Include full OCR text in completed responses (default: true)""" + """Include full OCR text in completed responses (default: false)""" diff --git a/src/casedev/types/ocr/v1_retrieve_response.py b/src/casedev/types/ocr/v1_retrieve_response.py index a5a6ca8a..d7173544 100644 --- a/src/casedev/types/ocr/v1_retrieve_response.py +++ b/src/casedev/types/ocr/v1_retrieve_response.py @@ -29,4 +29,4 @@ class V1RetrieveResponse(BaseModel): """Number of pages processed""" text: Optional[str] = None - """Extracted text content (when completed)""" + """Extracted text content when completed and include_text=true""" diff --git a/src/casedev/types/search/__init__.py b/src/casedev/types/search/__init__.py index bd520293..5365d86e 100644 --- a/src/casedev/types/search/__init__.py +++ b/src/casedev/types/search/__init__.py @@ -7,10 +7,6 @@ from .v1_similar_params import V1SimilarParams as V1SimilarParams from .v1_answer_response import V1AnswerResponse as V1AnswerResponse from .v1_contents_params import V1ContentsParams as V1ContentsParams -from .v1_research_params import V1ResearchParams as V1ResearchParams from .v1_search_response import V1SearchResponse as V1SearchResponse from .v1_similar_response import V1SimilarResponse as V1SimilarResponse from .v1_contents_response import V1ContentsResponse as V1ContentsResponse -from .v1_research_response import V1ResearchResponse as V1ResearchResponse -from .v1_retrieve_research_params import V1RetrieveResearchParams as V1RetrieveResearchParams -from .v1_retrieve_research_response import V1RetrieveResearchResponse as V1RetrieveResearchResponse diff --git a/src/casedev/types/search/v1_research_params.py b/src/casedev/types/search/v1_research_params.py deleted file mode 100644 index ea5924af..00000000 --- a/src/casedev/types/search/v1_research_params.py +++ /dev/null @@ -1,23 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from __future__ import annotations - -from typing_extensions import Literal, Required, Annotated, TypedDict - -from ..._utils import PropertyInfo - -__all__ = ["V1ResearchParams"] - - -class V1ResearchParams(TypedDict, total=False): - instructions: Required[str] - """Research instructions or query""" - - model: Literal["fast", "normal", "pro"] - """Research quality level - fast (quick), normal (balanced), pro (comprehensive)""" - - output_schema: Annotated[object, PropertyInfo(alias="outputSchema")] - """Optional JSON schema to structure the research output""" - - query: str - """Alias for instructions (for convenience)""" diff --git a/src/casedev/types/search/v1_research_response.py b/src/casedev/types/search/v1_research_response.py deleted file mode 100644 index db1b1259..00000000 --- a/src/casedev/types/search/v1_research_response.py +++ /dev/null @@ -1,20 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from typing import Optional - -from pydantic import Field as FieldInfo - -from ..._models import BaseModel - -__all__ = ["V1ResearchResponse"] - - -class V1ResearchResponse(BaseModel): - model: Optional[str] = None - """Model used for research""" - - research_id: Optional[str] = FieldInfo(alias="researchId", default=None) - """Unique identifier for this research""" - - results: Optional[object] = None - """Research findings and analysis""" diff --git a/src/casedev/types/search/v1_retrieve_research_params.py b/src/casedev/types/search/v1_retrieve_research_params.py deleted file mode 100644 index c62a5e1c..00000000 --- a/src/casedev/types/search/v1_retrieve_research_params.py +++ /dev/null @@ -1,15 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from __future__ import annotations - -from typing_extensions import TypedDict - -__all__ = ["V1RetrieveResearchParams"] - - -class V1RetrieveResearchParams(TypedDict, total=False): - events: str - """Filter specific event types for streaming""" - - stream: bool - """Enable streaming for real-time updates""" diff --git a/src/casedev/types/search/v1_retrieve_research_response.py b/src/casedev/types/search/v1_retrieve_research_response.py deleted file mode 100644 index 2e05e7d6..00000000 --- a/src/casedev/types/search/v1_retrieve_research_response.py +++ /dev/null @@ -1,74 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from typing import List, Optional -from datetime import datetime -from typing_extensions import Literal - -from pydantic import Field as FieldInfo - -from ..._models import BaseModel - -__all__ = ["V1RetrieveResearchResponse", "Results", "ResultsSection", "ResultsSectionSource", "ResultsSource"] - - -class ResultsSectionSource(BaseModel): - snippet: Optional[str] = None - - title: Optional[str] = None - - url: Optional[str] = None - - -class ResultsSection(BaseModel): - content: Optional[str] = None - - sources: Optional[List[ResultsSectionSource]] = None - - title: Optional[str] = None - - -class ResultsSource(BaseModel): - snippet: Optional[str] = None - - title: Optional[str] = None - - url: Optional[str] = None - - -class Results(BaseModel): - """Research findings and analysis""" - - sections: Optional[List[ResultsSection]] = None - """Detailed research sections""" - - sources: Optional[List[ResultsSource]] = None - """All sources referenced in research""" - - summary: Optional[str] = None - """Executive summary of research findings""" - - -class V1RetrieveResearchResponse(BaseModel): - id: Optional[str] = None - """Research task ID""" - - completed_at: Optional[datetime] = FieldInfo(alias="completedAt", default=None) - """Task completion timestamp""" - - created_at: Optional[datetime] = FieldInfo(alias="createdAt", default=None) - """Task creation timestamp""" - - model: Optional[Literal["fast", "normal", "pro"]] = None - """Research model used""" - - progress: Optional[float] = None - """Completion percentage (0-100)""" - - query: Optional[str] = None - """Original research query""" - - results: Optional[Results] = None - """Research findings and analysis""" - - status: Optional[Literal["pending", "running", "completed", "failed"]] = None - """Current status of the research task""" diff --git a/src/casedev/types/superdoc/__init__.py b/src/casedev/types/superdoc/__init__.py deleted file mode 100644 index 111238a8..00000000 --- a/src/casedev/types/superdoc/__init__.py +++ /dev/null @@ -1,6 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from __future__ import annotations - -from .v1_convert_params import V1ConvertParams as V1ConvertParams -from .v1_annotate_params import V1AnnotateParams as V1AnnotateParams diff --git a/src/casedev/types/superdoc/v1_annotate_params.py b/src/casedev/types/superdoc/v1_annotate_params.py deleted file mode 100644 index fc0321ba..00000000 --- a/src/casedev/types/superdoc/v1_annotate_params.py +++ /dev/null @@ -1,56 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from __future__ import annotations - -from typing import Union, Iterable -from typing_extensions import Literal, Required, TypedDict - -__all__ = ["V1AnnotateParams", "Document", "Field", "FieldOptions"] - - -class V1AnnotateParams(TypedDict, total=False): - document: Required[Document] - """Document source - provide either URL or base64""" - - fields: Required[Iterable[Field]] - """Fields to populate in the template""" - - output_format: Literal["docx", "pdf"] - """Output format for the annotated document""" - - -class Document(TypedDict, total=False): - """Document source - provide either URL or base64""" - - base64: str - """Base64-encoded DOCX template""" - - url: str - """URL to the DOCX template""" - - -class FieldOptions(TypedDict, total=False): - """Optional configuration (e.g., image dimensions)""" - - height: float - """Image height in pixels""" - - width: float - """Image width in pixels""" - - -class Field(TypedDict, total=False): - type: Required[Literal["text", "image", "date", "number"]] - """Field data type""" - - value: Required[Union[str, float]] - """Value to populate""" - - id: str - """Target field ID (for single field)""" - - group: str - """Target field group (for multiple fields with same tag)""" - - options: FieldOptions - """Optional configuration (e.g., image dimensions)""" diff --git a/src/casedev/types/superdoc/v1_convert_params.py b/src/casedev/types/superdoc/v1_convert_params.py deleted file mode 100644 index 7e1513fb..00000000 --- a/src/casedev/types/superdoc/v1_convert_params.py +++ /dev/null @@ -1,23 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from __future__ import annotations - -from typing_extensions import Literal, Required, Annotated, TypedDict - -from ..._utils import PropertyInfo - -__all__ = ["V1ConvertParams"] - - -class V1ConvertParams(TypedDict, total=False): - from_: Required[Annotated[Literal["docx", "md", "html"], PropertyInfo(alias="from")]] - """Source format of the document""" - - document_base64: str - """Base64-encoded document content""" - - document_url: str - """URL to the document to convert""" - - to: Literal["pdf", "docx"] - """Target format for conversion""" diff --git a/src/casedev/types/translate/__init__.py b/src/casedev/types/translate/__init__.py index 8df52194..28cf9f11 100644 --- a/src/casedev/types/translate/__init__.py +++ b/src/casedev/types/translate/__init__.py @@ -8,3 +8,4 @@ from .v1_translate_response import V1TranslateResponse as V1TranslateResponse from .v1_list_languages_params import V1ListLanguagesParams as V1ListLanguagesParams from .v1_list_languages_response import V1ListLanguagesResponse as V1ListLanguagesResponse +from .v1_translate_document_params import V1TranslateDocumentParams as V1TranslateDocumentParams diff --git a/src/casedev/types/translate/v1_translate_document_params.py b/src/casedev/types/translate/v1_translate_document_params.py new file mode 100644 index 00000000..64abe2d2 --- /dev/null +++ b/src/casedev/types/translate/v1_translate_document_params.py @@ -0,0 +1,20 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing_extensions import Required, TypedDict + +from ..._types import FileTypes + +__all__ = ["V1TranslateDocumentParams"] + + +class V1TranslateDocumentParams(TypedDict, total=False): + file: Required[FileTypes] + """TXT, DOCX, or searchable PDF document (max 20MB)""" + + target: Required[str] + """Target BCP-47 language code""" + + source: str + """Optional source BCP-47 language code. Auto-detected when omitted.""" diff --git a/src/casedev/types/vault/__init__.py b/src/casedev/types/vault/__init__.py index 3847c97b..702284d9 100644 --- a/src/casedev/types/vault/__init__.py +++ b/src/casedev/types/vault/__init__.py @@ -5,6 +5,7 @@ from .object_list_params import ObjectListParams as ObjectListParams from .group_create_params import GroupCreateParams as GroupCreateParams from .group_update_params import GroupUpdateParams as GroupUpdateParams +from .object_merge_params import ObjectMergeParams as ObjectMergeParams from .memory_create_params import MemoryCreateParams as MemoryCreateParams from .memory_list_response import MemoryListResponse as MemoryListResponse from .memory_search_params import MemorySearchParams as MemorySearchParams @@ -14,7 +15,7 @@ from .object_list_response import ObjectListResponse as ObjectListResponse from .object_update_params import ObjectUpdateParams as ObjectUpdateParams from .multipart_init_params import MultipartInitParams as MultipartInitParams -from .graphrag_init_response import GraphragInitResponse as GraphragInitResponse +from .object_merge_response import ObjectMergeResponse as ObjectMergeResponse from .memory_create_response import MemoryCreateResponse as MemoryCreateResponse from .memory_search_response import MemorySearchResponse as MemorySearchResponse from .multipart_abort_params import MultipartAbortParams as MultipartAbortParams @@ -23,20 +24,15 @@ from .object_update_response import ObjectUpdateResponse as ObjectUpdateResponse from .multipart_init_response import MultipartInitResponse as MultipartInitResponse from .object_get_pages_params import ObjectGetPagesParams as ObjectGetPagesParams -from .object_summarize_params import ObjectSummarizeParams as ObjectSummarizeParams from .object_get_chunks_params import ObjectGetChunksParams as ObjectGetChunksParams from .object_get_text_response import ObjectGetTextResponse as ObjectGetTextResponse from .object_retrieve_response import ObjectRetrieveResponse as ObjectRetrieveResponse from .multipart_complete_params import MultipartCompleteParams as MultipartCompleteParams from .object_get_pages_response import ObjectGetPagesResponse as ObjectGetPagesResponse -from .object_summarize_response import ObjectSummarizeResponse as ObjectSummarizeResponse from .object_get_chunks_response import ObjectGetChunksResponse as ObjectGetChunksResponse -from .graphrag_get_stats_response import GraphragGetStatsResponse as GraphragGetStatsResponse from .object_get_ocr_words_params import ObjectGetOcrWordsParams as ObjectGetOcrWordsParams from .object_get_ocr_words_response import ObjectGetOcrWordsResponse as ObjectGetOcrWordsResponse from .multipart_get_part_urls_params import MultipartGetPartURLsParams as MultipartGetPartURLsParams -from .graphrag_process_object_response import GraphragProcessObjectResponse as GraphragProcessObjectResponse from .multipart_get_part_urls_response import MultipartGetPartURLsResponse as MultipartGetPartURLsResponse -from .object_get_summarize_job_response import ObjectGetSummarizeJobResponse as ObjectGetSummarizeJobResponse from .object_create_presigned_url_params import ObjectCreatePresignedURLParams as ObjectCreatePresignedURLParams from .object_create_presigned_url_response import ObjectCreatePresignedURLResponse as ObjectCreatePresignedURLResponse diff --git a/src/casedev/types/vault/graphrag_get_stats_response.py b/src/casedev/types/vault/graphrag_get_stats_response.py deleted file mode 100644 index f390b944..00000000 --- a/src/casedev/types/vault/graphrag_get_stats_response.py +++ /dev/null @@ -1,31 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from typing import Optional -from datetime import datetime -from typing_extensions import Literal - -from pydantic import Field as FieldInfo - -from ..._models import BaseModel - -__all__ = ["GraphragGetStatsResponse"] - - -class GraphragGetStatsResponse(BaseModel): - communities: Optional[int] = None - """Number of entity communities identified""" - - documents: Optional[int] = None - """Number of processed documents""" - - entities: Optional[int] = None - """Total number of entities extracted from documents""" - - last_processed: Optional[datetime] = FieldInfo(alias="lastProcessed", default=None) - """Timestamp of last GraphRAG processing""" - - relationships: Optional[int] = None - """Total number of relationships between entities""" - - status: Optional[Literal["processing", "completed", "error"]] = None - """Current processing status""" diff --git a/src/casedev/types/vault/graphrag_init_response.py b/src/casedev/types/vault/graphrag_init_response.py deleted file mode 100644 index ef489299..00000000 --- a/src/casedev/types/vault/graphrag_init_response.py +++ /dev/null @@ -1,17 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from typing import Optional - -from ..._models import BaseModel - -__all__ = ["GraphragInitResponse"] - - -class GraphragInitResponse(BaseModel): - message: Optional[str] = None - - status: Optional[str] = None - - success: Optional[bool] = None - - vault_id: Optional[str] = None diff --git a/src/casedev/types/vault/graphrag_process_object_response.py b/src/casedev/types/vault/graphrag_process_object_response.py deleted file mode 100644 index d15b21ff..00000000 --- a/src/casedev/types/vault/graphrag_process_object_response.py +++ /dev/null @@ -1,45 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from typing import Optional - -from pydantic import Field as FieldInfo - -from ..._models import BaseModel - -__all__ = ["GraphragProcessObjectResponse", "Stats"] - - -class Stats(BaseModel): - """Extraction statistics""" - - community_count: Optional[int] = None - - entity_count: Optional[int] = None - - relationship_count: Optional[int] = None - - -class GraphragProcessObjectResponse(BaseModel): - communities: int - """Number of communities detected""" - - entities: int - """Number of entities extracted""" - - object_id: str = FieldInfo(alias="objectId") - """ID of the indexed object""" - - relationships: int - """Number of relationships extracted""" - - stats: Stats - """Extraction statistics""" - - status: str - """Status from GraphRAG service""" - - success: bool - """Whether indexing completed successfully""" - - vault_id: str = FieldInfo(alias="vaultId") - """ID of the vault""" diff --git a/src/casedev/types/vault/object_append_params.py b/src/casedev/types/vault/object_append_params.py index 7be67633..5c0f8ac7 100644 --- a/src/casedev/types/vault/object_append_params.py +++ b/src/casedev/types/vault/object_append_params.py @@ -7,7 +7,7 @@ from ..._types import SequenceNotStr from ..._utils import PropertyInfo -__all__ = ["ObjectAppendParams"] +__all__ = ["ObjectAppendParams", "Bates"] class ObjectAppendParams(TypedDict, total=False): @@ -29,9 +29,33 @@ class ObjectAppendParams(TypedDict, total=False): appended page. """ + bates: Bates + """Optional Bates stamping for appended source PDFs. + + Numbering is deterministic across appendObjectIds order and does not stamp the + target report pages. + """ + rewrite_links: Annotated[bool, PropertyInfo(alias="rewriteLinks")] """ When true, rewrites links in the target object to internal PDF jumps when the URL contains exactly one appended object ID as a standalone query parameter value or decoded path segment. """ + + +class Bates(TypedDict, total=False): + """Optional Bates stamping for appended source PDFs. + + Numbering is deterministic across appendObjectIds order and does not stamp the target report pages. + """ + + enabled: bool + + pad_to: Annotated[int, PropertyInfo(alias="padTo")] + + prefix: str + + start: int + + suffix: str diff --git a/src/casedev/types/vault/object_append_response.py b/src/casedev/types/vault/object_append_response.py index c038e0b3..a9fdf9ff 100644 --- a/src/casedev/types/vault/object_append_response.py +++ b/src/casedev/types/vault/object_append_response.py @@ -13,6 +13,8 @@ class ObjectAppendResponse(BaseModel): id: Optional[str] = None + bates: Optional[object] = None + checksum: Optional[str] = None content_type: Optional[str] = FieldInfo(alias="contentType", default=None) @@ -29,6 +31,8 @@ class ObjectAppendResponse(BaseModel): metadata: Optional[object] = None + object_id: Optional[str] = FieldInfo(alias="objectId", default=None) + page_count: Optional[int] = FieldInfo(alias="pageCount", default=None) size_bytes: Optional[int] = FieldInfo(alias="sizeBytes", default=None) diff --git a/src/casedev/types/vault/object_get_summarize_job_response.py b/src/casedev/types/vault/object_get_summarize_job_response.py deleted file mode 100644 index d57770f9..00000000 --- a/src/casedev/types/vault/object_get_summarize_job_response.py +++ /dev/null @@ -1,40 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from typing import Optional -from datetime import datetime -from typing_extensions import Literal - -from pydantic import Field as FieldInfo - -from ..._models import BaseModel - -__all__ = ["ObjectGetSummarizeJobResponse"] - - -class ObjectGetSummarizeJobResponse(BaseModel): - completed_at: Optional[datetime] = FieldInfo(alias="completedAt", default=None) - """When the job completed""" - - created_at: Optional[datetime] = FieldInfo(alias="createdAt", default=None) - """When the job was created""" - - error: Optional[str] = None - """Error message (if failed)""" - - job_id: Optional[str] = FieldInfo(alias="jobId", default=None) - """Case.dev job ID""" - - result_filename: Optional[str] = FieldInfo(alias="resultFilename", default=None) - """Filename of the result document (if completed)""" - - result_object_id: Optional[str] = FieldInfo(alias="resultObjectId", default=None) - """ID of the result document (if completed)""" - - source_object_id: Optional[str] = FieldInfo(alias="sourceObjectId", default=None) - """ID of the source document""" - - status: Optional[Literal["pending", "processing", "completed", "failed"]] = None - """Current job status""" - - workflow_type: Optional[str] = FieldInfo(alias="workflowType", default=None) - """Type of workflow being executed""" diff --git a/src/casedev/types/vault/object_merge_params.py b/src/casedev/types/vault/object_merge_params.py new file mode 100644 index 00000000..a0f3d6d9 --- /dev/null +++ b/src/casedev/types/vault/object_merge_params.py @@ -0,0 +1,36 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing_extensions import Literal, Required, Annotated, TypedDict + +from ..._types import SequenceNotStr +from ..._utils import PropertyInfo + +__all__ = ["ObjectMergeParams", "Bates"] + + +class ObjectMergeParams(TypedDict, total=False): + filename: Required[str] + """Output PDF filename""" + + source_object_ids: Required[Annotated[SequenceNotStr[str], PropertyInfo(alias="sourceObjectIds")]] + """Source object IDs in output order""" + + source_rendition: Required[Annotated[Literal["original", "searchable_pdf"], PropertyInfo(alias="sourceRendition")]] + + idempotency_key: Required[Annotated[str, PropertyInfo(alias="Idempotency-Key")]] + + bates: Bates + + client_reference: Annotated[str, PropertyInfo(alias="clientReference")] + + +class Bates(TypedDict, total=False): + pad_to: Annotated[int, PropertyInfo(alias="padTo")] + + prefix: str + + start: int + + suffix: str diff --git a/src/casedev/types/vault/object_merge_response.py b/src/casedev/types/vault/object_merge_response.py new file mode 100644 index 00000000..65704223 --- /dev/null +++ b/src/casedev/types/vault/object_merge_response.py @@ -0,0 +1,20 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import Optional +from typing_extensions import Literal + +from pydantic import Field as FieldInfo + +from ..._models import BaseModel + +__all__ = ["ObjectMergeResponse"] + + +class ObjectMergeResponse(BaseModel): + client_reference: Optional[str] = FieldInfo(alias="clientReference", default=None) + + object_id: Optional[str] = FieldInfo(alias="objectId", default=None) + + status: Optional[Literal["processing"]] = None + + workflow_id: Optional[str] = FieldInfo(alias="workflowId", default=None) diff --git a/src/casedev/types/vault/object_summarize_params.py b/src/casedev/types/vault/object_summarize_params.py deleted file mode 100644 index 7dfc29d7..00000000 --- a/src/casedev/types/vault/object_summarize_params.py +++ /dev/null @@ -1,19 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from __future__ import annotations - -from typing_extensions import Literal, Required, Annotated, TypedDict - -from ..._utils import PropertyInfo - -__all__ = ["ObjectSummarizeParams"] - - -class ObjectSummarizeParams(TypedDict, total=False): - id: Required[str] - - output_format: Annotated[Literal["PDF", "WORD"], PropertyInfo(alias="outputFormat")] - """Output format for the summary document""" - - workflow_type: Annotated[str, PropertyInfo(alias="workflowType")] - """Type of CaseMark workflow to run""" diff --git a/src/casedev/types/vault/object_summarize_response.py b/src/casedev/types/vault/object_summarize_response.py deleted file mode 100644 index d7205994..00000000 --- a/src/casedev/types/vault/object_summarize_response.py +++ /dev/null @@ -1,27 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from typing import Optional -from typing_extensions import Literal - -from pydantic import Field as FieldInfo - -from ..._models import BaseModel - -__all__ = ["ObjectSummarizeResponse"] - - -class ObjectSummarizeResponse(BaseModel): - casemark_workflow_id: Optional[str] = FieldInfo(alias="casemarkWorkflowId", default=None) - """CaseMark workflow ID""" - - job_id: Optional[str] = FieldInfo(alias="jobId", default=None) - """Case.dev job ID for tracking""" - - status: Optional[Literal["pending", "processing", "completed", "failed"]] = None - """Current job status""" - - status_url: Optional[str] = FieldInfo(alias="statusUrl", default=None) - """URL to check job status""" - - workflow_type: Optional[str] = FieldInfo(alias="workflowType", default=None) - """Type of workflow being executed""" diff --git a/src/casedev/types/vault_confirm_upload_params.py b/src/casedev/types/vault_confirm_upload_params.py index f094a8a9..9d684c4e 100644 --- a/src/casedev/types/vault_confirm_upload_params.py +++ b/src/casedev/types/vault_confirm_upload_params.py @@ -2,21 +2,17 @@ from __future__ import annotations -from typing import Union -from typing_extensions import Literal, Required, Annotated, TypeAlias, TypedDict +from typing_extensions import Required, Annotated, TypedDict from .._utils import PropertyInfo -__all__ = ["VaultConfirmUploadParams", "VaultConfirmUploadSuccess", "VaultConfirmUploadFailure"] +__all__ = ["VaultConfirmUploadParams"] -class VaultConfirmUploadSuccess(TypedDict, total=False): +class VaultConfirmUploadParams(TypedDict, total=False): id: Required[str] - size_bytes: Required[Annotated[int, PropertyInfo(alias="sizeBytes")]] - """Uploaded file size in bytes""" - - success: Required[Literal[True]] + success: Required[bool] """Whether the upload succeeded""" auto_ingest: Annotated[bool, PropertyInfo(alias="autoIngest")] @@ -27,21 +23,17 @@ class VaultConfirmUploadSuccess(TypedDict, total=False): does not fail the confirmation. """ - etag: str - """S3 ETag for the uploaded object (optional if client cannot access ETag header)""" - - -class VaultConfirmUploadFailure(TypedDict, total=False): - id: Required[str] + error_code: Annotated[str, PropertyInfo(alias="errorCode")] + """Client-side error code. Required when success=false.""" - error_code: Required[Annotated[str, PropertyInfo(alias="errorCode")]] - """Client-side error code""" + error_message: Annotated[str, PropertyInfo(alias="errorMessage")] + """Client-side error message. Required when success=false.""" - error_message: Required[Annotated[str, PropertyInfo(alias="errorMessage")]] - """Client-side error message""" - - success: Required[Literal[False]] - """Whether the upload succeeded""" + etag: str + """S3 ETag for the uploaded object (optional if client cannot access ETag header). + Only meaningful when success=true. + """ -VaultConfirmUploadParams: TypeAlias = Union[VaultConfirmUploadSuccess, VaultConfirmUploadFailure] + size_bytes: Annotated[int, PropertyInfo(alias="sizeBytes")] + """Uploaded file size in bytes. Required when success=true.""" diff --git a/src/casedev/types/vault_ingest_response.py b/src/casedev/types/vault_ingest_response.py index 454bf75c..0d3ffff8 100644 --- a/src/casedev/types/vault_ingest_response.py +++ b/src/casedev/types/vault_ingest_response.py @@ -12,10 +12,7 @@ class VaultIngestResponse(BaseModel): enable_graph_rag: bool = FieldInfo(alias="enableGraphRAG") - """ - Always false - GraphRAG must be triggered separately via POST - /vault/:id/graphrag/:objectId - """ + """Always false; retained for response compatibility""" message: str """Human-readable status message""" diff --git a/src/casedev/types/vault_search_params.py b/src/casedev/types/vault_search_params.py index 72c708e0..b3264eb3 100644 --- a/src/casedev/types/vault_search_params.py +++ b/src/casedev/types/vault_search_params.py @@ -31,7 +31,11 @@ class VaultSearchParams(TypedDict, total=False): """ -class Filters(TypedDict, total=False, extra_items=object): # type: ignore[call-arg] +class Filters( # type: ignore[call-arg] + TypedDict, + total=False, + extra_items=object, # pyright: ignore[reportGeneralTypeIssues] +): """Filters to narrow search results to specific documents""" object_id: Union[str, SequenceNotStr[str]] diff --git a/src/casedev/types/vault_upload_params.py b/src/casedev/types/vault_upload_params.py index 034db6bc..af2e9f6e 100644 --- a/src/casedev/types/vault_upload_params.py +++ b/src/casedev/types/vault_upload_params.py @@ -42,3 +42,5 @@ class VaultUploadParams(TypedDict, total=False): When provided, enforces exact file size at S3 level. """ + + idempotency_key: Annotated[str, PropertyInfo(alias="Idempotency-Key")] diff --git a/src/casedev/types/vault_upload_response.py b/src/casedev/types/vault_upload_response.py index aba99367..6b97a741 100644 --- a/src/casedev/types/vault_upload_response.py +++ b/src/casedev/types/vault_upload_response.py @@ -18,6 +18,9 @@ class Instructions(BaseModel): class VaultUploadResponse(BaseModel): + already_uploaded: Optional[bool] = FieldInfo(alias="alreadyUploaded", default=None) + """True when this idempotency key already identifies a confirmed upload""" + auto_index: Optional[bool] = None """Whether the file will be automatically indexed""" diff --git a/src/casedev/types/voice/transcription_create_response.py b/src/casedev/types/voice/transcription_create_response.py index 20fee025..2430b802 100644 --- a/src/casedev/types/voice/transcription_create_response.py +++ b/src/casedev/types/voice/transcription_create_response.py @@ -12,10 +12,16 @@ class TranscriptionCreateResponse(BaseModel): id: Optional[str] = None """Unique transcription job ID""" + input_object_id: Optional[str] = None + """Object submitted to the speech provider. + + For large videos, this is an internal audio derivative. + """ + source_object_id: Optional[str] = None - """Source audio object ID (only for vault-based transcription)""" + """Original source media object ID (only for vault-based transcription)""" - status: Optional[Literal["queued", "processing", "completed", "error"]] = None + status: Optional[Literal["queued", "preprocessing", "processing", "completed", "error"]] = None """Current status of the transcription job""" vault_id: Optional[str] = None diff --git a/src/casedev/types/voice/transcription_retrieve_response.py b/src/casedev/types/voice/transcription_retrieve_response.py index a50dc146..66ff4d4e 100644 --- a/src/casedev/types/voice/transcription_retrieve_response.py +++ b/src/casedev/types/voice/transcription_retrieve_response.py @@ -12,7 +12,7 @@ class TranscriptionRetrieveResponse(BaseModel): id: str """Unique transcription job ID""" - status: Literal["queued", "processing", "completed", "failed"] + status: Literal["queued", "preprocessing", "processing", "completed", "failed"] """Current status of the transcription job""" audio_duration: Optional[float] = None @@ -24,11 +24,17 @@ class TranscriptionRetrieveResponse(BaseModel): error: Optional[str] = None """Error message (only present when status is failed)""" + input_object_id: Optional[str] = None + """Media object submitted to the speech provider. + + May be an internal audio derivative for large videos. + """ + result_object_id: Optional[str] = None """Result transcript object ID (vault-based jobs, when completed)""" source_object_id: Optional[str] = None - """Source audio object ID (vault-based jobs only)""" + """Original source media object ID (vault-based jobs only)""" text: Optional[str] = None """ diff --git a/tests/api_resources/agent/v1/test_agents.py b/tests/api_resources/agent/v1/test_agents.py deleted file mode 100644 index 91ce447a..00000000 --- a/tests/api_resources/agent/v1/test_agents.py +++ /dev/null @@ -1,460 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from __future__ import annotations - -import os -from typing import Any, cast - -import pytest - -from casedev import Casedev, AsyncCasedev -from tests.utils import assert_matches_type -from casedev.types.agent.v1 import ( - AgentListResponse, - AgentCreateResponse, - AgentDeleteResponse, - AgentUpdateResponse, - AgentRetrieveResponse, -) - -base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") - - -class TestAgents: - parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"]) - - @parametrize - def test_method_create(self, client: Casedev) -> None: - agent = client.agent.v1.agents.create( - instructions="instructions", - name="name", - ) - assert_matches_type(AgentCreateResponse, agent, path=["response"]) - - @parametrize - def test_method_create_with_all_params(self, client: Casedev) -> None: - agent = client.agent.v1.agents.create( - instructions="instructions", - name="name", - description="description", - disabled_tools=["string"], - enabled_tools=["string"], - model="model", - sandbox={ - "cpu": 0, - "memory_mi_b": 0, - }, - vault_groups=["string"], - vault_ids=["string"], - ) - assert_matches_type(AgentCreateResponse, agent, path=["response"]) - - @parametrize - def test_raw_response_create(self, client: Casedev) -> None: - response = client.agent.v1.agents.with_raw_response.create( - instructions="instructions", - name="name", - ) - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - agent = response.parse() - assert_matches_type(AgentCreateResponse, agent, path=["response"]) - - @parametrize - def test_streaming_response_create(self, client: Casedev) -> None: - with client.agent.v1.agents.with_streaming_response.create( - instructions="instructions", - name="name", - ) as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - agent = response.parse() - assert_matches_type(AgentCreateResponse, agent, path=["response"]) - - assert cast(Any, response.is_closed) is True - - @parametrize - def test_method_retrieve(self, client: Casedev) -> None: - agent = client.agent.v1.agents.retrieve( - "id", - ) - assert_matches_type(AgentRetrieveResponse, agent, path=["response"]) - - @parametrize - def test_raw_response_retrieve(self, client: Casedev) -> None: - response = client.agent.v1.agents.with_raw_response.retrieve( - "id", - ) - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - agent = response.parse() - assert_matches_type(AgentRetrieveResponse, agent, path=["response"]) - - @parametrize - def test_streaming_response_retrieve(self, client: Casedev) -> None: - with client.agent.v1.agents.with_streaming_response.retrieve( - "id", - ) as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - agent = response.parse() - assert_matches_type(AgentRetrieveResponse, agent, path=["response"]) - - assert cast(Any, response.is_closed) is True - - @parametrize - def test_path_params_retrieve(self, client: Casedev) -> None: - with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): - client.agent.v1.agents.with_raw_response.retrieve( - "", - ) - - @parametrize - def test_method_update(self, client: Casedev) -> None: - agent = client.agent.v1.agents.update( - id="id", - ) - assert_matches_type(AgentUpdateResponse, agent, path=["response"]) - - @parametrize - def test_method_update_with_all_params(self, client: Casedev) -> None: - agent = client.agent.v1.agents.update( - id="id", - description="description", - disabled_tools=["string"], - enabled_tools=["string"], - instructions="instructions", - model="model", - name="name", - sandbox={}, - vault_groups=["string"], - vault_ids=["string"], - ) - assert_matches_type(AgentUpdateResponse, agent, path=["response"]) - - @parametrize - def test_raw_response_update(self, client: Casedev) -> None: - response = client.agent.v1.agents.with_raw_response.update( - id="id", - ) - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - agent = response.parse() - assert_matches_type(AgentUpdateResponse, agent, path=["response"]) - - @parametrize - def test_streaming_response_update(self, client: Casedev) -> None: - with client.agent.v1.agents.with_streaming_response.update( - id="id", - ) as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - agent = response.parse() - assert_matches_type(AgentUpdateResponse, agent, path=["response"]) - - assert cast(Any, response.is_closed) is True - - @parametrize - def test_path_params_update(self, client: Casedev) -> None: - with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): - client.agent.v1.agents.with_raw_response.update( - id="", - ) - - @parametrize - def test_method_list(self, client: Casedev) -> None: - agent = client.agent.v1.agents.list() - assert_matches_type(AgentListResponse, agent, path=["response"]) - - @parametrize - def test_method_list_with_all_params(self, client: Casedev) -> None: - agent = client.agent.v1.agents.list( - cursor="cursor", - limit=1, - ) - assert_matches_type(AgentListResponse, agent, path=["response"]) - - @parametrize - def test_raw_response_list(self, client: Casedev) -> None: - response = client.agent.v1.agents.with_raw_response.list() - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - agent = response.parse() - assert_matches_type(AgentListResponse, agent, path=["response"]) - - @parametrize - def test_streaming_response_list(self, client: Casedev) -> None: - with client.agent.v1.agents.with_streaming_response.list() as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - agent = response.parse() - assert_matches_type(AgentListResponse, agent, path=["response"]) - - assert cast(Any, response.is_closed) is True - - @parametrize - def test_method_delete(self, client: Casedev) -> None: - agent = client.agent.v1.agents.delete( - "id", - ) - assert_matches_type(AgentDeleteResponse, agent, path=["response"]) - - @parametrize - def test_raw_response_delete(self, client: Casedev) -> None: - response = client.agent.v1.agents.with_raw_response.delete( - "id", - ) - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - agent = response.parse() - assert_matches_type(AgentDeleteResponse, agent, path=["response"]) - - @parametrize - def test_streaming_response_delete(self, client: Casedev) -> None: - with client.agent.v1.agents.with_streaming_response.delete( - "id", - ) as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - agent = response.parse() - assert_matches_type(AgentDeleteResponse, agent, path=["response"]) - - assert cast(Any, response.is_closed) is True - - @parametrize - def test_path_params_delete(self, client: Casedev) -> None: - with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): - client.agent.v1.agents.with_raw_response.delete( - "", - ) - - -class TestAsyncAgents: - parametrize = pytest.mark.parametrize( - "async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"] - ) - - @parametrize - async def test_method_create(self, async_client: AsyncCasedev) -> None: - agent = await async_client.agent.v1.agents.create( - instructions="instructions", - name="name", - ) - assert_matches_type(AgentCreateResponse, agent, path=["response"]) - - @parametrize - async def test_method_create_with_all_params(self, async_client: AsyncCasedev) -> None: - agent = await async_client.agent.v1.agents.create( - instructions="instructions", - name="name", - description="description", - disabled_tools=["string"], - enabled_tools=["string"], - model="model", - sandbox={ - "cpu": 0, - "memory_mi_b": 0, - }, - vault_groups=["string"], - vault_ids=["string"], - ) - assert_matches_type(AgentCreateResponse, agent, path=["response"]) - - @parametrize - async def test_raw_response_create(self, async_client: AsyncCasedev) -> None: - response = await async_client.agent.v1.agents.with_raw_response.create( - instructions="instructions", - name="name", - ) - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - agent = await response.parse() - assert_matches_type(AgentCreateResponse, agent, path=["response"]) - - @parametrize - async def test_streaming_response_create(self, async_client: AsyncCasedev) -> None: - async with async_client.agent.v1.agents.with_streaming_response.create( - instructions="instructions", - name="name", - ) as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - agent = await response.parse() - assert_matches_type(AgentCreateResponse, agent, path=["response"]) - - assert cast(Any, response.is_closed) is True - - @parametrize - async def test_method_retrieve(self, async_client: AsyncCasedev) -> None: - agent = await async_client.agent.v1.agents.retrieve( - "id", - ) - assert_matches_type(AgentRetrieveResponse, agent, path=["response"]) - - @parametrize - async def test_raw_response_retrieve(self, async_client: AsyncCasedev) -> None: - response = await async_client.agent.v1.agents.with_raw_response.retrieve( - "id", - ) - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - agent = await response.parse() - assert_matches_type(AgentRetrieveResponse, agent, path=["response"]) - - @parametrize - async def test_streaming_response_retrieve(self, async_client: AsyncCasedev) -> None: - async with async_client.agent.v1.agents.with_streaming_response.retrieve( - "id", - ) as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - agent = await response.parse() - assert_matches_type(AgentRetrieveResponse, agent, path=["response"]) - - assert cast(Any, response.is_closed) is True - - @parametrize - async def test_path_params_retrieve(self, async_client: AsyncCasedev) -> None: - with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): - await async_client.agent.v1.agents.with_raw_response.retrieve( - "", - ) - - @parametrize - async def test_method_update(self, async_client: AsyncCasedev) -> None: - agent = await async_client.agent.v1.agents.update( - id="id", - ) - assert_matches_type(AgentUpdateResponse, agent, path=["response"]) - - @parametrize - async def test_method_update_with_all_params(self, async_client: AsyncCasedev) -> None: - agent = await async_client.agent.v1.agents.update( - id="id", - description="description", - disabled_tools=["string"], - enabled_tools=["string"], - instructions="instructions", - model="model", - name="name", - sandbox={}, - vault_groups=["string"], - vault_ids=["string"], - ) - assert_matches_type(AgentUpdateResponse, agent, path=["response"]) - - @parametrize - async def test_raw_response_update(self, async_client: AsyncCasedev) -> None: - response = await async_client.agent.v1.agents.with_raw_response.update( - id="id", - ) - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - agent = await response.parse() - assert_matches_type(AgentUpdateResponse, agent, path=["response"]) - - @parametrize - async def test_streaming_response_update(self, async_client: AsyncCasedev) -> None: - async with async_client.agent.v1.agents.with_streaming_response.update( - id="id", - ) as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - agent = await response.parse() - assert_matches_type(AgentUpdateResponse, agent, path=["response"]) - - assert cast(Any, response.is_closed) is True - - @parametrize - async def test_path_params_update(self, async_client: AsyncCasedev) -> None: - with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): - await async_client.agent.v1.agents.with_raw_response.update( - id="", - ) - - @parametrize - async def test_method_list(self, async_client: AsyncCasedev) -> None: - agent = await async_client.agent.v1.agents.list() - assert_matches_type(AgentListResponse, agent, path=["response"]) - - @parametrize - async def test_method_list_with_all_params(self, async_client: AsyncCasedev) -> None: - agent = await async_client.agent.v1.agents.list( - cursor="cursor", - limit=1, - ) - assert_matches_type(AgentListResponse, agent, path=["response"]) - - @parametrize - async def test_raw_response_list(self, async_client: AsyncCasedev) -> None: - response = await async_client.agent.v1.agents.with_raw_response.list() - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - agent = await response.parse() - assert_matches_type(AgentListResponse, agent, path=["response"]) - - @parametrize - async def test_streaming_response_list(self, async_client: AsyncCasedev) -> None: - async with async_client.agent.v1.agents.with_streaming_response.list() as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - agent = await response.parse() - assert_matches_type(AgentListResponse, agent, path=["response"]) - - assert cast(Any, response.is_closed) is True - - @parametrize - async def test_method_delete(self, async_client: AsyncCasedev) -> None: - agent = await async_client.agent.v1.agents.delete( - "id", - ) - assert_matches_type(AgentDeleteResponse, agent, path=["response"]) - - @parametrize - async def test_raw_response_delete(self, async_client: AsyncCasedev) -> None: - response = await async_client.agent.v1.agents.with_raw_response.delete( - "id", - ) - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - agent = await response.parse() - assert_matches_type(AgentDeleteResponse, agent, path=["response"]) - - @parametrize - async def test_streaming_response_delete(self, async_client: AsyncCasedev) -> None: - async with async_client.agent.v1.agents.with_streaming_response.delete( - "id", - ) as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - agent = await response.parse() - assert_matches_type(AgentDeleteResponse, agent, path=["response"]) - - assert cast(Any, response.is_closed) is True - - @parametrize - async def test_path_params_delete(self, async_client: AsyncCasedev) -> None: - with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): - await async_client.agent.v1.agents.with_raw_response.delete( - "", - ) diff --git a/tests/api_resources/agent/v1/test_execute.py b/tests/api_resources/agent/v1/test_execute.py deleted file mode 100644 index 6a1e4370..00000000 --- a/tests/api_resources/agent/v1/test_execute.py +++ /dev/null @@ -1,122 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from __future__ import annotations - -import os -from typing import Any, cast - -import pytest - -from casedev import Casedev, AsyncCasedev -from tests.utils import assert_matches_type -from casedev.types.agent.v1 import ExecuteCreateResponse - -base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") - - -class TestExecute: - parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"]) - - @parametrize - def test_method_create(self, client: Casedev) -> None: - execute = client.agent.v1.execute.create( - prompt="prompt", - ) - assert_matches_type(ExecuteCreateResponse, execute, path=["response"]) - - @parametrize - def test_method_create_with_all_params(self, client: Casedev) -> None: - execute = client.agent.v1.execute.create( - prompt="prompt", - disabled_tools=["string"], - enabled_tools=["string"], - guidance="guidance", - instructions="instructions", - model="model", - object_ids=["string"], - sandbox={ - "cpu": 0, - "memory_mi_b": 0, - }, - vault_ids=["string"], - ) - assert_matches_type(ExecuteCreateResponse, execute, path=["response"]) - - @parametrize - def test_raw_response_create(self, client: Casedev) -> None: - response = client.agent.v1.execute.with_raw_response.create( - prompt="prompt", - ) - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - execute = response.parse() - assert_matches_type(ExecuteCreateResponse, execute, path=["response"]) - - @parametrize - def test_streaming_response_create(self, client: Casedev) -> None: - with client.agent.v1.execute.with_streaming_response.create( - prompt="prompt", - ) as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - execute = response.parse() - assert_matches_type(ExecuteCreateResponse, execute, path=["response"]) - - assert cast(Any, response.is_closed) is True - - -class TestAsyncExecute: - parametrize = pytest.mark.parametrize( - "async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"] - ) - - @parametrize - async def test_method_create(self, async_client: AsyncCasedev) -> None: - execute = await async_client.agent.v1.execute.create( - prompt="prompt", - ) - assert_matches_type(ExecuteCreateResponse, execute, path=["response"]) - - @parametrize - async def test_method_create_with_all_params(self, async_client: AsyncCasedev) -> None: - execute = await async_client.agent.v1.execute.create( - prompt="prompt", - disabled_tools=["string"], - enabled_tools=["string"], - guidance="guidance", - instructions="instructions", - model="model", - object_ids=["string"], - sandbox={ - "cpu": 0, - "memory_mi_b": 0, - }, - vault_ids=["string"], - ) - assert_matches_type(ExecuteCreateResponse, execute, path=["response"]) - - @parametrize - async def test_raw_response_create(self, async_client: AsyncCasedev) -> None: - response = await async_client.agent.v1.execute.with_raw_response.create( - prompt="prompt", - ) - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - execute = await response.parse() - assert_matches_type(ExecuteCreateResponse, execute, path=["response"]) - - @parametrize - async def test_streaming_response_create(self, async_client: AsyncCasedev) -> None: - async with async_client.agent.v1.execute.with_streaming_response.create( - prompt="prompt", - ) as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - execute = await response.parse() - assert_matches_type(ExecuteCreateResponse, execute, path=["response"]) - - assert cast(Any, response.is_closed) is True diff --git a/tests/api_resources/agent/v1/test_run.py b/tests/api_resources/agent/v1/test_run.py deleted file mode 100644 index 902153a1..00000000 --- a/tests/api_resources/agent/v1/test_run.py +++ /dev/null @@ -1,672 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from __future__ import annotations - -import os -from typing import Any, cast - -import pytest - -from casedev import Casedev, AsyncCasedev -from tests.utils import assert_matches_type -from casedev.types.agent.v1 import ( - RunExecResponse, - RunListResponse, - RunWatchResponse, - RunCancelResponse, - RunCreateResponse, - RunGetStatusResponse, - RunGetDetailsResponse, -) - -base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") - - -class TestRun: - parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"]) - - @parametrize - def test_method_create(self, client: Casedev) -> None: - run = client.agent.v1.run.create( - agent_id="agentId", - prompt="prompt", - ) - assert_matches_type(RunCreateResponse, run, path=["response"]) - - @parametrize - def test_method_create_with_all_params(self, client: Casedev) -> None: - run = client.agent.v1.run.create( - agent_id="agentId", - prompt="prompt", - callback_url="https://example.com", - guidance="guidance", - model="model", - object_ids=["string"], - ) - assert_matches_type(RunCreateResponse, run, path=["response"]) - - @parametrize - def test_raw_response_create(self, client: Casedev) -> None: - response = client.agent.v1.run.with_raw_response.create( - agent_id="agentId", - prompt="prompt", - ) - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - run = response.parse() - assert_matches_type(RunCreateResponse, run, path=["response"]) - - @parametrize - def test_streaming_response_create(self, client: Casedev) -> None: - with client.agent.v1.run.with_streaming_response.create( - agent_id="agentId", - prompt="prompt", - ) as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - run = response.parse() - assert_matches_type(RunCreateResponse, run, path=["response"]) - - assert cast(Any, response.is_closed) is True - - @parametrize - def test_method_list(self, client: Casedev) -> None: - run = client.agent.v1.run.list() - assert_matches_type(RunListResponse, run, path=["response"]) - - @parametrize - def test_method_list_with_all_params(self, client: Casedev) -> None: - run = client.agent.v1.run.list( - agent_id="agentId", - cursor="cursor", - limit=1, - status="queued", - ) - assert_matches_type(RunListResponse, run, path=["response"]) - - @parametrize - def test_raw_response_list(self, client: Casedev) -> None: - response = client.agent.v1.run.with_raw_response.list() - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - run = response.parse() - assert_matches_type(RunListResponse, run, path=["response"]) - - @parametrize - def test_streaming_response_list(self, client: Casedev) -> None: - with client.agent.v1.run.with_streaming_response.list() as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - run = response.parse() - assert_matches_type(RunListResponse, run, path=["response"]) - - assert cast(Any, response.is_closed) is True - - @parametrize - def test_method_cancel(self, client: Casedev) -> None: - run = client.agent.v1.run.cancel( - "id", - ) - assert_matches_type(RunCancelResponse, run, path=["response"]) - - @parametrize - def test_raw_response_cancel(self, client: Casedev) -> None: - response = client.agent.v1.run.with_raw_response.cancel( - "id", - ) - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - run = response.parse() - assert_matches_type(RunCancelResponse, run, path=["response"]) - - @parametrize - def test_streaming_response_cancel(self, client: Casedev) -> None: - with client.agent.v1.run.with_streaming_response.cancel( - "id", - ) as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - run = response.parse() - assert_matches_type(RunCancelResponse, run, path=["response"]) - - assert cast(Any, response.is_closed) is True - - @parametrize - def test_path_params_cancel(self, client: Casedev) -> None: - with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): - client.agent.v1.run.with_raw_response.cancel( - "", - ) - - @parametrize - def test_method_events(self, client: Casedev) -> None: - run_stream = client.agent.v1.run.events( - id="id", - ) - run_stream.response.close() - - @parametrize - def test_method_events_with_all_params(self, client: Casedev) -> None: - run_stream = client.agent.v1.run.events( - id="id", - last_event_id=0, - ) - run_stream.response.close() - - @parametrize - def test_raw_response_events(self, client: Casedev) -> None: - response = client.agent.v1.run.with_raw_response.events( - id="id", - ) - - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - stream = response.parse() - stream.close() - - @parametrize - def test_streaming_response_events(self, client: Casedev) -> None: - with client.agent.v1.run.with_streaming_response.events( - id="id", - ) as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - stream = response.parse() - stream.close() - - assert cast(Any, response.is_closed) is True - - @parametrize - def test_path_params_events(self, client: Casedev) -> None: - with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): - client.agent.v1.run.with_raw_response.events( - id="", - ) - - @parametrize - def test_method_exec(self, client: Casedev) -> None: - run = client.agent.v1.run.exec( - "id", - ) - assert_matches_type(RunExecResponse, run, path=["response"]) - - @parametrize - def test_raw_response_exec(self, client: Casedev) -> None: - response = client.agent.v1.run.with_raw_response.exec( - "id", - ) - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - run = response.parse() - assert_matches_type(RunExecResponse, run, path=["response"]) - - @parametrize - def test_streaming_response_exec(self, client: Casedev) -> None: - with client.agent.v1.run.with_streaming_response.exec( - "id", - ) as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - run = response.parse() - assert_matches_type(RunExecResponse, run, path=["response"]) - - assert cast(Any, response.is_closed) is True - - @parametrize - def test_path_params_exec(self, client: Casedev) -> None: - with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): - client.agent.v1.run.with_raw_response.exec( - "", - ) - - @parametrize - def test_method_get_details(self, client: Casedev) -> None: - run = client.agent.v1.run.get_details( - "id", - ) - assert_matches_type(RunGetDetailsResponse, run, path=["response"]) - - @parametrize - def test_raw_response_get_details(self, client: Casedev) -> None: - response = client.agent.v1.run.with_raw_response.get_details( - "id", - ) - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - run = response.parse() - assert_matches_type(RunGetDetailsResponse, run, path=["response"]) - - @parametrize - def test_streaming_response_get_details(self, client: Casedev) -> None: - with client.agent.v1.run.with_streaming_response.get_details( - "id", - ) as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - run = response.parse() - assert_matches_type(RunGetDetailsResponse, run, path=["response"]) - - assert cast(Any, response.is_closed) is True - - @parametrize - def test_path_params_get_details(self, client: Casedev) -> None: - with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): - client.agent.v1.run.with_raw_response.get_details( - "", - ) - - @parametrize - def test_method_get_status(self, client: Casedev) -> None: - run = client.agent.v1.run.get_status( - "id", - ) - assert_matches_type(RunGetStatusResponse, run, path=["response"]) - - @parametrize - def test_raw_response_get_status(self, client: Casedev) -> None: - response = client.agent.v1.run.with_raw_response.get_status( - "id", - ) - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - run = response.parse() - assert_matches_type(RunGetStatusResponse, run, path=["response"]) - - @parametrize - def test_streaming_response_get_status(self, client: Casedev) -> None: - with client.agent.v1.run.with_streaming_response.get_status( - "id", - ) as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - run = response.parse() - assert_matches_type(RunGetStatusResponse, run, path=["response"]) - - assert cast(Any, response.is_closed) is True - - @parametrize - def test_path_params_get_status(self, client: Casedev) -> None: - with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): - client.agent.v1.run.with_raw_response.get_status( - "", - ) - - @parametrize - def test_method_watch(self, client: Casedev) -> None: - run = client.agent.v1.run.watch( - id="id", - callback_url="https://example.com", - ) - assert_matches_type(RunWatchResponse, run, path=["response"]) - - @parametrize - def test_raw_response_watch(self, client: Casedev) -> None: - response = client.agent.v1.run.with_raw_response.watch( - id="id", - callback_url="https://example.com", - ) - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - run = response.parse() - assert_matches_type(RunWatchResponse, run, path=["response"]) - - @parametrize - def test_streaming_response_watch(self, client: Casedev) -> None: - with client.agent.v1.run.with_streaming_response.watch( - id="id", - callback_url="https://example.com", - ) as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - run = response.parse() - assert_matches_type(RunWatchResponse, run, path=["response"]) - - assert cast(Any, response.is_closed) is True - - @parametrize - def test_path_params_watch(self, client: Casedev) -> None: - with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): - client.agent.v1.run.with_raw_response.watch( - id="", - callback_url="https://example.com", - ) - - -class TestAsyncRun: - parametrize = pytest.mark.parametrize( - "async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"] - ) - - @parametrize - async def test_method_create(self, async_client: AsyncCasedev) -> None: - run = await async_client.agent.v1.run.create( - agent_id="agentId", - prompt="prompt", - ) - assert_matches_type(RunCreateResponse, run, path=["response"]) - - @parametrize - async def test_method_create_with_all_params(self, async_client: AsyncCasedev) -> None: - run = await async_client.agent.v1.run.create( - agent_id="agentId", - prompt="prompt", - callback_url="https://example.com", - guidance="guidance", - model="model", - object_ids=["string"], - ) - assert_matches_type(RunCreateResponse, run, path=["response"]) - - @parametrize - async def test_raw_response_create(self, async_client: AsyncCasedev) -> None: - response = await async_client.agent.v1.run.with_raw_response.create( - agent_id="agentId", - prompt="prompt", - ) - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - run = await response.parse() - assert_matches_type(RunCreateResponse, run, path=["response"]) - - @parametrize - async def test_streaming_response_create(self, async_client: AsyncCasedev) -> None: - async with async_client.agent.v1.run.with_streaming_response.create( - agent_id="agentId", - prompt="prompt", - ) as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - run = await response.parse() - assert_matches_type(RunCreateResponse, run, path=["response"]) - - assert cast(Any, response.is_closed) is True - - @parametrize - async def test_method_list(self, async_client: AsyncCasedev) -> None: - run = await async_client.agent.v1.run.list() - assert_matches_type(RunListResponse, run, path=["response"]) - - @parametrize - async def test_method_list_with_all_params(self, async_client: AsyncCasedev) -> None: - run = await async_client.agent.v1.run.list( - agent_id="agentId", - cursor="cursor", - limit=1, - status="queued", - ) - assert_matches_type(RunListResponse, run, path=["response"]) - - @parametrize - async def test_raw_response_list(self, async_client: AsyncCasedev) -> None: - response = await async_client.agent.v1.run.with_raw_response.list() - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - run = await response.parse() - assert_matches_type(RunListResponse, run, path=["response"]) - - @parametrize - async def test_streaming_response_list(self, async_client: AsyncCasedev) -> None: - async with async_client.agent.v1.run.with_streaming_response.list() as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - run = await response.parse() - assert_matches_type(RunListResponse, run, path=["response"]) - - assert cast(Any, response.is_closed) is True - - @parametrize - async def test_method_cancel(self, async_client: AsyncCasedev) -> None: - run = await async_client.agent.v1.run.cancel( - "id", - ) - assert_matches_type(RunCancelResponse, run, path=["response"]) - - @parametrize - async def test_raw_response_cancel(self, async_client: AsyncCasedev) -> None: - response = await async_client.agent.v1.run.with_raw_response.cancel( - "id", - ) - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - run = await response.parse() - assert_matches_type(RunCancelResponse, run, path=["response"]) - - @parametrize - async def test_streaming_response_cancel(self, async_client: AsyncCasedev) -> None: - async with async_client.agent.v1.run.with_streaming_response.cancel( - "id", - ) as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - run = await response.parse() - assert_matches_type(RunCancelResponse, run, path=["response"]) - - assert cast(Any, response.is_closed) is True - - @parametrize - async def test_path_params_cancel(self, async_client: AsyncCasedev) -> None: - with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): - await async_client.agent.v1.run.with_raw_response.cancel( - "", - ) - - @parametrize - async def test_method_events(self, async_client: AsyncCasedev) -> None: - run_stream = await async_client.agent.v1.run.events( - id="id", - ) - await run_stream.response.aclose() - - @parametrize - async def test_method_events_with_all_params(self, async_client: AsyncCasedev) -> None: - run_stream = await async_client.agent.v1.run.events( - id="id", - last_event_id=0, - ) - await run_stream.response.aclose() - - @parametrize - async def test_raw_response_events(self, async_client: AsyncCasedev) -> None: - response = await async_client.agent.v1.run.with_raw_response.events( - id="id", - ) - - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - stream = await response.parse() - await stream.close() - - @parametrize - async def test_streaming_response_events(self, async_client: AsyncCasedev) -> None: - async with async_client.agent.v1.run.with_streaming_response.events( - id="id", - ) as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - stream = await response.parse() - await stream.close() - - assert cast(Any, response.is_closed) is True - - @parametrize - async def test_path_params_events(self, async_client: AsyncCasedev) -> None: - with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): - await async_client.agent.v1.run.with_raw_response.events( - id="", - ) - - @parametrize - async def test_method_exec(self, async_client: AsyncCasedev) -> None: - run = await async_client.agent.v1.run.exec( - "id", - ) - assert_matches_type(RunExecResponse, run, path=["response"]) - - @parametrize - async def test_raw_response_exec(self, async_client: AsyncCasedev) -> None: - response = await async_client.agent.v1.run.with_raw_response.exec( - "id", - ) - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - run = await response.parse() - assert_matches_type(RunExecResponse, run, path=["response"]) - - @parametrize - async def test_streaming_response_exec(self, async_client: AsyncCasedev) -> None: - async with async_client.agent.v1.run.with_streaming_response.exec( - "id", - ) as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - run = await response.parse() - assert_matches_type(RunExecResponse, run, path=["response"]) - - assert cast(Any, response.is_closed) is True - - @parametrize - async def test_path_params_exec(self, async_client: AsyncCasedev) -> None: - with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): - await async_client.agent.v1.run.with_raw_response.exec( - "", - ) - - @parametrize - async def test_method_get_details(self, async_client: AsyncCasedev) -> None: - run = await async_client.agent.v1.run.get_details( - "id", - ) - assert_matches_type(RunGetDetailsResponse, run, path=["response"]) - - @parametrize - async def test_raw_response_get_details(self, async_client: AsyncCasedev) -> None: - response = await async_client.agent.v1.run.with_raw_response.get_details( - "id", - ) - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - run = await response.parse() - assert_matches_type(RunGetDetailsResponse, run, path=["response"]) - - @parametrize - async def test_streaming_response_get_details(self, async_client: AsyncCasedev) -> None: - async with async_client.agent.v1.run.with_streaming_response.get_details( - "id", - ) as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - run = await response.parse() - assert_matches_type(RunGetDetailsResponse, run, path=["response"]) - - assert cast(Any, response.is_closed) is True - - @parametrize - async def test_path_params_get_details(self, async_client: AsyncCasedev) -> None: - with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): - await async_client.agent.v1.run.with_raw_response.get_details( - "", - ) - - @parametrize - async def test_method_get_status(self, async_client: AsyncCasedev) -> None: - run = await async_client.agent.v1.run.get_status( - "id", - ) - assert_matches_type(RunGetStatusResponse, run, path=["response"]) - - @parametrize - async def test_raw_response_get_status(self, async_client: AsyncCasedev) -> None: - response = await async_client.agent.v1.run.with_raw_response.get_status( - "id", - ) - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - run = await response.parse() - assert_matches_type(RunGetStatusResponse, run, path=["response"]) - - @parametrize - async def test_streaming_response_get_status(self, async_client: AsyncCasedev) -> None: - async with async_client.agent.v1.run.with_streaming_response.get_status( - "id", - ) as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - run = await response.parse() - assert_matches_type(RunGetStatusResponse, run, path=["response"]) - - assert cast(Any, response.is_closed) is True - - @parametrize - async def test_path_params_get_status(self, async_client: AsyncCasedev) -> None: - with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): - await async_client.agent.v1.run.with_raw_response.get_status( - "", - ) - - @parametrize - async def test_method_watch(self, async_client: AsyncCasedev) -> None: - run = await async_client.agent.v1.run.watch( - id="id", - callback_url="https://example.com", - ) - assert_matches_type(RunWatchResponse, run, path=["response"]) - - @parametrize - async def test_raw_response_watch(self, async_client: AsyncCasedev) -> None: - response = await async_client.agent.v1.run.with_raw_response.watch( - id="id", - callback_url="https://example.com", - ) - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - run = await response.parse() - assert_matches_type(RunWatchResponse, run, path=["response"]) - - @parametrize - async def test_streaming_response_watch(self, async_client: AsyncCasedev) -> None: - async with async_client.agent.v1.run.with_streaming_response.watch( - id="id", - callback_url="https://example.com", - ) as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - run = await response.parse() - assert_matches_type(RunWatchResponse, run, path=["response"]) - - assert cast(Any, response.is_closed) is True - - @parametrize - async def test_path_params_watch(self, async_client: AsyncCasedev) -> None: - with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): - await async_client.agent.v1.run.with_raw_response.watch( - id="", - callback_url="https://example.com", - ) diff --git a/tests/api_resources/agent/__init__.py b/tests/api_resources/connectors/__init__.py similarity index 100% rename from tests/api_resources/agent/__init__.py rename to tests/api_resources/connectors/__init__.py diff --git a/tests/api_resources/connectors/test_v1.py b/tests/api_resources/connectors/test_v1.py new file mode 100644 index 00000000..c74c3ae3 --- /dev/null +++ b/tests/api_resources/connectors/test_v1.py @@ -0,0 +1,282 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +import os +from typing import Any, cast + +import pytest + +from casedev import Casedev, AsyncCasedev +from tests.utils import assert_matches_type +from casedev.types.connectors import V1SyncLinkResponse, V1TransferResponse + +base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") + + +class TestV1: + parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"]) + + @parametrize + def test_method_sync_link(self, client: Casedev) -> None: + v1 = client.connectors.v1.sync_link( + connection_id="connection_id", + direction="import", + remote={"folder_id": "folder_id"}, + vault_id="vault_id", + ) + assert_matches_type(V1SyncLinkResponse, v1, path=["response"]) + + @parametrize + def test_method_sync_link_with_all_params(self, client: Casedev) -> None: + v1 = client.connectors.v1.sync_link( + connection_id="connection_id", + direction="import", + remote={ + "folder_id": "folder_id", + "container_id": "container_id", + "path": "path", + "site_id": "site_id", + }, + vault_id="vault_id", + matter_id="matter_id", + policy={ + "collisions": "version", + "deletes": "mirror", + "filters": { + "exclude_mime": ["string"], + "max_size_bytes": 0, + }, + }, + ) + assert_matches_type(V1SyncLinkResponse, v1, path=["response"]) + + @parametrize + def test_raw_response_sync_link(self, client: Casedev) -> None: + response = client.connectors.v1.with_raw_response.sync_link( + connection_id="connection_id", + direction="import", + remote={"folder_id": "folder_id"}, + vault_id="vault_id", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + v1 = response.parse() + assert_matches_type(V1SyncLinkResponse, v1, path=["response"]) + + @parametrize + def test_streaming_response_sync_link(self, client: Casedev) -> None: + with client.connectors.v1.with_streaming_response.sync_link( + connection_id="connection_id", + direction="import", + remote={"folder_id": "folder_id"}, + vault_id="vault_id", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + v1 = response.parse() + assert_matches_type(V1SyncLinkResponse, v1, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @parametrize + def test_method_transfer(self, client: Casedev) -> None: + v1 = client.connectors.v1.transfer( + connection_id="connection_id", + direction="import", + remote={"folder_id": "folder_id"}, + vault_id="vault_id", + ) + assert_matches_type(V1TransferResponse, v1, path=["response"]) + + @parametrize + def test_method_transfer_with_all_params(self, client: Casedev) -> None: + v1 = client.connectors.v1.transfer( + connection_id="connection_id", + direction="import", + remote={ + "folder_id": "folder_id", + "container_id": "container_id", + "path": "path", + "site_id": "site_id", + }, + vault_id="vault_id", + matter_id="matter_id", + policy={ + "collisions": "version", + "deletes": "mirror", + "filters": { + "exclude_mime": ["string"], + "max_size_bytes": 0, + }, + }, + run_mode="auto", + ) + assert_matches_type(V1TransferResponse, v1, path=["response"]) + + @parametrize + def test_raw_response_transfer(self, client: Casedev) -> None: + response = client.connectors.v1.with_raw_response.transfer( + connection_id="connection_id", + direction="import", + remote={"folder_id": "folder_id"}, + vault_id="vault_id", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + v1 = response.parse() + assert_matches_type(V1TransferResponse, v1, path=["response"]) + + @parametrize + def test_streaming_response_transfer(self, client: Casedev) -> None: + with client.connectors.v1.with_streaming_response.transfer( + connection_id="connection_id", + direction="import", + remote={"folder_id": "folder_id"}, + vault_id="vault_id", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + v1 = response.parse() + assert_matches_type(V1TransferResponse, v1, path=["response"]) + + assert cast(Any, response.is_closed) is True + + +class TestAsyncV1: + parametrize = pytest.mark.parametrize( + "async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"] + ) + + @parametrize + async def test_method_sync_link(self, async_client: AsyncCasedev) -> None: + v1 = await async_client.connectors.v1.sync_link( + connection_id="connection_id", + direction="import", + remote={"folder_id": "folder_id"}, + vault_id="vault_id", + ) + assert_matches_type(V1SyncLinkResponse, v1, path=["response"]) + + @parametrize + async def test_method_sync_link_with_all_params(self, async_client: AsyncCasedev) -> None: + v1 = await async_client.connectors.v1.sync_link( + connection_id="connection_id", + direction="import", + remote={ + "folder_id": "folder_id", + "container_id": "container_id", + "path": "path", + "site_id": "site_id", + }, + vault_id="vault_id", + matter_id="matter_id", + policy={ + "collisions": "version", + "deletes": "mirror", + "filters": { + "exclude_mime": ["string"], + "max_size_bytes": 0, + }, + }, + ) + assert_matches_type(V1SyncLinkResponse, v1, path=["response"]) + + @parametrize + async def test_raw_response_sync_link(self, async_client: AsyncCasedev) -> None: + response = await async_client.connectors.v1.with_raw_response.sync_link( + connection_id="connection_id", + direction="import", + remote={"folder_id": "folder_id"}, + vault_id="vault_id", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + v1 = await response.parse() + assert_matches_type(V1SyncLinkResponse, v1, path=["response"]) + + @parametrize + async def test_streaming_response_sync_link(self, async_client: AsyncCasedev) -> None: + async with async_client.connectors.v1.with_streaming_response.sync_link( + connection_id="connection_id", + direction="import", + remote={"folder_id": "folder_id"}, + vault_id="vault_id", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + v1 = await response.parse() + assert_matches_type(V1SyncLinkResponse, v1, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @parametrize + async def test_method_transfer(self, async_client: AsyncCasedev) -> None: + v1 = await async_client.connectors.v1.transfer( + connection_id="connection_id", + direction="import", + remote={"folder_id": "folder_id"}, + vault_id="vault_id", + ) + assert_matches_type(V1TransferResponse, v1, path=["response"]) + + @parametrize + async def test_method_transfer_with_all_params(self, async_client: AsyncCasedev) -> None: + v1 = await async_client.connectors.v1.transfer( + connection_id="connection_id", + direction="import", + remote={ + "folder_id": "folder_id", + "container_id": "container_id", + "path": "path", + "site_id": "site_id", + }, + vault_id="vault_id", + matter_id="matter_id", + policy={ + "collisions": "version", + "deletes": "mirror", + "filters": { + "exclude_mime": ["string"], + "max_size_bytes": 0, + }, + }, + run_mode="auto", + ) + assert_matches_type(V1TransferResponse, v1, path=["response"]) + + @parametrize + async def test_raw_response_transfer(self, async_client: AsyncCasedev) -> None: + response = await async_client.connectors.v1.with_raw_response.transfer( + connection_id="connection_id", + direction="import", + remote={"folder_id": "folder_id"}, + vault_id="vault_id", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + v1 = await response.parse() + assert_matches_type(V1TransferResponse, v1, path=["response"]) + + @parametrize + async def test_streaming_response_transfer(self, async_client: AsyncCasedev) -> None: + async with async_client.connectors.v1.with_streaming_response.transfer( + connection_id="connection_id", + direction="import", + remote={"folder_id": "folder_id"}, + vault_id="vault_id", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + v1 = await response.parse() + assert_matches_type(V1TransferResponse, v1, path=["response"]) + + assert cast(Any, response.is_closed) is True diff --git a/tests/api_resources/agent/v1/__init__.py b/tests/api_resources/connectors/v1/__init__.py similarity index 100% rename from tests/api_resources/agent/v1/__init__.py rename to tests/api_resources/connectors/v1/__init__.py diff --git a/tests/api_resources/database/__init__.py b/tests/api_resources/connectors/v1/installations/__init__.py similarity index 100% rename from tests/api_resources/database/__init__.py rename to tests/api_resources/connectors/v1/installations/__init__.py diff --git a/tests/api_resources/connectors/v1/installations/test_vaults.py b/tests/api_resources/connectors/v1/installations/test_vaults.py new file mode 100644 index 00000000..00855920 --- /dev/null +++ b/tests/api_resources/connectors/v1/installations/test_vaults.py @@ -0,0 +1,316 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +import os +from typing import Any, cast + +import pytest + +from casedev import Casedev, AsyncCasedev + +base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") + + +class TestVaults: + parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"]) + + @parametrize + def test_method_list(self, client: Casedev) -> None: + vault = client.connectors.v1.installations.vaults.list( + "id", + ) + assert vault is None + + @parametrize + def test_raw_response_list(self, client: Casedev) -> None: + response = client.connectors.v1.installations.vaults.with_raw_response.list( + "id", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + vault = response.parse() + assert vault is None + + @parametrize + def test_streaming_response_list(self, client: Casedev) -> None: + with client.connectors.v1.installations.vaults.with_streaming_response.list( + "id", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + vault = response.parse() + assert vault is None + + assert cast(Any, response.is_closed) is True + + @parametrize + def test_path_params_list(self, client: Casedev) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): + client.connectors.v1.installations.vaults.with_raw_response.list( + "", + ) + + @parametrize + def test_method_grant(self, client: Casedev) -> None: + vault = client.connectors.v1.installations.vaults.grant( + vault_id="vaultId", + id="id", + ) + assert vault is None + + @parametrize + def test_method_grant_with_all_params(self, client: Casedev) -> None: + vault = client.connectors.v1.installations.vaults.grant( + vault_id="vaultId", + id="id", + can_manage=True, + can_read=True, + can_write=True, + relationship="owned", + source="provisioning", + ) + assert vault is None + + @parametrize + def test_raw_response_grant(self, client: Casedev) -> None: + response = client.connectors.v1.installations.vaults.with_raw_response.grant( + vault_id="vaultId", + id="id", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + vault = response.parse() + assert vault is None + + @parametrize + def test_streaming_response_grant(self, client: Casedev) -> None: + with client.connectors.v1.installations.vaults.with_streaming_response.grant( + vault_id="vaultId", + id="id", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + vault = response.parse() + assert vault is None + + assert cast(Any, response.is_closed) is True + + @parametrize + def test_path_params_grant(self, client: Casedev) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): + client.connectors.v1.installations.vaults.with_raw_response.grant( + vault_id="vaultId", + id="", + ) + + with pytest.raises(ValueError, match=r"Expected a non-empty value for `vault_id` but received ''"): + client.connectors.v1.installations.vaults.with_raw_response.grant( + vault_id="", + id="id", + ) + + @parametrize + def test_method_revoke(self, client: Casedev) -> None: + vault = client.connectors.v1.installations.vaults.revoke( + vault_id="vaultId", + id="id", + ) + assert vault is None + + @parametrize + def test_raw_response_revoke(self, client: Casedev) -> None: + response = client.connectors.v1.installations.vaults.with_raw_response.revoke( + vault_id="vaultId", + id="id", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + vault = response.parse() + assert vault is None + + @parametrize + def test_streaming_response_revoke(self, client: Casedev) -> None: + with client.connectors.v1.installations.vaults.with_streaming_response.revoke( + vault_id="vaultId", + id="id", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + vault = response.parse() + assert vault is None + + assert cast(Any, response.is_closed) is True + + @parametrize + def test_path_params_revoke(self, client: Casedev) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): + client.connectors.v1.installations.vaults.with_raw_response.revoke( + vault_id="vaultId", + id="", + ) + + with pytest.raises(ValueError, match=r"Expected a non-empty value for `vault_id` but received ''"): + client.connectors.v1.installations.vaults.with_raw_response.revoke( + vault_id="", + id="id", + ) + + +class TestAsyncVaults: + parametrize = pytest.mark.parametrize( + "async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"] + ) + + @parametrize + async def test_method_list(self, async_client: AsyncCasedev) -> None: + vault = await async_client.connectors.v1.installations.vaults.list( + "id", + ) + assert vault is None + + @parametrize + async def test_raw_response_list(self, async_client: AsyncCasedev) -> None: + response = await async_client.connectors.v1.installations.vaults.with_raw_response.list( + "id", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + vault = await response.parse() + assert vault is None + + @parametrize + async def test_streaming_response_list(self, async_client: AsyncCasedev) -> None: + async with async_client.connectors.v1.installations.vaults.with_streaming_response.list( + "id", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + vault = await response.parse() + assert vault is None + + assert cast(Any, response.is_closed) is True + + @parametrize + async def test_path_params_list(self, async_client: AsyncCasedev) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): + await async_client.connectors.v1.installations.vaults.with_raw_response.list( + "", + ) + + @parametrize + async def test_method_grant(self, async_client: AsyncCasedev) -> None: + vault = await async_client.connectors.v1.installations.vaults.grant( + vault_id="vaultId", + id="id", + ) + assert vault is None + + @parametrize + async def test_method_grant_with_all_params(self, async_client: AsyncCasedev) -> None: + vault = await async_client.connectors.v1.installations.vaults.grant( + vault_id="vaultId", + id="id", + can_manage=True, + can_read=True, + can_write=True, + relationship="owned", + source="provisioning", + ) + assert vault is None + + @parametrize + async def test_raw_response_grant(self, async_client: AsyncCasedev) -> None: + response = await async_client.connectors.v1.installations.vaults.with_raw_response.grant( + vault_id="vaultId", + id="id", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + vault = await response.parse() + assert vault is None + + @parametrize + async def test_streaming_response_grant(self, async_client: AsyncCasedev) -> None: + async with async_client.connectors.v1.installations.vaults.with_streaming_response.grant( + vault_id="vaultId", + id="id", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + vault = await response.parse() + assert vault is None + + assert cast(Any, response.is_closed) is True + + @parametrize + async def test_path_params_grant(self, async_client: AsyncCasedev) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): + await async_client.connectors.v1.installations.vaults.with_raw_response.grant( + vault_id="vaultId", + id="", + ) + + with pytest.raises(ValueError, match=r"Expected a non-empty value for `vault_id` but received ''"): + await async_client.connectors.v1.installations.vaults.with_raw_response.grant( + vault_id="", + id="id", + ) + + @parametrize + async def test_method_revoke(self, async_client: AsyncCasedev) -> None: + vault = await async_client.connectors.v1.installations.vaults.revoke( + vault_id="vaultId", + id="id", + ) + assert vault is None + + @parametrize + async def test_raw_response_revoke(self, async_client: AsyncCasedev) -> None: + response = await async_client.connectors.v1.installations.vaults.with_raw_response.revoke( + vault_id="vaultId", + id="id", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + vault = await response.parse() + assert vault is None + + @parametrize + async def test_streaming_response_revoke(self, async_client: AsyncCasedev) -> None: + async with async_client.connectors.v1.installations.vaults.with_streaming_response.revoke( + vault_id="vaultId", + id="id", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + vault = await response.parse() + assert vault is None + + assert cast(Any, response.is_closed) is True + + @parametrize + async def test_path_params_revoke(self, async_client: AsyncCasedev) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): + await async_client.connectors.v1.installations.vaults.with_raw_response.revoke( + vault_id="vaultId", + id="", + ) + + with pytest.raises(ValueError, match=r"Expected a non-empty value for `vault_id` but received ''"): + await async_client.connectors.v1.installations.vaults.with_raw_response.revoke( + vault_id="", + id="id", + ) diff --git a/tests/api_resources/connectors/v1/test_connections.py b/tests/api_resources/connectors/v1/test_connections.py new file mode 100644 index 00000000..b434fc17 --- /dev/null +++ b/tests/api_resources/connectors/v1/test_connections.py @@ -0,0 +1,450 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +import os +from typing import Any, cast + +import pytest + +from casedev import Casedev, AsyncCasedev +from tests.utils import assert_matches_type +from casedev.types.connectors.v1 import ( + ConnectionListResponse, + ConnectionBrowseResponse, + ConnectionCreateResponse, +) + +base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") + + +class TestConnections: + parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"]) + + @parametrize + def test_method_create(self, client: Casedev) -> None: + connection = client.connectors.v1.connections.create( + provider="clio", + return_url="return_url", + ) + assert_matches_type(ConnectionCreateResponse, connection, path=["response"]) + + @parametrize + def test_method_create_with_all_params(self, client: Casedev) -> None: + connection = client.connectors.v1.connections.create( + provider="clio", + return_url="return_url", + scope_tier="clio.us", + ) + assert_matches_type(ConnectionCreateResponse, connection, path=["response"]) + + @parametrize + def test_raw_response_create(self, client: Casedev) -> None: + response = client.connectors.v1.connections.with_raw_response.create( + provider="clio", + return_url="return_url", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + connection = response.parse() + assert_matches_type(ConnectionCreateResponse, connection, path=["response"]) + + @parametrize + def test_streaming_response_create(self, client: Casedev) -> None: + with client.connectors.v1.connections.with_streaming_response.create( + provider="clio", + return_url="return_url", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + connection = response.parse() + assert_matches_type(ConnectionCreateResponse, connection, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @parametrize + def test_method_retrieve(self, client: Casedev) -> None: + connection = client.connectors.v1.connections.retrieve( + "id", + ) + assert connection is None + + @parametrize + def test_raw_response_retrieve(self, client: Casedev) -> None: + response = client.connectors.v1.connections.with_raw_response.retrieve( + "id", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + connection = response.parse() + assert connection is None + + @parametrize + def test_streaming_response_retrieve(self, client: Casedev) -> None: + with client.connectors.v1.connections.with_streaming_response.retrieve( + "id", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + connection = response.parse() + assert connection is None + + assert cast(Any, response.is_closed) is True + + @parametrize + def test_path_params_retrieve(self, client: Casedev) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): + client.connectors.v1.connections.with_raw_response.retrieve( + "", + ) + + @parametrize + def test_method_list(self, client: Casedev) -> None: + connection = client.connectors.v1.connections.list() + assert_matches_type(ConnectionListResponse, connection, path=["response"]) + + @parametrize + def test_method_list_with_all_params(self, client: Casedev) -> None: + connection = client.connectors.v1.connections.list( + provider="provider", + status="pending", + ) + assert_matches_type(ConnectionListResponse, connection, path=["response"]) + + @parametrize + def test_raw_response_list(self, client: Casedev) -> None: + response = client.connectors.v1.connections.with_raw_response.list() + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + connection = response.parse() + assert_matches_type(ConnectionListResponse, connection, path=["response"]) + + @parametrize + def test_streaming_response_list(self, client: Casedev) -> None: + with client.connectors.v1.connections.with_streaming_response.list() as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + connection = response.parse() + assert_matches_type(ConnectionListResponse, connection, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @parametrize + def test_method_delete(self, client: Casedev) -> None: + connection = client.connectors.v1.connections.delete( + id="id", + ) + assert connection is None + + @parametrize + def test_method_delete_with_all_params(self, client: Casedev) -> None: + connection = client.connectors.v1.connections.delete( + id="id", + purge=True, + ) + assert connection is None + + @parametrize + def test_raw_response_delete(self, client: Casedev) -> None: + response = client.connectors.v1.connections.with_raw_response.delete( + id="id", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + connection = response.parse() + assert connection is None + + @parametrize + def test_streaming_response_delete(self, client: Casedev) -> None: + with client.connectors.v1.connections.with_streaming_response.delete( + id="id", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + connection = response.parse() + assert connection is None + + assert cast(Any, response.is_closed) is True + + @parametrize + def test_path_params_delete(self, client: Casedev) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): + client.connectors.v1.connections.with_raw_response.delete( + id="", + ) + + @parametrize + def test_method_browse(self, client: Casedev) -> None: + connection = client.connectors.v1.connections.browse( + id="id", + ) + assert_matches_type(ConnectionBrowseResponse, connection, path=["response"]) + + @parametrize + def test_method_browse_with_all_params(self, client: Casedev) -> None: + connection = client.connectors.v1.connections.browse( + id="id", + container="container", + cursor="cursor", + page_size=1000, + parent="parent", + query="query", + site="site", + ) + assert_matches_type(ConnectionBrowseResponse, connection, path=["response"]) + + @parametrize + def test_raw_response_browse(self, client: Casedev) -> None: + response = client.connectors.v1.connections.with_raw_response.browse( + id="id", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + connection = response.parse() + assert_matches_type(ConnectionBrowseResponse, connection, path=["response"]) + + @parametrize + def test_streaming_response_browse(self, client: Casedev) -> None: + with client.connectors.v1.connections.with_streaming_response.browse( + id="id", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + connection = response.parse() + assert_matches_type(ConnectionBrowseResponse, connection, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @parametrize + def test_path_params_browse(self, client: Casedev) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): + client.connectors.v1.connections.with_raw_response.browse( + id="", + ) + + +class TestAsyncConnections: + parametrize = pytest.mark.parametrize( + "async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"] + ) + + @parametrize + async def test_method_create(self, async_client: AsyncCasedev) -> None: + connection = await async_client.connectors.v1.connections.create( + provider="clio", + return_url="return_url", + ) + assert_matches_type(ConnectionCreateResponse, connection, path=["response"]) + + @parametrize + async def test_method_create_with_all_params(self, async_client: AsyncCasedev) -> None: + connection = await async_client.connectors.v1.connections.create( + provider="clio", + return_url="return_url", + scope_tier="clio.us", + ) + assert_matches_type(ConnectionCreateResponse, connection, path=["response"]) + + @parametrize + async def test_raw_response_create(self, async_client: AsyncCasedev) -> None: + response = await async_client.connectors.v1.connections.with_raw_response.create( + provider="clio", + return_url="return_url", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + connection = await response.parse() + assert_matches_type(ConnectionCreateResponse, connection, path=["response"]) + + @parametrize + async def test_streaming_response_create(self, async_client: AsyncCasedev) -> None: + async with async_client.connectors.v1.connections.with_streaming_response.create( + provider="clio", + return_url="return_url", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + connection = await response.parse() + assert_matches_type(ConnectionCreateResponse, connection, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @parametrize + async def test_method_retrieve(self, async_client: AsyncCasedev) -> None: + connection = await async_client.connectors.v1.connections.retrieve( + "id", + ) + assert connection is None + + @parametrize + async def test_raw_response_retrieve(self, async_client: AsyncCasedev) -> None: + response = await async_client.connectors.v1.connections.with_raw_response.retrieve( + "id", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + connection = await response.parse() + assert connection is None + + @parametrize + async def test_streaming_response_retrieve(self, async_client: AsyncCasedev) -> None: + async with async_client.connectors.v1.connections.with_streaming_response.retrieve( + "id", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + connection = await response.parse() + assert connection is None + + assert cast(Any, response.is_closed) is True + + @parametrize + async def test_path_params_retrieve(self, async_client: AsyncCasedev) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): + await async_client.connectors.v1.connections.with_raw_response.retrieve( + "", + ) + + @parametrize + async def test_method_list(self, async_client: AsyncCasedev) -> None: + connection = await async_client.connectors.v1.connections.list() + assert_matches_type(ConnectionListResponse, connection, path=["response"]) + + @parametrize + async def test_method_list_with_all_params(self, async_client: AsyncCasedev) -> None: + connection = await async_client.connectors.v1.connections.list( + provider="provider", + status="pending", + ) + assert_matches_type(ConnectionListResponse, connection, path=["response"]) + + @parametrize + async def test_raw_response_list(self, async_client: AsyncCasedev) -> None: + response = await async_client.connectors.v1.connections.with_raw_response.list() + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + connection = await response.parse() + assert_matches_type(ConnectionListResponse, connection, path=["response"]) + + @parametrize + async def test_streaming_response_list(self, async_client: AsyncCasedev) -> None: + async with async_client.connectors.v1.connections.with_streaming_response.list() as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + connection = await response.parse() + assert_matches_type(ConnectionListResponse, connection, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @parametrize + async def test_method_delete(self, async_client: AsyncCasedev) -> None: + connection = await async_client.connectors.v1.connections.delete( + id="id", + ) + assert connection is None + + @parametrize + async def test_method_delete_with_all_params(self, async_client: AsyncCasedev) -> None: + connection = await async_client.connectors.v1.connections.delete( + id="id", + purge=True, + ) + assert connection is None + + @parametrize + async def test_raw_response_delete(self, async_client: AsyncCasedev) -> None: + response = await async_client.connectors.v1.connections.with_raw_response.delete( + id="id", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + connection = await response.parse() + assert connection is None + + @parametrize + async def test_streaming_response_delete(self, async_client: AsyncCasedev) -> None: + async with async_client.connectors.v1.connections.with_streaming_response.delete( + id="id", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + connection = await response.parse() + assert connection is None + + assert cast(Any, response.is_closed) is True + + @parametrize + async def test_path_params_delete(self, async_client: AsyncCasedev) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): + await async_client.connectors.v1.connections.with_raw_response.delete( + id="", + ) + + @parametrize + async def test_method_browse(self, async_client: AsyncCasedev) -> None: + connection = await async_client.connectors.v1.connections.browse( + id="id", + ) + assert_matches_type(ConnectionBrowseResponse, connection, path=["response"]) + + @parametrize + async def test_method_browse_with_all_params(self, async_client: AsyncCasedev) -> None: + connection = await async_client.connectors.v1.connections.browse( + id="id", + container="container", + cursor="cursor", + page_size=1000, + parent="parent", + query="query", + site="site", + ) + assert_matches_type(ConnectionBrowseResponse, connection, path=["response"]) + + @parametrize + async def test_raw_response_browse(self, async_client: AsyncCasedev) -> None: + response = await async_client.connectors.v1.connections.with_raw_response.browse( + id="id", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + connection = await response.parse() + assert_matches_type(ConnectionBrowseResponse, connection, path=["response"]) + + @parametrize + async def test_streaming_response_browse(self, async_client: AsyncCasedev) -> None: + async with async_client.connectors.v1.connections.with_streaming_response.browse( + id="id", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + connection = await response.parse() + assert_matches_type(ConnectionBrowseResponse, connection, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @parametrize + async def test_path_params_browse(self, async_client: AsyncCasedev) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): + await async_client.connectors.v1.connections.with_raw_response.browse( + id="", + ) diff --git a/tests/api_resources/connectors/v1/test_installations.py b/tests/api_resources/connectors/v1/test_installations.py new file mode 100644 index 00000000..b97b2a38 --- /dev/null +++ b/tests/api_resources/connectors/v1/test_installations.py @@ -0,0 +1,156 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +import os +from typing import Any, cast + +import pytest + +from casedev import Casedev, AsyncCasedev + +base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") + + +class TestInstallations: + parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"]) + + @parametrize + def test_method_list(self, client: Casedev) -> None: + installation = client.connectors.v1.installations.list() + assert installation is None + + @parametrize + def test_method_list_with_all_params(self, client: Casedev) -> None: + installation = client.connectors.v1.installations.list( + application="application", + external_tenant_id="external_tenant_id", + ) + assert installation is None + + @parametrize + def test_raw_response_list(self, client: Casedev) -> None: + response = client.connectors.v1.installations.with_raw_response.list() + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + installation = response.parse() + assert installation is None + + @parametrize + def test_streaming_response_list(self, client: Casedev) -> None: + with client.connectors.v1.installations.with_streaming_response.list() as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + installation = response.parse() + assert installation is None + + assert cast(Any, response.is_closed) is True + + @parametrize + def test_method_ensure(self, client: Casedev) -> None: + installation = client.connectors.v1.installations.ensure( + application="application", + external_tenant_id="external_tenant_id", + ) + assert installation is None + + @parametrize + def test_raw_response_ensure(self, client: Casedev) -> None: + response = client.connectors.v1.installations.with_raw_response.ensure( + application="application", + external_tenant_id="external_tenant_id", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + installation = response.parse() + assert installation is None + + @parametrize + def test_streaming_response_ensure(self, client: Casedev) -> None: + with client.connectors.v1.installations.with_streaming_response.ensure( + application="application", + external_tenant_id="external_tenant_id", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + installation = response.parse() + assert installation is None + + assert cast(Any, response.is_closed) is True + + +class TestAsyncInstallations: + parametrize = pytest.mark.parametrize( + "async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"] + ) + + @parametrize + async def test_method_list(self, async_client: AsyncCasedev) -> None: + installation = await async_client.connectors.v1.installations.list() + assert installation is None + + @parametrize + async def test_method_list_with_all_params(self, async_client: AsyncCasedev) -> None: + installation = await async_client.connectors.v1.installations.list( + application="application", + external_tenant_id="external_tenant_id", + ) + assert installation is None + + @parametrize + async def test_raw_response_list(self, async_client: AsyncCasedev) -> None: + response = await async_client.connectors.v1.installations.with_raw_response.list() + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + installation = await response.parse() + assert installation is None + + @parametrize + async def test_streaming_response_list(self, async_client: AsyncCasedev) -> None: + async with async_client.connectors.v1.installations.with_streaming_response.list() as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + installation = await response.parse() + assert installation is None + + assert cast(Any, response.is_closed) is True + + @parametrize + async def test_method_ensure(self, async_client: AsyncCasedev) -> None: + installation = await async_client.connectors.v1.installations.ensure( + application="application", + external_tenant_id="external_tenant_id", + ) + assert installation is None + + @parametrize + async def test_raw_response_ensure(self, async_client: AsyncCasedev) -> None: + response = await async_client.connectors.v1.installations.with_raw_response.ensure( + application="application", + external_tenant_id="external_tenant_id", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + installation = await response.parse() + assert installation is None + + @parametrize + async def test_streaming_response_ensure(self, async_client: AsyncCasedev) -> None: + async with async_client.connectors.v1.installations.with_streaming_response.ensure( + application="application", + external_tenant_id="external_tenant_id", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + installation = await response.parse() + assert installation is None + + assert cast(Any, response.is_closed) is True diff --git a/tests/api_resources/test_document_templates.py b/tests/api_resources/connectors/v1/test_links.py similarity index 50% rename from tests/api_resources/test_document_templates.py rename to tests/api_resources/connectors/v1/test_links.py index 2b839a26..dd16ceef 100644 --- a/tests/api_resources/test_document_templates.py +++ b/tests/api_resources/connectors/v1/test_links.py @@ -12,415 +12,443 @@ base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") -class TestDocumentTemplates: +class TestLinks: parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"]) - @parametrize - def test_method_create(self, client: Casedev) -> None: - document_template = client.document_templates.create() - assert document_template is None - - @parametrize - def test_raw_response_create(self, client: Casedev) -> None: - response = client.document_templates.with_raw_response.create() - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - document_template = response.parse() - assert document_template is None - - @parametrize - def test_streaming_response_create(self, client: Casedev) -> None: - with client.document_templates.with_streaming_response.create() as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - document_template = response.parse() - assert document_template is None - - assert cast(Any, response.is_closed) is True - @parametrize def test_method_retrieve(self, client: Casedev) -> None: - document_template = client.document_templates.retrieve( + link = client.connectors.v1.links.retrieve( "id", ) - assert document_template is None + assert link is None @parametrize def test_raw_response_retrieve(self, client: Casedev) -> None: - response = client.document_templates.with_raw_response.retrieve( + response = client.connectors.v1.links.with_raw_response.retrieve( "id", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" - document_template = response.parse() - assert document_template is None + link = response.parse() + assert link is None @parametrize def test_streaming_response_retrieve(self, client: Casedev) -> None: - with client.document_templates.with_streaming_response.retrieve( + with client.connectors.v1.links.with_streaming_response.retrieve( "id", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" - document_template = response.parse() - assert document_template is None + link = response.parse() + assert link is None assert cast(Any, response.is_closed) is True @parametrize def test_path_params_retrieve(self, client: Casedev) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): - client.document_templates.with_raw_response.retrieve( + client.connectors.v1.links.with_raw_response.retrieve( "", ) @parametrize def test_method_update(self, client: Casedev) -> None: - document_template = client.document_templates.update( - "id", + link = client.connectors.v1.links.update( + id="id", + ) + assert link is None + + @parametrize + def test_method_update_with_all_params(self, client: Casedev) -> None: + link = client.connectors.v1.links.update( + id="id", + mode="once", + policy={}, + state="paused", ) - assert document_template is None + assert link is None @parametrize def test_raw_response_update(self, client: Casedev) -> None: - response = client.document_templates.with_raw_response.update( - "id", + response = client.connectors.v1.links.with_raw_response.update( + id="id", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" - document_template = response.parse() - assert document_template is None + link = response.parse() + assert link is None @parametrize def test_streaming_response_update(self, client: Casedev) -> None: - with client.document_templates.with_streaming_response.update( - "id", + with client.connectors.v1.links.with_streaming_response.update( + id="id", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" - document_template = response.parse() - assert document_template is None + link = response.parse() + assert link is None assert cast(Any, response.is_closed) is True @parametrize def test_path_params_update(self, client: Casedev) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): - client.document_templates.with_raw_response.update( - "", + client.connectors.v1.links.with_raw_response.update( + id="", ) @parametrize def test_method_list(self, client: Casedev) -> None: - document_template = client.document_templates.list() - assert document_template is None + link = client.connectors.v1.links.list() + assert link is None + + @parametrize + def test_method_list_with_all_params(self, client: Casedev) -> None: + link = client.connectors.v1.links.list( + connection_id="connection_id", + direction="import", + mode="once", + pair_id="pair_id", + state="ready", + vault_id="vault_id", + ) + assert link is None @parametrize def test_raw_response_list(self, client: Casedev) -> None: - response = client.document_templates.with_raw_response.list() + response = client.connectors.v1.links.with_raw_response.list() assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" - document_template = response.parse() - assert document_template is None + link = response.parse() + assert link is None @parametrize def test_streaming_response_list(self, client: Casedev) -> None: - with client.document_templates.with_streaming_response.list() as response: + with client.connectors.v1.links.with_streaming_response.list() as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" - document_template = response.parse() - assert document_template is None + link = response.parse() + assert link is None assert cast(Any, response.is_closed) is True @parametrize def test_method_delete(self, client: Casedev) -> None: - document_template = client.document_templates.delete( - "id", + link = client.connectors.v1.links.delete( + id="id", ) - assert document_template is None + assert link is None + + @parametrize + def test_method_delete_with_all_params(self, client: Casedev) -> None: + link = client.connectors.v1.links.delete( + id="id", + vault_docs="keep", + ) + assert link is None @parametrize def test_raw_response_delete(self, client: Casedev) -> None: - response = client.document_templates.with_raw_response.delete( - "id", + response = client.connectors.v1.links.with_raw_response.delete( + id="id", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" - document_template = response.parse() - assert document_template is None + link = response.parse() + assert link is None @parametrize def test_streaming_response_delete(self, client: Casedev) -> None: - with client.document_templates.with_streaming_response.delete( - "id", + with client.connectors.v1.links.with_streaming_response.delete( + id="id", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" - document_template = response.parse() - assert document_template is None + link = response.parse() + assert link is None assert cast(Any, response.is_closed) is True @parametrize def test_path_params_delete(self, client: Casedev) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): - client.document_templates.with_raw_response.delete( - "", + client.connectors.v1.links.with_raw_response.delete( + id="", ) @parametrize - def test_method_confirm(self, client: Casedev) -> None: - document_template = client.document_templates.confirm( - "id", + def test_method_list_objects(self, client: Casedev) -> None: + link = client.connectors.v1.links.list_objects( + id="id", ) - assert document_template is None + assert link is None @parametrize - def test_raw_response_confirm(self, client: Casedev) -> None: - response = client.document_templates.with_raw_response.confirm( - "id", + def test_method_list_objects_with_all_params(self, client: Casedev) -> None: + link = client.connectors.v1.links.list_objects( + id="id", + cursor="cursor", + state="pending", + ) + assert link is None + + @parametrize + def test_raw_response_list_objects(self, client: Casedev) -> None: + response = client.connectors.v1.links.with_raw_response.list_objects( + id="id", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" - document_template = response.parse() - assert document_template is None + link = response.parse() + assert link is None @parametrize - def test_streaming_response_confirm(self, client: Casedev) -> None: - with client.document_templates.with_streaming_response.confirm( - "id", + def test_streaming_response_list_objects(self, client: Casedev) -> None: + with client.connectors.v1.links.with_streaming_response.list_objects( + id="id", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" - document_template = response.parse() - assert document_template is None + link = response.parse() + assert link is None assert cast(Any, response.is_closed) is True @parametrize - def test_path_params_confirm(self, client: Casedev) -> None: + def test_path_params_list_objects(self, client: Casedev) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): - client.document_templates.with_raw_response.confirm( - "", + client.connectors.v1.links.with_raw_response.list_objects( + id="", ) -class TestAsyncDocumentTemplates: +class TestAsyncLinks: parametrize = pytest.mark.parametrize( "async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"] ) - @parametrize - async def test_method_create(self, async_client: AsyncCasedev) -> None: - document_template = await async_client.document_templates.create() - assert document_template is None - - @parametrize - async def test_raw_response_create(self, async_client: AsyncCasedev) -> None: - response = await async_client.document_templates.with_raw_response.create() - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - document_template = await response.parse() - assert document_template is None - - @parametrize - async def test_streaming_response_create(self, async_client: AsyncCasedev) -> None: - async with async_client.document_templates.with_streaming_response.create() as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - document_template = await response.parse() - assert document_template is None - - assert cast(Any, response.is_closed) is True - @parametrize async def test_method_retrieve(self, async_client: AsyncCasedev) -> None: - document_template = await async_client.document_templates.retrieve( + link = await async_client.connectors.v1.links.retrieve( "id", ) - assert document_template is None + assert link is None @parametrize async def test_raw_response_retrieve(self, async_client: AsyncCasedev) -> None: - response = await async_client.document_templates.with_raw_response.retrieve( + response = await async_client.connectors.v1.links.with_raw_response.retrieve( "id", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" - document_template = await response.parse() - assert document_template is None + link = await response.parse() + assert link is None @parametrize async def test_streaming_response_retrieve(self, async_client: AsyncCasedev) -> None: - async with async_client.document_templates.with_streaming_response.retrieve( + async with async_client.connectors.v1.links.with_streaming_response.retrieve( "id", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" - document_template = await response.parse() - assert document_template is None + link = await response.parse() + assert link is None assert cast(Any, response.is_closed) is True @parametrize async def test_path_params_retrieve(self, async_client: AsyncCasedev) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): - await async_client.document_templates.with_raw_response.retrieve( + await async_client.connectors.v1.links.with_raw_response.retrieve( "", ) @parametrize async def test_method_update(self, async_client: AsyncCasedev) -> None: - document_template = await async_client.document_templates.update( - "id", + link = await async_client.connectors.v1.links.update( + id="id", + ) + assert link is None + + @parametrize + async def test_method_update_with_all_params(self, async_client: AsyncCasedev) -> None: + link = await async_client.connectors.v1.links.update( + id="id", + mode="once", + policy={}, + state="paused", ) - assert document_template is None + assert link is None @parametrize async def test_raw_response_update(self, async_client: AsyncCasedev) -> None: - response = await async_client.document_templates.with_raw_response.update( - "id", + response = await async_client.connectors.v1.links.with_raw_response.update( + id="id", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" - document_template = await response.parse() - assert document_template is None + link = await response.parse() + assert link is None @parametrize async def test_streaming_response_update(self, async_client: AsyncCasedev) -> None: - async with async_client.document_templates.with_streaming_response.update( - "id", + async with async_client.connectors.v1.links.with_streaming_response.update( + id="id", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" - document_template = await response.parse() - assert document_template is None + link = await response.parse() + assert link is None assert cast(Any, response.is_closed) is True @parametrize async def test_path_params_update(self, async_client: AsyncCasedev) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): - await async_client.document_templates.with_raw_response.update( - "", + await async_client.connectors.v1.links.with_raw_response.update( + id="", ) @parametrize async def test_method_list(self, async_client: AsyncCasedev) -> None: - document_template = await async_client.document_templates.list() - assert document_template is None + link = await async_client.connectors.v1.links.list() + assert link is None + + @parametrize + async def test_method_list_with_all_params(self, async_client: AsyncCasedev) -> None: + link = await async_client.connectors.v1.links.list( + connection_id="connection_id", + direction="import", + mode="once", + pair_id="pair_id", + state="ready", + vault_id="vault_id", + ) + assert link is None @parametrize async def test_raw_response_list(self, async_client: AsyncCasedev) -> None: - response = await async_client.document_templates.with_raw_response.list() + response = await async_client.connectors.v1.links.with_raw_response.list() assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" - document_template = await response.parse() - assert document_template is None + link = await response.parse() + assert link is None @parametrize async def test_streaming_response_list(self, async_client: AsyncCasedev) -> None: - async with async_client.document_templates.with_streaming_response.list() as response: + async with async_client.connectors.v1.links.with_streaming_response.list() as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" - document_template = await response.parse() - assert document_template is None + link = await response.parse() + assert link is None assert cast(Any, response.is_closed) is True @parametrize async def test_method_delete(self, async_client: AsyncCasedev) -> None: - document_template = await async_client.document_templates.delete( - "id", + link = await async_client.connectors.v1.links.delete( + id="id", ) - assert document_template is None + assert link is None + + @parametrize + async def test_method_delete_with_all_params(self, async_client: AsyncCasedev) -> None: + link = await async_client.connectors.v1.links.delete( + id="id", + vault_docs="keep", + ) + assert link is None @parametrize async def test_raw_response_delete(self, async_client: AsyncCasedev) -> None: - response = await async_client.document_templates.with_raw_response.delete( - "id", + response = await async_client.connectors.v1.links.with_raw_response.delete( + id="id", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" - document_template = await response.parse() - assert document_template is None + link = await response.parse() + assert link is None @parametrize async def test_streaming_response_delete(self, async_client: AsyncCasedev) -> None: - async with async_client.document_templates.with_streaming_response.delete( - "id", + async with async_client.connectors.v1.links.with_streaming_response.delete( + id="id", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" - document_template = await response.parse() - assert document_template is None + link = await response.parse() + assert link is None assert cast(Any, response.is_closed) is True @parametrize async def test_path_params_delete(self, async_client: AsyncCasedev) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): - await async_client.document_templates.with_raw_response.delete( - "", + await async_client.connectors.v1.links.with_raw_response.delete( + id="", ) @parametrize - async def test_method_confirm(self, async_client: AsyncCasedev) -> None: - document_template = await async_client.document_templates.confirm( - "id", + async def test_method_list_objects(self, async_client: AsyncCasedev) -> None: + link = await async_client.connectors.v1.links.list_objects( + id="id", ) - assert document_template is None + assert link is None @parametrize - async def test_raw_response_confirm(self, async_client: AsyncCasedev) -> None: - response = await async_client.document_templates.with_raw_response.confirm( - "id", + async def test_method_list_objects_with_all_params(self, async_client: AsyncCasedev) -> None: + link = await async_client.connectors.v1.links.list_objects( + id="id", + cursor="cursor", + state="pending", + ) + assert link is None + + @parametrize + async def test_raw_response_list_objects(self, async_client: AsyncCasedev) -> None: + response = await async_client.connectors.v1.links.with_raw_response.list_objects( + id="id", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" - document_template = await response.parse() - assert document_template is None + link = await response.parse() + assert link is None @parametrize - async def test_streaming_response_confirm(self, async_client: AsyncCasedev) -> None: - async with async_client.document_templates.with_streaming_response.confirm( - "id", + async def test_streaming_response_list_objects(self, async_client: AsyncCasedev) -> None: + async with async_client.connectors.v1.links.with_streaming_response.list_objects( + id="id", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" - document_template = await response.parse() - assert document_template is None + link = await response.parse() + assert link is None assert cast(Any, response.is_closed) is True @parametrize - async def test_path_params_confirm(self, async_client: AsyncCasedev) -> None: + async def test_path_params_list_objects(self, async_client: AsyncCasedev) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): - await async_client.document_templates.with_raw_response.confirm( - "", + await async_client.connectors.v1.links.with_raw_response.list_objects( + id="", ) diff --git a/tests/api_resources/database/test_v1.py b/tests/api_resources/database/test_v1.py deleted file mode 100644 index 61b93aac..00000000 --- a/tests/api_resources/database/test_v1.py +++ /dev/null @@ -1,74 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from __future__ import annotations - -import os -from typing import Any, cast - -import pytest - -from casedev import Casedev, AsyncCasedev -from tests.utils import assert_matches_type -from casedev.types.database import V1GetUsageResponse - -base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") - - -class TestV1: - parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"]) - - @parametrize - def test_method_get_usage(self, client: Casedev) -> None: - v1 = client.database.v1.get_usage() - assert_matches_type(V1GetUsageResponse, v1, path=["response"]) - - @parametrize - def test_raw_response_get_usage(self, client: Casedev) -> None: - response = client.database.v1.with_raw_response.get_usage() - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - v1 = response.parse() - assert_matches_type(V1GetUsageResponse, v1, path=["response"]) - - @parametrize - def test_streaming_response_get_usage(self, client: Casedev) -> None: - with client.database.v1.with_streaming_response.get_usage() as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - v1 = response.parse() - assert_matches_type(V1GetUsageResponse, v1, path=["response"]) - - assert cast(Any, response.is_closed) is True - - -class TestAsyncV1: - parametrize = pytest.mark.parametrize( - "async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"] - ) - - @parametrize - async def test_method_get_usage(self, async_client: AsyncCasedev) -> None: - v1 = await async_client.database.v1.get_usage() - assert_matches_type(V1GetUsageResponse, v1, path=["response"]) - - @parametrize - async def test_raw_response_get_usage(self, async_client: AsyncCasedev) -> None: - response = await async_client.database.v1.with_raw_response.get_usage() - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - v1 = await response.parse() - assert_matches_type(V1GetUsageResponse, v1, path=["response"]) - - @parametrize - async def test_streaming_response_get_usage(self, async_client: AsyncCasedev) -> None: - async with async_client.database.v1.with_streaming_response.get_usage() as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - v1 = await response.parse() - assert_matches_type(V1GetUsageResponse, v1, path=["response"]) - - assert cast(Any, response.is_closed) is True diff --git a/tests/api_resources/database/v1/__init__.py b/tests/api_resources/database/v1/__init__.py deleted file mode 100644 index fd8019a9..00000000 --- a/tests/api_resources/database/v1/__init__.py +++ /dev/null @@ -1 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. diff --git a/tests/api_resources/database/v1/test_projects.py b/tests/api_resources/database/v1/test_projects.py deleted file mode 100644 index 8a1d0ffe..00000000 --- a/tests/api_resources/database/v1/test_projects.py +++ /dev/null @@ -1,586 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from __future__ import annotations - -import os -from typing import Any, cast - -import pytest - -from casedev import Casedev, AsyncCasedev -from tests.utils import assert_matches_type -from casedev.types.database.v1 import ( - ProjectListResponse, - ProjectCreateResponse, - ProjectDeleteResponse, - ProjectRetrieveResponse, - ProjectCreateBranchResponse, - ProjectListBranchesResponse, - ProjectGetConnectionResponse, -) - -base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") - - -class TestProjects: - parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"]) - - @parametrize - def test_method_create(self, client: Casedev) -> None: - project = client.database.v1.projects.create( - name="litigation-docs-db", - ) - assert_matches_type(ProjectCreateResponse, project, path=["response"]) - - @parametrize - def test_method_create_with_all_params(self, client: Casedev) -> None: - project = client.database.v1.projects.create( - name="litigation-docs-db", - description="Production database for litigation document management", - region="aws-us-east-1", - ) - assert_matches_type(ProjectCreateResponse, project, path=["response"]) - - @parametrize - def test_raw_response_create(self, client: Casedev) -> None: - response = client.database.v1.projects.with_raw_response.create( - name="litigation-docs-db", - ) - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - project = response.parse() - assert_matches_type(ProjectCreateResponse, project, path=["response"]) - - @parametrize - def test_streaming_response_create(self, client: Casedev) -> None: - with client.database.v1.projects.with_streaming_response.create( - name="litigation-docs-db", - ) as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - project = response.parse() - assert_matches_type(ProjectCreateResponse, project, path=["response"]) - - assert cast(Any, response.is_closed) is True - - @parametrize - def test_method_retrieve(self, client: Casedev) -> None: - project = client.database.v1.projects.retrieve( - "id", - ) - assert_matches_type(ProjectRetrieveResponse, project, path=["response"]) - - @parametrize - def test_raw_response_retrieve(self, client: Casedev) -> None: - response = client.database.v1.projects.with_raw_response.retrieve( - "id", - ) - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - project = response.parse() - assert_matches_type(ProjectRetrieveResponse, project, path=["response"]) - - @parametrize - def test_streaming_response_retrieve(self, client: Casedev) -> None: - with client.database.v1.projects.with_streaming_response.retrieve( - "id", - ) as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - project = response.parse() - assert_matches_type(ProjectRetrieveResponse, project, path=["response"]) - - assert cast(Any, response.is_closed) is True - - @parametrize - def test_path_params_retrieve(self, client: Casedev) -> None: - with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): - client.database.v1.projects.with_raw_response.retrieve( - "", - ) - - @parametrize - def test_method_list(self, client: Casedev) -> None: - project = client.database.v1.projects.list() - assert_matches_type(ProjectListResponse, project, path=["response"]) - - @parametrize - def test_raw_response_list(self, client: Casedev) -> None: - response = client.database.v1.projects.with_raw_response.list() - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - project = response.parse() - assert_matches_type(ProjectListResponse, project, path=["response"]) - - @parametrize - def test_streaming_response_list(self, client: Casedev) -> None: - with client.database.v1.projects.with_streaming_response.list() as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - project = response.parse() - assert_matches_type(ProjectListResponse, project, path=["response"]) - - assert cast(Any, response.is_closed) is True - - @parametrize - def test_method_delete(self, client: Casedev) -> None: - project = client.database.v1.projects.delete( - "id", - ) - assert_matches_type(ProjectDeleteResponse, project, path=["response"]) - - @parametrize - def test_raw_response_delete(self, client: Casedev) -> None: - response = client.database.v1.projects.with_raw_response.delete( - "id", - ) - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - project = response.parse() - assert_matches_type(ProjectDeleteResponse, project, path=["response"]) - - @parametrize - def test_streaming_response_delete(self, client: Casedev) -> None: - with client.database.v1.projects.with_streaming_response.delete( - "id", - ) as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - project = response.parse() - assert_matches_type(ProjectDeleteResponse, project, path=["response"]) - - assert cast(Any, response.is_closed) is True - - @parametrize - def test_path_params_delete(self, client: Casedev) -> None: - with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): - client.database.v1.projects.with_raw_response.delete( - "", - ) - - @parametrize - def test_method_create_branch(self, client: Casedev) -> None: - project = client.database.v1.projects.create_branch( - id="id", - name="staging", - ) - assert_matches_type(ProjectCreateBranchResponse, project, path=["response"]) - - @parametrize - def test_method_create_branch_with_all_params(self, client: Casedev) -> None: - project = client.database.v1.projects.create_branch( - id="id", - name="staging", - parent_branch_id="branch_main_123", - ) - assert_matches_type(ProjectCreateBranchResponse, project, path=["response"]) - - @parametrize - def test_raw_response_create_branch(self, client: Casedev) -> None: - response = client.database.v1.projects.with_raw_response.create_branch( - id="id", - name="staging", - ) - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - project = response.parse() - assert_matches_type(ProjectCreateBranchResponse, project, path=["response"]) - - @parametrize - def test_streaming_response_create_branch(self, client: Casedev) -> None: - with client.database.v1.projects.with_streaming_response.create_branch( - id="id", - name="staging", - ) as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - project = response.parse() - assert_matches_type(ProjectCreateBranchResponse, project, path=["response"]) - - assert cast(Any, response.is_closed) is True - - @parametrize - def test_path_params_create_branch(self, client: Casedev) -> None: - with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): - client.database.v1.projects.with_raw_response.create_branch( - id="", - name="staging", - ) - - @parametrize - def test_method_get_connection(self, client: Casedev) -> None: - project = client.database.v1.projects.get_connection( - id="id", - ) - assert_matches_type(ProjectGetConnectionResponse, project, path=["response"]) - - @parametrize - def test_method_get_connection_with_all_params(self, client: Casedev) -> None: - project = client.database.v1.projects.get_connection( - id="id", - branch="branch", - pooled=True, - ) - assert_matches_type(ProjectGetConnectionResponse, project, path=["response"]) - - @parametrize - def test_raw_response_get_connection(self, client: Casedev) -> None: - response = client.database.v1.projects.with_raw_response.get_connection( - id="id", - ) - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - project = response.parse() - assert_matches_type(ProjectGetConnectionResponse, project, path=["response"]) - - @parametrize - def test_streaming_response_get_connection(self, client: Casedev) -> None: - with client.database.v1.projects.with_streaming_response.get_connection( - id="id", - ) as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - project = response.parse() - assert_matches_type(ProjectGetConnectionResponse, project, path=["response"]) - - assert cast(Any, response.is_closed) is True - - @parametrize - def test_path_params_get_connection(self, client: Casedev) -> None: - with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): - client.database.v1.projects.with_raw_response.get_connection( - id="", - ) - - @parametrize - def test_method_list_branches(self, client: Casedev) -> None: - project = client.database.v1.projects.list_branches( - "id", - ) - assert_matches_type(ProjectListBranchesResponse, project, path=["response"]) - - @parametrize - def test_raw_response_list_branches(self, client: Casedev) -> None: - response = client.database.v1.projects.with_raw_response.list_branches( - "id", - ) - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - project = response.parse() - assert_matches_type(ProjectListBranchesResponse, project, path=["response"]) - - @parametrize - def test_streaming_response_list_branches(self, client: Casedev) -> None: - with client.database.v1.projects.with_streaming_response.list_branches( - "id", - ) as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - project = response.parse() - assert_matches_type(ProjectListBranchesResponse, project, path=["response"]) - - assert cast(Any, response.is_closed) is True - - @parametrize - def test_path_params_list_branches(self, client: Casedev) -> None: - with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): - client.database.v1.projects.with_raw_response.list_branches( - "", - ) - - -class TestAsyncProjects: - parametrize = pytest.mark.parametrize( - "async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"] - ) - - @parametrize - async def test_method_create(self, async_client: AsyncCasedev) -> None: - project = await async_client.database.v1.projects.create( - name="litigation-docs-db", - ) - assert_matches_type(ProjectCreateResponse, project, path=["response"]) - - @parametrize - async def test_method_create_with_all_params(self, async_client: AsyncCasedev) -> None: - project = await async_client.database.v1.projects.create( - name="litigation-docs-db", - description="Production database for litigation document management", - region="aws-us-east-1", - ) - assert_matches_type(ProjectCreateResponse, project, path=["response"]) - - @parametrize - async def test_raw_response_create(self, async_client: AsyncCasedev) -> None: - response = await async_client.database.v1.projects.with_raw_response.create( - name="litigation-docs-db", - ) - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - project = await response.parse() - assert_matches_type(ProjectCreateResponse, project, path=["response"]) - - @parametrize - async def test_streaming_response_create(self, async_client: AsyncCasedev) -> None: - async with async_client.database.v1.projects.with_streaming_response.create( - name="litigation-docs-db", - ) as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - project = await response.parse() - assert_matches_type(ProjectCreateResponse, project, path=["response"]) - - assert cast(Any, response.is_closed) is True - - @parametrize - async def test_method_retrieve(self, async_client: AsyncCasedev) -> None: - project = await async_client.database.v1.projects.retrieve( - "id", - ) - assert_matches_type(ProjectRetrieveResponse, project, path=["response"]) - - @parametrize - async def test_raw_response_retrieve(self, async_client: AsyncCasedev) -> None: - response = await async_client.database.v1.projects.with_raw_response.retrieve( - "id", - ) - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - project = await response.parse() - assert_matches_type(ProjectRetrieveResponse, project, path=["response"]) - - @parametrize - async def test_streaming_response_retrieve(self, async_client: AsyncCasedev) -> None: - async with async_client.database.v1.projects.with_streaming_response.retrieve( - "id", - ) as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - project = await response.parse() - assert_matches_type(ProjectRetrieveResponse, project, path=["response"]) - - assert cast(Any, response.is_closed) is True - - @parametrize - async def test_path_params_retrieve(self, async_client: AsyncCasedev) -> None: - with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): - await async_client.database.v1.projects.with_raw_response.retrieve( - "", - ) - - @parametrize - async def test_method_list(self, async_client: AsyncCasedev) -> None: - project = await async_client.database.v1.projects.list() - assert_matches_type(ProjectListResponse, project, path=["response"]) - - @parametrize - async def test_raw_response_list(self, async_client: AsyncCasedev) -> None: - response = await async_client.database.v1.projects.with_raw_response.list() - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - project = await response.parse() - assert_matches_type(ProjectListResponse, project, path=["response"]) - - @parametrize - async def test_streaming_response_list(self, async_client: AsyncCasedev) -> None: - async with async_client.database.v1.projects.with_streaming_response.list() as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - project = await response.parse() - assert_matches_type(ProjectListResponse, project, path=["response"]) - - assert cast(Any, response.is_closed) is True - - @parametrize - async def test_method_delete(self, async_client: AsyncCasedev) -> None: - project = await async_client.database.v1.projects.delete( - "id", - ) - assert_matches_type(ProjectDeleteResponse, project, path=["response"]) - - @parametrize - async def test_raw_response_delete(self, async_client: AsyncCasedev) -> None: - response = await async_client.database.v1.projects.with_raw_response.delete( - "id", - ) - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - project = await response.parse() - assert_matches_type(ProjectDeleteResponse, project, path=["response"]) - - @parametrize - async def test_streaming_response_delete(self, async_client: AsyncCasedev) -> None: - async with async_client.database.v1.projects.with_streaming_response.delete( - "id", - ) as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - project = await response.parse() - assert_matches_type(ProjectDeleteResponse, project, path=["response"]) - - assert cast(Any, response.is_closed) is True - - @parametrize - async def test_path_params_delete(self, async_client: AsyncCasedev) -> None: - with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): - await async_client.database.v1.projects.with_raw_response.delete( - "", - ) - - @parametrize - async def test_method_create_branch(self, async_client: AsyncCasedev) -> None: - project = await async_client.database.v1.projects.create_branch( - id="id", - name="staging", - ) - assert_matches_type(ProjectCreateBranchResponse, project, path=["response"]) - - @parametrize - async def test_method_create_branch_with_all_params(self, async_client: AsyncCasedev) -> None: - project = await async_client.database.v1.projects.create_branch( - id="id", - name="staging", - parent_branch_id="branch_main_123", - ) - assert_matches_type(ProjectCreateBranchResponse, project, path=["response"]) - - @parametrize - async def test_raw_response_create_branch(self, async_client: AsyncCasedev) -> None: - response = await async_client.database.v1.projects.with_raw_response.create_branch( - id="id", - name="staging", - ) - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - project = await response.parse() - assert_matches_type(ProjectCreateBranchResponse, project, path=["response"]) - - @parametrize - async def test_streaming_response_create_branch(self, async_client: AsyncCasedev) -> None: - async with async_client.database.v1.projects.with_streaming_response.create_branch( - id="id", - name="staging", - ) as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - project = await response.parse() - assert_matches_type(ProjectCreateBranchResponse, project, path=["response"]) - - assert cast(Any, response.is_closed) is True - - @parametrize - async def test_path_params_create_branch(self, async_client: AsyncCasedev) -> None: - with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): - await async_client.database.v1.projects.with_raw_response.create_branch( - id="", - name="staging", - ) - - @parametrize - async def test_method_get_connection(self, async_client: AsyncCasedev) -> None: - project = await async_client.database.v1.projects.get_connection( - id="id", - ) - assert_matches_type(ProjectGetConnectionResponse, project, path=["response"]) - - @parametrize - async def test_method_get_connection_with_all_params(self, async_client: AsyncCasedev) -> None: - project = await async_client.database.v1.projects.get_connection( - id="id", - branch="branch", - pooled=True, - ) - assert_matches_type(ProjectGetConnectionResponse, project, path=["response"]) - - @parametrize - async def test_raw_response_get_connection(self, async_client: AsyncCasedev) -> None: - response = await async_client.database.v1.projects.with_raw_response.get_connection( - id="id", - ) - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - project = await response.parse() - assert_matches_type(ProjectGetConnectionResponse, project, path=["response"]) - - @parametrize - async def test_streaming_response_get_connection(self, async_client: AsyncCasedev) -> None: - async with async_client.database.v1.projects.with_streaming_response.get_connection( - id="id", - ) as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - project = await response.parse() - assert_matches_type(ProjectGetConnectionResponse, project, path=["response"]) - - assert cast(Any, response.is_closed) is True - - @parametrize - async def test_path_params_get_connection(self, async_client: AsyncCasedev) -> None: - with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): - await async_client.database.v1.projects.with_raw_response.get_connection( - id="", - ) - - @parametrize - async def test_method_list_branches(self, async_client: AsyncCasedev) -> None: - project = await async_client.database.v1.projects.list_branches( - "id", - ) - assert_matches_type(ProjectListBranchesResponse, project, path=["response"]) - - @parametrize - async def test_raw_response_list_branches(self, async_client: AsyncCasedev) -> None: - response = await async_client.database.v1.projects.with_raw_response.list_branches( - "id", - ) - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - project = await response.parse() - assert_matches_type(ProjectListBranchesResponse, project, path=["response"]) - - @parametrize - async def test_streaming_response_list_branches(self, async_client: AsyncCasedev) -> None: - async with async_client.database.v1.projects.with_streaming_response.list_branches( - "id", - ) as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - project = await response.parse() - assert_matches_type(ProjectListBranchesResponse, project, path=["response"]) - - assert cast(Any, response.is_closed) is True - - @parametrize - async def test_path_params_list_branches(self, async_client: AsyncCasedev) -> None: - with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): - await async_client.database.v1.projects.with_raw_response.list_branches( - "", - ) diff --git a/tests/api_resources/document_templates/__init__.py b/tests/api_resources/document_templates/__init__.py deleted file mode 100644 index fd8019a9..00000000 --- a/tests/api_resources/document_templates/__init__.py +++ /dev/null @@ -1 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. diff --git a/tests/api_resources/document_templates/test_from_vault_object.py b/tests/api_resources/document_templates/test_from_vault_object.py deleted file mode 100644 index 39a95ca2..00000000 --- a/tests/api_resources/document_templates/test_from_vault_object.py +++ /dev/null @@ -1,72 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from __future__ import annotations - -import os -from typing import Any, cast - -import pytest - -from casedev import Casedev, AsyncCasedev - -base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") - - -class TestFromVaultObject: - parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"]) - - @parametrize - def test_method_create(self, client: Casedev) -> None: - from_vault_object = client.document_templates.from_vault_object.create() - assert from_vault_object is None - - @parametrize - def test_raw_response_create(self, client: Casedev) -> None: - response = client.document_templates.from_vault_object.with_raw_response.create() - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - from_vault_object = response.parse() - assert from_vault_object is None - - @parametrize - def test_streaming_response_create(self, client: Casedev) -> None: - with client.document_templates.from_vault_object.with_streaming_response.create() as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - from_vault_object = response.parse() - assert from_vault_object is None - - assert cast(Any, response.is_closed) is True - - -class TestAsyncFromVaultObject: - parametrize = pytest.mark.parametrize( - "async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"] - ) - - @parametrize - async def test_method_create(self, async_client: AsyncCasedev) -> None: - from_vault_object = await async_client.document_templates.from_vault_object.create() - assert from_vault_object is None - - @parametrize - async def test_raw_response_create(self, async_client: AsyncCasedev) -> None: - response = await async_client.document_templates.from_vault_object.with_raw_response.create() - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - from_vault_object = await response.parse() - assert from_vault_object is None - - @parametrize - async def test_streaming_response_create(self, async_client: AsyncCasedev) -> None: - async with async_client.document_templates.from_vault_object.with_streaming_response.create() as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - from_vault_object = await response.parse() - assert from_vault_object is None - - assert cast(Any, response.is_closed) is True diff --git a/tests/api_resources/format/__init__.py b/tests/api_resources/format/__init__.py deleted file mode 100644 index fd8019a9..00000000 --- a/tests/api_resources/format/__init__.py +++ /dev/null @@ -1 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. diff --git a/tests/api_resources/format/test_v1.py b/tests/api_resources/format/test_v1.py deleted file mode 100644 index 67a1690a..00000000 --- a/tests/api_resources/format/test_v1.py +++ /dev/null @@ -1,170 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from __future__ import annotations - -import os -from typing import Any, cast - -import httpx -import pytest -from respx import MockRouter - -from casedev import Casedev, AsyncCasedev -from casedev._response import ( - BinaryAPIResponse, - AsyncBinaryAPIResponse, - StreamedBinaryAPIResponse, - AsyncStreamedBinaryAPIResponse, -) - -base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") - - -class TestV1: - parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"]) - - @parametrize - @pytest.mark.respx(base_url=base_url) - def test_method_create_document(self, client: Casedev, respx_mock: MockRouter) -> None: - respx_mock.post("/format/v1/document").mock(return_value=httpx.Response(200, json={"foo": "bar"})) - v1 = client.format.v1.create_document( - content="content", - output_format="pdf", - ) - assert v1.is_closed - assert v1.json() == {"foo": "bar"} - assert cast(Any, v1.is_closed) is True - assert isinstance(v1, BinaryAPIResponse) - - @parametrize - @pytest.mark.respx(base_url=base_url) - def test_method_create_document_with_all_params(self, client: Casedev, respx_mock: MockRouter) -> None: - respx_mock.post("/format/v1/document").mock(return_value=httpx.Response(200, json={"foo": "bar"})) - v1 = client.format.v1.create_document( - content="content", - output_format="pdf", - input_format="md", - options={ - "components": [ - { - "content": "content", - "styles": {}, - "template_id": "templateId", - "variables": {}, - } - ] - }, - ) - assert v1.is_closed - assert v1.json() == {"foo": "bar"} - assert cast(Any, v1.is_closed) is True - assert isinstance(v1, BinaryAPIResponse) - - @parametrize - @pytest.mark.respx(base_url=base_url) - def test_raw_response_create_document(self, client: Casedev, respx_mock: MockRouter) -> None: - respx_mock.post("/format/v1/document").mock(return_value=httpx.Response(200, json={"foo": "bar"})) - - v1 = client.format.v1.with_raw_response.create_document( - content="content", - output_format="pdf", - ) - - assert v1.is_closed is True - assert v1.http_request.headers.get("X-Stainless-Lang") == "python" - assert v1.json() == {"foo": "bar"} - assert isinstance(v1, BinaryAPIResponse) - - @parametrize - @pytest.mark.respx(base_url=base_url) - def test_streaming_response_create_document(self, client: Casedev, respx_mock: MockRouter) -> None: - respx_mock.post("/format/v1/document").mock(return_value=httpx.Response(200, json={"foo": "bar"})) - with client.format.v1.with_streaming_response.create_document( - content="content", - output_format="pdf", - ) as v1: - assert not v1.is_closed - assert v1.http_request.headers.get("X-Stainless-Lang") == "python" - - assert v1.json() == {"foo": "bar"} - assert cast(Any, v1.is_closed) is True - assert isinstance(v1, StreamedBinaryAPIResponse) - - assert cast(Any, v1.is_closed) is True - - -class TestAsyncV1: - parametrize = pytest.mark.parametrize( - "async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"] - ) - - @parametrize - @pytest.mark.respx(base_url=base_url) - async def test_method_create_document(self, async_client: AsyncCasedev, respx_mock: MockRouter) -> None: - respx_mock.post("/format/v1/document").mock(return_value=httpx.Response(200, json={"foo": "bar"})) - v1 = await async_client.format.v1.create_document( - content="content", - output_format="pdf", - ) - assert v1.is_closed - assert await v1.json() == {"foo": "bar"} - assert cast(Any, v1.is_closed) is True - assert isinstance(v1, AsyncBinaryAPIResponse) - - @parametrize - @pytest.mark.respx(base_url=base_url) - async def test_method_create_document_with_all_params( - self, async_client: AsyncCasedev, respx_mock: MockRouter - ) -> None: - respx_mock.post("/format/v1/document").mock(return_value=httpx.Response(200, json={"foo": "bar"})) - v1 = await async_client.format.v1.create_document( - content="content", - output_format="pdf", - input_format="md", - options={ - "components": [ - { - "content": "content", - "styles": {}, - "template_id": "templateId", - "variables": {}, - } - ] - }, - ) - assert v1.is_closed - assert await v1.json() == {"foo": "bar"} - assert cast(Any, v1.is_closed) is True - assert isinstance(v1, AsyncBinaryAPIResponse) - - @parametrize - @pytest.mark.respx(base_url=base_url) - async def test_raw_response_create_document(self, async_client: AsyncCasedev, respx_mock: MockRouter) -> None: - respx_mock.post("/format/v1/document").mock(return_value=httpx.Response(200, json={"foo": "bar"})) - - v1 = await async_client.format.v1.with_raw_response.create_document( - content="content", - output_format="pdf", - ) - - assert v1.is_closed is True - assert v1.http_request.headers.get("X-Stainless-Lang") == "python" - assert await v1.json() == {"foo": "bar"} - assert isinstance(v1, AsyncBinaryAPIResponse) - - @parametrize - @pytest.mark.respx(base_url=base_url) - async def test_streaming_response_create_document(self, async_client: AsyncCasedev, respx_mock: MockRouter) -> None: - respx_mock.post("/format/v1/document").mock(return_value=httpx.Response(200, json={"foo": "bar"})) - async with async_client.format.v1.with_streaming_response.create_document( - content="content", - output_format="pdf", - ) as v1: - assert not v1.is_closed - assert v1.http_request.headers.get("X-Stainless-Lang") == "python" - - assert await v1.json() == {"foo": "bar"} - assert cast(Any, v1.is_closed) is True - assert isinstance(v1, AsyncStreamedBinaryAPIResponse) - - assert cast(Any, v1.is_closed) is True diff --git a/tests/api_resources/format/v1/__init__.py b/tests/api_resources/format/v1/__init__.py deleted file mode 100644 index fd8019a9..00000000 --- a/tests/api_resources/format/v1/__init__.py +++ /dev/null @@ -1 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. diff --git a/tests/api_resources/format/v1/test_templates.py b/tests/api_resources/format/v1/test_templates.py deleted file mode 100644 index 5817c69b..00000000 --- a/tests/api_resources/format/v1/test_templates.py +++ /dev/null @@ -1,268 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from __future__ import annotations - -import os -from typing import Any, cast - -import pytest - -from casedev import Casedev, AsyncCasedev -from tests.utils import assert_matches_type -from casedev.types.format.v1 import ( - TemplateListResponse, - TemplateCreateResponse, - TemplateRetrieveResponse, -) - -base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") - - -class TestTemplates: - parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"]) - - @parametrize - def test_method_create(self, client: Casedev) -> None: - template = client.format.v1.templates.create( - content="content", - name="name", - type="caption", - ) - assert_matches_type(TemplateCreateResponse, template, path=["response"]) - - @parametrize - def test_method_create_with_all_params(self, client: Casedev) -> None: - template = client.format.v1.templates.create( - content="content", - name="name", - type="caption", - description="description", - styles={}, - tags=["string"], - variables=["string"], - ) - assert_matches_type(TemplateCreateResponse, template, path=["response"]) - - @parametrize - def test_raw_response_create(self, client: Casedev) -> None: - response = client.format.v1.templates.with_raw_response.create( - content="content", - name="name", - type="caption", - ) - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - template = response.parse() - assert_matches_type(TemplateCreateResponse, template, path=["response"]) - - @parametrize - def test_streaming_response_create(self, client: Casedev) -> None: - with client.format.v1.templates.with_streaming_response.create( - content="content", - name="name", - type="caption", - ) as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - template = response.parse() - assert_matches_type(TemplateCreateResponse, template, path=["response"]) - - assert cast(Any, response.is_closed) is True - - @parametrize - def test_method_retrieve(self, client: Casedev) -> None: - template = client.format.v1.templates.retrieve( - "id", - ) - assert_matches_type(TemplateRetrieveResponse, template, path=["response"]) - - @parametrize - def test_raw_response_retrieve(self, client: Casedev) -> None: - response = client.format.v1.templates.with_raw_response.retrieve( - "id", - ) - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - template = response.parse() - assert_matches_type(TemplateRetrieveResponse, template, path=["response"]) - - @parametrize - def test_streaming_response_retrieve(self, client: Casedev) -> None: - with client.format.v1.templates.with_streaming_response.retrieve( - "id", - ) as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - template = response.parse() - assert_matches_type(TemplateRetrieveResponse, template, path=["response"]) - - assert cast(Any, response.is_closed) is True - - @parametrize - def test_path_params_retrieve(self, client: Casedev) -> None: - with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): - client.format.v1.templates.with_raw_response.retrieve( - "", - ) - - @parametrize - def test_method_list(self, client: Casedev) -> None: - template = client.format.v1.templates.list() - assert_matches_type(TemplateListResponse, template, path=["response"]) - - @parametrize - def test_method_list_with_all_params(self, client: Casedev) -> None: - template = client.format.v1.templates.list( - type="type", - ) - assert_matches_type(TemplateListResponse, template, path=["response"]) - - @parametrize - def test_raw_response_list(self, client: Casedev) -> None: - response = client.format.v1.templates.with_raw_response.list() - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - template = response.parse() - assert_matches_type(TemplateListResponse, template, path=["response"]) - - @parametrize - def test_streaming_response_list(self, client: Casedev) -> None: - with client.format.v1.templates.with_streaming_response.list() as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - template = response.parse() - assert_matches_type(TemplateListResponse, template, path=["response"]) - - assert cast(Any, response.is_closed) is True - - -class TestAsyncTemplates: - parametrize = pytest.mark.parametrize( - "async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"] - ) - - @parametrize - async def test_method_create(self, async_client: AsyncCasedev) -> None: - template = await async_client.format.v1.templates.create( - content="content", - name="name", - type="caption", - ) - assert_matches_type(TemplateCreateResponse, template, path=["response"]) - - @parametrize - async def test_method_create_with_all_params(self, async_client: AsyncCasedev) -> None: - template = await async_client.format.v1.templates.create( - content="content", - name="name", - type="caption", - description="description", - styles={}, - tags=["string"], - variables=["string"], - ) - assert_matches_type(TemplateCreateResponse, template, path=["response"]) - - @parametrize - async def test_raw_response_create(self, async_client: AsyncCasedev) -> None: - response = await async_client.format.v1.templates.with_raw_response.create( - content="content", - name="name", - type="caption", - ) - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - template = await response.parse() - assert_matches_type(TemplateCreateResponse, template, path=["response"]) - - @parametrize - async def test_streaming_response_create(self, async_client: AsyncCasedev) -> None: - async with async_client.format.v1.templates.with_streaming_response.create( - content="content", - name="name", - type="caption", - ) as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - template = await response.parse() - assert_matches_type(TemplateCreateResponse, template, path=["response"]) - - assert cast(Any, response.is_closed) is True - - @parametrize - async def test_method_retrieve(self, async_client: AsyncCasedev) -> None: - template = await async_client.format.v1.templates.retrieve( - "id", - ) - assert_matches_type(TemplateRetrieveResponse, template, path=["response"]) - - @parametrize - async def test_raw_response_retrieve(self, async_client: AsyncCasedev) -> None: - response = await async_client.format.v1.templates.with_raw_response.retrieve( - "id", - ) - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - template = await response.parse() - assert_matches_type(TemplateRetrieveResponse, template, path=["response"]) - - @parametrize - async def test_streaming_response_retrieve(self, async_client: AsyncCasedev) -> None: - async with async_client.format.v1.templates.with_streaming_response.retrieve( - "id", - ) as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - template = await response.parse() - assert_matches_type(TemplateRetrieveResponse, template, path=["response"]) - - assert cast(Any, response.is_closed) is True - - @parametrize - async def test_path_params_retrieve(self, async_client: AsyncCasedev) -> None: - with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): - await async_client.format.v1.templates.with_raw_response.retrieve( - "", - ) - - @parametrize - async def test_method_list(self, async_client: AsyncCasedev) -> None: - template = await async_client.format.v1.templates.list() - assert_matches_type(TemplateListResponse, template, path=["response"]) - - @parametrize - async def test_method_list_with_all_params(self, async_client: AsyncCasedev) -> None: - template = await async_client.format.v1.templates.list( - type="type", - ) - assert_matches_type(TemplateListResponse, template, path=["response"]) - - @parametrize - async def test_raw_response_list(self, async_client: AsyncCasedev) -> None: - response = await async_client.format.v1.templates.with_raw_response.list() - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - template = await response.parse() - assert_matches_type(TemplateListResponse, template, path=["response"]) - - @parametrize - async def test_streaming_response_list(self, async_client: AsyncCasedev) -> None: - async with async_client.format.v1.templates.with_streaming_response.list() as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - template = await response.parse() - assert_matches_type(TemplateListResponse, template, path=["response"]) - - assert cast(Any, response.is_closed) is True diff --git a/tests/api_resources/legal/test_v1.py b/tests/api_resources/legal/test_v1.py index c1edc410..e4e24632 100644 --- a/tests/api_resources/legal/test_v1.py +++ b/tests/api_resources/legal/test_v1.py @@ -12,7 +12,6 @@ from casedev._utils import parse_date from casedev.types.legal import ( V1FindResponse, - V1DraftResponse, V1DocketResponse, V1VerifyResponse, V1SimilarResponse, @@ -81,59 +80,6 @@ def test_streaming_response_docket(self, client: Casedev) -> None: assert cast(Any, response.is_closed) is True - @parametrize - def test_method_draft(self, client: Casedev) -> None: - v1 = client.legal.v1.draft( - instructions="xxxxxxxxxx", - vault_id="vault_id", - ) - assert_matches_type(V1DraftResponse, v1, path=["response"]) - - @parametrize - def test_method_draft_with_all_params(self, client: Casedev) -> None: - v1 = client.legal.v1.draft( - instructions="xxxxxxxxxx", - vault_id="vault_id", - citations=True, - format="format", - length={ - "target": 0, - "unit": "words", - }, - model="model", - object_ids=["string"], - output_name="output_name", - output_type="pdf", - verified=True, - ) - assert_matches_type(V1DraftResponse, v1, path=["response"]) - - @parametrize - def test_raw_response_draft(self, client: Casedev) -> None: - response = client.legal.v1.with_raw_response.draft( - instructions="xxxxxxxxxx", - vault_id="vault_id", - ) - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - v1 = response.parse() - assert_matches_type(V1DraftResponse, v1, path=["response"]) - - @parametrize - def test_streaming_response_draft(self, client: Casedev) -> None: - with client.legal.v1.with_streaming_response.draft( - instructions="xxxxxxxxxx", - vault_id="vault_id", - ) as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - v1 = response.parse() - assert_matches_type(V1DraftResponse, v1, path=["response"]) - - assert cast(Any, response.is_closed) is True - @parametrize def test_method_find(self, client: Casedev) -> None: v1 = client.legal.v1.find( @@ -641,59 +587,6 @@ async def test_streaming_response_docket(self, async_client: AsyncCasedev) -> No assert cast(Any, response.is_closed) is True - @parametrize - async def test_method_draft(self, async_client: AsyncCasedev) -> None: - v1 = await async_client.legal.v1.draft( - instructions="xxxxxxxxxx", - vault_id="vault_id", - ) - assert_matches_type(V1DraftResponse, v1, path=["response"]) - - @parametrize - async def test_method_draft_with_all_params(self, async_client: AsyncCasedev) -> None: - v1 = await async_client.legal.v1.draft( - instructions="xxxxxxxxxx", - vault_id="vault_id", - citations=True, - format="format", - length={ - "target": 0, - "unit": "words", - }, - model="model", - object_ids=["string"], - output_name="output_name", - output_type="pdf", - verified=True, - ) - assert_matches_type(V1DraftResponse, v1, path=["response"]) - - @parametrize - async def test_raw_response_draft(self, async_client: AsyncCasedev) -> None: - response = await async_client.legal.v1.with_raw_response.draft( - instructions="xxxxxxxxxx", - vault_id="vault_id", - ) - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - v1 = await response.parse() - assert_matches_type(V1DraftResponse, v1, path=["response"]) - - @parametrize - async def test_streaming_response_draft(self, async_client: AsyncCasedev) -> None: - async with async_client.legal.v1.with_streaming_response.draft( - instructions="xxxxxxxxxx", - vault_id="vault_id", - ) as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - v1 = await response.parse() - assert_matches_type(V1DraftResponse, v1, path=["response"]) - - assert cast(Any, response.is_closed) is True - @parametrize async def test_method_find(self, async_client: AsyncCasedev) -> None: v1 = await async_client.legal.v1.find( diff --git a/tests/api_resources/linc/v1/test_sessions.py b/tests/api_resources/linc/v1/test_sessions.py index 6cf63563..be6e84c0 100644 --- a/tests/api_resources/linc/v1/test_sessions.py +++ b/tests/api_resources/linc/v1/test_sessions.py @@ -29,6 +29,7 @@ def test_method_create_with_all_params(self, client: Casedev) -> None: instructions="instructions", model="model", scoped_api_key="scopedApiKey", + service_tier="default", skill_slugs=["string"], title="title", vault_ids=["string"], @@ -96,14 +97,22 @@ def test_path_params_delete(self, client: Casedev) -> None: @parametrize def test_method_cancel(self, client: Casedev) -> None: session = client.linc.v1.sessions.cancel( - "id", + id="id", + ) + assert session is None + + @parametrize + def test_method_cancel_with_all_params(self, client: Casedev) -> None: + session = client.linc.v1.sessions.cancel( + id="id", + clear_queue=True, ) assert session is None @parametrize def test_raw_response_cancel(self, client: Casedev) -> None: response = client.linc.v1.sessions.with_raw_response.cancel( - "id", + id="id", ) assert response.is_closed is True @@ -114,7 +123,7 @@ def test_raw_response_cancel(self, client: Casedev) -> None: @parametrize def test_streaming_response_cancel(self, client: Casedev) -> None: with client.linc.v1.sessions.with_streaming_response.cancel( - "id", + id="id", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" @@ -128,7 +137,7 @@ def test_streaming_response_cancel(self, client: Casedev) -> None: def test_path_params_cancel(self, client: Casedev) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): client.linc.v1.sessions.with_raw_response.cancel( - "", + id="", ) @parametrize @@ -403,6 +412,7 @@ async def test_method_create_with_all_params(self, async_client: AsyncCasedev) - instructions="instructions", model="model", scoped_api_key="scopedApiKey", + service_tier="default", skill_slugs=["string"], title="title", vault_ids=["string"], @@ -470,14 +480,22 @@ async def test_path_params_delete(self, async_client: AsyncCasedev) -> None: @parametrize async def test_method_cancel(self, async_client: AsyncCasedev) -> None: session = await async_client.linc.v1.sessions.cancel( - "id", + id="id", + ) + assert session is None + + @parametrize + async def test_method_cancel_with_all_params(self, async_client: AsyncCasedev) -> None: + session = await async_client.linc.v1.sessions.cancel( + id="id", + clear_queue=True, ) assert session is None @parametrize async def test_raw_response_cancel(self, async_client: AsyncCasedev) -> None: response = await async_client.linc.v1.sessions.with_raw_response.cancel( - "id", + id="id", ) assert response.is_closed is True @@ -488,7 +506,7 @@ async def test_raw_response_cancel(self, async_client: AsyncCasedev) -> None: @parametrize async def test_streaming_response_cancel(self, async_client: AsyncCasedev) -> None: async with async_client.linc.v1.sessions.with_streaming_response.cancel( - "id", + id="id", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" @@ -502,7 +520,7 @@ async def test_streaming_response_cancel(self, async_client: AsyncCasedev) -> No async def test_path_params_cancel(self, async_client: AsyncCasedev) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): await async_client.linc.v1.sessions.with_raw_response.cancel( - "", + id="", ) @parametrize diff --git a/tests/api_resources/mail/__init__.py b/tests/api_resources/mail/__init__.py deleted file mode 100644 index fd8019a9..00000000 --- a/tests/api_resources/mail/__init__.py +++ /dev/null @@ -1 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. diff --git a/tests/api_resources/mail/v1/__init__.py b/tests/api_resources/mail/v1/__init__.py deleted file mode 100644 index fd8019a9..00000000 --- a/tests/api_resources/mail/v1/__init__.py +++ /dev/null @@ -1 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. diff --git a/tests/api_resources/mail/v1/test_inboxes.py b/tests/api_resources/mail/v1/test_inboxes.py deleted file mode 100644 index 02cb0b7d..00000000 --- a/tests/api_resources/mail/v1/test_inboxes.py +++ /dev/null @@ -1,930 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from __future__ import annotations - -import os -from typing import Any, cast - -import pytest - -from casedev import Casedev, AsyncCasedev - -base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") - - -class TestInboxes: - parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"]) - - @parametrize - def test_method_create(self, client: Casedev) -> None: - inbox = client.mail.v1.inboxes.create() - assert inbox is None - - @parametrize - def test_method_create_with_all_params(self, client: Casedev) -> None: - inbox = client.mail.v1.inboxes.create( - address="address", - display_name="displayName", - ) - assert inbox is None - - @parametrize - def test_raw_response_create(self, client: Casedev) -> None: - response = client.mail.v1.inboxes.with_raw_response.create() - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - inbox = response.parse() - assert inbox is None - - @parametrize - def test_streaming_response_create(self, client: Casedev) -> None: - with client.mail.v1.inboxes.with_streaming_response.create() as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - inbox = response.parse() - assert inbox is None - - assert cast(Any, response.is_closed) is True - - @parametrize - def test_method_retrieve(self, client: Casedev) -> None: - inbox = client.mail.v1.inboxes.retrieve( - "inboxId", - ) - assert inbox is None - - @parametrize - def test_raw_response_retrieve(self, client: Casedev) -> None: - response = client.mail.v1.inboxes.with_raw_response.retrieve( - "inboxId", - ) - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - inbox = response.parse() - assert inbox is None - - @parametrize - def test_streaming_response_retrieve(self, client: Casedev) -> None: - with client.mail.v1.inboxes.with_streaming_response.retrieve( - "inboxId", - ) as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - inbox = response.parse() - assert inbox is None - - assert cast(Any, response.is_closed) is True - - @parametrize - def test_path_params_retrieve(self, client: Casedev) -> None: - with pytest.raises(ValueError, match=r"Expected a non-empty value for `inbox_id` but received ''"): - client.mail.v1.inboxes.with_raw_response.retrieve( - "", - ) - - @parametrize - def test_method_list(self, client: Casedev) -> None: - inbox = client.mail.v1.inboxes.list() - assert inbox is None - - @parametrize - def test_raw_response_list(self, client: Casedev) -> None: - response = client.mail.v1.inboxes.with_raw_response.list() - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - inbox = response.parse() - assert inbox is None - - @parametrize - def test_streaming_response_list(self, client: Casedev) -> None: - with client.mail.v1.inboxes.with_streaming_response.list() as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - inbox = response.parse() - assert inbox is None - - assert cast(Any, response.is_closed) is True - - @parametrize - def test_method_delete(self, client: Casedev) -> None: - inbox = client.mail.v1.inboxes.delete( - "inboxId", - ) - assert inbox is None - - @parametrize - def test_raw_response_delete(self, client: Casedev) -> None: - response = client.mail.v1.inboxes.with_raw_response.delete( - "inboxId", - ) - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - inbox = response.parse() - assert inbox is None - - @parametrize - def test_streaming_response_delete(self, client: Casedev) -> None: - with client.mail.v1.inboxes.with_streaming_response.delete( - "inboxId", - ) as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - inbox = response.parse() - assert inbox is None - - assert cast(Any, response.is_closed) is True - - @parametrize - def test_path_params_delete(self, client: Casedev) -> None: - with pytest.raises(ValueError, match=r"Expected a non-empty value for `inbox_id` but received ''"): - client.mail.v1.inboxes.with_raw_response.delete( - "", - ) - - @parametrize - def test_method_get_attachment(self, client: Casedev) -> None: - inbox = client.mail.v1.inboxes.get_attachment( - attachment_id="attachmentId", - inbox_id="inboxId", - message_id="messageId", - ) - assert inbox is None - - @parametrize - def test_raw_response_get_attachment(self, client: Casedev) -> None: - response = client.mail.v1.inboxes.with_raw_response.get_attachment( - attachment_id="attachmentId", - inbox_id="inboxId", - message_id="messageId", - ) - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - inbox = response.parse() - assert inbox is None - - @parametrize - def test_streaming_response_get_attachment(self, client: Casedev) -> None: - with client.mail.v1.inboxes.with_streaming_response.get_attachment( - attachment_id="attachmentId", - inbox_id="inboxId", - message_id="messageId", - ) as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - inbox = response.parse() - assert inbox is None - - assert cast(Any, response.is_closed) is True - - @parametrize - def test_path_params_get_attachment(self, client: Casedev) -> None: - with pytest.raises(ValueError, match=r"Expected a non-empty value for `inbox_id` but received ''"): - client.mail.v1.inboxes.with_raw_response.get_attachment( - attachment_id="attachmentId", - inbox_id="", - message_id="messageId", - ) - - with pytest.raises(ValueError, match=r"Expected a non-empty value for `message_id` but received ''"): - client.mail.v1.inboxes.with_raw_response.get_attachment( - attachment_id="attachmentId", - inbox_id="inboxId", - message_id="", - ) - - with pytest.raises(ValueError, match=r"Expected a non-empty value for `attachment_id` but received ''"): - client.mail.v1.inboxes.with_raw_response.get_attachment( - attachment_id="", - inbox_id="inboxId", - message_id="messageId", - ) - - @parametrize - def test_method_get_message(self, client: Casedev) -> None: - inbox = client.mail.v1.inboxes.get_message( - message_id="messageId", - inbox_id="inboxId", - ) - assert inbox is None - - @parametrize - def test_raw_response_get_message(self, client: Casedev) -> None: - response = client.mail.v1.inboxes.with_raw_response.get_message( - message_id="messageId", - inbox_id="inboxId", - ) - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - inbox = response.parse() - assert inbox is None - - @parametrize - def test_streaming_response_get_message(self, client: Casedev) -> None: - with client.mail.v1.inboxes.with_streaming_response.get_message( - message_id="messageId", - inbox_id="inboxId", - ) as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - inbox = response.parse() - assert inbox is None - - assert cast(Any, response.is_closed) is True - - @parametrize - def test_path_params_get_message(self, client: Casedev) -> None: - with pytest.raises(ValueError, match=r"Expected a non-empty value for `inbox_id` but received ''"): - client.mail.v1.inboxes.with_raw_response.get_message( - message_id="messageId", - inbox_id="", - ) - - with pytest.raises(ValueError, match=r"Expected a non-empty value for `message_id` but received ''"): - client.mail.v1.inboxes.with_raw_response.get_message( - message_id="", - inbox_id="inboxId", - ) - - @parametrize - def test_method_get_policy(self, client: Casedev) -> None: - inbox = client.mail.v1.inboxes.get_policy( - "inboxId", - ) - assert inbox is None - - @parametrize - def test_raw_response_get_policy(self, client: Casedev) -> None: - response = client.mail.v1.inboxes.with_raw_response.get_policy( - "inboxId", - ) - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - inbox = response.parse() - assert inbox is None - - @parametrize - def test_streaming_response_get_policy(self, client: Casedev) -> None: - with client.mail.v1.inboxes.with_streaming_response.get_policy( - "inboxId", - ) as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - inbox = response.parse() - assert inbox is None - - assert cast(Any, response.is_closed) is True - - @parametrize - def test_path_params_get_policy(self, client: Casedev) -> None: - with pytest.raises(ValueError, match=r"Expected a non-empty value for `inbox_id` but received ''"): - client.mail.v1.inboxes.with_raw_response.get_policy( - "", - ) - - @parametrize - def test_method_list_messages(self, client: Casedev) -> None: - inbox = client.mail.v1.inboxes.list_messages( - "inboxId", - ) - assert inbox is None - - @parametrize - def test_raw_response_list_messages(self, client: Casedev) -> None: - response = client.mail.v1.inboxes.with_raw_response.list_messages( - "inboxId", - ) - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - inbox = response.parse() - assert inbox is None - - @parametrize - def test_streaming_response_list_messages(self, client: Casedev) -> None: - with client.mail.v1.inboxes.with_streaming_response.list_messages( - "inboxId", - ) as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - inbox = response.parse() - assert inbox is None - - assert cast(Any, response.is_closed) is True - - @parametrize - def test_path_params_list_messages(self, client: Casedev) -> None: - with pytest.raises(ValueError, match=r"Expected a non-empty value for `inbox_id` but received ''"): - client.mail.v1.inboxes.with_raw_response.list_messages( - "", - ) - - @parametrize - def test_method_reply(self, client: Casedev) -> None: - inbox = client.mail.v1.inboxes.reply( - message_id="messageId", - inbox_id="inboxId", - ) - assert inbox is None - - @parametrize - def test_raw_response_reply(self, client: Casedev) -> None: - response = client.mail.v1.inboxes.with_raw_response.reply( - message_id="messageId", - inbox_id="inboxId", - ) - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - inbox = response.parse() - assert inbox is None - - @parametrize - def test_streaming_response_reply(self, client: Casedev) -> None: - with client.mail.v1.inboxes.with_streaming_response.reply( - message_id="messageId", - inbox_id="inboxId", - ) as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - inbox = response.parse() - assert inbox is None - - assert cast(Any, response.is_closed) is True - - @parametrize - def test_path_params_reply(self, client: Casedev) -> None: - with pytest.raises(ValueError, match=r"Expected a non-empty value for `inbox_id` but received ''"): - client.mail.v1.inboxes.with_raw_response.reply( - message_id="messageId", - inbox_id="", - ) - - with pytest.raises(ValueError, match=r"Expected a non-empty value for `message_id` but received ''"): - client.mail.v1.inboxes.with_raw_response.reply( - message_id="", - inbox_id="inboxId", - ) - - @parametrize - def test_method_send(self, client: Casedev) -> None: - inbox = client.mail.v1.inboxes.send( - "inboxId", - ) - assert inbox is None - - @parametrize - def test_raw_response_send(self, client: Casedev) -> None: - response = client.mail.v1.inboxes.with_raw_response.send( - "inboxId", - ) - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - inbox = response.parse() - assert inbox is None - - @parametrize - def test_streaming_response_send(self, client: Casedev) -> None: - with client.mail.v1.inboxes.with_streaming_response.send( - "inboxId", - ) as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - inbox = response.parse() - assert inbox is None - - assert cast(Any, response.is_closed) is True - - @parametrize - def test_path_params_send(self, client: Casedev) -> None: - with pytest.raises(ValueError, match=r"Expected a non-empty value for `inbox_id` but received ''"): - client.mail.v1.inboxes.with_raw_response.send( - "", - ) - - @parametrize - def test_method_set_policy(self, client: Casedev) -> None: - inbox = client.mail.v1.inboxes.set_policy( - inbox_id="inboxId", - ) - assert inbox is None - - @parametrize - def test_method_set_policy_with_all_params(self, client: Casedev) -> None: - inbox = client.mail.v1.inboxes.set_policy( - inbox_id="inboxId", - allowed_sender_patterns=["string"], - enforce_sender_allowlist=True, - read_access_rules=["string"], - reply_access_rules=["string"], - send_access_rules=["string"], - ) - assert inbox is None - - @parametrize - def test_raw_response_set_policy(self, client: Casedev) -> None: - response = client.mail.v1.inboxes.with_raw_response.set_policy( - inbox_id="inboxId", - ) - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - inbox = response.parse() - assert inbox is None - - @parametrize - def test_streaming_response_set_policy(self, client: Casedev) -> None: - with client.mail.v1.inboxes.with_streaming_response.set_policy( - inbox_id="inboxId", - ) as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - inbox = response.parse() - assert inbox is None - - assert cast(Any, response.is_closed) is True - - @parametrize - def test_path_params_set_policy(self, client: Casedev) -> None: - with pytest.raises(ValueError, match=r"Expected a non-empty value for `inbox_id` but received ''"): - client.mail.v1.inboxes.with_raw_response.set_policy( - inbox_id="", - ) - - -class TestAsyncInboxes: - parametrize = pytest.mark.parametrize( - "async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"] - ) - - @parametrize - async def test_method_create(self, async_client: AsyncCasedev) -> None: - inbox = await async_client.mail.v1.inboxes.create() - assert inbox is None - - @parametrize - async def test_method_create_with_all_params(self, async_client: AsyncCasedev) -> None: - inbox = await async_client.mail.v1.inboxes.create( - address="address", - display_name="displayName", - ) - assert inbox is None - - @parametrize - async def test_raw_response_create(self, async_client: AsyncCasedev) -> None: - response = await async_client.mail.v1.inboxes.with_raw_response.create() - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - inbox = await response.parse() - assert inbox is None - - @parametrize - async def test_streaming_response_create(self, async_client: AsyncCasedev) -> None: - async with async_client.mail.v1.inboxes.with_streaming_response.create() as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - inbox = await response.parse() - assert inbox is None - - assert cast(Any, response.is_closed) is True - - @parametrize - async def test_method_retrieve(self, async_client: AsyncCasedev) -> None: - inbox = await async_client.mail.v1.inboxes.retrieve( - "inboxId", - ) - assert inbox is None - - @parametrize - async def test_raw_response_retrieve(self, async_client: AsyncCasedev) -> None: - response = await async_client.mail.v1.inboxes.with_raw_response.retrieve( - "inboxId", - ) - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - inbox = await response.parse() - assert inbox is None - - @parametrize - async def test_streaming_response_retrieve(self, async_client: AsyncCasedev) -> None: - async with async_client.mail.v1.inboxes.with_streaming_response.retrieve( - "inboxId", - ) as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - inbox = await response.parse() - assert inbox is None - - assert cast(Any, response.is_closed) is True - - @parametrize - async def test_path_params_retrieve(self, async_client: AsyncCasedev) -> None: - with pytest.raises(ValueError, match=r"Expected a non-empty value for `inbox_id` but received ''"): - await async_client.mail.v1.inboxes.with_raw_response.retrieve( - "", - ) - - @parametrize - async def test_method_list(self, async_client: AsyncCasedev) -> None: - inbox = await async_client.mail.v1.inboxes.list() - assert inbox is None - - @parametrize - async def test_raw_response_list(self, async_client: AsyncCasedev) -> None: - response = await async_client.mail.v1.inboxes.with_raw_response.list() - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - inbox = await response.parse() - assert inbox is None - - @parametrize - async def test_streaming_response_list(self, async_client: AsyncCasedev) -> None: - async with async_client.mail.v1.inboxes.with_streaming_response.list() as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - inbox = await response.parse() - assert inbox is None - - assert cast(Any, response.is_closed) is True - - @parametrize - async def test_method_delete(self, async_client: AsyncCasedev) -> None: - inbox = await async_client.mail.v1.inboxes.delete( - "inboxId", - ) - assert inbox is None - - @parametrize - async def test_raw_response_delete(self, async_client: AsyncCasedev) -> None: - response = await async_client.mail.v1.inboxes.with_raw_response.delete( - "inboxId", - ) - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - inbox = await response.parse() - assert inbox is None - - @parametrize - async def test_streaming_response_delete(self, async_client: AsyncCasedev) -> None: - async with async_client.mail.v1.inboxes.with_streaming_response.delete( - "inboxId", - ) as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - inbox = await response.parse() - assert inbox is None - - assert cast(Any, response.is_closed) is True - - @parametrize - async def test_path_params_delete(self, async_client: AsyncCasedev) -> None: - with pytest.raises(ValueError, match=r"Expected a non-empty value for `inbox_id` but received ''"): - await async_client.mail.v1.inboxes.with_raw_response.delete( - "", - ) - - @parametrize - async def test_method_get_attachment(self, async_client: AsyncCasedev) -> None: - inbox = await async_client.mail.v1.inboxes.get_attachment( - attachment_id="attachmentId", - inbox_id="inboxId", - message_id="messageId", - ) - assert inbox is None - - @parametrize - async def test_raw_response_get_attachment(self, async_client: AsyncCasedev) -> None: - response = await async_client.mail.v1.inboxes.with_raw_response.get_attachment( - attachment_id="attachmentId", - inbox_id="inboxId", - message_id="messageId", - ) - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - inbox = await response.parse() - assert inbox is None - - @parametrize - async def test_streaming_response_get_attachment(self, async_client: AsyncCasedev) -> None: - async with async_client.mail.v1.inboxes.with_streaming_response.get_attachment( - attachment_id="attachmentId", - inbox_id="inboxId", - message_id="messageId", - ) as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - inbox = await response.parse() - assert inbox is None - - assert cast(Any, response.is_closed) is True - - @parametrize - async def test_path_params_get_attachment(self, async_client: AsyncCasedev) -> None: - with pytest.raises(ValueError, match=r"Expected a non-empty value for `inbox_id` but received ''"): - await async_client.mail.v1.inboxes.with_raw_response.get_attachment( - attachment_id="attachmentId", - inbox_id="", - message_id="messageId", - ) - - with pytest.raises(ValueError, match=r"Expected a non-empty value for `message_id` but received ''"): - await async_client.mail.v1.inboxes.with_raw_response.get_attachment( - attachment_id="attachmentId", - inbox_id="inboxId", - message_id="", - ) - - with pytest.raises(ValueError, match=r"Expected a non-empty value for `attachment_id` but received ''"): - await async_client.mail.v1.inboxes.with_raw_response.get_attachment( - attachment_id="", - inbox_id="inboxId", - message_id="messageId", - ) - - @parametrize - async def test_method_get_message(self, async_client: AsyncCasedev) -> None: - inbox = await async_client.mail.v1.inboxes.get_message( - message_id="messageId", - inbox_id="inboxId", - ) - assert inbox is None - - @parametrize - async def test_raw_response_get_message(self, async_client: AsyncCasedev) -> None: - response = await async_client.mail.v1.inboxes.with_raw_response.get_message( - message_id="messageId", - inbox_id="inboxId", - ) - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - inbox = await response.parse() - assert inbox is None - - @parametrize - async def test_streaming_response_get_message(self, async_client: AsyncCasedev) -> None: - async with async_client.mail.v1.inboxes.with_streaming_response.get_message( - message_id="messageId", - inbox_id="inboxId", - ) as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - inbox = await response.parse() - assert inbox is None - - assert cast(Any, response.is_closed) is True - - @parametrize - async def test_path_params_get_message(self, async_client: AsyncCasedev) -> None: - with pytest.raises(ValueError, match=r"Expected a non-empty value for `inbox_id` but received ''"): - await async_client.mail.v1.inboxes.with_raw_response.get_message( - message_id="messageId", - inbox_id="", - ) - - with pytest.raises(ValueError, match=r"Expected a non-empty value for `message_id` but received ''"): - await async_client.mail.v1.inboxes.with_raw_response.get_message( - message_id="", - inbox_id="inboxId", - ) - - @parametrize - async def test_method_get_policy(self, async_client: AsyncCasedev) -> None: - inbox = await async_client.mail.v1.inboxes.get_policy( - "inboxId", - ) - assert inbox is None - - @parametrize - async def test_raw_response_get_policy(self, async_client: AsyncCasedev) -> None: - response = await async_client.mail.v1.inboxes.with_raw_response.get_policy( - "inboxId", - ) - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - inbox = await response.parse() - assert inbox is None - - @parametrize - async def test_streaming_response_get_policy(self, async_client: AsyncCasedev) -> None: - async with async_client.mail.v1.inboxes.with_streaming_response.get_policy( - "inboxId", - ) as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - inbox = await response.parse() - assert inbox is None - - assert cast(Any, response.is_closed) is True - - @parametrize - async def test_path_params_get_policy(self, async_client: AsyncCasedev) -> None: - with pytest.raises(ValueError, match=r"Expected a non-empty value for `inbox_id` but received ''"): - await async_client.mail.v1.inboxes.with_raw_response.get_policy( - "", - ) - - @parametrize - async def test_method_list_messages(self, async_client: AsyncCasedev) -> None: - inbox = await async_client.mail.v1.inboxes.list_messages( - "inboxId", - ) - assert inbox is None - - @parametrize - async def test_raw_response_list_messages(self, async_client: AsyncCasedev) -> None: - response = await async_client.mail.v1.inboxes.with_raw_response.list_messages( - "inboxId", - ) - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - inbox = await response.parse() - assert inbox is None - - @parametrize - async def test_streaming_response_list_messages(self, async_client: AsyncCasedev) -> None: - async with async_client.mail.v1.inboxes.with_streaming_response.list_messages( - "inboxId", - ) as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - inbox = await response.parse() - assert inbox is None - - assert cast(Any, response.is_closed) is True - - @parametrize - async def test_path_params_list_messages(self, async_client: AsyncCasedev) -> None: - with pytest.raises(ValueError, match=r"Expected a non-empty value for `inbox_id` but received ''"): - await async_client.mail.v1.inboxes.with_raw_response.list_messages( - "", - ) - - @parametrize - async def test_method_reply(self, async_client: AsyncCasedev) -> None: - inbox = await async_client.mail.v1.inboxes.reply( - message_id="messageId", - inbox_id="inboxId", - ) - assert inbox is None - - @parametrize - async def test_raw_response_reply(self, async_client: AsyncCasedev) -> None: - response = await async_client.mail.v1.inboxes.with_raw_response.reply( - message_id="messageId", - inbox_id="inboxId", - ) - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - inbox = await response.parse() - assert inbox is None - - @parametrize - async def test_streaming_response_reply(self, async_client: AsyncCasedev) -> None: - async with async_client.mail.v1.inboxes.with_streaming_response.reply( - message_id="messageId", - inbox_id="inboxId", - ) as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - inbox = await response.parse() - assert inbox is None - - assert cast(Any, response.is_closed) is True - - @parametrize - async def test_path_params_reply(self, async_client: AsyncCasedev) -> None: - with pytest.raises(ValueError, match=r"Expected a non-empty value for `inbox_id` but received ''"): - await async_client.mail.v1.inboxes.with_raw_response.reply( - message_id="messageId", - inbox_id="", - ) - - with pytest.raises(ValueError, match=r"Expected a non-empty value for `message_id` but received ''"): - await async_client.mail.v1.inboxes.with_raw_response.reply( - message_id="", - inbox_id="inboxId", - ) - - @parametrize - async def test_method_send(self, async_client: AsyncCasedev) -> None: - inbox = await async_client.mail.v1.inboxes.send( - "inboxId", - ) - assert inbox is None - - @parametrize - async def test_raw_response_send(self, async_client: AsyncCasedev) -> None: - response = await async_client.mail.v1.inboxes.with_raw_response.send( - "inboxId", - ) - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - inbox = await response.parse() - assert inbox is None - - @parametrize - async def test_streaming_response_send(self, async_client: AsyncCasedev) -> None: - async with async_client.mail.v1.inboxes.with_streaming_response.send( - "inboxId", - ) as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - inbox = await response.parse() - assert inbox is None - - assert cast(Any, response.is_closed) is True - - @parametrize - async def test_path_params_send(self, async_client: AsyncCasedev) -> None: - with pytest.raises(ValueError, match=r"Expected a non-empty value for `inbox_id` but received ''"): - await async_client.mail.v1.inboxes.with_raw_response.send( - "", - ) - - @parametrize - async def test_method_set_policy(self, async_client: AsyncCasedev) -> None: - inbox = await async_client.mail.v1.inboxes.set_policy( - inbox_id="inboxId", - ) - assert inbox is None - - @parametrize - async def test_method_set_policy_with_all_params(self, async_client: AsyncCasedev) -> None: - inbox = await async_client.mail.v1.inboxes.set_policy( - inbox_id="inboxId", - allowed_sender_patterns=["string"], - enforce_sender_allowlist=True, - read_access_rules=["string"], - reply_access_rules=["string"], - send_access_rules=["string"], - ) - assert inbox is None - - @parametrize - async def test_raw_response_set_policy(self, async_client: AsyncCasedev) -> None: - response = await async_client.mail.v1.inboxes.with_raw_response.set_policy( - inbox_id="inboxId", - ) - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - inbox = await response.parse() - assert inbox is None - - @parametrize - async def test_streaming_response_set_policy(self, async_client: AsyncCasedev) -> None: - async with async_client.mail.v1.inboxes.with_streaming_response.set_policy( - inbox_id="inboxId", - ) as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - inbox = await response.parse() - assert inbox is None - - assert cast(Any, response.is_closed) is True - - @parametrize - async def test_path_params_set_policy(self, async_client: AsyncCasedev) -> None: - with pytest.raises(ValueError, match=r"Expected a non-empty value for `inbox_id` but received ''"): - await async_client.mail.v1.inboxes.with_raw_response.set_policy( - inbox_id="", - ) diff --git a/tests/api_resources/matters/v1/test_work_items.py b/tests/api_resources/matters/v1/test_work_items.py index 8456b862..7128c0af 100644 --- a/tests/api_resources/matters/v1/test_work_items.py +++ b/tests/api_resources/matters/v1/test_work_items.py @@ -252,7 +252,6 @@ def test_method_decide_with_all_params(self, client: Casedev) -> None: work_item_id="workItemId", id="id", decision="approve", - agent_type_id="agent_type_id", metadata={"foo": "bar"}, reason="reason", ) @@ -302,54 +301,6 @@ def test_path_params_decide(self, client: Casedev) -> None: decision="approve", ) - @parametrize - def test_method_list_executions(self, client: Casedev) -> None: - work_item = client.matters.v1.work_items.list_executions( - work_item_id="workItemId", - id="id", - ) - assert work_item is None - - @parametrize - def test_raw_response_list_executions(self, client: Casedev) -> None: - response = client.matters.v1.work_items.with_raw_response.list_executions( - work_item_id="workItemId", - id="id", - ) - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - work_item = response.parse() - assert work_item is None - - @parametrize - def test_streaming_response_list_executions(self, client: Casedev) -> None: - with client.matters.v1.work_items.with_streaming_response.list_executions( - work_item_id="workItemId", - id="id", - ) as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - work_item = response.parse() - assert work_item is None - - assert cast(Any, response.is_closed) is True - - @parametrize - def test_path_params_list_executions(self, client: Casedev) -> None: - with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): - client.matters.v1.work_items.with_raw_response.list_executions( - work_item_id="workItemId", - id="", - ) - - with pytest.raises(ValueError, match=r"Expected a non-empty value for `work_item_id` but received ''"): - client.matters.v1.work_items.with_raw_response.list_executions( - work_item_id="", - id="id", - ) - class TestAsyncWorkItems: parametrize = pytest.mark.parametrize( @@ -592,7 +543,6 @@ async def test_method_decide_with_all_params(self, async_client: AsyncCasedev) - work_item_id="workItemId", id="id", decision="approve", - agent_type_id="agent_type_id", metadata={"foo": "bar"}, reason="reason", ) @@ -641,51 +591,3 @@ async def test_path_params_decide(self, async_client: AsyncCasedev) -> None: id="id", decision="approve", ) - - @parametrize - async def test_method_list_executions(self, async_client: AsyncCasedev) -> None: - work_item = await async_client.matters.v1.work_items.list_executions( - work_item_id="workItemId", - id="id", - ) - assert work_item is None - - @parametrize - async def test_raw_response_list_executions(self, async_client: AsyncCasedev) -> None: - response = await async_client.matters.v1.work_items.with_raw_response.list_executions( - work_item_id="workItemId", - id="id", - ) - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - work_item = await response.parse() - assert work_item is None - - @parametrize - async def test_streaming_response_list_executions(self, async_client: AsyncCasedev) -> None: - async with async_client.matters.v1.work_items.with_streaming_response.list_executions( - work_item_id="workItemId", - id="id", - ) as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - work_item = await response.parse() - assert work_item is None - - assert cast(Any, response.is_closed) is True - - @parametrize - async def test_path_params_list_executions(self, async_client: AsyncCasedev) -> None: - with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): - await async_client.matters.v1.work_items.with_raw_response.list_executions( - work_item_id="workItemId", - id="", - ) - - with pytest.raises(ValueError, match=r"Expected a non-empty value for `work_item_id` but received ''"): - await async_client.matters.v1.work_items.with_raw_response.list_executions( - work_item_id="", - id="id", - ) diff --git a/tests/api_resources/search/test_v1.py b/tests/api_resources/search/test_v1.py index c33c4361..fa704f35 100644 --- a/tests/api_resources/search/test_v1.py +++ b/tests/api_resources/search/test_v1.py @@ -15,8 +15,6 @@ V1SearchResponse, V1SimilarResponse, V1ContentsResponse, - V1ResearchResponse, - V1RetrieveResearchResponse, ) base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") @@ -120,94 +118,6 @@ def test_streaming_response_contents(self, client: Casedev) -> None: assert cast(Any, response.is_closed) is True - @parametrize - def test_method_research(self, client: Casedev) -> None: - v1 = client.search.v1.research( - instructions="instructions", - ) - assert_matches_type(V1ResearchResponse, v1, path=["response"]) - - @parametrize - def test_method_research_with_all_params(self, client: Casedev) -> None: - v1 = client.search.v1.research( - instructions="instructions", - model="fast", - output_schema={}, - query="query", - ) - assert_matches_type(V1ResearchResponse, v1, path=["response"]) - - @parametrize - def test_raw_response_research(self, client: Casedev) -> None: - response = client.search.v1.with_raw_response.research( - instructions="instructions", - ) - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - v1 = response.parse() - assert_matches_type(V1ResearchResponse, v1, path=["response"]) - - @parametrize - def test_streaming_response_research(self, client: Casedev) -> None: - with client.search.v1.with_streaming_response.research( - instructions="instructions", - ) as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - v1 = response.parse() - assert_matches_type(V1ResearchResponse, v1, path=["response"]) - - assert cast(Any, response.is_closed) is True - - @parametrize - def test_method_retrieve_research(self, client: Casedev) -> None: - v1 = client.search.v1.retrieve_research( - id="id", - ) - assert_matches_type(V1RetrieveResearchResponse, v1, path=["response"]) - - @parametrize - def test_method_retrieve_research_with_all_params(self, client: Casedev) -> None: - v1 = client.search.v1.retrieve_research( - id="id", - events="events", - stream=True, - ) - assert_matches_type(V1RetrieveResearchResponse, v1, path=["response"]) - - @parametrize - def test_raw_response_retrieve_research(self, client: Casedev) -> None: - response = client.search.v1.with_raw_response.retrieve_research( - id="id", - ) - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - v1 = response.parse() - assert_matches_type(V1RetrieveResearchResponse, v1, path=["response"]) - - @parametrize - def test_streaming_response_retrieve_research(self, client: Casedev) -> None: - with client.search.v1.with_streaming_response.retrieve_research( - id="id", - ) as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - v1 = response.parse() - assert_matches_type(V1RetrieveResearchResponse, v1, path=["response"]) - - assert cast(Any, response.is_closed) is True - - @parametrize - def test_path_params_retrieve_research(self, client: Casedev) -> None: - with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): - client.search.v1.with_raw_response.retrieve_research( - id="", - ) - @parametrize def test_method_search(self, client: Casedev) -> None: v1 = client.search.v1.search( @@ -407,94 +317,6 @@ async def test_streaming_response_contents(self, async_client: AsyncCasedev) -> assert cast(Any, response.is_closed) is True - @parametrize - async def test_method_research(self, async_client: AsyncCasedev) -> None: - v1 = await async_client.search.v1.research( - instructions="instructions", - ) - assert_matches_type(V1ResearchResponse, v1, path=["response"]) - - @parametrize - async def test_method_research_with_all_params(self, async_client: AsyncCasedev) -> None: - v1 = await async_client.search.v1.research( - instructions="instructions", - model="fast", - output_schema={}, - query="query", - ) - assert_matches_type(V1ResearchResponse, v1, path=["response"]) - - @parametrize - async def test_raw_response_research(self, async_client: AsyncCasedev) -> None: - response = await async_client.search.v1.with_raw_response.research( - instructions="instructions", - ) - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - v1 = await response.parse() - assert_matches_type(V1ResearchResponse, v1, path=["response"]) - - @parametrize - async def test_streaming_response_research(self, async_client: AsyncCasedev) -> None: - async with async_client.search.v1.with_streaming_response.research( - instructions="instructions", - ) as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - v1 = await response.parse() - assert_matches_type(V1ResearchResponse, v1, path=["response"]) - - assert cast(Any, response.is_closed) is True - - @parametrize - async def test_method_retrieve_research(self, async_client: AsyncCasedev) -> None: - v1 = await async_client.search.v1.retrieve_research( - id="id", - ) - assert_matches_type(V1RetrieveResearchResponse, v1, path=["response"]) - - @parametrize - async def test_method_retrieve_research_with_all_params(self, async_client: AsyncCasedev) -> None: - v1 = await async_client.search.v1.retrieve_research( - id="id", - events="events", - stream=True, - ) - assert_matches_type(V1RetrieveResearchResponse, v1, path=["response"]) - - @parametrize - async def test_raw_response_retrieve_research(self, async_client: AsyncCasedev) -> None: - response = await async_client.search.v1.with_raw_response.retrieve_research( - id="id", - ) - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - v1 = await response.parse() - assert_matches_type(V1RetrieveResearchResponse, v1, path=["response"]) - - @parametrize - async def test_streaming_response_retrieve_research(self, async_client: AsyncCasedev) -> None: - async with async_client.search.v1.with_streaming_response.retrieve_research( - id="id", - ) as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - v1 = await response.parse() - assert_matches_type(V1RetrieveResearchResponse, v1, path=["response"]) - - assert cast(Any, response.is_closed) is True - - @parametrize - async def test_path_params_retrieve_research(self, async_client: AsyncCasedev) -> None: - with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): - await async_client.search.v1.with_raw_response.retrieve_research( - id="", - ) - @parametrize async def test_method_search(self, async_client: AsyncCasedev) -> None: v1 = await async_client.search.v1.search( diff --git a/tests/api_resources/superdoc/__init__.py b/tests/api_resources/superdoc/__init__.py deleted file mode 100644 index fd8019a9..00000000 --- a/tests/api_resources/superdoc/__init__.py +++ /dev/null @@ -1 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. diff --git a/tests/api_resources/superdoc/test_v1.py b/tests/api_resources/superdoc/test_v1.py deleted file mode 100644 index 458417cb..00000000 --- a/tests/api_resources/superdoc/test_v1.py +++ /dev/null @@ -1,320 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from __future__ import annotations - -import os -from typing import Any, cast - -import httpx -import pytest -from respx import MockRouter - -from casedev import Casedev, AsyncCasedev -from casedev._response import ( - BinaryAPIResponse, - AsyncBinaryAPIResponse, - StreamedBinaryAPIResponse, - AsyncStreamedBinaryAPIResponse, -) - -base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") - - -class TestV1: - parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"]) - - @parametrize - @pytest.mark.respx(base_url=base_url) - def test_method_annotate(self, client: Casedev, respx_mock: MockRouter) -> None: - respx_mock.post("/superdoc/v1/annotate").mock(return_value=httpx.Response(200, json={"foo": "bar"})) - v1 = client.superdoc.v1.annotate( - document={}, - fields=[ - { - "type": "text", - "value": "string", - } - ], - ) - assert v1.is_closed - assert v1.json() == {"foo": "bar"} - assert cast(Any, v1.is_closed) is True - assert isinstance(v1, BinaryAPIResponse) - - @parametrize - @pytest.mark.respx(base_url=base_url) - def test_method_annotate_with_all_params(self, client: Casedev, respx_mock: MockRouter) -> None: - respx_mock.post("/superdoc/v1/annotate").mock(return_value=httpx.Response(200, json={"foo": "bar"})) - v1 = client.superdoc.v1.annotate( - document={ - "base64": "base64", - "url": "url", - }, - fields=[ - { - "type": "text", - "value": "string", - "id": "id", - "group": "group", - "options": { - "height": 0, - "width": 0, - }, - } - ], - output_format="docx", - ) - assert v1.is_closed - assert v1.json() == {"foo": "bar"} - assert cast(Any, v1.is_closed) is True - assert isinstance(v1, BinaryAPIResponse) - - @parametrize - @pytest.mark.respx(base_url=base_url) - def test_raw_response_annotate(self, client: Casedev, respx_mock: MockRouter) -> None: - respx_mock.post("/superdoc/v1/annotate").mock(return_value=httpx.Response(200, json={"foo": "bar"})) - - v1 = client.superdoc.v1.with_raw_response.annotate( - document={}, - fields=[ - { - "type": "text", - "value": "string", - } - ], - ) - - assert v1.is_closed is True - assert v1.http_request.headers.get("X-Stainless-Lang") == "python" - assert v1.json() == {"foo": "bar"} - assert isinstance(v1, BinaryAPIResponse) - - @parametrize - @pytest.mark.respx(base_url=base_url) - def test_streaming_response_annotate(self, client: Casedev, respx_mock: MockRouter) -> None: - respx_mock.post("/superdoc/v1/annotate").mock(return_value=httpx.Response(200, json={"foo": "bar"})) - with client.superdoc.v1.with_streaming_response.annotate( - document={}, - fields=[ - { - "type": "text", - "value": "string", - } - ], - ) as v1: - assert not v1.is_closed - assert v1.http_request.headers.get("X-Stainless-Lang") == "python" - - assert v1.json() == {"foo": "bar"} - assert cast(Any, v1.is_closed) is True - assert isinstance(v1, StreamedBinaryAPIResponse) - - assert cast(Any, v1.is_closed) is True - - @parametrize - @pytest.mark.respx(base_url=base_url) - def test_method_convert(self, client: Casedev, respx_mock: MockRouter) -> None: - respx_mock.post("/superdoc/v1/convert").mock(return_value=httpx.Response(200, json={"foo": "bar"})) - v1 = client.superdoc.v1.convert( - from_="docx", - ) - assert v1.is_closed - assert v1.json() == {"foo": "bar"} - assert cast(Any, v1.is_closed) is True - assert isinstance(v1, BinaryAPIResponse) - - @parametrize - @pytest.mark.respx(base_url=base_url) - def test_method_convert_with_all_params(self, client: Casedev, respx_mock: MockRouter) -> None: - respx_mock.post("/superdoc/v1/convert").mock(return_value=httpx.Response(200, json={"foo": "bar"})) - v1 = client.superdoc.v1.convert( - from_="docx", - document_base64="document_base64", - document_url="document_url", - to="pdf", - ) - assert v1.is_closed - assert v1.json() == {"foo": "bar"} - assert cast(Any, v1.is_closed) is True - assert isinstance(v1, BinaryAPIResponse) - - @parametrize - @pytest.mark.respx(base_url=base_url) - def test_raw_response_convert(self, client: Casedev, respx_mock: MockRouter) -> None: - respx_mock.post("/superdoc/v1/convert").mock(return_value=httpx.Response(200, json={"foo": "bar"})) - - v1 = client.superdoc.v1.with_raw_response.convert( - from_="docx", - ) - - assert v1.is_closed is True - assert v1.http_request.headers.get("X-Stainless-Lang") == "python" - assert v1.json() == {"foo": "bar"} - assert isinstance(v1, BinaryAPIResponse) - - @parametrize - @pytest.mark.respx(base_url=base_url) - def test_streaming_response_convert(self, client: Casedev, respx_mock: MockRouter) -> None: - respx_mock.post("/superdoc/v1/convert").mock(return_value=httpx.Response(200, json={"foo": "bar"})) - with client.superdoc.v1.with_streaming_response.convert( - from_="docx", - ) as v1: - assert not v1.is_closed - assert v1.http_request.headers.get("X-Stainless-Lang") == "python" - - assert v1.json() == {"foo": "bar"} - assert cast(Any, v1.is_closed) is True - assert isinstance(v1, StreamedBinaryAPIResponse) - - assert cast(Any, v1.is_closed) is True - - -class TestAsyncV1: - parametrize = pytest.mark.parametrize( - "async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"] - ) - - @parametrize - @pytest.mark.respx(base_url=base_url) - async def test_method_annotate(self, async_client: AsyncCasedev, respx_mock: MockRouter) -> None: - respx_mock.post("/superdoc/v1/annotate").mock(return_value=httpx.Response(200, json={"foo": "bar"})) - v1 = await async_client.superdoc.v1.annotate( - document={}, - fields=[ - { - "type": "text", - "value": "string", - } - ], - ) - assert v1.is_closed - assert await v1.json() == {"foo": "bar"} - assert cast(Any, v1.is_closed) is True - assert isinstance(v1, AsyncBinaryAPIResponse) - - @parametrize - @pytest.mark.respx(base_url=base_url) - async def test_method_annotate_with_all_params(self, async_client: AsyncCasedev, respx_mock: MockRouter) -> None: - respx_mock.post("/superdoc/v1/annotate").mock(return_value=httpx.Response(200, json={"foo": "bar"})) - v1 = await async_client.superdoc.v1.annotate( - document={ - "base64": "base64", - "url": "url", - }, - fields=[ - { - "type": "text", - "value": "string", - "id": "id", - "group": "group", - "options": { - "height": 0, - "width": 0, - }, - } - ], - output_format="docx", - ) - assert v1.is_closed - assert await v1.json() == {"foo": "bar"} - assert cast(Any, v1.is_closed) is True - assert isinstance(v1, AsyncBinaryAPIResponse) - - @parametrize - @pytest.mark.respx(base_url=base_url) - async def test_raw_response_annotate(self, async_client: AsyncCasedev, respx_mock: MockRouter) -> None: - respx_mock.post("/superdoc/v1/annotate").mock(return_value=httpx.Response(200, json={"foo": "bar"})) - - v1 = await async_client.superdoc.v1.with_raw_response.annotate( - document={}, - fields=[ - { - "type": "text", - "value": "string", - } - ], - ) - - assert v1.is_closed is True - assert v1.http_request.headers.get("X-Stainless-Lang") == "python" - assert await v1.json() == {"foo": "bar"} - assert isinstance(v1, AsyncBinaryAPIResponse) - - @parametrize - @pytest.mark.respx(base_url=base_url) - async def test_streaming_response_annotate(self, async_client: AsyncCasedev, respx_mock: MockRouter) -> None: - respx_mock.post("/superdoc/v1/annotate").mock(return_value=httpx.Response(200, json={"foo": "bar"})) - async with async_client.superdoc.v1.with_streaming_response.annotate( - document={}, - fields=[ - { - "type": "text", - "value": "string", - } - ], - ) as v1: - assert not v1.is_closed - assert v1.http_request.headers.get("X-Stainless-Lang") == "python" - - assert await v1.json() == {"foo": "bar"} - assert cast(Any, v1.is_closed) is True - assert isinstance(v1, AsyncStreamedBinaryAPIResponse) - - assert cast(Any, v1.is_closed) is True - - @parametrize - @pytest.mark.respx(base_url=base_url) - async def test_method_convert(self, async_client: AsyncCasedev, respx_mock: MockRouter) -> None: - respx_mock.post("/superdoc/v1/convert").mock(return_value=httpx.Response(200, json={"foo": "bar"})) - v1 = await async_client.superdoc.v1.convert( - from_="docx", - ) - assert v1.is_closed - assert await v1.json() == {"foo": "bar"} - assert cast(Any, v1.is_closed) is True - assert isinstance(v1, AsyncBinaryAPIResponse) - - @parametrize - @pytest.mark.respx(base_url=base_url) - async def test_method_convert_with_all_params(self, async_client: AsyncCasedev, respx_mock: MockRouter) -> None: - respx_mock.post("/superdoc/v1/convert").mock(return_value=httpx.Response(200, json={"foo": "bar"})) - v1 = await async_client.superdoc.v1.convert( - from_="docx", - document_base64="document_base64", - document_url="document_url", - to="pdf", - ) - assert v1.is_closed - assert await v1.json() == {"foo": "bar"} - assert cast(Any, v1.is_closed) is True - assert isinstance(v1, AsyncBinaryAPIResponse) - - @parametrize - @pytest.mark.respx(base_url=base_url) - async def test_raw_response_convert(self, async_client: AsyncCasedev, respx_mock: MockRouter) -> None: - respx_mock.post("/superdoc/v1/convert").mock(return_value=httpx.Response(200, json={"foo": "bar"})) - - v1 = await async_client.superdoc.v1.with_raw_response.convert( - from_="docx", - ) - - assert v1.is_closed is True - assert v1.http_request.headers.get("X-Stainless-Lang") == "python" - assert await v1.json() == {"foo": "bar"} - assert isinstance(v1, AsyncBinaryAPIResponse) - - @parametrize - @pytest.mark.respx(base_url=base_url) - async def test_streaming_response_convert(self, async_client: AsyncCasedev, respx_mock: MockRouter) -> None: - respx_mock.post("/superdoc/v1/convert").mock(return_value=httpx.Response(200, json={"foo": "bar"})) - async with async_client.superdoc.v1.with_streaming_response.convert( - from_="docx", - ) as v1: - assert not v1.is_closed - assert v1.http_request.headers.get("X-Stainless-Lang") == "python" - - assert await v1.json() == {"foo": "bar"} - assert cast(Any, v1.is_closed) is True - assert isinstance(v1, AsyncStreamedBinaryAPIResponse) - - assert cast(Any, v1.is_closed) is True diff --git a/tests/api_resources/test_vault.py b/tests/api_resources/test_vault.py index 79c54352..704c42b5 100644 --- a/tests/api_resources/test_vault.py +++ b/tests/api_resources/test_vault.py @@ -233,33 +233,33 @@ def test_path_params_delete(self, client: Casedev) -> None: ) @parametrize - def test_method_confirm_upload_overload_1(self, client: Casedev) -> None: + def test_method_confirm_upload(self, client: Casedev) -> None: vault = client.vault.confirm_upload( object_id="objectId", id="id", - size_bytes=1, success=True, ) assert_matches_type(VaultConfirmUploadResponse, vault, path=["response"]) @parametrize - def test_method_confirm_upload_with_all_params_overload_1(self, client: Casedev) -> None: + def test_method_confirm_upload_with_all_params(self, client: Casedev) -> None: vault = client.vault.confirm_upload( object_id="objectId", id="id", - size_bytes=1, success=True, auto_ingest=True, + error_code="errorCode", + error_message="errorMessage", etag="etag", + size_bytes=1, ) assert_matches_type(VaultConfirmUploadResponse, vault, path=["response"]) @parametrize - def test_raw_response_confirm_upload_overload_1(self, client: Casedev) -> None: + def test_raw_response_confirm_upload(self, client: Casedev) -> None: response = client.vault.with_raw_response.confirm_upload( object_id="objectId", id="id", - size_bytes=1, success=True, ) @@ -269,11 +269,10 @@ def test_raw_response_confirm_upload_overload_1(self, client: Casedev) -> None: assert_matches_type(VaultConfirmUploadResponse, vault, path=["response"]) @parametrize - def test_streaming_response_confirm_upload_overload_1(self, client: Casedev) -> None: + def test_streaming_response_confirm_upload(self, client: Casedev) -> None: with client.vault.with_streaming_response.confirm_upload( object_id="objectId", id="id", - size_bytes=1, success=True, ) as response: assert not response.is_closed @@ -285,12 +284,11 @@ def test_streaming_response_confirm_upload_overload_1(self, client: Casedev) -> assert cast(Any, response.is_closed) is True @parametrize - def test_path_params_confirm_upload_overload_1(self, client: Casedev) -> None: + def test_path_params_confirm_upload(self, client: Casedev) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): client.vault.with_raw_response.confirm_upload( object_id="objectId", id="", - size_bytes=1, success=True, ) @@ -298,73 +296,9 @@ def test_path_params_confirm_upload_overload_1(self, client: Casedev) -> None: client.vault.with_raw_response.confirm_upload( object_id="", id="id", - size_bytes=1, success=True, ) - @parametrize - def test_method_confirm_upload_overload_2(self, client: Casedev) -> None: - vault = client.vault.confirm_upload( - object_id="objectId", - id="id", - error_code="errorCode", - error_message="errorMessage", - success=False, - ) - assert_matches_type(VaultConfirmUploadResponse, vault, path=["response"]) - - @parametrize - def test_raw_response_confirm_upload_overload_2(self, client: Casedev) -> None: - response = client.vault.with_raw_response.confirm_upload( - object_id="objectId", - id="id", - error_code="errorCode", - error_message="errorMessage", - success=False, - ) - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - vault = response.parse() - assert_matches_type(VaultConfirmUploadResponse, vault, path=["response"]) - - @parametrize - def test_streaming_response_confirm_upload_overload_2(self, client: Casedev) -> None: - with client.vault.with_streaming_response.confirm_upload( - object_id="objectId", - id="id", - error_code="errorCode", - error_message="errorMessage", - success=False, - ) as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - vault = response.parse() - assert_matches_type(VaultConfirmUploadResponse, vault, path=["response"]) - - assert cast(Any, response.is_closed) is True - - @parametrize - def test_path_params_confirm_upload_overload_2(self, client: Casedev) -> None: - with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): - client.vault.with_raw_response.confirm_upload( - object_id="objectId", - id="", - error_code="errorCode", - error_message="errorMessage", - success=False, - ) - - with pytest.raises(ValueError, match=r"Expected a non-empty value for `object_id` but received ''"): - client.vault.with_raw_response.confirm_upload( - object_id="", - id="id", - error_code="errorCode", - error_message="errorMessage", - success=False, - ) - @parametrize def test_method_ingest(self, client: Casedev) -> None: vault = client.vault.ingest( @@ -486,6 +420,7 @@ def test_method_upload_with_all_params(self, client: Casedev) -> None: metadata={}, path="path", size_bytes=1, + idempotency_key="Idempotency-Key", ) assert_matches_type(VaultUploadResponse, vault, path=["response"]) @@ -738,33 +673,33 @@ async def test_path_params_delete(self, async_client: AsyncCasedev) -> None: ) @parametrize - async def test_method_confirm_upload_overload_1(self, async_client: AsyncCasedev) -> None: + async def test_method_confirm_upload(self, async_client: AsyncCasedev) -> None: vault = await async_client.vault.confirm_upload( object_id="objectId", id="id", - size_bytes=1, success=True, ) assert_matches_type(VaultConfirmUploadResponse, vault, path=["response"]) @parametrize - async def test_method_confirm_upload_with_all_params_overload_1(self, async_client: AsyncCasedev) -> None: + async def test_method_confirm_upload_with_all_params(self, async_client: AsyncCasedev) -> None: vault = await async_client.vault.confirm_upload( object_id="objectId", id="id", - size_bytes=1, success=True, auto_ingest=True, + error_code="errorCode", + error_message="errorMessage", etag="etag", + size_bytes=1, ) assert_matches_type(VaultConfirmUploadResponse, vault, path=["response"]) @parametrize - async def test_raw_response_confirm_upload_overload_1(self, async_client: AsyncCasedev) -> None: + async def test_raw_response_confirm_upload(self, async_client: AsyncCasedev) -> None: response = await async_client.vault.with_raw_response.confirm_upload( object_id="objectId", id="id", - size_bytes=1, success=True, ) @@ -774,11 +709,10 @@ async def test_raw_response_confirm_upload_overload_1(self, async_client: AsyncC assert_matches_type(VaultConfirmUploadResponse, vault, path=["response"]) @parametrize - async def test_streaming_response_confirm_upload_overload_1(self, async_client: AsyncCasedev) -> None: + async def test_streaming_response_confirm_upload(self, async_client: AsyncCasedev) -> None: async with async_client.vault.with_streaming_response.confirm_upload( object_id="objectId", id="id", - size_bytes=1, success=True, ) as response: assert not response.is_closed @@ -790,12 +724,11 @@ async def test_streaming_response_confirm_upload_overload_1(self, async_client: assert cast(Any, response.is_closed) is True @parametrize - async def test_path_params_confirm_upload_overload_1(self, async_client: AsyncCasedev) -> None: + async def test_path_params_confirm_upload(self, async_client: AsyncCasedev) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): await async_client.vault.with_raw_response.confirm_upload( object_id="objectId", id="", - size_bytes=1, success=True, ) @@ -803,73 +736,9 @@ async def test_path_params_confirm_upload_overload_1(self, async_client: AsyncCa await async_client.vault.with_raw_response.confirm_upload( object_id="", id="id", - size_bytes=1, success=True, ) - @parametrize - async def test_method_confirm_upload_overload_2(self, async_client: AsyncCasedev) -> None: - vault = await async_client.vault.confirm_upload( - object_id="objectId", - id="id", - error_code="errorCode", - error_message="errorMessage", - success=False, - ) - assert_matches_type(VaultConfirmUploadResponse, vault, path=["response"]) - - @parametrize - async def test_raw_response_confirm_upload_overload_2(self, async_client: AsyncCasedev) -> None: - response = await async_client.vault.with_raw_response.confirm_upload( - object_id="objectId", - id="id", - error_code="errorCode", - error_message="errorMessage", - success=False, - ) - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - vault = await response.parse() - assert_matches_type(VaultConfirmUploadResponse, vault, path=["response"]) - - @parametrize - async def test_streaming_response_confirm_upload_overload_2(self, async_client: AsyncCasedev) -> None: - async with async_client.vault.with_streaming_response.confirm_upload( - object_id="objectId", - id="id", - error_code="errorCode", - error_message="errorMessage", - success=False, - ) as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - vault = await response.parse() - assert_matches_type(VaultConfirmUploadResponse, vault, path=["response"]) - - assert cast(Any, response.is_closed) is True - - @parametrize - async def test_path_params_confirm_upload_overload_2(self, async_client: AsyncCasedev) -> None: - with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): - await async_client.vault.with_raw_response.confirm_upload( - object_id="objectId", - id="", - error_code="errorCode", - error_message="errorMessage", - success=False, - ) - - with pytest.raises(ValueError, match=r"Expected a non-empty value for `object_id` but received ''"): - await async_client.vault.with_raw_response.confirm_upload( - object_id="", - id="id", - error_code="errorCode", - error_message="errorMessage", - success=False, - ) - @parametrize async def test_method_ingest(self, async_client: AsyncCasedev) -> None: vault = await async_client.vault.ingest( @@ -991,6 +860,7 @@ async def test_method_upload_with_all_params(self, async_client: AsyncCasedev) - metadata={}, path="path", size_bytes=1, + idempotency_key="Idempotency-Key", ) assert_matches_type(VaultUploadResponse, vault, path=["response"]) diff --git a/tests/api_resources/translate/test_v1.py b/tests/api_resources/translate/test_v1.py index 3af69dc8..921b8c79 100644 --- a/tests/api_resources/translate/test_v1.py +++ b/tests/api_resources/translate/test_v1.py @@ -5,10 +5,18 @@ import os from typing import Any, cast +import httpx import pytest +from respx import MockRouter from casedev import Casedev, AsyncCasedev from tests.utils import assert_matches_type +from casedev._response import ( + BinaryAPIResponse, + AsyncBinaryAPIResponse, + StreamedBinaryAPIResponse, + AsyncStreamedBinaryAPIResponse, +) from casedev.types.translate import ( V1DetectResponse, V1TranslateResponse, @@ -130,6 +138,65 @@ def test_streaming_response_translate(self, client: Casedev) -> None: assert cast(Any, response.is_closed) is True + @parametrize + @pytest.mark.respx(base_url=base_url) + def test_method_translate_document(self, client: Casedev, respx_mock: MockRouter) -> None: + respx_mock.post("/translate/v1/document").mock(return_value=httpx.Response(200, json={"foo": "bar"})) + v1 = client.translate.v1.translate_document( + file=b"Example data", + target="es", + ) + assert v1.is_closed + assert v1.json() == {"foo": "bar"} + assert cast(Any, v1.is_closed) is True + assert isinstance(v1, BinaryAPIResponse) + + @parametrize + @pytest.mark.respx(base_url=base_url) + def test_method_translate_document_with_all_params(self, client: Casedev, respx_mock: MockRouter) -> None: + respx_mock.post("/translate/v1/document").mock(return_value=httpx.Response(200, json={"foo": "bar"})) + v1 = client.translate.v1.translate_document( + file=b"Example data", + target="es", + source="en", + ) + assert v1.is_closed + assert v1.json() == {"foo": "bar"} + assert cast(Any, v1.is_closed) is True + assert isinstance(v1, BinaryAPIResponse) + + @parametrize + @pytest.mark.respx(base_url=base_url) + def test_raw_response_translate_document(self, client: Casedev, respx_mock: MockRouter) -> None: + respx_mock.post("/translate/v1/document").mock(return_value=httpx.Response(200, json={"foo": "bar"})) + + v1 = client.translate.v1.with_raw_response.translate_document( + file=b"Example data", + target="es", + ) + + assert v1.is_closed is True + assert v1.http_request.headers.get("X-Stainless-Lang") == "python" + assert v1.json() == {"foo": "bar"} + assert isinstance(v1, BinaryAPIResponse) + + @parametrize + @pytest.mark.respx(base_url=base_url) + def test_streaming_response_translate_document(self, client: Casedev, respx_mock: MockRouter) -> None: + respx_mock.post("/translate/v1/document").mock(return_value=httpx.Response(200, json={"foo": "bar"})) + with client.translate.v1.with_streaming_response.translate_document( + file=b"Example data", + target="es", + ) as v1: + assert not v1.is_closed + assert v1.http_request.headers.get("X-Stainless-Lang") == "python" + + assert v1.json() == {"foo": "bar"} + assert cast(Any, v1.is_closed) is True + assert isinstance(v1, StreamedBinaryAPIResponse) + + assert cast(Any, v1.is_closed) is True + class TestAsyncV1: parametrize = pytest.mark.parametrize( @@ -244,3 +311,66 @@ async def test_streaming_response_translate(self, async_client: AsyncCasedev) -> assert_matches_type(V1TranslateResponse, v1, path=["response"]) assert cast(Any, response.is_closed) is True + + @parametrize + @pytest.mark.respx(base_url=base_url) + async def test_method_translate_document(self, async_client: AsyncCasedev, respx_mock: MockRouter) -> None: + respx_mock.post("/translate/v1/document").mock(return_value=httpx.Response(200, json={"foo": "bar"})) + v1 = await async_client.translate.v1.translate_document( + file=b"Example data", + target="es", + ) + assert v1.is_closed + assert await v1.json() == {"foo": "bar"} + assert cast(Any, v1.is_closed) is True + assert isinstance(v1, AsyncBinaryAPIResponse) + + @parametrize + @pytest.mark.respx(base_url=base_url) + async def test_method_translate_document_with_all_params( + self, async_client: AsyncCasedev, respx_mock: MockRouter + ) -> None: + respx_mock.post("/translate/v1/document").mock(return_value=httpx.Response(200, json={"foo": "bar"})) + v1 = await async_client.translate.v1.translate_document( + file=b"Example data", + target="es", + source="en", + ) + assert v1.is_closed + assert await v1.json() == {"foo": "bar"} + assert cast(Any, v1.is_closed) is True + assert isinstance(v1, AsyncBinaryAPIResponse) + + @parametrize + @pytest.mark.respx(base_url=base_url) + async def test_raw_response_translate_document(self, async_client: AsyncCasedev, respx_mock: MockRouter) -> None: + respx_mock.post("/translate/v1/document").mock(return_value=httpx.Response(200, json={"foo": "bar"})) + + v1 = await async_client.translate.v1.with_raw_response.translate_document( + file=b"Example data", + target="es", + ) + + assert v1.is_closed is True + assert v1.http_request.headers.get("X-Stainless-Lang") == "python" + assert await v1.json() == {"foo": "bar"} + assert isinstance(v1, AsyncBinaryAPIResponse) + + @parametrize + @pytest.mark.respx(base_url=base_url) + async def test_streaming_response_translate_document( + self, async_client: AsyncCasedev, respx_mock: MockRouter + ) -> None: + respx_mock.post("/translate/v1/document").mock(return_value=httpx.Response(200, json={"foo": "bar"})) + async with async_client.translate.v1.with_streaming_response.translate_document( + file=b"Example data", + target="es", + ) as v1: + assert not v1.is_closed + assert v1.http_request.headers.get("X-Stainless-Lang") == "python" + + assert await v1.json() == {"foo": "bar"} + assert cast(Any, v1.is_closed) is True + assert isinstance(v1, AsyncStreamedBinaryAPIResponse) + + assert cast(Any, v1.is_closed) is True diff --git a/tests/api_resources/vault/test_graphrag.py b/tests/api_resources/vault/test_graphrag.py deleted file mode 100644 index 7a36f4de..00000000 --- a/tests/api_resources/vault/test_graphrag.py +++ /dev/null @@ -1,272 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from __future__ import annotations - -import os -from typing import Any, cast - -import pytest - -from casedev import Casedev, AsyncCasedev -from tests.utils import assert_matches_type -from casedev.types.vault import GraphragInitResponse, GraphragGetStatsResponse, GraphragProcessObjectResponse - -base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") - - -class TestGraphrag: - parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"]) - - @parametrize - def test_method_get_stats(self, client: Casedev) -> None: - graphrag = client.vault.graphrag.get_stats( - "id", - ) - assert_matches_type(GraphragGetStatsResponse, graphrag, path=["response"]) - - @parametrize - def test_raw_response_get_stats(self, client: Casedev) -> None: - response = client.vault.graphrag.with_raw_response.get_stats( - "id", - ) - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - graphrag = response.parse() - assert_matches_type(GraphragGetStatsResponse, graphrag, path=["response"]) - - @parametrize - def test_streaming_response_get_stats(self, client: Casedev) -> None: - with client.vault.graphrag.with_streaming_response.get_stats( - "id", - ) as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - graphrag = response.parse() - assert_matches_type(GraphragGetStatsResponse, graphrag, path=["response"]) - - assert cast(Any, response.is_closed) is True - - @parametrize - def test_path_params_get_stats(self, client: Casedev) -> None: - with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): - client.vault.graphrag.with_raw_response.get_stats( - "", - ) - - @parametrize - def test_method_init(self, client: Casedev) -> None: - graphrag = client.vault.graphrag.init( - "id", - ) - assert_matches_type(GraphragInitResponse, graphrag, path=["response"]) - - @parametrize - def test_raw_response_init(self, client: Casedev) -> None: - response = client.vault.graphrag.with_raw_response.init( - "id", - ) - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - graphrag = response.parse() - assert_matches_type(GraphragInitResponse, graphrag, path=["response"]) - - @parametrize - def test_streaming_response_init(self, client: Casedev) -> None: - with client.vault.graphrag.with_streaming_response.init( - "id", - ) as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - graphrag = response.parse() - assert_matches_type(GraphragInitResponse, graphrag, path=["response"]) - - assert cast(Any, response.is_closed) is True - - @parametrize - def test_path_params_init(self, client: Casedev) -> None: - with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): - client.vault.graphrag.with_raw_response.init( - "", - ) - - @parametrize - def test_method_process_object(self, client: Casedev) -> None: - graphrag = client.vault.graphrag.process_object( - object_id="objectId", - id="id", - ) - assert_matches_type(GraphragProcessObjectResponse, graphrag, path=["response"]) - - @parametrize - def test_raw_response_process_object(self, client: Casedev) -> None: - response = client.vault.graphrag.with_raw_response.process_object( - object_id="objectId", - id="id", - ) - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - graphrag = response.parse() - assert_matches_type(GraphragProcessObjectResponse, graphrag, path=["response"]) - - @parametrize - def test_streaming_response_process_object(self, client: Casedev) -> None: - with client.vault.graphrag.with_streaming_response.process_object( - object_id="objectId", - id="id", - ) as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - graphrag = response.parse() - assert_matches_type(GraphragProcessObjectResponse, graphrag, path=["response"]) - - assert cast(Any, response.is_closed) is True - - @parametrize - def test_path_params_process_object(self, client: Casedev) -> None: - with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): - client.vault.graphrag.with_raw_response.process_object( - object_id="objectId", - id="", - ) - - with pytest.raises(ValueError, match=r"Expected a non-empty value for `object_id` but received ''"): - client.vault.graphrag.with_raw_response.process_object( - object_id="", - id="id", - ) - - -class TestAsyncGraphrag: - parametrize = pytest.mark.parametrize( - "async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"] - ) - - @parametrize - async def test_method_get_stats(self, async_client: AsyncCasedev) -> None: - graphrag = await async_client.vault.graphrag.get_stats( - "id", - ) - assert_matches_type(GraphragGetStatsResponse, graphrag, path=["response"]) - - @parametrize - async def test_raw_response_get_stats(self, async_client: AsyncCasedev) -> None: - response = await async_client.vault.graphrag.with_raw_response.get_stats( - "id", - ) - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - graphrag = await response.parse() - assert_matches_type(GraphragGetStatsResponse, graphrag, path=["response"]) - - @parametrize - async def test_streaming_response_get_stats(self, async_client: AsyncCasedev) -> None: - async with async_client.vault.graphrag.with_streaming_response.get_stats( - "id", - ) as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - graphrag = await response.parse() - assert_matches_type(GraphragGetStatsResponse, graphrag, path=["response"]) - - assert cast(Any, response.is_closed) is True - - @parametrize - async def test_path_params_get_stats(self, async_client: AsyncCasedev) -> None: - with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): - await async_client.vault.graphrag.with_raw_response.get_stats( - "", - ) - - @parametrize - async def test_method_init(self, async_client: AsyncCasedev) -> None: - graphrag = await async_client.vault.graphrag.init( - "id", - ) - assert_matches_type(GraphragInitResponse, graphrag, path=["response"]) - - @parametrize - async def test_raw_response_init(self, async_client: AsyncCasedev) -> None: - response = await async_client.vault.graphrag.with_raw_response.init( - "id", - ) - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - graphrag = await response.parse() - assert_matches_type(GraphragInitResponse, graphrag, path=["response"]) - - @parametrize - async def test_streaming_response_init(self, async_client: AsyncCasedev) -> None: - async with async_client.vault.graphrag.with_streaming_response.init( - "id", - ) as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - graphrag = await response.parse() - assert_matches_type(GraphragInitResponse, graphrag, path=["response"]) - - assert cast(Any, response.is_closed) is True - - @parametrize - async def test_path_params_init(self, async_client: AsyncCasedev) -> None: - with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): - await async_client.vault.graphrag.with_raw_response.init( - "", - ) - - @parametrize - async def test_method_process_object(self, async_client: AsyncCasedev) -> None: - graphrag = await async_client.vault.graphrag.process_object( - object_id="objectId", - id="id", - ) - assert_matches_type(GraphragProcessObjectResponse, graphrag, path=["response"]) - - @parametrize - async def test_raw_response_process_object(self, async_client: AsyncCasedev) -> None: - response = await async_client.vault.graphrag.with_raw_response.process_object( - object_id="objectId", - id="id", - ) - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - graphrag = await response.parse() - assert_matches_type(GraphragProcessObjectResponse, graphrag, path=["response"]) - - @parametrize - async def test_streaming_response_process_object(self, async_client: AsyncCasedev) -> None: - async with async_client.vault.graphrag.with_streaming_response.process_object( - object_id="objectId", - id="id", - ) as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - graphrag = await response.parse() - assert_matches_type(GraphragProcessObjectResponse, graphrag, path=["response"]) - - assert cast(Any, response.is_closed) is True - - @parametrize - async def test_path_params_process_object(self, async_client: AsyncCasedev) -> None: - with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): - await async_client.vault.graphrag.with_raw_response.process_object( - object_id="objectId", - id="", - ) - - with pytest.raises(ValueError, match=r"Expected a non-empty value for `object_id` but received ''"): - await async_client.vault.graphrag.with_raw_response.process_object( - object_id="", - id="id", - ) diff --git a/tests/api_resources/vault/test_objects.py b/tests/api_resources/vault/test_objects.py index aef6d4e7..d47f7070 100644 --- a/tests/api_resources/vault/test_objects.py +++ b/tests/api_resources/vault/test_objects.py @@ -19,6 +19,7 @@ ) from casedev.types.vault import ( ObjectListResponse, + ObjectMergeResponse, ObjectAppendResponse, ObjectDeleteResponse, ObjectUpdateResponse, @@ -26,9 +27,7 @@ ObjectGetPagesResponse, ObjectRetrieveResponse, ObjectGetChunksResponse, - ObjectSummarizeResponse, ObjectGetOcrWordsResponse, - ObjectGetSummarizeJobResponse, ObjectCreatePresignedURLResponse, ) @@ -265,6 +264,13 @@ def test_method_append_with_all_params(self, client: Casedev) -> None: append_object_ids=["string"], back_links=True, back_links_text="backLinksText", + bates={ + "enabled": True, + "pad_to": 0, + "prefix": "prefix", + "start": 1, + "suffix": "suffix", + }, rewrite_links=True, ) assert_matches_type(ObjectAppendResponse, object_, path=["response"]) @@ -614,66 +620,6 @@ def test_path_params_get_pages(self, client: Casedev) -> None: id="id", ) - @parametrize - def test_method_get_summarize_job(self, client: Casedev) -> None: - object_ = client.vault.objects.get_summarize_job( - job_id="jobId", - id="id", - object_id="objectId", - ) - assert_matches_type(ObjectGetSummarizeJobResponse, object_, path=["response"]) - - @parametrize - def test_raw_response_get_summarize_job(self, client: Casedev) -> None: - response = client.vault.objects.with_raw_response.get_summarize_job( - job_id="jobId", - id="id", - object_id="objectId", - ) - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - object_ = response.parse() - assert_matches_type(ObjectGetSummarizeJobResponse, object_, path=["response"]) - - @parametrize - def test_streaming_response_get_summarize_job(self, client: Casedev) -> None: - with client.vault.objects.with_streaming_response.get_summarize_job( - job_id="jobId", - id="id", - object_id="objectId", - ) as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - object_ = response.parse() - assert_matches_type(ObjectGetSummarizeJobResponse, object_, path=["response"]) - - assert cast(Any, response.is_closed) is True - - @parametrize - def test_path_params_get_summarize_job(self, client: Casedev) -> None: - with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): - client.vault.objects.with_raw_response.get_summarize_job( - job_id="jobId", - id="", - object_id="objectId", - ) - - with pytest.raises(ValueError, match=r"Expected a non-empty value for `object_id` but received ''"): - client.vault.objects.with_raw_response.get_summarize_job( - job_id="jobId", - id="id", - object_id="", - ) - - with pytest.raises(ValueError, match=r"Expected a non-empty value for `job_id` but received ''"): - client.vault.objects.with_raw_response.get_summarize_job( - job_id="", - id="id", - object_id="objectId", - ) - @parametrize def test_method_get_text(self, client: Casedev) -> None: object_ = client.vault.objects.get_text( @@ -723,61 +669,75 @@ def test_path_params_get_text(self, client: Casedev) -> None: ) @parametrize - def test_method_summarize(self, client: Casedev) -> None: - object_ = client.vault.objects.summarize( - object_id="objectId", + def test_method_merge(self, client: Casedev) -> None: + object_ = client.vault.objects.merge( id="id", + filename="filename", + source_object_ids=["string"], + source_rendition="original", + idempotency_key="x", ) - assert_matches_type(ObjectSummarizeResponse, object_, path=["response"]) + assert_matches_type(ObjectMergeResponse, object_, path=["response"]) @parametrize - def test_method_summarize_with_all_params(self, client: Casedev) -> None: - object_ = client.vault.objects.summarize( - object_id="objectId", + def test_method_merge_with_all_params(self, client: Casedev) -> None: + object_ = client.vault.objects.merge( id="id", - output_format="PDF", - workflow_type="workflowType", + filename="filename", + source_object_ids=["string"], + source_rendition="original", + idempotency_key="x", + bates={ + "pad_to": 0, + "prefix": "prefix", + "start": 1, + "suffix": "suffix", + }, + client_reference="clientReference", ) - assert_matches_type(ObjectSummarizeResponse, object_, path=["response"]) + assert_matches_type(ObjectMergeResponse, object_, path=["response"]) @parametrize - def test_raw_response_summarize(self, client: Casedev) -> None: - response = client.vault.objects.with_raw_response.summarize( - object_id="objectId", + def test_raw_response_merge(self, client: Casedev) -> None: + response = client.vault.objects.with_raw_response.merge( id="id", + filename="filename", + source_object_ids=["string"], + source_rendition="original", + idempotency_key="x", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" object_ = response.parse() - assert_matches_type(ObjectSummarizeResponse, object_, path=["response"]) + assert_matches_type(ObjectMergeResponse, object_, path=["response"]) @parametrize - def test_streaming_response_summarize(self, client: Casedev) -> None: - with client.vault.objects.with_streaming_response.summarize( - object_id="objectId", + def test_streaming_response_merge(self, client: Casedev) -> None: + with client.vault.objects.with_streaming_response.merge( id="id", + filename="filename", + source_object_ids=["string"], + source_rendition="original", + idempotency_key="x", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" object_ = response.parse() - assert_matches_type(ObjectSummarizeResponse, object_, path=["response"]) + assert_matches_type(ObjectMergeResponse, object_, path=["response"]) assert cast(Any, response.is_closed) is True @parametrize - def test_path_params_summarize(self, client: Casedev) -> None: + def test_path_params_merge(self, client: Casedev) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): - client.vault.objects.with_raw_response.summarize( - object_id="objectId", + client.vault.objects.with_raw_response.merge( id="", - ) - - with pytest.raises(ValueError, match=r"Expected a non-empty value for `object_id` but received ''"): - client.vault.objects.with_raw_response.summarize( - object_id="", - id="id", + filename="filename", + source_object_ids=["string"], + source_rendition="original", + idempotency_key="x", ) @@ -1013,6 +973,13 @@ async def test_method_append_with_all_params(self, async_client: AsyncCasedev) - append_object_ids=["string"], back_links=True, back_links_text="backLinksText", + bates={ + "enabled": True, + "pad_to": 0, + "prefix": "prefix", + "start": 1, + "suffix": "suffix", + }, rewrite_links=True, ) assert_matches_type(ObjectAppendResponse, object_, path=["response"]) @@ -1362,66 +1329,6 @@ async def test_path_params_get_pages(self, async_client: AsyncCasedev) -> None: id="id", ) - @parametrize - async def test_method_get_summarize_job(self, async_client: AsyncCasedev) -> None: - object_ = await async_client.vault.objects.get_summarize_job( - job_id="jobId", - id="id", - object_id="objectId", - ) - assert_matches_type(ObjectGetSummarizeJobResponse, object_, path=["response"]) - - @parametrize - async def test_raw_response_get_summarize_job(self, async_client: AsyncCasedev) -> None: - response = await async_client.vault.objects.with_raw_response.get_summarize_job( - job_id="jobId", - id="id", - object_id="objectId", - ) - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - object_ = await response.parse() - assert_matches_type(ObjectGetSummarizeJobResponse, object_, path=["response"]) - - @parametrize - async def test_streaming_response_get_summarize_job(self, async_client: AsyncCasedev) -> None: - async with async_client.vault.objects.with_streaming_response.get_summarize_job( - job_id="jobId", - id="id", - object_id="objectId", - ) as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - object_ = await response.parse() - assert_matches_type(ObjectGetSummarizeJobResponse, object_, path=["response"]) - - assert cast(Any, response.is_closed) is True - - @parametrize - async def test_path_params_get_summarize_job(self, async_client: AsyncCasedev) -> None: - with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): - await async_client.vault.objects.with_raw_response.get_summarize_job( - job_id="jobId", - id="", - object_id="objectId", - ) - - with pytest.raises(ValueError, match=r"Expected a non-empty value for `object_id` but received ''"): - await async_client.vault.objects.with_raw_response.get_summarize_job( - job_id="jobId", - id="id", - object_id="", - ) - - with pytest.raises(ValueError, match=r"Expected a non-empty value for `job_id` but received ''"): - await async_client.vault.objects.with_raw_response.get_summarize_job( - job_id="", - id="id", - object_id="objectId", - ) - @parametrize async def test_method_get_text(self, async_client: AsyncCasedev) -> None: object_ = await async_client.vault.objects.get_text( @@ -1471,59 +1378,73 @@ async def test_path_params_get_text(self, async_client: AsyncCasedev) -> None: ) @parametrize - async def test_method_summarize(self, async_client: AsyncCasedev) -> None: - object_ = await async_client.vault.objects.summarize( - object_id="objectId", + async def test_method_merge(self, async_client: AsyncCasedev) -> None: + object_ = await async_client.vault.objects.merge( id="id", + filename="filename", + source_object_ids=["string"], + source_rendition="original", + idempotency_key="x", ) - assert_matches_type(ObjectSummarizeResponse, object_, path=["response"]) + assert_matches_type(ObjectMergeResponse, object_, path=["response"]) @parametrize - async def test_method_summarize_with_all_params(self, async_client: AsyncCasedev) -> None: - object_ = await async_client.vault.objects.summarize( - object_id="objectId", + async def test_method_merge_with_all_params(self, async_client: AsyncCasedev) -> None: + object_ = await async_client.vault.objects.merge( id="id", - output_format="PDF", - workflow_type="workflowType", + filename="filename", + source_object_ids=["string"], + source_rendition="original", + idempotency_key="x", + bates={ + "pad_to": 0, + "prefix": "prefix", + "start": 1, + "suffix": "suffix", + }, + client_reference="clientReference", ) - assert_matches_type(ObjectSummarizeResponse, object_, path=["response"]) + assert_matches_type(ObjectMergeResponse, object_, path=["response"]) @parametrize - async def test_raw_response_summarize(self, async_client: AsyncCasedev) -> None: - response = await async_client.vault.objects.with_raw_response.summarize( - object_id="objectId", + async def test_raw_response_merge(self, async_client: AsyncCasedev) -> None: + response = await async_client.vault.objects.with_raw_response.merge( id="id", + filename="filename", + source_object_ids=["string"], + source_rendition="original", + idempotency_key="x", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" object_ = await response.parse() - assert_matches_type(ObjectSummarizeResponse, object_, path=["response"]) + assert_matches_type(ObjectMergeResponse, object_, path=["response"]) @parametrize - async def test_streaming_response_summarize(self, async_client: AsyncCasedev) -> None: - async with async_client.vault.objects.with_streaming_response.summarize( - object_id="objectId", + async def test_streaming_response_merge(self, async_client: AsyncCasedev) -> None: + async with async_client.vault.objects.with_streaming_response.merge( id="id", + filename="filename", + source_object_ids=["string"], + source_rendition="original", + idempotency_key="x", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" object_ = await response.parse() - assert_matches_type(ObjectSummarizeResponse, object_, path=["response"]) + assert_matches_type(ObjectMergeResponse, object_, path=["response"]) assert cast(Any, response.is_closed) is True @parametrize - async def test_path_params_summarize(self, async_client: AsyncCasedev) -> None: + async def test_path_params_merge(self, async_client: AsyncCasedev) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): - await async_client.vault.objects.with_raw_response.summarize( - object_id="objectId", + await async_client.vault.objects.with_raw_response.merge( id="", - ) - - with pytest.raises(ValueError, match=r"Expected a non-empty value for `object_id` but received ''"): - await async_client.vault.objects.with_raw_response.summarize( - object_id="", - id="id", + filename="filename", + source_object_ids=["string"], + source_rendition="original", + idempotency_key="x", )