From b5da506b1ea89e26f37b6c32c63422177ee53bbf Mon Sep 17 00:00:00 2001 From: njbrake <33383515+njbrake@users.noreply.github.com> Date: Fri, 21 Aug 2026 22:09:09 +0000 Subject: [PATCH] chore: regenerate SDK client core from Otari OpenAPI spec --- sdk-endpoints.txt | 23 + src/otari/_client/__init__.py | 34 + src/otari/_client/api/__init__.py | 2 + src/otari/_client/api/auth_api.py | 1571 ++++++++++++++++- src/otari/_client/api/budgets_api.py | 6 +- src/otari/_client/api/mcp_servers_api.py | 1223 +++++++++++++ src/otari/_client/api/scoped_budgets_api.py | 6 +- .../workspace_code_execution_policy_api.py | 860 +++++++++ src/otari/_client/models/__init__.py | 15 + .../active_organization_member_public.py | 2 +- src/otari/_client/models/budget_response.py | 9 +- .../_client/models/chat_completion_request.py | 2 +- .../_client/models/create_budget_request.py | 25 +- .../models/create_scoped_budget_request.py | 39 +- src/otari/_client/models/messages_request.py | 2 +- .../models/request_password_reset_request.py | 89 + .../models/request_password_reset_response.py | 88 + .../models/resend_verification_request.py | 89 + .../models/resend_verification_response.py | 88 + .../_client/models/reset_password_request.py | 91 + src/otari/_client/models/responses_request.py | 2 +- .../_client/models/scoped_budget_response.py | 6 +- src/otari/_client/models/signup_request.py | 100 ++ src/otari/_client/models/signup_response.py | 88 + .../_client/models/update_budget_request.py | 25 +- .../models/update_scoped_budget_request.py | 42 +- .../_client/models/verify_email_request.py | 89 + .../_client/models/verify_email_response.py | 88 + .../workspace_code_execution_policy_public.py | 130 ++ .../workspace_code_execution_policy_update.py | 110 ++ .../models/workspace_mcp_server_create.py | 114 ++ .../models/workspace_mcp_server_public.py | 117 ++ .../models/workspace_mcp_server_update.py | 114 ++ .../models/workspace_mcp_servers_public.py | 98 + .../workspace_member_budget_policy_create.py | 27 +- .../workspace_member_budget_policy_public.py | 4 +- .../workspace_member_budget_policy_update.py | 29 +- 37 files changed, 5220 insertions(+), 227 deletions(-) create mode 100644 src/otari/_client/api/mcp_servers_api.py create mode 100644 src/otari/_client/api/workspace_code_execution_policy_api.py create mode 100644 src/otari/_client/models/request_password_reset_request.py create mode 100644 src/otari/_client/models/request_password_reset_response.py create mode 100644 src/otari/_client/models/resend_verification_request.py create mode 100644 src/otari/_client/models/resend_verification_response.py create mode 100644 src/otari/_client/models/reset_password_request.py create mode 100644 src/otari/_client/models/signup_request.py create mode 100644 src/otari/_client/models/signup_response.py create mode 100644 src/otari/_client/models/verify_email_request.py create mode 100644 src/otari/_client/models/verify_email_response.py create mode 100644 src/otari/_client/models/workspace_code_execution_policy_public.py create mode 100644 src/otari/_client/models/workspace_code_execution_policy_update.py create mode 100644 src/otari/_client/models/workspace_mcp_server_create.py create mode 100644 src/otari/_client/models/workspace_mcp_server_public.py create mode 100644 src/otari/_client/models/workspace_mcp_server_update.py create mode 100644 src/otari/_client/models/workspace_mcp_servers_public.py diff --git a/sdk-endpoints.txt b/sdk-endpoints.txt index f05f0a1..d131bd0 100644 --- a/sdk-endpoints.txt +++ b/sdk-endpoints.txt @@ -118,6 +118,14 @@ DELETE /v1/auth/session # dashboard-only # flow. An SDK authenticates with the master key or an API key and never holds # a password, so there is nothing here for one to wrap. PUT /v1/auth/password # dashboard-only +# Signup, email verification, and password reset (otari#650): claiming a +# roster identity's dashboard login and recovering it, the same browser-only +# credential flow PUT /v1/auth/password is. No SDK caller holds a password. +POST /v1/auth/signup # dashboard-only +POST /v1/auth/verify-email # dashboard-only +POST /v1/auth/resend-verification # dashboard-only +POST /v1/auth/password/reset # dashboard-only +POST /v1/auth/password/reset/confirm # dashboard-only # OTLP ingest: OpenTelemetry collector receivers, not an SDK surface. POST /v1/logs # otel ingest POST /v1/traces # otel ingest @@ -214,6 +222,13 @@ DELETE /v1/workspaces/{workspace_id}/member-budget-policies/{default_id} # dashb GET /v1/workspaces/{workspace_id}/activation # dashboard-only POST /v1/workspaces/{workspace_id}/activation/key # dashboard-only POST /v1/workspaces/{workspace_id}/activation/dismiss # dashboard-only +# The workspace's code-execution policy (otari#657) is set by whoever administers +# the workspace, not by the key-holder running code inside it, so it is the same +# dashboard-side surface as the rows above. An SDK caller sees its effect on +# `otari_code_execution` (a 403, a lower iteration ceiling), never the policy row. +GET /v1/workspaces/{workspace_id}/code-execution-policy # dashboard-only +PUT /v1/workspaces/{workspace_id}/code-execution-policy # dashboard-only +DELETE /v1/workspaces/{workspace_id}/code-execution-policy # dashboard-only # Organization-scoped provider keys (otari-ai#1748, otari#643): the same # tenancy-admin surface as the organization/workspace rows just above, and # excluded for the same reason. An SDK caller acts inside one workspace with a @@ -232,3 +247,11 @@ DELETE /v1/workspaces/{workspace_id}/provider-keys/{key_id} # dash GET /v1/workspaces/{workspace_id}/provider-keys/{key_id}/models # dashboard-only POST /v1/workspaces/{workspace_id}/provider-keys/{key_id}/models # dashboard-only DELETE /v1/workspaces/{workspace_id}/provider-keys/{key_id}/models/{model} # dashboard-only +# Workspace-scoped MCP servers (otari#658): a master-key operator surface for +# registering the endpoints a workspace's requests may reach, alongside the +# tenancy admin rows above. An SDK caller does not manage these; it names them +# by id in `mcp_server_ids` on a completion request, which is already covered. +GET /v1/workspaces/{workspace_id}/mcp-servers # operator surface +POST /v1/workspaces/{workspace_id}/mcp-servers # operator surface +PATCH /v1/workspaces/{workspace_id}/mcp-servers/{server_id} # operator surface +DELETE /v1/workspaces/{workspace_id}/mcp-servers/{server_id} # operator surface diff --git a/src/otari/_client/__init__.py b/src/otari/_client/__init__.py index ccd145f..bd3ef9a 100644 --- a/src/otari/_client/__init__.py +++ b/src/otari/_client/__init__.py @@ -32,6 +32,7 @@ "ImagesApi", "InvitationsApi", "KeysApi", + "McpServersApi", "MessagesApi", "ModelsApi", "ModerationsApi", @@ -53,6 +54,7 @@ "UsageApi", "UsersApi", "WorkspaceActivationApi", + "WorkspaceCodeExecutionPolicyApi", "WorkspaceMemberBudgetPoliciesApi", "WorkspacesApi", "ApiResponse", @@ -374,8 +376,13 @@ "RecordedPool", "ReencryptProviderCredentialsResponse", "ReencryptSearchToolsResponse", + "RequestPasswordResetRequest", + "RequestPasswordResetResponse", "RerankRequest", "RerankResponse", + "ResendVerificationRequest", + "ResendVerificationResponse", + "ResetPasswordRequest", "ResponsesRequest", "RotateMasterKeyResponse", "RouterStatus", @@ -391,6 +398,8 @@ "SessionResponse", "SetPasswordRequest", "SetPricingRequest", + "SignupRequest", + "SignupResponse", "Source", "Source1", "Stop", @@ -443,9 +452,17 @@ "ValidationError", "Value", "Value1", + "VerifyEmailRequest", + "VerifyEmailResponse", "WorkspaceActivationPublic", "WorkspaceAssignmentRequest", + "WorkspaceCodeExecutionPolicyPublic", + "WorkspaceCodeExecutionPolicyUpdate", "WorkspaceCreate", + "WorkspaceMcpServerCreate", + "WorkspaceMcpServerPublic", + "WorkspaceMcpServerUpdate", + "WorkspaceMcpServersPublic", "WorkspaceMemberBudgetPoliciesPublic", "WorkspaceMemberBudgetPolicyCreate", "WorkspaceMemberBudgetPolicyPublic", @@ -477,6 +494,7 @@ from otari._client.api.images_api import ImagesApi as ImagesApi from otari._client.api.invitations_api import InvitationsApi as InvitationsApi from otari._client.api.keys_api import KeysApi as KeysApi +from otari._client.api.mcp_servers_api import McpServersApi as McpServersApi from otari._client.api.messages_api import MessagesApi as MessagesApi from otari._client.api.models_api import ModelsApi as ModelsApi from otari._client.api.moderations_api import ModerationsApi as ModerationsApi @@ -498,6 +516,7 @@ from otari._client.api.usage_api import UsageApi as UsageApi from otari._client.api.users_api import UsersApi as UsersApi from otari._client.api.workspace_activation_api import WorkspaceActivationApi as WorkspaceActivationApi +from otari._client.api.workspace_code_execution_policy_api import WorkspaceCodeExecutionPolicyApi as WorkspaceCodeExecutionPolicyApi from otari._client.api.workspace_member_budget_policies_api import WorkspaceMemberBudgetPoliciesApi as WorkspaceMemberBudgetPoliciesApi from otari._client.api.workspaces_api import WorkspacesApi as WorkspacesApi @@ -823,8 +842,13 @@ from otari._client.models.recorded_pool import RecordedPool as RecordedPool from otari._client.models.reencrypt_provider_credentials_response import ReencryptProviderCredentialsResponse as ReencryptProviderCredentialsResponse from otari._client.models.reencrypt_search_tools_response import ReencryptSearchToolsResponse as ReencryptSearchToolsResponse +from otari._client.models.request_password_reset_request import RequestPasswordResetRequest as RequestPasswordResetRequest +from otari._client.models.request_password_reset_response import RequestPasswordResetResponse as RequestPasswordResetResponse from otari._client.models.rerank_request import RerankRequest as RerankRequest from otari._client.models.rerank_response import RerankResponse as RerankResponse +from otari._client.models.resend_verification_request import ResendVerificationRequest as ResendVerificationRequest +from otari._client.models.resend_verification_response import ResendVerificationResponse as ResendVerificationResponse +from otari._client.models.reset_password_request import ResetPasswordRequest as ResetPasswordRequest from otari._client.models.responses_request import ResponsesRequest as ResponsesRequest from otari._client.models.rotate_master_key_response import RotateMasterKeyResponse as RotateMasterKeyResponse from otari._client.models.router_status import RouterStatus as RouterStatus @@ -840,6 +864,8 @@ from otari._client.models.session_response import SessionResponse as SessionResponse from otari._client.models.set_password_request import SetPasswordRequest as SetPasswordRequest from otari._client.models.set_pricing_request import SetPricingRequest as SetPricingRequest +from otari._client.models.signup_request import SignupRequest as SignupRequest +from otari._client.models.signup_response import SignupResponse as SignupResponse from otari._client.models.source import Source as Source from otari._client.models.source1 import Source1 as Source1 from otari._client.models.stop import Stop as Stop @@ -892,9 +918,17 @@ from otari._client.models.validation_error import ValidationError as ValidationError from otari._client.models.value import Value as Value from otari._client.models.value1 import Value1 as Value1 +from otari._client.models.verify_email_request import VerifyEmailRequest as VerifyEmailRequest +from otari._client.models.verify_email_response import VerifyEmailResponse as VerifyEmailResponse from otari._client.models.workspace_activation_public import WorkspaceActivationPublic as WorkspaceActivationPublic from otari._client.models.workspace_assignment_request import WorkspaceAssignmentRequest as WorkspaceAssignmentRequest +from otari._client.models.workspace_code_execution_policy_public import WorkspaceCodeExecutionPolicyPublic as WorkspaceCodeExecutionPolicyPublic +from otari._client.models.workspace_code_execution_policy_update import WorkspaceCodeExecutionPolicyUpdate as WorkspaceCodeExecutionPolicyUpdate from otari._client.models.workspace_create import WorkspaceCreate as WorkspaceCreate +from otari._client.models.workspace_mcp_server_create import WorkspaceMcpServerCreate as WorkspaceMcpServerCreate +from otari._client.models.workspace_mcp_server_public import WorkspaceMcpServerPublic as WorkspaceMcpServerPublic +from otari._client.models.workspace_mcp_server_update import WorkspaceMcpServerUpdate as WorkspaceMcpServerUpdate +from otari._client.models.workspace_mcp_servers_public import WorkspaceMcpServersPublic as WorkspaceMcpServersPublic from otari._client.models.workspace_member_budget_policies_public import WorkspaceMemberBudgetPoliciesPublic as WorkspaceMemberBudgetPoliciesPublic from otari._client.models.workspace_member_budget_policy_create import WorkspaceMemberBudgetPolicyCreate as WorkspaceMemberBudgetPolicyCreate from otari._client.models.workspace_member_budget_policy_public import WorkspaceMemberBudgetPolicyPublic as WorkspaceMemberBudgetPolicyPublic diff --git a/src/otari/_client/api/__init__.py b/src/otari/_client/api/__init__.py index a4199f7..6bd9078 100644 --- a/src/otari/_client/api/__init__.py +++ b/src/otari/_client/api/__init__.py @@ -15,6 +15,7 @@ from otari._client.api.images_api import ImagesApi from otari._client.api.invitations_api import InvitationsApi from otari._client.api.keys_api import KeysApi +from otari._client.api.mcp_servers_api import McpServersApi from otari._client.api.messages_api import MessagesApi from otari._client.api.models_api import ModelsApi from otari._client.api.moderations_api import ModerationsApi @@ -36,6 +37,7 @@ from otari._client.api.usage_api import UsageApi from otari._client.api.users_api import UsersApi from otari._client.api.workspace_activation_api import WorkspaceActivationApi +from otari._client.api.workspace_code_execution_policy_api import WorkspaceCodeExecutionPolicyApi from otari._client.api.workspace_member_budget_policies_api import WorkspaceMemberBudgetPoliciesApi from otari._client.api.workspaces_api import WorkspacesApi diff --git a/src/otari/_client/api/auth_api.py b/src/otari/_client/api/auth_api.py index f60ad0d..e638fea 100644 --- a/src/otari/_client/api/auth_api.py +++ b/src/otari/_client/api/auth_api.py @@ -17,8 +17,17 @@ from otari._client.models.create_session_request import CreateSessionRequest from otari._client.models.password_response import PasswordResponse +from otari._client.models.request_password_reset_request import RequestPasswordResetRequest +from otari._client.models.request_password_reset_response import RequestPasswordResetResponse +from otari._client.models.resend_verification_request import ResendVerificationRequest +from otari._client.models.resend_verification_response import ResendVerificationResponse +from otari._client.models.reset_password_request import ResetPasswordRequest from otari._client.models.session_response import SessionResponse from otari._client.models.set_password_request import SetPasswordRequest +from otari._client.models.signup_request import SignupRequest +from otari._client.models.signup_response import SignupResponse +from otari._client.models.verify_email_request import VerifyEmailRequest +from otari._client.models.verify_email_response import VerifyEmailResponse from otari._client.api_client import ApiClient, RequestSerialized from otari._client.api_response import ApiResponse @@ -38,10 +47,1352 @@ def __init__(self, api_client=None) -> None: self.api_client = api_client + @validate_call + def confirm_reset_v1_auth_password_reset_confirm_post( + self, + reset_password_request: ResetPasswordRequest, + _request_timeout: Union[ + None, + Annotated[StrictFloat, Field(gt=0)], + Tuple[ + Annotated[StrictFloat, Field(gt=0)], + Annotated[StrictFloat, Field(gt=0)] + ] + ] = None, + _request_auth: Optional[Dict[StrictStr, Any]] = None, + _content_type: Optional[StrictStr] = None, + _headers: Optional[Dict[StrictStr, Any]] = None, + _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, + ) -> None: + """Confirm Reset + + Complete a password reset. Single-use: the token stops working after this. + + :param reset_password_request: (required) + :type reset_password_request: ResetPasswordRequest + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :type _request_timeout: int, tuple(int, int), optional + :param _request_auth: set to override the auth_settings for an a single + request; this effectively ignores the + authentication in the spec for a single request. + :type _request_auth: dict, optional + :param _content_type: force content-type for the request. + :type _content_type: str, Optional + :param _headers: set to override the headers for a single + request; this effectively ignores the headers + in the spec for a single request. + :type _headers: dict, optional + :param _host_index: set to override the host_index for a single + request; this effectively ignores the host_index + in the spec for a single request. + :type _host_index: int, optional + :return: Returns the result object. + """ # noqa: E501 + + _param = self._confirm_reset_v1_auth_password_reset_confirm_post_serialize( + reset_password_request=reset_password_request, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '204': None, + '422': "HTTPValidationError", + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + response_data.read() + return self.api_client.response_deserialize( + response_data=response_data, + response_types_map=_response_types_map, + ).data + + + @validate_call + def confirm_reset_v1_auth_password_reset_confirm_post_with_http_info( + self, + reset_password_request: ResetPasswordRequest, + _request_timeout: Union[ + None, + Annotated[StrictFloat, Field(gt=0)], + Tuple[ + Annotated[StrictFloat, Field(gt=0)], + Annotated[StrictFloat, Field(gt=0)] + ] + ] = None, + _request_auth: Optional[Dict[StrictStr, Any]] = None, + _content_type: Optional[StrictStr] = None, + _headers: Optional[Dict[StrictStr, Any]] = None, + _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, + ) -> ApiResponse[None]: + """Confirm Reset + + Complete a password reset. Single-use: the token stops working after this. + + :param reset_password_request: (required) + :type reset_password_request: ResetPasswordRequest + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :type _request_timeout: int, tuple(int, int), optional + :param _request_auth: set to override the auth_settings for an a single + request; this effectively ignores the + authentication in the spec for a single request. + :type _request_auth: dict, optional + :param _content_type: force content-type for the request. + :type _content_type: str, Optional + :param _headers: set to override the headers for a single + request; this effectively ignores the headers + in the spec for a single request. + :type _headers: dict, optional + :param _host_index: set to override the host_index for a single + request; this effectively ignores the host_index + in the spec for a single request. + :type _host_index: int, optional + :return: Returns the result object. + """ # noqa: E501 + + _param = self._confirm_reset_v1_auth_password_reset_confirm_post_serialize( + reset_password_request=reset_password_request, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '204': None, + '422': "HTTPValidationError", + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + response_data.read() + return self.api_client.response_deserialize( + response_data=response_data, + response_types_map=_response_types_map, + ) + + + @validate_call + def confirm_reset_v1_auth_password_reset_confirm_post_without_preload_content( + self, + reset_password_request: ResetPasswordRequest, + _request_timeout: Union[ + None, + Annotated[StrictFloat, Field(gt=0)], + Tuple[ + Annotated[StrictFloat, Field(gt=0)], + Annotated[StrictFloat, Field(gt=0)] + ] + ] = None, + _request_auth: Optional[Dict[StrictStr, Any]] = None, + _content_type: Optional[StrictStr] = None, + _headers: Optional[Dict[StrictStr, Any]] = None, + _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, + ) -> RESTResponseType: + """Confirm Reset + + Complete a password reset. Single-use: the token stops working after this. + + :param reset_password_request: (required) + :type reset_password_request: ResetPasswordRequest + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :type _request_timeout: int, tuple(int, int), optional + :param _request_auth: set to override the auth_settings for an a single + request; this effectively ignores the + authentication in the spec for a single request. + :type _request_auth: dict, optional + :param _content_type: force content-type for the request. + :type _content_type: str, Optional + :param _headers: set to override the headers for a single + request; this effectively ignores the headers + in the spec for a single request. + :type _headers: dict, optional + :param _host_index: set to override the host_index for a single + request; this effectively ignores the host_index + in the spec for a single request. + :type _host_index: int, optional + :return: Returns the result object. + """ # noqa: E501 + + _param = self._confirm_reset_v1_auth_password_reset_confirm_post_serialize( + reset_password_request=reset_password_request, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '204': None, + '422': "HTTPValidationError", + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + return response_data.response + + + def _confirm_reset_v1_auth_password_reset_confirm_post_serialize( + self, + reset_password_request, + _request_auth, + _content_type, + _headers, + _host_index, + ) -> RequestSerialized: + + _host = None + + _collection_formats: Dict[str, str] = { + } + + _path_params: Dict[str, str] = {} + _query_params: List[Tuple[str, str]] = [] + _header_params: Dict[str, Optional[str]] = _headers or {} + _form_params: List[Tuple[str, str]] = [] + _files: Dict[ + str, Union[str, bytes, List[str], List[bytes], List[Tuple[str, bytes]]] + ] = {} + _body_params: Optional[bytes] = None + + # process the path parameters + # process the query parameters + # process the header parameters + # process the form parameters + # process the body parameter + if reset_password_request is not None: + _body_params = reset_password_request + + + # set the HTTP header `Accept` + if 'Accept' not in _header_params: + _header_params['Accept'] = self.api_client.select_header_accept( + [ + 'application/json' + ] + ) + + # set the HTTP header `Content-Type` + if _content_type: + _header_params['Content-Type'] = _content_type + else: + _default_content_type = ( + self.api_client.select_header_content_type( + [ + 'application/json' + ] + ) + ) + if _default_content_type is not None: + _header_params['Content-Type'] = _default_content_type + + # authentication setting + _auth_settings: List[str] = [ + ] + + return self.api_client.param_serialize( + method='POST', + resource_path='/v1/auth/password/reset/confirm', + path_params=_path_params, + query_params=_query_params, + header_params=_header_params, + body=_body_params, + post_params=_form_params, + files=_files, + auth_settings=_auth_settings, + collection_formats=_collection_formats, + _host=_host, + _request_auth=_request_auth + ) + + + + @validate_call def create_session_v1_auth_session_post( self, - create_session_request: CreateSessionRequest, + create_session_request: CreateSessionRequest, + _request_timeout: Union[ + None, + Annotated[StrictFloat, Field(gt=0)], + Tuple[ + Annotated[StrictFloat, Field(gt=0)], + Annotated[StrictFloat, Field(gt=0)] + ] + ] = None, + _request_auth: Optional[Dict[StrictStr, Any]] = None, + _content_type: Optional[StrictStr] = None, + _headers: Optional[Dict[StrictStr, Any]] = None, + _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, + ) -> SessionResponse: + """Create Session + + Verify a sign-in credential and set the HttpOnly session cookie. The session is bound to the identity that authenticated, so every request it later authenticates resolves a user and that user's active organization rather than only \"a credential was presented once\". The response names both, so a client knows who it is signed in as without a second call. The rate-limit check deliberately runs only after a failed verification, not before it: a pre-verification gate can't know whether *this* attempt would have succeeded, so once an IP has used up its failure quota it would end up blocking that IP's legitimate owner too, not just further attackers. Running after verification also means the throttle bounds how many verdicts an IP gets, not how much work it can cause: a password attempt pays for a bcrypt verification (cost 12, on the order of 200ms of CPU, and one is burned against a stand-in hash even for an address nobody holds) before the limit is consulted, so a 429 costs the same as a 401. A gateway exposed to the internet should rate-limit this path at the proxy as well. + + :param create_session_request: (required) + :type create_session_request: CreateSessionRequest + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :type _request_timeout: int, tuple(int, int), optional + :param _request_auth: set to override the auth_settings for an a single + request; this effectively ignores the + authentication in the spec for a single request. + :type _request_auth: dict, optional + :param _content_type: force content-type for the request. + :type _content_type: str, Optional + :param _headers: set to override the headers for a single + request; this effectively ignores the headers + in the spec for a single request. + :type _headers: dict, optional + :param _host_index: set to override the host_index for a single + request; this effectively ignores the host_index + in the spec for a single request. + :type _host_index: int, optional + :return: Returns the result object. + """ # noqa: E501 + + _param = self._create_session_v1_auth_session_post_serialize( + create_session_request=create_session_request, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "SessionResponse", + '422': "HTTPValidationError", + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + response_data.read() + return self.api_client.response_deserialize( + response_data=response_data, + response_types_map=_response_types_map, + ).data + + + @validate_call + def create_session_v1_auth_session_post_with_http_info( + self, + create_session_request: CreateSessionRequest, + _request_timeout: Union[ + None, + Annotated[StrictFloat, Field(gt=0)], + Tuple[ + Annotated[StrictFloat, Field(gt=0)], + Annotated[StrictFloat, Field(gt=0)] + ] + ] = None, + _request_auth: Optional[Dict[StrictStr, Any]] = None, + _content_type: Optional[StrictStr] = None, + _headers: Optional[Dict[StrictStr, Any]] = None, + _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, + ) -> ApiResponse[SessionResponse]: + """Create Session + + Verify a sign-in credential and set the HttpOnly session cookie. The session is bound to the identity that authenticated, so every request it later authenticates resolves a user and that user's active organization rather than only \"a credential was presented once\". The response names both, so a client knows who it is signed in as without a second call. The rate-limit check deliberately runs only after a failed verification, not before it: a pre-verification gate can't know whether *this* attempt would have succeeded, so once an IP has used up its failure quota it would end up blocking that IP's legitimate owner too, not just further attackers. Running after verification also means the throttle bounds how many verdicts an IP gets, not how much work it can cause: a password attempt pays for a bcrypt verification (cost 12, on the order of 200ms of CPU, and one is burned against a stand-in hash even for an address nobody holds) before the limit is consulted, so a 429 costs the same as a 401. A gateway exposed to the internet should rate-limit this path at the proxy as well. + + :param create_session_request: (required) + :type create_session_request: CreateSessionRequest + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :type _request_timeout: int, tuple(int, int), optional + :param _request_auth: set to override the auth_settings for an a single + request; this effectively ignores the + authentication in the spec for a single request. + :type _request_auth: dict, optional + :param _content_type: force content-type for the request. + :type _content_type: str, Optional + :param _headers: set to override the headers for a single + request; this effectively ignores the headers + in the spec for a single request. + :type _headers: dict, optional + :param _host_index: set to override the host_index for a single + request; this effectively ignores the host_index + in the spec for a single request. + :type _host_index: int, optional + :return: Returns the result object. + """ # noqa: E501 + + _param = self._create_session_v1_auth_session_post_serialize( + create_session_request=create_session_request, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "SessionResponse", + '422': "HTTPValidationError", + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + response_data.read() + return self.api_client.response_deserialize( + response_data=response_data, + response_types_map=_response_types_map, + ) + + + @validate_call + def create_session_v1_auth_session_post_without_preload_content( + self, + create_session_request: CreateSessionRequest, + _request_timeout: Union[ + None, + Annotated[StrictFloat, Field(gt=0)], + Tuple[ + Annotated[StrictFloat, Field(gt=0)], + Annotated[StrictFloat, Field(gt=0)] + ] + ] = None, + _request_auth: Optional[Dict[StrictStr, Any]] = None, + _content_type: Optional[StrictStr] = None, + _headers: Optional[Dict[StrictStr, Any]] = None, + _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, + ) -> RESTResponseType: + """Create Session + + Verify a sign-in credential and set the HttpOnly session cookie. The session is bound to the identity that authenticated, so every request it later authenticates resolves a user and that user's active organization rather than only \"a credential was presented once\". The response names both, so a client knows who it is signed in as without a second call. The rate-limit check deliberately runs only after a failed verification, not before it: a pre-verification gate can't know whether *this* attempt would have succeeded, so once an IP has used up its failure quota it would end up blocking that IP's legitimate owner too, not just further attackers. Running after verification also means the throttle bounds how many verdicts an IP gets, not how much work it can cause: a password attempt pays for a bcrypt verification (cost 12, on the order of 200ms of CPU, and one is burned against a stand-in hash even for an address nobody holds) before the limit is consulted, so a 429 costs the same as a 401. A gateway exposed to the internet should rate-limit this path at the proxy as well. + + :param create_session_request: (required) + :type create_session_request: CreateSessionRequest + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :type _request_timeout: int, tuple(int, int), optional + :param _request_auth: set to override the auth_settings for an a single + request; this effectively ignores the + authentication in the spec for a single request. + :type _request_auth: dict, optional + :param _content_type: force content-type for the request. + :type _content_type: str, Optional + :param _headers: set to override the headers for a single + request; this effectively ignores the headers + in the spec for a single request. + :type _headers: dict, optional + :param _host_index: set to override the host_index for a single + request; this effectively ignores the host_index + in the spec for a single request. + :type _host_index: int, optional + :return: Returns the result object. + """ # noqa: E501 + + _param = self._create_session_v1_auth_session_post_serialize( + create_session_request=create_session_request, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "SessionResponse", + '422': "HTTPValidationError", + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + return response_data.response + + + def _create_session_v1_auth_session_post_serialize( + self, + create_session_request, + _request_auth, + _content_type, + _headers, + _host_index, + ) -> RequestSerialized: + + _host = None + + _collection_formats: Dict[str, str] = { + } + + _path_params: Dict[str, str] = {} + _query_params: List[Tuple[str, str]] = [] + _header_params: Dict[str, Optional[str]] = _headers or {} + _form_params: List[Tuple[str, str]] = [] + _files: Dict[ + str, Union[str, bytes, List[str], List[bytes], List[Tuple[str, bytes]]] + ] = {} + _body_params: Optional[bytes] = None + + # process the path parameters + # process the query parameters + # process the header parameters + # process the form parameters + # process the body parameter + if create_session_request is not None: + _body_params = create_session_request + + + # set the HTTP header `Accept` + if 'Accept' not in _header_params: + _header_params['Accept'] = self.api_client.select_header_accept( + [ + 'application/json' + ] + ) + + # set the HTTP header `Content-Type` + if _content_type: + _header_params['Content-Type'] = _content_type + else: + _default_content_type = ( + self.api_client.select_header_content_type( + [ + 'application/json' + ] + ) + ) + if _default_content_type is not None: + _header_params['Content-Type'] = _default_content_type + + # authentication setting + _auth_settings: List[str] = [ + ] + + return self.api_client.param_serialize( + method='POST', + resource_path='/v1/auth/session', + path_params=_path_params, + query_params=_query_params, + header_params=_header_params, + body=_body_params, + post_params=_form_params, + files=_files, + auth_settings=_auth_settings, + collection_formats=_collection_formats, + _host=_host, + _request_auth=_request_auth + ) + + + + + @validate_call + def delete_session_v1_auth_session_delete( + self, + _request_timeout: Union[ + None, + Annotated[StrictFloat, Field(gt=0)], + Tuple[ + Annotated[StrictFloat, Field(gt=0)], + Annotated[StrictFloat, Field(gt=0)] + ] + ] = None, + _request_auth: Optional[Dict[StrictStr, Any]] = None, + _content_type: Optional[StrictStr] = None, + _headers: Optional[Dict[StrictStr, Any]] = None, + _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, + ) -> None: + """Delete Session + + Sign out: revoke the cookie's session server-side and expire the cookie. Deliberately unauthenticated and idempotent: it only ever revokes the session named by the caller's own cookie, and the dashboard calls it on the 401-bounce path where no valid credential exists anymore. Unlike the read path in ``deps.py`` it applies no Sec-Fetch-Site check: ``SameSite=Strict`` already keeps cross-site requests from carrying the cookie, and the worst a forged call could do is sign the operator out. + + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :type _request_timeout: int, tuple(int, int), optional + :param _request_auth: set to override the auth_settings for an a single + request; this effectively ignores the + authentication in the spec for a single request. + :type _request_auth: dict, optional + :param _content_type: force content-type for the request. + :type _content_type: str, Optional + :param _headers: set to override the headers for a single + request; this effectively ignores the headers + in the spec for a single request. + :type _headers: dict, optional + :param _host_index: set to override the host_index for a single + request; this effectively ignores the host_index + in the spec for a single request. + :type _host_index: int, optional + :return: Returns the result object. + """ # noqa: E501 + + _param = self._delete_session_v1_auth_session_delete_serialize( + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '204': None, + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + response_data.read() + return self.api_client.response_deserialize( + response_data=response_data, + response_types_map=_response_types_map, + ).data + + + @validate_call + def delete_session_v1_auth_session_delete_with_http_info( + self, + _request_timeout: Union[ + None, + Annotated[StrictFloat, Field(gt=0)], + Tuple[ + Annotated[StrictFloat, Field(gt=0)], + Annotated[StrictFloat, Field(gt=0)] + ] + ] = None, + _request_auth: Optional[Dict[StrictStr, Any]] = None, + _content_type: Optional[StrictStr] = None, + _headers: Optional[Dict[StrictStr, Any]] = None, + _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, + ) -> ApiResponse[None]: + """Delete Session + + Sign out: revoke the cookie's session server-side and expire the cookie. Deliberately unauthenticated and idempotent: it only ever revokes the session named by the caller's own cookie, and the dashboard calls it on the 401-bounce path where no valid credential exists anymore. Unlike the read path in ``deps.py`` it applies no Sec-Fetch-Site check: ``SameSite=Strict`` already keeps cross-site requests from carrying the cookie, and the worst a forged call could do is sign the operator out. + + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :type _request_timeout: int, tuple(int, int), optional + :param _request_auth: set to override the auth_settings for an a single + request; this effectively ignores the + authentication in the spec for a single request. + :type _request_auth: dict, optional + :param _content_type: force content-type for the request. + :type _content_type: str, Optional + :param _headers: set to override the headers for a single + request; this effectively ignores the headers + in the spec for a single request. + :type _headers: dict, optional + :param _host_index: set to override the host_index for a single + request; this effectively ignores the host_index + in the spec for a single request. + :type _host_index: int, optional + :return: Returns the result object. + """ # noqa: E501 + + _param = self._delete_session_v1_auth_session_delete_serialize( + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '204': None, + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + response_data.read() + return self.api_client.response_deserialize( + response_data=response_data, + response_types_map=_response_types_map, + ) + + + @validate_call + def delete_session_v1_auth_session_delete_without_preload_content( + self, + _request_timeout: Union[ + None, + Annotated[StrictFloat, Field(gt=0)], + Tuple[ + Annotated[StrictFloat, Field(gt=0)], + Annotated[StrictFloat, Field(gt=0)] + ] + ] = None, + _request_auth: Optional[Dict[StrictStr, Any]] = None, + _content_type: Optional[StrictStr] = None, + _headers: Optional[Dict[StrictStr, Any]] = None, + _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, + ) -> RESTResponseType: + """Delete Session + + Sign out: revoke the cookie's session server-side and expire the cookie. Deliberately unauthenticated and idempotent: it only ever revokes the session named by the caller's own cookie, and the dashboard calls it on the 401-bounce path where no valid credential exists anymore. Unlike the read path in ``deps.py`` it applies no Sec-Fetch-Site check: ``SameSite=Strict`` already keeps cross-site requests from carrying the cookie, and the worst a forged call could do is sign the operator out. + + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :type _request_timeout: int, tuple(int, int), optional + :param _request_auth: set to override the auth_settings for an a single + request; this effectively ignores the + authentication in the spec for a single request. + :type _request_auth: dict, optional + :param _content_type: force content-type for the request. + :type _content_type: str, Optional + :param _headers: set to override the headers for a single + request; this effectively ignores the headers + in the spec for a single request. + :type _headers: dict, optional + :param _host_index: set to override the host_index for a single + request; this effectively ignores the host_index + in the spec for a single request. + :type _host_index: int, optional + :return: Returns the result object. + """ # noqa: E501 + + _param = self._delete_session_v1_auth_session_delete_serialize( + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '204': None, + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + return response_data.response + + + def _delete_session_v1_auth_session_delete_serialize( + self, + _request_auth, + _content_type, + _headers, + _host_index, + ) -> RequestSerialized: + + _host = None + + _collection_formats: Dict[str, str] = { + } + + _path_params: Dict[str, str] = {} + _query_params: List[Tuple[str, str]] = [] + _header_params: Dict[str, Optional[str]] = _headers or {} + _form_params: List[Tuple[str, str]] = [] + _files: Dict[ + str, Union[str, bytes, List[str], List[bytes], List[Tuple[str, bytes]]] + ] = {} + _body_params: Optional[bytes] = None + + # process the path parameters + # process the query parameters + # process the header parameters + # process the form parameters + # process the body parameter + + + + + # authentication setting + _auth_settings: List[str] = [ + ] + + return self.api_client.param_serialize( + method='DELETE', + resource_path='/v1/auth/session', + path_params=_path_params, + query_params=_query_params, + header_params=_header_params, + body=_body_params, + post_params=_form_params, + files=_files, + auth_settings=_auth_settings, + collection_formats=_collection_formats, + _host=_host, + _request_auth=_request_auth + ) + + + + + @validate_call + def request_reset_v1_auth_password_reset_post( + self, + request_password_reset_request: RequestPasswordResetRequest, + _request_timeout: Union[ + None, + Annotated[StrictFloat, Field(gt=0)], + Tuple[ + Annotated[StrictFloat, Field(gt=0)], + Annotated[StrictFloat, Field(gt=0)] + ] + ] = None, + _request_auth: Optional[Dict[StrictStr, Any]] = None, + _content_type: Optional[StrictStr] = None, + _headers: Optional[Dict[StrictStr, Any]] = None, + _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, + ) -> RequestPasswordResetResponse: + """Request Reset + + Mail a password-reset link, or do nothing: the response never says which. + + :param request_password_reset_request: (required) + :type request_password_reset_request: RequestPasswordResetRequest + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :type _request_timeout: int, tuple(int, int), optional + :param _request_auth: set to override the auth_settings for an a single + request; this effectively ignores the + authentication in the spec for a single request. + :type _request_auth: dict, optional + :param _content_type: force content-type for the request. + :type _content_type: str, Optional + :param _headers: set to override the headers for a single + request; this effectively ignores the headers + in the spec for a single request. + :type _headers: dict, optional + :param _host_index: set to override the host_index for a single + request; this effectively ignores the host_index + in the spec for a single request. + :type _host_index: int, optional + :return: Returns the result object. + """ # noqa: E501 + + _param = self._request_reset_v1_auth_password_reset_post_serialize( + request_password_reset_request=request_password_reset_request, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "RequestPasswordResetResponse", + '422': "HTTPValidationError", + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + response_data.read() + return self.api_client.response_deserialize( + response_data=response_data, + response_types_map=_response_types_map, + ).data + + + @validate_call + def request_reset_v1_auth_password_reset_post_with_http_info( + self, + request_password_reset_request: RequestPasswordResetRequest, + _request_timeout: Union[ + None, + Annotated[StrictFloat, Field(gt=0)], + Tuple[ + Annotated[StrictFloat, Field(gt=0)], + Annotated[StrictFloat, Field(gt=0)] + ] + ] = None, + _request_auth: Optional[Dict[StrictStr, Any]] = None, + _content_type: Optional[StrictStr] = None, + _headers: Optional[Dict[StrictStr, Any]] = None, + _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, + ) -> ApiResponse[RequestPasswordResetResponse]: + """Request Reset + + Mail a password-reset link, or do nothing: the response never says which. + + :param request_password_reset_request: (required) + :type request_password_reset_request: RequestPasswordResetRequest + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :type _request_timeout: int, tuple(int, int), optional + :param _request_auth: set to override the auth_settings for an a single + request; this effectively ignores the + authentication in the spec for a single request. + :type _request_auth: dict, optional + :param _content_type: force content-type for the request. + :type _content_type: str, Optional + :param _headers: set to override the headers for a single + request; this effectively ignores the headers + in the spec for a single request. + :type _headers: dict, optional + :param _host_index: set to override the host_index for a single + request; this effectively ignores the host_index + in the spec for a single request. + :type _host_index: int, optional + :return: Returns the result object. + """ # noqa: E501 + + _param = self._request_reset_v1_auth_password_reset_post_serialize( + request_password_reset_request=request_password_reset_request, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "RequestPasswordResetResponse", + '422': "HTTPValidationError", + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + response_data.read() + return self.api_client.response_deserialize( + response_data=response_data, + response_types_map=_response_types_map, + ) + + + @validate_call + def request_reset_v1_auth_password_reset_post_without_preload_content( + self, + request_password_reset_request: RequestPasswordResetRequest, + _request_timeout: Union[ + None, + Annotated[StrictFloat, Field(gt=0)], + Tuple[ + Annotated[StrictFloat, Field(gt=0)], + Annotated[StrictFloat, Field(gt=0)] + ] + ] = None, + _request_auth: Optional[Dict[StrictStr, Any]] = None, + _content_type: Optional[StrictStr] = None, + _headers: Optional[Dict[StrictStr, Any]] = None, + _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, + ) -> RESTResponseType: + """Request Reset + + Mail a password-reset link, or do nothing: the response never says which. + + :param request_password_reset_request: (required) + :type request_password_reset_request: RequestPasswordResetRequest + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :type _request_timeout: int, tuple(int, int), optional + :param _request_auth: set to override the auth_settings for an a single + request; this effectively ignores the + authentication in the spec for a single request. + :type _request_auth: dict, optional + :param _content_type: force content-type for the request. + :type _content_type: str, Optional + :param _headers: set to override the headers for a single + request; this effectively ignores the headers + in the spec for a single request. + :type _headers: dict, optional + :param _host_index: set to override the host_index for a single + request; this effectively ignores the host_index + in the spec for a single request. + :type _host_index: int, optional + :return: Returns the result object. + """ # noqa: E501 + + _param = self._request_reset_v1_auth_password_reset_post_serialize( + request_password_reset_request=request_password_reset_request, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "RequestPasswordResetResponse", + '422': "HTTPValidationError", + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + return response_data.response + + + def _request_reset_v1_auth_password_reset_post_serialize( + self, + request_password_reset_request, + _request_auth, + _content_type, + _headers, + _host_index, + ) -> RequestSerialized: + + _host = None + + _collection_formats: Dict[str, str] = { + } + + _path_params: Dict[str, str] = {} + _query_params: List[Tuple[str, str]] = [] + _header_params: Dict[str, Optional[str]] = _headers or {} + _form_params: List[Tuple[str, str]] = [] + _files: Dict[ + str, Union[str, bytes, List[str], List[bytes], List[Tuple[str, bytes]]] + ] = {} + _body_params: Optional[bytes] = None + + # process the path parameters + # process the query parameters + # process the header parameters + # process the form parameters + # process the body parameter + if request_password_reset_request is not None: + _body_params = request_password_reset_request + + + # set the HTTP header `Accept` + if 'Accept' not in _header_params: + _header_params['Accept'] = self.api_client.select_header_accept( + [ + 'application/json' + ] + ) + + # set the HTTP header `Content-Type` + if _content_type: + _header_params['Content-Type'] = _content_type + else: + _default_content_type = ( + self.api_client.select_header_content_type( + [ + 'application/json' + ] + ) + ) + if _default_content_type is not None: + _header_params['Content-Type'] = _default_content_type + + # authentication setting + _auth_settings: List[str] = [ + ] + + return self.api_client.param_serialize( + method='POST', + resource_path='/v1/auth/password/reset', + path_params=_path_params, + query_params=_query_params, + header_params=_header_params, + body=_body_params, + post_params=_form_params, + files=_files, + auth_settings=_auth_settings, + collection_formats=_collection_formats, + _host=_host, + _request_auth=_request_auth + ) + + + + + @validate_call + def resend_verification_v1_auth_resend_verification_post( + self, + resend_verification_request: ResendVerificationRequest, + _request_timeout: Union[ + None, + Annotated[StrictFloat, Field(gt=0)], + Tuple[ + Annotated[StrictFloat, Field(gt=0)], + Annotated[StrictFloat, Field(gt=0)] + ] + ] = None, + _request_auth: Optional[Dict[StrictStr, Any]] = None, + _content_type: Optional[StrictStr] = None, + _headers: Optional[Dict[StrictStr, Any]] = None, + _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, + ) -> ResendVerificationResponse: + """Resend Verification + + Mail a fresh verification link, or do nothing: the response never says which. + + :param resend_verification_request: (required) + :type resend_verification_request: ResendVerificationRequest + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :type _request_timeout: int, tuple(int, int), optional + :param _request_auth: set to override the auth_settings for an a single + request; this effectively ignores the + authentication in the spec for a single request. + :type _request_auth: dict, optional + :param _content_type: force content-type for the request. + :type _content_type: str, Optional + :param _headers: set to override the headers for a single + request; this effectively ignores the headers + in the spec for a single request. + :type _headers: dict, optional + :param _host_index: set to override the host_index for a single + request; this effectively ignores the host_index + in the spec for a single request. + :type _host_index: int, optional + :return: Returns the result object. + """ # noqa: E501 + + _param = self._resend_verification_v1_auth_resend_verification_post_serialize( + resend_verification_request=resend_verification_request, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "ResendVerificationResponse", + '422': "HTTPValidationError", + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + response_data.read() + return self.api_client.response_deserialize( + response_data=response_data, + response_types_map=_response_types_map, + ).data + + + @validate_call + def resend_verification_v1_auth_resend_verification_post_with_http_info( + self, + resend_verification_request: ResendVerificationRequest, + _request_timeout: Union[ + None, + Annotated[StrictFloat, Field(gt=0)], + Tuple[ + Annotated[StrictFloat, Field(gt=0)], + Annotated[StrictFloat, Field(gt=0)] + ] + ] = None, + _request_auth: Optional[Dict[StrictStr, Any]] = None, + _content_type: Optional[StrictStr] = None, + _headers: Optional[Dict[StrictStr, Any]] = None, + _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, + ) -> ApiResponse[ResendVerificationResponse]: + """Resend Verification + + Mail a fresh verification link, or do nothing: the response never says which. + + :param resend_verification_request: (required) + :type resend_verification_request: ResendVerificationRequest + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :type _request_timeout: int, tuple(int, int), optional + :param _request_auth: set to override the auth_settings for an a single + request; this effectively ignores the + authentication in the spec for a single request. + :type _request_auth: dict, optional + :param _content_type: force content-type for the request. + :type _content_type: str, Optional + :param _headers: set to override the headers for a single + request; this effectively ignores the headers + in the spec for a single request. + :type _headers: dict, optional + :param _host_index: set to override the host_index for a single + request; this effectively ignores the host_index + in the spec for a single request. + :type _host_index: int, optional + :return: Returns the result object. + """ # noqa: E501 + + _param = self._resend_verification_v1_auth_resend_verification_post_serialize( + resend_verification_request=resend_verification_request, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "ResendVerificationResponse", + '422': "HTTPValidationError", + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + response_data.read() + return self.api_client.response_deserialize( + response_data=response_data, + response_types_map=_response_types_map, + ) + + + @validate_call + def resend_verification_v1_auth_resend_verification_post_without_preload_content( + self, + resend_verification_request: ResendVerificationRequest, + _request_timeout: Union[ + None, + Annotated[StrictFloat, Field(gt=0)], + Tuple[ + Annotated[StrictFloat, Field(gt=0)], + Annotated[StrictFloat, Field(gt=0)] + ] + ] = None, + _request_auth: Optional[Dict[StrictStr, Any]] = None, + _content_type: Optional[StrictStr] = None, + _headers: Optional[Dict[StrictStr, Any]] = None, + _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, + ) -> RESTResponseType: + """Resend Verification + + Mail a fresh verification link, or do nothing: the response never says which. + + :param resend_verification_request: (required) + :type resend_verification_request: ResendVerificationRequest + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :type _request_timeout: int, tuple(int, int), optional + :param _request_auth: set to override the auth_settings for an a single + request; this effectively ignores the + authentication in the spec for a single request. + :type _request_auth: dict, optional + :param _content_type: force content-type for the request. + :type _content_type: str, Optional + :param _headers: set to override the headers for a single + request; this effectively ignores the headers + in the spec for a single request. + :type _headers: dict, optional + :param _host_index: set to override the host_index for a single + request; this effectively ignores the host_index + in the spec for a single request. + :type _host_index: int, optional + :return: Returns the result object. + """ # noqa: E501 + + _param = self._resend_verification_v1_auth_resend_verification_post_serialize( + resend_verification_request=resend_verification_request, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "ResendVerificationResponse", + '422': "HTTPValidationError", + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + return response_data.response + + + def _resend_verification_v1_auth_resend_verification_post_serialize( + self, + resend_verification_request, + _request_auth, + _content_type, + _headers, + _host_index, + ) -> RequestSerialized: + + _host = None + + _collection_formats: Dict[str, str] = { + } + + _path_params: Dict[str, str] = {} + _query_params: List[Tuple[str, str]] = [] + _header_params: Dict[str, Optional[str]] = _headers or {} + _form_params: List[Tuple[str, str]] = [] + _files: Dict[ + str, Union[str, bytes, List[str], List[bytes], List[Tuple[str, bytes]]] + ] = {} + _body_params: Optional[bytes] = None + + # process the path parameters + # process the query parameters + # process the header parameters + # process the form parameters + # process the body parameter + if resend_verification_request is not None: + _body_params = resend_verification_request + + + # set the HTTP header `Accept` + if 'Accept' not in _header_params: + _header_params['Accept'] = self.api_client.select_header_accept( + [ + 'application/json' + ] + ) + + # set the HTTP header `Content-Type` + if _content_type: + _header_params['Content-Type'] = _content_type + else: + _default_content_type = ( + self.api_client.select_header_content_type( + [ + 'application/json' + ] + ) + ) + if _default_content_type is not None: + _header_params['Content-Type'] = _default_content_type + + # authentication setting + _auth_settings: List[str] = [ + ] + + return self.api_client.param_serialize( + method='POST', + resource_path='/v1/auth/resend-verification', + path_params=_path_params, + query_params=_query_params, + header_params=_header_params, + body=_body_params, + post_params=_form_params, + files=_files, + auth_settings=_auth_settings, + collection_formats=_collection_formats, + _host=_host, + _request_auth=_request_auth + ) + + + + + @validate_call + def set_dashboard_password_v1_auth_password_put( + self, + set_password_request: SetPasswordRequest, _request_timeout: Union[ None, Annotated[StrictFloat, Field(gt=0)], @@ -54,13 +1405,13 @@ def create_session_v1_auth_session_post( _content_type: Optional[StrictStr] = None, _headers: Optional[Dict[StrictStr, Any]] = None, _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, - ) -> SessionResponse: - """Create Session + ) -> PasswordResponse: + """Set Dashboard Password - Verify a sign-in credential and set the HttpOnly session cookie. The session is bound to the identity that authenticated, so every request it later authenticates resolves a user and that user's active organization rather than only \"a credential was presented once\". The response names both, so a client knows who it is signed in as without a second call. The rate-limit check deliberately runs only after a failed verification, not before it: a pre-verification gate can't know whether *this* attempt would have succeeded, so once an IP has used up its failure quota it would end up blocking that IP's legitimate owner too, not just further attackers. Running after verification also means the throttle bounds how many verdicts an IP gets, not how much work it can cause: a password attempt pays for a bcrypt verification (cost 12, on the order of 200ms of CPU, and one is burned against a stand-in hash even for an address nobody holds) before the limit is consulted, so a 429 costs the same as a 401. A gateway exposed to the internet should rate-limit this path at the proxy as well. + Set or change the password the caller signs in to the dashboard with. Always the caller's own identity. Supply ``email`` when it has no sign-in address yet, which is the state first boot leaves the operator in, and ``current_password`` when it already has a password and the request is authenticated by the session cookie. The master key in a header is what excuses ``current_password``, which is how a forgotten password is recovered; it does not excuse ``email``, because an identity with no address has nothing to sign in with whoever is asking. Setting a password for the first time retires master-key sign-in on this deployment. Every other session this identity holds ends, the caller's own excepted, so a cookie stolen before the change does not outlive it. - :param create_session_request: (required) - :type create_session_request: CreateSessionRequest + :param set_password_request: (required) + :type set_password_request: SetPasswordRequest :param _request_timeout: timeout setting for this request. If one number provided, it will be total request timeout. It can also be a pair (tuple) of @@ -83,8 +1434,8 @@ def create_session_v1_auth_session_post( :return: Returns the result object. """ # noqa: E501 - _param = self._create_session_v1_auth_session_post_serialize( - create_session_request=create_session_request, + _param = self._set_dashboard_password_v1_auth_password_put_serialize( + set_password_request=set_password_request, _request_auth=_request_auth, _content_type=_content_type, _headers=_headers, @@ -92,7 +1443,7 @@ def create_session_v1_auth_session_post( ) _response_types_map: Dict[str, Optional[str]] = { - '200': "SessionResponse", + '200': "PasswordResponse", '422': "HTTPValidationError", } response_data = self.api_client.call_api( @@ -107,9 +1458,9 @@ def create_session_v1_auth_session_post( @validate_call - def create_session_v1_auth_session_post_with_http_info( + def set_dashboard_password_v1_auth_password_put_with_http_info( self, - create_session_request: CreateSessionRequest, + set_password_request: SetPasswordRequest, _request_timeout: Union[ None, Annotated[StrictFloat, Field(gt=0)], @@ -122,13 +1473,13 @@ def create_session_v1_auth_session_post_with_http_info( _content_type: Optional[StrictStr] = None, _headers: Optional[Dict[StrictStr, Any]] = None, _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, - ) -> ApiResponse[SessionResponse]: - """Create Session + ) -> ApiResponse[PasswordResponse]: + """Set Dashboard Password - Verify a sign-in credential and set the HttpOnly session cookie. The session is bound to the identity that authenticated, so every request it later authenticates resolves a user and that user's active organization rather than only \"a credential was presented once\". The response names both, so a client knows who it is signed in as without a second call. The rate-limit check deliberately runs only after a failed verification, not before it: a pre-verification gate can't know whether *this* attempt would have succeeded, so once an IP has used up its failure quota it would end up blocking that IP's legitimate owner too, not just further attackers. Running after verification also means the throttle bounds how many verdicts an IP gets, not how much work it can cause: a password attempt pays for a bcrypt verification (cost 12, on the order of 200ms of CPU, and one is burned against a stand-in hash even for an address nobody holds) before the limit is consulted, so a 429 costs the same as a 401. A gateway exposed to the internet should rate-limit this path at the proxy as well. + Set or change the password the caller signs in to the dashboard with. Always the caller's own identity. Supply ``email`` when it has no sign-in address yet, which is the state first boot leaves the operator in, and ``current_password`` when it already has a password and the request is authenticated by the session cookie. The master key in a header is what excuses ``current_password``, which is how a forgotten password is recovered; it does not excuse ``email``, because an identity with no address has nothing to sign in with whoever is asking. Setting a password for the first time retires master-key sign-in on this deployment. Every other session this identity holds ends, the caller's own excepted, so a cookie stolen before the change does not outlive it. - :param create_session_request: (required) - :type create_session_request: CreateSessionRequest + :param set_password_request: (required) + :type set_password_request: SetPasswordRequest :param _request_timeout: timeout setting for this request. If one number provided, it will be total request timeout. It can also be a pair (tuple) of @@ -151,8 +1502,8 @@ def create_session_v1_auth_session_post_with_http_info( :return: Returns the result object. """ # noqa: E501 - _param = self._create_session_v1_auth_session_post_serialize( - create_session_request=create_session_request, + _param = self._set_dashboard_password_v1_auth_password_put_serialize( + set_password_request=set_password_request, _request_auth=_request_auth, _content_type=_content_type, _headers=_headers, @@ -160,7 +1511,7 @@ def create_session_v1_auth_session_post_with_http_info( ) _response_types_map: Dict[str, Optional[str]] = { - '200': "SessionResponse", + '200': "PasswordResponse", '422': "HTTPValidationError", } response_data = self.api_client.call_api( @@ -175,9 +1526,9 @@ def create_session_v1_auth_session_post_with_http_info( @validate_call - def create_session_v1_auth_session_post_without_preload_content( + def set_dashboard_password_v1_auth_password_put_without_preload_content( self, - create_session_request: CreateSessionRequest, + set_password_request: SetPasswordRequest, _request_timeout: Union[ None, Annotated[StrictFloat, Field(gt=0)], @@ -191,12 +1542,12 @@ def create_session_v1_auth_session_post_without_preload_content( _headers: Optional[Dict[StrictStr, Any]] = None, _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, ) -> RESTResponseType: - """Create Session + """Set Dashboard Password - Verify a sign-in credential and set the HttpOnly session cookie. The session is bound to the identity that authenticated, so every request it later authenticates resolves a user and that user's active organization rather than only \"a credential was presented once\". The response names both, so a client knows who it is signed in as without a second call. The rate-limit check deliberately runs only after a failed verification, not before it: a pre-verification gate can't know whether *this* attempt would have succeeded, so once an IP has used up its failure quota it would end up blocking that IP's legitimate owner too, not just further attackers. Running after verification also means the throttle bounds how many verdicts an IP gets, not how much work it can cause: a password attempt pays for a bcrypt verification (cost 12, on the order of 200ms of CPU, and one is burned against a stand-in hash even for an address nobody holds) before the limit is consulted, so a 429 costs the same as a 401. A gateway exposed to the internet should rate-limit this path at the proxy as well. + Set or change the password the caller signs in to the dashboard with. Always the caller's own identity. Supply ``email`` when it has no sign-in address yet, which is the state first boot leaves the operator in, and ``current_password`` when it already has a password and the request is authenticated by the session cookie. The master key in a header is what excuses ``current_password``, which is how a forgotten password is recovered; it does not excuse ``email``, because an identity with no address has nothing to sign in with whoever is asking. Setting a password for the first time retires master-key sign-in on this deployment. Every other session this identity holds ends, the caller's own excepted, so a cookie stolen before the change does not outlive it. - :param create_session_request: (required) - :type create_session_request: CreateSessionRequest + :param set_password_request: (required) + :type set_password_request: SetPasswordRequest :param _request_timeout: timeout setting for this request. If one number provided, it will be total request timeout. It can also be a pair (tuple) of @@ -219,8 +1570,8 @@ def create_session_v1_auth_session_post_without_preload_content( :return: Returns the result object. """ # noqa: E501 - _param = self._create_session_v1_auth_session_post_serialize( - create_session_request=create_session_request, + _param = self._set_dashboard_password_v1_auth_password_put_serialize( + set_password_request=set_password_request, _request_auth=_request_auth, _content_type=_content_type, _headers=_headers, @@ -228,7 +1579,7 @@ def create_session_v1_auth_session_post_without_preload_content( ) _response_types_map: Dict[str, Optional[str]] = { - '200': "SessionResponse", + '200': "PasswordResponse", '422': "HTTPValidationError", } response_data = self.api_client.call_api( @@ -238,9 +1589,9 @@ def create_session_v1_auth_session_post_without_preload_content( return response_data.response - def _create_session_v1_auth_session_post_serialize( + def _set_dashboard_password_v1_auth_password_put_serialize( self, - create_session_request, + set_password_request, _request_auth, _content_type, _headers, @@ -266,8 +1617,8 @@ def _create_session_v1_auth_session_post_serialize( # process the header parameters # process the form parameters # process the body parameter - if create_session_request is not None: - _body_params = create_session_request + if set_password_request is not None: + _body_params = set_password_request # set the HTTP header `Accept` @@ -294,11 +1645,13 @@ def _create_session_v1_auth_session_post_serialize( # authentication setting _auth_settings: List[str] = [ + 'XApiKeyAuth', + 'ApiKeyAuth' ] return self.api_client.param_serialize( - method='POST', - resource_path='/v1/auth/session', + method='PUT', + resource_path='/v1/auth/password', path_params=_path_params, query_params=_query_params, header_params=_header_params, @@ -315,8 +1668,9 @@ def _create_session_v1_auth_session_post_serialize( @validate_call - def delete_session_v1_auth_session_delete( + def signup_v1_auth_signup_post( self, + signup_request: SignupRequest, _request_timeout: Union[ None, Annotated[StrictFloat, Field(gt=0)], @@ -329,11 +1683,13 @@ def delete_session_v1_auth_session_delete( _content_type: Optional[StrictStr] = None, _headers: Optional[Dict[StrictStr, Any]] = None, _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, - ) -> None: - """Delete Session + ) -> SignupResponse: + """Signup - Sign out: revoke the cookie's session server-side and expire the cookie. Deliberately unauthenticated and idempotent: it only ever revokes the session named by the caller's own cookie, and the dashboard calls it on the 401-bounce path where no valid credential exists anymore. Unlike the read path in ``deps.py`` it applies no Sec-Fetch-Site check: ``SameSite=Strict`` already keeps cross-site requests from carrying the cookie, and the worst a forged call could do is sign the operator out. + Claim a roster identity, or do nothing: the response never says which. No session is minted. A newly claimed identity is hard-blocked from signing in until it verifies, so there is nothing yet to sign it into. + :param signup_request: (required) + :type signup_request: SignupRequest :param _request_timeout: timeout setting for this request. If one number provided, it will be total request timeout. It can also be a pair (tuple) of @@ -356,7 +1712,8 @@ def delete_session_v1_auth_session_delete( :return: Returns the result object. """ # noqa: E501 - _param = self._delete_session_v1_auth_session_delete_serialize( + _param = self._signup_v1_auth_signup_post_serialize( + signup_request=signup_request, _request_auth=_request_auth, _content_type=_content_type, _headers=_headers, @@ -364,7 +1721,8 @@ def delete_session_v1_auth_session_delete( ) _response_types_map: Dict[str, Optional[str]] = { - '204': None, + '200': "SignupResponse", + '422': "HTTPValidationError", } response_data = self.api_client.call_api( *_param, @@ -378,8 +1736,9 @@ def delete_session_v1_auth_session_delete( @validate_call - def delete_session_v1_auth_session_delete_with_http_info( + def signup_v1_auth_signup_post_with_http_info( self, + signup_request: SignupRequest, _request_timeout: Union[ None, Annotated[StrictFloat, Field(gt=0)], @@ -392,11 +1751,13 @@ def delete_session_v1_auth_session_delete_with_http_info( _content_type: Optional[StrictStr] = None, _headers: Optional[Dict[StrictStr, Any]] = None, _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, - ) -> ApiResponse[None]: - """Delete Session + ) -> ApiResponse[SignupResponse]: + """Signup - Sign out: revoke the cookie's session server-side and expire the cookie. Deliberately unauthenticated and idempotent: it only ever revokes the session named by the caller's own cookie, and the dashboard calls it on the 401-bounce path where no valid credential exists anymore. Unlike the read path in ``deps.py`` it applies no Sec-Fetch-Site check: ``SameSite=Strict`` already keeps cross-site requests from carrying the cookie, and the worst a forged call could do is sign the operator out. + Claim a roster identity, or do nothing: the response never says which. No session is minted. A newly claimed identity is hard-blocked from signing in until it verifies, so there is nothing yet to sign it into. + :param signup_request: (required) + :type signup_request: SignupRequest :param _request_timeout: timeout setting for this request. If one number provided, it will be total request timeout. It can also be a pair (tuple) of @@ -419,7 +1780,8 @@ def delete_session_v1_auth_session_delete_with_http_info( :return: Returns the result object. """ # noqa: E501 - _param = self._delete_session_v1_auth_session_delete_serialize( + _param = self._signup_v1_auth_signup_post_serialize( + signup_request=signup_request, _request_auth=_request_auth, _content_type=_content_type, _headers=_headers, @@ -427,7 +1789,8 @@ def delete_session_v1_auth_session_delete_with_http_info( ) _response_types_map: Dict[str, Optional[str]] = { - '204': None, + '200': "SignupResponse", + '422': "HTTPValidationError", } response_data = self.api_client.call_api( *_param, @@ -441,8 +1804,9 @@ def delete_session_v1_auth_session_delete_with_http_info( @validate_call - def delete_session_v1_auth_session_delete_without_preload_content( + def signup_v1_auth_signup_post_without_preload_content( self, + signup_request: SignupRequest, _request_timeout: Union[ None, Annotated[StrictFloat, Field(gt=0)], @@ -456,10 +1820,12 @@ def delete_session_v1_auth_session_delete_without_preload_content( _headers: Optional[Dict[StrictStr, Any]] = None, _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, ) -> RESTResponseType: - """Delete Session + """Signup - Sign out: revoke the cookie's session server-side and expire the cookie. Deliberately unauthenticated and idempotent: it only ever revokes the session named by the caller's own cookie, and the dashboard calls it on the 401-bounce path where no valid credential exists anymore. Unlike the read path in ``deps.py`` it applies no Sec-Fetch-Site check: ``SameSite=Strict`` already keeps cross-site requests from carrying the cookie, and the worst a forged call could do is sign the operator out. + Claim a roster identity, or do nothing: the response never says which. No session is minted. A newly claimed identity is hard-blocked from signing in until it verifies, so there is nothing yet to sign it into. + :param signup_request: (required) + :type signup_request: SignupRequest :param _request_timeout: timeout setting for this request. If one number provided, it will be total request timeout. It can also be a pair (tuple) of @@ -482,7 +1848,8 @@ def delete_session_v1_auth_session_delete_without_preload_content( :return: Returns the result object. """ # noqa: E501 - _param = self._delete_session_v1_auth_session_delete_serialize( + _param = self._signup_v1_auth_signup_post_serialize( + signup_request=signup_request, _request_auth=_request_auth, _content_type=_content_type, _headers=_headers, @@ -490,7 +1857,8 @@ def delete_session_v1_auth_session_delete_without_preload_content( ) _response_types_map: Dict[str, Optional[str]] = { - '204': None, + '200': "SignupResponse", + '422': "HTTPValidationError", } response_data = self.api_client.call_api( *_param, @@ -499,8 +1867,9 @@ def delete_session_v1_auth_session_delete_without_preload_content( return response_data.response - def _delete_session_v1_auth_session_delete_serialize( + def _signup_v1_auth_signup_post_serialize( self, + signup_request, _request_auth, _content_type, _headers, @@ -526,17 +1895,39 @@ def _delete_session_v1_auth_session_delete_serialize( # process the header parameters # process the form parameters # process the body parameter + if signup_request is not None: + _body_params = signup_request + # set the HTTP header `Accept` + if 'Accept' not in _header_params: + _header_params['Accept'] = self.api_client.select_header_accept( + [ + 'application/json' + ] + ) + # set the HTTP header `Content-Type` + if _content_type: + _header_params['Content-Type'] = _content_type + else: + _default_content_type = ( + self.api_client.select_header_content_type( + [ + 'application/json' + ] + ) + ) + if _default_content_type is not None: + _header_params['Content-Type'] = _default_content_type # authentication setting _auth_settings: List[str] = [ ] return self.api_client.param_serialize( - method='DELETE', - resource_path='/v1/auth/session', + method='POST', + resource_path='/v1/auth/signup', path_params=_path_params, query_params=_query_params, header_params=_header_params, @@ -553,9 +1944,9 @@ def _delete_session_v1_auth_session_delete_serialize( @validate_call - def set_dashboard_password_v1_auth_password_put( + def verify_email_route_v1_auth_verify_email_post( self, - set_password_request: SetPasswordRequest, + verify_email_request: VerifyEmailRequest, _request_timeout: Union[ None, Annotated[StrictFloat, Field(gt=0)], @@ -568,13 +1959,13 @@ def set_dashboard_password_v1_auth_password_put( _content_type: Optional[StrictStr] = None, _headers: Optional[Dict[StrictStr, Any]] = None, _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, - ) -> PasswordResponse: - """Set Dashboard Password + ) -> VerifyEmailResponse: + """Verify Email Route - Set or change the password the caller signs in to the dashboard with. Always the caller's own identity. Supply ``email`` when it has no sign-in address yet, which is the state first boot leaves the operator in, and ``current_password`` when it already has a password and the request is authenticated by the session cookie. The master key in a header is what excuses ``current_password``, which is how a forgotten password is recovered; it does not excuse ``email``, because an identity with no address has nothing to sign in with whoever is asking. Setting a password for the first time retires master-key sign-in on this deployment. Every other session this identity holds ends, the caller's own excepted, so a cookie stolen before the change does not outlive it. + Confirm an address from its verification link, lifting the sign-in gate. - :param set_password_request: (required) - :type set_password_request: SetPasswordRequest + :param verify_email_request: (required) + :type verify_email_request: VerifyEmailRequest :param _request_timeout: timeout setting for this request. If one number provided, it will be total request timeout. It can also be a pair (tuple) of @@ -597,8 +1988,8 @@ def set_dashboard_password_v1_auth_password_put( :return: Returns the result object. """ # noqa: E501 - _param = self._set_dashboard_password_v1_auth_password_put_serialize( - set_password_request=set_password_request, + _param = self._verify_email_route_v1_auth_verify_email_post_serialize( + verify_email_request=verify_email_request, _request_auth=_request_auth, _content_type=_content_type, _headers=_headers, @@ -606,7 +1997,7 @@ def set_dashboard_password_v1_auth_password_put( ) _response_types_map: Dict[str, Optional[str]] = { - '200': "PasswordResponse", + '200': "VerifyEmailResponse", '422': "HTTPValidationError", } response_data = self.api_client.call_api( @@ -621,9 +2012,9 @@ def set_dashboard_password_v1_auth_password_put( @validate_call - def set_dashboard_password_v1_auth_password_put_with_http_info( + def verify_email_route_v1_auth_verify_email_post_with_http_info( self, - set_password_request: SetPasswordRequest, + verify_email_request: VerifyEmailRequest, _request_timeout: Union[ None, Annotated[StrictFloat, Field(gt=0)], @@ -636,13 +2027,13 @@ def set_dashboard_password_v1_auth_password_put_with_http_info( _content_type: Optional[StrictStr] = None, _headers: Optional[Dict[StrictStr, Any]] = None, _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, - ) -> ApiResponse[PasswordResponse]: - """Set Dashboard Password + ) -> ApiResponse[VerifyEmailResponse]: + """Verify Email Route - Set or change the password the caller signs in to the dashboard with. Always the caller's own identity. Supply ``email`` when it has no sign-in address yet, which is the state first boot leaves the operator in, and ``current_password`` when it already has a password and the request is authenticated by the session cookie. The master key in a header is what excuses ``current_password``, which is how a forgotten password is recovered; it does not excuse ``email``, because an identity with no address has nothing to sign in with whoever is asking. Setting a password for the first time retires master-key sign-in on this deployment. Every other session this identity holds ends, the caller's own excepted, so a cookie stolen before the change does not outlive it. + Confirm an address from its verification link, lifting the sign-in gate. - :param set_password_request: (required) - :type set_password_request: SetPasswordRequest + :param verify_email_request: (required) + :type verify_email_request: VerifyEmailRequest :param _request_timeout: timeout setting for this request. If one number provided, it will be total request timeout. It can also be a pair (tuple) of @@ -665,8 +2056,8 @@ def set_dashboard_password_v1_auth_password_put_with_http_info( :return: Returns the result object. """ # noqa: E501 - _param = self._set_dashboard_password_v1_auth_password_put_serialize( - set_password_request=set_password_request, + _param = self._verify_email_route_v1_auth_verify_email_post_serialize( + verify_email_request=verify_email_request, _request_auth=_request_auth, _content_type=_content_type, _headers=_headers, @@ -674,7 +2065,7 @@ def set_dashboard_password_v1_auth_password_put_with_http_info( ) _response_types_map: Dict[str, Optional[str]] = { - '200': "PasswordResponse", + '200': "VerifyEmailResponse", '422': "HTTPValidationError", } response_data = self.api_client.call_api( @@ -689,9 +2080,9 @@ def set_dashboard_password_v1_auth_password_put_with_http_info( @validate_call - def set_dashboard_password_v1_auth_password_put_without_preload_content( + def verify_email_route_v1_auth_verify_email_post_without_preload_content( self, - set_password_request: SetPasswordRequest, + verify_email_request: VerifyEmailRequest, _request_timeout: Union[ None, Annotated[StrictFloat, Field(gt=0)], @@ -705,12 +2096,12 @@ def set_dashboard_password_v1_auth_password_put_without_preload_content( _headers: Optional[Dict[StrictStr, Any]] = None, _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, ) -> RESTResponseType: - """Set Dashboard Password + """Verify Email Route - Set or change the password the caller signs in to the dashboard with. Always the caller's own identity. Supply ``email`` when it has no sign-in address yet, which is the state first boot leaves the operator in, and ``current_password`` when it already has a password and the request is authenticated by the session cookie. The master key in a header is what excuses ``current_password``, which is how a forgotten password is recovered; it does not excuse ``email``, because an identity with no address has nothing to sign in with whoever is asking. Setting a password for the first time retires master-key sign-in on this deployment. Every other session this identity holds ends, the caller's own excepted, so a cookie stolen before the change does not outlive it. + Confirm an address from its verification link, lifting the sign-in gate. - :param set_password_request: (required) - :type set_password_request: SetPasswordRequest + :param verify_email_request: (required) + :type verify_email_request: VerifyEmailRequest :param _request_timeout: timeout setting for this request. If one number provided, it will be total request timeout. It can also be a pair (tuple) of @@ -733,8 +2124,8 @@ def set_dashboard_password_v1_auth_password_put_without_preload_content( :return: Returns the result object. """ # noqa: E501 - _param = self._set_dashboard_password_v1_auth_password_put_serialize( - set_password_request=set_password_request, + _param = self._verify_email_route_v1_auth_verify_email_post_serialize( + verify_email_request=verify_email_request, _request_auth=_request_auth, _content_type=_content_type, _headers=_headers, @@ -742,7 +2133,7 @@ def set_dashboard_password_v1_auth_password_put_without_preload_content( ) _response_types_map: Dict[str, Optional[str]] = { - '200': "PasswordResponse", + '200': "VerifyEmailResponse", '422': "HTTPValidationError", } response_data = self.api_client.call_api( @@ -752,9 +2143,9 @@ def set_dashboard_password_v1_auth_password_put_without_preload_content( return response_data.response - def _set_dashboard_password_v1_auth_password_put_serialize( + def _verify_email_route_v1_auth_verify_email_post_serialize( self, - set_password_request, + verify_email_request, _request_auth, _content_type, _headers, @@ -780,8 +2171,8 @@ def _set_dashboard_password_v1_auth_password_put_serialize( # process the header parameters # process the form parameters # process the body parameter - if set_password_request is not None: - _body_params = set_password_request + if verify_email_request is not None: + _body_params = verify_email_request # set the HTTP header `Accept` @@ -808,13 +2199,11 @@ def _set_dashboard_password_v1_auth_password_put_serialize( # authentication setting _auth_settings: List[str] = [ - 'XApiKeyAuth', - 'ApiKeyAuth' ] return self.api_client.param_serialize( - method='PUT', - resource_path='/v1/auth/password', + method='POST', + resource_path='/v1/auth/verify-email', path_params=_path_params, query_params=_query_params, header_params=_header_params, diff --git a/src/otari/_client/api/budgets_api.py b/src/otari/_client/api/budgets_api.py index f13bc49..4ddbeef 100644 --- a/src/otari/_client/api/budgets_api.py +++ b/src/otari/_client/api/budgets_api.py @@ -338,7 +338,7 @@ def delete_budget_v1_budgets_budget_id_delete( ) -> None: """Delete Budget - Delete a budget. + Delete a budget. Refused with 409 while anything still names this budget: a workspace handing it to its members, or a scoped ceiling enforcing it. Both foreign keys are ``RESTRICT``, so the database would refuse either anyway, but as an ``IntegrityError`` reported as \"Database error\" with nothing naming what to go and change. Checked here so the refusal can say which, and where. :param budget_id: (required) :type budget_id: str @@ -406,7 +406,7 @@ def delete_budget_v1_budgets_budget_id_delete_with_http_info( ) -> ApiResponse[None]: """Delete Budget - Delete a budget. + Delete a budget. Refused with 409 while anything still names this budget: a workspace handing it to its members, or a scoped ceiling enforcing it. Both foreign keys are ``RESTRICT``, so the database would refuse either anyway, but as an ``IntegrityError`` reported as \"Database error\" with nothing naming what to go and change. Checked here so the refusal can say which, and where. :param budget_id: (required) :type budget_id: str @@ -474,7 +474,7 @@ def delete_budget_v1_budgets_budget_id_delete_without_preload_content( ) -> RESTResponseType: """Delete Budget - Delete a budget. + Delete a budget. Refused with 409 while anything still names this budget: a workspace handing it to its members, or a scoped ceiling enforcing it. Both foreign keys are ``RESTRICT``, so the database would refuse either anyway, but as an ``IntegrityError`` reported as \"Database error\" with nothing naming what to go and change. Checked here so the refusal can say which, and where. :param budget_id: (required) :type budget_id: str diff --git a/src/otari/_client/api/mcp_servers_api.py b/src/otari/_client/api/mcp_servers_api.py new file mode 100644 index 0000000..c7a3f47 --- /dev/null +++ b/src/otari/_client/api/mcp_servers_api.py @@ -0,0 +1,1223 @@ +""" + otari + + Otari, an OpenAI-compatible LLM gateway with API key management + + The version of the OpenAPI document: 0.0.0-dev + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +import warnings +from pydantic import validate_call, Field, StrictFloat, StrictStr, StrictInt +from typing import Any, Dict, List, Optional, Tuple, Union +from typing_extensions import Annotated + +from pydantic import Field +from typing import Optional +from typing_extensions import Annotated +from uuid import UUID +from otari._client.models.message import Message +from otari._client.models.workspace_mcp_server_create import WorkspaceMcpServerCreate +from otari._client.models.workspace_mcp_server_public import WorkspaceMcpServerPublic +from otari._client.models.workspace_mcp_server_update import WorkspaceMcpServerUpdate +from otari._client.models.workspace_mcp_servers_public import WorkspaceMcpServersPublic + +from otari._client.api_client import ApiClient, RequestSerialized +from otari._client.api_response import ApiResponse +from otari._client.rest import RESTResponseType + + +class McpServersApi: + """NOTE: This class is auto generated by OpenAPI Generator + Ref: https://openapi-generator.tech + + Do not edit the class manually. + """ + + def __init__(self, api_client=None) -> None: + if api_client is None: + api_client = ApiClient.get_default() + self.api_client = api_client + + + @validate_call + def create_workspace_mcp_server_v1_workspaces_workspace_id_mcp_servers_post( + self, + workspace_id: UUID, + workspace_mcp_server_create: WorkspaceMcpServerCreate, + _request_timeout: Union[ + None, + Annotated[StrictFloat, Field(gt=0)], + Tuple[ + Annotated[StrictFloat, Field(gt=0)], + Annotated[StrictFloat, Field(gt=0)] + ] + ] = None, + _request_auth: Optional[Dict[StrictStr, Any]] = None, + _content_type: Optional[StrictStr] = None, + _headers: Optional[Dict[StrictStr, Any]] = None, + _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, + ) -> WorkspaceMcpServerPublic: + """Create Workspace Mcp Server + + Register an MCP server for a workspace. Organization owners/admins or this workspace's owners/admins. The authorization token is encrypted at rest and never returned. The URL is checked for SSRF safety here as well as on the request path, and must use https when a token is set. A name already used in this workspace is refused with a 409. + + :param workspace_id: (required) + :type workspace_id: UUID + :param workspace_mcp_server_create: (required) + :type workspace_mcp_server_create: WorkspaceMcpServerCreate + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :type _request_timeout: int, tuple(int, int), optional + :param _request_auth: set to override the auth_settings for an a single + request; this effectively ignores the + authentication in the spec for a single request. + :type _request_auth: dict, optional + :param _content_type: force content-type for the request. + :type _content_type: str, Optional + :param _headers: set to override the headers for a single + request; this effectively ignores the headers + in the spec for a single request. + :type _headers: dict, optional + :param _host_index: set to override the host_index for a single + request; this effectively ignores the host_index + in the spec for a single request. + :type _host_index: int, optional + :return: Returns the result object. + """ # noqa: E501 + + _param = self._create_workspace_mcp_server_v1_workspaces_workspace_id_mcp_servers_post_serialize( + workspace_id=workspace_id, + workspace_mcp_server_create=workspace_mcp_server_create, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '201': "WorkspaceMcpServerPublic", + '422': "HTTPValidationError", + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + response_data.read() + return self.api_client.response_deserialize( + response_data=response_data, + response_types_map=_response_types_map, + ).data + + + @validate_call + def create_workspace_mcp_server_v1_workspaces_workspace_id_mcp_servers_post_with_http_info( + self, + workspace_id: UUID, + workspace_mcp_server_create: WorkspaceMcpServerCreate, + _request_timeout: Union[ + None, + Annotated[StrictFloat, Field(gt=0)], + Tuple[ + Annotated[StrictFloat, Field(gt=0)], + Annotated[StrictFloat, Field(gt=0)] + ] + ] = None, + _request_auth: Optional[Dict[StrictStr, Any]] = None, + _content_type: Optional[StrictStr] = None, + _headers: Optional[Dict[StrictStr, Any]] = None, + _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, + ) -> ApiResponse[WorkspaceMcpServerPublic]: + """Create Workspace Mcp Server + + Register an MCP server for a workspace. Organization owners/admins or this workspace's owners/admins. The authorization token is encrypted at rest and never returned. The URL is checked for SSRF safety here as well as on the request path, and must use https when a token is set. A name already used in this workspace is refused with a 409. + + :param workspace_id: (required) + :type workspace_id: UUID + :param workspace_mcp_server_create: (required) + :type workspace_mcp_server_create: WorkspaceMcpServerCreate + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :type _request_timeout: int, tuple(int, int), optional + :param _request_auth: set to override the auth_settings for an a single + request; this effectively ignores the + authentication in the spec for a single request. + :type _request_auth: dict, optional + :param _content_type: force content-type for the request. + :type _content_type: str, Optional + :param _headers: set to override the headers for a single + request; this effectively ignores the headers + in the spec for a single request. + :type _headers: dict, optional + :param _host_index: set to override the host_index for a single + request; this effectively ignores the host_index + in the spec for a single request. + :type _host_index: int, optional + :return: Returns the result object. + """ # noqa: E501 + + _param = self._create_workspace_mcp_server_v1_workspaces_workspace_id_mcp_servers_post_serialize( + workspace_id=workspace_id, + workspace_mcp_server_create=workspace_mcp_server_create, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '201': "WorkspaceMcpServerPublic", + '422': "HTTPValidationError", + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + response_data.read() + return self.api_client.response_deserialize( + response_data=response_data, + response_types_map=_response_types_map, + ) + + + @validate_call + def create_workspace_mcp_server_v1_workspaces_workspace_id_mcp_servers_post_without_preload_content( + self, + workspace_id: UUID, + workspace_mcp_server_create: WorkspaceMcpServerCreate, + _request_timeout: Union[ + None, + Annotated[StrictFloat, Field(gt=0)], + Tuple[ + Annotated[StrictFloat, Field(gt=0)], + Annotated[StrictFloat, Field(gt=0)] + ] + ] = None, + _request_auth: Optional[Dict[StrictStr, Any]] = None, + _content_type: Optional[StrictStr] = None, + _headers: Optional[Dict[StrictStr, Any]] = None, + _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, + ) -> RESTResponseType: + """Create Workspace Mcp Server + + Register an MCP server for a workspace. Organization owners/admins or this workspace's owners/admins. The authorization token is encrypted at rest and never returned. The URL is checked for SSRF safety here as well as on the request path, and must use https when a token is set. A name already used in this workspace is refused with a 409. + + :param workspace_id: (required) + :type workspace_id: UUID + :param workspace_mcp_server_create: (required) + :type workspace_mcp_server_create: WorkspaceMcpServerCreate + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :type _request_timeout: int, tuple(int, int), optional + :param _request_auth: set to override the auth_settings for an a single + request; this effectively ignores the + authentication in the spec for a single request. + :type _request_auth: dict, optional + :param _content_type: force content-type for the request. + :type _content_type: str, Optional + :param _headers: set to override the headers for a single + request; this effectively ignores the headers + in the spec for a single request. + :type _headers: dict, optional + :param _host_index: set to override the host_index for a single + request; this effectively ignores the host_index + in the spec for a single request. + :type _host_index: int, optional + :return: Returns the result object. + """ # noqa: E501 + + _param = self._create_workspace_mcp_server_v1_workspaces_workspace_id_mcp_servers_post_serialize( + workspace_id=workspace_id, + workspace_mcp_server_create=workspace_mcp_server_create, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '201': "WorkspaceMcpServerPublic", + '422': "HTTPValidationError", + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + return response_data.response + + + def _create_workspace_mcp_server_v1_workspaces_workspace_id_mcp_servers_post_serialize( + self, + workspace_id, + workspace_mcp_server_create, + _request_auth, + _content_type, + _headers, + _host_index, + ) -> RequestSerialized: + + _host = None + + _collection_formats: Dict[str, str] = { + } + + _path_params: Dict[str, str] = {} + _query_params: List[Tuple[str, str]] = [] + _header_params: Dict[str, Optional[str]] = _headers or {} + _form_params: List[Tuple[str, str]] = [] + _files: Dict[ + str, Union[str, bytes, List[str], List[bytes], List[Tuple[str, bytes]]] + ] = {} + _body_params: Optional[bytes] = None + + # process the path parameters + if workspace_id is not None: + _path_params['workspace_id'] = workspace_id + # process the query parameters + # process the header parameters + # process the form parameters + # process the body parameter + if workspace_mcp_server_create is not None: + _body_params = workspace_mcp_server_create + + + # set the HTTP header `Accept` + if 'Accept' not in _header_params: + _header_params['Accept'] = self.api_client.select_header_accept( + [ + 'application/json' + ] + ) + + # set the HTTP header `Content-Type` + if _content_type: + _header_params['Content-Type'] = _content_type + else: + _default_content_type = ( + self.api_client.select_header_content_type( + [ + 'application/json' + ] + ) + ) + if _default_content_type is not None: + _header_params['Content-Type'] = _default_content_type + + # authentication setting + _auth_settings: List[str] = [ + 'XApiKeyAuth', + 'ApiKeyAuth' + ] + + return self.api_client.param_serialize( + method='POST', + resource_path='/v1/workspaces/{workspace_id}/mcp-servers', + path_params=_path_params, + query_params=_query_params, + header_params=_header_params, + body=_body_params, + post_params=_form_params, + files=_files, + auth_settings=_auth_settings, + collection_formats=_collection_formats, + _host=_host, + _request_auth=_request_auth + ) + + + + + @validate_call + def delete_workspace_mcp_server_v1_workspaces_workspace_id_mcp_servers_server_id_delete( + self, + workspace_id: UUID, + server_id: UUID, + _request_timeout: Union[ + None, + Annotated[StrictFloat, Field(gt=0)], + Tuple[ + Annotated[StrictFloat, Field(gt=0)], + Annotated[StrictFloat, Field(gt=0)] + ] + ] = None, + _request_auth: Optional[Dict[StrictStr, Any]] = None, + _content_type: Optional[StrictStr] = None, + _headers: Optional[Dict[StrictStr, Any]] = None, + _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, + ) -> Message: + """Delete Workspace Mcp Server + + Delete a server and the token stored with it. Organization owners/admins or this workspace's owners/admins. + + :param workspace_id: (required) + :type workspace_id: UUID + :param server_id: (required) + :type server_id: UUID + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :type _request_timeout: int, tuple(int, int), optional + :param _request_auth: set to override the auth_settings for an a single + request; this effectively ignores the + authentication in the spec for a single request. + :type _request_auth: dict, optional + :param _content_type: force content-type for the request. + :type _content_type: str, Optional + :param _headers: set to override the headers for a single + request; this effectively ignores the headers + in the spec for a single request. + :type _headers: dict, optional + :param _host_index: set to override the host_index for a single + request; this effectively ignores the host_index + in the spec for a single request. + :type _host_index: int, optional + :return: Returns the result object. + """ # noqa: E501 + + _param = self._delete_workspace_mcp_server_v1_workspaces_workspace_id_mcp_servers_server_id_delete_serialize( + workspace_id=workspace_id, + server_id=server_id, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "Message", + '422': "HTTPValidationError", + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + response_data.read() + return self.api_client.response_deserialize( + response_data=response_data, + response_types_map=_response_types_map, + ).data + + + @validate_call + def delete_workspace_mcp_server_v1_workspaces_workspace_id_mcp_servers_server_id_delete_with_http_info( + self, + workspace_id: UUID, + server_id: UUID, + _request_timeout: Union[ + None, + Annotated[StrictFloat, Field(gt=0)], + Tuple[ + Annotated[StrictFloat, Field(gt=0)], + Annotated[StrictFloat, Field(gt=0)] + ] + ] = None, + _request_auth: Optional[Dict[StrictStr, Any]] = None, + _content_type: Optional[StrictStr] = None, + _headers: Optional[Dict[StrictStr, Any]] = None, + _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, + ) -> ApiResponse[Message]: + """Delete Workspace Mcp Server + + Delete a server and the token stored with it. Organization owners/admins or this workspace's owners/admins. + + :param workspace_id: (required) + :type workspace_id: UUID + :param server_id: (required) + :type server_id: UUID + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :type _request_timeout: int, tuple(int, int), optional + :param _request_auth: set to override the auth_settings for an a single + request; this effectively ignores the + authentication in the spec for a single request. + :type _request_auth: dict, optional + :param _content_type: force content-type for the request. + :type _content_type: str, Optional + :param _headers: set to override the headers for a single + request; this effectively ignores the headers + in the spec for a single request. + :type _headers: dict, optional + :param _host_index: set to override the host_index for a single + request; this effectively ignores the host_index + in the spec for a single request. + :type _host_index: int, optional + :return: Returns the result object. + """ # noqa: E501 + + _param = self._delete_workspace_mcp_server_v1_workspaces_workspace_id_mcp_servers_server_id_delete_serialize( + workspace_id=workspace_id, + server_id=server_id, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "Message", + '422': "HTTPValidationError", + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + response_data.read() + return self.api_client.response_deserialize( + response_data=response_data, + response_types_map=_response_types_map, + ) + + + @validate_call + def delete_workspace_mcp_server_v1_workspaces_workspace_id_mcp_servers_server_id_delete_without_preload_content( + self, + workspace_id: UUID, + server_id: UUID, + _request_timeout: Union[ + None, + Annotated[StrictFloat, Field(gt=0)], + Tuple[ + Annotated[StrictFloat, Field(gt=0)], + Annotated[StrictFloat, Field(gt=0)] + ] + ] = None, + _request_auth: Optional[Dict[StrictStr, Any]] = None, + _content_type: Optional[StrictStr] = None, + _headers: Optional[Dict[StrictStr, Any]] = None, + _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, + ) -> RESTResponseType: + """Delete Workspace Mcp Server + + Delete a server and the token stored with it. Organization owners/admins or this workspace's owners/admins. + + :param workspace_id: (required) + :type workspace_id: UUID + :param server_id: (required) + :type server_id: UUID + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :type _request_timeout: int, tuple(int, int), optional + :param _request_auth: set to override the auth_settings for an a single + request; this effectively ignores the + authentication in the spec for a single request. + :type _request_auth: dict, optional + :param _content_type: force content-type for the request. + :type _content_type: str, Optional + :param _headers: set to override the headers for a single + request; this effectively ignores the headers + in the spec for a single request. + :type _headers: dict, optional + :param _host_index: set to override the host_index for a single + request; this effectively ignores the host_index + in the spec for a single request. + :type _host_index: int, optional + :return: Returns the result object. + """ # noqa: E501 + + _param = self._delete_workspace_mcp_server_v1_workspaces_workspace_id_mcp_servers_server_id_delete_serialize( + workspace_id=workspace_id, + server_id=server_id, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "Message", + '422': "HTTPValidationError", + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + return response_data.response + + + def _delete_workspace_mcp_server_v1_workspaces_workspace_id_mcp_servers_server_id_delete_serialize( + self, + workspace_id, + server_id, + _request_auth, + _content_type, + _headers, + _host_index, + ) -> RequestSerialized: + + _host = None + + _collection_formats: Dict[str, str] = { + } + + _path_params: Dict[str, str] = {} + _query_params: List[Tuple[str, str]] = [] + _header_params: Dict[str, Optional[str]] = _headers or {} + _form_params: List[Tuple[str, str]] = [] + _files: Dict[ + str, Union[str, bytes, List[str], List[bytes], List[Tuple[str, bytes]]] + ] = {} + _body_params: Optional[bytes] = None + + # process the path parameters + if workspace_id is not None: + _path_params['workspace_id'] = workspace_id + if server_id is not None: + _path_params['server_id'] = server_id + # process the query parameters + # process the header parameters + # process the form parameters + # process the body parameter + + + # set the HTTP header `Accept` + if 'Accept' not in _header_params: + _header_params['Accept'] = self.api_client.select_header_accept( + [ + 'application/json' + ] + ) + + + # authentication setting + _auth_settings: List[str] = [ + 'XApiKeyAuth', + 'ApiKeyAuth' + ] + + return self.api_client.param_serialize( + method='DELETE', + resource_path='/v1/workspaces/{workspace_id}/mcp-servers/{server_id}', + path_params=_path_params, + query_params=_query_params, + header_params=_header_params, + body=_body_params, + post_params=_form_params, + files=_files, + auth_settings=_auth_settings, + collection_formats=_collection_formats, + _host=_host, + _request_auth=_request_auth + ) + + + + + @validate_call + def list_workspace_mcp_servers_v1_workspaces_workspace_id_mcp_servers_get( + self, + workspace_id: UUID, + skip: Annotated[Optional[Annotated[int, Field(strict=True, ge=0)]], Field(description="Number of records to skip")] = None, + limit: Annotated[Optional[Annotated[int, Field(le=1000, strict=True, ge=1)]], Field(description="Maximum number of records to return")] = None, + _request_timeout: Union[ + None, + Annotated[StrictFloat, Field(gt=0)], + Tuple[ + Annotated[StrictFloat, Field(gt=0)], + Annotated[StrictFloat, Field(gt=0)] + ] + ] = None, + _request_auth: Optional[Dict[StrictStr, Any]] = None, + _content_type: Optional[StrictStr] = None, + _headers: Optional[Dict[StrictStr, Any]] = None, + _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, + ) -> WorkspaceMcpServersPublic: + """List Workspace Mcp Servers + + List the MCP servers configured for a workspace. Organization owners/admins or this workspace's owners/admins. Reads are gated like writes because these rows name the endpoints the gateway connects to on the workspace's behalf. Authorization tokens are never included; each server reports only whether it has one. + + :param workspace_id: (required) + :type workspace_id: UUID + :param skip: Number of records to skip + :type skip: int + :param limit: Maximum number of records to return + :type limit: int + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :type _request_timeout: int, tuple(int, int), optional + :param _request_auth: set to override the auth_settings for an a single + request; this effectively ignores the + authentication in the spec for a single request. + :type _request_auth: dict, optional + :param _content_type: force content-type for the request. + :type _content_type: str, Optional + :param _headers: set to override the headers for a single + request; this effectively ignores the headers + in the spec for a single request. + :type _headers: dict, optional + :param _host_index: set to override the host_index for a single + request; this effectively ignores the host_index + in the spec for a single request. + :type _host_index: int, optional + :return: Returns the result object. + """ # noqa: E501 + + _param = self._list_workspace_mcp_servers_v1_workspaces_workspace_id_mcp_servers_get_serialize( + workspace_id=workspace_id, + skip=skip, + limit=limit, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "WorkspaceMcpServersPublic", + '422': "HTTPValidationError", + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + response_data.read() + return self.api_client.response_deserialize( + response_data=response_data, + response_types_map=_response_types_map, + ).data + + + @validate_call + def list_workspace_mcp_servers_v1_workspaces_workspace_id_mcp_servers_get_with_http_info( + self, + workspace_id: UUID, + skip: Annotated[Optional[Annotated[int, Field(strict=True, ge=0)]], Field(description="Number of records to skip")] = None, + limit: Annotated[Optional[Annotated[int, Field(le=1000, strict=True, ge=1)]], Field(description="Maximum number of records to return")] = None, + _request_timeout: Union[ + None, + Annotated[StrictFloat, Field(gt=0)], + Tuple[ + Annotated[StrictFloat, Field(gt=0)], + Annotated[StrictFloat, Field(gt=0)] + ] + ] = None, + _request_auth: Optional[Dict[StrictStr, Any]] = None, + _content_type: Optional[StrictStr] = None, + _headers: Optional[Dict[StrictStr, Any]] = None, + _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, + ) -> ApiResponse[WorkspaceMcpServersPublic]: + """List Workspace Mcp Servers + + List the MCP servers configured for a workspace. Organization owners/admins or this workspace's owners/admins. Reads are gated like writes because these rows name the endpoints the gateway connects to on the workspace's behalf. Authorization tokens are never included; each server reports only whether it has one. + + :param workspace_id: (required) + :type workspace_id: UUID + :param skip: Number of records to skip + :type skip: int + :param limit: Maximum number of records to return + :type limit: int + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :type _request_timeout: int, tuple(int, int), optional + :param _request_auth: set to override the auth_settings for an a single + request; this effectively ignores the + authentication in the spec for a single request. + :type _request_auth: dict, optional + :param _content_type: force content-type for the request. + :type _content_type: str, Optional + :param _headers: set to override the headers for a single + request; this effectively ignores the headers + in the spec for a single request. + :type _headers: dict, optional + :param _host_index: set to override the host_index for a single + request; this effectively ignores the host_index + in the spec for a single request. + :type _host_index: int, optional + :return: Returns the result object. + """ # noqa: E501 + + _param = self._list_workspace_mcp_servers_v1_workspaces_workspace_id_mcp_servers_get_serialize( + workspace_id=workspace_id, + skip=skip, + limit=limit, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "WorkspaceMcpServersPublic", + '422': "HTTPValidationError", + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + response_data.read() + return self.api_client.response_deserialize( + response_data=response_data, + response_types_map=_response_types_map, + ) + + + @validate_call + def list_workspace_mcp_servers_v1_workspaces_workspace_id_mcp_servers_get_without_preload_content( + self, + workspace_id: UUID, + skip: Annotated[Optional[Annotated[int, Field(strict=True, ge=0)]], Field(description="Number of records to skip")] = None, + limit: Annotated[Optional[Annotated[int, Field(le=1000, strict=True, ge=1)]], Field(description="Maximum number of records to return")] = None, + _request_timeout: Union[ + None, + Annotated[StrictFloat, Field(gt=0)], + Tuple[ + Annotated[StrictFloat, Field(gt=0)], + Annotated[StrictFloat, Field(gt=0)] + ] + ] = None, + _request_auth: Optional[Dict[StrictStr, Any]] = None, + _content_type: Optional[StrictStr] = None, + _headers: Optional[Dict[StrictStr, Any]] = None, + _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, + ) -> RESTResponseType: + """List Workspace Mcp Servers + + List the MCP servers configured for a workspace. Organization owners/admins or this workspace's owners/admins. Reads are gated like writes because these rows name the endpoints the gateway connects to on the workspace's behalf. Authorization tokens are never included; each server reports only whether it has one. + + :param workspace_id: (required) + :type workspace_id: UUID + :param skip: Number of records to skip + :type skip: int + :param limit: Maximum number of records to return + :type limit: int + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :type _request_timeout: int, tuple(int, int), optional + :param _request_auth: set to override the auth_settings for an a single + request; this effectively ignores the + authentication in the spec for a single request. + :type _request_auth: dict, optional + :param _content_type: force content-type for the request. + :type _content_type: str, Optional + :param _headers: set to override the headers for a single + request; this effectively ignores the headers + in the spec for a single request. + :type _headers: dict, optional + :param _host_index: set to override the host_index for a single + request; this effectively ignores the host_index + in the spec for a single request. + :type _host_index: int, optional + :return: Returns the result object. + """ # noqa: E501 + + _param = self._list_workspace_mcp_servers_v1_workspaces_workspace_id_mcp_servers_get_serialize( + workspace_id=workspace_id, + skip=skip, + limit=limit, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "WorkspaceMcpServersPublic", + '422': "HTTPValidationError", + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + return response_data.response + + + def _list_workspace_mcp_servers_v1_workspaces_workspace_id_mcp_servers_get_serialize( + self, + workspace_id, + skip, + limit, + _request_auth, + _content_type, + _headers, + _host_index, + ) -> RequestSerialized: + + _host = None + + _collection_formats: Dict[str, str] = { + } + + _path_params: Dict[str, str] = {} + _query_params: List[Tuple[str, str]] = [] + _header_params: Dict[str, Optional[str]] = _headers or {} + _form_params: List[Tuple[str, str]] = [] + _files: Dict[ + str, Union[str, bytes, List[str], List[bytes], List[Tuple[str, bytes]]] + ] = {} + _body_params: Optional[bytes] = None + + # process the path parameters + if workspace_id is not None: + _path_params['workspace_id'] = workspace_id + # process the query parameters + if skip is not None: + + _query_params.append(('skip', skip)) + + if limit is not None: + + _query_params.append(('limit', limit)) + + # process the header parameters + # process the form parameters + # process the body parameter + + + # set the HTTP header `Accept` + if 'Accept' not in _header_params: + _header_params['Accept'] = self.api_client.select_header_accept( + [ + 'application/json' + ] + ) + + + # authentication setting + _auth_settings: List[str] = [ + 'XApiKeyAuth', + 'ApiKeyAuth' + ] + + return self.api_client.param_serialize( + method='GET', + resource_path='/v1/workspaces/{workspace_id}/mcp-servers', + path_params=_path_params, + query_params=_query_params, + header_params=_header_params, + body=_body_params, + post_params=_form_params, + files=_files, + auth_settings=_auth_settings, + collection_formats=_collection_formats, + _host=_host, + _request_auth=_request_auth + ) + + + + + @validate_call + def update_workspace_mcp_server_v1_workspaces_workspace_id_mcp_servers_server_id_patch( + self, + workspace_id: UUID, + server_id: UUID, + workspace_mcp_server_update: WorkspaceMcpServerUpdate, + _request_timeout: Union[ + None, + Annotated[StrictFloat, Field(gt=0)], + Tuple[ + Annotated[StrictFloat, Field(gt=0)], + Annotated[StrictFloat, Field(gt=0)] + ] + ] = None, + _request_auth: Optional[Dict[StrictStr, Any]] = None, + _content_type: Optional[StrictStr] = None, + _headers: Optional[Dict[StrictStr, Any]] = None, + _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, + ) -> WorkspaceMcpServerPublic: + """Update Workspace Mcp Server + + Update a server. Organization owners/admins or this workspace's owners/admins. Only the fields sent are applied. Omit `authorization_token` to leave the stored token alone, send an empty string to clear it, or send a value to rotate it. + + :param workspace_id: (required) + :type workspace_id: UUID + :param server_id: (required) + :type server_id: UUID + :param workspace_mcp_server_update: (required) + :type workspace_mcp_server_update: WorkspaceMcpServerUpdate + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :type _request_timeout: int, tuple(int, int), optional + :param _request_auth: set to override the auth_settings for an a single + request; this effectively ignores the + authentication in the spec for a single request. + :type _request_auth: dict, optional + :param _content_type: force content-type for the request. + :type _content_type: str, Optional + :param _headers: set to override the headers for a single + request; this effectively ignores the headers + in the spec for a single request. + :type _headers: dict, optional + :param _host_index: set to override the host_index for a single + request; this effectively ignores the host_index + in the spec for a single request. + :type _host_index: int, optional + :return: Returns the result object. + """ # noqa: E501 + + _param = self._update_workspace_mcp_server_v1_workspaces_workspace_id_mcp_servers_server_id_patch_serialize( + workspace_id=workspace_id, + server_id=server_id, + workspace_mcp_server_update=workspace_mcp_server_update, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "WorkspaceMcpServerPublic", + '422': "HTTPValidationError", + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + response_data.read() + return self.api_client.response_deserialize( + response_data=response_data, + response_types_map=_response_types_map, + ).data + + + @validate_call + def update_workspace_mcp_server_v1_workspaces_workspace_id_mcp_servers_server_id_patch_with_http_info( + self, + workspace_id: UUID, + server_id: UUID, + workspace_mcp_server_update: WorkspaceMcpServerUpdate, + _request_timeout: Union[ + None, + Annotated[StrictFloat, Field(gt=0)], + Tuple[ + Annotated[StrictFloat, Field(gt=0)], + Annotated[StrictFloat, Field(gt=0)] + ] + ] = None, + _request_auth: Optional[Dict[StrictStr, Any]] = None, + _content_type: Optional[StrictStr] = None, + _headers: Optional[Dict[StrictStr, Any]] = None, + _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, + ) -> ApiResponse[WorkspaceMcpServerPublic]: + """Update Workspace Mcp Server + + Update a server. Organization owners/admins or this workspace's owners/admins. Only the fields sent are applied. Omit `authorization_token` to leave the stored token alone, send an empty string to clear it, or send a value to rotate it. + + :param workspace_id: (required) + :type workspace_id: UUID + :param server_id: (required) + :type server_id: UUID + :param workspace_mcp_server_update: (required) + :type workspace_mcp_server_update: WorkspaceMcpServerUpdate + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :type _request_timeout: int, tuple(int, int), optional + :param _request_auth: set to override the auth_settings for an a single + request; this effectively ignores the + authentication in the spec for a single request. + :type _request_auth: dict, optional + :param _content_type: force content-type for the request. + :type _content_type: str, Optional + :param _headers: set to override the headers for a single + request; this effectively ignores the headers + in the spec for a single request. + :type _headers: dict, optional + :param _host_index: set to override the host_index for a single + request; this effectively ignores the host_index + in the spec for a single request. + :type _host_index: int, optional + :return: Returns the result object. + """ # noqa: E501 + + _param = self._update_workspace_mcp_server_v1_workspaces_workspace_id_mcp_servers_server_id_patch_serialize( + workspace_id=workspace_id, + server_id=server_id, + workspace_mcp_server_update=workspace_mcp_server_update, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "WorkspaceMcpServerPublic", + '422': "HTTPValidationError", + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + response_data.read() + return self.api_client.response_deserialize( + response_data=response_data, + response_types_map=_response_types_map, + ) + + + @validate_call + def update_workspace_mcp_server_v1_workspaces_workspace_id_mcp_servers_server_id_patch_without_preload_content( + self, + workspace_id: UUID, + server_id: UUID, + workspace_mcp_server_update: WorkspaceMcpServerUpdate, + _request_timeout: Union[ + None, + Annotated[StrictFloat, Field(gt=0)], + Tuple[ + Annotated[StrictFloat, Field(gt=0)], + Annotated[StrictFloat, Field(gt=0)] + ] + ] = None, + _request_auth: Optional[Dict[StrictStr, Any]] = None, + _content_type: Optional[StrictStr] = None, + _headers: Optional[Dict[StrictStr, Any]] = None, + _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, + ) -> RESTResponseType: + """Update Workspace Mcp Server + + Update a server. Organization owners/admins or this workspace's owners/admins. Only the fields sent are applied. Omit `authorization_token` to leave the stored token alone, send an empty string to clear it, or send a value to rotate it. + + :param workspace_id: (required) + :type workspace_id: UUID + :param server_id: (required) + :type server_id: UUID + :param workspace_mcp_server_update: (required) + :type workspace_mcp_server_update: WorkspaceMcpServerUpdate + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :type _request_timeout: int, tuple(int, int), optional + :param _request_auth: set to override the auth_settings for an a single + request; this effectively ignores the + authentication in the spec for a single request. + :type _request_auth: dict, optional + :param _content_type: force content-type for the request. + :type _content_type: str, Optional + :param _headers: set to override the headers for a single + request; this effectively ignores the headers + in the spec for a single request. + :type _headers: dict, optional + :param _host_index: set to override the host_index for a single + request; this effectively ignores the host_index + in the spec for a single request. + :type _host_index: int, optional + :return: Returns the result object. + """ # noqa: E501 + + _param = self._update_workspace_mcp_server_v1_workspaces_workspace_id_mcp_servers_server_id_patch_serialize( + workspace_id=workspace_id, + server_id=server_id, + workspace_mcp_server_update=workspace_mcp_server_update, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "WorkspaceMcpServerPublic", + '422': "HTTPValidationError", + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + return response_data.response + + + def _update_workspace_mcp_server_v1_workspaces_workspace_id_mcp_servers_server_id_patch_serialize( + self, + workspace_id, + server_id, + workspace_mcp_server_update, + _request_auth, + _content_type, + _headers, + _host_index, + ) -> RequestSerialized: + + _host = None + + _collection_formats: Dict[str, str] = { + } + + _path_params: Dict[str, str] = {} + _query_params: List[Tuple[str, str]] = [] + _header_params: Dict[str, Optional[str]] = _headers or {} + _form_params: List[Tuple[str, str]] = [] + _files: Dict[ + str, Union[str, bytes, List[str], List[bytes], List[Tuple[str, bytes]]] + ] = {} + _body_params: Optional[bytes] = None + + # process the path parameters + if workspace_id is not None: + _path_params['workspace_id'] = workspace_id + if server_id is not None: + _path_params['server_id'] = server_id + # process the query parameters + # process the header parameters + # process the form parameters + # process the body parameter + if workspace_mcp_server_update is not None: + _body_params = workspace_mcp_server_update + + + # set the HTTP header `Accept` + if 'Accept' not in _header_params: + _header_params['Accept'] = self.api_client.select_header_accept( + [ + 'application/json' + ] + ) + + # set the HTTP header `Content-Type` + if _content_type: + _header_params['Content-Type'] = _content_type + else: + _default_content_type = ( + self.api_client.select_header_content_type( + [ + 'application/json' + ] + ) + ) + if _default_content_type is not None: + _header_params['Content-Type'] = _default_content_type + + # authentication setting + _auth_settings: List[str] = [ + 'XApiKeyAuth', + 'ApiKeyAuth' + ] + + return self.api_client.param_serialize( + method='PATCH', + resource_path='/v1/workspaces/{workspace_id}/mcp-servers/{server_id}', + path_params=_path_params, + query_params=_query_params, + header_params=_header_params, + body=_body_params, + post_params=_form_params, + files=_files, + auth_settings=_auth_settings, + collection_formats=_collection_formats, + _host=_host, + _request_auth=_request_auth + ) + + diff --git a/src/otari/_client/api/scoped_budgets_api.py b/src/otari/_client/api/scoped_budgets_api.py index 32a5d98..2427f2f 100644 --- a/src/otari/_client/api/scoped_budgets_api.py +++ b/src/otari/_client/api/scoped_budgets_api.py @@ -1186,7 +1186,7 @@ def update_scoped_budget_v1_scoped_budgets_budget_id_patch( ) -> ScopedBudgetResponse: """Update Scoped Budget - Update a scoped budget's label, limit, or period. The scope and the provider narrowing are not editable: changing either would move the ceiling to a different identity while carrying its spend, which is a delete and a create, not an update. + Relabel a ceiling, or point it at a different budget. The scope and the provider narrowing are not editable: changing either would move the ceiling to a different identity while carrying its spend, which is a delete and a create, not an update. There is no limit or period to set here any more. Both are properties of the budget, so changing what a ceiling allows is either editing that budget, which moves every ceiling naming it, or naming a different one. :param budget_id: (required) :type budget_id: str @@ -1258,7 +1258,7 @@ def update_scoped_budget_v1_scoped_budgets_budget_id_patch_with_http_info( ) -> ApiResponse[ScopedBudgetResponse]: """Update Scoped Budget - Update a scoped budget's label, limit, or period. The scope and the provider narrowing are not editable: changing either would move the ceiling to a different identity while carrying its spend, which is a delete and a create, not an update. + Relabel a ceiling, or point it at a different budget. The scope and the provider narrowing are not editable: changing either would move the ceiling to a different identity while carrying its spend, which is a delete and a create, not an update. There is no limit or period to set here any more. Both are properties of the budget, so changing what a ceiling allows is either editing that budget, which moves every ceiling naming it, or naming a different one. :param budget_id: (required) :type budget_id: str @@ -1330,7 +1330,7 @@ def update_scoped_budget_v1_scoped_budgets_budget_id_patch_without_preload_conte ) -> RESTResponseType: """Update Scoped Budget - Update a scoped budget's label, limit, or period. The scope and the provider narrowing are not editable: changing either would move the ceiling to a different identity while carrying its spend, which is a delete and a create, not an update. + Relabel a ceiling, or point it at a different budget. The scope and the provider narrowing are not editable: changing either would move the ceiling to a different identity while carrying its spend, which is a delete and a create, not an update. There is no limit or period to set here any more. Both are properties of the budget, so changing what a ceiling allows is either editing that budget, which moves every ceiling naming it, or naming a different one. :param budget_id: (required) :type budget_id: str diff --git a/src/otari/_client/api/workspace_code_execution_policy_api.py b/src/otari/_client/api/workspace_code_execution_policy_api.py new file mode 100644 index 0000000..6eb6b12 --- /dev/null +++ b/src/otari/_client/api/workspace_code_execution_policy_api.py @@ -0,0 +1,860 @@ +""" + otari + + Otari, an OpenAI-compatible LLM gateway with API key management + + The version of the OpenAPI document: 0.0.0-dev + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +import warnings +from pydantic import validate_call, Field, StrictFloat, StrictStr, StrictInt +from typing import Any, Dict, List, Optional, Tuple, Union +from typing_extensions import Annotated + +from uuid import UUID +from otari._client.models.workspace_code_execution_policy_public import WorkspaceCodeExecutionPolicyPublic +from otari._client.models.workspace_code_execution_policy_update import WorkspaceCodeExecutionPolicyUpdate + +from otari._client.api_client import ApiClient, RequestSerialized +from otari._client.api_response import ApiResponse +from otari._client.rest import RESTResponseType + + +class WorkspaceCodeExecutionPolicyApi: + """NOTE: This class is auto generated by OpenAPI Generator + Ref: https://openapi-generator.tech + + Do not edit the class manually. + """ + + def __init__(self, api_client=None) -> None: + if api_client is None: + api_client = ApiClient.get_default() + self.api_client = api_client + + + @validate_call + def clear_workspace_code_execution_policy_v1_workspaces_workspace_id_code_execution_policy_delete( + self, + workspace_id: UUID, + _request_timeout: Union[ + None, + Annotated[StrictFloat, Field(gt=0)], + Tuple[ + Annotated[StrictFloat, Field(gt=0)], + Annotated[StrictFloat, Field(gt=0)] + ] + ] = None, + _request_auth: Optional[Dict[StrictStr, Any]] = None, + _content_type: Optional[StrictStr] = None, + _headers: Optional[Dict[StrictStr, Any]] = None, + _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, + ) -> WorkspaceCodeExecutionPolicyPublic: + """Clear Workspace Code Execution Policy + + Drop a workspace's policy, returning it to the deployment's behavior. Idempotent: a workspace that has no policy is already in the state this asks for, so it answers with the unconfigured policy rather than a 404. + + :param workspace_id: (required) + :type workspace_id: UUID + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :type _request_timeout: int, tuple(int, int), optional + :param _request_auth: set to override the auth_settings for an a single + request; this effectively ignores the + authentication in the spec for a single request. + :type _request_auth: dict, optional + :param _content_type: force content-type for the request. + :type _content_type: str, Optional + :param _headers: set to override the headers for a single + request; this effectively ignores the headers + in the spec for a single request. + :type _headers: dict, optional + :param _host_index: set to override the host_index for a single + request; this effectively ignores the host_index + in the spec for a single request. + :type _host_index: int, optional + :return: Returns the result object. + """ # noqa: E501 + + _param = self._clear_workspace_code_execution_policy_v1_workspaces_workspace_id_code_execution_policy_delete_serialize( + workspace_id=workspace_id, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "WorkspaceCodeExecutionPolicyPublic", + '422': "HTTPValidationError", + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + response_data.read() + return self.api_client.response_deserialize( + response_data=response_data, + response_types_map=_response_types_map, + ).data + + + @validate_call + def clear_workspace_code_execution_policy_v1_workspaces_workspace_id_code_execution_policy_delete_with_http_info( + self, + workspace_id: UUID, + _request_timeout: Union[ + None, + Annotated[StrictFloat, Field(gt=0)], + Tuple[ + Annotated[StrictFloat, Field(gt=0)], + Annotated[StrictFloat, Field(gt=0)] + ] + ] = None, + _request_auth: Optional[Dict[StrictStr, Any]] = None, + _content_type: Optional[StrictStr] = None, + _headers: Optional[Dict[StrictStr, Any]] = None, + _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, + ) -> ApiResponse[WorkspaceCodeExecutionPolicyPublic]: + """Clear Workspace Code Execution Policy + + Drop a workspace's policy, returning it to the deployment's behavior. Idempotent: a workspace that has no policy is already in the state this asks for, so it answers with the unconfigured policy rather than a 404. + + :param workspace_id: (required) + :type workspace_id: UUID + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :type _request_timeout: int, tuple(int, int), optional + :param _request_auth: set to override the auth_settings for an a single + request; this effectively ignores the + authentication in the spec for a single request. + :type _request_auth: dict, optional + :param _content_type: force content-type for the request. + :type _content_type: str, Optional + :param _headers: set to override the headers for a single + request; this effectively ignores the headers + in the spec for a single request. + :type _headers: dict, optional + :param _host_index: set to override the host_index for a single + request; this effectively ignores the host_index + in the spec for a single request. + :type _host_index: int, optional + :return: Returns the result object. + """ # noqa: E501 + + _param = self._clear_workspace_code_execution_policy_v1_workspaces_workspace_id_code_execution_policy_delete_serialize( + workspace_id=workspace_id, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "WorkspaceCodeExecutionPolicyPublic", + '422': "HTTPValidationError", + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + response_data.read() + return self.api_client.response_deserialize( + response_data=response_data, + response_types_map=_response_types_map, + ) + + + @validate_call + def clear_workspace_code_execution_policy_v1_workspaces_workspace_id_code_execution_policy_delete_without_preload_content( + self, + workspace_id: UUID, + _request_timeout: Union[ + None, + Annotated[StrictFloat, Field(gt=0)], + Tuple[ + Annotated[StrictFloat, Field(gt=0)], + Annotated[StrictFloat, Field(gt=0)] + ] + ] = None, + _request_auth: Optional[Dict[StrictStr, Any]] = None, + _content_type: Optional[StrictStr] = None, + _headers: Optional[Dict[StrictStr, Any]] = None, + _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, + ) -> RESTResponseType: + """Clear Workspace Code Execution Policy + + Drop a workspace's policy, returning it to the deployment's behavior. Idempotent: a workspace that has no policy is already in the state this asks for, so it answers with the unconfigured policy rather than a 404. + + :param workspace_id: (required) + :type workspace_id: UUID + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :type _request_timeout: int, tuple(int, int), optional + :param _request_auth: set to override the auth_settings for an a single + request; this effectively ignores the + authentication in the spec for a single request. + :type _request_auth: dict, optional + :param _content_type: force content-type for the request. + :type _content_type: str, Optional + :param _headers: set to override the headers for a single + request; this effectively ignores the headers + in the spec for a single request. + :type _headers: dict, optional + :param _host_index: set to override the host_index for a single + request; this effectively ignores the host_index + in the spec for a single request. + :type _host_index: int, optional + :return: Returns the result object. + """ # noqa: E501 + + _param = self._clear_workspace_code_execution_policy_v1_workspaces_workspace_id_code_execution_policy_delete_serialize( + workspace_id=workspace_id, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "WorkspaceCodeExecutionPolicyPublic", + '422': "HTTPValidationError", + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + return response_data.response + + + def _clear_workspace_code_execution_policy_v1_workspaces_workspace_id_code_execution_policy_delete_serialize( + self, + workspace_id, + _request_auth, + _content_type, + _headers, + _host_index, + ) -> RequestSerialized: + + _host = None + + _collection_formats: Dict[str, str] = { + } + + _path_params: Dict[str, str] = {} + _query_params: List[Tuple[str, str]] = [] + _header_params: Dict[str, Optional[str]] = _headers or {} + _form_params: List[Tuple[str, str]] = [] + _files: Dict[ + str, Union[str, bytes, List[str], List[bytes], List[Tuple[str, bytes]]] + ] = {} + _body_params: Optional[bytes] = None + + # process the path parameters + if workspace_id is not None: + _path_params['workspace_id'] = workspace_id + # process the query parameters + # process the header parameters + # process the form parameters + # process the body parameter + + + # set the HTTP header `Accept` + if 'Accept' not in _header_params: + _header_params['Accept'] = self.api_client.select_header_accept( + [ + 'application/json' + ] + ) + + + # authentication setting + _auth_settings: List[str] = [ + 'XApiKeyAuth', + 'ApiKeyAuth' + ] + + return self.api_client.param_serialize( + method='DELETE', + resource_path='/v1/workspaces/{workspace_id}/code-execution-policy', + path_params=_path_params, + query_params=_query_params, + header_params=_header_params, + body=_body_params, + post_params=_form_params, + files=_files, + auth_settings=_auth_settings, + collection_formats=_collection_formats, + _host=_host, + _request_auth=_request_auth + ) + + + + + @validate_call + def get_workspace_code_execution_policy_v1_workspaces_workspace_id_code_execution_policy_get( + self, + workspace_id: UUID, + _request_timeout: Union[ + None, + Annotated[StrictFloat, Field(gt=0)], + Tuple[ + Annotated[StrictFloat, Field(gt=0)], + Annotated[StrictFloat, Field(gt=0)] + ] + ] = None, + _request_auth: Optional[Dict[StrictStr, Any]] = None, + _content_type: Optional[StrictStr] = None, + _headers: Optional[Dict[StrictStr, Any]] = None, + _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, + ) -> WorkspaceCodeExecutionPolicyPublic: + """Get Workspace Code Execution Policy + + Read a workspace's code-execution policy. Takes the same role as setting it (an organization owner/admin, or an owner/admin of this workspace), because the policy describes the workspace's security and billing posture rather than one member's allowance. A workspace with no policy answers with the unconfigured one (``configured: false``), which is the deployment's own behavior described in the same shape rather than a 404. + + :param workspace_id: (required) + :type workspace_id: UUID + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :type _request_timeout: int, tuple(int, int), optional + :param _request_auth: set to override the auth_settings for an a single + request; this effectively ignores the + authentication in the spec for a single request. + :type _request_auth: dict, optional + :param _content_type: force content-type for the request. + :type _content_type: str, Optional + :param _headers: set to override the headers for a single + request; this effectively ignores the headers + in the spec for a single request. + :type _headers: dict, optional + :param _host_index: set to override the host_index for a single + request; this effectively ignores the host_index + in the spec for a single request. + :type _host_index: int, optional + :return: Returns the result object. + """ # noqa: E501 + + _param = self._get_workspace_code_execution_policy_v1_workspaces_workspace_id_code_execution_policy_get_serialize( + workspace_id=workspace_id, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "WorkspaceCodeExecutionPolicyPublic", + '422': "HTTPValidationError", + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + response_data.read() + return self.api_client.response_deserialize( + response_data=response_data, + response_types_map=_response_types_map, + ).data + + + @validate_call + def get_workspace_code_execution_policy_v1_workspaces_workspace_id_code_execution_policy_get_with_http_info( + self, + workspace_id: UUID, + _request_timeout: Union[ + None, + Annotated[StrictFloat, Field(gt=0)], + Tuple[ + Annotated[StrictFloat, Field(gt=0)], + Annotated[StrictFloat, Field(gt=0)] + ] + ] = None, + _request_auth: Optional[Dict[StrictStr, Any]] = None, + _content_type: Optional[StrictStr] = None, + _headers: Optional[Dict[StrictStr, Any]] = None, + _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, + ) -> ApiResponse[WorkspaceCodeExecutionPolicyPublic]: + """Get Workspace Code Execution Policy + + Read a workspace's code-execution policy. Takes the same role as setting it (an organization owner/admin, or an owner/admin of this workspace), because the policy describes the workspace's security and billing posture rather than one member's allowance. A workspace with no policy answers with the unconfigured one (``configured: false``), which is the deployment's own behavior described in the same shape rather than a 404. + + :param workspace_id: (required) + :type workspace_id: UUID + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :type _request_timeout: int, tuple(int, int), optional + :param _request_auth: set to override the auth_settings for an a single + request; this effectively ignores the + authentication in the spec for a single request. + :type _request_auth: dict, optional + :param _content_type: force content-type for the request. + :type _content_type: str, Optional + :param _headers: set to override the headers for a single + request; this effectively ignores the headers + in the spec for a single request. + :type _headers: dict, optional + :param _host_index: set to override the host_index for a single + request; this effectively ignores the host_index + in the spec for a single request. + :type _host_index: int, optional + :return: Returns the result object. + """ # noqa: E501 + + _param = self._get_workspace_code_execution_policy_v1_workspaces_workspace_id_code_execution_policy_get_serialize( + workspace_id=workspace_id, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "WorkspaceCodeExecutionPolicyPublic", + '422': "HTTPValidationError", + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + response_data.read() + return self.api_client.response_deserialize( + response_data=response_data, + response_types_map=_response_types_map, + ) + + + @validate_call + def get_workspace_code_execution_policy_v1_workspaces_workspace_id_code_execution_policy_get_without_preload_content( + self, + workspace_id: UUID, + _request_timeout: Union[ + None, + Annotated[StrictFloat, Field(gt=0)], + Tuple[ + Annotated[StrictFloat, Field(gt=0)], + Annotated[StrictFloat, Field(gt=0)] + ] + ] = None, + _request_auth: Optional[Dict[StrictStr, Any]] = None, + _content_type: Optional[StrictStr] = None, + _headers: Optional[Dict[StrictStr, Any]] = None, + _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, + ) -> RESTResponseType: + """Get Workspace Code Execution Policy + + Read a workspace's code-execution policy. Takes the same role as setting it (an organization owner/admin, or an owner/admin of this workspace), because the policy describes the workspace's security and billing posture rather than one member's allowance. A workspace with no policy answers with the unconfigured one (``configured: false``), which is the deployment's own behavior described in the same shape rather than a 404. + + :param workspace_id: (required) + :type workspace_id: UUID + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :type _request_timeout: int, tuple(int, int), optional + :param _request_auth: set to override the auth_settings for an a single + request; this effectively ignores the + authentication in the spec for a single request. + :type _request_auth: dict, optional + :param _content_type: force content-type for the request. + :type _content_type: str, Optional + :param _headers: set to override the headers for a single + request; this effectively ignores the headers + in the spec for a single request. + :type _headers: dict, optional + :param _host_index: set to override the host_index for a single + request; this effectively ignores the host_index + in the spec for a single request. + :type _host_index: int, optional + :return: Returns the result object. + """ # noqa: E501 + + _param = self._get_workspace_code_execution_policy_v1_workspaces_workspace_id_code_execution_policy_get_serialize( + workspace_id=workspace_id, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "WorkspaceCodeExecutionPolicyPublic", + '422': "HTTPValidationError", + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + return response_data.response + + + def _get_workspace_code_execution_policy_v1_workspaces_workspace_id_code_execution_policy_get_serialize( + self, + workspace_id, + _request_auth, + _content_type, + _headers, + _host_index, + ) -> RequestSerialized: + + _host = None + + _collection_formats: Dict[str, str] = { + } + + _path_params: Dict[str, str] = {} + _query_params: List[Tuple[str, str]] = [] + _header_params: Dict[str, Optional[str]] = _headers or {} + _form_params: List[Tuple[str, str]] = [] + _files: Dict[ + str, Union[str, bytes, List[str], List[bytes], List[Tuple[str, bytes]]] + ] = {} + _body_params: Optional[bytes] = None + + # process the path parameters + if workspace_id is not None: + _path_params['workspace_id'] = workspace_id + # process the query parameters + # process the header parameters + # process the form parameters + # process the body parameter + + + # set the HTTP header `Accept` + if 'Accept' not in _header_params: + _header_params['Accept'] = self.api_client.select_header_accept( + [ + 'application/json' + ] + ) + + + # authentication setting + _auth_settings: List[str] = [ + 'XApiKeyAuth', + 'ApiKeyAuth' + ] + + return self.api_client.param_serialize( + method='GET', + resource_path='/v1/workspaces/{workspace_id}/code-execution-policy', + path_params=_path_params, + query_params=_query_params, + header_params=_header_params, + body=_body_params, + post_params=_form_params, + files=_files, + auth_settings=_auth_settings, + collection_formats=_collection_formats, + _host=_host, + _request_auth=_request_auth + ) + + + + + @validate_call + def set_workspace_code_execution_policy_v1_workspaces_workspace_id_code_execution_policy_put( + self, + workspace_id: UUID, + workspace_code_execution_policy_update: WorkspaceCodeExecutionPolicyUpdate, + _request_timeout: Union[ + None, + Annotated[StrictFloat, Field(gt=0)], + Tuple[ + Annotated[StrictFloat, Field(gt=0)], + Annotated[StrictFloat, Field(gt=0)] + ] + ] = None, + _request_auth: Optional[Dict[StrictStr, Any]] = None, + _content_type: Optional[StrictStr] = None, + _headers: Optional[Dict[StrictStr, Any]] = None, + _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, + ) -> WorkspaceCodeExecutionPolicyPublic: + """Set Workspace Code Execution Policy + + Set a workspace's code-execution policy, replacing any existing one. An organization owner/admin, or an owner/admin of this workspace, may write it. The policy can only narrow what the deployment permits: turning code execution off for the workspace, and lowering the loop and execution ceilings. It never turns a sandbox the deployment has not configured on. + + :param workspace_id: (required) + :type workspace_id: UUID + :param workspace_code_execution_policy_update: (required) + :type workspace_code_execution_policy_update: WorkspaceCodeExecutionPolicyUpdate + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :type _request_timeout: int, tuple(int, int), optional + :param _request_auth: set to override the auth_settings for an a single + request; this effectively ignores the + authentication in the spec for a single request. + :type _request_auth: dict, optional + :param _content_type: force content-type for the request. + :type _content_type: str, Optional + :param _headers: set to override the headers for a single + request; this effectively ignores the headers + in the spec for a single request. + :type _headers: dict, optional + :param _host_index: set to override the host_index for a single + request; this effectively ignores the host_index + in the spec for a single request. + :type _host_index: int, optional + :return: Returns the result object. + """ # noqa: E501 + + _param = self._set_workspace_code_execution_policy_v1_workspaces_workspace_id_code_execution_policy_put_serialize( + workspace_id=workspace_id, + workspace_code_execution_policy_update=workspace_code_execution_policy_update, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "WorkspaceCodeExecutionPolicyPublic", + '422': "HTTPValidationError", + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + response_data.read() + return self.api_client.response_deserialize( + response_data=response_data, + response_types_map=_response_types_map, + ).data + + + @validate_call + def set_workspace_code_execution_policy_v1_workspaces_workspace_id_code_execution_policy_put_with_http_info( + self, + workspace_id: UUID, + workspace_code_execution_policy_update: WorkspaceCodeExecutionPolicyUpdate, + _request_timeout: Union[ + None, + Annotated[StrictFloat, Field(gt=0)], + Tuple[ + Annotated[StrictFloat, Field(gt=0)], + Annotated[StrictFloat, Field(gt=0)] + ] + ] = None, + _request_auth: Optional[Dict[StrictStr, Any]] = None, + _content_type: Optional[StrictStr] = None, + _headers: Optional[Dict[StrictStr, Any]] = None, + _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, + ) -> ApiResponse[WorkspaceCodeExecutionPolicyPublic]: + """Set Workspace Code Execution Policy + + Set a workspace's code-execution policy, replacing any existing one. An organization owner/admin, or an owner/admin of this workspace, may write it. The policy can only narrow what the deployment permits: turning code execution off for the workspace, and lowering the loop and execution ceilings. It never turns a sandbox the deployment has not configured on. + + :param workspace_id: (required) + :type workspace_id: UUID + :param workspace_code_execution_policy_update: (required) + :type workspace_code_execution_policy_update: WorkspaceCodeExecutionPolicyUpdate + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :type _request_timeout: int, tuple(int, int), optional + :param _request_auth: set to override the auth_settings for an a single + request; this effectively ignores the + authentication in the spec for a single request. + :type _request_auth: dict, optional + :param _content_type: force content-type for the request. + :type _content_type: str, Optional + :param _headers: set to override the headers for a single + request; this effectively ignores the headers + in the spec for a single request. + :type _headers: dict, optional + :param _host_index: set to override the host_index for a single + request; this effectively ignores the host_index + in the spec for a single request. + :type _host_index: int, optional + :return: Returns the result object. + """ # noqa: E501 + + _param = self._set_workspace_code_execution_policy_v1_workspaces_workspace_id_code_execution_policy_put_serialize( + workspace_id=workspace_id, + workspace_code_execution_policy_update=workspace_code_execution_policy_update, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "WorkspaceCodeExecutionPolicyPublic", + '422': "HTTPValidationError", + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + response_data.read() + return self.api_client.response_deserialize( + response_data=response_data, + response_types_map=_response_types_map, + ) + + + @validate_call + def set_workspace_code_execution_policy_v1_workspaces_workspace_id_code_execution_policy_put_without_preload_content( + self, + workspace_id: UUID, + workspace_code_execution_policy_update: WorkspaceCodeExecutionPolicyUpdate, + _request_timeout: Union[ + None, + Annotated[StrictFloat, Field(gt=0)], + Tuple[ + Annotated[StrictFloat, Field(gt=0)], + Annotated[StrictFloat, Field(gt=0)] + ] + ] = None, + _request_auth: Optional[Dict[StrictStr, Any]] = None, + _content_type: Optional[StrictStr] = None, + _headers: Optional[Dict[StrictStr, Any]] = None, + _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, + ) -> RESTResponseType: + """Set Workspace Code Execution Policy + + Set a workspace's code-execution policy, replacing any existing one. An organization owner/admin, or an owner/admin of this workspace, may write it. The policy can only narrow what the deployment permits: turning code execution off for the workspace, and lowering the loop and execution ceilings. It never turns a sandbox the deployment has not configured on. + + :param workspace_id: (required) + :type workspace_id: UUID + :param workspace_code_execution_policy_update: (required) + :type workspace_code_execution_policy_update: WorkspaceCodeExecutionPolicyUpdate + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :type _request_timeout: int, tuple(int, int), optional + :param _request_auth: set to override the auth_settings for an a single + request; this effectively ignores the + authentication in the spec for a single request. + :type _request_auth: dict, optional + :param _content_type: force content-type for the request. + :type _content_type: str, Optional + :param _headers: set to override the headers for a single + request; this effectively ignores the headers + in the spec for a single request. + :type _headers: dict, optional + :param _host_index: set to override the host_index for a single + request; this effectively ignores the host_index + in the spec for a single request. + :type _host_index: int, optional + :return: Returns the result object. + """ # noqa: E501 + + _param = self._set_workspace_code_execution_policy_v1_workspaces_workspace_id_code_execution_policy_put_serialize( + workspace_id=workspace_id, + workspace_code_execution_policy_update=workspace_code_execution_policy_update, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "WorkspaceCodeExecutionPolicyPublic", + '422': "HTTPValidationError", + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + return response_data.response + + + def _set_workspace_code_execution_policy_v1_workspaces_workspace_id_code_execution_policy_put_serialize( + self, + workspace_id, + workspace_code_execution_policy_update, + _request_auth, + _content_type, + _headers, + _host_index, + ) -> RequestSerialized: + + _host = None + + _collection_formats: Dict[str, str] = { + } + + _path_params: Dict[str, str] = {} + _query_params: List[Tuple[str, str]] = [] + _header_params: Dict[str, Optional[str]] = _headers or {} + _form_params: List[Tuple[str, str]] = [] + _files: Dict[ + str, Union[str, bytes, List[str], List[bytes], List[Tuple[str, bytes]]] + ] = {} + _body_params: Optional[bytes] = None + + # process the path parameters + if workspace_id is not None: + _path_params['workspace_id'] = workspace_id + # process the query parameters + # process the header parameters + # process the form parameters + # process the body parameter + if workspace_code_execution_policy_update is not None: + _body_params = workspace_code_execution_policy_update + + + # set the HTTP header `Accept` + if 'Accept' not in _header_params: + _header_params['Accept'] = self.api_client.select_header_accept( + [ + 'application/json' + ] + ) + + # set the HTTP header `Content-Type` + if _content_type: + _header_params['Content-Type'] = _content_type + else: + _default_content_type = ( + self.api_client.select_header_content_type( + [ + 'application/json' + ] + ) + ) + if _default_content_type is not None: + _header_params['Content-Type'] = _default_content_type + + # authentication setting + _auth_settings: List[str] = [ + 'XApiKeyAuth', + 'ApiKeyAuth' + ] + + return self.api_client.param_serialize( + method='PUT', + resource_path='/v1/workspaces/{workspace_id}/code-execution-policy', + path_params=_path_params, + query_params=_query_params, + header_params=_header_params, + body=_body_params, + post_params=_form_params, + files=_files, + auth_settings=_auth_settings, + collection_formats=_collection_formats, + _host=_host, + _request_auth=_request_auth + ) + + diff --git a/src/otari/_client/models/__init__.py b/src/otari/_client/models/__init__.py index 0c7f177..f1288fb 100644 --- a/src/otari/_client/models/__init__.py +++ b/src/otari/_client/models/__init__.py @@ -323,8 +323,13 @@ from otari._client.models.recorded_pool import RecordedPool from otari._client.models.reencrypt_provider_credentials_response import ReencryptProviderCredentialsResponse from otari._client.models.reencrypt_search_tools_response import ReencryptSearchToolsResponse +from otari._client.models.request_password_reset_request import RequestPasswordResetRequest +from otari._client.models.request_password_reset_response import RequestPasswordResetResponse from otari._client.models.rerank_request import RerankRequest from otari._client.models.rerank_response import RerankResponse +from otari._client.models.resend_verification_request import ResendVerificationRequest +from otari._client.models.resend_verification_response import ResendVerificationResponse +from otari._client.models.reset_password_request import ResetPasswordRequest from otari._client.models.responses_request import ResponsesRequest from otari._client.models.rotate_master_key_response import RotateMasterKeyResponse from otari._client.models.router_status import RouterStatus @@ -340,6 +345,8 @@ from otari._client.models.session_response import SessionResponse from otari._client.models.set_password_request import SetPasswordRequest from otari._client.models.set_pricing_request import SetPricingRequest +from otari._client.models.signup_request import SignupRequest +from otari._client.models.signup_response import SignupResponse from otari._client.models.source import Source from otari._client.models.source1 import Source1 from otari._client.models.stop import Stop @@ -392,9 +399,17 @@ from otari._client.models.validation_error import ValidationError from otari._client.models.value import Value from otari._client.models.value1 import Value1 +from otari._client.models.verify_email_request import VerifyEmailRequest +from otari._client.models.verify_email_response import VerifyEmailResponse from otari._client.models.workspace_activation_public import WorkspaceActivationPublic from otari._client.models.workspace_assignment_request import WorkspaceAssignmentRequest +from otari._client.models.workspace_code_execution_policy_public import WorkspaceCodeExecutionPolicyPublic +from otari._client.models.workspace_code_execution_policy_update import WorkspaceCodeExecutionPolicyUpdate from otari._client.models.workspace_create import WorkspaceCreate +from otari._client.models.workspace_mcp_server_create import WorkspaceMcpServerCreate +from otari._client.models.workspace_mcp_server_public import WorkspaceMcpServerPublic +from otari._client.models.workspace_mcp_server_update import WorkspaceMcpServerUpdate +from otari._client.models.workspace_mcp_servers_public import WorkspaceMcpServersPublic from otari._client.models.workspace_member_budget_policies_public import WorkspaceMemberBudgetPoliciesPublic from otari._client.models.workspace_member_budget_policy_create import WorkspaceMemberBudgetPolicyCreate from otari._client.models.workspace_member_budget_policy_public import WorkspaceMemberBudgetPolicyPublic diff --git a/src/otari/_client/models/active_organization_member_public.py b/src/otari/_client/models/active_organization_member_public.py index 1f51c72..e042e9b 100644 --- a/src/otari/_client/models/active_organization_member_public.py +++ b/src/otari/_client/models/active_organization_member_public.py @@ -27,7 +27,7 @@ class ActiveOrganizationMemberPublic(BaseModel): """ - A member row joined to the identity behind it, as the roster shows it. Field-for-field the platform's shape, so the ported roster page is not rewritten around a new contract, with two consequences of the OSS line: ``email`` is nullable here (a local operator identity has no sign-in address), and ``invitation_id`` is always null until the invitation flow rehomes, which is what fills it. ``attribution_user_id`` is the addition the platform has no counterpart for. Keys, budgets, and usage attach to the gateway's string-keyed ``users`` row, not to this UUID identity, so this carries the ``user_id`` a caller passes to ``POST /v1/keys`` to give this member a key. It is null when no usable row exists (nobody minted one, or it was soft-deleted through ``DELETE /v1/users``), which is the signal not to offer this member as a key owner: key creation would refuse. The two ids converge when the request plane re-parents onto tenancy (M4), and this field is what lets that happen without the dashboard changing. + A member row joined to the identity behind it, as the roster shows it. Field-for-field the platform's shape, so the ported roster page is not rewritten around a new contract, with two consequences of the OSS line: ``email`` is nullable here (a local operator identity has no sign-in address), and ``invitation_id`` is always null until the invitation flow rehomes, which is what fills it. ``attribution_user_id`` is the addition the platform has no counterpart for. Keys, budgets, and usage attach to the gateway's string-keyed ``users`` row, not to this UUID identity, so this carries the ``user_id`` a caller passes to ``POST /v1/keys`` to give this member a key. It is null when no usable row exists (nobody minted one, or it was soft-deleted through ``DELETE /v1/users``), which is the signal not to offer this member as a key owner: key creation would refuse. How the two ids converge is the open question in otari-ai#1727; this field is the join until it is answered, and is what lets either answer land without the dashboard changing. """ # noqa: E501 attribution_user_id: Optional[StrictStr] = None created_at: datetime diff --git a/src/otari/_client/models/budget_response.py b/src/otari/_client/models/budget_response.py index fd4ed18..6af1cd6 100644 --- a/src/otari/_client/models/budget_response.py +++ b/src/otari/_client/models/budget_response.py @@ -32,11 +32,12 @@ class BudgetResponse(BaseModel): created_at: StrictStr max_budget: Optional[Union[StrictFloat, StrictInt]] name: Optional[StrictStr] + reset_alignment: Optional[StrictStr] total_reserved: Optional[Union[StrictFloat, StrictInt]] = 0.0 total_spend: Optional[Union[StrictFloat, StrictInt]] = 0.0 updated_at: StrictStr user_count: Optional[StrictInt] = 0 - __properties: ClassVar[List[str]] = ["budget_duration_sec", "budget_id", "created_at", "max_budget", "name", "total_reserved", "total_spend", "updated_at", "user_count"] + __properties: ClassVar[List[str]] = ["budget_duration_sec", "budget_id", "created_at", "max_budget", "name", "reset_alignment", "total_reserved", "total_spend", "updated_at", "user_count"] model_config = ConfigDict( validate_by_name=True, @@ -92,6 +93,11 @@ def to_dict(self) -> Dict[str, Any]: if self.name is None and "name" in self.model_fields_set: _dict['name'] = None + # set to None if reset_alignment (nullable) is None + # and model_fields_set contains the field + if self.reset_alignment is None and "reset_alignment" in self.model_fields_set: + _dict['reset_alignment'] = None + return _dict @classmethod @@ -109,6 +115,7 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: "created_at": obj.get("created_at"), "max_budget": obj.get("max_budget"), "name": obj.get("name"), + "reset_alignment": obj.get("reset_alignment"), "total_reserved": obj.get("total_reserved") if obj.get("total_reserved") is not None else 0.0, "total_spend": obj.get("total_spend") if obj.get("total_spend") is not None else 0.0, "updated_at": obj.get("updated_at"), diff --git a/src/otari/_client/models/chat_completion_request.py b/src/otari/_client/models/chat_completion_request.py index 129522c..231f045 100644 --- a/src/otari/_client/models/chat_completion_request.py +++ b/src/otari/_client/models/chat_completion_request.py @@ -42,7 +42,7 @@ class ChatCompletionRequest(BaseModel): max_completion_tokens: Optional[StrictInt] = None max_tokens: Optional[StrictInt] = None max_tool_iterations: Optional[Annotated[int, Field(le=25, strict=True, ge=1)]] = None - mcp_server_ids: Optional[List[UUID]] = None + mcp_server_ids: Optional[Annotated[List[UUID], Field(max_length=50)]] = None mcp_servers: Optional[List[McpServerConfig]] = None messages: Annotated[List[ChatMessageInput], Field(min_length=1)] model: StrictStr diff --git a/src/otari/_client/models/create_budget_request.py b/src/otari/_client/models/create_budget_request.py index 87acd46..f204b8b 100644 --- a/src/otari/_client/models/create_budget_request.py +++ b/src/otari/_client/models/create_budget_request.py @@ -17,7 +17,7 @@ import re # noqa: F401 import json -from pydantic import BaseModel, ConfigDict, Field, StrictStr +from pydantic import BaseModel, ConfigDict, Field, StrictStr, field_validator from typing import Any, ClassVar, Dict, List, Optional, Union from typing_extensions import Annotated from typing import Optional, Set @@ -29,9 +29,20 @@ class CreateBudgetRequest(BaseModel): Request model for creating a new budget. """ # noqa: E501 budget_duration_sec: Optional[Annotated[int, Field(strict=True, gt=0)]] = Field(default=None, description="Budget duration in seconds (e.g., 86400 for daily, 604800 for weekly)") - max_budget: Optional[Union[Annotated[float, Field(strict=True, ge=0.0)], Annotated[int, Field(strict=True, ge=0)]]] = Field(default=None, description="Maximum spending limit") + max_budget: Optional[Union[Annotated[float, Field(le=999999999999, strict=True, ge=0.0)], Annotated[int, Field(le=2147483647, strict=True, ge=0)]]] = Field(default=None, description="Maximum spending limit") name: Optional[StrictStr] = Field(default=None, description="Admin-facing label for the budget") - __properties: ClassVar[List[str]] = ["budget_duration_sec", "max_budget", "name"] + reset_alignment: Optional[StrictStr] = Field(default=None, description="Reset on a UTC calendar boundary instead of a fixed number of seconds, which is the only way to express a calendar month. Mutually exclusive with budget_duration_sec") + __properties: ClassVar[List[str]] = ["budget_duration_sec", "max_budget", "name", "reset_alignment"] + + @field_validator('reset_alignment') + def reset_alignment_validate_enum(cls, value): + """Validates the enum""" + if value is None: + return value + + if value not in set(['calendar_day', 'calendar_week', 'calendar_month']): + raise ValueError("must be one of enum values ('calendar_day', 'calendar_week', 'calendar_month')") + return value model_config = ConfigDict( validate_by_name=True, @@ -87,6 +98,11 @@ def to_dict(self) -> Dict[str, Any]: if self.name is None and "name" in self.model_fields_set: _dict['name'] = None + # set to None if reset_alignment (nullable) is None + # and model_fields_set contains the field + if self.reset_alignment is None and "reset_alignment" in self.model_fields_set: + _dict['reset_alignment'] = None + return _dict @classmethod @@ -101,7 +117,8 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: _obj = cls.model_validate({ "budget_duration_sec": obj.get("budget_duration_sec"), "max_budget": obj.get("max_budget"), - "name": obj.get("name") + "name": obj.get("name"), + "reset_alignment": obj.get("reset_alignment") }) return _obj diff --git a/src/otari/_client/models/create_scoped_budget_request.py b/src/otari/_client/models/create_scoped_budget_request.py index 33a65c2..e0192c3 100644 --- a/src/otari/_client/models/create_scoped_budget_request.py +++ b/src/otari/_client/models/create_scoped_budget_request.py @@ -18,7 +18,7 @@ import json from pydantic import BaseModel, ConfigDict, Field, StrictStr, field_validator -from typing import Any, ClassVar, Dict, List, Optional, Union +from typing import Any, ClassVar, Dict, List, Optional from typing_extensions import Annotated from typing import Optional, Set from typing_extensions import Self @@ -28,24 +28,12 @@ class CreateScopedBudgetRequest(BaseModel): """ Request model for creating a scoped budget. """ # noqa: E501 - budget_duration_sec: Optional[Annotated[int, Field(strict=True, gt=0)]] = Field(default=None, description="Period length in seconds (e.g. 86400 for daily); null never resets") - max_budget: Optional[Union[Annotated[float, Field(strict=True, ge=0.0)], Annotated[int, Field(strict=True, ge=0)]]] = Field(default=None, description="Maximum USD spend in the period") - name: Optional[Annotated[str, Field(strict=True, max_length=200)]] = Field(default=None, description="Admin-facing label for the budget") + budget_id: Annotated[str, Field(min_length=1, strict=True, max_length=255)] = Field(description="The budget this ceiling enforces; its limit and period are read through it") + name: Optional[Annotated[str, Field(strict=True, max_length=200)]] = Field(default=None, description="Admin-facing label for this ceiling") provider_key_id: Optional[Annotated[str, Field(strict=True, max_length=255)]] = Field(default=None, description="Narrow the cap to one provider instance; null caps spend across every provider") - reset_alignment: Optional[StrictStr] = Field(default=None, description="Reset on a UTC calendar boundary instead of a fixed number of seconds, which is the only way to express a calendar month. Mutually exclusive with budget_duration_sec") scope_id: Annotated[str, Field(min_length=1, strict=True, max_length=255)] = Field(description="Id of the capped identity: an organization, workspace, membership row, or API key") scope_type: StrictStr = Field(description="Which kind of identity this ceiling caps") - __properties: ClassVar[List[str]] = ["budget_duration_sec", "max_budget", "name", "provider_key_id", "reset_alignment", "scope_id", "scope_type"] - - @field_validator('reset_alignment') - def reset_alignment_validate_enum(cls, value): - """Validates the enum""" - if value is None: - return value - - if value not in set(['calendar_day', 'calendar_week', 'calendar_month']): - raise ValueError("must be one of enum values ('calendar_day', 'calendar_week', 'calendar_month')") - return value + __properties: ClassVar[List[str]] = ["budget_id", "name", "provider_key_id", "scope_id", "scope_type"] @field_validator('scope_type') def scope_type_validate_enum(cls, value): @@ -93,16 +81,6 @@ def to_dict(self) -> Dict[str, Any]: exclude=excluded_fields, exclude_none=True, ) - # set to None if budget_duration_sec (nullable) is None - # and model_fields_set contains the field - if self.budget_duration_sec is None and "budget_duration_sec" in self.model_fields_set: - _dict['budget_duration_sec'] = None - - # set to None if max_budget (nullable) is None - # and model_fields_set contains the field - if self.max_budget is None and "max_budget" in self.model_fields_set: - _dict['max_budget'] = None - # set to None if name (nullable) is None # and model_fields_set contains the field if self.name is None and "name" in self.model_fields_set: @@ -113,11 +91,6 @@ def to_dict(self) -> Dict[str, Any]: if self.provider_key_id is None and "provider_key_id" in self.model_fields_set: _dict['provider_key_id'] = None - # set to None if reset_alignment (nullable) is None - # and model_fields_set contains the field - if self.reset_alignment is None and "reset_alignment" in self.model_fields_set: - _dict['reset_alignment'] = None - return _dict @classmethod @@ -130,11 +103,9 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: return cls.model_validate(obj) _obj = cls.model_validate({ - "budget_duration_sec": obj.get("budget_duration_sec"), - "max_budget": obj.get("max_budget"), + "budget_id": obj.get("budget_id"), "name": obj.get("name"), "provider_key_id": obj.get("provider_key_id"), - "reset_alignment": obj.get("reset_alignment"), "scope_id": obj.get("scope_id"), "scope_type": obj.get("scope_type") }) diff --git a/src/otari/_client/models/messages_request.py b/src/otari/_client/models/messages_request.py index b7dd282..92c8ec0 100644 --- a/src/otari/_client/models/messages_request.py +++ b/src/otari/_client/models/messages_request.py @@ -38,7 +38,7 @@ class MessagesRequest(BaseModel): guardrails: Optional[Annotated[List[GuardrailConfig], Field(max_length=8)]] = None max_tokens: StrictInt max_tool_iterations: Optional[Annotated[int, Field(le=25, strict=True, ge=1)]] = None - mcp_server_ids: Optional[List[UUID]] = None + mcp_server_ids: Optional[Annotated[List[UUID], Field(max_length=50)]] = None mcp_servers: Optional[List[McpServerConfig]] = None messages: Annotated[List[Dict[str, Any]], Field(min_length=1)] metadata: Optional[Dict[str, Any]] = None diff --git a/src/otari/_client/models/request_password_reset_request.py b/src/otari/_client/models/request_password_reset_request.py new file mode 100644 index 0000000..438bbf4 --- /dev/null +++ b/src/otari/_client/models/request_password_reset_request.py @@ -0,0 +1,89 @@ +# coding: utf-8 + +""" + otari + + Otari, an OpenAI-compatible LLM gateway with API key management + + The version of the OpenAPI document: 0.0.0-dev + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +from __future__ import annotations +import pprint +import re # noqa: F401 +import json + +from pydantic import BaseModel, ConfigDict, Field +from typing import Any, ClassVar, Dict, List +from typing_extensions import Annotated +from typing import Optional, Set +from typing_extensions import Self +from pydantic_core import to_jsonable_python + +class RequestPasswordResetRequest(BaseModel): + """ + RequestPasswordResetRequest + """ # noqa: E501 + email: Annotated[str, Field(strict=True, max_length=255)] = Field(description="The address to send a reset link to.") + __properties: ClassVar[List[str]] = ["email"] + + model_config = ConfigDict( + validate_by_name=True, + validate_by_alias=True, + validate_assignment=True, + protected_namespaces=(), + ) + + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(to_jsonable_python(self.to_dict())) + + @classmethod + def from_json(cls, json_str: str) -> Optional[Self]: + """Create an instance of RequestPasswordResetRequest from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self) -> Dict[str, Any]: + """Return the dictionary representation of the model using alias. + + This has the following differences from calling pydantic's + `self.model_dump(by_alias=True)`: + + * `None` is only added to the output dict for nullable fields that + were set at model initialization. Other fields with value `None` + are ignored. + """ + excluded_fields: Set[str] = set([ + ]) + + _dict = self.model_dump( + by_alias=True, + exclude=excluded_fields, + exclude_none=True, + ) + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of RequestPasswordResetRequest from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "email": obj.get("email") + }) + return _obj + + diff --git a/src/otari/_client/models/request_password_reset_response.py b/src/otari/_client/models/request_password_reset_response.py new file mode 100644 index 0000000..920bd64 --- /dev/null +++ b/src/otari/_client/models/request_password_reset_response.py @@ -0,0 +1,88 @@ +# coding: utf-8 + +""" + otari + + Otari, an OpenAI-compatible LLM gateway with API key management + + The version of the OpenAPI document: 0.0.0-dev + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +from __future__ import annotations +import pprint +import re # noqa: F401 +import json + +from pydantic import BaseModel, ConfigDict, Field, StrictStr +from typing import Any, ClassVar, Dict, List +from typing import Optional, Set +from typing_extensions import Self +from pydantic_core import to_jsonable_python + +class RequestPasswordResetResponse(BaseModel): + """ + RequestPasswordResetResponse + """ # noqa: E501 + message: StrictStr = Field(description="The same message whether or not the address has a password to reset.") + __properties: ClassVar[List[str]] = ["message"] + + model_config = ConfigDict( + validate_by_name=True, + validate_by_alias=True, + validate_assignment=True, + protected_namespaces=(), + ) + + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(to_jsonable_python(self.to_dict())) + + @classmethod + def from_json(cls, json_str: str) -> Optional[Self]: + """Create an instance of RequestPasswordResetResponse from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self) -> Dict[str, Any]: + """Return the dictionary representation of the model using alias. + + This has the following differences from calling pydantic's + `self.model_dump(by_alias=True)`: + + * `None` is only added to the output dict for nullable fields that + were set at model initialization. Other fields with value `None` + are ignored. + """ + excluded_fields: Set[str] = set([ + ]) + + _dict = self.model_dump( + by_alias=True, + exclude=excluded_fields, + exclude_none=True, + ) + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of RequestPasswordResetResponse from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "message": obj.get("message") + }) + return _obj + + diff --git a/src/otari/_client/models/resend_verification_request.py b/src/otari/_client/models/resend_verification_request.py new file mode 100644 index 0000000..e917389 --- /dev/null +++ b/src/otari/_client/models/resend_verification_request.py @@ -0,0 +1,89 @@ +# coding: utf-8 + +""" + otari + + Otari, an OpenAI-compatible LLM gateway with API key management + + The version of the OpenAPI document: 0.0.0-dev + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +from __future__ import annotations +import pprint +import re # noqa: F401 +import json + +from pydantic import BaseModel, ConfigDict, Field +from typing import Any, ClassVar, Dict, List +from typing_extensions import Annotated +from typing import Optional, Set +from typing_extensions import Self +from pydantic_core import to_jsonable_python + +class ResendVerificationRequest(BaseModel): + """ + ResendVerificationRequest + """ # noqa: E501 + email: Annotated[str, Field(strict=True, max_length=255)] = Field(description="The address to resend a verification link to.") + __properties: ClassVar[List[str]] = ["email"] + + model_config = ConfigDict( + validate_by_name=True, + validate_by_alias=True, + validate_assignment=True, + protected_namespaces=(), + ) + + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(to_jsonable_python(self.to_dict())) + + @classmethod + def from_json(cls, json_str: str) -> Optional[Self]: + """Create an instance of ResendVerificationRequest from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self) -> Dict[str, Any]: + """Return the dictionary representation of the model using alias. + + This has the following differences from calling pydantic's + `self.model_dump(by_alias=True)`: + + * `None` is only added to the output dict for nullable fields that + were set at model initialization. Other fields with value `None` + are ignored. + """ + excluded_fields: Set[str] = set([ + ]) + + _dict = self.model_dump( + by_alias=True, + exclude=excluded_fields, + exclude_none=True, + ) + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of ResendVerificationRequest from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "email": obj.get("email") + }) + return _obj + + diff --git a/src/otari/_client/models/resend_verification_response.py b/src/otari/_client/models/resend_verification_response.py new file mode 100644 index 0000000..53bdd28 --- /dev/null +++ b/src/otari/_client/models/resend_verification_response.py @@ -0,0 +1,88 @@ +# coding: utf-8 + +""" + otari + + Otari, an OpenAI-compatible LLM gateway with API key management + + The version of the OpenAPI document: 0.0.0-dev + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +from __future__ import annotations +import pprint +import re # noqa: F401 +import json + +from pydantic import BaseModel, ConfigDict, Field, StrictStr +from typing import Any, ClassVar, Dict, List +from typing import Optional, Set +from typing_extensions import Self +from pydantic_core import to_jsonable_python + +class ResendVerificationResponse(BaseModel): + """ + ResendVerificationResponse + """ # noqa: E501 + message: StrictStr = Field(description="The same message whether or not the address has anything to verify.") + __properties: ClassVar[List[str]] = ["message"] + + model_config = ConfigDict( + validate_by_name=True, + validate_by_alias=True, + validate_assignment=True, + protected_namespaces=(), + ) + + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(to_jsonable_python(self.to_dict())) + + @classmethod + def from_json(cls, json_str: str) -> Optional[Self]: + """Create an instance of ResendVerificationResponse from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self) -> Dict[str, Any]: + """Return the dictionary representation of the model using alias. + + This has the following differences from calling pydantic's + `self.model_dump(by_alias=True)`: + + * `None` is only added to the output dict for nullable fields that + were set at model initialization. Other fields with value `None` + are ignored. + """ + excluded_fields: Set[str] = set([ + ]) + + _dict = self.model_dump( + by_alias=True, + exclude=excluded_fields, + exclude_none=True, + ) + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of ResendVerificationResponse from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "message": obj.get("message") + }) + return _obj + + diff --git a/src/otari/_client/models/reset_password_request.py b/src/otari/_client/models/reset_password_request.py new file mode 100644 index 0000000..c7c3964 --- /dev/null +++ b/src/otari/_client/models/reset_password_request.py @@ -0,0 +1,91 @@ +# coding: utf-8 + +""" + otari + + Otari, an OpenAI-compatible LLM gateway with API key management + + The version of the OpenAPI document: 0.0.0-dev + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +from __future__ import annotations +import pprint +import re # noqa: F401 +import json + +from pydantic import BaseModel, ConfigDict, Field +from typing import Any, ClassVar, Dict, List +from typing_extensions import Annotated +from typing import Optional, Set +from typing_extensions import Self +from pydantic_core import to_jsonable_python + +class ResetPasswordRequest(BaseModel): + """ + ResetPasswordRequest + """ # noqa: E501 + new_password: Annotated[str, Field(min_length=8, strict=True, max_length=1024)] = Field(description="The password to sign in with from now on. At least 8 characters, at most 72 bytes.") + token: Annotated[str, Field(strict=True, max_length=512)] = Field(description="The token from the reset link.") + __properties: ClassVar[List[str]] = ["new_password", "token"] + + model_config = ConfigDict( + validate_by_name=True, + validate_by_alias=True, + validate_assignment=True, + protected_namespaces=(), + ) + + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(to_jsonable_python(self.to_dict())) + + @classmethod + def from_json(cls, json_str: str) -> Optional[Self]: + """Create an instance of ResetPasswordRequest from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self) -> Dict[str, Any]: + """Return the dictionary representation of the model using alias. + + This has the following differences from calling pydantic's + `self.model_dump(by_alias=True)`: + + * `None` is only added to the output dict for nullable fields that + were set at model initialization. Other fields with value `None` + are ignored. + """ + excluded_fields: Set[str] = set([ + ]) + + _dict = self.model_dump( + by_alias=True, + exclude=excluded_fields, + exclude_none=True, + ) + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of ResetPasswordRequest from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "new_password": obj.get("new_password"), + "token": obj.get("token") + }) + return _obj + + diff --git a/src/otari/_client/models/responses_request.py b/src/otari/_client/models/responses_request.py index 2c535f8..119a1cf 100644 --- a/src/otari/_client/models/responses_request.py +++ b/src/otari/_client/models/responses_request.py @@ -44,7 +44,7 @@ class ResponsesRequest(BaseModel): max_output_tokens: Optional[StrictInt] = None max_tool_calls: Optional[StrictInt] = None max_tool_iterations: Optional[Annotated[int, Field(le=25, strict=True, ge=1)]] = None - mcp_server_ids: Optional[List[UUID]] = None + mcp_server_ids: Optional[Annotated[List[UUID], Field(max_length=50)]] = None mcp_servers: Optional[List[McpServerConfig]] = None metadata: Optional[Dict[str, StrictStr]] = None model: StrictStr diff --git a/src/otari/_client/models/scoped_budget_response.py b/src/otari/_client/models/scoped_budget_response.py index fa42fba..7df245a 100644 --- a/src/otari/_client/models/scoped_budget_response.py +++ b/src/otari/_client/models/scoped_budget_response.py @@ -25,9 +25,10 @@ class ScopedBudgetResponse(BaseModel): """ - One scoped ceiling and its live counters. Unlike ``/v1/budgets``, the counters are the row's own: a scoped ceiling is enforced against ``current_spend + reserved_spend``, so there is no rollup over users to compute. + One scoped ceiling and its live counters. Unlike ``/v1/budgets``, the counters are the row's own: a scoped ceiling is enforced against ``current_spend + reserved_spend``, so there is no rollup over users to compute. ``max_budget``, ``budget_duration_sec`` and ``reset_alignment`` are read off the budget rather than stored here, and are carried on the wire so a caller can render a ceiling without fetching every budget to resolve one id. """ # noqa: E501 budget_duration_sec: Optional[StrictInt] + budget_id: StrictStr created_at: StrictStr current_spend: Union[StrictFloat, StrictInt] id: StrictStr @@ -41,7 +42,7 @@ class ScopedBudgetResponse(BaseModel): scope_id: StrictStr scope_type: StrictStr updated_at: StrictStr - __properties: ClassVar[List[str]] = ["budget_duration_sec", "created_at", "current_spend", "id", "max_budget", "name", "period_end", "period_start", "provider_key_id", "reserved_spend", "reset_alignment", "scope_id", "scope_type", "updated_at"] + __properties: ClassVar[List[str]] = ["budget_duration_sec", "budget_id", "created_at", "current_spend", "id", "max_budget", "name", "period_end", "period_start", "provider_key_id", "reserved_spend", "reset_alignment", "scope_id", "scope_type", "updated_at"] model_config = ConfigDict( validate_by_name=True, @@ -130,6 +131,7 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: _obj = cls.model_validate({ "budget_duration_sec": obj.get("budget_duration_sec"), + "budget_id": obj.get("budget_id"), "created_at": obj.get("created_at"), "current_spend": obj.get("current_spend"), "id": obj.get("id"), diff --git a/src/otari/_client/models/signup_request.py b/src/otari/_client/models/signup_request.py new file mode 100644 index 0000000..cef43e4 --- /dev/null +++ b/src/otari/_client/models/signup_request.py @@ -0,0 +1,100 @@ +# coding: utf-8 + +""" + otari + + Otari, an OpenAI-compatible LLM gateway with API key management + + The version of the OpenAPI document: 0.0.0-dev + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +from __future__ import annotations +import pprint +import re # noqa: F401 +import json + +from pydantic import BaseModel, ConfigDict, Field, StrictBool +from typing import Any, ClassVar, Dict, List, Optional +from typing_extensions import Annotated +from typing import Optional, Set +from typing_extensions import Self +from pydantic_core import to_jsonable_python + +class SignupRequest(BaseModel): + """ + Claim an identity already on the roster by setting its password. + """ # noqa: E501 + email: Annotated[str, Field(strict=True, max_length=255)] = Field(description="The address an admin added or invited.") + full_name: Optional[Annotated[str, Field(strict=True, max_length=255)]] = Field(default=None, description="Filled in only if not already set.") + password: Annotated[str, Field(min_length=8, strict=True, max_length=1024)] = Field(description="The password to sign in with once verified. At least 8 characters, at most 72 bytes.") + terms_accepted: Optional[StrictBool] = Field(default=False, description="Whether the caller accepted this deployment's terms.") + __properties: ClassVar[List[str]] = ["email", "full_name", "password", "terms_accepted"] + + model_config = ConfigDict( + validate_by_name=True, + validate_by_alias=True, + validate_assignment=True, + protected_namespaces=(), + ) + + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(to_jsonable_python(self.to_dict())) + + @classmethod + def from_json(cls, json_str: str) -> Optional[Self]: + """Create an instance of SignupRequest from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self) -> Dict[str, Any]: + """Return the dictionary representation of the model using alias. + + This has the following differences from calling pydantic's + `self.model_dump(by_alias=True)`: + + * `None` is only added to the output dict for nullable fields that + were set at model initialization. Other fields with value `None` + are ignored. + """ + excluded_fields: Set[str] = set([ + ]) + + _dict = self.model_dump( + by_alias=True, + exclude=excluded_fields, + exclude_none=True, + ) + # set to None if full_name (nullable) is None + # and model_fields_set contains the field + if self.full_name is None and "full_name" in self.model_fields_set: + _dict['full_name'] = None + + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of SignupRequest from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "email": obj.get("email"), + "full_name": obj.get("full_name"), + "password": obj.get("password"), + "terms_accepted": obj.get("terms_accepted") if obj.get("terms_accepted") is not None else False + }) + return _obj + + diff --git a/src/otari/_client/models/signup_response.py b/src/otari/_client/models/signup_response.py new file mode 100644 index 0000000..2536d2a --- /dev/null +++ b/src/otari/_client/models/signup_response.py @@ -0,0 +1,88 @@ +# coding: utf-8 + +""" + otari + + Otari, an OpenAI-compatible LLM gateway with API key management + + The version of the OpenAPI document: 0.0.0-dev + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +from __future__ import annotations +import pprint +import re # noqa: F401 +import json + +from pydantic import BaseModel, ConfigDict, Field, StrictStr +from typing import Any, ClassVar, Dict, List +from typing import Optional, Set +from typing_extensions import Self +from pydantic_core import to_jsonable_python + +class SignupResponse(BaseModel): + """ + The same message whether or not the address had anything to claim. + """ # noqa: E501 + message: StrictStr = Field(description="What the caller should do next.") + __properties: ClassVar[List[str]] = ["message"] + + model_config = ConfigDict( + validate_by_name=True, + validate_by_alias=True, + validate_assignment=True, + protected_namespaces=(), + ) + + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(to_jsonable_python(self.to_dict())) + + @classmethod + def from_json(cls, json_str: str) -> Optional[Self]: + """Create an instance of SignupResponse from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self) -> Dict[str, Any]: + """Return the dictionary representation of the model using alias. + + This has the following differences from calling pydantic's + `self.model_dump(by_alias=True)`: + + * `None` is only added to the output dict for nullable fields that + were set at model initialization. Other fields with value `None` + are ignored. + """ + excluded_fields: Set[str] = set([ + ]) + + _dict = self.model_dump( + by_alias=True, + exclude=excluded_fields, + exclude_none=True, + ) + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of SignupResponse from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "message": obj.get("message") + }) + return _obj + + diff --git a/src/otari/_client/models/update_budget_request.py b/src/otari/_client/models/update_budget_request.py index 2fa9f67..02dcee4 100644 --- a/src/otari/_client/models/update_budget_request.py +++ b/src/otari/_client/models/update_budget_request.py @@ -17,7 +17,7 @@ import re # noqa: F401 import json -from pydantic import BaseModel, ConfigDict, Field, StrictStr +from pydantic import BaseModel, ConfigDict, Field, StrictStr, field_validator from typing import Any, ClassVar, Dict, List, Optional, Union from typing_extensions import Annotated from typing import Optional, Set @@ -29,9 +29,20 @@ class UpdateBudgetRequest(BaseModel): Request model for updating a budget. """ # noqa: E501 budget_duration_sec: Optional[Annotated[int, Field(strict=True, gt=0)]] = None - max_budget: Optional[Union[Annotated[float, Field(strict=True, ge=0.0)], Annotated[int, Field(strict=True, ge=0)]]] = None + max_budget: Optional[Union[Annotated[float, Field(le=999999999999, strict=True, ge=0.0)], Annotated[int, Field(le=2147483647, strict=True, ge=0)]]] = None name: Optional[StrictStr] = None - __properties: ClassVar[List[str]] = ["budget_duration_sec", "max_budget", "name"] + reset_alignment: Optional[StrictStr] = None + __properties: ClassVar[List[str]] = ["budget_duration_sec", "max_budget", "name", "reset_alignment"] + + @field_validator('reset_alignment') + def reset_alignment_validate_enum(cls, value): + """Validates the enum""" + if value is None: + return value + + if value not in set(['calendar_day', 'calendar_week', 'calendar_month']): + raise ValueError("must be one of enum values ('calendar_day', 'calendar_week', 'calendar_month')") + return value model_config = ConfigDict( validate_by_name=True, @@ -87,6 +98,11 @@ def to_dict(self) -> Dict[str, Any]: if self.name is None and "name" in self.model_fields_set: _dict['name'] = None + # set to None if reset_alignment (nullable) is None + # and model_fields_set contains the field + if self.reset_alignment is None and "reset_alignment" in self.model_fields_set: + _dict['reset_alignment'] = None + return _dict @classmethod @@ -101,7 +117,8 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: _obj = cls.model_validate({ "budget_duration_sec": obj.get("budget_duration_sec"), "max_budget": obj.get("max_budget"), - "name": obj.get("name") + "name": obj.get("name"), + "reset_alignment": obj.get("reset_alignment") }) return _obj diff --git a/src/otari/_client/models/update_scoped_budget_request.py b/src/otari/_client/models/update_scoped_budget_request.py index 3016d62..9521f7c 100644 --- a/src/otari/_client/models/update_scoped_budget_request.py +++ b/src/otari/_client/models/update_scoped_budget_request.py @@ -17,8 +17,8 @@ import re # noqa: F401 import json -from pydantic import BaseModel, ConfigDict, Field, StrictStr, field_validator -from typing import Any, ClassVar, Dict, List, Optional, Union +from pydantic import BaseModel, ConfigDict, Field +from typing import Any, ClassVar, Dict, List, Optional from typing_extensions import Annotated from typing import Optional, Set from typing_extensions import Self @@ -28,21 +28,9 @@ class UpdateScopedBudgetRequest(BaseModel): """ Request model for updating a scoped budget. """ # noqa: E501 - budget_duration_sec: Optional[Annotated[int, Field(strict=True, gt=0)]] = None - max_budget: Optional[Union[Annotated[float, Field(strict=True, ge=0.0)], Annotated[int, Field(strict=True, ge=0)]]] = None + budget_id: Optional[Annotated[str, Field(min_length=1, strict=True, max_length=255)]] = None name: Optional[Annotated[str, Field(strict=True, max_length=200)]] = None - reset_alignment: Optional[StrictStr] = None - __properties: ClassVar[List[str]] = ["budget_duration_sec", "max_budget", "name", "reset_alignment"] - - @field_validator('reset_alignment') - def reset_alignment_validate_enum(cls, value): - """Validates the enum""" - if value is None: - return value - - if value not in set(['calendar_day', 'calendar_week', 'calendar_month']): - raise ValueError("must be one of enum values ('calendar_day', 'calendar_week', 'calendar_month')") - return value + __properties: ClassVar[List[str]] = ["budget_id", "name"] model_config = ConfigDict( validate_by_name=True, @@ -83,26 +71,16 @@ def to_dict(self) -> Dict[str, Any]: exclude=excluded_fields, exclude_none=True, ) - # set to None if budget_duration_sec (nullable) is None - # and model_fields_set contains the field - if self.budget_duration_sec is None and "budget_duration_sec" in self.model_fields_set: - _dict['budget_duration_sec'] = None - - # set to None if max_budget (nullable) is None + # set to None if budget_id (nullable) is None # and model_fields_set contains the field - if self.max_budget is None and "max_budget" in self.model_fields_set: - _dict['max_budget'] = None + if self.budget_id is None and "budget_id" in self.model_fields_set: + _dict['budget_id'] = None # set to None if name (nullable) is None # and model_fields_set contains the field if self.name is None and "name" in self.model_fields_set: _dict['name'] = None - # set to None if reset_alignment (nullable) is None - # and model_fields_set contains the field - if self.reset_alignment is None and "reset_alignment" in self.model_fields_set: - _dict['reset_alignment'] = None - return _dict @classmethod @@ -115,10 +93,8 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: return cls.model_validate(obj) _obj = cls.model_validate({ - "budget_duration_sec": obj.get("budget_duration_sec"), - "max_budget": obj.get("max_budget"), - "name": obj.get("name"), - "reset_alignment": obj.get("reset_alignment") + "budget_id": obj.get("budget_id"), + "name": obj.get("name") }) return _obj diff --git a/src/otari/_client/models/verify_email_request.py b/src/otari/_client/models/verify_email_request.py new file mode 100644 index 0000000..22f7b3f --- /dev/null +++ b/src/otari/_client/models/verify_email_request.py @@ -0,0 +1,89 @@ +# coding: utf-8 + +""" + otari + + Otari, an OpenAI-compatible LLM gateway with API key management + + The version of the OpenAPI document: 0.0.0-dev + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +from __future__ import annotations +import pprint +import re # noqa: F401 +import json + +from pydantic import BaseModel, ConfigDict, Field +from typing import Any, ClassVar, Dict, List +from typing_extensions import Annotated +from typing import Optional, Set +from typing_extensions import Self +from pydantic_core import to_jsonable_python + +class VerifyEmailRequest(BaseModel): + """ + VerifyEmailRequest + """ # noqa: E501 + token: Annotated[str, Field(strict=True, max_length=512)] = Field(description="The token from the verification link.") + __properties: ClassVar[List[str]] = ["token"] + + model_config = ConfigDict( + validate_by_name=True, + validate_by_alias=True, + validate_assignment=True, + protected_namespaces=(), + ) + + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(to_jsonable_python(self.to_dict())) + + @classmethod + def from_json(cls, json_str: str) -> Optional[Self]: + """Create an instance of VerifyEmailRequest from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self) -> Dict[str, Any]: + """Return the dictionary representation of the model using alias. + + This has the following differences from calling pydantic's + `self.model_dump(by_alias=True)`: + + * `None` is only added to the output dict for nullable fields that + were set at model initialization. Other fields with value `None` + are ignored. + """ + excluded_fields: Set[str] = set([ + ]) + + _dict = self.model_dump( + by_alias=True, + exclude=excluded_fields, + exclude_none=True, + ) + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of VerifyEmailRequest from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "token": obj.get("token") + }) + return _obj + + diff --git a/src/otari/_client/models/verify_email_response.py b/src/otari/_client/models/verify_email_response.py new file mode 100644 index 0000000..215b2d3 --- /dev/null +++ b/src/otari/_client/models/verify_email_response.py @@ -0,0 +1,88 @@ +# coding: utf-8 + +""" + otari + + Otari, an OpenAI-compatible LLM gateway with API key management + + The version of the OpenAPI document: 0.0.0-dev + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +from __future__ import annotations +import pprint +import re # noqa: F401 +import json + +from pydantic import BaseModel, ConfigDict, Field, StrictStr +from typing import Any, ClassVar, Dict, List +from typing import Optional, Set +from typing_extensions import Self +from pydantic_core import to_jsonable_python + +class VerifyEmailResponse(BaseModel): + """ + VerifyEmailResponse + """ # noqa: E501 + email: StrictStr = Field(description="The address that is now verified.") + __properties: ClassVar[List[str]] = ["email"] + + model_config = ConfigDict( + validate_by_name=True, + validate_by_alias=True, + validate_assignment=True, + protected_namespaces=(), + ) + + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(to_jsonable_python(self.to_dict())) + + @classmethod + def from_json(cls, json_str: str) -> Optional[Self]: + """Create an instance of VerifyEmailResponse from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self) -> Dict[str, Any]: + """Return the dictionary representation of the model using alias. + + This has the following differences from calling pydantic's + `self.model_dump(by_alias=True)`: + + * `None` is only added to the output dict for nullable fields that + were set at model initialization. Other fields with value `None` + are ignored. + """ + excluded_fields: Set[str] = set([ + ]) + + _dict = self.model_dump( + by_alias=True, + exclude=excluded_fields, + exclude_none=True, + ) + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of VerifyEmailResponse from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "email": obj.get("email") + }) + return _obj + + diff --git a/src/otari/_client/models/workspace_code_execution_policy_public.py b/src/otari/_client/models/workspace_code_execution_policy_public.py new file mode 100644 index 0000000..f40b450 --- /dev/null +++ b/src/otari/_client/models/workspace_code_execution_policy_public.py @@ -0,0 +1,130 @@ +# coding: utf-8 + +""" + otari + + Otari, an OpenAI-compatible LLM gateway with API key management + + The version of the OpenAPI document: 0.0.0-dev + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +from __future__ import annotations +import pprint +import re # noqa: F401 +import json + +from pydantic import BaseModel, ConfigDict, StrictBool, StrictInt, StrictStr +from typing import Any, ClassVar, Dict, List, Optional +from uuid import UUID +from typing import Optional, Set +from typing_extensions import Self +from pydantic_core import to_jsonable_python + +class WorkspaceCodeExecutionPolicyPublic(BaseModel): + """ + A workspace's policy, or the unconfigured policy it has without one. + """ # noqa: E501 + configured: StrictBool + created_at: Optional[StrictStr] + default_purpose_hint: Optional[StrictStr] + enabled: StrictBool + exec_timeout_s: Optional[StrictInt] + max_iterations: Optional[StrictInt] + sandbox_configured: StrictBool + updated_at: Optional[StrictStr] + workspace_id: UUID + __properties: ClassVar[List[str]] = ["configured", "created_at", "default_purpose_hint", "enabled", "exec_timeout_s", "max_iterations", "sandbox_configured", "updated_at", "workspace_id"] + + model_config = ConfigDict( + validate_by_name=True, + validate_by_alias=True, + validate_assignment=True, + protected_namespaces=(), + ) + + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(to_jsonable_python(self.to_dict())) + + @classmethod + def from_json(cls, json_str: str) -> Optional[Self]: + """Create an instance of WorkspaceCodeExecutionPolicyPublic from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self) -> Dict[str, Any]: + """Return the dictionary representation of the model using alias. + + This has the following differences from calling pydantic's + `self.model_dump(by_alias=True)`: + + * `None` is only added to the output dict for nullable fields that + were set at model initialization. Other fields with value `None` + are ignored. + """ + excluded_fields: Set[str] = set([ + ]) + + _dict = self.model_dump( + by_alias=True, + exclude=excluded_fields, + exclude_none=True, + ) + # set to None if created_at (nullable) is None + # and model_fields_set contains the field + if self.created_at is None and "created_at" in self.model_fields_set: + _dict['created_at'] = None + + # set to None if default_purpose_hint (nullable) is None + # and model_fields_set contains the field + if self.default_purpose_hint is None and "default_purpose_hint" in self.model_fields_set: + _dict['default_purpose_hint'] = None + + # set to None if exec_timeout_s (nullable) is None + # and model_fields_set contains the field + if self.exec_timeout_s is None and "exec_timeout_s" in self.model_fields_set: + _dict['exec_timeout_s'] = None + + # set to None if max_iterations (nullable) is None + # and model_fields_set contains the field + if self.max_iterations is None and "max_iterations" in self.model_fields_set: + _dict['max_iterations'] = None + + # set to None if updated_at (nullable) is None + # and model_fields_set contains the field + if self.updated_at is None and "updated_at" in self.model_fields_set: + _dict['updated_at'] = None + + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of WorkspaceCodeExecutionPolicyPublic from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "configured": obj.get("configured"), + "created_at": obj.get("created_at"), + "default_purpose_hint": obj.get("default_purpose_hint"), + "enabled": obj.get("enabled"), + "exec_timeout_s": obj.get("exec_timeout_s"), + "max_iterations": obj.get("max_iterations"), + "sandbox_configured": obj.get("sandbox_configured"), + "updated_at": obj.get("updated_at"), + "workspace_id": obj.get("workspace_id") + }) + return _obj + + diff --git a/src/otari/_client/models/workspace_code_execution_policy_update.py b/src/otari/_client/models/workspace_code_execution_policy_update.py new file mode 100644 index 0000000..60cfb4c --- /dev/null +++ b/src/otari/_client/models/workspace_code_execution_policy_update.py @@ -0,0 +1,110 @@ +# coding: utf-8 + +""" + otari + + Otari, an OpenAI-compatible LLM gateway with API key management + + The version of the OpenAPI document: 0.0.0-dev + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +from __future__ import annotations +import pprint +import re # noqa: F401 +import json + +from pydantic import BaseModel, ConfigDict, Field, StrictBool +from typing import Any, ClassVar, Dict, List, Optional +from typing_extensions import Annotated +from typing import Optional, Set +from typing_extensions import Self +from pydantic_core import to_jsonable_python + +class WorkspaceCodeExecutionPolicyUpdate(BaseModel): + """ + The policy to store for a workspace, as a whole. ``PUT`` semantics, ported from the hosted ``CodeExecutionConfigUpsert``: what is sent is what the workspace has afterwards, so an omitted limit is cleared rather than left as it was. + """ # noqa: E501 + default_purpose_hint: Optional[Annotated[str, Field(strict=True, max_length=2048)]] = Field(default=None, description="Hint used when a request declares otari_code_execution without one of its own") + enabled: StrictBool = Field(description="False refuses code execution for this workspace") + exec_timeout_s: Optional[Annotated[int, Field(le=60, strict=True, gt=0)]] = Field(default=None, description="Ceiling on one execution's runtime in seconds; only ever lowers the effective limit, so at most 60") + max_iterations: Optional[Annotated[int, Field(le=25, strict=True, gt=0)]] = Field(default=None, description="Ceiling on tool-loop iterations; only ever lowers the effective limit, so at most 25") + __properties: ClassVar[List[str]] = ["default_purpose_hint", "enabled", "exec_timeout_s", "max_iterations"] + + model_config = ConfigDict( + validate_by_name=True, + validate_by_alias=True, + validate_assignment=True, + protected_namespaces=(), + ) + + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(to_jsonable_python(self.to_dict())) + + @classmethod + def from_json(cls, json_str: str) -> Optional[Self]: + """Create an instance of WorkspaceCodeExecutionPolicyUpdate from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self) -> Dict[str, Any]: + """Return the dictionary representation of the model using alias. + + This has the following differences from calling pydantic's + `self.model_dump(by_alias=True)`: + + * `None` is only added to the output dict for nullable fields that + were set at model initialization. Other fields with value `None` + are ignored. + """ + excluded_fields: Set[str] = set([ + ]) + + _dict = self.model_dump( + by_alias=True, + exclude=excluded_fields, + exclude_none=True, + ) + # set to None if default_purpose_hint (nullable) is None + # and model_fields_set contains the field + if self.default_purpose_hint is None and "default_purpose_hint" in self.model_fields_set: + _dict['default_purpose_hint'] = None + + # set to None if exec_timeout_s (nullable) is None + # and model_fields_set contains the field + if self.exec_timeout_s is None and "exec_timeout_s" in self.model_fields_set: + _dict['exec_timeout_s'] = None + + # set to None if max_iterations (nullable) is None + # and model_fields_set contains the field + if self.max_iterations is None and "max_iterations" in self.model_fields_set: + _dict['max_iterations'] = None + + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of WorkspaceCodeExecutionPolicyUpdate from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "default_purpose_hint": obj.get("default_purpose_hint"), + "enabled": obj.get("enabled"), + "exec_timeout_s": obj.get("exec_timeout_s"), + "max_iterations": obj.get("max_iterations") + }) + return _obj + + diff --git a/src/otari/_client/models/workspace_mcp_server_create.py b/src/otari/_client/models/workspace_mcp_server_create.py new file mode 100644 index 0000000..00f4525 --- /dev/null +++ b/src/otari/_client/models/workspace_mcp_server_create.py @@ -0,0 +1,114 @@ +# coding: utf-8 + +""" + otari + + Otari, an OpenAI-compatible LLM gateway with API key management + + The version of the OpenAPI document: 0.0.0-dev + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +from __future__ import annotations +import pprint +import re # noqa: F401 +import json + +from pydantic import BaseModel, ConfigDict, Field, StrictBool +from typing import Any, ClassVar, Dict, List, Optional +from typing_extensions import Annotated +from typing import Optional, Set +from typing_extensions import Self +from pydantic_core import to_jsonable_python + +class WorkspaceMcpServerCreate(BaseModel): + """ + Request body for registering a server. ``authorization_token`` is never stored as sent: it is encrypted with ``OTARI_SECRET_KEY`` and only the ciphertext is kept, the same convention `entities.ProviderCredential` and `OrgProviderKey` already use. + """ # noqa: E501 + allowed_tools: Optional[Annotated[List[Annotated[str, Field(strict=True, max_length=256)]], Field(max_length=200)]] = Field(default=None, description="Allow-list of tool names; null exposes every tool the server offers") + authorization_token: Optional[Annotated[str, Field(strict=True, max_length=8192)]] = Field(default=None, description="Bearer token for the server; requires an https URL. Encrypted at rest, never returned") + enabled: Optional[StrictBool] = Field(default=True, description="Whether a request naming this server actually reaches it") + name: Annotated[str, Field(min_length=1, strict=True, max_length=128)] = Field(description="Label for the server, unique within the workspace") + purpose_hint: Optional[Annotated[str, Field(strict=True, max_length=2000)]] = Field(default=None, description="Hint prepended to the system message to help the model choose") + url: Annotated[str, Field(min_length=1, strict=True, max_length=2048)] = Field(description="Streamable HTTP MCP endpoint") + __properties: ClassVar[List[str]] = ["allowed_tools", "authorization_token", "enabled", "name", "purpose_hint", "url"] + + model_config = ConfigDict( + validate_by_name=True, + validate_by_alias=True, + validate_assignment=True, + protected_namespaces=(), + ) + + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(to_jsonable_python(self.to_dict())) + + @classmethod + def from_json(cls, json_str: str) -> Optional[Self]: + """Create an instance of WorkspaceMcpServerCreate from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self) -> Dict[str, Any]: + """Return the dictionary representation of the model using alias. + + This has the following differences from calling pydantic's + `self.model_dump(by_alias=True)`: + + * `None` is only added to the output dict for nullable fields that + were set at model initialization. Other fields with value `None` + are ignored. + """ + excluded_fields: Set[str] = set([ + ]) + + _dict = self.model_dump( + by_alias=True, + exclude=excluded_fields, + exclude_none=True, + ) + # set to None if allowed_tools (nullable) is None + # and model_fields_set contains the field + if self.allowed_tools is None and "allowed_tools" in self.model_fields_set: + _dict['allowed_tools'] = None + + # set to None if authorization_token (nullable) is None + # and model_fields_set contains the field + if self.authorization_token is None and "authorization_token" in self.model_fields_set: + _dict['authorization_token'] = None + + # set to None if purpose_hint (nullable) is None + # and model_fields_set contains the field + if self.purpose_hint is None and "purpose_hint" in self.model_fields_set: + _dict['purpose_hint'] = None + + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of WorkspaceMcpServerCreate from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "allowed_tools": obj.get("allowed_tools"), + "authorization_token": obj.get("authorization_token"), + "enabled": obj.get("enabled") if obj.get("enabled") is not None else True, + "name": obj.get("name"), + "purpose_hint": obj.get("purpose_hint"), + "url": obj.get("url") + }) + return _obj + + diff --git a/src/otari/_client/models/workspace_mcp_server_public.py b/src/otari/_client/models/workspace_mcp_server_public.py new file mode 100644 index 0000000..32965a0 --- /dev/null +++ b/src/otari/_client/models/workspace_mcp_server_public.py @@ -0,0 +1,117 @@ +# coding: utf-8 + +""" + otari + + Otari, an OpenAI-compatible LLM gateway with API key management + + The version of the OpenAPI document: 0.0.0-dev + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +from __future__ import annotations +import pprint +import re # noqa: F401 +import json + +from pydantic import BaseModel, ConfigDict, StrictBool, StrictStr +from typing import Any, ClassVar, Dict, List, Optional +from uuid import UUID +from typing import Optional, Set +from typing_extensions import Self +from pydantic_core import to_jsonable_python + +class WorkspaceMcpServerPublic(BaseModel): + """ + The API-facing shape. Never carries the token, only whether one is set. No ``last4``-style prefix either, unlike `OrgProviderKeyPublic`: a provider key's last four digits let an operator match a stored key against the one in their provider's console, and there is no equivalent workflow for an MCP bearer token. + """ # noqa: E501 + allowed_tools: Optional[List[StrictStr]] + created_at: StrictStr + enabled: StrictBool + has_token: StrictBool + id: UUID + name: StrictStr + purpose_hint: Optional[StrictStr] + updated_at: StrictStr + url: StrictStr + workspace_id: UUID + __properties: ClassVar[List[str]] = ["allowed_tools", "created_at", "enabled", "has_token", "id", "name", "purpose_hint", "updated_at", "url", "workspace_id"] + + model_config = ConfigDict( + validate_by_name=True, + validate_by_alias=True, + validate_assignment=True, + protected_namespaces=(), + ) + + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(to_jsonable_python(self.to_dict())) + + @classmethod + def from_json(cls, json_str: str) -> Optional[Self]: + """Create an instance of WorkspaceMcpServerPublic from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self) -> Dict[str, Any]: + """Return the dictionary representation of the model using alias. + + This has the following differences from calling pydantic's + `self.model_dump(by_alias=True)`: + + * `None` is only added to the output dict for nullable fields that + were set at model initialization. Other fields with value `None` + are ignored. + """ + excluded_fields: Set[str] = set([ + ]) + + _dict = self.model_dump( + by_alias=True, + exclude=excluded_fields, + exclude_none=True, + ) + # set to None if allowed_tools (nullable) is None + # and model_fields_set contains the field + if self.allowed_tools is None and "allowed_tools" in self.model_fields_set: + _dict['allowed_tools'] = None + + # set to None if purpose_hint (nullable) is None + # and model_fields_set contains the field + if self.purpose_hint is None and "purpose_hint" in self.model_fields_set: + _dict['purpose_hint'] = None + + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of WorkspaceMcpServerPublic from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "allowed_tools": obj.get("allowed_tools"), + "created_at": obj.get("created_at"), + "enabled": obj.get("enabled"), + "has_token": obj.get("has_token"), + "id": obj.get("id"), + "name": obj.get("name"), + "purpose_hint": obj.get("purpose_hint"), + "updated_at": obj.get("updated_at"), + "url": obj.get("url"), + "workspace_id": obj.get("workspace_id") + }) + return _obj + + diff --git a/src/otari/_client/models/workspace_mcp_server_update.py b/src/otari/_client/models/workspace_mcp_server_update.py new file mode 100644 index 0000000..d27d2fb --- /dev/null +++ b/src/otari/_client/models/workspace_mcp_server_update.py @@ -0,0 +1,114 @@ +# coding: utf-8 + +""" + otari + + Otari, an OpenAI-compatible LLM gateway with API key management + + The version of the OpenAPI document: 0.0.0-dev + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +from __future__ import annotations +import pprint +import re # noqa: F401 +import json + +from pydantic import BaseModel, ConfigDict, Field, StrictBool +from typing import Any, ClassVar, Dict, List, Optional +from typing_extensions import Annotated +from typing import Optional, Set +from typing_extensions import Self +from pydantic_core import to_jsonable_python + +class WorkspaceMcpServerUpdate(BaseModel): + """ + Partial update. Only the fields the caller sets are applied. ``authorization_token`` has three states rather than two, which is what a write-only field needs: omit it to leave the stored token alone, send ``\"\"`` to clear it, send a value to rotate it. An explicit ``null`` also leaves it alone, matching the platform: a client that serializes its whole form back, with an empty token box it never filled in, must not destroy a token it was never shown. + """ # noqa: E501 + allowed_tools: Optional[Annotated[List[Annotated[str, Field(strict=True, max_length=256)]], Field(max_length=200)]] = None + authorization_token: Optional[Annotated[str, Field(strict=True, max_length=8192)]] = None + enabled: Optional[StrictBool] = None + name: Optional[Annotated[str, Field(min_length=1, strict=True, max_length=128)]] = None + purpose_hint: Optional[Annotated[str, Field(strict=True, max_length=2000)]] = None + url: Optional[Annotated[str, Field(min_length=1, strict=True, max_length=2048)]] = None + __properties: ClassVar[List[str]] = ["allowed_tools", "authorization_token", "enabled", "name", "purpose_hint", "url"] + + model_config = ConfigDict( + validate_by_name=True, + validate_by_alias=True, + validate_assignment=True, + protected_namespaces=(), + ) + + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(to_jsonable_python(self.to_dict())) + + @classmethod + def from_json(cls, json_str: str) -> Optional[Self]: + """Create an instance of WorkspaceMcpServerUpdate from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self) -> Dict[str, Any]: + """Return the dictionary representation of the model using alias. + + This has the following differences from calling pydantic's + `self.model_dump(by_alias=True)`: + + * `None` is only added to the output dict for nullable fields that + were set at model initialization. Other fields with value `None` + are ignored. + """ + excluded_fields: Set[str] = set([ + ]) + + _dict = self.model_dump( + by_alias=True, + exclude=excluded_fields, + exclude_none=True, + ) + # set to None if allowed_tools (nullable) is None + # and model_fields_set contains the field + if self.allowed_tools is None and "allowed_tools" in self.model_fields_set: + _dict['allowed_tools'] = None + + # set to None if authorization_token (nullable) is None + # and model_fields_set contains the field + if self.authorization_token is None and "authorization_token" in self.model_fields_set: + _dict['authorization_token'] = None + + # set to None if purpose_hint (nullable) is None + # and model_fields_set contains the field + if self.purpose_hint is None and "purpose_hint" in self.model_fields_set: + _dict['purpose_hint'] = None + + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of WorkspaceMcpServerUpdate from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "allowed_tools": obj.get("allowed_tools"), + "authorization_token": obj.get("authorization_token"), + "enabled": obj.get("enabled"), + "name": obj.get("name"), + "purpose_hint": obj.get("purpose_hint"), + "url": obj.get("url") + }) + return _obj + + diff --git a/src/otari/_client/models/workspace_mcp_servers_public.py b/src/otari/_client/models/workspace_mcp_servers_public.py new file mode 100644 index 0000000..330091d --- /dev/null +++ b/src/otari/_client/models/workspace_mcp_servers_public.py @@ -0,0 +1,98 @@ +# coding: utf-8 + +""" + otari + + Otari, an OpenAI-compatible LLM gateway with API key management + + The version of the OpenAPI document: 0.0.0-dev + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +from __future__ import annotations +import pprint +import re # noqa: F401 +import json + +from pydantic import BaseModel, ConfigDict, StrictInt +from typing import Any, ClassVar, Dict, List +from otari._client.models.workspace_mcp_server_public import WorkspaceMcpServerPublic +from typing import Optional, Set +from typing_extensions import Self +from pydantic_core import to_jsonable_python + +class WorkspaceMcpServersPublic(BaseModel): + """ + WorkspaceMcpServersPublic + """ # noqa: E501 + count: StrictInt + data: List[WorkspaceMcpServerPublic] + __properties: ClassVar[List[str]] = ["count", "data"] + + model_config = ConfigDict( + validate_by_name=True, + validate_by_alias=True, + validate_assignment=True, + protected_namespaces=(), + ) + + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(to_jsonable_python(self.to_dict())) + + @classmethod + def from_json(cls, json_str: str) -> Optional[Self]: + """Create an instance of WorkspaceMcpServersPublic from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self) -> Dict[str, Any]: + """Return the dictionary representation of the model using alias. + + This has the following differences from calling pydantic's + `self.model_dump(by_alias=True)`: + + * `None` is only added to the output dict for nullable fields that + were set at model initialization. Other fields with value `None` + are ignored. + """ + excluded_fields: Set[str] = set([ + ]) + + _dict = self.model_dump( + by_alias=True, + exclude=excluded_fields, + exclude_none=True, + ) + # override the default output from pydantic by calling `to_dict()` of each item in data (list) + _items = [] + if self.data: + for _item_data in self.data: + if _item_data: + _items.append(_item_data.to_dict()) + _dict['data'] = _items + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of WorkspaceMcpServersPublic from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "count": obj.get("count"), + "data": [WorkspaceMcpServerPublic.from_dict(_item) for _item in obj["data"]] if obj.get("data") is not None else None + }) + return _obj + + diff --git a/src/otari/_client/models/workspace_member_budget_policy_create.py b/src/otari/_client/models/workspace_member_budget_policy_create.py index ce11059..d31ccf1 100644 --- a/src/otari/_client/models/workspace_member_budget_policy_create.py +++ b/src/otari/_client/models/workspace_member_budget_policy_create.py @@ -18,7 +18,7 @@ import json from pydantic import BaseModel, ConfigDict, Field -from typing import Any, ClassVar, Dict, List, Optional, Union +from typing import Any, ClassVar, Dict, List, Optional from typing_extensions import Annotated from typing import Optional, Set from typing_extensions import Self @@ -28,11 +28,9 @@ class WorkspaceMemberBudgetPolicyCreate(BaseModel): """ Request body for creating a default. """ # noqa: E501 - budget_duration_sec: Optional[Annotated[int, Field(le=315360000, strict=True, gt=0)]] = Field(default=None, description="Period length in seconds; null never resets") - max_budget: Optional[Union[Annotated[float, Field(strict=True, ge=0.0)], Annotated[int, Field(strict=True, ge=0)]]] = Field(default=None, description="Maximum USD spend per member in the period") - name: Optional[Annotated[str, Field(strict=True, max_length=200)]] = Field(default=None, description="Admin-facing label") + budget_id: Annotated[str, Field(min_length=1, strict=True, max_length=255)] = Field(description="The budget this workspace hands to every member") provider_key_id: Optional[Annotated[str, Field(strict=True, max_length=255)]] = Field(default=None, description="Narrow the default to one provider instance; null applies to every provider") - __properties: ClassVar[List[str]] = ["budget_duration_sec", "max_budget", "name", "provider_key_id"] + __properties: ClassVar[List[str]] = ["budget_id", "provider_key_id"] model_config = ConfigDict( validate_by_name=True, @@ -73,21 +71,6 @@ def to_dict(self) -> Dict[str, Any]: exclude=excluded_fields, exclude_none=True, ) - # set to None if budget_duration_sec (nullable) is None - # and model_fields_set contains the field - if self.budget_duration_sec is None and "budget_duration_sec" in self.model_fields_set: - _dict['budget_duration_sec'] = None - - # set to None if max_budget (nullable) is None - # and model_fields_set contains the field - if self.max_budget is None and "max_budget" in self.model_fields_set: - _dict['max_budget'] = None - - # set to None if name (nullable) is None - # and model_fields_set contains the field - if self.name is None and "name" in self.model_fields_set: - _dict['name'] = None - # set to None if provider_key_id (nullable) is None # and model_fields_set contains the field if self.provider_key_id is None and "provider_key_id" in self.model_fields_set: @@ -105,9 +88,7 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: return cls.model_validate(obj) _obj = cls.model_validate({ - "budget_duration_sec": obj.get("budget_duration_sec"), - "max_budget": obj.get("max_budget"), - "name": obj.get("name"), + "budget_id": obj.get("budget_id"), "provider_key_id": obj.get("provider_key_id") }) return _obj diff --git a/src/otari/_client/models/workspace_member_budget_policy_public.py b/src/otari/_client/models/workspace_member_budget_policy_public.py index 8e28ab6..32381a9 100644 --- a/src/otari/_client/models/workspace_member_budget_policy_public.py +++ b/src/otari/_client/models/workspace_member_budget_policy_public.py @@ -29,6 +29,7 @@ class WorkspaceMemberBudgetPolicyPublic(BaseModel): One default and its template values. """ # noqa: E501 budget_duration_sec: Optional[StrictInt] + budget_id: StrictStr created_at: StrictStr id: StrictStr max_budget: Optional[Union[StrictFloat, StrictInt]] @@ -36,7 +37,7 @@ class WorkspaceMemberBudgetPolicyPublic(BaseModel): provider_key_id: Optional[StrictStr] updated_at: StrictStr workspace_id: UUID - __properties: ClassVar[List[str]] = ["budget_duration_sec", "created_at", "id", "max_budget", "name", "provider_key_id", "updated_at", "workspace_id"] + __properties: ClassVar[List[str]] = ["budget_duration_sec", "budget_id", "created_at", "id", "max_budget", "name", "provider_key_id", "updated_at", "workspace_id"] model_config = ConfigDict( validate_by_name=True, @@ -110,6 +111,7 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: _obj = cls.model_validate({ "budget_duration_sec": obj.get("budget_duration_sec"), + "budget_id": obj.get("budget_id"), "created_at": obj.get("created_at"), "id": obj.get("id"), "max_budget": obj.get("max_budget"), diff --git a/src/otari/_client/models/workspace_member_budget_policy_update.py b/src/otari/_client/models/workspace_member_budget_policy_update.py index f2d9538..b88251e 100644 --- a/src/otari/_client/models/workspace_member_budget_policy_update.py +++ b/src/otari/_client/models/workspace_member_budget_policy_update.py @@ -18,7 +18,7 @@ import json from pydantic import BaseModel, ConfigDict, Field -from typing import Any, ClassVar, Dict, List, Optional, Union +from typing import Any, ClassVar, Dict, List from typing_extensions import Annotated from typing import Optional, Set from typing_extensions import Self @@ -26,12 +26,10 @@ class WorkspaceMemberBudgetPolicyUpdate(BaseModel): """ - Request body for updating a default. Not retroactive: a member already materialized from this default keeps the value that was in effect when they were materialized. Only a member materialized after this update sees the new one. + Request body for pointing a default at a different budget. Members already materialized from this default keep the budget they were given: their ceiling names it directly, and this only changes what a member joining afterwards is handed. Editing the *budget* is the retroactive act, and it moves everyone naming it, in this workspace and outside it. """ # noqa: E501 - budget_duration_sec: Optional[Annotated[int, Field(le=315360000, strict=True, gt=0)]] = None - max_budget: Optional[Union[Annotated[float, Field(strict=True, ge=0.0)], Annotated[int, Field(strict=True, ge=0)]]] = None - name: Optional[Annotated[str, Field(strict=True, max_length=200)]] = None - __properties: ClassVar[List[str]] = ["budget_duration_sec", "max_budget", "name"] + budget_id: Annotated[str, Field(min_length=1, strict=True, max_length=255)] + __properties: ClassVar[List[str]] = ["budget_id"] model_config = ConfigDict( validate_by_name=True, @@ -72,21 +70,6 @@ def to_dict(self) -> Dict[str, Any]: exclude=excluded_fields, exclude_none=True, ) - # set to None if budget_duration_sec (nullable) is None - # and model_fields_set contains the field - if self.budget_duration_sec is None and "budget_duration_sec" in self.model_fields_set: - _dict['budget_duration_sec'] = None - - # set to None if max_budget (nullable) is None - # and model_fields_set contains the field - if self.max_budget is None and "max_budget" in self.model_fields_set: - _dict['max_budget'] = None - - # set to None if name (nullable) is None - # and model_fields_set contains the field - if self.name is None and "name" in self.model_fields_set: - _dict['name'] = None - return _dict @classmethod @@ -99,9 +82,7 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: return cls.model_validate(obj) _obj = cls.model_validate({ - "budget_duration_sec": obj.get("budget_duration_sec"), - "max_budget": obj.get("max_budget"), - "name": obj.get("name") + "budget_id": obj.get("budget_id") }) return _obj