From 81a43f8e6b3ae4b87d8ae5dc3e588599fdd202f9 Mon Sep 17 00:00:00 2001 From: mgauz01 <40064186+mgauz01@users.noreply.github.com> Date: Wed, 7 Oct 2026 16:26:09 +0000 Subject: [PATCH] feat: regenerate SDK client core from Otari OpenAPI spec --- sdk-endpoints.txt | 15 + src/otari/_client/__init__.py | 28 + src/otari/_client/api/__init__.py | 1 + src/otari/_client/api/budgets_api.py | 304 +- src/otari/_client/api/keys_api.py | 1122 ++++++- .../_client/api/organization_usage_api.py | 89 + src/otari/_client/api/routing_api.py | 280 ++ src/otari/_client/api/search_api.py | 12 +- src/otari/_client/api/usage_api.py | 89 + src/otari/_client/api/web_search_keys_api.py | 2863 +++++++++++++++++ src/otari/_client/models/__init__.py | 13 + .../models/agent_model_recommendation.py | 102 + .../agent_model_recommendation_request.py | 115 + src/otari/_client/models/billing_meters.py | 2 +- src/otari/_client/models/budget_response.py | 16 +- src/otari/_client/models/call_tool_result.py | 2 +- .../models/cc_chat_completion_message.py | 2 +- .../_client/models/chat_completion_request.py | 13 +- .../chat_completion_request_tools_inner.py | 2 +- src/otari/_client/models/container.py | 2 +- src/otari/_client/models/conversation.py | 2 +- .../_client/models/count_tokens_request.py | 10 +- .../_client/models/create_budget_request.py | 18 +- .../_client/models/create_key_request.py | 12 +- .../_client/models/create_key_response.py | 4 +- .../models/create_search_tool_request.py | 2 +- .../models/create_stored_provider_request.py | 2 +- src/otari/_client/models/criteria_inner.py | 2 +- src/otari/_client/models/criteria_value.py | 2 +- src/otari/_client/models/decision_answer.py | 2 +- src/otari/_client/models/end_user_public.py | 125 + src/otari/_client/models/end_user_put.py | 89 + src/otari/_client/models/end_user_update.py | 101 + src/otari/_client/models/explain_request.py | 2 +- src/otari/_client/models/instructions.py | 2 +- src/otari/_client/models/key_info.py | 4 +- .../_client/models/mcp_tool_definition.py | 2 +- src/otari/_client/models/messages_request.py | 4 +- src/otari/_client/models/model_false.py | 2 +- src/otari/_client/models/model_true.py | 2 +- src/otari/_client/models/moderation_result.py | 2 +- .../org_web_search_key_create_request.py | 93 + .../models/org_web_search_key_public.py | 123 + .../org_web_search_key_update_request.py | 101 + .../models/org_web_search_keys_public.py | 98 + .../models/organization_guardrail_create.py | 2 +- ...rganization_guardrail_definition_update.py | 2 +- .../models/organization_guardrail_public.py | 2 +- .../models/organization_guardrail_update.py | 2 +- .../provider_endpoint_create_request.py | 2 +- .../models/provider_endpoint_public.py | 2 +- src/otari/_client/models/responses_request.py | 4 +- src/otari/_client/models/sandbox_provider.py | 37 + src/otari/_client/models/state.py | 2 +- src/otari/_client/models/tool_choice.py | 2 +- .../_client/models/tool_settings_response.py | 16 +- .../_client/models/update_budget_request.py | 18 +- .../_client/models/update_key_request.py | 12 +- .../models/update_search_tool_request.py | 2 +- src/otari/_client/models/usage_entry.py | 9 +- .../usage_entry_pricing_breakdown_inner.py | 2 +- src/otari/_client/models/usage_summary.py | 11 +- .../workspace_web_search_config_public.py | 2 +- .../workspace_web_search_config_update.py | 2 +- ...rkspace_web_search_key_override_request.py | 100 + .../models/workspace_web_search_key_public.py | 110 + .../workspace_web_search_keys_public.py | 98 + 67 files changed, 6139 insertions(+), 178 deletions(-) create mode 100644 src/otari/_client/api/web_search_keys_api.py create mode 100644 src/otari/_client/models/agent_model_recommendation.py create mode 100644 src/otari/_client/models/agent_model_recommendation_request.py create mode 100644 src/otari/_client/models/end_user_public.py create mode 100644 src/otari/_client/models/end_user_put.py create mode 100644 src/otari/_client/models/end_user_update.py create mode 100644 src/otari/_client/models/org_web_search_key_create_request.py create mode 100644 src/otari/_client/models/org_web_search_key_public.py create mode 100644 src/otari/_client/models/org_web_search_key_update_request.py create mode 100644 src/otari/_client/models/org_web_search_keys_public.py create mode 100644 src/otari/_client/models/sandbox_provider.py create mode 100644 src/otari/_client/models/workspace_web_search_key_override_request.py create mode 100644 src/otari/_client/models/workspace_web_search_key_public.py create mode 100644 src/otari/_client/models/workspace_web_search_keys_public.py diff --git a/sdk-endpoints.txt b/sdk-endpoints.txt index 22792899..c8133051 100644 --- a/sdk-endpoints.txt +++ b/sdk-endpoints.txt @@ -154,6 +154,10 @@ GET /api/v1/usage/count # not yet wrapped GET /api/v1/usage/requests/{request_id} # not yet wrapped POST /api/v1/keys/{key_id}/rotate # not yet wrapped GET /api/v1/budgets/{budget_id}/reset-logs # not yet wrapped +PUT /api/v1/budgets/{budget_id} # not yet wrapped +GET /api/v1/keys/{key_id}/end-users/{external_id} # not yet wrapped +PUT /api/v1/keys/{key_id}/end-users/{external_id} # not yet wrapped +PATCH /api/v1/keys/{key_id}/end-users/{external_id} # not yet wrapped # --- Second wave of gateway endpoints (added after the initial manifest) --- # Dashboard session auth: browser cookie flow for the admin UI, not an SDK surface. @@ -227,6 +231,7 @@ DELETE /api/v1/routing/policies/{name} # not yet wrapped POST /api/v1/routing/policies/explain # not yet wrapped POST /api/v1/routing/preferences/rank # not yet wrapped GET /api/v1/routing/status # not yet wrapped +POST /api/v1/routing/recommend # not yet wrapped # Pricing refresh workflow POST /api/v1/pricing/refresh # not yet wrapped POST /api/v1/pricing/refresh/confirm # not yet wrapped @@ -429,6 +434,16 @@ DELETE /api/v1/workspaces/{workspace_id}/provider-keys/{key_id} # GET /api/v1/workspaces/{workspace_id}/provider-keys/{key_id}/models # dashboard-only POST /api/v1/workspaces/{workspace_id}/provider-keys/{key_id}/models # dashboard-only DELETE /api/v1/workspaces/{workspace_id}/provider-keys/{key_id}/models/{model} # dashboard-only +GET /api/v1/organizations/me/web-search-keys # dashboard-only +POST /api/v1/organizations/me/web-search-keys # dashboard-only +PATCH /api/v1/organizations/me/web-search-keys/{key_id} # dashboard-only +DELETE /api/v1/organizations/me/web-search-keys/{key_id} # dashboard-only +POST /api/v1/organizations/me/web-search-keys/{key_id}/archive # dashboard-only +POST /api/v1/organizations/me/web-search-keys/{key_id}/restore # dashboard-only +POST /api/v1/organizations/me/web-search-keys/{key_id}/default # dashboard-only +GET /api/v1/workspaces/{workspace_id}/web-search-keys # dashboard-only +PATCH /api/v1/workspaces/{workspace_id}/web-search-keys/{key_id} # dashboard-only +DELETE /api/v1/workspaces/{workspace_id}/web-search-keys/{key_id} # 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 diff --git a/src/otari/_client/__init__.py b/src/otari/_client/__init__.py index 65066abf..1d96c0aa 100644 --- a/src/otari/_client/__init__.py +++ b/src/otari/_client/__init__.py @@ -69,6 +69,7 @@ "UsageApi", "UsersApi", "WebSearchApi", + "WebSearchKeysApi", "WorkspaceActivationApi", "WorkspaceCodeExecutionPolicyApi", "WorkspaceMemberBudgetPoliciesApi", @@ -94,6 +95,8 @@ "ActiveOrganizationMemberUpdateRequest", "ActiveOrganizationMembersPublic", "ActiveOrganizationUpdateRequest", + "AgentModelRecommendation", + "AgentModelRecommendationRequest", "AgentTelemetryBehavior", "AgentTelemetryCount", "AgentTelemetryDeleteRequest", @@ -261,6 +264,9 @@ "EMBUsage", "EmbeddedResource", "EmbeddingRequest", + "EndUserPublic", + "EndUserPut", + "EndUserUpdate", "ExecutionState", "ExplainRequest", "ExplainResponse", @@ -486,6 +492,10 @@ "OrgProviderKeyUpdateRequest", "OrgProviderKeysPublic", "OrgProviderModelsRefreshPublic", + "OrgWebSearchKeyCreateRequest", + "OrgWebSearchKeyPublic", + "OrgWebSearchKeyUpdateRequest", + "OrgWebSearchKeysPublic", "OrganizationBudgetCreate", "OrganizationBudgetPublic", "OrganizationBudgetUpdate", @@ -594,6 +604,7 @@ "ResponsesRequest", "RotateMasterKeyResponse", "RouterStatus", + "SandboxProvider", "ScopedBudgetResponse", "ScoreQuestion", "ScoredExample", @@ -701,6 +712,9 @@ "WorkspaceUpdate", "WorkspaceWebSearchConfigPublic", "WorkspaceWebSearchConfigUpdate", + "WorkspaceWebSearchKeyOverrideRequest", + "WorkspaceWebSearchKeyPublic", + "WorkspaceWebSearchKeysPublic", "WorkspacesPublic", "WorstAllocationResponse", ] @@ -757,6 +771,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.web_search_api import WebSearchApi as WebSearchApi +from otari._client.api.web_search_keys_api import WebSearchKeysApi as WebSearchKeysApi 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 @@ -786,6 +801,8 @@ from otari._client.models.active_organization_member_update_request import ActiveOrganizationMemberUpdateRequest as ActiveOrganizationMemberUpdateRequest from otari._client.models.active_organization_members_public import ActiveOrganizationMembersPublic as ActiveOrganizationMembersPublic from otari._client.models.active_organization_update_request import ActiveOrganizationUpdateRequest as ActiveOrganizationUpdateRequest +from otari._client.models.agent_model_recommendation import AgentModelRecommendation as AgentModelRecommendation +from otari._client.models.agent_model_recommendation_request import AgentModelRecommendationRequest as AgentModelRecommendationRequest from otari._client.models.agent_telemetry_behavior import AgentTelemetryBehavior as AgentTelemetryBehavior from otari._client.models.agent_telemetry_count import AgentTelemetryCount as AgentTelemetryCount from otari._client.models.agent_telemetry_delete_request import AgentTelemetryDeleteRequest as AgentTelemetryDeleteRequest @@ -953,6 +970,9 @@ from otari._client.models.emb_usage import EMBUsage as EMBUsage from otari._client.models.embedded_resource import EmbeddedResource as EmbeddedResource from otari._client.models.embedding_request import EmbeddingRequest as EmbeddingRequest +from otari._client.models.end_user_public import EndUserPublic as EndUserPublic +from otari._client.models.end_user_put import EndUserPut as EndUserPut +from otari._client.models.end_user_update import EndUserUpdate as EndUserUpdate from otari._client.models.execution_state import ExecutionState as ExecutionState from otari._client.models.explain_request import ExplainRequest as ExplainRequest from otari._client.models.explain_response import ExplainResponse as ExplainResponse @@ -1178,6 +1198,10 @@ from otari._client.models.org_provider_key_update_request import OrgProviderKeyUpdateRequest as OrgProviderKeyUpdateRequest from otari._client.models.org_provider_keys_public import OrgProviderKeysPublic as OrgProviderKeysPublic from otari._client.models.org_provider_models_refresh_public import OrgProviderModelsRefreshPublic as OrgProviderModelsRefreshPublic +from otari._client.models.org_web_search_key_create_request import OrgWebSearchKeyCreateRequest as OrgWebSearchKeyCreateRequest +from otari._client.models.org_web_search_key_public import OrgWebSearchKeyPublic as OrgWebSearchKeyPublic +from otari._client.models.org_web_search_key_update_request import OrgWebSearchKeyUpdateRequest as OrgWebSearchKeyUpdateRequest +from otari._client.models.org_web_search_keys_public import OrgWebSearchKeysPublic as OrgWebSearchKeysPublic from otari._client.models.organization_budget_create import OrganizationBudgetCreate as OrganizationBudgetCreate from otari._client.models.organization_budget_public import OrganizationBudgetPublic as OrganizationBudgetPublic from otari._client.models.organization_budget_update import OrganizationBudgetUpdate as OrganizationBudgetUpdate @@ -1286,6 +1310,7 @@ 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 +from otari._client.models.sandbox_provider import SandboxProvider as SandboxProvider from otari._client.models.scoped_budget_response import ScopedBudgetResponse as ScopedBudgetResponse from otari._client.models.score_question import ScoreQuestion as ScoreQuestion from otari._client.models.scored_example import ScoredExample as ScoredExample @@ -1393,6 +1418,9 @@ from otari._client.models.workspace_update import WorkspaceUpdate as WorkspaceUpdate from otari._client.models.workspace_web_search_config_public import WorkspaceWebSearchConfigPublic as WorkspaceWebSearchConfigPublic from otari._client.models.workspace_web_search_config_update import WorkspaceWebSearchConfigUpdate as WorkspaceWebSearchConfigUpdate +from otari._client.models.workspace_web_search_key_override_request import WorkspaceWebSearchKeyOverrideRequest as WorkspaceWebSearchKeyOverrideRequest +from otari._client.models.workspace_web_search_key_public import WorkspaceWebSearchKeyPublic as WorkspaceWebSearchKeyPublic +from otari._client.models.workspace_web_search_keys_public import WorkspaceWebSearchKeysPublic as WorkspaceWebSearchKeysPublic from otari._client.models.workspaces_public import WorkspacesPublic as WorkspacesPublic from otari._client.models.worst_allocation_response import WorstAllocationResponse as WorstAllocationResponse diff --git a/src/otari/_client/api/__init__.py b/src/otari/_client/api/__init__.py index 7bf6a51f..b873b0d0 100644 --- a/src/otari/_client/api/__init__.py +++ b/src/otari/_client/api/__init__.py @@ -52,6 +52,7 @@ from otari._client.api.usage_api import UsageApi from otari._client.api.users_api import UsersApi from otari._client.api.web_search_api import WebSearchApi +from otari._client.api.web_search_keys_api import WebSearchKeysApi 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 diff --git a/src/otari/_client/api/budgets_api.py b/src/otari/_client/api/budgets_api.py index d1ada405..4dc52f1d 100644 --- a/src/otari/_client/api/budgets_api.py +++ b/src/otari/_client/api/budgets_api.py @@ -15,7 +15,7 @@ from typing import Any, Dict, List, Optional, Tuple, Union from typing_extensions import Annotated -from pydantic import Field, StrictStr +from pydantic import Field, StrictStr, field_validator from typing import List, Optional from typing_extensions import Annotated from otari._client.models.budget_reset_log_response import BudgetResetLogResponse @@ -338,7 +338,7 @@ def budgets_delete_budget( ) -> None: """Delete Budget - Delete a budget the deployment owns. Refused with 409 for an organization's budget: the operator may edit one (``PATCH`` retimes its ceilings) but deleting it would take a budget the tenant defined out from under them. Refused with 409, too, while anything still names this budget: a workspace handing it to its members, or a scoped ceiling enforcing it. The refusal says which, and where. Gateway users assigned to the budget are left uncapped, as the dashboard's confirmation says, and its reset history is deleted with it. + Delete a budget the deployment owns. Refused with 409 for an organization's budget: the operator may edit one (``PATCH`` retimes its ceilings) but deleting it would take a budget the tenant defined out from under them. Refused with 409, too, while anything still names this budget: a workspace handing it to its members, or a scoped ceiling enforcing it. The refusal says which, and where. Gateway users assigned to the budget are left uncapped, as the dashboard's confirmation says, its reset history is deleted with it, and it is taken off every service key's ``end_user_budget_ids``. A budget that is a key's ``end_user_budget_id`` is refused (409) until that key's default changes. :param budget_id: (required) :type budget_id: str @@ -406,7 +406,7 @@ def budgets_delete_budget_with_http_info( ) -> ApiResponse[None]: """Delete Budget - Delete a budget the deployment owns. Refused with 409 for an organization's budget: the operator may edit one (``PATCH`` retimes its ceilings) but deleting it would take a budget the tenant defined out from under them. Refused with 409, too, while anything still names this budget: a workspace handing it to its members, or a scoped ceiling enforcing it. The refusal says which, and where. Gateway users assigned to the budget are left uncapped, as the dashboard's confirmation says, and its reset history is deleted with it. + Delete a budget the deployment owns. Refused with 409 for an organization's budget: the operator may edit one (``PATCH`` retimes its ceilings) but deleting it would take a budget the tenant defined out from under them. Refused with 409, too, while anything still names this budget: a workspace handing it to its members, or a scoped ceiling enforcing it. The refusal says which, and where. Gateway users assigned to the budget are left uncapped, as the dashboard's confirmation says, its reset history is deleted with it, and it is taken off every service key's ``end_user_budget_ids``. A budget that is a key's ``end_user_budget_id`` is refused (409) until that key's default changes. :param budget_id: (required) :type budget_id: str @@ -474,7 +474,7 @@ def budgets_delete_budget_without_preload_content( ) -> RESTResponseType: """Delete Budget - Delete a budget the deployment owns. Refused with 409 for an organization's budget: the operator may edit one (``PATCH`` retimes its ceilings) but deleting it would take a budget the tenant defined out from under them. Refused with 409, too, while anything still names this budget: a workspace handing it to its members, or a scoped ceiling enforcing it. The refusal says which, and where. Gateway users assigned to the budget are left uncapped, as the dashboard's confirmation says, and its reset history is deleted with it. + Delete a budget the deployment owns. Refused with 409 for an organization's budget: the operator may edit one (``PATCH`` retimes its ceilings) but deleting it would take a budget the tenant defined out from under them. Refused with 409, too, while anything still names this budget: a workspace handing it to its members, or a scoped ceiling enforcing it. The refusal says which, and where. Gateway users assigned to the budget are left uncapped, as the dashboard's confirmation says, its reset history is deleted with it, and it is taken off every service key's ``end_user_budget_ids``. A budget that is a key's ``end_user_budget_id`` is refused (409) until that key's default changes. :param budget_id: (required) :type budget_id: str @@ -1432,6 +1432,302 @@ def _budgets_list_budgets_serialize( + @validate_call + def budgets_put_budget( + self, + budget_id: Annotated[str, Field(strict=True, description="An id you choose: up to 128 letters, digits, '.', '_' and '-', starting with a letter or digit")], + create_budget_request: CreateBudgetRequest, + _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, + ) -> BudgetResponse: + """Put Budget + + Create a budget under an id you choose, or replace the one with that id. Every field takes the value in the body, and a field left out is cleared, so the same request always leaves the same budget. Answers 201 when it created the budget. Users on a budget it replaces stay on it, and its ceilings follow a change of reset period. A budget an organization owns is not replaced. + + :param budget_id: An id you choose: up to 128 letters, digits, '.', '_' and '-', starting with a letter or digit (required) + :type budget_id: str + :param create_budget_request: (required) + :type create_budget_request: CreateBudgetRequest + :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._budgets_put_budget_serialize( + budget_id=budget_id, + create_budget_request=create_budget_request, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "BudgetResponse", + '201': "BudgetResponse", + '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 budgets_put_budget_with_http_info( + self, + budget_id: Annotated[str, Field(strict=True, description="An id you choose: up to 128 letters, digits, '.', '_' and '-', starting with a letter or digit")], + create_budget_request: CreateBudgetRequest, + _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[BudgetResponse]: + """Put Budget + + Create a budget under an id you choose, or replace the one with that id. Every field takes the value in the body, and a field left out is cleared, so the same request always leaves the same budget. Answers 201 when it created the budget. Users on a budget it replaces stay on it, and its ceilings follow a change of reset period. A budget an organization owns is not replaced. + + :param budget_id: An id you choose: up to 128 letters, digits, '.', '_' and '-', starting with a letter or digit (required) + :type budget_id: str + :param create_budget_request: (required) + :type create_budget_request: CreateBudgetRequest + :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._budgets_put_budget_serialize( + budget_id=budget_id, + create_budget_request=create_budget_request, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "BudgetResponse", + '201': "BudgetResponse", + '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 budgets_put_budget_without_preload_content( + self, + budget_id: Annotated[str, Field(strict=True, description="An id you choose: up to 128 letters, digits, '.', '_' and '-', starting with a letter or digit")], + create_budget_request: CreateBudgetRequest, + _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: + """Put Budget + + Create a budget under an id you choose, or replace the one with that id. Every field takes the value in the body, and a field left out is cleared, so the same request always leaves the same budget. Answers 201 when it created the budget. Users on a budget it replaces stay on it, and its ceilings follow a change of reset period. A budget an organization owns is not replaced. + + :param budget_id: An id you choose: up to 128 letters, digits, '.', '_' and '-', starting with a letter or digit (required) + :type budget_id: str + :param create_budget_request: (required) + :type create_budget_request: CreateBudgetRequest + :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._budgets_put_budget_serialize( + budget_id=budget_id, + create_budget_request=create_budget_request, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "BudgetResponse", + '201': "BudgetResponse", + '422': "HTTPValidationError", + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + return response_data.response + + + def _budgets_put_budget_serialize( + self, + budget_id, + create_budget_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 + if budget_id is not None: + _path_params['budget_id'] = budget_id + # process the query parameters + # process the header parameters + # process the form parameters + # process the body parameter + if create_budget_request is not None: + _body_params = create_budget_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] = [ + 'XApiKeyAuth', + 'ApiKeyAuth' + ] + + return self.api_client.param_serialize( + method='PUT', + resource_path='/api/v1/budgets/{budget_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 budgets_update_budget( self, diff --git a/src/otari/_client/api/keys_api.py b/src/otari/_client/api/keys_api.py index a2ff62d2..ae90f041 100644 --- a/src/otari/_client/api/keys_api.py +++ b/src/otari/_client/api/keys_api.py @@ -21,6 +21,9 @@ from uuid import UUID from otari._client.models.create_key_request import CreateKeyRequest from otari._client.models.create_key_response import CreateKeyResponse +from otari._client.models.end_user_public import EndUserPublic +from otari._client.models.end_user_put import EndUserPut +from otari._client.models.end_user_update import EndUserUpdate from otari._client.models.key_info import KeyInfo from otari._client.models.update_key_request import UpdateKeyRequest @@ -585,6 +588,286 @@ def _keys_delete_key_serialize( + @validate_call + def keys_get_end_user( + self, + key_id: StrictStr, + external_id: Annotated[StrictStr, Field(description="The id the service names the end user by in a request's user field")], + _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, + ) -> EndUserPublic: + """Get End User + + Get an end user of a service key by the id the service names it by. End users belong to the key's user, so every service key of one user reaches the same end users. + + :param key_id: (required) + :type key_id: str + :param external_id: The id the service names the end user by in a request's user field (required) + :type external_id: str + :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._keys_get_end_user_serialize( + key_id=key_id, + external_id=external_id, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "EndUserPublic", + '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 keys_get_end_user_with_http_info( + self, + key_id: StrictStr, + external_id: Annotated[StrictStr, Field(description="The id the service names the end user by in a request's user field")], + _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[EndUserPublic]: + """Get End User + + Get an end user of a service key by the id the service names it by. End users belong to the key's user, so every service key of one user reaches the same end users. + + :param key_id: (required) + :type key_id: str + :param external_id: The id the service names the end user by in a request's user field (required) + :type external_id: str + :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._keys_get_end_user_serialize( + key_id=key_id, + external_id=external_id, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "EndUserPublic", + '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 keys_get_end_user_without_preload_content( + self, + key_id: StrictStr, + external_id: Annotated[StrictStr, Field(description="The id the service names the end user by in a request's user field")], + _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 End User + + Get an end user of a service key by the id the service names it by. End users belong to the key's user, so every service key of one user reaches the same end users. + + :param key_id: (required) + :type key_id: str + :param external_id: The id the service names the end user by in a request's user field (required) + :type external_id: str + :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._keys_get_end_user_serialize( + key_id=key_id, + external_id=external_id, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "EndUserPublic", + '422': "HTTPValidationError", + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + return response_data.response + + + def _keys_get_end_user_serialize( + self, + key_id, + external_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 key_id is not None: + _path_params['key_id'] = key_id + if external_id is not None: + _path_params['external_id'] = external_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='/api/v1/keys/{key_id}/end-users/{external_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 keys_get_key( self, @@ -601,13 +884,585 @@ def keys_get_key( _content_type: Optional[StrictStr] = None, _headers: Optional[Dict[StrictStr, Any]] = None, _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, - ) -> KeyInfo: - """Get Key + ) -> KeyInfo: + """Get Key + + Get details of a specific API key in the caller's organization. Requires master key authentication. + + :param key_id: (required) + :type key_id: str + :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._keys_get_key_serialize( + key_id=key_id, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "KeyInfo", + '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 keys_get_key_with_http_info( + self, + key_id: StrictStr, + _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[KeyInfo]: + """Get Key + + Get details of a specific API key in the caller's organization. Requires master key authentication. + + :param key_id: (required) + :type key_id: str + :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._keys_get_key_serialize( + key_id=key_id, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "KeyInfo", + '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 keys_get_key_without_preload_content( + self, + key_id: StrictStr, + _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 Key + + Get details of a specific API key in the caller's organization. Requires master key authentication. + + :param key_id: (required) + :type key_id: str + :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._keys_get_key_serialize( + key_id=key_id, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "KeyInfo", + '422': "HTTPValidationError", + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + return response_data.response + + + def _keys_get_key_serialize( + self, + key_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 key_id is not None: + _path_params['key_id'] = key_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='/api/v1/keys/{key_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 keys_list_keys( + self, + skip: Optional[Annotated[int, Field(strict=True, ge=0)]] = None, + limit: Optional[Annotated[int, Field(le=1000, strict=True, ge=1)]] = None, + workspace_id: Annotated[Optional[UUID], Field(description="Only keys in this workspace.")] = 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, + ) -> List[KeyInfo]: + """List Keys + + List the API keys in the caller's organization. Requires master key authentication. An unset ``workspace_id`` lists every key in that organization; naming a workspace in another one lists nothing rather than refusing, so the filter reports no more than the unfiltered read does. + + :param skip: + :type skip: int + :param limit: + :type limit: int + :param workspace_id: Only keys in this workspace. + :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._keys_list_keys_serialize( + skip=skip, + limit=limit, + 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': "List[KeyInfo]", + '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 keys_list_keys_with_http_info( + self, + skip: Optional[Annotated[int, Field(strict=True, ge=0)]] = None, + limit: Optional[Annotated[int, Field(le=1000, strict=True, ge=1)]] = None, + workspace_id: Annotated[Optional[UUID], Field(description="Only keys in this workspace.")] = 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[List[KeyInfo]]: + """List Keys + + List the API keys in the caller's organization. Requires master key authentication. An unset ``workspace_id`` lists every key in that organization; naming a workspace in another one lists nothing rather than refusing, so the filter reports no more than the unfiltered read does. + + :param skip: + :type skip: int + :param limit: + :type limit: int + :param workspace_id: Only keys in this workspace. + :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._keys_list_keys_serialize( + skip=skip, + limit=limit, + 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': "List[KeyInfo]", + '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 keys_list_keys_without_preload_content( + self, + skip: Optional[Annotated[int, Field(strict=True, ge=0)]] = None, + limit: Optional[Annotated[int, Field(le=1000, strict=True, ge=1)]] = None, + workspace_id: Annotated[Optional[UUID], Field(description="Only keys in this workspace.")] = 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 Keys + + List the API keys in the caller's organization. Requires master key authentication. An unset ``workspace_id`` lists every key in that organization; naming a workspace in another one lists nothing rather than refusing, so the filter reports no more than the unfiltered read does. + + :param skip: + :type skip: int + :param limit: + :type limit: int + :param workspace_id: Only keys in this workspace. + :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._keys_list_keys_serialize( + skip=skip, + limit=limit, + 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': "List[KeyInfo]", + '422': "HTTPValidationError", + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + return response_data.response + + + def _keys_list_keys_serialize( + self, + skip, + limit, + 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 + # process the query parameters + if skip is not None: + + _query_params.append(('skip', skip)) + + if limit is not None: + + _query_params.append(('limit', limit)) + + if workspace_id is not None: + + _query_params.append(('workspace_id', workspace_id)) + + # 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='/api/v1/keys', + 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 keys_put_end_user( + self, + key_id: StrictStr, + external_id: Annotated[StrictStr, Field(description="The id the service names the end user by in a request's user field")], + end_user_put: EndUserPut, + _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, + ) -> EndUserPublic: + """Put End User - Get details of a specific API key in the caller's organization. Requires master key authentication. + Put an end user of a service key on a budget from the key's list, creating it if it does not exist yet. Answers 201 when the end user was created, so one can be placed on a budget before its first request. An end user already on the budget keeps its current period, so repeating the call changes nothing. A budget that is not on the key's ``end_user_budget_ids`` is refused with 403 and ``end_user_budget_not_allowed``. :param key_id: (required) :type key_id: str + :param external_id: The id the service names the end user by in a request's user field (required) + :type external_id: str + :param end_user_put: (required) + :type end_user_put: EndUserPut :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 @@ -630,8 +1485,10 @@ def keys_get_key( :return: Returns the result object. """ # noqa: E501 - _param = self._keys_get_key_serialize( + _param = self._keys_put_end_user_serialize( key_id=key_id, + external_id=external_id, + end_user_put=end_user_put, _request_auth=_request_auth, _content_type=_content_type, _headers=_headers, @@ -639,7 +1496,8 @@ def keys_get_key( ) _response_types_map: Dict[str, Optional[str]] = { - '200': "KeyInfo", + '200': "EndUserPublic", + '201': "EndUserPublic", '422': "HTTPValidationError", } response_data = self.api_client.call_api( @@ -654,9 +1512,11 @@ def keys_get_key( @validate_call - def keys_get_key_with_http_info( + def keys_put_end_user_with_http_info( self, key_id: StrictStr, + external_id: Annotated[StrictStr, Field(description="The id the service names the end user by in a request's user field")], + end_user_put: EndUserPut, _request_timeout: Union[ None, Annotated[StrictFloat, Field(gt=0)], @@ -669,13 +1529,17 @@ def keys_get_key_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[KeyInfo]: - """Get Key + ) -> ApiResponse[EndUserPublic]: + """Put End User - Get details of a specific API key in the caller's organization. Requires master key authentication. + Put an end user of a service key on a budget from the key's list, creating it if it does not exist yet. Answers 201 when the end user was created, so one can be placed on a budget before its first request. An end user already on the budget keeps its current period, so repeating the call changes nothing. A budget that is not on the key's ``end_user_budget_ids`` is refused with 403 and ``end_user_budget_not_allowed``. :param key_id: (required) :type key_id: str + :param external_id: The id the service names the end user by in a request's user field (required) + :type external_id: str + :param end_user_put: (required) + :type end_user_put: EndUserPut :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 @@ -698,8 +1562,10 @@ def keys_get_key_with_http_info( :return: Returns the result object. """ # noqa: E501 - _param = self._keys_get_key_serialize( + _param = self._keys_put_end_user_serialize( key_id=key_id, + external_id=external_id, + end_user_put=end_user_put, _request_auth=_request_auth, _content_type=_content_type, _headers=_headers, @@ -707,7 +1573,8 @@ def keys_get_key_with_http_info( ) _response_types_map: Dict[str, Optional[str]] = { - '200': "KeyInfo", + '200': "EndUserPublic", + '201': "EndUserPublic", '422': "HTTPValidationError", } response_data = self.api_client.call_api( @@ -722,9 +1589,11 @@ def keys_get_key_with_http_info( @validate_call - def keys_get_key_without_preload_content( + def keys_put_end_user_without_preload_content( self, key_id: StrictStr, + external_id: Annotated[StrictStr, Field(description="The id the service names the end user by in a request's user field")], + end_user_put: EndUserPut, _request_timeout: Union[ None, Annotated[StrictFloat, Field(gt=0)], @@ -738,12 +1607,16 @@ def keys_get_key_without_preload_content( _headers: Optional[Dict[StrictStr, Any]] = None, _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, ) -> RESTResponseType: - """Get Key + """Put End User - Get details of a specific API key in the caller's organization. Requires master key authentication. + Put an end user of a service key on a budget from the key's list, creating it if it does not exist yet. Answers 201 when the end user was created, so one can be placed on a budget before its first request. An end user already on the budget keeps its current period, so repeating the call changes nothing. A budget that is not on the key's ``end_user_budget_ids`` is refused with 403 and ``end_user_budget_not_allowed``. :param key_id: (required) :type key_id: str + :param external_id: The id the service names the end user by in a request's user field (required) + :type external_id: str + :param end_user_put: (required) + :type end_user_put: EndUserPut :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 @@ -766,8 +1639,10 @@ def keys_get_key_without_preload_content( :return: Returns the result object. """ # noqa: E501 - _param = self._keys_get_key_serialize( + _param = self._keys_put_end_user_serialize( key_id=key_id, + external_id=external_id, + end_user_put=end_user_put, _request_auth=_request_auth, _content_type=_content_type, _headers=_headers, @@ -775,7 +1650,8 @@ def keys_get_key_without_preload_content( ) _response_types_map: Dict[str, Optional[str]] = { - '200': "KeyInfo", + '200': "EndUserPublic", + '201': "EndUserPublic", '422': "HTTPValidationError", } response_data = self.api_client.call_api( @@ -785,9 +1661,11 @@ def keys_get_key_without_preload_content( return response_data.response - def _keys_get_key_serialize( + def _keys_put_end_user_serialize( self, key_id, + external_id, + end_user_put, _request_auth, _content_type, _headers, @@ -811,10 +1689,14 @@ def _keys_get_key_serialize( # process the path parameters if key_id is not None: _path_params['key_id'] = key_id + if external_id is not None: + _path_params['external_id'] = external_id # process the query parameters # process the header parameters # process the form parameters # process the body parameter + if end_user_put is not None: + _body_params = end_user_put # set the HTTP header `Accept` @@ -825,6 +1707,19 @@ def _keys_get_key_serialize( ] ) + # 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] = [ @@ -833,8 +1728,8 @@ def _keys_get_key_serialize( ] return self.api_client.param_serialize( - method='GET', - resource_path='/api/v1/keys/{key_id}', + method='PUT', + resource_path='/api/v1/keys/{key_id}/end-users/{external_id}', path_params=_path_params, query_params=_query_params, header_params=_header_params, @@ -851,11 +1746,9 @@ def _keys_get_key_serialize( @validate_call - def keys_list_keys( + def keys_rotate_key( self, - skip: Optional[Annotated[int, Field(strict=True, ge=0)]] = None, - limit: Optional[Annotated[int, Field(le=1000, strict=True, ge=1)]] = None, - workspace_id: Annotated[Optional[UUID], Field(description="Only keys in this workspace.")] = None, + key_id: StrictStr, _request_timeout: Union[ None, Annotated[StrictFloat, Field(gt=0)], @@ -868,17 +1761,13 @@ def keys_list_keys( _content_type: Optional[StrictStr] = None, _headers: Optional[Dict[StrictStr, Any]] = None, _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, - ) -> List[KeyInfo]: - """List Keys + ) -> CreateKeyResponse: + """Rotate Key - List the API keys in the caller's organization. Requires master key authentication. An unset ``workspace_id`` lists every key in that organization; naming a workspace in another one lists nothing rather than refusing, so the filter reports no more than the unfiltered read does. + Rotate an API key's secret in place, within the caller's organization. Requires master key authentication. Generates a new secret for the same key row (id, user, name, expiry, and metadata are preserved) and returns the new raw key once, using the same response shape as key creation. The previous secret stops authenticating immediately; there is no grace window. - :param skip: - :type skip: int - :param limit: - :type limit: int - :param workspace_id: Only keys in this workspace. - :type workspace_id: UUID + :param key_id: (required) + :type key_id: str :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 @@ -901,10 +1790,8 @@ def keys_list_keys( :return: Returns the result object. """ # noqa: E501 - _param = self._keys_list_keys_serialize( - skip=skip, - limit=limit, - workspace_id=workspace_id, + _param = self._keys_rotate_key_serialize( + key_id=key_id, _request_auth=_request_auth, _content_type=_content_type, _headers=_headers, @@ -912,7 +1799,7 @@ def keys_list_keys( ) _response_types_map: Dict[str, Optional[str]] = { - '200': "List[KeyInfo]", + '200': "CreateKeyResponse", '422': "HTTPValidationError", } response_data = self.api_client.call_api( @@ -927,11 +1814,9 @@ def keys_list_keys( @validate_call - def keys_list_keys_with_http_info( + def keys_rotate_key_with_http_info( self, - skip: Optional[Annotated[int, Field(strict=True, ge=0)]] = None, - limit: Optional[Annotated[int, Field(le=1000, strict=True, ge=1)]] = None, - workspace_id: Annotated[Optional[UUID], Field(description="Only keys in this workspace.")] = None, + key_id: StrictStr, _request_timeout: Union[ None, Annotated[StrictFloat, Field(gt=0)], @@ -944,17 +1829,13 @@ def keys_list_keys_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[List[KeyInfo]]: - """List Keys + ) -> ApiResponse[CreateKeyResponse]: + """Rotate Key - List the API keys in the caller's organization. Requires master key authentication. An unset ``workspace_id`` lists every key in that organization; naming a workspace in another one lists nothing rather than refusing, so the filter reports no more than the unfiltered read does. + Rotate an API key's secret in place, within the caller's organization. Requires master key authentication. Generates a new secret for the same key row (id, user, name, expiry, and metadata are preserved) and returns the new raw key once, using the same response shape as key creation. The previous secret stops authenticating immediately; there is no grace window. - :param skip: - :type skip: int - :param limit: - :type limit: int - :param workspace_id: Only keys in this workspace. - :type workspace_id: UUID + :param key_id: (required) + :type key_id: str :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 @@ -977,10 +1858,8 @@ def keys_list_keys_with_http_info( :return: Returns the result object. """ # noqa: E501 - _param = self._keys_list_keys_serialize( - skip=skip, - limit=limit, - workspace_id=workspace_id, + _param = self._keys_rotate_key_serialize( + key_id=key_id, _request_auth=_request_auth, _content_type=_content_type, _headers=_headers, @@ -988,7 +1867,7 @@ def keys_list_keys_with_http_info( ) _response_types_map: Dict[str, Optional[str]] = { - '200': "List[KeyInfo]", + '200': "CreateKeyResponse", '422': "HTTPValidationError", } response_data = self.api_client.call_api( @@ -1003,11 +1882,9 @@ def keys_list_keys_with_http_info( @validate_call - def keys_list_keys_without_preload_content( + def keys_rotate_key_without_preload_content( self, - skip: Optional[Annotated[int, Field(strict=True, ge=0)]] = None, - limit: Optional[Annotated[int, Field(le=1000, strict=True, ge=1)]] = None, - workspace_id: Annotated[Optional[UUID], Field(description="Only keys in this workspace.")] = None, + key_id: StrictStr, _request_timeout: Union[ None, Annotated[StrictFloat, Field(gt=0)], @@ -1021,16 +1898,12 @@ def keys_list_keys_without_preload_content( _headers: Optional[Dict[StrictStr, Any]] = None, _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, ) -> RESTResponseType: - """List Keys + """Rotate Key - List the API keys in the caller's organization. Requires master key authentication. An unset ``workspace_id`` lists every key in that organization; naming a workspace in another one lists nothing rather than refusing, so the filter reports no more than the unfiltered read does. + Rotate an API key's secret in place, within the caller's organization. Requires master key authentication. Generates a new secret for the same key row (id, user, name, expiry, and metadata are preserved) and returns the new raw key once, using the same response shape as key creation. The previous secret stops authenticating immediately; there is no grace window. - :param skip: - :type skip: int - :param limit: - :type limit: int - :param workspace_id: Only keys in this workspace. - :type workspace_id: UUID + :param key_id: (required) + :type key_id: str :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 @@ -1053,10 +1926,8 @@ def keys_list_keys_without_preload_content( :return: Returns the result object. """ # noqa: E501 - _param = self._keys_list_keys_serialize( - skip=skip, - limit=limit, - workspace_id=workspace_id, + _param = self._keys_rotate_key_serialize( + key_id=key_id, _request_auth=_request_auth, _content_type=_content_type, _headers=_headers, @@ -1064,7 +1935,7 @@ def keys_list_keys_without_preload_content( ) _response_types_map: Dict[str, Optional[str]] = { - '200': "List[KeyInfo]", + '200': "CreateKeyResponse", '422': "HTTPValidationError", } response_data = self.api_client.call_api( @@ -1074,11 +1945,9 @@ def keys_list_keys_without_preload_content( return response_data.response - def _keys_list_keys_serialize( + def _keys_rotate_key_serialize( self, - skip, - limit, - workspace_id, + key_id, _request_auth, _content_type, _headers, @@ -1100,19 +1969,9 @@ def _keys_list_keys_serialize( _body_params: Optional[bytes] = None # process the path parameters + if key_id is not None: + _path_params['key_id'] = key_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)) - - if workspace_id is not None: - - _query_params.append(('workspace_id', workspace_id)) - # process the header parameters # process the form parameters # process the body parameter @@ -1134,8 +1993,8 @@ def _keys_list_keys_serialize( ] return self.api_client.param_serialize( - method='GET', - resource_path='/api/v1/keys', + method='POST', + resource_path='/api/v1/keys/{key_id}/rotate', path_params=_path_params, query_params=_query_params, header_params=_header_params, @@ -1152,9 +2011,11 @@ def _keys_list_keys_serialize( @validate_call - def keys_rotate_key( + def keys_update_end_user( self, key_id: StrictStr, + external_id: Annotated[StrictStr, Field(description="The id the service names the end user by in a request's user field")], + end_user_update: EndUserUpdate, _request_timeout: Union[ None, Annotated[StrictFloat, Field(gt=0)], @@ -1167,13 +2028,17 @@ def keys_rotate_key( _content_type: Optional[StrictStr] = None, _headers: Optional[Dict[StrictStr, Any]] = None, _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, - ) -> CreateKeyResponse: - """Rotate Key + ) -> EndUserPublic: + """Update End User - Rotate an API key's secret in place, within the caller's organization. Requires master key authentication. Generates a new secret for the same key row (id, user, name, expiry, and metadata are preserved) and returns the new raw key once, using the same response shape as key creation. The previous secret stops authenticating immediately; there is no grace window. + Block, unblock or move an end user of a service key. A move restarts the end user's period on the new budget but keeps what it has spent and used so far, as the users API does. The budget must be on the key's ``end_user_budget_ids``. :param key_id: (required) :type key_id: str + :param external_id: The id the service names the end user by in a request's user field (required) + :type external_id: str + :param end_user_update: (required) + :type end_user_update: EndUserUpdate :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 @@ -1196,8 +2061,10 @@ def keys_rotate_key( :return: Returns the result object. """ # noqa: E501 - _param = self._keys_rotate_key_serialize( + _param = self._keys_update_end_user_serialize( key_id=key_id, + external_id=external_id, + end_user_update=end_user_update, _request_auth=_request_auth, _content_type=_content_type, _headers=_headers, @@ -1205,7 +2072,7 @@ def keys_rotate_key( ) _response_types_map: Dict[str, Optional[str]] = { - '200': "CreateKeyResponse", + '200': "EndUserPublic", '422': "HTTPValidationError", } response_data = self.api_client.call_api( @@ -1220,9 +2087,11 @@ def keys_rotate_key( @validate_call - def keys_rotate_key_with_http_info( + def keys_update_end_user_with_http_info( self, key_id: StrictStr, + external_id: Annotated[StrictStr, Field(description="The id the service names the end user by in a request's user field")], + end_user_update: EndUserUpdate, _request_timeout: Union[ None, Annotated[StrictFloat, Field(gt=0)], @@ -1235,13 +2104,17 @@ def keys_rotate_key_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[CreateKeyResponse]: - """Rotate Key + ) -> ApiResponse[EndUserPublic]: + """Update End User - Rotate an API key's secret in place, within the caller's organization. Requires master key authentication. Generates a new secret for the same key row (id, user, name, expiry, and metadata are preserved) and returns the new raw key once, using the same response shape as key creation. The previous secret stops authenticating immediately; there is no grace window. + Block, unblock or move an end user of a service key. A move restarts the end user's period on the new budget but keeps what it has spent and used so far, as the users API does. The budget must be on the key's ``end_user_budget_ids``. :param key_id: (required) :type key_id: str + :param external_id: The id the service names the end user by in a request's user field (required) + :type external_id: str + :param end_user_update: (required) + :type end_user_update: EndUserUpdate :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 @@ -1264,8 +2137,10 @@ def keys_rotate_key_with_http_info( :return: Returns the result object. """ # noqa: E501 - _param = self._keys_rotate_key_serialize( + _param = self._keys_update_end_user_serialize( key_id=key_id, + external_id=external_id, + end_user_update=end_user_update, _request_auth=_request_auth, _content_type=_content_type, _headers=_headers, @@ -1273,7 +2148,7 @@ def keys_rotate_key_with_http_info( ) _response_types_map: Dict[str, Optional[str]] = { - '200': "CreateKeyResponse", + '200': "EndUserPublic", '422': "HTTPValidationError", } response_data = self.api_client.call_api( @@ -1288,9 +2163,11 @@ def keys_rotate_key_with_http_info( @validate_call - def keys_rotate_key_without_preload_content( + def keys_update_end_user_without_preload_content( self, key_id: StrictStr, + external_id: Annotated[StrictStr, Field(description="The id the service names the end user by in a request's user field")], + end_user_update: EndUserUpdate, _request_timeout: Union[ None, Annotated[StrictFloat, Field(gt=0)], @@ -1304,12 +2181,16 @@ def keys_rotate_key_without_preload_content( _headers: Optional[Dict[StrictStr, Any]] = None, _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, ) -> RESTResponseType: - """Rotate Key + """Update End User - Rotate an API key's secret in place, within the caller's organization. Requires master key authentication. Generates a new secret for the same key row (id, user, name, expiry, and metadata are preserved) and returns the new raw key once, using the same response shape as key creation. The previous secret stops authenticating immediately; there is no grace window. + Block, unblock or move an end user of a service key. A move restarts the end user's period on the new budget but keeps what it has spent and used so far, as the users API does. The budget must be on the key's ``end_user_budget_ids``. :param key_id: (required) :type key_id: str + :param external_id: The id the service names the end user by in a request's user field (required) + :type external_id: str + :param end_user_update: (required) + :type end_user_update: EndUserUpdate :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 @@ -1332,8 +2213,10 @@ def keys_rotate_key_without_preload_content( :return: Returns the result object. """ # noqa: E501 - _param = self._keys_rotate_key_serialize( + _param = self._keys_update_end_user_serialize( key_id=key_id, + external_id=external_id, + end_user_update=end_user_update, _request_auth=_request_auth, _content_type=_content_type, _headers=_headers, @@ -1341,7 +2224,7 @@ def keys_rotate_key_without_preload_content( ) _response_types_map: Dict[str, Optional[str]] = { - '200': "CreateKeyResponse", + '200': "EndUserPublic", '422': "HTTPValidationError", } response_data = self.api_client.call_api( @@ -1351,9 +2234,11 @@ def keys_rotate_key_without_preload_content( return response_data.response - def _keys_rotate_key_serialize( + def _keys_update_end_user_serialize( self, key_id, + external_id, + end_user_update, _request_auth, _content_type, _headers, @@ -1377,10 +2262,14 @@ def _keys_rotate_key_serialize( # process the path parameters if key_id is not None: _path_params['key_id'] = key_id + if external_id is not None: + _path_params['external_id'] = external_id # process the query parameters # process the header parameters # process the form parameters # process the body parameter + if end_user_update is not None: + _body_params = end_user_update # set the HTTP header `Accept` @@ -1391,6 +2280,19 @@ def _keys_rotate_key_serialize( ] ) + # 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] = [ @@ -1399,8 +2301,8 @@ def _keys_rotate_key_serialize( ] return self.api_client.param_serialize( - method='POST', - resource_path='/api/v1/keys/{key_id}/rotate', + method='PATCH', + resource_path='/api/v1/keys/{key_id}/end-users/{external_id}', path_params=_path_params, query_params=_query_params, header_params=_header_params, diff --git a/src/otari/_client/api/organization_usage_api.py b/src/otari/_client/api/organization_usage_api.py index 6c67b682..73cdb368 100644 --- a/src/otari/_client/api/organization_usage_api.py +++ b/src/otari/_client/api/organization_usage_api.py @@ -56,6 +56,7 @@ def organization_usage_count_organization_usage( provider: Annotated[Optional[StrictStr], Field(description="Filter to a single provider (e.g. 'openai')")] = None, source: Annotated[Optional[StrictStr], Field(description="Filter to a single provenance source (e.g. 'gateway' or 'claude_code')")] = None, source_label: Annotated[Optional[StrictStr], Field(description="Filter to a single session/project label (the source_label carried by imported usage)")] = None, + tag: Annotated[Optional[Annotated[List[StrictStr], Field(max_length=50)]], Field(description="Filter by a request tag (what a request sent in its `metadata`), as `key:value`. Repeatable: values for the same key match any of them, and different keys must all match. At most 50 per call.")] = None, api_key_id: Annotated[Optional[Annotated[List[StrictStr], Field(max_length=50)]], Field(description="Filter to one or more API key ids; repeatable (api_key_id=a&api_key_id=b). Several values match any of them. At most 50 per call.")] = None, priced: Annotated[Optional[StrictBool], Field(description="Filter by token-pricing state: true = only rows whose model tokens were priced, false = only rows that still need pricing (no cost at all, or tokens that were never metered because the model had no rate). A row charged only for gateway-run tool calls still counts as needing pricing.")] = None, tool: Annotated[Optional[StrictStr], Field(description="Filter to requests that ran a gateway-run tool. 'any' matches any tool; a tool name (web_search, web_fetch, code_execution) matches that tool specifically.")] = None, @@ -99,6 +100,8 @@ def organization_usage_count_organization_usage( :type source: str :param source_label: Filter to a single session/project label (the source_label carried by imported usage) :type source_label: str + :param tag: Filter by a request tag (what a request sent in its `metadata`), as `key:value`. Repeatable: values for the same key match any of them, and different keys must all match. At most 50 per call. + :type tag: List[str] :param api_key_id: Filter to one or more API key ids; repeatable (api_key_id=a&api_key_id=b). Several values match any of them. At most 50 per call. :type api_key_id: List[str] :param priced: Filter by token-pricing state: true = only rows whose model tokens were priced, false = only rows that still need pricing (no cost at all, or tokens that were never metered because the model had no rate). A row charged only for gateway-run tool calls still counts as needing pricing. @@ -144,6 +147,7 @@ def organization_usage_count_organization_usage( provider=provider, source=source, source_label=source_label, + tag=tag, api_key_id=api_key_id, priced=priced, tool=tool, @@ -184,6 +188,7 @@ def organization_usage_count_organization_usage_with_http_info( provider: Annotated[Optional[StrictStr], Field(description="Filter to a single provider (e.g. 'openai')")] = None, source: Annotated[Optional[StrictStr], Field(description="Filter to a single provenance source (e.g. 'gateway' or 'claude_code')")] = None, source_label: Annotated[Optional[StrictStr], Field(description="Filter to a single session/project label (the source_label carried by imported usage)")] = None, + tag: Annotated[Optional[Annotated[List[StrictStr], Field(max_length=50)]], Field(description="Filter by a request tag (what a request sent in its `metadata`), as `key:value`. Repeatable: values for the same key match any of them, and different keys must all match. At most 50 per call.")] = None, api_key_id: Annotated[Optional[Annotated[List[StrictStr], Field(max_length=50)]], Field(description="Filter to one or more API key ids; repeatable (api_key_id=a&api_key_id=b). Several values match any of them. At most 50 per call.")] = None, priced: Annotated[Optional[StrictBool], Field(description="Filter by token-pricing state: true = only rows whose model tokens were priced, false = only rows that still need pricing (no cost at all, or tokens that were never metered because the model had no rate). A row charged only for gateway-run tool calls still counts as needing pricing.")] = None, tool: Annotated[Optional[StrictStr], Field(description="Filter to requests that ran a gateway-run tool. 'any' matches any tool; a tool name (web_search, web_fetch, code_execution) matches that tool specifically.")] = None, @@ -227,6 +232,8 @@ def organization_usage_count_organization_usage_with_http_info( :type source: str :param source_label: Filter to a single session/project label (the source_label carried by imported usage) :type source_label: str + :param tag: Filter by a request tag (what a request sent in its `metadata`), as `key:value`. Repeatable: values for the same key match any of them, and different keys must all match. At most 50 per call. + :type tag: List[str] :param api_key_id: Filter to one or more API key ids; repeatable (api_key_id=a&api_key_id=b). Several values match any of them. At most 50 per call. :type api_key_id: List[str] :param priced: Filter by token-pricing state: true = only rows whose model tokens were priced, false = only rows that still need pricing (no cost at all, or tokens that were never metered because the model had no rate). A row charged only for gateway-run tool calls still counts as needing pricing. @@ -272,6 +279,7 @@ def organization_usage_count_organization_usage_with_http_info( provider=provider, source=source, source_label=source_label, + tag=tag, api_key_id=api_key_id, priced=priced, tool=tool, @@ -312,6 +320,7 @@ def organization_usage_count_organization_usage_without_preload_content( provider: Annotated[Optional[StrictStr], Field(description="Filter to a single provider (e.g. 'openai')")] = None, source: Annotated[Optional[StrictStr], Field(description="Filter to a single provenance source (e.g. 'gateway' or 'claude_code')")] = None, source_label: Annotated[Optional[StrictStr], Field(description="Filter to a single session/project label (the source_label carried by imported usage)")] = None, + tag: Annotated[Optional[Annotated[List[StrictStr], Field(max_length=50)]], Field(description="Filter by a request tag (what a request sent in its `metadata`), as `key:value`. Repeatable: values for the same key match any of them, and different keys must all match. At most 50 per call.")] = None, api_key_id: Annotated[Optional[Annotated[List[StrictStr], Field(max_length=50)]], Field(description="Filter to one or more API key ids; repeatable (api_key_id=a&api_key_id=b). Several values match any of them. At most 50 per call.")] = None, priced: Annotated[Optional[StrictBool], Field(description="Filter by token-pricing state: true = only rows whose model tokens were priced, false = only rows that still need pricing (no cost at all, or tokens that were never metered because the model had no rate). A row charged only for gateway-run tool calls still counts as needing pricing.")] = None, tool: Annotated[Optional[StrictStr], Field(description="Filter to requests that ran a gateway-run tool. 'any' matches any tool; a tool name (web_search, web_fetch, code_execution) matches that tool specifically.")] = None, @@ -355,6 +364,8 @@ def organization_usage_count_organization_usage_without_preload_content( :type source: str :param source_label: Filter to a single session/project label (the source_label carried by imported usage) :type source_label: str + :param tag: Filter by a request tag (what a request sent in its `metadata`), as `key:value`. Repeatable: values for the same key match any of them, and different keys must all match. At most 50 per call. + :type tag: List[str] :param api_key_id: Filter to one or more API key ids; repeatable (api_key_id=a&api_key_id=b). Several values match any of them. At most 50 per call. :type api_key_id: List[str] :param priced: Filter by token-pricing state: true = only rows whose model tokens were priced, false = only rows that still need pricing (no cost at all, or tokens that were never metered because the model had no rate). A row charged only for gateway-run tool calls still counts as needing pricing. @@ -400,6 +411,7 @@ def organization_usage_count_organization_usage_without_preload_content( provider=provider, source=source, source_label=source_label, + tag=tag, api_key_id=api_key_id, priced=priced, tool=tool, @@ -435,6 +447,7 @@ def _organization_usage_count_organization_usage_serialize( provider, source, source_label, + tag, api_key_id, priced, tool, @@ -452,6 +465,7 @@ def _organization_usage_count_organization_usage_serialize( _collection_formats: Dict[str, str] = { 'user_id': 'multi', 'model': 'multi', + 'tag': 'multi', 'api_key_id': 'multi', 'request_group_id': 'multi', } @@ -525,6 +539,10 @@ def _organization_usage_count_organization_usage_serialize( _query_params.append(('source_label', source_label)) + if tag is not None: + + _query_params.append(('tag', tag)) + if api_key_id is not None: _query_params.append(('api_key_id', api_key_id)) @@ -600,6 +618,7 @@ def organization_usage_list_organization_usage( provider: Annotated[Optional[StrictStr], Field(description="Filter to a single provider (e.g. 'openai')")] = None, source: Annotated[Optional[StrictStr], Field(description="Filter to a single provenance source (e.g. 'gateway' or 'claude_code')")] = None, source_label: Annotated[Optional[StrictStr], Field(description="Filter to a single session/project label (the source_label carried by imported usage)")] = None, + tag: Annotated[Optional[Annotated[List[StrictStr], Field(max_length=50)]], Field(description="Filter by a request tag (what a request sent in its `metadata`), as `key:value`. Repeatable: values for the same key match any of them, and different keys must all match. At most 50 per call.")] = None, api_key_id: Annotated[Optional[Annotated[List[StrictStr], Field(max_length=50)]], Field(description="Filter to one or more API key ids; repeatable (api_key_id=a&api_key_id=b). Several values match any of them. At most 50 per call.")] = None, priced: Annotated[Optional[StrictBool], Field(description="Filter by token-pricing state: true = only rows whose model tokens were priced, false = only rows that still need pricing (no cost at all, or tokens that were never metered because the model had no rate). A row charged only for gateway-run tool calls still counts as needing pricing.")] = None, tool: Annotated[Optional[StrictStr], Field(description="Filter to requests that ran a gateway-run tool. 'any' matches any tool; a tool name (web_search, web_fetch, code_execution) matches that tool specifically.")] = None, @@ -645,6 +664,8 @@ def organization_usage_list_organization_usage( :type source: str :param source_label: Filter to a single session/project label (the source_label carried by imported usage) :type source_label: str + :param tag: Filter by a request tag (what a request sent in its `metadata`), as `key:value`. Repeatable: values for the same key match any of them, and different keys must all match. At most 50 per call. + :type tag: List[str] :param api_key_id: Filter to one or more API key ids; repeatable (api_key_id=a&api_key_id=b). Several values match any of them. At most 50 per call. :type api_key_id: List[str] :param priced: Filter by token-pricing state: true = only rows whose model tokens were priced, false = only rows that still need pricing (no cost at all, or tokens that were never metered because the model had no rate). A row charged only for gateway-run tool calls still counts as needing pricing. @@ -694,6 +715,7 @@ def organization_usage_list_organization_usage( provider=provider, source=source, source_label=source_label, + tag=tag, api_key_id=api_key_id, priced=priced, tool=tool, @@ -736,6 +758,7 @@ def organization_usage_list_organization_usage_with_http_info( provider: Annotated[Optional[StrictStr], Field(description="Filter to a single provider (e.g. 'openai')")] = None, source: Annotated[Optional[StrictStr], Field(description="Filter to a single provenance source (e.g. 'gateway' or 'claude_code')")] = None, source_label: Annotated[Optional[StrictStr], Field(description="Filter to a single session/project label (the source_label carried by imported usage)")] = None, + tag: Annotated[Optional[Annotated[List[StrictStr], Field(max_length=50)]], Field(description="Filter by a request tag (what a request sent in its `metadata`), as `key:value`. Repeatable: values for the same key match any of them, and different keys must all match. At most 50 per call.")] = None, api_key_id: Annotated[Optional[Annotated[List[StrictStr], Field(max_length=50)]], Field(description="Filter to one or more API key ids; repeatable (api_key_id=a&api_key_id=b). Several values match any of them. At most 50 per call.")] = None, priced: Annotated[Optional[StrictBool], Field(description="Filter by token-pricing state: true = only rows whose model tokens were priced, false = only rows that still need pricing (no cost at all, or tokens that were never metered because the model had no rate). A row charged only for gateway-run tool calls still counts as needing pricing.")] = None, tool: Annotated[Optional[StrictStr], Field(description="Filter to requests that ran a gateway-run tool. 'any' matches any tool; a tool name (web_search, web_fetch, code_execution) matches that tool specifically.")] = None, @@ -781,6 +804,8 @@ def organization_usage_list_organization_usage_with_http_info( :type source: str :param source_label: Filter to a single session/project label (the source_label carried by imported usage) :type source_label: str + :param tag: Filter by a request tag (what a request sent in its `metadata`), as `key:value`. Repeatable: values for the same key match any of them, and different keys must all match. At most 50 per call. + :type tag: List[str] :param api_key_id: Filter to one or more API key ids; repeatable (api_key_id=a&api_key_id=b). Several values match any of them. At most 50 per call. :type api_key_id: List[str] :param priced: Filter by token-pricing state: true = only rows whose model tokens were priced, false = only rows that still need pricing (no cost at all, or tokens that were never metered because the model had no rate). A row charged only for gateway-run tool calls still counts as needing pricing. @@ -830,6 +855,7 @@ def organization_usage_list_organization_usage_with_http_info( provider=provider, source=source, source_label=source_label, + tag=tag, api_key_id=api_key_id, priced=priced, tool=tool, @@ -872,6 +898,7 @@ def organization_usage_list_organization_usage_without_preload_content( provider: Annotated[Optional[StrictStr], Field(description="Filter to a single provider (e.g. 'openai')")] = None, source: Annotated[Optional[StrictStr], Field(description="Filter to a single provenance source (e.g. 'gateway' or 'claude_code')")] = None, source_label: Annotated[Optional[StrictStr], Field(description="Filter to a single session/project label (the source_label carried by imported usage)")] = None, + tag: Annotated[Optional[Annotated[List[StrictStr], Field(max_length=50)]], Field(description="Filter by a request tag (what a request sent in its `metadata`), as `key:value`. Repeatable: values for the same key match any of them, and different keys must all match. At most 50 per call.")] = None, api_key_id: Annotated[Optional[Annotated[List[StrictStr], Field(max_length=50)]], Field(description="Filter to one or more API key ids; repeatable (api_key_id=a&api_key_id=b). Several values match any of them. At most 50 per call.")] = None, priced: Annotated[Optional[StrictBool], Field(description="Filter by token-pricing state: true = only rows whose model tokens were priced, false = only rows that still need pricing (no cost at all, or tokens that were never metered because the model had no rate). A row charged only for gateway-run tool calls still counts as needing pricing.")] = None, tool: Annotated[Optional[StrictStr], Field(description="Filter to requests that ran a gateway-run tool. 'any' matches any tool; a tool name (web_search, web_fetch, code_execution) matches that tool specifically.")] = None, @@ -917,6 +944,8 @@ def organization_usage_list_organization_usage_without_preload_content( :type source: str :param source_label: Filter to a single session/project label (the source_label carried by imported usage) :type source_label: str + :param tag: Filter by a request tag (what a request sent in its `metadata`), as `key:value`. Repeatable: values for the same key match any of them, and different keys must all match. At most 50 per call. + :type tag: List[str] :param api_key_id: Filter to one or more API key ids; repeatable (api_key_id=a&api_key_id=b). Several values match any of them. At most 50 per call. :type api_key_id: List[str] :param priced: Filter by token-pricing state: true = only rows whose model tokens were priced, false = only rows that still need pricing (no cost at all, or tokens that were never metered because the model had no rate). A row charged only for gateway-run tool calls still counts as needing pricing. @@ -966,6 +995,7 @@ def organization_usage_list_organization_usage_without_preload_content( provider=provider, source=source, source_label=source_label, + tag=tag, api_key_id=api_key_id, priced=priced, tool=tool, @@ -1003,6 +1033,7 @@ def _organization_usage_list_organization_usage_serialize( provider, source, source_label, + tag, api_key_id, priced, tool, @@ -1022,6 +1053,7 @@ def _organization_usage_list_organization_usage_serialize( _collection_formats: Dict[str, str] = { 'user_id': 'multi', 'model': 'multi', + 'tag': 'multi', 'api_key_id': 'multi', 'request_group_id': 'multi', } @@ -1095,6 +1127,10 @@ def _organization_usage_list_organization_usage_serialize( _query_params.append(('source_label', source_label)) + if tag is not None: + + _query_params.append(('tag', tag)) + if api_key_id is not None: _query_params.append(('api_key_id', api_key_id)) @@ -1179,6 +1215,7 @@ def organization_usage_organization_usage_series( provider: Annotated[Optional[StrictStr], Field(description="Filter to a single provider (e.g. 'openai')")] = None, source: Annotated[Optional[StrictStr], Field(description="Filter to a single provenance source (e.g. 'gateway' or 'claude_code')")] = None, source_label: Annotated[Optional[StrictStr], Field(description="Filter to a single session/project label (the source_label carried by imported usage)")] = None, + tag: Annotated[Optional[Annotated[List[StrictStr], Field(max_length=50)]], Field(description="Filter by a request tag (what a request sent in its `metadata`), as `key:value`. Repeatable: values for the same key match any of them, and different keys must all match. At most 50 per call.")] = None, api_key_id: Annotated[Optional[Annotated[List[StrictStr], Field(max_length=50)]], Field(description="Filter to one or more API key ids; repeatable (api_key_id=a&api_key_id=b). Several values match any of them. At most 50 per call.")] = None, priced: Annotated[Optional[StrictBool], Field(description="Filter by token-pricing state: true = only rows whose model tokens were priced, false = only rows that still need pricing (no cost at all, or tokens that were never metered because the model had no rate). A row charged only for gateway-run tool calls still counts as needing pricing.")] = None, tool: Annotated[Optional[StrictStr], Field(description="Filter to requests that ran a gateway-run tool. 'any' matches any tool; a tool name (web_search, web_fetch, code_execution) matches that tool specifically.")] = None, @@ -1224,6 +1261,8 @@ def organization_usage_organization_usage_series( :type source: str :param source_label: Filter to a single session/project label (the source_label carried by imported usage) :type source_label: str + :param tag: Filter by a request tag (what a request sent in its `metadata`), as `key:value`. Repeatable: values for the same key match any of them, and different keys must all match. At most 50 per call. + :type tag: List[str] :param api_key_id: Filter to one or more API key ids; repeatable (api_key_id=a&api_key_id=b). Several values match any of them. At most 50 per call. :type api_key_id: List[str] :param priced: Filter by token-pricing state: true = only rows whose model tokens were priced, false = only rows that still need pricing (no cost at all, or tokens that were never metered because the model had no rate). A row charged only for gateway-run tool calls still counts as needing pricing. @@ -1270,6 +1309,7 @@ def organization_usage_organization_usage_series( provider=provider, source=source, source_label=source_label, + tag=tag, api_key_id=api_key_id, priced=priced, tool=tool, @@ -1311,6 +1351,7 @@ def organization_usage_organization_usage_series_with_http_info( provider: Annotated[Optional[StrictStr], Field(description="Filter to a single provider (e.g. 'openai')")] = None, source: Annotated[Optional[StrictStr], Field(description="Filter to a single provenance source (e.g. 'gateway' or 'claude_code')")] = None, source_label: Annotated[Optional[StrictStr], Field(description="Filter to a single session/project label (the source_label carried by imported usage)")] = None, + tag: Annotated[Optional[Annotated[List[StrictStr], Field(max_length=50)]], Field(description="Filter by a request tag (what a request sent in its `metadata`), as `key:value`. Repeatable: values for the same key match any of them, and different keys must all match. At most 50 per call.")] = None, api_key_id: Annotated[Optional[Annotated[List[StrictStr], Field(max_length=50)]], Field(description="Filter to one or more API key ids; repeatable (api_key_id=a&api_key_id=b). Several values match any of them. At most 50 per call.")] = None, priced: Annotated[Optional[StrictBool], Field(description="Filter by token-pricing state: true = only rows whose model tokens were priced, false = only rows that still need pricing (no cost at all, or tokens that were never metered because the model had no rate). A row charged only for gateway-run tool calls still counts as needing pricing.")] = None, tool: Annotated[Optional[StrictStr], Field(description="Filter to requests that ran a gateway-run tool. 'any' matches any tool; a tool name (web_search, web_fetch, code_execution) matches that tool specifically.")] = None, @@ -1356,6 +1397,8 @@ def organization_usage_organization_usage_series_with_http_info( :type source: str :param source_label: Filter to a single session/project label (the source_label carried by imported usage) :type source_label: str + :param tag: Filter by a request tag (what a request sent in its `metadata`), as `key:value`. Repeatable: values for the same key match any of them, and different keys must all match. At most 50 per call. + :type tag: List[str] :param api_key_id: Filter to one or more API key ids; repeatable (api_key_id=a&api_key_id=b). Several values match any of them. At most 50 per call. :type api_key_id: List[str] :param priced: Filter by token-pricing state: true = only rows whose model tokens were priced, false = only rows that still need pricing (no cost at all, or tokens that were never metered because the model had no rate). A row charged only for gateway-run tool calls still counts as needing pricing. @@ -1402,6 +1445,7 @@ def organization_usage_organization_usage_series_with_http_info( provider=provider, source=source, source_label=source_label, + tag=tag, api_key_id=api_key_id, priced=priced, tool=tool, @@ -1443,6 +1487,7 @@ def organization_usage_organization_usage_series_without_preload_content( provider: Annotated[Optional[StrictStr], Field(description="Filter to a single provider (e.g. 'openai')")] = None, source: Annotated[Optional[StrictStr], Field(description="Filter to a single provenance source (e.g. 'gateway' or 'claude_code')")] = None, source_label: Annotated[Optional[StrictStr], Field(description="Filter to a single session/project label (the source_label carried by imported usage)")] = None, + tag: Annotated[Optional[Annotated[List[StrictStr], Field(max_length=50)]], Field(description="Filter by a request tag (what a request sent in its `metadata`), as `key:value`. Repeatable: values for the same key match any of them, and different keys must all match. At most 50 per call.")] = None, api_key_id: Annotated[Optional[Annotated[List[StrictStr], Field(max_length=50)]], Field(description="Filter to one or more API key ids; repeatable (api_key_id=a&api_key_id=b). Several values match any of them. At most 50 per call.")] = None, priced: Annotated[Optional[StrictBool], Field(description="Filter by token-pricing state: true = only rows whose model tokens were priced, false = only rows that still need pricing (no cost at all, or tokens that were never metered because the model had no rate). A row charged only for gateway-run tool calls still counts as needing pricing.")] = None, tool: Annotated[Optional[StrictStr], Field(description="Filter to requests that ran a gateway-run tool. 'any' matches any tool; a tool name (web_search, web_fetch, code_execution) matches that tool specifically.")] = None, @@ -1488,6 +1533,8 @@ def organization_usage_organization_usage_series_without_preload_content( :type source: str :param source_label: Filter to a single session/project label (the source_label carried by imported usage) :type source_label: str + :param tag: Filter by a request tag (what a request sent in its `metadata`), as `key:value`. Repeatable: values for the same key match any of them, and different keys must all match. At most 50 per call. + :type tag: List[str] :param api_key_id: Filter to one or more API key ids; repeatable (api_key_id=a&api_key_id=b). Several values match any of them. At most 50 per call. :type api_key_id: List[str] :param priced: Filter by token-pricing state: true = only rows whose model tokens were priced, false = only rows that still need pricing (no cost at all, or tokens that were never metered because the model had no rate). A row charged only for gateway-run tool calls still counts as needing pricing. @@ -1534,6 +1581,7 @@ def organization_usage_organization_usage_series_without_preload_content( provider=provider, source=source, source_label=source_label, + tag=tag, api_key_id=api_key_id, priced=priced, tool=tool, @@ -1570,6 +1618,7 @@ def _organization_usage_organization_usage_series_serialize( provider, source, source_label, + tag, api_key_id, priced, tool, @@ -1587,6 +1636,7 @@ def _organization_usage_organization_usage_series_serialize( _collection_formats: Dict[str, str] = { 'user_id': 'multi', 'model': 'multi', + 'tag': 'multi', 'api_key_id': 'multi', } @@ -1663,6 +1713,10 @@ def _organization_usage_organization_usage_series_serialize( _query_params.append(('source_label', source_label)) + if tag is not None: + + _query_params.append(('tag', tag)) + if api_key_id is not None: _query_params.append(('api_key_id', api_key_id)) @@ -1738,6 +1792,7 @@ def organization_usage_organization_usage_summary( provider: Annotated[Optional[StrictStr], Field(description="Filter to a single provider (e.g. 'openai')")] = None, source: Annotated[Optional[StrictStr], Field(description="Filter to a single provenance source (e.g. 'gateway' or 'claude_code')")] = None, source_label: Annotated[Optional[StrictStr], Field(description="Filter to a single session/project label (the source_label carried by imported usage)")] = None, + tag: Annotated[Optional[Annotated[List[StrictStr], Field(max_length=50)]], Field(description="Filter by a request tag (what a request sent in its `metadata`), as `key:value`. Repeatable: values for the same key match any of them, and different keys must all match. At most 50 per call.")] = None, api_key_id: Annotated[Optional[Annotated[List[StrictStr], Field(max_length=50)]], Field(description="Filter to one or more API key ids; repeatable (api_key_id=a&api_key_id=b). Several values match any of them. At most 50 per call.")] = None, priced: Annotated[Optional[StrictBool], Field(description="Filter by token-pricing state: true = only rows whose model tokens were priced, false = only rows that still need pricing (no cost at all, or tokens that were never metered because the model had no rate). A row charged only for gateway-run tool calls still counts as needing pricing.")] = None, tool: Annotated[Optional[StrictStr], Field(description="Filter to requests that ran a gateway-run tool. 'any' matches any tool; a tool name (web_search, web_fetch, code_execution) matches that tool specifically.")] = None, @@ -1745,6 +1800,7 @@ def organization_usage_organization_usage_summary( workspace_id: Annotated[Optional[UUID], Field(description="Only usage recorded in this workspace.")] = None, bucket: Annotated[Optional[StrictStr], Field(description="Time-series granularity: 'hour' or 'day'")] = None, dimensions: Annotated[Optional[List[StrictStr]], Field(description="Which breakdowns to compute; repeatable (dimensions=model&dimensions=user). Each value names the 'by_' response field it fills, except 'status_code', which fills the failure taxonomy in 'errors_by_status_code'. Omit for every breakdown (the default); pass 'none' for a totals-and-series-only response. Each dimension left out skips one GROUP BY scan, so a caller that reads only the tiles or the time series should say so. Fields that were not requested come back empty.")] = None, + group_by_tag: Annotated[Optional[Annotated[str, Field(min_length=1, strict=True, max_length=64)]], Field(description="A tag key to break spend down by, returned as `by_tag`. Rows that do not carry the tag group under a null key.")] = None, _request_timeout: Union[ None, Annotated[StrictFloat, Field(gt=0)], @@ -1782,6 +1838,8 @@ def organization_usage_organization_usage_summary( :type source: str :param source_label: Filter to a single session/project label (the source_label carried by imported usage) :type source_label: str + :param tag: Filter by a request tag (what a request sent in its `metadata`), as `key:value`. Repeatable: values for the same key match any of them, and different keys must all match. At most 50 per call. + :type tag: List[str] :param api_key_id: Filter to one or more API key ids; repeatable (api_key_id=a&api_key_id=b). Several values match any of them. At most 50 per call. :type api_key_id: List[str] :param priced: Filter by token-pricing state: true = only rows whose model tokens were priced, false = only rows that still need pricing (no cost at all, or tokens that were never metered because the model had no rate). A row charged only for gateway-run tool calls still counts as needing pricing. @@ -1796,6 +1854,8 @@ def organization_usage_organization_usage_summary( :type bucket: str :param dimensions: Which breakdowns to compute; repeatable (dimensions=model&dimensions=user). Each value names the 'by_' response field it fills, except 'status_code', which fills the failure taxonomy in 'errors_by_status_code'. Omit for every breakdown (the default); pass 'none' for a totals-and-series-only response. Each dimension left out skips one GROUP BY scan, so a caller that reads only the tiles or the time series should say so. Fields that were not requested come back empty. :type dimensions: List[str] + :param group_by_tag: A tag key to break spend down by, returned as `by_tag`. Rows that do not carry the tag group under a null key. + :type group_by_tag: str :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 @@ -1829,6 +1889,7 @@ def organization_usage_organization_usage_summary( provider=provider, source=source, source_label=source_label, + tag=tag, api_key_id=api_key_id, priced=priced, tool=tool, @@ -1836,6 +1897,7 @@ def organization_usage_organization_usage_summary( workspace_id=workspace_id, bucket=bucket, dimensions=dimensions, + group_by_tag=group_by_tag, _request_auth=_request_auth, _content_type=_content_type, _headers=_headers, @@ -1870,6 +1932,7 @@ def organization_usage_organization_usage_summary_with_http_info( provider: Annotated[Optional[StrictStr], Field(description="Filter to a single provider (e.g. 'openai')")] = None, source: Annotated[Optional[StrictStr], Field(description="Filter to a single provenance source (e.g. 'gateway' or 'claude_code')")] = None, source_label: Annotated[Optional[StrictStr], Field(description="Filter to a single session/project label (the source_label carried by imported usage)")] = None, + tag: Annotated[Optional[Annotated[List[StrictStr], Field(max_length=50)]], Field(description="Filter by a request tag (what a request sent in its `metadata`), as `key:value`. Repeatable: values for the same key match any of them, and different keys must all match. At most 50 per call.")] = None, api_key_id: Annotated[Optional[Annotated[List[StrictStr], Field(max_length=50)]], Field(description="Filter to one or more API key ids; repeatable (api_key_id=a&api_key_id=b). Several values match any of them. At most 50 per call.")] = None, priced: Annotated[Optional[StrictBool], Field(description="Filter by token-pricing state: true = only rows whose model tokens were priced, false = only rows that still need pricing (no cost at all, or tokens that were never metered because the model had no rate). A row charged only for gateway-run tool calls still counts as needing pricing.")] = None, tool: Annotated[Optional[StrictStr], Field(description="Filter to requests that ran a gateway-run tool. 'any' matches any tool; a tool name (web_search, web_fetch, code_execution) matches that tool specifically.")] = None, @@ -1877,6 +1940,7 @@ def organization_usage_organization_usage_summary_with_http_info( workspace_id: Annotated[Optional[UUID], Field(description="Only usage recorded in this workspace.")] = None, bucket: Annotated[Optional[StrictStr], Field(description="Time-series granularity: 'hour' or 'day'")] = None, dimensions: Annotated[Optional[List[StrictStr]], Field(description="Which breakdowns to compute; repeatable (dimensions=model&dimensions=user). Each value names the 'by_' response field it fills, except 'status_code', which fills the failure taxonomy in 'errors_by_status_code'. Omit for every breakdown (the default); pass 'none' for a totals-and-series-only response. Each dimension left out skips one GROUP BY scan, so a caller that reads only the tiles or the time series should say so. Fields that were not requested come back empty.")] = None, + group_by_tag: Annotated[Optional[Annotated[str, Field(min_length=1, strict=True, max_length=64)]], Field(description="A tag key to break spend down by, returned as `by_tag`. Rows that do not carry the tag group under a null key.")] = None, _request_timeout: Union[ None, Annotated[StrictFloat, Field(gt=0)], @@ -1914,6 +1978,8 @@ def organization_usage_organization_usage_summary_with_http_info( :type source: str :param source_label: Filter to a single session/project label (the source_label carried by imported usage) :type source_label: str + :param tag: Filter by a request tag (what a request sent in its `metadata`), as `key:value`. Repeatable: values for the same key match any of them, and different keys must all match. At most 50 per call. + :type tag: List[str] :param api_key_id: Filter to one or more API key ids; repeatable (api_key_id=a&api_key_id=b). Several values match any of them. At most 50 per call. :type api_key_id: List[str] :param priced: Filter by token-pricing state: true = only rows whose model tokens were priced, false = only rows that still need pricing (no cost at all, or tokens that were never metered because the model had no rate). A row charged only for gateway-run tool calls still counts as needing pricing. @@ -1928,6 +1994,8 @@ def organization_usage_organization_usage_summary_with_http_info( :type bucket: str :param dimensions: Which breakdowns to compute; repeatable (dimensions=model&dimensions=user). Each value names the 'by_' response field it fills, except 'status_code', which fills the failure taxonomy in 'errors_by_status_code'. Omit for every breakdown (the default); pass 'none' for a totals-and-series-only response. Each dimension left out skips one GROUP BY scan, so a caller that reads only the tiles or the time series should say so. Fields that were not requested come back empty. :type dimensions: List[str] + :param group_by_tag: A tag key to break spend down by, returned as `by_tag`. Rows that do not carry the tag group under a null key. + :type group_by_tag: str :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 @@ -1961,6 +2029,7 @@ def organization_usage_organization_usage_summary_with_http_info( provider=provider, source=source, source_label=source_label, + tag=tag, api_key_id=api_key_id, priced=priced, tool=tool, @@ -1968,6 +2037,7 @@ def organization_usage_organization_usage_summary_with_http_info( workspace_id=workspace_id, bucket=bucket, dimensions=dimensions, + group_by_tag=group_by_tag, _request_auth=_request_auth, _content_type=_content_type, _headers=_headers, @@ -2002,6 +2072,7 @@ def organization_usage_organization_usage_summary_without_preload_content( provider: Annotated[Optional[StrictStr], Field(description="Filter to a single provider (e.g. 'openai')")] = None, source: Annotated[Optional[StrictStr], Field(description="Filter to a single provenance source (e.g. 'gateway' or 'claude_code')")] = None, source_label: Annotated[Optional[StrictStr], Field(description="Filter to a single session/project label (the source_label carried by imported usage)")] = None, + tag: Annotated[Optional[Annotated[List[StrictStr], Field(max_length=50)]], Field(description="Filter by a request tag (what a request sent in its `metadata`), as `key:value`. Repeatable: values for the same key match any of them, and different keys must all match. At most 50 per call.")] = None, api_key_id: Annotated[Optional[Annotated[List[StrictStr], Field(max_length=50)]], Field(description="Filter to one or more API key ids; repeatable (api_key_id=a&api_key_id=b). Several values match any of them. At most 50 per call.")] = None, priced: Annotated[Optional[StrictBool], Field(description="Filter by token-pricing state: true = only rows whose model tokens were priced, false = only rows that still need pricing (no cost at all, or tokens that were never metered because the model had no rate). A row charged only for gateway-run tool calls still counts as needing pricing.")] = None, tool: Annotated[Optional[StrictStr], Field(description="Filter to requests that ran a gateway-run tool. 'any' matches any tool; a tool name (web_search, web_fetch, code_execution) matches that tool specifically.")] = None, @@ -2009,6 +2080,7 @@ def organization_usage_organization_usage_summary_without_preload_content( workspace_id: Annotated[Optional[UUID], Field(description="Only usage recorded in this workspace.")] = None, bucket: Annotated[Optional[StrictStr], Field(description="Time-series granularity: 'hour' or 'day'")] = None, dimensions: Annotated[Optional[List[StrictStr]], Field(description="Which breakdowns to compute; repeatable (dimensions=model&dimensions=user). Each value names the 'by_' response field it fills, except 'status_code', which fills the failure taxonomy in 'errors_by_status_code'. Omit for every breakdown (the default); pass 'none' for a totals-and-series-only response. Each dimension left out skips one GROUP BY scan, so a caller that reads only the tiles or the time series should say so. Fields that were not requested come back empty.")] = None, + group_by_tag: Annotated[Optional[Annotated[str, Field(min_length=1, strict=True, max_length=64)]], Field(description="A tag key to break spend down by, returned as `by_tag`. Rows that do not carry the tag group under a null key.")] = None, _request_timeout: Union[ None, Annotated[StrictFloat, Field(gt=0)], @@ -2046,6 +2118,8 @@ def organization_usage_organization_usage_summary_without_preload_content( :type source: str :param source_label: Filter to a single session/project label (the source_label carried by imported usage) :type source_label: str + :param tag: Filter by a request tag (what a request sent in its `metadata`), as `key:value`. Repeatable: values for the same key match any of them, and different keys must all match. At most 50 per call. + :type tag: List[str] :param api_key_id: Filter to one or more API key ids; repeatable (api_key_id=a&api_key_id=b). Several values match any of them. At most 50 per call. :type api_key_id: List[str] :param priced: Filter by token-pricing state: true = only rows whose model tokens were priced, false = only rows that still need pricing (no cost at all, or tokens that were never metered because the model had no rate). A row charged only for gateway-run tool calls still counts as needing pricing. @@ -2060,6 +2134,8 @@ def organization_usage_organization_usage_summary_without_preload_content( :type bucket: str :param dimensions: Which breakdowns to compute; repeatable (dimensions=model&dimensions=user). Each value names the 'by_' response field it fills, except 'status_code', which fills the failure taxonomy in 'errors_by_status_code'. Omit for every breakdown (the default); pass 'none' for a totals-and-series-only response. Each dimension left out skips one GROUP BY scan, so a caller that reads only the tiles or the time series should say so. Fields that were not requested come back empty. :type dimensions: List[str] + :param group_by_tag: A tag key to break spend down by, returned as `by_tag`. Rows that do not carry the tag group under a null key. + :type group_by_tag: str :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 @@ -2093,6 +2169,7 @@ def organization_usage_organization_usage_summary_without_preload_content( provider=provider, source=source, source_label=source_label, + tag=tag, api_key_id=api_key_id, priced=priced, tool=tool, @@ -2100,6 +2177,7 @@ def organization_usage_organization_usage_summary_without_preload_content( workspace_id=workspace_id, bucket=bucket, dimensions=dimensions, + group_by_tag=group_by_tag, _request_auth=_request_auth, _content_type=_content_type, _headers=_headers, @@ -2129,6 +2207,7 @@ def _organization_usage_organization_usage_summary_serialize( provider, source, source_label, + tag, api_key_id, priced, tool, @@ -2136,6 +2215,7 @@ def _organization_usage_organization_usage_summary_serialize( workspace_id, bucket, dimensions, + group_by_tag, _request_auth, _content_type, _headers, @@ -2147,6 +2227,7 @@ def _organization_usage_organization_usage_summary_serialize( _collection_formats: Dict[str, str] = { 'user_id': 'multi', 'model': 'multi', + 'tag': 'multi', 'api_key_id': 'multi', 'dimensions': 'multi', } @@ -2220,6 +2301,10 @@ def _organization_usage_organization_usage_summary_serialize( _query_params.append(('source_label', source_label)) + if tag is not None: + + _query_params.append(('tag', tag)) + if api_key_id is not None: _query_params.append(('api_key_id', api_key_id)) @@ -2248,6 +2333,10 @@ def _organization_usage_organization_usage_summary_serialize( _query_params.append(('dimensions', dimensions)) + if group_by_tag is not None: + + _query_params.append(('group_by_tag', group_by_tag)) + # process the header parameters # process the form parameters # process the body parameter diff --git a/src/otari/_client/api/routing_api.py b/src/otari/_client/api/routing_api.py index 07f7e49c..bc07a9b2 100644 --- a/src/otari/_client/api/routing_api.py +++ b/src/otari/_client/api/routing_api.py @@ -19,6 +19,8 @@ from typing import List, Optional from typing_extensions import Annotated from uuid import UUID +from otari._client.models.agent_model_recommendation import AgentModelRecommendation +from otari._client.models.agent_model_recommendation_request import AgentModelRecommendationRequest from otari._client.models.explain_request import ExplainRequest from otari._client.models.explain_response import ExplainResponse from otari._client.models.policy_request import PolicyRequest @@ -1733,6 +1735,284 @@ def _routing_rank_candidates_serialize( + @validate_call + def routing_recommend_model_for_agent( + self, + agent_model_recommendation_request: AgentModelRecommendationRequest, + _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, + ) -> AgentModelRecommendation: + """Recommend Model For Agent + + Recommend the model a subagent about to start should run on. The harness sends the facts it holds at spawn time: its own ids for the session and the spawning tool call, the subagent type, the task, the parent's model and the model the caller asked for, if any. The gateway asks the decision model named by `agent_recommender_model` to pick one of the `agent_recommender_candidates`, and answers with that candidate, the model's probability for each candidate, and a one-line reason. Authentication modes: - Master key: the ``user`` field is required and names who the decision is billed to. - API key: the decision is billed to the key's own user. + + :param agent_model_recommendation_request: (required) + :type agent_model_recommendation_request: AgentModelRecommendationRequest + :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._routing_recommend_model_for_agent_serialize( + agent_model_recommendation_request=agent_model_recommendation_request, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "AgentModelRecommendation", + '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 routing_recommend_model_for_agent_with_http_info( + self, + agent_model_recommendation_request: AgentModelRecommendationRequest, + _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[AgentModelRecommendation]: + """Recommend Model For Agent + + Recommend the model a subagent about to start should run on. The harness sends the facts it holds at spawn time: its own ids for the session and the spawning tool call, the subagent type, the task, the parent's model and the model the caller asked for, if any. The gateway asks the decision model named by `agent_recommender_model` to pick one of the `agent_recommender_candidates`, and answers with that candidate, the model's probability for each candidate, and a one-line reason. Authentication modes: - Master key: the ``user`` field is required and names who the decision is billed to. - API key: the decision is billed to the key's own user. + + :param agent_model_recommendation_request: (required) + :type agent_model_recommendation_request: AgentModelRecommendationRequest + :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._routing_recommend_model_for_agent_serialize( + agent_model_recommendation_request=agent_model_recommendation_request, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "AgentModelRecommendation", + '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 routing_recommend_model_for_agent_without_preload_content( + self, + agent_model_recommendation_request: AgentModelRecommendationRequest, + _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: + """Recommend Model For Agent + + Recommend the model a subagent about to start should run on. The harness sends the facts it holds at spawn time: its own ids for the session and the spawning tool call, the subagent type, the task, the parent's model and the model the caller asked for, if any. The gateway asks the decision model named by `agent_recommender_model` to pick one of the `agent_recommender_candidates`, and answers with that candidate, the model's probability for each candidate, and a one-line reason. Authentication modes: - Master key: the ``user`` field is required and names who the decision is billed to. - API key: the decision is billed to the key's own user. + + :param agent_model_recommendation_request: (required) + :type agent_model_recommendation_request: AgentModelRecommendationRequest + :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._routing_recommend_model_for_agent_serialize( + agent_model_recommendation_request=agent_model_recommendation_request, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "AgentModelRecommendation", + '422': "HTTPValidationError", + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + return response_data.response + + + def _routing_recommend_model_for_agent_serialize( + self, + agent_model_recommendation_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 agent_model_recommendation_request is not None: + _body_params = agent_model_recommendation_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] = [ + 'XApiKeyAuth', + 'ApiKeyAuth' + ] + + return self.api_client.param_serialize( + method='POST', + resource_path='/api/v1/routing/recommend', + 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 routing_routing_memory_status( self, diff --git a/src/otari/_client/api/search_api.py b/src/otari/_client/api/search_api.py index b31f39f6..f21138f6 100644 --- a/src/otari/_client/api/search_api.py +++ b/src/otari/_client/api/search_api.py @@ -57,7 +57,7 @@ def search_create_search( ) -> SearchResponse: """Create Search - Run a search against a configured search tool. The tool is taken from ``search_tool_name``, which may be omitted when exactly one tool is configured. Authentication modes: - Master key: the ``user`` field is required and may name any existing user. - API key: usage and spend bind to the key's own user. A ``user`` field naming a different user is rejected with 403 (or ignored, when the key's own ``reject_user_mismatch`` is false, or the deployment-wide setting is disabled and the key does not override it); it is never billed to that user. - Service key: a ``user`` field names one of the key owner's end users, created on first use with the key's end-user budget, and is billed and rate limited as that end user, as on chat completions. + Run a search against a configured search tool. The tool is taken from ``search_tool_name``, which may be omitted when exactly one tool is configured. Authentication modes: - Master key: the ``user`` field is required and may name any existing user. - API key: usage and spend bind to the key's own user. A ``user`` field naming a different user is rejected with 403 (or ignored, when the key's own ``reject_user_mismatch`` is false, or the deployment-wide setting is disabled and the key does not override it); it is never billed to that user. - Service key: a ``user`` field names one of the key owner's end users, created on first use on the budget ``Otari-End-User-Budget`` names (or the key's default), and is billed and rate limited as that end user, as on chat completions. :param search_request: (required) :type search_request: SearchRequest @@ -125,7 +125,7 @@ def search_create_search_with_http_info( ) -> ApiResponse[SearchResponse]: """Create Search - Run a search against a configured search tool. The tool is taken from ``search_tool_name``, which may be omitted when exactly one tool is configured. Authentication modes: - Master key: the ``user`` field is required and may name any existing user. - API key: usage and spend bind to the key's own user. A ``user`` field naming a different user is rejected with 403 (or ignored, when the key's own ``reject_user_mismatch`` is false, or the deployment-wide setting is disabled and the key does not override it); it is never billed to that user. - Service key: a ``user`` field names one of the key owner's end users, created on first use with the key's end-user budget, and is billed and rate limited as that end user, as on chat completions. + Run a search against a configured search tool. The tool is taken from ``search_tool_name``, which may be omitted when exactly one tool is configured. Authentication modes: - Master key: the ``user`` field is required and may name any existing user. - API key: usage and spend bind to the key's own user. A ``user`` field naming a different user is rejected with 403 (or ignored, when the key's own ``reject_user_mismatch`` is false, or the deployment-wide setting is disabled and the key does not override it); it is never billed to that user. - Service key: a ``user`` field names one of the key owner's end users, created on first use on the budget ``Otari-End-User-Budget`` names (or the key's default), and is billed and rate limited as that end user, as on chat completions. :param search_request: (required) :type search_request: SearchRequest @@ -193,7 +193,7 @@ def search_create_search_without_preload_content( ) -> RESTResponseType: """Create Search - Run a search against a configured search tool. The tool is taken from ``search_tool_name``, which may be omitted when exactly one tool is configured. Authentication modes: - Master key: the ``user`` field is required and may name any existing user. - API key: usage and spend bind to the key's own user. A ``user`` field naming a different user is rejected with 403 (or ignored, when the key's own ``reject_user_mismatch`` is false, or the deployment-wide setting is disabled and the key does not override it); it is never billed to that user. - Service key: a ``user`` field names one of the key owner's end users, created on first use with the key's end-user budget, and is billed and rate limited as that end user, as on chat completions. + Run a search against a configured search tool. The tool is taken from ``search_tool_name``, which may be omitted when exactly one tool is configured. Authentication modes: - Master key: the ``user`` field is required and may name any existing user. - API key: usage and spend bind to the key's own user. A ``user`` field naming a different user is rejected with 403 (or ignored, when the key's own ``reject_user_mismatch`` is false, or the deployment-wide setting is disabled and the key does not override it); it is never billed to that user. - Service key: a ``user`` field names one of the key owner's end users, created on first use on the budget ``Otari-End-User-Budget`` names (or the key's default), and is billed and rate limited as that end user, as on chat completions. :param search_request: (required) :type search_request: SearchRequest @@ -336,7 +336,7 @@ def search_create_search_for_tool( ) -> SearchResponse: """Create Search For Tool - Run a search against the search tool named in the path. Identical to ``POST /api/v1/search`` except that the path names the tool, which is the form LiteLLM clients use. Any ``search_tool_name`` in the body is ignored. Authentication modes: - Master key: the ``user`` field is required and may name any existing user. - API key: usage and spend bind to the key's own user. A ``user`` field naming a different user is rejected with 403 (or ignored, when the key's own ``reject_user_mismatch`` is false, or the deployment-wide setting is disabled and the key does not override it); it is never billed to that user. - Service key: a ``user`` field names one of the key owner's end users, created on first use with the key's end-user budget, and is billed and rate limited as that end user, as on chat completions. + Run a search against the search tool named in the path. Identical to ``POST /api/v1/search`` except that the path names the tool, which is the form LiteLLM clients use. Any ``search_tool_name`` in the body is ignored. Authentication modes: - Master key: the ``user`` field is required and may name any existing user. - API key: usage and spend bind to the key's own user. A ``user`` field naming a different user is rejected with 403 (or ignored, when the key's own ``reject_user_mismatch`` is false, or the deployment-wide setting is disabled and the key does not override it); it is never billed to that user. - Service key: a ``user`` field names one of the key owner's end users, created on first use on the budget ``Otari-End-User-Budget`` names (or the key's default), and is billed and rate limited as that end user, as on chat completions. :param search_tool_name: Configured search tool to run against (required) :type search_tool_name: str @@ -408,7 +408,7 @@ def search_create_search_for_tool_with_http_info( ) -> ApiResponse[SearchResponse]: """Create Search For Tool - Run a search against the search tool named in the path. Identical to ``POST /api/v1/search`` except that the path names the tool, which is the form LiteLLM clients use. Any ``search_tool_name`` in the body is ignored. Authentication modes: - Master key: the ``user`` field is required and may name any existing user. - API key: usage and spend bind to the key's own user. A ``user`` field naming a different user is rejected with 403 (or ignored, when the key's own ``reject_user_mismatch`` is false, or the deployment-wide setting is disabled and the key does not override it); it is never billed to that user. - Service key: a ``user`` field names one of the key owner's end users, created on first use with the key's end-user budget, and is billed and rate limited as that end user, as on chat completions. + Run a search against the search tool named in the path. Identical to ``POST /api/v1/search`` except that the path names the tool, which is the form LiteLLM clients use. Any ``search_tool_name`` in the body is ignored. Authentication modes: - Master key: the ``user`` field is required and may name any existing user. - API key: usage and spend bind to the key's own user. A ``user`` field naming a different user is rejected with 403 (or ignored, when the key's own ``reject_user_mismatch`` is false, or the deployment-wide setting is disabled and the key does not override it); it is never billed to that user. - Service key: a ``user`` field names one of the key owner's end users, created on first use on the budget ``Otari-End-User-Budget`` names (or the key's default), and is billed and rate limited as that end user, as on chat completions. :param search_tool_name: Configured search tool to run against (required) :type search_tool_name: str @@ -480,7 +480,7 @@ def search_create_search_for_tool_without_preload_content( ) -> RESTResponseType: """Create Search For Tool - Run a search against the search tool named in the path. Identical to ``POST /api/v1/search`` except that the path names the tool, which is the form LiteLLM clients use. Any ``search_tool_name`` in the body is ignored. Authentication modes: - Master key: the ``user`` field is required and may name any existing user. - API key: usage and spend bind to the key's own user. A ``user`` field naming a different user is rejected with 403 (or ignored, when the key's own ``reject_user_mismatch`` is false, or the deployment-wide setting is disabled and the key does not override it); it is never billed to that user. - Service key: a ``user`` field names one of the key owner's end users, created on first use with the key's end-user budget, and is billed and rate limited as that end user, as on chat completions. + Run a search against the search tool named in the path. Identical to ``POST /api/v1/search`` except that the path names the tool, which is the form LiteLLM clients use. Any ``search_tool_name`` in the body is ignored. Authentication modes: - Master key: the ``user`` field is required and may name any existing user. - API key: usage and spend bind to the key's own user. A ``user`` field naming a different user is rejected with 403 (or ignored, when the key's own ``reject_user_mismatch`` is false, or the deployment-wide setting is disabled and the key does not override it); it is never billed to that user. - Service key: a ``user`` field names one of the key owner's end users, created on first use on the budget ``Otari-End-User-Budget`` names (or the key's default), and is billed and rate limited as that end user, as on chat completions. :param search_tool_name: Configured search tool to run against (required) :type search_tool_name: str diff --git a/src/otari/_client/api/usage_api.py b/src/otari/_client/api/usage_api.py index 853641b9..79458aec 100644 --- a/src/otari/_client/api/usage_api.py +++ b/src/otari/_client/api/usage_api.py @@ -64,6 +64,7 @@ def usage_count_usage( provider: Annotated[Optional[StrictStr], Field(description="Filter to a single provider (e.g. 'openai')")] = None, source: Annotated[Optional[StrictStr], Field(description="Filter to a single provenance source (e.g. 'gateway' or 'claude_code')")] = None, source_label: Annotated[Optional[StrictStr], Field(description="Filter to a single session/project label (the source_label carried by imported usage)")] = None, + tag: Annotated[Optional[Annotated[List[StrictStr], Field(max_length=50)]], Field(description="Filter by a request tag (what a request sent in its `metadata`), as `key:value`. Repeatable: values for the same key match any of them, and different keys must all match. At most 50 per call.")] = None, api_key_id: Annotated[Optional[Annotated[List[StrictStr], Field(max_length=50)]], Field(description="Filter to one or more API key ids; repeatable (api_key_id=a&api_key_id=b). Several values match any of them. At most 50 per call.")] = None, priced: Annotated[Optional[StrictBool], Field(description="Filter by token-pricing state: true = only rows whose model tokens were priced, false = only rows that still need pricing (no cost at all, or tokens that were never metered because the model had no rate). A row charged only for gateway-run tool calls still counts as needing pricing.")] = None, tool: Annotated[Optional[StrictStr], Field(description="Filter to requests that ran a gateway-run tool. 'any' matches any tool; a tool name (web_search, web_fetch, code_execution) matches that tool specifically.")] = None, @@ -107,6 +108,8 @@ def usage_count_usage( :type source: str :param source_label: Filter to a single session/project label (the source_label carried by imported usage) :type source_label: str + :param tag: Filter by a request tag (what a request sent in its `metadata`), as `key:value`. Repeatable: values for the same key match any of them, and different keys must all match. At most 50 per call. + :type tag: List[str] :param api_key_id: Filter to one or more API key ids; repeatable (api_key_id=a&api_key_id=b). Several values match any of them. At most 50 per call. :type api_key_id: List[str] :param priced: Filter by token-pricing state: true = only rows whose model tokens were priced, false = only rows that still need pricing (no cost at all, or tokens that were never metered because the model had no rate). A row charged only for gateway-run tool calls still counts as needing pricing. @@ -152,6 +155,7 @@ def usage_count_usage( provider=provider, source=source, source_label=source_label, + tag=tag, api_key_id=api_key_id, priced=priced, tool=tool, @@ -192,6 +196,7 @@ def usage_count_usage_with_http_info( provider: Annotated[Optional[StrictStr], Field(description="Filter to a single provider (e.g. 'openai')")] = None, source: Annotated[Optional[StrictStr], Field(description="Filter to a single provenance source (e.g. 'gateway' or 'claude_code')")] = None, source_label: Annotated[Optional[StrictStr], Field(description="Filter to a single session/project label (the source_label carried by imported usage)")] = None, + tag: Annotated[Optional[Annotated[List[StrictStr], Field(max_length=50)]], Field(description="Filter by a request tag (what a request sent in its `metadata`), as `key:value`. Repeatable: values for the same key match any of them, and different keys must all match. At most 50 per call.")] = None, api_key_id: Annotated[Optional[Annotated[List[StrictStr], Field(max_length=50)]], Field(description="Filter to one or more API key ids; repeatable (api_key_id=a&api_key_id=b). Several values match any of them. At most 50 per call.")] = None, priced: Annotated[Optional[StrictBool], Field(description="Filter by token-pricing state: true = only rows whose model tokens were priced, false = only rows that still need pricing (no cost at all, or tokens that were never metered because the model had no rate). A row charged only for gateway-run tool calls still counts as needing pricing.")] = None, tool: Annotated[Optional[StrictStr], Field(description="Filter to requests that ran a gateway-run tool. 'any' matches any tool; a tool name (web_search, web_fetch, code_execution) matches that tool specifically.")] = None, @@ -235,6 +240,8 @@ def usage_count_usage_with_http_info( :type source: str :param source_label: Filter to a single session/project label (the source_label carried by imported usage) :type source_label: str + :param tag: Filter by a request tag (what a request sent in its `metadata`), as `key:value`. Repeatable: values for the same key match any of them, and different keys must all match. At most 50 per call. + :type tag: List[str] :param api_key_id: Filter to one or more API key ids; repeatable (api_key_id=a&api_key_id=b). Several values match any of them. At most 50 per call. :type api_key_id: List[str] :param priced: Filter by token-pricing state: true = only rows whose model tokens were priced, false = only rows that still need pricing (no cost at all, or tokens that were never metered because the model had no rate). A row charged only for gateway-run tool calls still counts as needing pricing. @@ -280,6 +287,7 @@ def usage_count_usage_with_http_info( provider=provider, source=source, source_label=source_label, + tag=tag, api_key_id=api_key_id, priced=priced, tool=tool, @@ -320,6 +328,7 @@ def usage_count_usage_without_preload_content( provider: Annotated[Optional[StrictStr], Field(description="Filter to a single provider (e.g. 'openai')")] = None, source: Annotated[Optional[StrictStr], Field(description="Filter to a single provenance source (e.g. 'gateway' or 'claude_code')")] = None, source_label: Annotated[Optional[StrictStr], Field(description="Filter to a single session/project label (the source_label carried by imported usage)")] = None, + tag: Annotated[Optional[Annotated[List[StrictStr], Field(max_length=50)]], Field(description="Filter by a request tag (what a request sent in its `metadata`), as `key:value`. Repeatable: values for the same key match any of them, and different keys must all match. At most 50 per call.")] = None, api_key_id: Annotated[Optional[Annotated[List[StrictStr], Field(max_length=50)]], Field(description="Filter to one or more API key ids; repeatable (api_key_id=a&api_key_id=b). Several values match any of them. At most 50 per call.")] = None, priced: Annotated[Optional[StrictBool], Field(description="Filter by token-pricing state: true = only rows whose model tokens were priced, false = only rows that still need pricing (no cost at all, or tokens that were never metered because the model had no rate). A row charged only for gateway-run tool calls still counts as needing pricing.")] = None, tool: Annotated[Optional[StrictStr], Field(description="Filter to requests that ran a gateway-run tool. 'any' matches any tool; a tool name (web_search, web_fetch, code_execution) matches that tool specifically.")] = None, @@ -363,6 +372,8 @@ def usage_count_usage_without_preload_content( :type source: str :param source_label: Filter to a single session/project label (the source_label carried by imported usage) :type source_label: str + :param tag: Filter by a request tag (what a request sent in its `metadata`), as `key:value`. Repeatable: values for the same key match any of them, and different keys must all match. At most 50 per call. + :type tag: List[str] :param api_key_id: Filter to one or more API key ids; repeatable (api_key_id=a&api_key_id=b). Several values match any of them. At most 50 per call. :type api_key_id: List[str] :param priced: Filter by token-pricing state: true = only rows whose model tokens were priced, false = only rows that still need pricing (no cost at all, or tokens that were never metered because the model had no rate). A row charged only for gateway-run tool calls still counts as needing pricing. @@ -408,6 +419,7 @@ def usage_count_usage_without_preload_content( provider=provider, source=source, source_label=source_label, + tag=tag, api_key_id=api_key_id, priced=priced, tool=tool, @@ -443,6 +455,7 @@ def _usage_count_usage_serialize( provider, source, source_label, + tag, api_key_id, priced, tool, @@ -460,6 +473,7 @@ def _usage_count_usage_serialize( _collection_formats: Dict[str, str] = { 'user_id': 'multi', 'model': 'multi', + 'tag': 'multi', 'api_key_id': 'multi', 'request_group_id': 'multi', } @@ -533,6 +547,10 @@ def _usage_count_usage_serialize( _query_params.append(('source_label', source_label)) + if tag is not None: + + _query_params.append(('tag', tag)) + if api_key_id is not None: _query_params.append(('api_key_id', api_key_id)) @@ -1676,6 +1694,7 @@ def usage_list_usage( provider: Annotated[Optional[StrictStr], Field(description="Filter to a single provider (e.g. 'openai')")] = None, source: Annotated[Optional[StrictStr], Field(description="Filter to a single provenance source (e.g. 'gateway' or 'claude_code')")] = None, source_label: Annotated[Optional[StrictStr], Field(description="Filter to a single session/project label (the source_label carried by imported usage)")] = None, + tag: Annotated[Optional[Annotated[List[StrictStr], Field(max_length=50)]], Field(description="Filter by a request tag (what a request sent in its `metadata`), as `key:value`. Repeatable: values for the same key match any of them, and different keys must all match. At most 50 per call.")] = None, api_key_id: Annotated[Optional[Annotated[List[StrictStr], Field(max_length=50)]], Field(description="Filter to one or more API key ids; repeatable (api_key_id=a&api_key_id=b). Several values match any of them. At most 50 per call.")] = None, priced: Annotated[Optional[StrictBool], Field(description="Filter by token-pricing state: true = only rows whose model tokens were priced, false = only rows that still need pricing (no cost at all, or tokens that were never metered because the model had no rate). A row charged only for gateway-run tool calls still counts as needing pricing.")] = None, tool: Annotated[Optional[StrictStr], Field(description="Filter to requests that ran a gateway-run tool. 'any' matches any tool; a tool name (web_search, web_fetch, code_execution) matches that tool specifically.")] = None, @@ -1721,6 +1740,8 @@ def usage_list_usage( :type source: str :param source_label: Filter to a single session/project label (the source_label carried by imported usage) :type source_label: str + :param tag: Filter by a request tag (what a request sent in its `metadata`), as `key:value`. Repeatable: values for the same key match any of them, and different keys must all match. At most 50 per call. + :type tag: List[str] :param api_key_id: Filter to one or more API key ids; repeatable (api_key_id=a&api_key_id=b). Several values match any of them. At most 50 per call. :type api_key_id: List[str] :param priced: Filter by token-pricing state: true = only rows whose model tokens were priced, false = only rows that still need pricing (no cost at all, or tokens that were never metered because the model had no rate). A row charged only for gateway-run tool calls still counts as needing pricing. @@ -1770,6 +1791,7 @@ def usage_list_usage( provider=provider, source=source, source_label=source_label, + tag=tag, api_key_id=api_key_id, priced=priced, tool=tool, @@ -1812,6 +1834,7 @@ def usage_list_usage_with_http_info( provider: Annotated[Optional[StrictStr], Field(description="Filter to a single provider (e.g. 'openai')")] = None, source: Annotated[Optional[StrictStr], Field(description="Filter to a single provenance source (e.g. 'gateway' or 'claude_code')")] = None, source_label: Annotated[Optional[StrictStr], Field(description="Filter to a single session/project label (the source_label carried by imported usage)")] = None, + tag: Annotated[Optional[Annotated[List[StrictStr], Field(max_length=50)]], Field(description="Filter by a request tag (what a request sent in its `metadata`), as `key:value`. Repeatable: values for the same key match any of them, and different keys must all match. At most 50 per call.")] = None, api_key_id: Annotated[Optional[Annotated[List[StrictStr], Field(max_length=50)]], Field(description="Filter to one or more API key ids; repeatable (api_key_id=a&api_key_id=b). Several values match any of them. At most 50 per call.")] = None, priced: Annotated[Optional[StrictBool], Field(description="Filter by token-pricing state: true = only rows whose model tokens were priced, false = only rows that still need pricing (no cost at all, or tokens that were never metered because the model had no rate). A row charged only for gateway-run tool calls still counts as needing pricing.")] = None, tool: Annotated[Optional[StrictStr], Field(description="Filter to requests that ran a gateway-run tool. 'any' matches any tool; a tool name (web_search, web_fetch, code_execution) matches that tool specifically.")] = None, @@ -1857,6 +1880,8 @@ def usage_list_usage_with_http_info( :type source: str :param source_label: Filter to a single session/project label (the source_label carried by imported usage) :type source_label: str + :param tag: Filter by a request tag (what a request sent in its `metadata`), as `key:value`. Repeatable: values for the same key match any of them, and different keys must all match. At most 50 per call. + :type tag: List[str] :param api_key_id: Filter to one or more API key ids; repeatable (api_key_id=a&api_key_id=b). Several values match any of them. At most 50 per call. :type api_key_id: List[str] :param priced: Filter by token-pricing state: true = only rows whose model tokens were priced, false = only rows that still need pricing (no cost at all, or tokens that were never metered because the model had no rate). A row charged only for gateway-run tool calls still counts as needing pricing. @@ -1906,6 +1931,7 @@ def usage_list_usage_with_http_info( provider=provider, source=source, source_label=source_label, + tag=tag, api_key_id=api_key_id, priced=priced, tool=tool, @@ -1948,6 +1974,7 @@ def usage_list_usage_without_preload_content( provider: Annotated[Optional[StrictStr], Field(description="Filter to a single provider (e.g. 'openai')")] = None, source: Annotated[Optional[StrictStr], Field(description="Filter to a single provenance source (e.g. 'gateway' or 'claude_code')")] = None, source_label: Annotated[Optional[StrictStr], Field(description="Filter to a single session/project label (the source_label carried by imported usage)")] = None, + tag: Annotated[Optional[Annotated[List[StrictStr], Field(max_length=50)]], Field(description="Filter by a request tag (what a request sent in its `metadata`), as `key:value`. Repeatable: values for the same key match any of them, and different keys must all match. At most 50 per call.")] = None, api_key_id: Annotated[Optional[Annotated[List[StrictStr], Field(max_length=50)]], Field(description="Filter to one or more API key ids; repeatable (api_key_id=a&api_key_id=b). Several values match any of them. At most 50 per call.")] = None, priced: Annotated[Optional[StrictBool], Field(description="Filter by token-pricing state: true = only rows whose model tokens were priced, false = only rows that still need pricing (no cost at all, or tokens that were never metered because the model had no rate). A row charged only for gateway-run tool calls still counts as needing pricing.")] = None, tool: Annotated[Optional[StrictStr], Field(description="Filter to requests that ran a gateway-run tool. 'any' matches any tool; a tool name (web_search, web_fetch, code_execution) matches that tool specifically.")] = None, @@ -1993,6 +2020,8 @@ def usage_list_usage_without_preload_content( :type source: str :param source_label: Filter to a single session/project label (the source_label carried by imported usage) :type source_label: str + :param tag: Filter by a request tag (what a request sent in its `metadata`), as `key:value`. Repeatable: values for the same key match any of them, and different keys must all match. At most 50 per call. + :type tag: List[str] :param api_key_id: Filter to one or more API key ids; repeatable (api_key_id=a&api_key_id=b). Several values match any of them. At most 50 per call. :type api_key_id: List[str] :param priced: Filter by token-pricing state: true = only rows whose model tokens were priced, false = only rows that still need pricing (no cost at all, or tokens that were never metered because the model had no rate). A row charged only for gateway-run tool calls still counts as needing pricing. @@ -2042,6 +2071,7 @@ def usage_list_usage_without_preload_content( provider=provider, source=source, source_label=source_label, + tag=tag, api_key_id=api_key_id, priced=priced, tool=tool, @@ -2079,6 +2109,7 @@ def _usage_list_usage_serialize( provider, source, source_label, + tag, api_key_id, priced, tool, @@ -2098,6 +2129,7 @@ def _usage_list_usage_serialize( _collection_formats: Dict[str, str] = { 'user_id': 'multi', 'model': 'multi', + 'tag': 'multi', 'api_key_id': 'multi', 'request_group_id': 'multi', } @@ -2171,6 +2203,10 @@ def _usage_list_usage_serialize( _query_params.append(('source_label', source_label)) + if tag is not None: + + _query_params.append(('tag', tag)) + if api_key_id is not None: _query_params.append(('api_key_id', api_key_id)) @@ -2533,6 +2569,7 @@ def usage_usage_series( provider: Annotated[Optional[StrictStr], Field(description="Filter to a single provider (e.g. 'openai')")] = None, source: Annotated[Optional[StrictStr], Field(description="Filter to a single provenance source (e.g. 'gateway' or 'claude_code')")] = None, source_label: Annotated[Optional[StrictStr], Field(description="Filter to a single session/project label (the source_label carried by imported usage)")] = None, + tag: Annotated[Optional[Annotated[List[StrictStr], Field(max_length=50)]], Field(description="Filter by a request tag (what a request sent in its `metadata`), as `key:value`. Repeatable: values for the same key match any of them, and different keys must all match. At most 50 per call.")] = None, api_key_id: Annotated[Optional[Annotated[List[StrictStr], Field(max_length=50)]], Field(description="Filter to one or more API key ids; repeatable (api_key_id=a&api_key_id=b). Several values match any of them. At most 50 per call.")] = None, priced: Annotated[Optional[StrictBool], Field(description="Filter by token-pricing state: true = only rows whose model tokens were priced, false = only rows that still need pricing (no cost at all, or tokens that were never metered because the model had no rate). A row charged only for gateway-run tool calls still counts as needing pricing.")] = None, tool: Annotated[Optional[StrictStr], Field(description="Filter to requests that ran a gateway-run tool. 'any' matches any tool; a tool name (web_search, web_fetch, code_execution) matches that tool specifically.")] = None, @@ -2578,6 +2615,8 @@ def usage_usage_series( :type source: str :param source_label: Filter to a single session/project label (the source_label carried by imported usage) :type source_label: str + :param tag: Filter by a request tag (what a request sent in its `metadata`), as `key:value`. Repeatable: values for the same key match any of them, and different keys must all match. At most 50 per call. + :type tag: List[str] :param api_key_id: Filter to one or more API key ids; repeatable (api_key_id=a&api_key_id=b). Several values match any of them. At most 50 per call. :type api_key_id: List[str] :param priced: Filter by token-pricing state: true = only rows whose model tokens were priced, false = only rows that still need pricing (no cost at all, or tokens that were never metered because the model had no rate). A row charged only for gateway-run tool calls still counts as needing pricing. @@ -2624,6 +2663,7 @@ def usage_usage_series( provider=provider, source=source, source_label=source_label, + tag=tag, api_key_id=api_key_id, priced=priced, tool=tool, @@ -2665,6 +2705,7 @@ def usage_usage_series_with_http_info( provider: Annotated[Optional[StrictStr], Field(description="Filter to a single provider (e.g. 'openai')")] = None, source: Annotated[Optional[StrictStr], Field(description="Filter to a single provenance source (e.g. 'gateway' or 'claude_code')")] = None, source_label: Annotated[Optional[StrictStr], Field(description="Filter to a single session/project label (the source_label carried by imported usage)")] = None, + tag: Annotated[Optional[Annotated[List[StrictStr], Field(max_length=50)]], Field(description="Filter by a request tag (what a request sent in its `metadata`), as `key:value`. Repeatable: values for the same key match any of them, and different keys must all match. At most 50 per call.")] = None, api_key_id: Annotated[Optional[Annotated[List[StrictStr], Field(max_length=50)]], Field(description="Filter to one or more API key ids; repeatable (api_key_id=a&api_key_id=b). Several values match any of them. At most 50 per call.")] = None, priced: Annotated[Optional[StrictBool], Field(description="Filter by token-pricing state: true = only rows whose model tokens were priced, false = only rows that still need pricing (no cost at all, or tokens that were never metered because the model had no rate). A row charged only for gateway-run tool calls still counts as needing pricing.")] = None, tool: Annotated[Optional[StrictStr], Field(description="Filter to requests that ran a gateway-run tool. 'any' matches any tool; a tool name (web_search, web_fetch, code_execution) matches that tool specifically.")] = None, @@ -2710,6 +2751,8 @@ def usage_usage_series_with_http_info( :type source: str :param source_label: Filter to a single session/project label (the source_label carried by imported usage) :type source_label: str + :param tag: Filter by a request tag (what a request sent in its `metadata`), as `key:value`. Repeatable: values for the same key match any of them, and different keys must all match. At most 50 per call. + :type tag: List[str] :param api_key_id: Filter to one or more API key ids; repeatable (api_key_id=a&api_key_id=b). Several values match any of them. At most 50 per call. :type api_key_id: List[str] :param priced: Filter by token-pricing state: true = only rows whose model tokens were priced, false = only rows that still need pricing (no cost at all, or tokens that were never metered because the model had no rate). A row charged only for gateway-run tool calls still counts as needing pricing. @@ -2756,6 +2799,7 @@ def usage_usage_series_with_http_info( provider=provider, source=source, source_label=source_label, + tag=tag, api_key_id=api_key_id, priced=priced, tool=tool, @@ -2797,6 +2841,7 @@ def usage_usage_series_without_preload_content( provider: Annotated[Optional[StrictStr], Field(description="Filter to a single provider (e.g. 'openai')")] = None, source: Annotated[Optional[StrictStr], Field(description="Filter to a single provenance source (e.g. 'gateway' or 'claude_code')")] = None, source_label: Annotated[Optional[StrictStr], Field(description="Filter to a single session/project label (the source_label carried by imported usage)")] = None, + tag: Annotated[Optional[Annotated[List[StrictStr], Field(max_length=50)]], Field(description="Filter by a request tag (what a request sent in its `metadata`), as `key:value`. Repeatable: values for the same key match any of them, and different keys must all match. At most 50 per call.")] = None, api_key_id: Annotated[Optional[Annotated[List[StrictStr], Field(max_length=50)]], Field(description="Filter to one or more API key ids; repeatable (api_key_id=a&api_key_id=b). Several values match any of them. At most 50 per call.")] = None, priced: Annotated[Optional[StrictBool], Field(description="Filter by token-pricing state: true = only rows whose model tokens were priced, false = only rows that still need pricing (no cost at all, or tokens that were never metered because the model had no rate). A row charged only for gateway-run tool calls still counts as needing pricing.")] = None, tool: Annotated[Optional[StrictStr], Field(description="Filter to requests that ran a gateway-run tool. 'any' matches any tool; a tool name (web_search, web_fetch, code_execution) matches that tool specifically.")] = None, @@ -2842,6 +2887,8 @@ def usage_usage_series_without_preload_content( :type source: str :param source_label: Filter to a single session/project label (the source_label carried by imported usage) :type source_label: str + :param tag: Filter by a request tag (what a request sent in its `metadata`), as `key:value`. Repeatable: values for the same key match any of them, and different keys must all match. At most 50 per call. + :type tag: List[str] :param api_key_id: Filter to one or more API key ids; repeatable (api_key_id=a&api_key_id=b). Several values match any of them. At most 50 per call. :type api_key_id: List[str] :param priced: Filter by token-pricing state: true = only rows whose model tokens were priced, false = only rows that still need pricing (no cost at all, or tokens that were never metered because the model had no rate). A row charged only for gateway-run tool calls still counts as needing pricing. @@ -2888,6 +2935,7 @@ def usage_usage_series_without_preload_content( provider=provider, source=source, source_label=source_label, + tag=tag, api_key_id=api_key_id, priced=priced, tool=tool, @@ -2924,6 +2972,7 @@ def _usage_usage_series_serialize( provider, source, source_label, + tag, api_key_id, priced, tool, @@ -2941,6 +2990,7 @@ def _usage_usage_series_serialize( _collection_formats: Dict[str, str] = { 'user_id': 'multi', 'model': 'multi', + 'tag': 'multi', 'api_key_id': 'multi', } @@ -3017,6 +3067,10 @@ def _usage_usage_series_serialize( _query_params.append(('source_label', source_label)) + if tag is not None: + + _query_params.append(('tag', tag)) + if api_key_id is not None: _query_params.append(('api_key_id', api_key_id)) @@ -3092,6 +3146,7 @@ def usage_usage_summary( provider: Annotated[Optional[StrictStr], Field(description="Filter to a single provider (e.g. 'openai')")] = None, source: Annotated[Optional[StrictStr], Field(description="Filter to a single provenance source (e.g. 'gateway' or 'claude_code')")] = None, source_label: Annotated[Optional[StrictStr], Field(description="Filter to a single session/project label (the source_label carried by imported usage)")] = None, + tag: Annotated[Optional[Annotated[List[StrictStr], Field(max_length=50)]], Field(description="Filter by a request tag (what a request sent in its `metadata`), as `key:value`. Repeatable: values for the same key match any of them, and different keys must all match. At most 50 per call.")] = None, api_key_id: Annotated[Optional[Annotated[List[StrictStr], Field(max_length=50)]], Field(description="Filter to one or more API key ids; repeatable (api_key_id=a&api_key_id=b). Several values match any of them. At most 50 per call.")] = None, priced: Annotated[Optional[StrictBool], Field(description="Filter by token-pricing state: true = only rows whose model tokens were priced, false = only rows that still need pricing (no cost at all, or tokens that were never metered because the model had no rate). A row charged only for gateway-run tool calls still counts as needing pricing.")] = None, tool: Annotated[Optional[StrictStr], Field(description="Filter to requests that ran a gateway-run tool. 'any' matches any tool; a tool name (web_search, web_fetch, code_execution) matches that tool specifically.")] = None, @@ -3099,6 +3154,7 @@ def usage_usage_summary( workspace_id: Annotated[Optional[UUID], Field(description="Only usage recorded in this workspace.")] = None, bucket: Annotated[Optional[StrictStr], Field(description="Time-series granularity: 'hour' or 'day'")] = None, dimensions: Annotated[Optional[List[StrictStr]], Field(description="Which breakdowns to compute; repeatable (dimensions=model&dimensions=user). Each value names the 'by_' response field it fills, except 'status_code', which fills the failure taxonomy in 'errors_by_status_code'. Omit for every breakdown (the default); pass 'none' for a totals-and-series-only response. Each dimension left out skips one GROUP BY scan, so a caller that reads only the tiles or the time series should say so. Fields that were not requested come back empty.")] = None, + group_by_tag: Annotated[Optional[Annotated[str, Field(min_length=1, strict=True, max_length=64)]], Field(description="A tag key to break spend down by, returned as `by_tag`. Rows that do not carry the tag group under a null key.")] = None, _request_timeout: Union[ None, Annotated[StrictFloat, Field(gt=0)], @@ -3136,6 +3192,8 @@ def usage_usage_summary( :type source: str :param source_label: Filter to a single session/project label (the source_label carried by imported usage) :type source_label: str + :param tag: Filter by a request tag (what a request sent in its `metadata`), as `key:value`. Repeatable: values for the same key match any of them, and different keys must all match. At most 50 per call. + :type tag: List[str] :param api_key_id: Filter to one or more API key ids; repeatable (api_key_id=a&api_key_id=b). Several values match any of them. At most 50 per call. :type api_key_id: List[str] :param priced: Filter by token-pricing state: true = only rows whose model tokens were priced, false = only rows that still need pricing (no cost at all, or tokens that were never metered because the model had no rate). A row charged only for gateway-run tool calls still counts as needing pricing. @@ -3150,6 +3208,8 @@ def usage_usage_summary( :type bucket: str :param dimensions: Which breakdowns to compute; repeatable (dimensions=model&dimensions=user). Each value names the 'by_' response field it fills, except 'status_code', which fills the failure taxonomy in 'errors_by_status_code'. Omit for every breakdown (the default); pass 'none' for a totals-and-series-only response. Each dimension left out skips one GROUP BY scan, so a caller that reads only the tiles or the time series should say so. Fields that were not requested come back empty. :type dimensions: List[str] + :param group_by_tag: A tag key to break spend down by, returned as `by_tag`. Rows that do not carry the tag group under a null key. + :type group_by_tag: str :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 @@ -3183,6 +3243,7 @@ def usage_usage_summary( provider=provider, source=source, source_label=source_label, + tag=tag, api_key_id=api_key_id, priced=priced, tool=tool, @@ -3190,6 +3251,7 @@ def usage_usage_summary( workspace_id=workspace_id, bucket=bucket, dimensions=dimensions, + group_by_tag=group_by_tag, _request_auth=_request_auth, _content_type=_content_type, _headers=_headers, @@ -3224,6 +3286,7 @@ def usage_usage_summary_with_http_info( provider: Annotated[Optional[StrictStr], Field(description="Filter to a single provider (e.g. 'openai')")] = None, source: Annotated[Optional[StrictStr], Field(description="Filter to a single provenance source (e.g. 'gateway' or 'claude_code')")] = None, source_label: Annotated[Optional[StrictStr], Field(description="Filter to a single session/project label (the source_label carried by imported usage)")] = None, + tag: Annotated[Optional[Annotated[List[StrictStr], Field(max_length=50)]], Field(description="Filter by a request tag (what a request sent in its `metadata`), as `key:value`. Repeatable: values for the same key match any of them, and different keys must all match. At most 50 per call.")] = None, api_key_id: Annotated[Optional[Annotated[List[StrictStr], Field(max_length=50)]], Field(description="Filter to one or more API key ids; repeatable (api_key_id=a&api_key_id=b). Several values match any of them. At most 50 per call.")] = None, priced: Annotated[Optional[StrictBool], Field(description="Filter by token-pricing state: true = only rows whose model tokens were priced, false = only rows that still need pricing (no cost at all, or tokens that were never metered because the model had no rate). A row charged only for gateway-run tool calls still counts as needing pricing.")] = None, tool: Annotated[Optional[StrictStr], Field(description="Filter to requests that ran a gateway-run tool. 'any' matches any tool; a tool name (web_search, web_fetch, code_execution) matches that tool specifically.")] = None, @@ -3231,6 +3294,7 @@ def usage_usage_summary_with_http_info( workspace_id: Annotated[Optional[UUID], Field(description="Only usage recorded in this workspace.")] = None, bucket: Annotated[Optional[StrictStr], Field(description="Time-series granularity: 'hour' or 'day'")] = None, dimensions: Annotated[Optional[List[StrictStr]], Field(description="Which breakdowns to compute; repeatable (dimensions=model&dimensions=user). Each value names the 'by_' response field it fills, except 'status_code', which fills the failure taxonomy in 'errors_by_status_code'. Omit for every breakdown (the default); pass 'none' for a totals-and-series-only response. Each dimension left out skips one GROUP BY scan, so a caller that reads only the tiles or the time series should say so. Fields that were not requested come back empty.")] = None, + group_by_tag: Annotated[Optional[Annotated[str, Field(min_length=1, strict=True, max_length=64)]], Field(description="A tag key to break spend down by, returned as `by_tag`. Rows that do not carry the tag group under a null key.")] = None, _request_timeout: Union[ None, Annotated[StrictFloat, Field(gt=0)], @@ -3268,6 +3332,8 @@ def usage_usage_summary_with_http_info( :type source: str :param source_label: Filter to a single session/project label (the source_label carried by imported usage) :type source_label: str + :param tag: Filter by a request tag (what a request sent in its `metadata`), as `key:value`. Repeatable: values for the same key match any of them, and different keys must all match. At most 50 per call. + :type tag: List[str] :param api_key_id: Filter to one or more API key ids; repeatable (api_key_id=a&api_key_id=b). Several values match any of them. At most 50 per call. :type api_key_id: List[str] :param priced: Filter by token-pricing state: true = only rows whose model tokens were priced, false = only rows that still need pricing (no cost at all, or tokens that were never metered because the model had no rate). A row charged only for gateway-run tool calls still counts as needing pricing. @@ -3282,6 +3348,8 @@ def usage_usage_summary_with_http_info( :type bucket: str :param dimensions: Which breakdowns to compute; repeatable (dimensions=model&dimensions=user). Each value names the 'by_' response field it fills, except 'status_code', which fills the failure taxonomy in 'errors_by_status_code'. Omit for every breakdown (the default); pass 'none' for a totals-and-series-only response. Each dimension left out skips one GROUP BY scan, so a caller that reads only the tiles or the time series should say so. Fields that were not requested come back empty. :type dimensions: List[str] + :param group_by_tag: A tag key to break spend down by, returned as `by_tag`. Rows that do not carry the tag group under a null key. + :type group_by_tag: str :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 @@ -3315,6 +3383,7 @@ def usage_usage_summary_with_http_info( provider=provider, source=source, source_label=source_label, + tag=tag, api_key_id=api_key_id, priced=priced, tool=tool, @@ -3322,6 +3391,7 @@ def usage_usage_summary_with_http_info( workspace_id=workspace_id, bucket=bucket, dimensions=dimensions, + group_by_tag=group_by_tag, _request_auth=_request_auth, _content_type=_content_type, _headers=_headers, @@ -3356,6 +3426,7 @@ def usage_usage_summary_without_preload_content( provider: Annotated[Optional[StrictStr], Field(description="Filter to a single provider (e.g. 'openai')")] = None, source: Annotated[Optional[StrictStr], Field(description="Filter to a single provenance source (e.g. 'gateway' or 'claude_code')")] = None, source_label: Annotated[Optional[StrictStr], Field(description="Filter to a single session/project label (the source_label carried by imported usage)")] = None, + tag: Annotated[Optional[Annotated[List[StrictStr], Field(max_length=50)]], Field(description="Filter by a request tag (what a request sent in its `metadata`), as `key:value`. Repeatable: values for the same key match any of them, and different keys must all match. At most 50 per call.")] = None, api_key_id: Annotated[Optional[Annotated[List[StrictStr], Field(max_length=50)]], Field(description="Filter to one or more API key ids; repeatable (api_key_id=a&api_key_id=b). Several values match any of them. At most 50 per call.")] = None, priced: Annotated[Optional[StrictBool], Field(description="Filter by token-pricing state: true = only rows whose model tokens were priced, false = only rows that still need pricing (no cost at all, or tokens that were never metered because the model had no rate). A row charged only for gateway-run tool calls still counts as needing pricing.")] = None, tool: Annotated[Optional[StrictStr], Field(description="Filter to requests that ran a gateway-run tool. 'any' matches any tool; a tool name (web_search, web_fetch, code_execution) matches that tool specifically.")] = None, @@ -3363,6 +3434,7 @@ def usage_usage_summary_without_preload_content( workspace_id: Annotated[Optional[UUID], Field(description="Only usage recorded in this workspace.")] = None, bucket: Annotated[Optional[StrictStr], Field(description="Time-series granularity: 'hour' or 'day'")] = None, dimensions: Annotated[Optional[List[StrictStr]], Field(description="Which breakdowns to compute; repeatable (dimensions=model&dimensions=user). Each value names the 'by_' response field it fills, except 'status_code', which fills the failure taxonomy in 'errors_by_status_code'. Omit for every breakdown (the default); pass 'none' for a totals-and-series-only response. Each dimension left out skips one GROUP BY scan, so a caller that reads only the tiles or the time series should say so. Fields that were not requested come back empty.")] = None, + group_by_tag: Annotated[Optional[Annotated[str, Field(min_length=1, strict=True, max_length=64)]], Field(description="A tag key to break spend down by, returned as `by_tag`. Rows that do not carry the tag group under a null key.")] = None, _request_timeout: Union[ None, Annotated[StrictFloat, Field(gt=0)], @@ -3400,6 +3472,8 @@ def usage_usage_summary_without_preload_content( :type source: str :param source_label: Filter to a single session/project label (the source_label carried by imported usage) :type source_label: str + :param tag: Filter by a request tag (what a request sent in its `metadata`), as `key:value`. Repeatable: values for the same key match any of them, and different keys must all match. At most 50 per call. + :type tag: List[str] :param api_key_id: Filter to one or more API key ids; repeatable (api_key_id=a&api_key_id=b). Several values match any of them. At most 50 per call. :type api_key_id: List[str] :param priced: Filter by token-pricing state: true = only rows whose model tokens were priced, false = only rows that still need pricing (no cost at all, or tokens that were never metered because the model had no rate). A row charged only for gateway-run tool calls still counts as needing pricing. @@ -3414,6 +3488,8 @@ def usage_usage_summary_without_preload_content( :type bucket: str :param dimensions: Which breakdowns to compute; repeatable (dimensions=model&dimensions=user). Each value names the 'by_' response field it fills, except 'status_code', which fills the failure taxonomy in 'errors_by_status_code'. Omit for every breakdown (the default); pass 'none' for a totals-and-series-only response. Each dimension left out skips one GROUP BY scan, so a caller that reads only the tiles or the time series should say so. Fields that were not requested come back empty. :type dimensions: List[str] + :param group_by_tag: A tag key to break spend down by, returned as `by_tag`. Rows that do not carry the tag group under a null key. + :type group_by_tag: str :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 @@ -3447,6 +3523,7 @@ def usage_usage_summary_without_preload_content( provider=provider, source=source, source_label=source_label, + tag=tag, api_key_id=api_key_id, priced=priced, tool=tool, @@ -3454,6 +3531,7 @@ def usage_usage_summary_without_preload_content( workspace_id=workspace_id, bucket=bucket, dimensions=dimensions, + group_by_tag=group_by_tag, _request_auth=_request_auth, _content_type=_content_type, _headers=_headers, @@ -3483,6 +3561,7 @@ def _usage_usage_summary_serialize( provider, source, source_label, + tag, api_key_id, priced, tool, @@ -3490,6 +3569,7 @@ def _usage_usage_summary_serialize( workspace_id, bucket, dimensions, + group_by_tag, _request_auth, _content_type, _headers, @@ -3501,6 +3581,7 @@ def _usage_usage_summary_serialize( _collection_formats: Dict[str, str] = { 'user_id': 'multi', 'model': 'multi', + 'tag': 'multi', 'api_key_id': 'multi', 'dimensions': 'multi', } @@ -3574,6 +3655,10 @@ def _usage_usage_summary_serialize( _query_params.append(('source_label', source_label)) + if tag is not None: + + _query_params.append(('tag', tag)) + if api_key_id is not None: _query_params.append(('api_key_id', api_key_id)) @@ -3602,6 +3687,10 @@ def _usage_usage_summary_serialize( _query_params.append(('dimensions', dimensions)) + if group_by_tag is not None: + + _query_params.append(('group_by_tag', group_by_tag)) + # process the header parameters # process the form parameters # process the body parameter diff --git a/src/otari/_client/api/web_search_keys_api.py b/src/otari/_client/api/web_search_keys_api.py new file mode 100644 index 00000000..a348514f --- /dev/null +++ b/src/otari/_client/api/web_search_keys_api.py @@ -0,0 +1,2863 @@ +""" + 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, StrictBool +from typing import Optional +from typing_extensions import Annotated +from uuid import UUID +from otari._client.models.org_web_search_key_create_request import OrgWebSearchKeyCreateRequest +from otari._client.models.org_web_search_key_public import OrgWebSearchKeyPublic +from otari._client.models.org_web_search_key_update_request import OrgWebSearchKeyUpdateRequest +from otari._client.models.org_web_search_keys_public import OrgWebSearchKeysPublic +from otari._client.models.workspace_web_search_key_override_request import WorkspaceWebSearchKeyOverrideRequest +from otari._client.models.workspace_web_search_keys_public import WorkspaceWebSearchKeysPublic + +from otari._client.api_client import ApiClient, RequestSerialized +from otari._client.api_response import ApiResponse +from otari._client.rest import RESTResponseType + + +class WebSearchKeysApi: + """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 web_search_keys_archive_org_web_search_key( + self, + key_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, + ) -> OrgWebSearchKeyPublic: + """Archive Org Web Search Key + + Take a web search key out of use. Organization owners and admins only. + + :param key_id: (required) + :type key_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._web_search_keys_archive_org_web_search_key_serialize( + key_id=key_id, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "OrgWebSearchKeyPublic", + '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 web_search_keys_archive_org_web_search_key_with_http_info( + self, + key_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[OrgWebSearchKeyPublic]: + """Archive Org Web Search Key + + Take a web search key out of use. Organization owners and admins only. + + :param key_id: (required) + :type key_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._web_search_keys_archive_org_web_search_key_serialize( + key_id=key_id, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "OrgWebSearchKeyPublic", + '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 web_search_keys_archive_org_web_search_key_without_preload_content( + self, + key_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: + """Archive Org Web Search Key + + Take a web search key out of use. Organization owners and admins only. + + :param key_id: (required) + :type key_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._web_search_keys_archive_org_web_search_key_serialize( + key_id=key_id, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "OrgWebSearchKeyPublic", + '422': "HTTPValidationError", + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + return response_data.response + + + def _web_search_keys_archive_org_web_search_key_serialize( + self, + key_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 key_id is not None: + _path_params['key_id'] = key_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='POST', + resource_path='/api/v1/organizations/me/web-search-keys/{key_id}/archive', + 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 web_search_keys_create_org_web_search_key( + self, + org_web_search_key_create_request: OrgWebSearchKeyCreateRequest, + _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, + ) -> OrgWebSearchKeyPublic: + """Create Org Web Search Key + + Add a web search key to the caller's organization. Organization owners and admins only. A workspace with a usable key searches with it rather than with the deployment's search. + + :param org_web_search_key_create_request: (required) + :type org_web_search_key_create_request: OrgWebSearchKeyCreateRequest + :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._web_search_keys_create_org_web_search_key_serialize( + org_web_search_key_create_request=org_web_search_key_create_request, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '201': "OrgWebSearchKeyPublic", + '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 web_search_keys_create_org_web_search_key_with_http_info( + self, + org_web_search_key_create_request: OrgWebSearchKeyCreateRequest, + _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[OrgWebSearchKeyPublic]: + """Create Org Web Search Key + + Add a web search key to the caller's organization. Organization owners and admins only. A workspace with a usable key searches with it rather than with the deployment's search. + + :param org_web_search_key_create_request: (required) + :type org_web_search_key_create_request: OrgWebSearchKeyCreateRequest + :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._web_search_keys_create_org_web_search_key_serialize( + org_web_search_key_create_request=org_web_search_key_create_request, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '201': "OrgWebSearchKeyPublic", + '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 web_search_keys_create_org_web_search_key_without_preload_content( + self, + org_web_search_key_create_request: OrgWebSearchKeyCreateRequest, + _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 Org Web Search Key + + Add a web search key to the caller's organization. Organization owners and admins only. A workspace with a usable key searches with it rather than with the deployment's search. + + :param org_web_search_key_create_request: (required) + :type org_web_search_key_create_request: OrgWebSearchKeyCreateRequest + :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._web_search_keys_create_org_web_search_key_serialize( + org_web_search_key_create_request=org_web_search_key_create_request, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '201': "OrgWebSearchKeyPublic", + '422': "HTTPValidationError", + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + return response_data.response + + + def _web_search_keys_create_org_web_search_key_serialize( + self, + org_web_search_key_create_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 org_web_search_key_create_request is not None: + _body_params = org_web_search_key_create_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] = [ + 'XApiKeyAuth', + 'ApiKeyAuth' + ] + + return self.api_client.param_serialize( + method='POST', + resource_path='/api/v1/organizations/me/web-search-keys', + 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 web_search_keys_delete_org_web_search_key( + self, + key_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, + ) -> None: + """Delete Org Web Search Key + + Delete an archived web search key. Organization owners and admins only. + + :param key_id: (required) + :type key_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._web_search_keys_delete_org_web_search_key_serialize( + key_id=key_id, + _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 web_search_keys_delete_org_web_search_key_with_http_info( + self, + key_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[None]: + """Delete Org Web Search Key + + Delete an archived web search key. Organization owners and admins only. + + :param key_id: (required) + :type key_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._web_search_keys_delete_org_web_search_key_serialize( + key_id=key_id, + _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 web_search_keys_delete_org_web_search_key_without_preload_content( + self, + key_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 Org Web Search Key + + Delete an archived web search key. Organization owners and admins only. + + :param key_id: (required) + :type key_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._web_search_keys_delete_org_web_search_key_serialize( + key_id=key_id, + _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 _web_search_keys_delete_org_web_search_key_serialize( + self, + key_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 key_id is not None: + _path_params['key_id'] = key_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='/api/v1/organizations/me/web-search-keys/{key_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 web_search_keys_list_org_web_search_keys( + self, + include_archived: Annotated[Optional[StrictBool], Field(description="Include archived keys.")] = None, + 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, + ) -> OrgWebSearchKeysPublic: + """List Org Web Search Keys + + List the caller's organization's web search keys. Organization owners and admins only. + + :param include_archived: Include archived keys. + :type include_archived: bool + :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._web_search_keys_list_org_web_search_keys_serialize( + include_archived=include_archived, + 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': "OrgWebSearchKeysPublic", + '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 web_search_keys_list_org_web_search_keys_with_http_info( + self, + include_archived: Annotated[Optional[StrictBool], Field(description="Include archived keys.")] = None, + 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[OrgWebSearchKeysPublic]: + """List Org Web Search Keys + + List the caller's organization's web search keys. Organization owners and admins only. + + :param include_archived: Include archived keys. + :type include_archived: bool + :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._web_search_keys_list_org_web_search_keys_serialize( + include_archived=include_archived, + 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': "OrgWebSearchKeysPublic", + '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 web_search_keys_list_org_web_search_keys_without_preload_content( + self, + include_archived: Annotated[Optional[StrictBool], Field(description="Include archived keys.")] = None, + 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 Org Web Search Keys + + List the caller's organization's web search keys. Organization owners and admins only. + + :param include_archived: Include archived keys. + :type include_archived: bool + :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._web_search_keys_list_org_web_search_keys_serialize( + include_archived=include_archived, + 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': "OrgWebSearchKeysPublic", + '422': "HTTPValidationError", + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + return response_data.response + + + def _web_search_keys_list_org_web_search_keys_serialize( + self, + include_archived, + 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 + # process the query parameters + if include_archived is not None: + + _query_params.append(('include_archived', include_archived)) + + 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='/api/v1/organizations/me/web-search-keys', + 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 web_search_keys_list_workspace_web_search_keys( + 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, + ) -> WorkspaceWebSearchKeysPublic: + """List Workspace Web Search Keys + + The organization's web search keys as this workspace sees them, and which one it searches with. Any member of the workspace may read it. ``is_effective`` is decided across every key, not only this page. + + :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._web_search_keys_list_workspace_web_search_keys_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': "WorkspaceWebSearchKeysPublic", + '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 web_search_keys_list_workspace_web_search_keys_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[WorkspaceWebSearchKeysPublic]: + """List Workspace Web Search Keys + + The organization's web search keys as this workspace sees them, and which one it searches with. Any member of the workspace may read it. ``is_effective`` is decided across every key, not only this page. + + :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._web_search_keys_list_workspace_web_search_keys_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': "WorkspaceWebSearchKeysPublic", + '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 web_search_keys_list_workspace_web_search_keys_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 Web Search Keys + + The organization's web search keys as this workspace sees them, and which one it searches with. Any member of the workspace may read it. ``is_effective`` is decided across every key, not only this page. + + :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._web_search_keys_list_workspace_web_search_keys_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': "WorkspaceWebSearchKeysPublic", + '422': "HTTPValidationError", + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + return response_data.response + + + def _web_search_keys_list_workspace_web_search_keys_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='/api/v1/workspaces/{workspace_id}/web-search-keys', + 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 web_search_keys_reset_workspace_web_search_key_override( + self, + workspace_id: UUID, + key_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, + ) -> WorkspaceWebSearchKeysPublic: + """Reset Workspace Web Search Key Override + + Return this workspace to inheriting the key. Idempotent. Answers with the list's first page. + + :param workspace_id: (required) + :type workspace_id: UUID + :param key_id: (required) + :type key_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._web_search_keys_reset_workspace_web_search_key_override_serialize( + workspace_id=workspace_id, + key_id=key_id, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "WorkspaceWebSearchKeysPublic", + '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 web_search_keys_reset_workspace_web_search_key_override_with_http_info( + self, + workspace_id: UUID, + key_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[WorkspaceWebSearchKeysPublic]: + """Reset Workspace Web Search Key Override + + Return this workspace to inheriting the key. Idempotent. Answers with the list's first page. + + :param workspace_id: (required) + :type workspace_id: UUID + :param key_id: (required) + :type key_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._web_search_keys_reset_workspace_web_search_key_override_serialize( + workspace_id=workspace_id, + key_id=key_id, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "WorkspaceWebSearchKeysPublic", + '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 web_search_keys_reset_workspace_web_search_key_override_without_preload_content( + self, + workspace_id: UUID, + key_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: + """Reset Workspace Web Search Key Override + + Return this workspace to inheriting the key. Idempotent. Answers with the list's first page. + + :param workspace_id: (required) + :type workspace_id: UUID + :param key_id: (required) + :type key_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._web_search_keys_reset_workspace_web_search_key_override_serialize( + workspace_id=workspace_id, + key_id=key_id, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "WorkspaceWebSearchKeysPublic", + '422': "HTTPValidationError", + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + return response_data.response + + + def _web_search_keys_reset_workspace_web_search_key_override_serialize( + self, + workspace_id, + key_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 key_id is not None: + _path_params['key_id'] = key_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='/api/v1/workspaces/{workspace_id}/web-search-keys/{key_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 web_search_keys_restore_org_web_search_key( + self, + key_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, + ) -> OrgWebSearchKeyPublic: + """Restore Org Web Search Key + + Put an archived web search key back in use. Organization owners and admins only. + + :param key_id: (required) + :type key_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._web_search_keys_restore_org_web_search_key_serialize( + key_id=key_id, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "OrgWebSearchKeyPublic", + '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 web_search_keys_restore_org_web_search_key_with_http_info( + self, + key_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[OrgWebSearchKeyPublic]: + """Restore Org Web Search Key + + Put an archived web search key back in use. Organization owners and admins only. + + :param key_id: (required) + :type key_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._web_search_keys_restore_org_web_search_key_serialize( + key_id=key_id, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "OrgWebSearchKeyPublic", + '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 web_search_keys_restore_org_web_search_key_without_preload_content( + self, + key_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: + """Restore Org Web Search Key + + Put an archived web search key back in use. Organization owners and admins only. + + :param key_id: (required) + :type key_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._web_search_keys_restore_org_web_search_key_serialize( + key_id=key_id, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "OrgWebSearchKeyPublic", + '422': "HTTPValidationError", + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + return response_data.response + + + def _web_search_keys_restore_org_web_search_key_serialize( + self, + key_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 key_id is not None: + _path_params['key_id'] = key_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='POST', + resource_path='/api/v1/organizations/me/web-search-keys/{key_id}/restore', + 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 web_search_keys_set_org_default_web_search_key( + self, + key_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, + ) -> OrgWebSearchKeyPublic: + """Set Org Default Web Search Key + + Make a web search key its provider's organization default. Organization owners and admins only. + + :param key_id: (required) + :type key_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._web_search_keys_set_org_default_web_search_key_serialize( + key_id=key_id, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "OrgWebSearchKeyPublic", + '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 web_search_keys_set_org_default_web_search_key_with_http_info( + self, + key_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[OrgWebSearchKeyPublic]: + """Set Org Default Web Search Key + + Make a web search key its provider's organization default. Organization owners and admins only. + + :param key_id: (required) + :type key_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._web_search_keys_set_org_default_web_search_key_serialize( + key_id=key_id, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "OrgWebSearchKeyPublic", + '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 web_search_keys_set_org_default_web_search_key_without_preload_content( + self, + key_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: + """Set Org Default Web Search Key + + Make a web search key its provider's organization default. Organization owners and admins only. + + :param key_id: (required) + :type key_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._web_search_keys_set_org_default_web_search_key_serialize( + key_id=key_id, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "OrgWebSearchKeyPublic", + '422': "HTTPValidationError", + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + return response_data.response + + + def _web_search_keys_set_org_default_web_search_key_serialize( + self, + key_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 key_id is not None: + _path_params['key_id'] = key_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='POST', + resource_path='/api/v1/organizations/me/web-search-keys/{key_id}/default', + 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 web_search_keys_set_workspace_web_search_key_override( + self, + workspace_id: UUID, + key_id: UUID, + workspace_web_search_key_override_request: WorkspaceWebSearchKeyOverrideRequest, + _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, + ) -> WorkspaceWebSearchKeysPublic: + """Set Workspace Web Search Key Override + + Pin a web search key as this workspace's own, or turn it off for this workspace. Organization owners and admins, or this workspace's owners and admins. Answers with the list's first page. + + :param workspace_id: (required) + :type workspace_id: UUID + :param key_id: (required) + :type key_id: UUID + :param workspace_web_search_key_override_request: (required) + :type workspace_web_search_key_override_request: WorkspaceWebSearchKeyOverrideRequest + :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._web_search_keys_set_workspace_web_search_key_override_serialize( + workspace_id=workspace_id, + key_id=key_id, + workspace_web_search_key_override_request=workspace_web_search_key_override_request, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "WorkspaceWebSearchKeysPublic", + '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 web_search_keys_set_workspace_web_search_key_override_with_http_info( + self, + workspace_id: UUID, + key_id: UUID, + workspace_web_search_key_override_request: WorkspaceWebSearchKeyOverrideRequest, + _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[WorkspaceWebSearchKeysPublic]: + """Set Workspace Web Search Key Override + + Pin a web search key as this workspace's own, or turn it off for this workspace. Organization owners and admins, or this workspace's owners and admins. Answers with the list's first page. + + :param workspace_id: (required) + :type workspace_id: UUID + :param key_id: (required) + :type key_id: UUID + :param workspace_web_search_key_override_request: (required) + :type workspace_web_search_key_override_request: WorkspaceWebSearchKeyOverrideRequest + :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._web_search_keys_set_workspace_web_search_key_override_serialize( + workspace_id=workspace_id, + key_id=key_id, + workspace_web_search_key_override_request=workspace_web_search_key_override_request, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "WorkspaceWebSearchKeysPublic", + '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 web_search_keys_set_workspace_web_search_key_override_without_preload_content( + self, + workspace_id: UUID, + key_id: UUID, + workspace_web_search_key_override_request: WorkspaceWebSearchKeyOverrideRequest, + _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 Web Search Key Override + + Pin a web search key as this workspace's own, or turn it off for this workspace. Organization owners and admins, or this workspace's owners and admins. Answers with the list's first page. + + :param workspace_id: (required) + :type workspace_id: UUID + :param key_id: (required) + :type key_id: UUID + :param workspace_web_search_key_override_request: (required) + :type workspace_web_search_key_override_request: WorkspaceWebSearchKeyOverrideRequest + :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._web_search_keys_set_workspace_web_search_key_override_serialize( + workspace_id=workspace_id, + key_id=key_id, + workspace_web_search_key_override_request=workspace_web_search_key_override_request, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "WorkspaceWebSearchKeysPublic", + '422': "HTTPValidationError", + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + return response_data.response + + + def _web_search_keys_set_workspace_web_search_key_override_serialize( + self, + workspace_id, + key_id, + workspace_web_search_key_override_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 + if workspace_id is not None: + _path_params['workspace_id'] = workspace_id + if key_id is not None: + _path_params['key_id'] = key_id + # process the query parameters + # process the header parameters + # process the form parameters + # process the body parameter + if workspace_web_search_key_override_request is not None: + _body_params = workspace_web_search_key_override_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] = [ + 'XApiKeyAuth', + 'ApiKeyAuth' + ] + + return self.api_client.param_serialize( + method='PATCH', + resource_path='/api/v1/workspaces/{workspace_id}/web-search-keys/{key_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 web_search_keys_update_org_web_search_key( + self, + key_id: UUID, + org_web_search_key_update_request: OrgWebSearchKeyUpdateRequest, + _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, + ) -> OrgWebSearchKeyPublic: + """Update Org Web Search Key + + Rename a web search key or replace its secret. Organization owners and admins only. + + :param key_id: (required) + :type key_id: UUID + :param org_web_search_key_update_request: (required) + :type org_web_search_key_update_request: OrgWebSearchKeyUpdateRequest + :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._web_search_keys_update_org_web_search_key_serialize( + key_id=key_id, + org_web_search_key_update_request=org_web_search_key_update_request, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "OrgWebSearchKeyPublic", + '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 web_search_keys_update_org_web_search_key_with_http_info( + self, + key_id: UUID, + org_web_search_key_update_request: OrgWebSearchKeyUpdateRequest, + _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[OrgWebSearchKeyPublic]: + """Update Org Web Search Key + + Rename a web search key or replace its secret. Organization owners and admins only. + + :param key_id: (required) + :type key_id: UUID + :param org_web_search_key_update_request: (required) + :type org_web_search_key_update_request: OrgWebSearchKeyUpdateRequest + :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._web_search_keys_update_org_web_search_key_serialize( + key_id=key_id, + org_web_search_key_update_request=org_web_search_key_update_request, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "OrgWebSearchKeyPublic", + '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 web_search_keys_update_org_web_search_key_without_preload_content( + self, + key_id: UUID, + org_web_search_key_update_request: OrgWebSearchKeyUpdateRequest, + _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 Org Web Search Key + + Rename a web search key or replace its secret. Organization owners and admins only. + + :param key_id: (required) + :type key_id: UUID + :param org_web_search_key_update_request: (required) + :type org_web_search_key_update_request: OrgWebSearchKeyUpdateRequest + :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._web_search_keys_update_org_web_search_key_serialize( + key_id=key_id, + org_web_search_key_update_request=org_web_search_key_update_request, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "OrgWebSearchKeyPublic", + '422': "HTTPValidationError", + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + return response_data.response + + + def _web_search_keys_update_org_web_search_key_serialize( + self, + key_id, + org_web_search_key_update_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 + if key_id is not None: + _path_params['key_id'] = key_id + # process the query parameters + # process the header parameters + # process the form parameters + # process the body parameter + if org_web_search_key_update_request is not None: + _body_params = org_web_search_key_update_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] = [ + 'XApiKeyAuth', + 'ApiKeyAuth' + ] + + return self.api_client.param_serialize( + method='PATCH', + resource_path='/api/v1/organizations/me/web-search-keys/{key_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/models/__init__.py b/src/otari/_client/models/__init__.py index 5c3ae758..0743ed4f 100644 --- a/src/otari/_client/models/__init__.py +++ b/src/otari/_client/models/__init__.py @@ -24,6 +24,8 @@ from otari._client.models.active_organization_member_update_request import ActiveOrganizationMemberUpdateRequest from otari._client.models.active_organization_members_public import ActiveOrganizationMembersPublic from otari._client.models.active_organization_update_request import ActiveOrganizationUpdateRequest +from otari._client.models.agent_model_recommendation import AgentModelRecommendation +from otari._client.models.agent_model_recommendation_request import AgentModelRecommendationRequest from otari._client.models.agent_telemetry_behavior import AgentTelemetryBehavior from otari._client.models.agent_telemetry_count import AgentTelemetryCount from otari._client.models.agent_telemetry_delete_request import AgentTelemetryDeleteRequest @@ -191,6 +193,9 @@ from otari._client.models.emb_usage import EMBUsage from otari._client.models.embedded_resource import EmbeddedResource from otari._client.models.embedding_request import EmbeddingRequest +from otari._client.models.end_user_public import EndUserPublic +from otari._client.models.end_user_put import EndUserPut +from otari._client.models.end_user_update import EndUserUpdate from otari._client.models.execution_state import ExecutionState from otari._client.models.explain_request import ExplainRequest from otari._client.models.explain_response import ExplainResponse @@ -416,6 +421,10 @@ from otari._client.models.org_provider_key_update_request import OrgProviderKeyUpdateRequest from otari._client.models.org_provider_keys_public import OrgProviderKeysPublic from otari._client.models.org_provider_models_refresh_public import OrgProviderModelsRefreshPublic +from otari._client.models.org_web_search_key_create_request import OrgWebSearchKeyCreateRequest +from otari._client.models.org_web_search_key_public import OrgWebSearchKeyPublic +from otari._client.models.org_web_search_key_update_request import OrgWebSearchKeyUpdateRequest +from otari._client.models.org_web_search_keys_public import OrgWebSearchKeysPublic from otari._client.models.organization_budget_create import OrganizationBudgetCreate from otari._client.models.organization_budget_public import OrganizationBudgetPublic from otari._client.models.organization_budget_update import OrganizationBudgetUpdate @@ -524,6 +533,7 @@ 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 +from otari._client.models.sandbox_provider import SandboxProvider from otari._client.models.scoped_budget_response import ScopedBudgetResponse from otari._client.models.score_question import ScoreQuestion from otari._client.models.scored_example import ScoredExample @@ -631,6 +641,9 @@ from otari._client.models.workspace_update import WorkspaceUpdate from otari._client.models.workspace_web_search_config_public import WorkspaceWebSearchConfigPublic from otari._client.models.workspace_web_search_config_update import WorkspaceWebSearchConfigUpdate +from otari._client.models.workspace_web_search_key_override_request import WorkspaceWebSearchKeyOverrideRequest +from otari._client.models.workspace_web_search_key_public import WorkspaceWebSearchKeyPublic +from otari._client.models.workspace_web_search_keys_public import WorkspaceWebSearchKeysPublic from otari._client.models.workspaces_public import WorkspacesPublic from otari._client.models.worst_allocation_response import WorstAllocationResponse diff --git a/src/otari/_client/models/agent_model_recommendation.py b/src/otari/_client/models/agent_model_recommendation.py new file mode 100644 index 00000000..63777166 --- /dev/null +++ b/src/otari/_client/models/agent_model_recommendation.py @@ -0,0 +1,102 @@ +# 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, StrictFloat, StrictInt, StrictStr +from typing import Any, ClassVar, Dict, List, Optional, Union +from typing import Optional, Set +from typing_extensions import Self +from pydantic_core import to_jsonable_python + +class AgentModelRecommendation(BaseModel): + """ + The model recommended for the subagent. + """ # noqa: E501 + model: StrictStr = Field(description="A model alias or id the harness can start the subagent on.") + probabilities: Optional[Dict[str, Union[StrictFloat, StrictInt]]] = Field(default=None, description="The decision model's probability for each candidate, when it reports them.") + reason: Optional[StrictStr] = Field(default=None, description="Why, in one short sentence the harness may show.") + __properties: ClassVar[List[str]] = ["model", "probabilities", "reason"] + + 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 AgentModelRecommendation 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 probabilities (nullable) is None + # and model_fields_set contains the field + if self.probabilities is None and "probabilities" in self.model_fields_set: + _dict['probabilities'] = None + + # set to None if reason (nullable) is None + # and model_fields_set contains the field + if self.reason is None and "reason" in self.model_fields_set: + _dict['reason'] = None + + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of AgentModelRecommendation from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "model": obj.get("model"), + "probabilities": obj.get("probabilities"), + "reason": obj.get("reason") + }) + return _obj + + diff --git a/src/otari/_client/models/agent_model_recommendation_request.py b/src/otari/_client/models/agent_model_recommendation_request.py new file mode 100644 index 00000000..8b124728 --- /dev/null +++ b/src/otari/_client/models/agent_model_recommendation_request.py @@ -0,0 +1,115 @@ +# 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, Optional +from typing_extensions import Annotated +from typing import Optional, Set +from typing_extensions import Self +from pydantic_core import to_jsonable_python + +class AgentModelRecommendationRequest(BaseModel): + """ + A coding agent about to start a subagent, asking which model it should run on. Every field but ``user`` is a fact the harness already holds at spawn time. The prompt is the task the subagent is given; it is read for the recommendation and never stored or logged. + """ # noqa: E501 + agent_type: Annotated[str, Field(min_length=1, strict=True, max_length=128)] = Field(description="The subagent type: a built-in such as `Explore` or `Plan`, or a custom agent's name.") + description: Optional[Annotated[str, Field(strict=True, max_length=1024)]] = Field(default='', description="The caller's short description of the task.") + harness: Annotated[str, Field(min_length=1, strict=True, max_length=64)] = Field(description="The agent harness asking, such as `claude-code`.") + parent_model: Annotated[str, Field(min_length=1, strict=True, max_length=256)] = Field(description="The model the parent conversation runs on, as the harness names it.") + prompt: Annotated[str, Field(min_length=1, strict=True, max_length=65536)] = Field(description="The task the subagent is given.") + requested_model: Optional[Annotated[str, Field(strict=True, max_length=256)]] = Field(default=None, description="The model the caller asked for, if any. Sent as a fact; the recommendation is the gateway's.") + session_id: Annotated[str, Field(min_length=1, strict=True, max_length=256)] = Field(description="The harness's own id for the session the spawn happens in.") + tool_use_id: Annotated[str, Field(min_length=1, strict=True, max_length=256)] = Field(description="The harness's own id for the tool call that spawns the subagent.") + user: Optional[StrictStr] = Field(default=None, description="User ID the decision is billed to when asking with the master key; not sent upstream.") + __properties: ClassVar[List[str]] = ["agent_type", "description", "harness", "parent_model", "prompt", "requested_model", "session_id", "tool_use_id", "user"] + + 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 AgentModelRecommendationRequest 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 requested_model (nullable) is None + # and model_fields_set contains the field + if self.requested_model is None and "requested_model" in self.model_fields_set: + _dict['requested_model'] = None + + # set to None if user (nullable) is None + # and model_fields_set contains the field + if self.user is None and "user" in self.model_fields_set: + _dict['user'] = None + + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of AgentModelRecommendationRequest from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "agent_type": obj.get("agent_type"), + "description": obj.get("description") if obj.get("description") is not None else '', + "harness": obj.get("harness"), + "parent_model": obj.get("parent_model"), + "prompt": obj.get("prompt"), + "requested_model": obj.get("requested_model"), + "session_id": obj.get("session_id"), + "tool_use_id": obj.get("tool_use_id"), + "user": obj.get("user") + }) + return _obj + + diff --git a/src/otari/_client/models/billing_meters.py b/src/otari/_client/models/billing_meters.py index 116ee732..859ce05b 100644 --- a/src/otari/_client/models/billing_meters.py +++ b/src/otari/_client/models/billing_meters.py @@ -33,7 +33,7 @@ class BillingMeters(BaseModel): # data type: BillingMeters anyof_schema_1_validator: Optional[BillingMeters] = None # data type: Dict[str, object] - anyof_schema_2_validator: Optional[Dict[str, Any]] = Field(default=None, description="Provider-native request fields used as defaults (e.g. exa's 'type', searxng's 'engines').") + anyof_schema_2_validator: Optional[Dict[str, Any]] = Field(default=None, description="Tags for cost attribution, recorded on the request's usage rows and filterable in the usage API: up to 16 string pairs, keys up to 64 characters and values up to 512. A null value is ignored. LiteLLM's nested `spend_logs_metadata` object is also read, and wins over a flat key of the same name; it is never forwarded to the provider.") if TYPE_CHECKING: actual_instance: Optional[Union[BillingMeters, Dict[str, object]]] = None else: diff --git a/src/otari/_client/models/budget_response.py b/src/otari/_client/models/budget_response.py index 0c56363c..5185e6d9 100644 --- a/src/otari/_client/models/budget_response.py +++ b/src/otari/_client/models/budget_response.py @@ -36,12 +36,14 @@ class BudgetResponse(BaseModel): organization_id: Optional[UUID] request_limit: Optional[StrictInt] reset_alignment: Optional[StrictStr] + rpm_limit: Optional[StrictInt] = None token_limit: Optional[StrictInt] total_reserved: Optional[Union[StrictFloat, StrictInt]] = 0.0 total_spend: Optional[Union[StrictFloat, StrictInt]] = 0.0 + tpm_limit: Optional[StrictInt] = None updated_at: StrictStr user_count: Optional[StrictInt] = 0 - __properties: ClassVar[List[str]] = ["budget_duration_sec", "budget_id", "created_at", "max_budget", "name", "organization_id", "request_limit", "reset_alignment", "token_limit", "total_reserved", "total_spend", "updated_at", "user_count"] + __properties: ClassVar[List[str]] = ["budget_duration_sec", "budget_id", "created_at", "max_budget", "name", "organization_id", "request_limit", "reset_alignment", "rpm_limit", "token_limit", "total_reserved", "total_spend", "tpm_limit", "updated_at", "user_count"] model_config = ConfigDict( validate_by_name=True, @@ -112,11 +114,21 @@ def to_dict(self) -> Dict[str, Any]: if self.reset_alignment is None and "reset_alignment" in self.model_fields_set: _dict['reset_alignment'] = None + # set to None if rpm_limit (nullable) is None + # and model_fields_set contains the field + if self.rpm_limit is None and "rpm_limit" in self.model_fields_set: + _dict['rpm_limit'] = None + # set to None if token_limit (nullable) is None # and model_fields_set contains the field if self.token_limit is None and "token_limit" in self.model_fields_set: _dict['token_limit'] = None + # set to None if tpm_limit (nullable) is None + # and model_fields_set contains the field + if self.tpm_limit is None and "tpm_limit" in self.model_fields_set: + _dict['tpm_limit'] = None + return _dict @classmethod @@ -137,9 +149,11 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: "organization_id": obj.get("organization_id"), "request_limit": obj.get("request_limit"), "reset_alignment": obj.get("reset_alignment"), + "rpm_limit": obj.get("rpm_limit"), "token_limit": obj.get("token_limit"), "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, + "tpm_limit": obj.get("tpm_limit"), "updated_at": obj.get("updated_at"), "user_count": obj.get("user_count") if obj.get("user_count") is not None else 0 }) diff --git a/src/otari/_client/models/call_tool_result.py b/src/otari/_client/models/call_tool_result.py index bcf9ba8c..9a72e80e 100644 --- a/src/otari/_client/models/call_tool_result.py +++ b/src/otari/_client/models/call_tool_result.py @@ -31,7 +31,7 @@ class CallToolResult(BaseModel): meta: Optional[Dict[str, Any]] = Field(default=None, alias="_meta") content: List[ContentInner] is_error: Optional[StrictBool] = Field(default=False, alias="isError") - structured_content: Optional[Dict[str, Any]] = Field(default=None, description="Provider-native request fields used as defaults (e.g. exa's 'type', searxng's 'engines').", alias="structuredContent") + structured_content: Optional[Dict[str, Any]] = Field(default=None, description="Tags for cost attribution, recorded on the request's usage rows and filterable in the usage API: up to 16 string pairs, keys up to 64 characters and values up to 512. A null value is ignored. LiteLLM's nested `spend_logs_metadata` object is also read, and wins over a flat key of the same name; it is never forwarded to the provider.", alias="structuredContent") additional_properties: Dict[str, Any] = {} __properties: ClassVar[List[str]] = ["_meta", "content", "isError", "structuredContent"] diff --git a/src/otari/_client/models/cc_chat_completion_message.py b/src/otari/_client/models/cc_chat_completion_message.py index b24ec504..bba38ce4 100644 --- a/src/otari/_client/models/cc_chat_completion_message.py +++ b/src/otari/_client/models/cc_chat_completion_message.py @@ -39,7 +39,7 @@ class CCChatCompletionMessage(BaseModel): function_call: Optional[CCFunctionCall] = None tool_calls: Optional[List[CCChatCompletionMessageToolCallsInner]] = None reasoning: Optional[StrictStr] = Field(default=None, description="Filter to a single event type or metric name (e.g. 'tool_result', 'claude_code.commit.count')") - extra_content: Optional[Dict[str, Any]] = Field(default=None, description="Provider-native request fields used as defaults (e.g. exa's 'type', searxng's 'engines').") + extra_content: Optional[Dict[str, Any]] = Field(default=None, description="Tags for cost attribution, recorded on the request's usage rows and filterable in the usage API: up to 16 string pairs, keys up to 64 characters and values up to 512. A null value is ignored. LiteLLM's nested `spend_logs_metadata` object is also read, and wins over a flat key of the same name; it is never forwarded to the provider.") images: Optional[List[CCImageContent]] = None additional_properties: Dict[str, Any] = {} __properties: ClassVar[List[str]] = ["content", "refusal", "role", "annotations", "audio", "function_call", "tool_calls", "reasoning", "extra_content", "images"] diff --git a/src/otari/_client/models/chat_completion_request.py b/src/otari/_client/models/chat_completion_request.py index 6bd00236..9e177060 100644 --- a/src/otari/_client/models/chat_completion_request.py +++ b/src/otari/_client/models/chat_completion_request.py @@ -45,19 +45,20 @@ class ChatCompletionRequest(BaseModel): 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)] + metadata: Optional[Dict[str, Any]] = Field(default=None, description="Tags for cost attribution, recorded on the request's usage rows and filterable in the usage API: up to 16 string pairs, keys up to 64 characters and values up to 512. A null value is ignored. LiteLLM's nested `spend_logs_metadata` object is also read, and wins over a flat key of the same name; it is never forwarded to the provider.") model: StrictStr n: Optional[StrictInt] = None parallel_tool_calls: Optional[StrictBool] = None presence_penalty: Optional[Union[StrictFloat, StrictInt]] = None prompt_cache_key: Optional[StrictStr] = None reasoning_effort: Optional[StrictStr] = None - response_format: Optional[Dict[str, Any]] = Field(default=None, description="Provider-native request fields used as defaults (e.g. exa's 'type', searxng's 'engines').") + response_format: Optional[Dict[str, Any]] = Field(default=None, description="Tags for cost attribution, recorded on the request's usage rows and filterable in the usage API: up to 16 string pairs, keys up to 64 characters and values up to 512. A null value is ignored. LiteLLM's nested `spend_logs_metadata` object is also read, and wins over a flat key of the same name; it is never forwarded to the provider.") seed: Optional[StrictInt] = None service_tier: Optional[StrictStr] = None session_label: Optional[Annotated[str, Field(strict=True, max_length=255)]] = Field(default=None, description="Optional caller-supplied label for cost attribution (per run, experiment, or conversation). In hybrid mode it is forwarded onto the platform usage report so spend can be sliced by session without standing up OpenTelemetry. Stripped before the request is forwarded upstream to the provider. Has no effect in standalone mode, where there is no platform to report it to.") stop: Optional[Stop] = None stream: Optional[StrictBool] = False - stream_options: Optional[Dict[str, Any]] = Field(default=None, description="Provider-native request fields used as defaults (e.g. exa's 'type', searxng's 'engines').") + stream_options: Optional[Dict[str, Any]] = Field(default=None, description="Tags for cost attribution, recorded on the request's usage rows and filterable in the usage API: up to 16 string pairs, keys up to 64 characters and values up to 512. A null value is ignored. LiteLLM's nested `spend_logs_metadata` object is also read, and wins over a flat key of the same name; it is never forwarded to the provider.") temperature: Optional[Union[StrictFloat, StrictInt]] = None tool_choice: Optional[ToolChoice] = None tools: Optional[List[ChatCompletionRequestToolsInner]] = None @@ -65,7 +66,7 @@ class ChatCompletionRequest(BaseModel): top_logprobs: Optional[StrictInt] = None top_p: Optional[Union[StrictFloat, StrictInt]] = None user: Optional[StrictStr] = None - __properties: ClassVar[List[str]] = ["frequency_penalty", "guardrails", "logit_bias", "logprobs", "max_completion_tokens", "max_tokens", "max_tool_iterations", "mcp_server_ids", "mcp_servers", "messages", "model", "n", "parallel_tool_calls", "presence_penalty", "prompt_cache_key", "reasoning_effort", "response_format", "seed", "service_tier", "session_label", "stop", "stream", "stream_options", "temperature", "tool_choice", "tools", "tools_header", "top_logprobs", "top_p", "user"] + __properties: ClassVar[List[str]] = ["frequency_penalty", "guardrails", "logit_bias", "logprobs", "max_completion_tokens", "max_tokens", "max_tool_iterations", "mcp_server_ids", "mcp_servers", "messages", "metadata", "model", "n", "parallel_tool_calls", "presence_penalty", "prompt_cache_key", "reasoning_effort", "response_format", "seed", "service_tier", "session_label", "stop", "stream", "stream_options", "temperature", "tool_choice", "tools", "tools_header", "top_logprobs", "top_p", "user"] @field_validator('reasoning_effort') def reasoning_effort_validate_enum(cls, value): @@ -195,6 +196,11 @@ def to_dict(self) -> Dict[str, Any]: if self.mcp_servers is None and "mcp_servers" in self.model_fields_set: _dict['mcp_servers'] = None + # set to None if metadata (nullable) is None + # and model_fields_set contains the field + if self.metadata is None and "metadata" in self.model_fields_set: + _dict['metadata'] = None + # set to None if n (nullable) is None # and model_fields_set contains the field if self.n is None and "n" in self.model_fields_set: @@ -307,6 +313,7 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: "mcp_server_ids": obj.get("mcp_server_ids"), "mcp_servers": [McpServerConfig.from_dict(_item) for _item in obj["mcp_servers"]] if obj.get("mcp_servers") is not None else None, "messages": [ChatMessageInput.from_dict(_item) for _item in obj["messages"]] if obj.get("messages") is not None else None, + "metadata": obj.get("metadata"), "model": obj.get("model"), "n": obj.get("n"), "parallel_tool_calls": obj.get("parallel_tool_calls"), diff --git a/src/otari/_client/models/chat_completion_request_tools_inner.py b/src/otari/_client/models/chat_completion_request_tools_inner.py index 3068f35c..f9a0d83f 100644 --- a/src/otari/_client/models/chat_completion_request_tools_inner.py +++ b/src/otari/_client/models/chat_completion_request_tools_inner.py @@ -31,7 +31,7 @@ class ChatCompletionRequestToolsInner(BaseModel): """ # data type: Dict[str, object] - anyof_schema_1_validator: Optional[Dict[str, Any]] = Field(default=None, description="Provider-native request fields used as defaults (e.g. exa's 'type', searxng's 'engines').") + anyof_schema_1_validator: Optional[Dict[str, Any]] = Field(default=None, description="Tags for cost attribution, recorded on the request's usage rows and filterable in the usage API: up to 16 string pairs, keys up to 64 characters and values up to 512. A null value is ignored. LiteLLM's nested `spend_logs_metadata` object is also read, and wins over a flat key of the same name; it is never forwarded to the provider.") # data type: Dict[str, object] anyof_schema_2_validator: Optional[Dict[str, Any]] = None if TYPE_CHECKING: diff --git a/src/otari/_client/models/container.py b/src/otari/_client/models/container.py index 9964d9ac..2a920f73 100644 --- a/src/otari/_client/models/container.py +++ b/src/otari/_client/models/container.py @@ -33,7 +33,7 @@ class Container(BaseModel): # data type: str anyof_schema_1_validator: Optional[StrictStr] = Field(default=None, description="Filter to a single event type or metric name (e.g. 'tool_result', 'claude_code.commit.count')") # data type: Dict[str, object] - anyof_schema_2_validator: Optional[Dict[str, Any]] = Field(default=None, description="Provider-native request fields used as defaults (e.g. exa's 'type', searxng's 'engines').") + anyof_schema_2_validator: Optional[Dict[str, Any]] = Field(default=None, description="Tags for cost attribution, recorded on the request's usage rows and filterable in the usage API: up to 16 string pairs, keys up to 64 characters and values up to 512. A null value is ignored. LiteLLM's nested `spend_logs_metadata` object is also read, and wins over a flat key of the same name; it is never forwarded to the provider.") if TYPE_CHECKING: actual_instance: Optional[Union[Dict[str, object], str]] = None else: diff --git a/src/otari/_client/models/conversation.py b/src/otari/_client/models/conversation.py index b4ce930f..44436aa4 100644 --- a/src/otari/_client/models/conversation.py +++ b/src/otari/_client/models/conversation.py @@ -33,7 +33,7 @@ class Conversation(BaseModel): # data type: str anyof_schema_1_validator: Optional[StrictStr] = Field(default=None, description="Filter to a single event type or metric name (e.g. 'tool_result', 'claude_code.commit.count')") # data type: Dict[str, object] - anyof_schema_2_validator: Optional[Dict[str, Any]] = Field(default=None, description="Provider-native request fields used as defaults (e.g. exa's 'type', searxng's 'engines').") + anyof_schema_2_validator: Optional[Dict[str, Any]] = Field(default=None, description="Tags for cost attribution, recorded on the request's usage rows and filterable in the usage API: up to 16 string pairs, keys up to 64 characters and values up to 512. A null value is ignored. LiteLLM's nested `spend_logs_metadata` object is also read, and wins over a flat key of the same name; it is never forwarded to the provider.") if TYPE_CHECKING: actual_instance: Optional[Union[Dict[str, object], str]] = None else: diff --git a/src/otari/_client/models/count_tokens_request.py b/src/otari/_client/models/count_tokens_request.py index 978a5976..a6daf58a 100644 --- a/src/otari/_client/models/count_tokens_request.py +++ b/src/otari/_client/models/count_tokens_request.py @@ -30,14 +30,14 @@ class CountTokensRequest(BaseModel): Anthropic ``/v1/messages/count_tokens`` request. A subset of :class:`MessagesRequest`: the input fields that affect the token count, minus ``max_tokens`` and the streaming/sampling controls, since the endpoint only counts input tokens. ``context_management`` and ``betas`` are accepted for wire compatibility, but the local estimate does not apply provider-side context edits. Clients such as Claude Code call this on every turn to keep their prompt within the model's context window. """ # noqa: E501 betas: Optional[List[StrictStr]] = None - cache_control: Optional[Dict[str, Any]] = Field(default=None, description="Provider-native request fields used as defaults (e.g. exa's 'type', searxng's 'engines').") - context_management: Optional[Dict[str, Any]] = Field(default=None, description="Provider-native request fields used as defaults (e.g. exa's 'type', searxng's 'engines').") + cache_control: Optional[Dict[str, Any]] = Field(default=None, description="Tags for cost attribution, recorded on the request's usage rows and filterable in the usage API: up to 16 string pairs, keys up to 64 characters and values up to 512. A null value is ignored. LiteLLM's nested `spend_logs_metadata` object is also read, and wins over a flat key of the same name; it is never forwarded to the provider.") + context_management: Optional[Dict[str, Any]] = Field(default=None, description="Tags for cost attribution, recorded on the request's usage rows and filterable in the usage API: up to 16 string pairs, keys up to 64 characters and values up to 512. A null value is ignored. LiteLLM's nested `spend_logs_metadata` object is also read, and wins over a flat key of the same name; it is never forwarded to the provider.") messages: Annotated[List[Optional[Dict[str, Any]]], Field(min_length=1)] - metadata: Optional[Dict[str, Any]] = Field(default=None, description="Provider-native request fields used as defaults (e.g. exa's 'type', searxng's 'engines').") + metadata: Optional[Dict[str, Any]] = Field(default=None, description="Tags for cost attribution, recorded on the request's usage rows and filterable in the usage API: up to 16 string pairs, keys up to 64 characters and values up to 512. A null value is ignored. LiteLLM's nested `spend_logs_metadata` object is also read, and wins over a flat key of the same name; it is never forwarded to the provider.") model: StrictStr system: Optional[System] = None - thinking: Optional[Dict[str, Any]] = Field(default=None, description="Provider-native request fields used as defaults (e.g. exa's 'type', searxng's 'engines').") - tool_choice: Optional[Dict[str, Any]] = Field(default=None, description="Provider-native request fields used as defaults (e.g. exa's 'type', searxng's 'engines').") + thinking: Optional[Dict[str, Any]] = Field(default=None, description="Tags for cost attribution, recorded on the request's usage rows and filterable in the usage API: up to 16 string pairs, keys up to 64 characters and values up to 512. A null value is ignored. LiteLLM's nested `spend_logs_metadata` object is also read, and wins over a flat key of the same name; it is never forwarded to the provider.") + tool_choice: Optional[Dict[str, Any]] = Field(default=None, description="Tags for cost attribution, recorded on the request's usage rows and filterable in the usage API: up to 16 string pairs, keys up to 64 characters and values up to 512. A null value is ignored. LiteLLM's nested `spend_logs_metadata` object is also read, and wins over a flat key of the same name; it is never forwarded to the provider.") tools: Optional[List[Dict[str, Any]]] = None __properties: ClassVar[List[str]] = ["betas", "cache_control", "context_management", "messages", "metadata", "model", "system", "thinking", "tool_choice", "tools"] diff --git a/src/otari/_client/models/create_budget_request.py b/src/otari/_client/models/create_budget_request.py index 0884a933..19b3abeb 100644 --- a/src/otari/_client/models/create_budget_request.py +++ b/src/otari/_client/models/create_budget_request.py @@ -33,8 +33,10 @@ class CreateBudgetRequest(BaseModel): name: Optional[StrictStr] = Field(default=None, description="Admin-facing label for the budget") request_limit: Optional[Annotated[int, Field(le=1000000000000000, strict=True, ge=0)]] = Field(default=None, description="Maximum requests over the period. Independent of max_budget; null is unlimited") 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") + rpm_limit: Optional[Annotated[int, Field(le=2147483647, strict=True, ge=1)]] = Field(default=None, description="Requests per minute for each user on this budget, across replicas; null is unlimited") token_limit: Optional[Annotated[int, Field(le=1000000000000000, strict=True, ge=0)]] = Field(default=None, description="Maximum tokens over the period. Independent of max_budget; null is unlimited") - __properties: ClassVar[List[str]] = ["budget_duration_sec", "max_budget", "name", "request_limit", "reset_alignment", "token_limit"] + tpm_limit: Optional[Annotated[int, Field(le=2147483647, strict=True, ge=1)]] = Field(default=None, description="Tokens per minute for each user on this budget, counted on what requests used: a request is admitted while the user's minute is under the limit. Null is unlimited") + __properties: ClassVar[List[str]] = ["budget_duration_sec", "max_budget", "name", "request_limit", "reset_alignment", "rpm_limit", "token_limit", "tpm_limit"] @field_validator('reset_alignment') def reset_alignment_validate_enum(cls, value): @@ -110,11 +112,21 @@ def to_dict(self) -> Dict[str, Any]: if self.reset_alignment is None and "reset_alignment" in self.model_fields_set: _dict['reset_alignment'] = None + # set to None if rpm_limit (nullable) is None + # and model_fields_set contains the field + if self.rpm_limit is None and "rpm_limit" in self.model_fields_set: + _dict['rpm_limit'] = None + # set to None if token_limit (nullable) is None # and model_fields_set contains the field if self.token_limit is None and "token_limit" in self.model_fields_set: _dict['token_limit'] = None + # set to None if tpm_limit (nullable) is None + # and model_fields_set contains the field + if self.tpm_limit is None and "tpm_limit" in self.model_fields_set: + _dict['tpm_limit'] = None + return _dict @classmethod @@ -132,7 +144,9 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: "name": obj.get("name"), "request_limit": obj.get("request_limit"), "reset_alignment": obj.get("reset_alignment"), - "token_limit": obj.get("token_limit") + "rpm_limit": obj.get("rpm_limit"), + "token_limit": obj.get("token_limit"), + "tpm_limit": obj.get("tpm_limit") }) return _obj diff --git a/src/otari/_client/models/create_key_request.py b/src/otari/_client/models/create_key_request.py index 92806940..ba77665c 100644 --- a/src/otari/_client/models/create_key_request.py +++ b/src/otari/_client/models/create_key_request.py @@ -20,6 +20,7 @@ from datetime import datetime from pydantic import BaseModel, ConfigDict, Field, StrictBool, StrictStr from typing import Any, ClassVar, Dict, List, Optional +from typing_extensions import Annotated from uuid import UUID from typing import Optional, Set from typing_extensions import Self @@ -31,7 +32,8 @@ class CreateKeyRequest(BaseModel): """ # noqa: E501 allowed_models: Optional[List[StrictStr]] = Field(default=None, description="Model allow-list: null = any model, [] = deny all, or canonical instance:model entries (with instance:* / instance:prefix* wildcards).") capture_agent_telemetry: Optional[StrictBool] = Field(default=None, description="Per-key override of the deployment-wide capture_agent_telemetry setting: null (default) inherits it, true always stores this key's coding-agent telemetry, false always discards it. Covers both behavioral events (tool_result, tool_decision, user_prompt, api_error) from POST /otlp/v1/logs and outcome-metric data points (lines of code, commits, pull requests, active time) from POST /otlp/v1/metrics. Usage capture and billing are unaffected either way.") - end_user_budget_id: Optional[StrictStr] = Field(default=None, description="Budget each end user this key creates is capped at. Null leaves end users capped only by this key's own ceiling.") + end_user_budget_id: Optional[StrictStr] = Field(default=None, description="Budget each end user this key creates is capped at, unless the request names another with Otari-End-User-Budget. Null leaves end users capped only by this key's own ceiling.") + end_user_budget_ids: Optional[Annotated[List[StrictStr], Field(max_length=100)]] = Field(default=None, description="Budgets a request may start a new end user on by naming one in Otari-End-User-Budget. Null allows end_user_budget_id alone. When both are set, end_user_budget_id must be on the list.") exclude_from_budget: Optional[StrictBool] = Field(default=False, description="When true, requests on this key are logged with cost but never reserved, reconciled into the user's spend, or gated by budget.") expires_at: Optional[datetime] = Field(default=None, description="Optional expiration timestamp") is_service_key: Optional[StrictBool] = Field(default=False, description="When true, a request may name an end user in its 'user' field. Each end user is created on first use, owned by this key's user, and billed to its own budget, while this key's own ceiling caps all of them together.") @@ -40,7 +42,7 @@ class CreateKeyRequest(BaseModel): reject_user_mismatch: Optional[StrictBool] = Field(default=None, description="Per-key override of the deployment-wide reject_user_mismatch setting: null (default) inherits it, true always rejects a request naming a different 'user', false always accepts it. Spend binds to this key's own user either way.") user_id: Optional[StrictStr] = Field(default=None, description="Optional user ID to associate with this key") workspace_id: Optional[UUID] = Field(default=None, description="Workspace this key belongs to, which must be one in the caller's organization. Omitted means that organization's default workspace. A key belongs to exactly one workspace: requests on it are scoped and billed there, so the workspace is read off the key rather than off a request header.") - __properties: ClassVar[List[str]] = ["allowed_models", "capture_agent_telemetry", "end_user_budget_id", "exclude_from_budget", "expires_at", "is_service_key", "key_name", "metadata", "reject_user_mismatch", "user_id", "workspace_id"] + __properties: ClassVar[List[str]] = ["allowed_models", "capture_agent_telemetry", "end_user_budget_id", "end_user_budget_ids", "exclude_from_budget", "expires_at", "is_service_key", "key_name", "metadata", "reject_user_mismatch", "user_id", "workspace_id"] model_config = ConfigDict( validate_by_name=True, @@ -96,6 +98,11 @@ def to_dict(self) -> Dict[str, Any]: if self.end_user_budget_id is None and "end_user_budget_id" in self.model_fields_set: _dict['end_user_budget_id'] = None + # set to None if end_user_budget_ids (nullable) is None + # and model_fields_set contains the field + if self.end_user_budget_ids is None and "end_user_budget_ids" in self.model_fields_set: + _dict['end_user_budget_ids'] = None + # set to None if expires_at (nullable) is None # and model_fields_set contains the field if self.expires_at is None and "expires_at" in self.model_fields_set: @@ -136,6 +143,7 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: "allowed_models": obj.get("allowed_models"), "capture_agent_telemetry": obj.get("capture_agent_telemetry"), "end_user_budget_id": obj.get("end_user_budget_id"), + "end_user_budget_ids": obj.get("end_user_budget_ids"), "exclude_from_budget": obj.get("exclude_from_budget") if obj.get("exclude_from_budget") is not None else False, "expires_at": obj.get("expires_at"), "is_service_key": obj.get("is_service_key") if obj.get("is_service_key") is not None else False, diff --git a/src/otari/_client/models/create_key_response.py b/src/otari/_client/models/create_key_response.py index decc2678..f9d97ea3 100644 --- a/src/otari/_client/models/create_key_response.py +++ b/src/otari/_client/models/create_key_response.py @@ -31,6 +31,7 @@ class CreateKeyResponse(BaseModel): capture_agent_telemetry: Optional[StrictBool] created_at: StrictStr end_user_budget_id: Optional[StrictStr] + end_user_budget_ids: List[StrictStr] exclude_from_budget: StrictBool expires_at: Optional[StrictStr] id: StrictStr @@ -43,7 +44,7 @@ class CreateKeyResponse(BaseModel): metadata: Dict[str, Any] reject_user_mismatch: Optional[StrictBool] user_id: Optional[StrictStr] - __properties: ClassVar[List[str]] = ["allowed_models", "capture_agent_telemetry", "created_at", "end_user_budget_id", "exclude_from_budget", "expires_at", "id", "is_active", "is_service_key", "key", "key_name", "key_prefix", "key_suffix", "metadata", "reject_user_mismatch", "user_id"] + __properties: ClassVar[List[str]] = ["allowed_models", "capture_agent_telemetry", "created_at", "end_user_budget_id", "end_user_budget_ids", "exclude_from_budget", "expires_at", "id", "is_active", "is_service_key", "key", "key_name", "key_prefix", "key_suffix", "metadata", "reject_user_mismatch", "user_id"] model_config = ConfigDict( validate_by_name=True, @@ -145,6 +146,7 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: "capture_agent_telemetry": obj.get("capture_agent_telemetry"), "created_at": obj.get("created_at"), "end_user_budget_id": obj.get("end_user_budget_id"), + "end_user_budget_ids": obj.get("end_user_budget_ids"), "exclude_from_budget": obj.get("exclude_from_budget"), "expires_at": obj.get("expires_at"), "id": obj.get("id"), diff --git a/src/otari/_client/models/create_search_tool_request.py b/src/otari/_client/models/create_search_tool_request.py index 819f40a9..19fb67b1 100644 --- a/src/otari/_client/models/create_search_tool_request.py +++ b/src/otari/_client/models/create_search_tool_request.py @@ -31,7 +31,7 @@ class CreateSearchToolRequest(BaseModel): api_base: Optional[StrictStr] = Field(default=None, description="Backend endpoint. Omit to inherit the provider's default (searxng inherits web_search_url).") api_key: Optional[StrictStr] = Field(default=None, description="Provider API key. Stored encrypted; never returned.") name: Annotated[str, Field(min_length=1, strict=True)] = Field(description="Name callers pass as 'search_tool_name' or in /api/v1/search/{tool}.") - options: Optional[Dict[str, Any]] = Field(default=None, description="Provider-native request fields used as defaults (e.g. exa's 'type', searxng's 'engines').") + options: Optional[Dict[str, Any]] = Field(default=None, description="Tags for cost attribution, recorded on the request's usage rows and filterable in the usage API: up to 16 string pairs, keys up to 64 characters and values up to 512. A null value is ignored. LiteLLM's nested `spend_logs_metadata` object is also read, and wins over a flat key of the same name; it is never forwarded to the provider.") provider: StrictStr = Field(description="Search provider, one of: exa, searxng.") timeout: Optional[Union[Annotated[float, Field(strict=True, gt=0.0)], Annotated[int, Field(strict=True, gt=0)]]] = Field(default=None, description="Per-request timeout in seconds.") __properties: ClassVar[List[str]] = ["api_base", "api_key", "name", "options", "provider", "timeout"] diff --git a/src/otari/_client/models/create_stored_provider_request.py b/src/otari/_client/models/create_stored_provider_request.py index 5247e368..8f60121d 100644 --- a/src/otari/_client/models/create_stored_provider_request.py +++ b/src/otari/_client/models/create_stored_provider_request.py @@ -30,7 +30,7 @@ class CreateStoredProviderRequest(BaseModel): """ # noqa: E501 api_base: Optional[StrictStr] = None api_key: Optional[StrictStr] = Field(default=None, description="Provider API key. Stored encrypted; never returned.") - client_args: Optional[Dict[str, Any]] = Field(default=None, description="Provider-native request fields used as defaults (e.g. exa's 'type', searxng's 'engines').") + client_args: Optional[Dict[str, Any]] = Field(default=None, description="Tags for cost attribution, recorded on the request's usage rows and filterable in the usage API: up to 16 string pairs, keys up to 64 characters and values up to 512. A null value is ignored. LiteLLM's nested `spend_logs_metadata` object is also read, and wins over a flat key of the same name; it is never forwarded to the provider.") instance: Annotated[str, Field(min_length=1, strict=True)] = Field(description="Routing key, e.g. 'openai' or a named instance like 'home_lab'.") provider_type: Optional[StrictStr] = Field(default=None, description="any-llm implementation when the instance name is not itself one.") __properties: ClassVar[List[str]] = ["api_base", "api_key", "client_args", "instance", "provider_type"] diff --git a/src/otari/_client/models/criteria_inner.py b/src/otari/_client/models/criteria_inner.py index d41c2ac9..9ed6caef 100644 --- a/src/otari/_client/models/criteria_inner.py +++ b/src/otari/_client/models/criteria_inner.py @@ -33,7 +33,7 @@ class CriteriaInner(BaseModel): # data type: str anyof_schema_1_validator: Optional[StrictStr] = Field(default=None, description="Filter to a single event type or metric name (e.g. 'tool_result', 'claude_code.commit.count')") # data type: Dict[str, object] - anyof_schema_2_validator: Optional[Dict[str, Any]] = Field(default=None, description="Provider-native request fields used as defaults (e.g. exa's 'type', searxng's 'engines').") + anyof_schema_2_validator: Optional[Dict[str, Any]] = Field(default=None, description="Tags for cost attribution, recorded on the request's usage rows and filterable in the usage API: up to 16 string pairs, keys up to 64 characters and values up to 512. A null value is ignored. LiteLLM's nested `spend_logs_metadata` object is also read, and wins over a flat key of the same name; it is never forwarded to the provider.") # data type: List[object] anyof_schema_3_validator: Optional[List[Any]] = None if TYPE_CHECKING: diff --git a/src/otari/_client/models/criteria_value.py b/src/otari/_client/models/criteria_value.py index 14eca75a..8cf174d7 100644 --- a/src/otari/_client/models/criteria_value.py +++ b/src/otari/_client/models/criteria_value.py @@ -33,7 +33,7 @@ class CriteriaValue(BaseModel): # data type: str anyof_schema_1_validator: Optional[StrictStr] = Field(default=None, description="Filter to a single event type or metric name (e.g. 'tool_result', 'claude_code.commit.count')") # data type: Dict[str, object] - anyof_schema_2_validator: Optional[Dict[str, Any]] = Field(default=None, description="Provider-native request fields used as defaults (e.g. exa's 'type', searxng's 'engines').") + anyof_schema_2_validator: Optional[Dict[str, Any]] = Field(default=None, description="Tags for cost attribution, recorded on the request's usage rows and filterable in the usage API: up to 16 string pairs, keys up to 64 characters and values up to 512. A null value is ignored. LiteLLM's nested `spend_logs_metadata` object is also read, and wins over a flat key of the same name; it is never forwarded to the provider.") # data type: List[object] anyof_schema_3_validator: Optional[List[Any]] = None if TYPE_CHECKING: diff --git a/src/otari/_client/models/decision_answer.py b/src/otari/_client/models/decision_answer.py index 3f8fad20..5a60b5b5 100644 --- a/src/otari/_client/models/decision_answer.py +++ b/src/otari/_client/models/decision_answer.py @@ -29,7 +29,7 @@ class DecisionAnswer(BaseModel): """ # noqa: E501 choice: Optional[StrictStr] = Field(default=None, description="The chosen option, for a choice question") confidence: Optional[Union[StrictFloat, StrictInt]] = None - legend: Optional[Dict[str, Any]] = Field(default=None, description="Provider-native request fields used as defaults (e.g. exa's 'type', searxng's 'engines').") + legend: Optional[Dict[str, Any]] = Field(default=None, description="Tags for cost attribution, recorded on the request's usage rows and filterable in the usage API: up to 16 string pairs, keys up to 64 characters and values up to 512. A null value is ignored. LiteLLM's nested `spend_logs_metadata` object is also read, and wins over a flat key of the same name; it is never forwarded to the provider.") noul: Optional[Union[StrictFloat, StrictInt]] = Field(default=None, description="Probability of yes, for a noul question") probabilities: Optional[Dict[str, Union[StrictFloat, StrictInt]]] = None score: Optional[Union[StrictFloat, StrictInt]] = Field(default=None, description="The level, for a score question") diff --git a/src/otari/_client/models/end_user_public.py b/src/otari/_client/models/end_user_public.py new file mode 100644 index 00000000..bd64cc64 --- /dev/null +++ b/src/otari/_client/models/end_user_public.py @@ -0,0 +1,125 @@ +# 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, StrictFloat, StrictInt, StrictStr +from typing import Any, ClassVar, Dict, List, Optional, Union +from typing import Optional, Set +from typing_extensions import Self +from pydantic_core import to_jsonable_python + +class EndUserPublic(BaseModel): + """ + An end user of a service key, addressed by the id the service named it by. + """ # noqa: E501 + blocked: StrictBool + budget_id: Optional[StrictStr] + budget_started_at: Optional[StrictStr] + created_at: StrictStr + current_requests: StrictInt + current_tokens: StrictInt + external_id: StrictStr + next_budget_reset_at: Optional[StrictStr] + owner_user_id: StrictStr + reserved: Union[StrictFloat, StrictInt] + spend: Union[StrictFloat, StrictInt] + user_id: StrictStr + __properties: ClassVar[List[str]] = ["blocked", "budget_id", "budget_started_at", "created_at", "current_requests", "current_tokens", "external_id", "next_budget_reset_at", "owner_user_id", "reserved", "spend", "user_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 EndUserPublic 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 budget_id (nullable) is None + # and model_fields_set contains the field + if self.budget_id is None and "budget_id" in self.model_fields_set: + _dict['budget_id'] = None + + # set to None if budget_started_at (nullable) is None + # and model_fields_set contains the field + if self.budget_started_at is None and "budget_started_at" in self.model_fields_set: + _dict['budget_started_at'] = None + + # set to None if next_budget_reset_at (nullable) is None + # and model_fields_set contains the field + if self.next_budget_reset_at is None and "next_budget_reset_at" in self.model_fields_set: + _dict['next_budget_reset_at'] = None + + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of EndUserPublic from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "blocked": obj.get("blocked"), + "budget_id": obj.get("budget_id"), + "budget_started_at": obj.get("budget_started_at"), + "created_at": obj.get("created_at"), + "current_requests": obj.get("current_requests"), + "current_tokens": obj.get("current_tokens"), + "external_id": obj.get("external_id"), + "next_budget_reset_at": obj.get("next_budget_reset_at"), + "owner_user_id": obj.get("owner_user_id"), + "reserved": obj.get("reserved"), + "spend": obj.get("spend"), + "user_id": obj.get("user_id") + }) + return _obj + + diff --git a/src/otari/_client/models/end_user_put.py b/src/otari/_client/models/end_user_put.py new file mode 100644 index 00000000..76aed515 --- /dev/null +++ b/src/otari/_client/models/end_user_put.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 EndUserPut(BaseModel): + """ + Create an end user ahead of its first request, or move one, onto a budget on the key's list. + """ # noqa: E501 + budget_id: Annotated[str, Field(min_length=1, strict=True)] = Field(description="A budget on the key's end_user_budget_ids") + __properties: ClassVar[List[str]] = ["budget_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 EndUserPut 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 EndUserPut from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "budget_id": obj.get("budget_id") + }) + return _obj + + diff --git a/src/otari/_client/models/end_user_update.py b/src/otari/_client/models/end_user_update.py new file mode 100644 index 00000000..ca156696 --- /dev/null +++ b/src/otari/_client/models/end_user_update.py @@ -0,0 +1,101 @@ +# 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 EndUserUpdate(BaseModel): + """ + Block, unblock or move an end user. An omitted field is left as it is. + """ # noqa: E501 + blocked: Optional[StrictBool] = Field(default=None, description="Whether the end user is refused") + budget_id: Optional[Annotated[str, Field(min_length=1, strict=True)]] = Field(default=None, description="A budget on the key's end_user_budget_ids to move the end user to") + __properties: ClassVar[List[str]] = ["blocked", "budget_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 EndUserUpdate 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 blocked (nullable) is None + # and model_fields_set contains the field + if self.blocked is None and "blocked" in self.model_fields_set: + _dict['blocked'] = None + + # set to None if budget_id (nullable) is None + # and model_fields_set contains the field + if self.budget_id is None and "budget_id" in self.model_fields_set: + _dict['budget_id'] = None + + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of EndUserUpdate from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "blocked": obj.get("blocked"), + "budget_id": obj.get("budget_id") + }) + return _obj + + diff --git a/src/otari/_client/models/explain_request.py b/src/otari/_client/models/explain_request.py index 37a9d14d..3b705db0 100644 --- a/src/otari/_client/models/explain_request.py +++ b/src/otari/_client/models/explain_request.py @@ -33,7 +33,7 @@ class ExplainRequest(BaseModel): budget_used_pct: Optional[Union[StrictFloat, StrictInt]] = Field(default=None, description="Simulated budget usage percentage.") key_id: Optional[StrictStr] = Field(default=None, description="Evaluate conditions as this API key id.") name: Optional[StrictStr] = Field(default=None, description="An existing policy to explain.") - spec: Optional[Dict[str, Any]] = Field(default=None, description="Provider-native request fields used as defaults (e.g. exa's 'type', searxng's 'engines').") + spec: Optional[Dict[str, Any]] = Field(default=None, description="Tags for cost attribution, recorded on the request's usage rows and filterable in the usage API: up to 16 string pairs, keys up to 64 characters and values up to 512. A null value is ignored. LiteLLM's nested `spend_logs_metadata` object is also read, and wins over a flat key of the same name; it is never forwarded to the provider.") user_id: Optional[StrictStr] = Field(default=None, description="Evaluate conditions as this user.") workspace_id: Optional[UUID] = Field(default=None, description="Resolve `name` and the policy's candidate selectors in this workspace. Omit for the deployment's default workspace.") __properties: ClassVar[List[str]] = ["allowed_models", "budget_remaining_usd", "budget_used_pct", "key_id", "name", "spec", "user_id", "workspace_id"] diff --git a/src/otari/_client/models/instructions.py b/src/otari/_client/models/instructions.py index 21085ec6..f90825e3 100644 --- a/src/otari/_client/models/instructions.py +++ b/src/otari/_client/models/instructions.py @@ -33,7 +33,7 @@ class Instructions(BaseModel): # data type: str anyof_schema_1_validator: Optional[StrictStr] = Field(default=None, description="Filter to a single event type or metric name (e.g. 'tool_result', 'claude_code.commit.count')") # data type: Dict[str, object] - anyof_schema_2_validator: Optional[Dict[str, Any]] = Field(default=None, description="Provider-native request fields used as defaults (e.g. exa's 'type', searxng's 'engines').") + anyof_schema_2_validator: Optional[Dict[str, Any]] = Field(default=None, description="Tags for cost attribution, recorded on the request's usage rows and filterable in the usage API: up to 16 string pairs, keys up to 64 characters and values up to 512. A null value is ignored. LiteLLM's nested `spend_logs_metadata` object is also read, and wins over a flat key of the same name; it is never forwarded to the provider.") # data type: List[object] anyof_schema_3_validator: Optional[List[Any]] = None if TYPE_CHECKING: diff --git a/src/otari/_client/models/key_info.py b/src/otari/_client/models/key_info.py index b140d31e..9a0e0672 100644 --- a/src/otari/_client/models/key_info.py +++ b/src/otari/_client/models/key_info.py @@ -32,6 +32,7 @@ class KeyInfo(BaseModel): capture_agent_telemetry: Optional[StrictBool] created_at: StrictStr end_user_budget_id: Optional[StrictStr] + end_user_budget_ids: List[StrictStr] exclude_from_budget: StrictBool expires_at: Optional[StrictStr] id: StrictStr @@ -45,7 +46,7 @@ class KeyInfo(BaseModel): reject_user_mismatch: Optional[StrictBool] user_id: Optional[StrictStr] workspace_id: UUID - __properties: ClassVar[List[str]] = ["allowed_models", "capture_agent_telemetry", "created_at", "end_user_budget_id", "exclude_from_budget", "expires_at", "id", "is_active", "is_service_key", "key_name", "key_prefix", "key_suffix", "last_used_at", "metadata", "reject_user_mismatch", "user_id", "workspace_id"] + __properties: ClassVar[List[str]] = ["allowed_models", "capture_agent_telemetry", "created_at", "end_user_budget_id", "end_user_budget_ids", "exclude_from_budget", "expires_at", "id", "is_active", "is_service_key", "key_name", "key_prefix", "key_suffix", "last_used_at", "metadata", "reject_user_mismatch", "user_id", "workspace_id"] model_config = ConfigDict( validate_by_name=True, @@ -152,6 +153,7 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: "capture_agent_telemetry": obj.get("capture_agent_telemetry"), "created_at": obj.get("created_at"), "end_user_budget_id": obj.get("end_user_budget_id"), + "end_user_budget_ids": obj.get("end_user_budget_ids"), "exclude_from_budget": obj.get("exclude_from_budget"), "expires_at": obj.get("expires_at"), "id": obj.get("id"), diff --git a/src/otari/_client/models/mcp_tool_definition.py b/src/otari/_client/models/mcp_tool_definition.py index de993a5f..4f4d491d 100644 --- a/src/otari/_client/models/mcp_tool_definition.py +++ b/src/otari/_client/models/mcp_tool_definition.py @@ -27,7 +27,7 @@ class McpToolDefinition(BaseModel): """ One live tool a caller-orchestrated application may expose to its model. ``annotations`` is the remote server's own metadata, passed through as untrusted data. Otari never turns ``readOnlyHint`` into an authorization decision; each application owns its risk policy, and a server cannot waive an application's approval gate by labeling itself read-only. """ # noqa: E501 - annotations: Optional[Dict[str, Any]] = Field(default=None, description="Provider-native request fields used as defaults (e.g. exa's 'type', searxng's 'engines').") + annotations: Optional[Dict[str, Any]] = Field(default=None, description="Tags for cost attribution, recorded on the request's usage rows and filterable in the usage API: up to 16 string pairs, keys up to 64 characters and values up to 512. A null value is ignored. LiteLLM's nested `spend_logs_metadata` object is also read, and wins over a flat key of the same name; it is never forwarded to the provider.") description: Optional[StrictStr] = Field(default=None, description="The server's own description, untrusted.") input_schema: Dict[str, Any] = Field(description="The tool's MCP inputSchema, unmodified.") name: StrictStr = Field(description="The remote MCP tool name to send back to /api/v1/mcp/execute.") diff --git a/src/otari/_client/models/messages_request.py b/src/otari/_client/models/messages_request.py index 04f75086..29a92e3e 100644 --- a/src/otari/_client/models/messages_request.py +++ b/src/otari/_client/models/messages_request.py @@ -43,9 +43,9 @@ class MessagesRequest(BaseModel): 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 + metadata: Optional[Dict[str, Any]] = Field(default=None, description="Tags for cost attribution, recorded on the request's usage rows and filterable in the usage API: up to 16 string pairs, keys up to 64 characters and values up to 512. A null value is ignored. LiteLLM's nested `spend_logs_metadata` object is also read, and wins over a flat key of the same name; it is never forwarded to the provider.") model: StrictStr - output_format: Optional[Dict[str, Any]] = Field(default=None, description="Provider-native request fields used as defaults (e.g. exa's 'type', searxng's 'engines').") + output_format: Optional[Dict[str, Any]] = Field(default=None, description="Tags for cost attribution, recorded on the request's usage rows and filterable in the usage API: up to 16 string pairs, keys up to 64 characters and values up to 512. A null value is ignored. LiteLLM's nested `spend_logs_metadata` object is also read, and wins over a flat key of the same name; it is never forwarded to the provider.") prompt_cache_key: Optional[StrictStr] = None service_tier: Optional[StrictStr] = None session_label: Optional[Annotated[str, Field(strict=True, max_length=255)]] = Field(default=None, description="Optional caller-supplied label for cost attribution (per run, experiment, or conversation). In hybrid mode it is forwarded onto the platform usage report so spend can be sliced by session without standing up OpenTelemetry. Stripped before the request is forwarded upstream to the provider. Has no effect in standalone mode, where there is no platform to report it to.") diff --git a/src/otari/_client/models/model_false.py b/src/otari/_client/models/model_false.py index 0cc17ef8..64cd53f9 100644 --- a/src/otari/_client/models/model_false.py +++ b/src/otari/_client/models/model_false.py @@ -33,7 +33,7 @@ class ModelFalse(BaseModel): # data type: str anyof_schema_1_validator: Optional[StrictStr] = Field(default=None, description="Filter to a single event type or metric name (e.g. 'tool_result', 'claude_code.commit.count')") # data type: Dict[str, object] - anyof_schema_2_validator: Optional[Dict[str, Any]] = Field(default=None, description="Provider-native request fields used as defaults (e.g. exa's 'type', searxng's 'engines').") + anyof_schema_2_validator: Optional[Dict[str, Any]] = Field(default=None, description="Tags for cost attribution, recorded on the request's usage rows and filterable in the usage API: up to 16 string pairs, keys up to 64 characters and values up to 512. A null value is ignored. LiteLLM's nested `spend_logs_metadata` object is also read, and wins over a flat key of the same name; it is never forwarded to the provider.") # data type: List[object] anyof_schema_3_validator: Optional[List[Any]] = None if TYPE_CHECKING: diff --git a/src/otari/_client/models/model_true.py b/src/otari/_client/models/model_true.py index 640935a5..22f4c6a5 100644 --- a/src/otari/_client/models/model_true.py +++ b/src/otari/_client/models/model_true.py @@ -33,7 +33,7 @@ class ModelTrue(BaseModel): # data type: str anyof_schema_1_validator: Optional[StrictStr] = Field(default=None, description="Filter to a single event type or metric name (e.g. 'tool_result', 'claude_code.commit.count')") # data type: Dict[str, object] - anyof_schema_2_validator: Optional[Dict[str, Any]] = Field(default=None, description="Provider-native request fields used as defaults (e.g. exa's 'type', searxng's 'engines').") + anyof_schema_2_validator: Optional[Dict[str, Any]] = Field(default=None, description="Tags for cost attribution, recorded on the request's usage rows and filterable in the usage API: up to 16 string pairs, keys up to 64 characters and values up to 512. A null value is ignored. LiteLLM's nested `spend_logs_metadata` object is also read, and wins over a flat key of the same name; it is never forwarded to the provider.") # data type: List[object] anyof_schema_3_validator: Optional[List[Any]] = None if TYPE_CHECKING: diff --git a/src/otari/_client/models/moderation_result.py b/src/otari/_client/models/moderation_result.py index 98893e05..b5d2e4b1 100644 --- a/src/otari/_client/models/moderation_result.py +++ b/src/otari/_client/models/moderation_result.py @@ -31,7 +31,7 @@ class ModerationResult(BaseModel): category_applied_input_types: Optional[Dict[str, List[StrictStr]]] = None category_scores: Optional[Dict[str, Union[StrictFloat, StrictInt]]] = None flagged: StrictBool - provider_raw: Optional[Dict[str, Any]] = Field(default=None, description="Provider-native request fields used as defaults (e.g. exa's 'type', searxng's 'engines').") + provider_raw: Optional[Dict[str, Any]] = Field(default=None, description="Tags for cost attribution, recorded on the request's usage rows and filterable in the usage API: up to 16 string pairs, keys up to 64 characters and values up to 512. A null value is ignored. LiteLLM's nested `spend_logs_metadata` object is also read, and wins over a flat key of the same name; it is never forwarded to the provider.") __properties: ClassVar[List[str]] = ["categories", "category_applied_input_types", "category_scores", "flagged", "provider_raw"] model_config = ConfigDict( diff --git a/src/otari/_client/models/org_web_search_key_create_request.py b/src/otari/_client/models/org_web_search_key_create_request.py new file mode 100644 index 00000000..b2bbbcf9 --- /dev/null +++ b/src/otari/_client/models/org_web_search_key_create_request.py @@ -0,0 +1,93 @@ +# 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 OrgWebSearchKeyCreateRequest(BaseModel): + """ + What a caller sends to add a key. The service keeps only its ciphertext and ``last4``. + """ # noqa: E501 + api_key: Annotated[str, Field(min_length=1, strict=True)] + name: Annotated[str, Field(strict=True, max_length=255)] = Field(description="How the organization tells this key apart from its others.") + provider: Annotated[str, Field(strict=True, max_length=255)] = Field(description="The search provider the key is for: tavily or brave.") + __properties: ClassVar[List[str]] = ["api_key", "name", "provider"] + + 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 OrgWebSearchKeyCreateRequest 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 OrgWebSearchKeyCreateRequest from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "api_key": obj.get("api_key"), + "name": obj.get("name"), + "provider": obj.get("provider") + }) + return _obj + + diff --git a/src/otari/_client/models/org_web_search_key_public.py b/src/otari/_client/models/org_web_search_key_public.py new file mode 100644 index 00000000..c2d87da2 --- /dev/null +++ b/src/otari/_client/models/org_web_search_key_public.py @@ -0,0 +1,123 @@ +# 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 datetime import datetime +from pydantic import BaseModel, ConfigDict, Field, 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 OrgWebSearchKeyPublic(BaseModel): + """ + One key as the API shows it: never the key itself, only ``last4``. + """ # noqa: E501 + archived_at: Optional[datetime] = None + created_at: datetime + id: UUID + is_org_default: StrictBool + last4: Optional[StrictStr] = None + name: StrictStr + organization_id: UUID + provider: StrictStr + updated_at: Optional[datetime] = None + usable: StrictBool = Field(description="False when this deployment cannot decrypt the stored key, so no search uses it. It is still listed, because replacing or deleting it is what fixes it.") + __properties: ClassVar[List[str]] = ["archived_at", "created_at", "id", "is_org_default", "last4", "name", "organization_id", "provider", "updated_at", "usable"] + + 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 OrgWebSearchKeyPublic 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 archived_at (nullable) is None + # and model_fields_set contains the field + if self.archived_at is None and "archived_at" in self.model_fields_set: + _dict['archived_at'] = None + + # set to None if last4 (nullable) is None + # and model_fields_set contains the field + if self.last4 is None and "last4" in self.model_fields_set: + _dict['last4'] = 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 OrgWebSearchKeyPublic from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "archived_at": obj.get("archived_at"), + "created_at": obj.get("created_at"), + "id": obj.get("id"), + "is_org_default": obj.get("is_org_default"), + "last4": obj.get("last4"), + "name": obj.get("name"), + "organization_id": obj.get("organization_id"), + "provider": obj.get("provider"), + "updated_at": obj.get("updated_at"), + "usable": obj.get("usable") + }) + return _obj + + diff --git a/src/otari/_client/models/org_web_search_key_update_request.py b/src/otari/_client/models/org_web_search_key_update_request.py new file mode 100644 index 00000000..4ba262be --- /dev/null +++ b/src/otari/_client/models/org_web_search_key_update_request.py @@ -0,0 +1,101 @@ +# 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, Optional +from typing_extensions import Annotated +from typing import Optional, Set +from typing_extensions import Self +from pydantic_core import to_jsonable_python + +class OrgWebSearchKeyUpdateRequest(BaseModel): + """ + A partial update: only what is set is applied. + """ # noqa: E501 + api_key: Optional[Annotated[str, Field(min_length=1, strict=True)]] = None + name: Optional[Annotated[str, Field(strict=True, max_length=255)]] = None + __properties: ClassVar[List[str]] = ["api_key", "name"] + + 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 OrgWebSearchKeyUpdateRequest 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 api_key (nullable) is None + # and model_fields_set contains the field + if self.api_key is None and "api_key" in self.model_fields_set: + _dict['api_key'] = 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 + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of OrgWebSearchKeyUpdateRequest from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "api_key": obj.get("api_key"), + "name": obj.get("name") + }) + return _obj + + diff --git a/src/otari/_client/models/org_web_search_keys_public.py b/src/otari/_client/models/org_web_search_keys_public.py new file mode 100644 index 00000000..018da507 --- /dev/null +++ b/src/otari/_client/models/org_web_search_keys_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.org_web_search_key_public import OrgWebSearchKeyPublic +from typing import Optional, Set +from typing_extensions import Self +from pydantic_core import to_jsonable_python + +class OrgWebSearchKeysPublic(BaseModel): + """ + OrgWebSearchKeysPublic + """ # noqa: E501 + count: StrictInt + data: List[OrgWebSearchKeyPublic] + __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 OrgWebSearchKeysPublic 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 OrgWebSearchKeysPublic 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": [OrgWebSearchKeyPublic.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/organization_guardrail_create.py b/src/otari/_client/models/organization_guardrail_create.py index 4c96de51..0eecd27e 100644 --- a/src/otari/_client/models/organization_guardrail_create.py +++ b/src/otari/_client/models/organization_guardrail_create.py @@ -37,7 +37,7 @@ class OrganizationGuardrailCreate(BaseModel): on_unavailable: Optional[StrictStr] = Field(default='block', description="What a block-mode entry does when the guardrails service cannot be reached at all") profile: Annotated[str, Field(min_length=1, strict=True, max_length=128)] = Field(description="Profile name configured on the guardrails service, unique within the organization") url: Optional[Annotated[str, Field(strict=True, max_length=2048)]] = Field(default=None, description="Guardrails endpoint for this entry; null uses the deployment's guardrails_url") - validate_kwargs: Optional[Dict[str, Any]] = Field(default=None, description="Provider-native request fields used as defaults (e.g. exa's 'type', searxng's 'engines').") + validate_kwargs: Optional[Dict[str, Any]] = Field(default=None, description="Tags for cost attribution, recorded on the request's usage rows and filterable in the usage API: up to 16 string pairs, keys up to 64 characters and values up to 512. A null value is ignored. LiteLLM's nested `spend_logs_metadata` object is also read, and wins over a flat key of the same name; it is never forwarded to the provider.") workspace_ids: Optional[Annotated[List[UUID], Field(max_length=500)]] = Field(default=None, description="Workspaces this guardrail runs in. Must be empty when applies_to_all_workspaces is true") __properties: ClassVar[List[str]] = ["applies_to_all_workspaces", "credential", "definition_id", "enabled", "mode", "on_unavailable", "profile", "url", "validate_kwargs", "workspace_ids"] diff --git a/src/otari/_client/models/organization_guardrail_definition_update.py b/src/otari/_client/models/organization_guardrail_definition_update.py index 50fa4a4b..b2b12e91 100644 --- a/src/otari/_client/models/organization_guardrail_definition_update.py +++ b/src/otari/_client/models/organization_guardrail_definition_update.py @@ -28,7 +28,7 @@ class OrganizationGuardrailDefinitionUpdate(BaseModel): """ Partial update. Only the fields the caller sets are applied. ``create_kwargs`` replaces the arguments whole when sent, and an argument the catalog marks secret keeps its stored value where the caller echoes back the ``***`` a read gave them. Omitting it leaves both columns untouched *and reads neither*, which is what lets an admin on a deployment whose ``OTARI_SECRET_KEY`` has moved still flip ``enabled`` and repair the row by typing the credential again. Changing ``guardrail_name`` without sending ``create_kwargs`` re-splits the stored arguments under the new class, because the plain/secret split is the old class's answer and would otherwise go stale. """ # noqa: E501 - create_kwargs: Optional[Dict[str, Any]] = Field(default=None, description="Provider-native request fields used as defaults (e.g. exa's 'type', searxng's 'engines').") + create_kwargs: Optional[Dict[str, Any]] = Field(default=None, description="Tags for cost attribution, recorded on the request's usage rows and filterable in the usage API: up to 16 string pairs, keys up to 64 characters and values up to 512. A null value is ignored. LiteLLM's nested `spend_logs_metadata` object is also read, and wins over a flat key of the same name; it is never forwarded to the provider.") enabled: Optional[StrictBool] = None guardrail_name: Optional[Annotated[str, Field(min_length=1, strict=True, max_length=128)]] = None name: Optional[Annotated[str, Field(min_length=1, strict=True, max_length=128)]] = None diff --git a/src/otari/_client/models/organization_guardrail_public.py b/src/otari/_client/models/organization_guardrail_public.py index 72c14b01..9cd3d2d4 100644 --- a/src/otari/_client/models/organization_guardrail_public.py +++ b/src/otari/_client/models/organization_guardrail_public.py @@ -40,7 +40,7 @@ class OrganizationGuardrailPublic(BaseModel): profile: StrictStr updated_at: StrictStr url: Optional[StrictStr] - validate_kwargs: Optional[Dict[str, Any]] = Field(description="Provider-native request fields used as defaults (e.g. exa's 'type', searxng's 'engines').") + validate_kwargs: Optional[Dict[str, Any]] = Field(description="Tags for cost attribution, recorded on the request's usage rows and filterable in the usage API: up to 16 string pairs, keys up to 64 characters and values up to 512. A null value is ignored. LiteLLM's nested `spend_logs_metadata` object is also read, and wins over a flat key of the same name; it is never forwarded to the provider.") workspace_ids: List[UUID] __properties: ClassVar[List[str]] = ["applies_to_all_workspaces", "created_at", "definition_id", "enabled", "has_credential", "id", "mode", "on_unavailable", "organization_id", "profile", "updated_at", "url", "validate_kwargs", "workspace_ids"] diff --git a/src/otari/_client/models/organization_guardrail_update.py b/src/otari/_client/models/organization_guardrail_update.py index f1652c54..38bfbb2d 100644 --- a/src/otari/_client/models/organization_guardrail_update.py +++ b/src/otari/_client/models/organization_guardrail_update.py @@ -37,7 +37,7 @@ class OrganizationGuardrailUpdate(BaseModel): on_unavailable: Optional[StrictStr] = None profile: Optional[Annotated[str, Field(min_length=1, strict=True, max_length=128)]] = None url: Optional[Annotated[str, Field(strict=True, max_length=2048)]] = None - validate_kwargs: Optional[Dict[str, Any]] = Field(default=None, description="Provider-native request fields used as defaults (e.g. exa's 'type', searxng's 'engines').") + validate_kwargs: Optional[Dict[str, Any]] = Field(default=None, description="Tags for cost attribution, recorded on the request's usage rows and filterable in the usage API: up to 16 string pairs, keys up to 64 characters and values up to 512. A null value is ignored. LiteLLM's nested `spend_logs_metadata` object is also read, and wins over a flat key of the same name; it is never forwarded to the provider.") workspace_ids: Optional[Annotated[List[UUID], Field(max_length=500)]] = None __properties: ClassVar[List[str]] = ["applies_to_all_workspaces", "credential", "definition_id", "enabled", "mode", "on_unavailable", "profile", "url", "validate_kwargs", "workspace_ids"] diff --git a/src/otari/_client/models/provider_endpoint_create_request.py b/src/otari/_client/models/provider_endpoint_create_request.py index 8f1e5a69..2f3a4c91 100644 --- a/src/otari/_client/models/provider_endpoint_create_request.py +++ b/src/otari/_client/models/provider_endpoint_create_request.py @@ -31,7 +31,7 @@ class ProviderEndpointCreateRequest(BaseModel): """ # noqa: E501 api_base: Annotated[str, Field(strict=True, max_length=1024)] = Field(description="Base URL of the endpoint. Refused when it resolves to a private, loopback, link-local or reserved address.") api_key: Optional[StrictStr] = Field(default=None, description="Sent to the endpoint. Never returned, only its last four.") - default_params: Optional[Dict[str, Any]] = Field(default=None, description="Provider-native request fields used as defaults (e.g. exa's 'type', searxng's 'engines').") + default_params: Optional[Dict[str, Any]] = Field(default=None, description="Tags for cost attribution, recorded on the request's usage rows and filterable in the usage API: up to 16 string pairs, keys up to 64 characters and values up to 512. A null value is ignored. LiteLLM's nested `spend_logs_metadata` object is also read, and wins over a flat key of the same name; it is never forwarded to the provider.") name: Annotated[str, Field(strict=True, max_length=64)] = Field(description="What callers put before the colon to reach this endpoint, as ':'. Letters, digits, '.', '_' and '-', starting with a letter or digit. It may not be a provider's name or a configured instance's.") provider: Annotated[str, Field(strict=True, max_length=64)] = Field(description="The implementation that speaks to the endpoint: 'openai' for an OpenAI-compatible server, 'anthropic' for an Anthropic-compatible one. Whichever it is, callers may use any of the chat, responses and messages routes.") user_id: Optional[StrictStr] = Field(default=None, description="User that owns the endpoint. Omit for one every caller in the workspace reaches. A user's endpoint shadows a workspace-wide one of the same name for that user alone.") diff --git a/src/otari/_client/models/provider_endpoint_public.py b/src/otari/_client/models/provider_endpoint_public.py index 9492ad2f..5b546be4 100644 --- a/src/otari/_client/models/provider_endpoint_public.py +++ b/src/otari/_client/models/provider_endpoint_public.py @@ -31,7 +31,7 @@ class ProviderEndpointPublic(BaseModel): """ # noqa: E501 api_base: StrictStr created_at: datetime - default_params: Optional[Dict[str, Any]] = Field(default=None, description="Provider-native request fields used as defaults (e.g. exa's 'type', searxng's 'engines').") + default_params: Optional[Dict[str, Any]] = Field(default=None, description="Tags for cost attribution, recorded on the request's usage rows and filterable in the usage API: up to 16 string pairs, keys up to 64 characters and values up to 512. A null value is ignored. LiteLLM's nested `spend_logs_metadata` object is also read, and wins over a flat key of the same name; it is never forwarded to the provider.") id: UUID last4: Optional[StrictStr] = None name: StrictStr diff --git a/src/otari/_client/models/responses_request.py b/src/otari/_client/models/responses_request.py index 119a1cf1..d42bc765 100644 --- a/src/otari/_client/models/responses_request.py +++ b/src/otari/_client/models/responses_request.py @@ -46,14 +46,14 @@ class ResponsesRequest(BaseModel): max_tool_iterations: Optional[Annotated[int, Field(le=25, strict=True, ge=1)]] = 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 + metadata: Optional[Dict[str, Any]] = Field(default=None, description="Tags for cost attribution, recorded on the request's usage rows and filterable in the usage API: up to 16 string pairs, keys up to 64 characters and values up to 512. A null value is ignored. LiteLLM's nested `spend_logs_metadata` object is also read, and wins over a flat key of the same name; it is never forwarded to the provider.") model: StrictStr parallel_tool_calls: Optional[StrictBool] = None presence_penalty: Optional[Union[StrictFloat, StrictInt]] = None previous_response_id: Optional[StrictStr] = None prompt_cache_key: Optional[StrictStr] = None prompt_cache_retention: Optional[StrictStr] = None - reasoning: Optional[Dict[str, Any]] = Field(default=None, description="Provider-native request fields used as defaults (e.g. exa's 'type', searxng's 'engines').") + reasoning: Optional[Dict[str, Any]] = Field(default=None, description="Tags for cost attribution, recorded on the request's usage rows and filterable in the usage API: up to 16 string pairs, keys up to 64 characters and values up to 512. A null value is ignored. LiteLLM's nested `spend_logs_metadata` object is also read, and wins over a flat key of the same name; it is never forwarded to the provider.") response_format: Optional[Dict[str, Any]] = None safety_identifier: Optional[StrictStr] = None service_tier: Optional[StrictStr] = None diff --git a/src/otari/_client/models/sandbox_provider.py b/src/otari/_client/models/sandbox_provider.py new file mode 100644 index 00000000..35db86b8 --- /dev/null +++ b/src/otari/_client/models/sandbox_provider.py @@ -0,0 +1,37 @@ +# 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 json +from enum import Enum +from typing_extensions import Self + + +class SandboxProvider(str, Enum): + """ + What runs the code a code-execution tool call asks for, chosen per deployment. Values are read without regard to case or surrounding whitespace. + """ + + """ + allowed enum values + """ + PROTOCOL = 'protocol' + E2B = 'e2b' + + @classmethod + def from_json(cls, json_str: str) -> Self: + """Create an instance of SandboxProvider from a JSON string""" + return cls(json.loads(json_str)) + + diff --git a/src/otari/_client/models/state.py b/src/otari/_client/models/state.py index b9ec5593..3e9c199a 100644 --- a/src/otari/_client/models/state.py +++ b/src/otari/_client/models/state.py @@ -33,7 +33,7 @@ class State(BaseModel): # data type: str anyof_schema_1_validator: Optional[StrictStr] = Field(default=None, description="Filter to a single event type or metric name (e.g. 'tool_result', 'claude_code.commit.count')") # data type: Dict[str, object] - anyof_schema_2_validator: Optional[Dict[str, Any]] = Field(default=None, description="Provider-native request fields used as defaults (e.g. exa's 'type', searxng's 'engines').") + anyof_schema_2_validator: Optional[Dict[str, Any]] = Field(default=None, description="Tags for cost attribution, recorded on the request's usage rows and filterable in the usage API: up to 16 string pairs, keys up to 64 characters and values up to 512. A null value is ignored. LiteLLM's nested `spend_logs_metadata` object is also read, and wins over a flat key of the same name; it is never forwarded to the provider.") # data type: List[object] anyof_schema_3_validator: Optional[List[Any]] = None if TYPE_CHECKING: diff --git a/src/otari/_client/models/tool_choice.py b/src/otari/_client/models/tool_choice.py index aa12e760..22def1d4 100644 --- a/src/otari/_client/models/tool_choice.py +++ b/src/otari/_client/models/tool_choice.py @@ -33,7 +33,7 @@ class ToolChoice(BaseModel): # data type: str anyof_schema_1_validator: Optional[StrictStr] = Field(default=None, description="Filter to a single event type or metric name (e.g. 'tool_result', 'claude_code.commit.count')") # data type: Dict[str, object] - anyof_schema_2_validator: Optional[Dict[str, Any]] = Field(default=None, description="Provider-native request fields used as defaults (e.g. exa's 'type', searxng's 'engines').") + anyof_schema_2_validator: Optional[Dict[str, Any]] = Field(default=None, description="Tags for cost attribution, recorded on the request's usage rows and filterable in the usage API: up to 16 string pairs, keys up to 64 characters and values up to 512. A null value is ignored. LiteLLM's nested `spend_logs_metadata` object is also read, and wins over a flat key of the same name; it is never forwarded to the provider.") if TYPE_CHECKING: actual_instance: Optional[Union[Dict[str, object], str]] = None else: diff --git a/src/otari/_client/models/tool_settings_response.py b/src/otari/_client/models/tool_settings_response.py index 1fe2ff3e..d16830b0 100644 --- a/src/otari/_client/models/tool_settings_response.py +++ b/src/otari/_client/models/tool_settings_response.py @@ -17,8 +17,9 @@ import re # noqa: F401 import json -from pydantic import BaseModel, ConfigDict -from typing import Any, ClassVar, Dict, List +from pydantic import BaseModel, ConfigDict, Field +from typing import Any, ClassVar, Dict, List, Optional +from otari._client.models.sandbox_provider import SandboxProvider from otari._client.models.tool_setting_field import ToolSettingField from typing import Optional, Set from typing_extensions import Self @@ -29,7 +30,8 @@ class ToolSettingsResponse(BaseModel): The effective value of every editable tool/guardrail field. """ # noqa: E501 fields: List[ToolSettingField] - __properties: ClassVar[List[str]] = ["fields"] + sandbox_provider: Optional[SandboxProvider] = Field(default=None, description="What runs generated code: 'protocol' (a sandbox at sandbox_url) or 'e2b'. Set at startup, not editable here. Null for a reader who does not operate the deployment.") + __properties: ClassVar[List[str]] = ["fields", "sandbox_provider"] model_config = ConfigDict( validate_by_name=True, @@ -77,6 +79,11 @@ def to_dict(self) -> Dict[str, Any]: if _item_fields: _items.append(_item_fields.to_dict()) _dict['fields'] = _items + # set to None if sandbox_provider (nullable) is None + # and model_fields_set contains the field + if self.sandbox_provider is None and "sandbox_provider" in self.model_fields_set: + _dict['sandbox_provider'] = None + return _dict @classmethod @@ -89,7 +96,8 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: return cls.model_validate(obj) _obj = cls.model_validate({ - "fields": [ToolSettingField.from_dict(_item) for _item in obj["fields"]] if obj.get("fields") is not None else None + "fields": [ToolSettingField.from_dict(_item) for _item in obj["fields"]] if obj.get("fields") is not None else None, + "sandbox_provider": obj.get("sandbox_provider") }) return _obj diff --git a/src/otari/_client/models/update_budget_request.py b/src/otari/_client/models/update_budget_request.py index 77a2cf88..c838020c 100644 --- a/src/otari/_client/models/update_budget_request.py +++ b/src/otari/_client/models/update_budget_request.py @@ -33,8 +33,10 @@ class UpdateBudgetRequest(BaseModel): name: Optional[StrictStr] = None request_limit: Optional[Annotated[int, Field(le=1000000000000000, strict=True, ge=0)]] = Field(default=None, description="Maximum requests over the period. Independent of max_budget; null is unlimited") reset_alignment: Optional[StrictStr] = None + rpm_limit: Optional[Annotated[int, Field(le=2147483647, strict=True, ge=1)]] = Field(default=None, description="Requests per minute for each user on this budget, across replicas; null is unlimited") token_limit: Optional[Annotated[int, Field(le=1000000000000000, strict=True, ge=0)]] = Field(default=None, description="Maximum tokens over the period. Independent of max_budget; null is unlimited") - __properties: ClassVar[List[str]] = ["budget_duration_sec", "max_budget", "name", "request_limit", "reset_alignment", "token_limit"] + tpm_limit: Optional[Annotated[int, Field(le=2147483647, strict=True, ge=1)]] = Field(default=None, description="Tokens per minute for each user on this budget, counted on what requests used: a request is admitted while the user's minute is under the limit. Null is unlimited") + __properties: ClassVar[List[str]] = ["budget_duration_sec", "max_budget", "name", "request_limit", "reset_alignment", "rpm_limit", "token_limit", "tpm_limit"] @field_validator('reset_alignment') def reset_alignment_validate_enum(cls, value): @@ -110,11 +112,21 @@ def to_dict(self) -> Dict[str, Any]: if self.reset_alignment is None and "reset_alignment" in self.model_fields_set: _dict['reset_alignment'] = None + # set to None if rpm_limit (nullable) is None + # and model_fields_set contains the field + if self.rpm_limit is None and "rpm_limit" in self.model_fields_set: + _dict['rpm_limit'] = None + # set to None if token_limit (nullable) is None # and model_fields_set contains the field if self.token_limit is None and "token_limit" in self.model_fields_set: _dict['token_limit'] = None + # set to None if tpm_limit (nullable) is None + # and model_fields_set contains the field + if self.tpm_limit is None and "tpm_limit" in self.model_fields_set: + _dict['tpm_limit'] = None + return _dict @classmethod @@ -132,7 +144,9 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: "name": obj.get("name"), "request_limit": obj.get("request_limit"), "reset_alignment": obj.get("reset_alignment"), - "token_limit": obj.get("token_limit") + "rpm_limit": obj.get("rpm_limit"), + "token_limit": obj.get("token_limit"), + "tpm_limit": obj.get("tpm_limit") }) return _obj diff --git a/src/otari/_client/models/update_key_request.py b/src/otari/_client/models/update_key_request.py index 87f9975b..fd056d37 100644 --- a/src/otari/_client/models/update_key_request.py +++ b/src/otari/_client/models/update_key_request.py @@ -18,8 +18,9 @@ import json from datetime import datetime -from pydantic import BaseModel, ConfigDict, StrictBool, StrictStr +from pydantic import BaseModel, ConfigDict, Field, StrictBool, StrictStr 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 @@ -31,6 +32,7 @@ class UpdateKeyRequest(BaseModel): allowed_models: Optional[List[StrictStr]] = None capture_agent_telemetry: Optional[StrictBool] = None end_user_budget_id: Optional[StrictStr] = None + end_user_budget_ids: Optional[Annotated[List[StrictStr], Field(max_length=100)]] = None exclude_from_budget: Optional[StrictBool] = None expires_at: Optional[datetime] = None is_active: Optional[StrictBool] = None @@ -38,7 +40,7 @@ class UpdateKeyRequest(BaseModel): key_name: Optional[StrictStr] = None metadata: Optional[Dict[str, Any]] = None reject_user_mismatch: Optional[StrictBool] = None - __properties: ClassVar[List[str]] = ["allowed_models", "capture_agent_telemetry", "end_user_budget_id", "exclude_from_budget", "expires_at", "is_active", "is_service_key", "key_name", "metadata", "reject_user_mismatch"] + __properties: ClassVar[List[str]] = ["allowed_models", "capture_agent_telemetry", "end_user_budget_id", "end_user_budget_ids", "exclude_from_budget", "expires_at", "is_active", "is_service_key", "key_name", "metadata", "reject_user_mismatch"] model_config = ConfigDict( validate_by_name=True, @@ -94,6 +96,11 @@ def to_dict(self) -> Dict[str, Any]: if self.end_user_budget_id is None and "end_user_budget_id" in self.model_fields_set: _dict['end_user_budget_id'] = None + # set to None if end_user_budget_ids (nullable) is None + # and model_fields_set contains the field + if self.end_user_budget_ids is None and "end_user_budget_ids" in self.model_fields_set: + _dict['end_user_budget_ids'] = None + # set to None if exclude_from_budget (nullable) is None # and model_fields_set contains the field if self.exclude_from_budget is None and "exclude_from_budget" in self.model_fields_set: @@ -144,6 +151,7 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: "allowed_models": obj.get("allowed_models"), "capture_agent_telemetry": obj.get("capture_agent_telemetry"), "end_user_budget_id": obj.get("end_user_budget_id"), + "end_user_budget_ids": obj.get("end_user_budget_ids"), "exclude_from_budget": obj.get("exclude_from_budget"), "expires_at": obj.get("expires_at"), "is_active": obj.get("is_active"), diff --git a/src/otari/_client/models/update_search_tool_request.py b/src/otari/_client/models/update_search_tool_request.py index ca86a64b..509d4716 100644 --- a/src/otari/_client/models/update_search_tool_request.py +++ b/src/otari/_client/models/update_search_tool_request.py @@ -31,7 +31,7 @@ class UpdateSearchToolRequest(BaseModel): api_base: Optional[StrictStr] = None api_key: Optional[StrictStr] = Field(default=None, description="New API key. Omit to keep the existing one. Never returned.") expected_updated_at: Optional[StrictStr] = Field(default=None, description="Optimistic concurrency: if set, the update 412s unless it matches the stored updated_at.") - options: Optional[Dict[str, Any]] = Field(default=None, description="Provider-native request fields used as defaults (e.g. exa's 'type', searxng's 'engines').") + options: Optional[Dict[str, Any]] = Field(default=None, description="Tags for cost attribution, recorded on the request's usage rows and filterable in the usage API: up to 16 string pairs, keys up to 64 characters and values up to 512. A null value is ignored. LiteLLM's nested `spend_logs_metadata` object is also read, and wins over a flat key of the same name; it is never forwarded to the provider.") provider: Optional[StrictStr] = None timeout: Optional[Union[Annotated[float, Field(strict=True, gt=0.0)], Annotated[int, Field(strict=True, gt=0)]]] = None __properties: ClassVar[List[str]] = ["api_base", "api_key", "expected_updated_at", "options", "provider", "timeout"] diff --git a/src/otari/_client/models/usage_entry.py b/src/otari/_client/models/usage_entry.py index 6417a046..ae95af9b 100644 --- a/src/otari/_client/models/usage_entry.py +++ b/src/otari/_client/models/usage_entry.py @@ -58,11 +58,12 @@ class UsageEntry(BaseModel): source_label: Optional[StrictStr] status: StrictStr status_code: Optional[StrictInt] + tags: Optional[Dict[str, StrictStr]] = None timestamp: StrictStr total_tokens: Optional[StrictInt] user_alias: Optional[StrictStr] = None user_id: Optional[StrictStr] - __properties: ClassVar[List[str]] = ["api_key_id", "api_key_name", "attempt_count", "attempt_position", "billing_meters", "bulk_editable", "cache_read_tokens", "cache_write_1h_tokens", "cache_write_tokens", "completion_tokens", "cost", "counts_toward_budget", "endpoint", "error_message", "id", "latency_ms", "model", "policy_name", "pricing_breakdown", "prompt_tokens", "provider", "provider_latency_ms", "reasoning_tokens", "request_group_id", "selection_reason", "source", "source_label", "status", "status_code", "timestamp", "total_tokens", "user_alias", "user_id"] + __properties: ClassVar[List[str]] = ["api_key_id", "api_key_name", "attempt_count", "attempt_position", "billing_meters", "bulk_editable", "cache_read_tokens", "cache_write_1h_tokens", "cache_write_tokens", "completion_tokens", "cost", "counts_toward_budget", "endpoint", "error_message", "id", "latency_ms", "model", "policy_name", "pricing_breakdown", "prompt_tokens", "provider", "provider_latency_ms", "reasoning_tokens", "request_group_id", "selection_reason", "source", "source_label", "status", "status_code", "tags", "timestamp", "total_tokens", "user_alias", "user_id"] model_config = ConfigDict( validate_by_name=True, @@ -223,6 +224,11 @@ def to_dict(self) -> Dict[str, Any]: if self.status_code is None and "status_code" in self.model_fields_set: _dict['status_code'] = None + # set to None if tags (nullable) is None + # and model_fields_set contains the field + if self.tags is None and "tags" in self.model_fields_set: + _dict['tags'] = None + # set to None if total_tokens (nullable) is None # and model_fields_set contains the field if self.total_tokens is None and "total_tokens" in self.model_fields_set: @@ -279,6 +285,7 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: "source_label": obj.get("source_label"), "status": obj.get("status"), "status_code": obj.get("status_code"), + "tags": obj.get("tags"), "timestamp": obj.get("timestamp"), "total_tokens": obj.get("total_tokens"), "user_alias": obj.get("user_alias"), diff --git a/src/otari/_client/models/usage_entry_pricing_breakdown_inner.py b/src/otari/_client/models/usage_entry_pricing_breakdown_inner.py index 3579dd72..9a34445d 100644 --- a/src/otari/_client/models/usage_entry_pricing_breakdown_inner.py +++ b/src/otari/_client/models/usage_entry_pricing_breakdown_inner.py @@ -37,7 +37,7 @@ class UsageEntryPricingBreakdownInner(BaseModel): # data type: UnitChargeLine anyof_schema_2_validator: Optional[UnitChargeLine] = None # data type: Dict[str, object] - anyof_schema_3_validator: Optional[Dict[str, Any]] = Field(default=None, description="Provider-native request fields used as defaults (e.g. exa's 'type', searxng's 'engines').") + anyof_schema_3_validator: Optional[Dict[str, Any]] = Field(default=None, description="Tags for cost attribution, recorded on the request's usage rows and filterable in the usage API: up to 16 string pairs, keys up to 64 characters and values up to 512. A null value is ignored. LiteLLM's nested `spend_logs_metadata` object is also read, and wins over a flat key of the same name; it is never forwarded to the provider.") if TYPE_CHECKING: actual_instance: Optional[Union[Dict[str, object], TokenChargeLine, UnitChargeLine]] = None else: diff --git a/src/otari/_client/models/usage_summary.py b/src/otari/_client/models/usage_summary.py index d4c0d150..87946f17 100644 --- a/src/otari/_client/models/usage_summary.py +++ b/src/otari/_client/models/usage_summary.py @@ -39,6 +39,7 @@ class UsageSummary(BaseModel): by_provider: List[UsageGroupRow] by_source: List[UsageGroupRow] by_source_label: List[UsageGroupRow] + by_tag: Optional[List[UsageGroupRow]] = None by_tool: Optional[List[UsageToolRow]] = None by_user: List[UsageGroupRow] end_date: StrictStr @@ -46,7 +47,7 @@ class UsageSummary(BaseModel): series: List[UsageSeriesPoint] start_date: StrictStr totals: UsageTotals - __properties: ClassVar[List[str]] = ["bucket", "by_api_key", "by_endpoint", "by_model", "by_provider", "by_source", "by_source_label", "by_tool", "by_user", "end_date", "errors_by_status_code", "series", "start_date", "totals"] + __properties: ClassVar[List[str]] = ["bucket", "by_api_key", "by_endpoint", "by_model", "by_provider", "by_source", "by_source_label", "by_tag", "by_tool", "by_user", "end_date", "errors_by_status_code", "series", "start_date", "totals"] @field_validator('bucket') def bucket_validate_enum(cls, value): @@ -136,6 +137,13 @@ def to_dict(self) -> Dict[str, Any]: if _item_by_source_label: _items.append(_item_by_source_label.to_dict()) _dict['by_source_label'] = _items + # override the default output from pydantic by calling `to_dict()` of each item in by_tag (list) + _items = [] + if self.by_tag: + for _item_by_tag in self.by_tag: + if _item_by_tag: + _items.append(_item_by_tag.to_dict()) + _dict['by_tag'] = _items # override the default output from pydantic by calling `to_dict()` of each item in by_tool (list) _items = [] if self.by_tool: @@ -186,6 +194,7 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: "by_provider": [UsageGroupRow.from_dict(_item) for _item in obj["by_provider"]] if obj.get("by_provider") is not None else None, "by_source": [UsageGroupRow.from_dict(_item) for _item in obj["by_source"]] if obj.get("by_source") is not None else None, "by_source_label": [UsageGroupRow.from_dict(_item) for _item in obj["by_source_label"]] if obj.get("by_source_label") is not None else None, + "by_tag": [UsageGroupRow.from_dict(_item) for _item in obj["by_tag"]] if obj.get("by_tag") is not None else None, "by_tool": [UsageToolRow.from_dict(_item) for _item in obj["by_tool"]] if obj.get("by_tool") is not None else None, "by_user": [UsageGroupRow.from_dict(_item) for _item in obj["by_user"]] if obj.get("by_user") is not None else None, "end_date": obj.get("end_date"), diff --git a/src/otari/_client/models/workspace_web_search_config_public.py b/src/otari/_client/models/workspace_web_search_config_public.py index afe6ce05..3bd8db3b 100644 --- a/src/otari/_client/models/workspace_web_search_config_public.py +++ b/src/otari/_client/models/workspace_web_search_config_public.py @@ -34,7 +34,7 @@ class WorkspaceWebSearchConfigPublic(BaseModel): created_at: Optional[StrictStr] enabled: StrictBool max_results: Optional[StrictInt] - provider_options: Optional[Dict[str, Any]] = Field(description="Provider-native request fields used as defaults (e.g. exa's 'type', searxng's 'engines').") + provider_options: Optional[Dict[str, Any]] = Field(description="Tags for cost attribution, recorded on the request's usage rows and filterable in the usage API: up to 16 string pairs, keys up to 64 characters and values up to 512. A null value is ignored. LiteLLM's nested `spend_logs_metadata` object is also read, and wins over a flat key of the same name; it is never forwarded to the provider.") purpose_hint: Optional[StrictStr] updated_at: Optional[StrictStr] web_search_configured: StrictBool diff --git a/src/otari/_client/models/workspace_web_search_config_update.py b/src/otari/_client/models/workspace_web_search_config_update.py index a9b8e0df..4419f856 100644 --- a/src/otari/_client/models/workspace_web_search_config_update.py +++ b/src/otari/_client/models/workspace_web_search_config_update.py @@ -32,7 +32,7 @@ class WorkspaceWebSearchConfigUpdate(BaseModel): blocked_domains: Optional[List[StrictStr]] = Field(default=None, description="Filters Search results and blocks initial and redirected Fetch destinations; added to any list the request sends") enabled: StrictBool = Field(description="False refuses web access for this workspace through otari_web_search, otari_web_fetch, and POST /api/v1/search.") max_results: Optional[Annotated[int, Field(le=20, strict=True, gt=0)]] = Field(default=None, description="Search only: ceiling on results one search returns; only ever lowers the effective limit, so at most 20") - provider_options: Optional[Dict[str, Any]] = Field(default=None, description="Provider-native request fields used as defaults (e.g. exa's 'type', searxng's 'engines').") + provider_options: Optional[Dict[str, Any]] = Field(default=None, description="Tags for cost attribution, recorded on the request's usage rows and filterable in the usage API: up to 16 string pairs, keys up to 64 characters and values up to 512. A null value is ignored. LiteLLM's nested `spend_logs_metadata` object is also read, and wins over a flat key of the same name; it is never forwarded to the provider.") purpose_hint: Optional[Annotated[str, Field(strict=True, max_length=2048)]] = Field(default=None, description="Search only: hint used when a request declares otari_web_search without one of its own") __properties: ClassVar[List[str]] = ["allowed_domains", "blocked_domains", "enabled", "max_results", "provider_options", "purpose_hint"] diff --git a/src/otari/_client/models/workspace_web_search_key_override_request.py b/src/otari/_client/models/workspace_web_search_key_override_request.py new file mode 100644 index 00000000..80e9e808 --- /dev/null +++ b/src/otari/_client/models/workspace_web_search_key_override_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, StrictBool +from typing import Any, ClassVar, Dict, List, Optional +from typing import Optional, Set +from typing_extensions import Self +from pydantic_core import to_jsonable_python + +class WorkspaceWebSearchKeyOverrideRequest(BaseModel): + """ + Tri-state: an omitted flag keeps its value. Pinning a key re-enables it and unpins any other key of the workspace, and turning a key off unpins it. Sending both flags true is refused. Both false deletes the override. + """ # noqa: E501 + disabled: Optional[StrictBool] = None + is_default: Optional[StrictBool] = None + __properties: ClassVar[List[str]] = ["disabled", "is_default"] + + 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 WorkspaceWebSearchKeyOverrideRequest 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 disabled (nullable) is None + # and model_fields_set contains the field + if self.disabled is None and "disabled" in self.model_fields_set: + _dict['disabled'] = None + + # set to None if is_default (nullable) is None + # and model_fields_set contains the field + if self.is_default is None and "is_default" in self.model_fields_set: + _dict['is_default'] = None + + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of WorkspaceWebSearchKeyOverrideRequest from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "disabled": obj.get("disabled"), + "is_default": obj.get("is_default") + }) + return _obj + + diff --git a/src/otari/_client/models/workspace_web_search_key_public.py b/src/otari/_client/models/workspace_web_search_key_public.py new file mode 100644 index 00000000..831fda01 --- /dev/null +++ b/src/otari/_client/models/workspace_web_search_key_public.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, 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 WorkspaceWebSearchKeyPublic(BaseModel): + """ + One of the organization's keys, as one workspace sees it. + """ # noqa: E501 + disabled: StrictBool = Field(description="The workspace turned this key off.") + is_default: StrictBool = Field(description="The workspace pinned this key as its own.") + is_effective: StrictBool = Field(description="This is the key the workspace's searches use.") + last4: Optional[StrictStr] = None + name: StrictStr + org_web_search_key_id: UUID + provider: StrictStr + usable: StrictBool + workspace_id: UUID + __properties: ClassVar[List[str]] = ["disabled", "is_default", "is_effective", "last4", "name", "org_web_search_key_id", "provider", "usable", "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 WorkspaceWebSearchKeyPublic 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 last4 (nullable) is None + # and model_fields_set contains the field + if self.last4 is None and "last4" in self.model_fields_set: + _dict['last4'] = None + + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of WorkspaceWebSearchKeyPublic from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "disabled": obj.get("disabled"), + "is_default": obj.get("is_default"), + "is_effective": obj.get("is_effective"), + "last4": obj.get("last4"), + "name": obj.get("name"), + "org_web_search_key_id": obj.get("org_web_search_key_id"), + "provider": obj.get("provider"), + "usable": obj.get("usable"), + "workspace_id": obj.get("workspace_id") + }) + return _obj + + diff --git a/src/otari/_client/models/workspace_web_search_keys_public.py b/src/otari/_client/models/workspace_web_search_keys_public.py new file mode 100644 index 00000000..bdb5edc3 --- /dev/null +++ b/src/otari/_client/models/workspace_web_search_keys_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, Field, StrictInt +from typing import Any, ClassVar, Dict, List +from otari._client.models.workspace_web_search_key_public import WorkspaceWebSearchKeyPublic +from typing import Optional, Set +from typing_extensions import Self +from pydantic_core import to_jsonable_python + +class WorkspaceWebSearchKeysPublic(BaseModel): + """ + WorkspaceWebSearchKeysPublic + """ # noqa: E501 + count: StrictInt = Field(description="Every live key of the organization, not only this page.") + data: List[WorkspaceWebSearchKeyPublic] + __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 WorkspaceWebSearchKeysPublic 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 WorkspaceWebSearchKeysPublic 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": [WorkspaceWebSearchKeyPublic.from_dict(_item) for _item in obj["data"]] if obj.get("data") is not None else None + }) + return _obj + +