From 09d546eb28819ea49181580a52a6b9fe4591024e Mon Sep 17 00:00:00 2001 From: njbrake <33383515+njbrake@users.noreply.github.com> Date: Mon, 17 Aug 2026 16:28:56 +0000 Subject: [PATCH] chore: regenerate SDK client core from Otari OpenAPI spec --- sdk-endpoints.txt | 18 +- src/otari/_client/__init__.py | 64 +- src/otari/_client/api/__init__.py | 2 + src/otari/_client/api/agent_telemetry_api.py | 1123 ++++++++++++ src/otari/_client/api/bootstrap_api.py | 280 +++ src/otari/_client/api/otel_api.py | 247 +++ src/otari/_client/api/pricing_api.py | 6 +- src/otari/_client/api/routing_api.py | 6 +- src/otari/_client/api/search_tools_api.py | 1619 +++++++++++++++++ src/otari/_client/models/__init__.py | 30 +- .../models/agent_telemetry_behavior.py | 108 ++ .../_client/models/agent_telemetry_count.py | 88 + .../models/agent_telemetry_group_row.py | 97 + .../models/agent_telemetry_grouped_series.py | 128 ++ .../agent_telemetry_grouped_series_point.py | 99 + .../models/agent_telemetry_measures.py | 142 ++ .../models/agent_telemetry_outcomes.py | 94 + .../models/agent_telemetry_series_point.py | 104 ++ .../_client/models/agent_telemetry_summary.py | 133 ++ .../models/agent_telemetry_tool_row.py | 95 + .../_client/models/agent_telemetry_usage.py | 90 + src/otari/_client/models/billing_meters.py | 143 ++ .../models/cc_chat_completion_message.py | 4 +- src/otari/_client/models/cck_choice_delta.py | 2 +- .../models/cck_choice_delta_function_call.py | 2 +- src/otari/_client/models/chat_completion.py | 2 +- .../_client/models/chat_completion_request.py | 13 +- .../chat_completion_request_tools_inner.py | 2 +- .../models/config_search_tool_schema.py | 101 + src/otari/_client/models/conversation.py | 4 +- .../_client/models/count_tokens_request.py | 10 +- .../_client/models/create_key_request.py | 2 +- .../models/create_search_tool_request.py | 119 ++ .../models/create_stored_provider_request.py | 2 +- .../_client/models/deployment_bootstrap.py | 113 ++ src/otari/_client/models/explain_request.py | 2 +- src/otari/_client/models/img_image.py | 6 +- src/otari/_client/models/message_response.py | 2 +- src/otari/_client/models/messages_request.py | 2 +- .../_client/models/model_pricing_info.py | 15 +- src/otari/_client/models/moderation_result.py | 2 +- .../models/mr_beta_diagnostics_fallback.py | 2 +- src/otari/_client/models/mr_message_usage.py | 2 +- .../_client/models/mr_refusal_stop_details.py | 2 +- src/otari/_client/models/policy_request.py | 9 +- .../_client/models/pricing_tiers_inner.py | 137 ++ ...py => pricing_tiers_inner_any_of_value.py} | 12 +- .../models/reencrypt_search_tools_response.py | 90 + src/otari/_client/models/rerank_response.py | 2 +- src/otari/_client/models/responses_request.py | 2 +- src/otari/_client/models/router_status.py | 2 +- .../_client/models/search_provider_schema.py | 99 + .../_client/models/search_tools_response.py | 106 ++ .../models/stored_search_tool_schema.py | 131 ++ src/otari/_client/models/token_charge_line.py | 111 ++ src/otari/_client/models/tool_choice.py | 4 +- src/otari/_client/models/tool_meter.py | 110 ++ src/otari/_client/models/unit_charge_line.py | 111 ++ ...cing_breakdown_inner_value.py => units.py} | 49 +- src/otari/_client/models/units1.py | 138 ++ .../models/update_search_tool_request.py | 129 ++ src/otari/_client/models/usage_entry.py | 25 +- .../usage_entry_pricing_breakdown_inner.py | 151 ++ 63 files changed, 6435 insertions(+), 110 deletions(-) create mode 100644 src/otari/_client/api/bootstrap_api.py create mode 100644 src/otari/_client/api/search_tools_api.py create mode 100644 src/otari/_client/models/agent_telemetry_behavior.py create mode 100644 src/otari/_client/models/agent_telemetry_count.py create mode 100644 src/otari/_client/models/agent_telemetry_group_row.py create mode 100644 src/otari/_client/models/agent_telemetry_grouped_series.py create mode 100644 src/otari/_client/models/agent_telemetry_grouped_series_point.py create mode 100644 src/otari/_client/models/agent_telemetry_measures.py create mode 100644 src/otari/_client/models/agent_telemetry_outcomes.py create mode 100644 src/otari/_client/models/agent_telemetry_series_point.py create mode 100644 src/otari/_client/models/agent_telemetry_summary.py create mode 100644 src/otari/_client/models/agent_telemetry_tool_row.py create mode 100644 src/otari/_client/models/agent_telemetry_usage.py create mode 100644 src/otari/_client/models/billing_meters.py create mode 100644 src/otari/_client/models/config_search_tool_schema.py create mode 100644 src/otari/_client/models/create_search_tool_request.py create mode 100644 src/otari/_client/models/deployment_bootstrap.py create mode 100644 src/otari/_client/models/pricing_tiers_inner.py rename src/otari/_client/models/{pricing_tiers_inner_value.py => pricing_tiers_inner_any_of_value.py} (91%) create mode 100644 src/otari/_client/models/reencrypt_search_tools_response.py create mode 100644 src/otari/_client/models/search_provider_schema.py create mode 100644 src/otari/_client/models/search_tools_response.py create mode 100644 src/otari/_client/models/stored_search_tool_schema.py create mode 100644 src/otari/_client/models/token_charge_line.py create mode 100644 src/otari/_client/models/tool_meter.py create mode 100644 src/otari/_client/models/unit_charge_line.py rename src/otari/_client/models/{usage_entry_pricing_breakdown_inner_value.py => units.py} (74%) create mode 100644 src/otari/_client/models/units1.py create mode 100644 src/otari/_client/models/update_search_tool_request.py create mode 100644 src/otari/_client/models/usage_entry_pricing_breakdown_inner.py diff --git a/sdk-endpoints.txt b/sdk-endpoints.txt index 49cd485..22488a2 100644 --- a/sdk-endpoints.txt +++ b/sdk-endpoints.txt @@ -91,7 +91,7 @@ POST /v1/provider-credentials/test # not yet wrapped PATCH /v1/provider-credentials/{instance} # not yet wrapped DELETE /v1/provider-credentials/{instance} # not yet wrapped POST /v1/provider-credentials/{instance}/test # not yet wrapped -# Providers catalogue +# Providers catalog GET /v1/providers # not yet wrapped GET /v1/providers/catalog # not yet wrapped # Runtime settings @@ -108,10 +108,14 @@ GET /v1/budgets/{budget_id}/reset-logs # 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. POST /v1/auth/session # dashboard-only +# Deployment bootstrap: tells the dashboard shell which deployment served it, so +# it exists for a browser deciding what to render. An SDK already knows. +GET /v1/bootstrap # dashboard-only DELETE /v1/auth/session # dashboard-only # OTLP ingest: OpenTelemetry collector receivers, not an SDK surface. POST /v1/logs # otel ingest POST /v1/traces # otel ingest +POST /v1/metrics # otel ingest # Usage analytics and maintenance GET /v1/usage/summary # not yet wrapped GET /v1/usage/summary.csv # not yet wrapped @@ -120,7 +124,10 @@ DELETE /v1/usage # not yet wrapped POST /v1/usage/external-events # not yet wrapped POST /v1/usage/set-price # not yet wrapped GET /v1/usage/in-flight # dashboard-only, per-worker live view -# Agent telemetry purge +# Agent telemetry read and purge +GET /v1/agent-telemetry/summary # not yet wrapped +GET /v1/agent-telemetry/count # not yet wrapped +GET /v1/agent-telemetry/series # not yet wrapped DELETE /v1/agent-telemetry # not yet wrapped # Routing policies GET /v1/routing/policies # not yet wrapped @@ -144,5 +151,12 @@ PATCH /v1/tool-settings # not yet wrapped POST /v1/tool-settings/{service}/test # not yet wrapped POST /v1/search # not yet wrapped POST /v1/search/{search_tool_name} # not yet wrapped +# Search tools (runtime search-tool management) +GET /v1/search-tools # not yet wrapped +GET /v1/search-tools/providers # not yet wrapped +POST /v1/search-tools # not yet wrapped +PATCH /v1/search-tools/{name} # not yet wrapped +DELETE /v1/search-tools/{name} # not yet wrapped +POST /v1/search-tools/reencrypt # not yet wrapped # Settings POST /v1/settings/master-key/rotate # not yet wrapped diff --git a/src/otari/_client/__init__.py b/src/otari/_client/__init__.py index d48a466..66479b7 100644 --- a/src/otari/_client/__init__.py +++ b/src/otari/_client/__init__.py @@ -23,6 +23,7 @@ "AudioApi", "AuthApi", "BatchesApi", + "BootstrapApi", "BudgetsApi", "ChatApi", "EmbeddingsApi", @@ -40,6 +41,7 @@ "ResponsesApi", "RoutingApi", "SearchApi", + "SearchToolsApi", "SettingsApi", "ToolSettingsApi", "ToolsApi", @@ -54,14 +56,26 @@ "ApiKeyError", "ApiAttributeError", "ApiException", + "AgentTelemetryBehavior", + "AgentTelemetryCount", "AgentTelemetryDeleteRequest", "AgentTelemetryDeleteResult", + "AgentTelemetryGroupRow", + "AgentTelemetryGroupedSeries", + "AgentTelemetryGroupedSeriesPoint", + "AgentTelemetryMeasures", + "AgentTelemetryOutcomes", + "AgentTelemetrySeriesPoint", + "AgentTelemetrySummary", + "AgentTelemetryToolRow", + "AgentTelemetryUsage", "AliasRequest", "AliasResponse", "ApiKeyId", "AppliedEditsInner", "AudioSpeechRequest", "BatchRequestItem", + "BillingMeters", "BudgetResetLogResponse", "BudgetResponse", "CCChatCompletionAudio", @@ -99,6 +113,7 @@ "ChatCompletionRequestToolsInner", "ChatMessageInput", "ConfigField", + "ConfigSearchToolSchema", "Content", "Content1", "Content10", @@ -126,9 +141,11 @@ "CreateEmbeddingResponse", "CreateKeyRequest", "CreateKeyResponse", + "CreateSearchToolRequest", "CreateSessionRequest", "CreateStoredProviderRequest", "CreateUserRequest", + "DeploymentBootstrap", "DiscoverableModel", "DiscoverableModelsResponse", "DiscoverableProvider", @@ -306,7 +323,8 @@ "PricingRefreshPreviewResponse", "PricingResponse", "PricingTier", - "PricingTiersInnerValue", + "PricingTiersInner", + "PricingTiersInnerAnyOfValue", "ProviderCapabilitiesSchema", "ProviderHealthResponse", "ProviderHealthSchema", @@ -319,35 +337,45 @@ "RankResponse", "RecordedPool", "ReencryptProviderCredentialsResponse", + "ReencryptSearchToolsResponse", "RerankRequest", "RerankResponse", "ResponsesRequest", "RotateMasterKeyResponse", "RouterStatus", "ScoredExample", + "SearchProviderSchema", "SearchRequest", "SearchResponse", "SearchResultItem", + "SearchToolsResponse", "SessionResponse", "SetPricingRequest", "Source", "Source1", "Stop", "StoredProviderResponse", + "StoredSearchToolSchema", "System", "TaskPool", "TestProviderRequest", "TestProviderResponse", "TestServiceRequest", "TestServiceResponse", + "TokenChargeLine", "ToolCallsInner", "ToolChoice", "ToolChoice1", + "ToolMeter", "ToolSettingField", "ToolSettingsResponse", "ToolsResponse", + "UnitChargeLine", + "Units", + "Units1", "UpdateBudgetRequest", "UpdateKeyRequest", + "UpdateSearchToolRequest", "UpdateSettingsRequest", "UpdateStoredProviderRequest", "UpdateToolSettingsRequest", @@ -356,7 +384,7 @@ "UsageDeleteRequest", "UsageDeleteResult", "UsageEntry", - "UsageEntryPricingBreakdownInnerValue", + "UsageEntryPricingBreakdownInner", "UsageErrorCodeRow", "UsageGroupRow", "UsageGroupedSeries", @@ -381,6 +409,7 @@ from otari._client.api.audio_api import AudioApi as AudioApi from otari._client.api.auth_api import AuthApi as AuthApi from otari._client.api.batches_api import BatchesApi as BatchesApi +from otari._client.api.bootstrap_api import BootstrapApi as BootstrapApi from otari._client.api.budgets_api import BudgetsApi as BudgetsApi from otari._client.api.chat_api import ChatApi as ChatApi from otari._client.api.embeddings_api import EmbeddingsApi as EmbeddingsApi @@ -398,6 +427,7 @@ from otari._client.api.responses_api import ResponsesApi as ResponsesApi from otari._client.api.routing_api import RoutingApi as RoutingApi from otari._client.api.search_api import SearchApi as SearchApi +from otari._client.api.search_tools_api import SearchToolsApi as SearchToolsApi from otari._client.api.settings_api import SettingsApi as SettingsApi from otari._client.api.tool_settings_api import ToolSettingsApi as ToolSettingsApi from otari._client.api.tools_api import ToolsApi as ToolsApi @@ -416,14 +446,26 @@ from otari._client.exceptions import ApiException as ApiException # import models into sdk package +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 from otari._client.models.agent_telemetry_delete_result import AgentTelemetryDeleteResult as AgentTelemetryDeleteResult +from otari._client.models.agent_telemetry_group_row import AgentTelemetryGroupRow as AgentTelemetryGroupRow +from otari._client.models.agent_telemetry_grouped_series import AgentTelemetryGroupedSeries as AgentTelemetryGroupedSeries +from otari._client.models.agent_telemetry_grouped_series_point import AgentTelemetryGroupedSeriesPoint as AgentTelemetryGroupedSeriesPoint +from otari._client.models.agent_telemetry_measures import AgentTelemetryMeasures as AgentTelemetryMeasures +from otari._client.models.agent_telemetry_outcomes import AgentTelemetryOutcomes as AgentTelemetryOutcomes +from otari._client.models.agent_telemetry_series_point import AgentTelemetrySeriesPoint as AgentTelemetrySeriesPoint +from otari._client.models.agent_telemetry_summary import AgentTelemetrySummary as AgentTelemetrySummary +from otari._client.models.agent_telemetry_tool_row import AgentTelemetryToolRow as AgentTelemetryToolRow +from otari._client.models.agent_telemetry_usage import AgentTelemetryUsage as AgentTelemetryUsage from otari._client.models.alias_request import AliasRequest as AliasRequest from otari._client.models.alias_response import AliasResponse as AliasResponse from otari._client.models.api_key_id import ApiKeyId as ApiKeyId from otari._client.models.applied_edits_inner import AppliedEditsInner as AppliedEditsInner from otari._client.models.audio_speech_request import AudioSpeechRequest as AudioSpeechRequest from otari._client.models.batch_request_item import BatchRequestItem as BatchRequestItem +from otari._client.models.billing_meters import BillingMeters as BillingMeters from otari._client.models.budget_reset_log_response import BudgetResetLogResponse as BudgetResetLogResponse from otari._client.models.budget_response import BudgetResponse as BudgetResponse from otari._client.models.cc_chat_completion_audio import CCChatCompletionAudio as CCChatCompletionAudio @@ -461,6 +503,7 @@ from otari._client.models.chat_completion_request_tools_inner import ChatCompletionRequestToolsInner as ChatCompletionRequestToolsInner from otari._client.models.chat_message_input import ChatMessageInput as ChatMessageInput from otari._client.models.config_field import ConfigField as ConfigField +from otari._client.models.config_search_tool_schema import ConfigSearchToolSchema as ConfigSearchToolSchema from otari._client.models.content import Content as Content from otari._client.models.content1 import Content1 as Content1 from otari._client.models.content10 import Content10 as Content10 @@ -488,9 +531,11 @@ from otari._client.models.create_embedding_response import CreateEmbeddingResponse as CreateEmbeddingResponse from otari._client.models.create_key_request import CreateKeyRequest as CreateKeyRequest from otari._client.models.create_key_response import CreateKeyResponse as CreateKeyResponse +from otari._client.models.create_search_tool_request import CreateSearchToolRequest as CreateSearchToolRequest from otari._client.models.create_session_request import CreateSessionRequest as CreateSessionRequest from otari._client.models.create_stored_provider_request import CreateStoredProviderRequest as CreateStoredProviderRequest from otari._client.models.create_user_request import CreateUserRequest as CreateUserRequest +from otari._client.models.deployment_bootstrap import DeploymentBootstrap as DeploymentBootstrap from otari._client.models.discoverable_model import DiscoverableModel as DiscoverableModel from otari._client.models.discoverable_models_response import DiscoverableModelsResponse as DiscoverableModelsResponse from otari._client.models.discoverable_provider import DiscoverableProvider as DiscoverableProvider @@ -668,7 +713,8 @@ from otari._client.models.pricing_refresh_preview_response import PricingRefreshPreviewResponse as PricingRefreshPreviewResponse from otari._client.models.pricing_response import PricingResponse as PricingResponse from otari._client.models.pricing_tier import PricingTier as PricingTier -from otari._client.models.pricing_tiers_inner_value import PricingTiersInnerValue as PricingTiersInnerValue +from otari._client.models.pricing_tiers_inner import PricingTiersInner as PricingTiersInner +from otari._client.models.pricing_tiers_inner_any_of_value import PricingTiersInnerAnyOfValue as PricingTiersInnerAnyOfValue from otari._client.models.provider_capabilities_schema import ProviderCapabilitiesSchema as ProviderCapabilitiesSchema from otari._client.models.provider_health_response import ProviderHealthResponse as ProviderHealthResponse from otari._client.models.provider_health_schema import ProviderHealthSchema as ProviderHealthSchema @@ -681,35 +727,45 @@ from otari._client.models.rank_response import RankResponse as RankResponse from otari._client.models.recorded_pool import RecordedPool as RecordedPool from otari._client.models.reencrypt_provider_credentials_response import ReencryptProviderCredentialsResponse as ReencryptProviderCredentialsResponse +from otari._client.models.reencrypt_search_tools_response import ReencryptSearchToolsResponse as ReencryptSearchToolsResponse from otari._client.models.rerank_request import RerankRequest as RerankRequest from otari._client.models.rerank_response import RerankResponse as RerankResponse 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.scored_example import ScoredExample as ScoredExample +from otari._client.models.search_provider_schema import SearchProviderSchema as SearchProviderSchema from otari._client.models.search_request import SearchRequest as SearchRequest from otari._client.models.search_response import SearchResponse as SearchResponse from otari._client.models.search_result_item import SearchResultItem as SearchResultItem +from otari._client.models.search_tools_response import SearchToolsResponse as SearchToolsResponse from otari._client.models.session_response import SessionResponse as SessionResponse from otari._client.models.set_pricing_request import SetPricingRequest as SetPricingRequest from otari._client.models.source import Source as Source from otari._client.models.source1 import Source1 as Source1 from otari._client.models.stop import Stop as Stop from otari._client.models.stored_provider_response import StoredProviderResponse as StoredProviderResponse +from otari._client.models.stored_search_tool_schema import StoredSearchToolSchema as StoredSearchToolSchema from otari._client.models.system import System as System from otari._client.models.task_pool import TaskPool as TaskPool from otari._client.models.test_provider_request import TestProviderRequest as TestProviderRequest from otari._client.models.test_provider_response import TestProviderResponse as TestProviderResponse from otari._client.models.test_service_request import TestServiceRequest as TestServiceRequest from otari._client.models.test_service_response import TestServiceResponse as TestServiceResponse +from otari._client.models.token_charge_line import TokenChargeLine as TokenChargeLine from otari._client.models.tool_calls_inner import ToolCallsInner as ToolCallsInner from otari._client.models.tool_choice import ToolChoice as ToolChoice from otari._client.models.tool_choice1 import ToolChoice1 as ToolChoice1 +from otari._client.models.tool_meter import ToolMeter as ToolMeter from otari._client.models.tool_setting_field import ToolSettingField as ToolSettingField from otari._client.models.tool_settings_response import ToolSettingsResponse as ToolSettingsResponse from otari._client.models.tools_response import ToolsResponse as ToolsResponse +from otari._client.models.unit_charge_line import UnitChargeLine as UnitChargeLine +from otari._client.models.units import Units as Units +from otari._client.models.units1 import Units1 as Units1 from otari._client.models.update_budget_request import UpdateBudgetRequest as UpdateBudgetRequest from otari._client.models.update_key_request import UpdateKeyRequest as UpdateKeyRequest +from otari._client.models.update_search_tool_request import UpdateSearchToolRequest as UpdateSearchToolRequest from otari._client.models.update_settings_request import UpdateSettingsRequest as UpdateSettingsRequest from otari._client.models.update_stored_provider_request import UpdateStoredProviderRequest as UpdateStoredProviderRequest from otari._client.models.update_tool_settings_request import UpdateToolSettingsRequest as UpdateToolSettingsRequest @@ -718,7 +774,7 @@ from otari._client.models.usage_delete_request import UsageDeleteRequest as UsageDeleteRequest from otari._client.models.usage_delete_result import UsageDeleteResult as UsageDeleteResult from otari._client.models.usage_entry import UsageEntry as UsageEntry -from otari._client.models.usage_entry_pricing_breakdown_inner_value import UsageEntryPricingBreakdownInnerValue as UsageEntryPricingBreakdownInnerValue +from otari._client.models.usage_entry_pricing_breakdown_inner import UsageEntryPricingBreakdownInner as UsageEntryPricingBreakdownInner from otari._client.models.usage_error_code_row import UsageErrorCodeRow as UsageErrorCodeRow from otari._client.models.usage_group_row import UsageGroupRow as UsageGroupRow from otari._client.models.usage_grouped_series import UsageGroupedSeries as UsageGroupedSeries diff --git a/src/otari/_client/api/__init__.py b/src/otari/_client/api/__init__.py index 91dc5b6..9eb82d6 100644 --- a/src/otari/_client/api/__init__.py +++ b/src/otari/_client/api/__init__.py @@ -6,6 +6,7 @@ from otari._client.api.audio_api import AudioApi from otari._client.api.auth_api import AuthApi from otari._client.api.batches_api import BatchesApi +from otari._client.api.bootstrap_api import BootstrapApi from otari._client.api.budgets_api import BudgetsApi from otari._client.api.chat_api import ChatApi from otari._client.api.embeddings_api import EmbeddingsApi @@ -23,6 +24,7 @@ from otari._client.api.responses_api import ResponsesApi from otari._client.api.routing_api import RoutingApi from otari._client.api.search_api import SearchApi +from otari._client.api.search_tools_api import SearchToolsApi from otari._client.api.settings_api import SettingsApi from otari._client.api.tool_settings_api import ToolSettingsApi from otari._client.api.tools_api import ToolsApi diff --git a/src/otari/_client/api/agent_telemetry_api.py b/src/otari/_client/api/agent_telemetry_api.py index 653c053..a907a48 100644 --- a/src/otari/_client/api/agent_telemetry_api.py +++ b/src/otari/_client/api/agent_telemetry_api.py @@ -15,8 +15,15 @@ from typing import Any, Dict, List, Optional, Tuple, Union from typing_extensions import Annotated +from datetime import datetime +from pydantic import Field, StrictStr, field_validator +from typing import List, Optional +from typing_extensions import Annotated +from otari._client.models.agent_telemetry_count import AgentTelemetryCount from otari._client.models.agent_telemetry_delete_request import AgentTelemetryDeleteRequest from otari._client.models.agent_telemetry_delete_result import AgentTelemetryDeleteResult +from otari._client.models.agent_telemetry_grouped_series import AgentTelemetryGroupedSeries +from otari._client.models.agent_telemetry_summary import AgentTelemetrySummary from otari._client.api_client import ApiClient, RequestSerialized from otari._client.api_response import ApiResponse @@ -36,6 +43,1122 @@ def __init__(self, api_client=None) -> None: self.api_client = api_client + @validate_call + def agent_telemetry_series_v1_agent_telemetry_series_get( + self, + group_by: Annotated[StrictStr, Field(description="Dimension to split the series by")], + start_date: Annotated[Optional[datetime], Field(description="Return rows with timestamp >= start_date (ISO 8601 or Unix epoch seconds)")] = None, + end_date: Annotated[Optional[datetime], Field(description="Return rows with timestamp < end_date (ISO 8601 or Unix epoch seconds)")] = None, + user_id: Annotated[Optional[Annotated[List[StrictStr], Field(max_length=50)]], Field(description="Filter to one or more users; repeatable (user_id=a&user_id=b). Several values match any of them. 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, + name: Annotated[Optional[StrictStr], Field(description="Filter to a single event type or metric name (e.g. 'tool_result', 'claude_code.commit.count')")] = None, + bucket: Annotated[Optional[StrictStr], Field(description="Time-series granularity: 'hour' or 'day'")] = 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, + ) -> AgentTelemetryGroupedSeries: + """Agent Telemetry Series + + Row volume over time, split by user or API key (standalone). Mirrors `/v1/usage/series`: same window bounds and bucket-grid cap, the top groups as their own series with the remainder folded into a reconciling ``other``, and sparse points (populated cells only). Counts rows, not spend, so it charts telemetry volume rather than cost. Master-key only. + + :param group_by: Dimension to split the series by (required) + :type group_by: str + :param start_date: Return rows with timestamp >= start_date (ISO 8601 or Unix epoch seconds) + :type start_date: datetime + :param end_date: Return rows with timestamp < end_date (ISO 8601 or Unix epoch seconds) + :type end_date: datetime + :param user_id: Filter to one or more users; repeatable (user_id=a&user_id=b). Several values match any of them. At most 50 per call. + :type user_id: 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 name: Filter to a single event type or metric name (e.g. 'tool_result', 'claude_code.commit.count') + :type name: str + :param bucket: Time-series granularity: 'hour' or 'day' + :type bucket: 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._agent_telemetry_series_v1_agent_telemetry_series_get_serialize( + group_by=group_by, + start_date=start_date, + end_date=end_date, + user_id=user_id, + api_key_id=api_key_id, + name=name, + bucket=bucket, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "AgentTelemetryGroupedSeries", + '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 agent_telemetry_series_v1_agent_telemetry_series_get_with_http_info( + self, + group_by: Annotated[StrictStr, Field(description="Dimension to split the series by")], + start_date: Annotated[Optional[datetime], Field(description="Return rows with timestamp >= start_date (ISO 8601 or Unix epoch seconds)")] = None, + end_date: Annotated[Optional[datetime], Field(description="Return rows with timestamp < end_date (ISO 8601 or Unix epoch seconds)")] = None, + user_id: Annotated[Optional[Annotated[List[StrictStr], Field(max_length=50)]], Field(description="Filter to one or more users; repeatable (user_id=a&user_id=b). Several values match any of them. 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, + name: Annotated[Optional[StrictStr], Field(description="Filter to a single event type or metric name (e.g. 'tool_result', 'claude_code.commit.count')")] = None, + bucket: Annotated[Optional[StrictStr], Field(description="Time-series granularity: 'hour' or 'day'")] = 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[AgentTelemetryGroupedSeries]: + """Agent Telemetry Series + + Row volume over time, split by user or API key (standalone). Mirrors `/v1/usage/series`: same window bounds and bucket-grid cap, the top groups as their own series with the remainder folded into a reconciling ``other``, and sparse points (populated cells only). Counts rows, not spend, so it charts telemetry volume rather than cost. Master-key only. + + :param group_by: Dimension to split the series by (required) + :type group_by: str + :param start_date: Return rows with timestamp >= start_date (ISO 8601 or Unix epoch seconds) + :type start_date: datetime + :param end_date: Return rows with timestamp < end_date (ISO 8601 or Unix epoch seconds) + :type end_date: datetime + :param user_id: Filter to one or more users; repeatable (user_id=a&user_id=b). Several values match any of them. At most 50 per call. + :type user_id: 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 name: Filter to a single event type or metric name (e.g. 'tool_result', 'claude_code.commit.count') + :type name: str + :param bucket: Time-series granularity: 'hour' or 'day' + :type bucket: 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._agent_telemetry_series_v1_agent_telemetry_series_get_serialize( + group_by=group_by, + start_date=start_date, + end_date=end_date, + user_id=user_id, + api_key_id=api_key_id, + name=name, + bucket=bucket, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "AgentTelemetryGroupedSeries", + '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 agent_telemetry_series_v1_agent_telemetry_series_get_without_preload_content( + self, + group_by: Annotated[StrictStr, Field(description="Dimension to split the series by")], + start_date: Annotated[Optional[datetime], Field(description="Return rows with timestamp >= start_date (ISO 8601 or Unix epoch seconds)")] = None, + end_date: Annotated[Optional[datetime], Field(description="Return rows with timestamp < end_date (ISO 8601 or Unix epoch seconds)")] = None, + user_id: Annotated[Optional[Annotated[List[StrictStr], Field(max_length=50)]], Field(description="Filter to one or more users; repeatable (user_id=a&user_id=b). Several values match any of them. 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, + name: Annotated[Optional[StrictStr], Field(description="Filter to a single event type or metric name (e.g. 'tool_result', 'claude_code.commit.count')")] = None, + bucket: Annotated[Optional[StrictStr], Field(description="Time-series granularity: 'hour' or 'day'")] = 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: + """Agent Telemetry Series + + Row volume over time, split by user or API key (standalone). Mirrors `/v1/usage/series`: same window bounds and bucket-grid cap, the top groups as their own series with the remainder folded into a reconciling ``other``, and sparse points (populated cells only). Counts rows, not spend, so it charts telemetry volume rather than cost. Master-key only. + + :param group_by: Dimension to split the series by (required) + :type group_by: str + :param start_date: Return rows with timestamp >= start_date (ISO 8601 or Unix epoch seconds) + :type start_date: datetime + :param end_date: Return rows with timestamp < end_date (ISO 8601 or Unix epoch seconds) + :type end_date: datetime + :param user_id: Filter to one or more users; repeatable (user_id=a&user_id=b). Several values match any of them. At most 50 per call. + :type user_id: 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 name: Filter to a single event type or metric name (e.g. 'tool_result', 'claude_code.commit.count') + :type name: str + :param bucket: Time-series granularity: 'hour' or 'day' + :type bucket: 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._agent_telemetry_series_v1_agent_telemetry_series_get_serialize( + group_by=group_by, + start_date=start_date, + end_date=end_date, + user_id=user_id, + api_key_id=api_key_id, + name=name, + bucket=bucket, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "AgentTelemetryGroupedSeries", + '422': "HTTPValidationError", + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + return response_data.response + + + def _agent_telemetry_series_v1_agent_telemetry_series_get_serialize( + self, + group_by, + start_date, + end_date, + user_id, + api_key_id, + name, + bucket, + _request_auth, + _content_type, + _headers, + _host_index, + ) -> RequestSerialized: + + _host = None + + _collection_formats: Dict[str, str] = { + 'user_id': 'multi', + 'api_key_id': 'multi', + } + + _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 group_by is not None: + + _query_params.append(('group_by', group_by)) + + if start_date is not None: + if isinstance(start_date, datetime): + _query_params.append( + ( + 'start_date', + start_date.strftime( + self.api_client.configuration.datetime_format + ) + ) + ) + else: + _query_params.append(('start_date', start_date)) + + if end_date is not None: + if isinstance(end_date, datetime): + _query_params.append( + ( + 'end_date', + end_date.strftime( + self.api_client.configuration.datetime_format + ) + ) + ) + else: + _query_params.append(('end_date', end_date)) + + if user_id is not None: + + _query_params.append(('user_id', user_id)) + + if api_key_id is not None: + + _query_params.append(('api_key_id', api_key_id)) + + if name is not None: + + _query_params.append(('name', name)) + + if bucket is not None: + + _query_params.append(('bucket', bucket)) + + # process the header parameters + # process the form parameters + # process the body parameter + + + # set the HTTP header `Accept` + if 'Accept' not in _header_params: + _header_params['Accept'] = self.api_client.select_header_accept( + [ + 'application/json' + ] + ) + + + # authentication setting + _auth_settings: List[str] = [ + 'XApiKeyAuth', + 'ApiKeyAuth' + ] + + return self.api_client.param_serialize( + method='GET', + resource_path='/v1/agent-telemetry/series', + 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 agent_telemetry_summary_v1_agent_telemetry_summary_get( + self, + start_date: Annotated[Optional[datetime], Field(description="Return rows with timestamp >= start_date (ISO 8601 or Unix epoch seconds)")] = None, + end_date: Annotated[Optional[datetime], Field(description="Return rows with timestamp < end_date (ISO 8601 or Unix epoch seconds)")] = None, + user_id: Annotated[Optional[Annotated[List[StrictStr], Field(max_length=50)]], Field(description="Filter to one or more users; repeatable (user_id=a&user_id=b). Several values match any of them. 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, + session_label: Annotated[Optional[StrictStr], Field(description="Filter to a single agent session. Matches agent_telemetry.session_label and, on the usage side of the join, the usage_logs.source_label that /v1/usage/summary filters on")] = None, + bucket: Annotated[Optional[StrictStr], Field(description="Time-series granularity: 'hour' or 'day'")] = 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, + ) -> AgentTelemetrySummary: + """Agent Telemetry Summary + + What the coding agent produced in a window, and what it cost (standalone). Range-bounded like `/v1/usage/summary` (default last 30 days, hard-capped), so the aggregates stay served by the timestamp index. Returns the outcome totals (commits, pull requests, lines changed, active time), the behavioral counts already captured from the logs signal (tool calls and their mix, tool accept/reject, turns, API errors), the recorded spend over the same scope, and the derived per-unit measures: cost per commit / pull request / line, spend per active hour, acceptance rate, turns per session, and error rate. Each measure is null rather than an error when its denominator is zero. Filterable by user, API key, and `session_label`, so cost per outcome can be read for one agent session as well as for a whole window. The spend side is every usage row in scope, not only the agent's: unfiltered, that includes traffic from clients that never reported telemetry, so a per-outcome measure read over a whole deployment answers \"what did this deployment spend per commit\", not \"what did the agent spend per commit\". Filter by user, API key, or session to divide only the matching spend. Outcome metrics are stored exactly as the agent reported them, so a cumulative counter is converted to a window increment here, at read time, diffed per series generation: a re-exported total adds nothing, and a counter reset never reads as negative work. Master-key only. + + :param start_date: Return rows with timestamp >= start_date (ISO 8601 or Unix epoch seconds) + :type start_date: datetime + :param end_date: Return rows with timestamp < end_date (ISO 8601 or Unix epoch seconds) + :type end_date: datetime + :param user_id: Filter to one or more users; repeatable (user_id=a&user_id=b). Several values match any of them. At most 50 per call. + :type user_id: 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 session_label: Filter to a single agent session. Matches agent_telemetry.session_label and, on the usage side of the join, the usage_logs.source_label that /v1/usage/summary filters on + :type session_label: str + :param bucket: Time-series granularity: 'hour' or 'day' + :type bucket: 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._agent_telemetry_summary_v1_agent_telemetry_summary_get_serialize( + start_date=start_date, + end_date=end_date, + user_id=user_id, + api_key_id=api_key_id, + session_label=session_label, + bucket=bucket, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "AgentTelemetrySummary", + '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 agent_telemetry_summary_v1_agent_telemetry_summary_get_with_http_info( + self, + start_date: Annotated[Optional[datetime], Field(description="Return rows with timestamp >= start_date (ISO 8601 or Unix epoch seconds)")] = None, + end_date: Annotated[Optional[datetime], Field(description="Return rows with timestamp < end_date (ISO 8601 or Unix epoch seconds)")] = None, + user_id: Annotated[Optional[Annotated[List[StrictStr], Field(max_length=50)]], Field(description="Filter to one or more users; repeatable (user_id=a&user_id=b). Several values match any of them. 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, + session_label: Annotated[Optional[StrictStr], Field(description="Filter to a single agent session. Matches agent_telemetry.session_label and, on the usage side of the join, the usage_logs.source_label that /v1/usage/summary filters on")] = None, + bucket: Annotated[Optional[StrictStr], Field(description="Time-series granularity: 'hour' or 'day'")] = 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[AgentTelemetrySummary]: + """Agent Telemetry Summary + + What the coding agent produced in a window, and what it cost (standalone). Range-bounded like `/v1/usage/summary` (default last 30 days, hard-capped), so the aggregates stay served by the timestamp index. Returns the outcome totals (commits, pull requests, lines changed, active time), the behavioral counts already captured from the logs signal (tool calls and their mix, tool accept/reject, turns, API errors), the recorded spend over the same scope, and the derived per-unit measures: cost per commit / pull request / line, spend per active hour, acceptance rate, turns per session, and error rate. Each measure is null rather than an error when its denominator is zero. Filterable by user, API key, and `session_label`, so cost per outcome can be read for one agent session as well as for a whole window. The spend side is every usage row in scope, not only the agent's: unfiltered, that includes traffic from clients that never reported telemetry, so a per-outcome measure read over a whole deployment answers \"what did this deployment spend per commit\", not \"what did the agent spend per commit\". Filter by user, API key, or session to divide only the matching spend. Outcome metrics are stored exactly as the agent reported them, so a cumulative counter is converted to a window increment here, at read time, diffed per series generation: a re-exported total adds nothing, and a counter reset never reads as negative work. Master-key only. + + :param start_date: Return rows with timestamp >= start_date (ISO 8601 or Unix epoch seconds) + :type start_date: datetime + :param end_date: Return rows with timestamp < end_date (ISO 8601 or Unix epoch seconds) + :type end_date: datetime + :param user_id: Filter to one or more users; repeatable (user_id=a&user_id=b). Several values match any of them. At most 50 per call. + :type user_id: 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 session_label: Filter to a single agent session. Matches agent_telemetry.session_label and, on the usage side of the join, the usage_logs.source_label that /v1/usage/summary filters on + :type session_label: str + :param bucket: Time-series granularity: 'hour' or 'day' + :type bucket: 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._agent_telemetry_summary_v1_agent_telemetry_summary_get_serialize( + start_date=start_date, + end_date=end_date, + user_id=user_id, + api_key_id=api_key_id, + session_label=session_label, + bucket=bucket, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "AgentTelemetrySummary", + '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 agent_telemetry_summary_v1_agent_telemetry_summary_get_without_preload_content( + self, + start_date: Annotated[Optional[datetime], Field(description="Return rows with timestamp >= start_date (ISO 8601 or Unix epoch seconds)")] = None, + end_date: Annotated[Optional[datetime], Field(description="Return rows with timestamp < end_date (ISO 8601 or Unix epoch seconds)")] = None, + user_id: Annotated[Optional[Annotated[List[StrictStr], Field(max_length=50)]], Field(description="Filter to one or more users; repeatable (user_id=a&user_id=b). Several values match any of them. 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, + session_label: Annotated[Optional[StrictStr], Field(description="Filter to a single agent session. Matches agent_telemetry.session_label and, on the usage side of the join, the usage_logs.source_label that /v1/usage/summary filters on")] = None, + bucket: Annotated[Optional[StrictStr], Field(description="Time-series granularity: 'hour' or 'day'")] = 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: + """Agent Telemetry Summary + + What the coding agent produced in a window, and what it cost (standalone). Range-bounded like `/v1/usage/summary` (default last 30 days, hard-capped), so the aggregates stay served by the timestamp index. Returns the outcome totals (commits, pull requests, lines changed, active time), the behavioral counts already captured from the logs signal (tool calls and their mix, tool accept/reject, turns, API errors), the recorded spend over the same scope, and the derived per-unit measures: cost per commit / pull request / line, spend per active hour, acceptance rate, turns per session, and error rate. Each measure is null rather than an error when its denominator is zero. Filterable by user, API key, and `session_label`, so cost per outcome can be read for one agent session as well as for a whole window. The spend side is every usage row in scope, not only the agent's: unfiltered, that includes traffic from clients that never reported telemetry, so a per-outcome measure read over a whole deployment answers \"what did this deployment spend per commit\", not \"what did the agent spend per commit\". Filter by user, API key, or session to divide only the matching spend. Outcome metrics are stored exactly as the agent reported them, so a cumulative counter is converted to a window increment here, at read time, diffed per series generation: a re-exported total adds nothing, and a counter reset never reads as negative work. Master-key only. + + :param start_date: Return rows with timestamp >= start_date (ISO 8601 or Unix epoch seconds) + :type start_date: datetime + :param end_date: Return rows with timestamp < end_date (ISO 8601 or Unix epoch seconds) + :type end_date: datetime + :param user_id: Filter to one or more users; repeatable (user_id=a&user_id=b). Several values match any of them. At most 50 per call. + :type user_id: 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 session_label: Filter to a single agent session. Matches agent_telemetry.session_label and, on the usage side of the join, the usage_logs.source_label that /v1/usage/summary filters on + :type session_label: str + :param bucket: Time-series granularity: 'hour' or 'day' + :type bucket: 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._agent_telemetry_summary_v1_agent_telemetry_summary_get_serialize( + start_date=start_date, + end_date=end_date, + user_id=user_id, + api_key_id=api_key_id, + session_label=session_label, + bucket=bucket, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "AgentTelemetrySummary", + '422': "HTTPValidationError", + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + return response_data.response + + + def _agent_telemetry_summary_v1_agent_telemetry_summary_get_serialize( + self, + start_date, + end_date, + user_id, + api_key_id, + session_label, + bucket, + _request_auth, + _content_type, + _headers, + _host_index, + ) -> RequestSerialized: + + _host = None + + _collection_formats: Dict[str, str] = { + 'user_id': 'multi', + 'api_key_id': 'multi', + } + + _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 start_date is not None: + if isinstance(start_date, datetime): + _query_params.append( + ( + 'start_date', + start_date.strftime( + self.api_client.configuration.datetime_format + ) + ) + ) + else: + _query_params.append(('start_date', start_date)) + + if end_date is not None: + if isinstance(end_date, datetime): + _query_params.append( + ( + 'end_date', + end_date.strftime( + self.api_client.configuration.datetime_format + ) + ) + ) + else: + _query_params.append(('end_date', end_date)) + + if user_id is not None: + + _query_params.append(('user_id', user_id)) + + if api_key_id is not None: + + _query_params.append(('api_key_id', api_key_id)) + + if session_label is not None: + + _query_params.append(('session_label', session_label)) + + if bucket is not None: + + _query_params.append(('bucket', bucket)) + + # process the header parameters + # process the form parameters + # process the body parameter + + + # set the HTTP header `Accept` + if 'Accept' not in _header_params: + _header_params['Accept'] = self.api_client.select_header_accept( + [ + 'application/json' + ] + ) + + + # authentication setting + _auth_settings: List[str] = [ + 'XApiKeyAuth', + 'ApiKeyAuth' + ] + + return self.api_client.param_serialize( + method='GET', + resource_path='/v1/agent-telemetry/summary', + 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 count_agent_telemetry_v1_agent_telemetry_count_get( + self, + start_date: Annotated[Optional[datetime], Field(description="Return rows with timestamp >= start_date (ISO 8601 or Unix epoch seconds)")] = None, + end_date: Annotated[Optional[datetime], Field(description="Return rows with timestamp < end_date (ISO 8601 or Unix epoch seconds)")] = None, + user_id: Annotated[Optional[Annotated[List[StrictStr], Field(max_length=50)]], Field(description="Filter to one or more users; repeatable (user_id=a&user_id=b). Several values match any of them. 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, + name: Annotated[Optional[StrictStr], Field(description="Filter to a single event type or metric name (e.g. 'tool_result', 'claude_code.commit.count')")] = 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, + ) -> AgentTelemetryCount: + """Count Agent Telemetry + + Total agent_telemetry rows matching the given filters (standalone). The filter set mirrors the purge endpoint's, so this sizes exactly what a \"delete all N matching\" would remove. Behavioral and metric rows are counted together: neither this nor the purge distinguishes them. Master-key only. + + :param start_date: Return rows with timestamp >= start_date (ISO 8601 or Unix epoch seconds) + :type start_date: datetime + :param end_date: Return rows with timestamp < end_date (ISO 8601 or Unix epoch seconds) + :type end_date: datetime + :param user_id: Filter to one or more users; repeatable (user_id=a&user_id=b). Several values match any of them. At most 50 per call. + :type user_id: 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 name: Filter to a single event type or metric name (e.g. 'tool_result', 'claude_code.commit.count') + :type name: 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._count_agent_telemetry_v1_agent_telemetry_count_get_serialize( + start_date=start_date, + end_date=end_date, + user_id=user_id, + api_key_id=api_key_id, + name=name, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "AgentTelemetryCount", + '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 count_agent_telemetry_v1_agent_telemetry_count_get_with_http_info( + self, + start_date: Annotated[Optional[datetime], Field(description="Return rows with timestamp >= start_date (ISO 8601 or Unix epoch seconds)")] = None, + end_date: Annotated[Optional[datetime], Field(description="Return rows with timestamp < end_date (ISO 8601 or Unix epoch seconds)")] = None, + user_id: Annotated[Optional[Annotated[List[StrictStr], Field(max_length=50)]], Field(description="Filter to one or more users; repeatable (user_id=a&user_id=b). Several values match any of them. 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, + name: Annotated[Optional[StrictStr], Field(description="Filter to a single event type or metric name (e.g. 'tool_result', 'claude_code.commit.count')")] = 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[AgentTelemetryCount]: + """Count Agent Telemetry + + Total agent_telemetry rows matching the given filters (standalone). The filter set mirrors the purge endpoint's, so this sizes exactly what a \"delete all N matching\" would remove. Behavioral and metric rows are counted together: neither this nor the purge distinguishes them. Master-key only. + + :param start_date: Return rows with timestamp >= start_date (ISO 8601 or Unix epoch seconds) + :type start_date: datetime + :param end_date: Return rows with timestamp < end_date (ISO 8601 or Unix epoch seconds) + :type end_date: datetime + :param user_id: Filter to one or more users; repeatable (user_id=a&user_id=b). Several values match any of them. At most 50 per call. + :type user_id: 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 name: Filter to a single event type or metric name (e.g. 'tool_result', 'claude_code.commit.count') + :type name: 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._count_agent_telemetry_v1_agent_telemetry_count_get_serialize( + start_date=start_date, + end_date=end_date, + user_id=user_id, + api_key_id=api_key_id, + name=name, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "AgentTelemetryCount", + '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 count_agent_telemetry_v1_agent_telemetry_count_get_without_preload_content( + self, + start_date: Annotated[Optional[datetime], Field(description="Return rows with timestamp >= start_date (ISO 8601 or Unix epoch seconds)")] = None, + end_date: Annotated[Optional[datetime], Field(description="Return rows with timestamp < end_date (ISO 8601 or Unix epoch seconds)")] = None, + user_id: Annotated[Optional[Annotated[List[StrictStr], Field(max_length=50)]], Field(description="Filter to one or more users; repeatable (user_id=a&user_id=b). Several values match any of them. 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, + name: Annotated[Optional[StrictStr], Field(description="Filter to a single event type or metric name (e.g. 'tool_result', 'claude_code.commit.count')")] = 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: + """Count Agent Telemetry + + Total agent_telemetry rows matching the given filters (standalone). The filter set mirrors the purge endpoint's, so this sizes exactly what a \"delete all N matching\" would remove. Behavioral and metric rows are counted together: neither this nor the purge distinguishes them. Master-key only. + + :param start_date: Return rows with timestamp >= start_date (ISO 8601 or Unix epoch seconds) + :type start_date: datetime + :param end_date: Return rows with timestamp < end_date (ISO 8601 or Unix epoch seconds) + :type end_date: datetime + :param user_id: Filter to one or more users; repeatable (user_id=a&user_id=b). Several values match any of them. At most 50 per call. + :type user_id: 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 name: Filter to a single event type or metric name (e.g. 'tool_result', 'claude_code.commit.count') + :type name: 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._count_agent_telemetry_v1_agent_telemetry_count_get_serialize( + start_date=start_date, + end_date=end_date, + user_id=user_id, + api_key_id=api_key_id, + name=name, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "AgentTelemetryCount", + '422': "HTTPValidationError", + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + return response_data.response + + + def _count_agent_telemetry_v1_agent_telemetry_count_get_serialize( + self, + start_date, + end_date, + user_id, + api_key_id, + name, + _request_auth, + _content_type, + _headers, + _host_index, + ) -> RequestSerialized: + + _host = None + + _collection_formats: Dict[str, str] = { + 'user_id': 'multi', + 'api_key_id': 'multi', + } + + _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 start_date is not None: + if isinstance(start_date, datetime): + _query_params.append( + ( + 'start_date', + start_date.strftime( + self.api_client.configuration.datetime_format + ) + ) + ) + else: + _query_params.append(('start_date', start_date)) + + if end_date is not None: + if isinstance(end_date, datetime): + _query_params.append( + ( + 'end_date', + end_date.strftime( + self.api_client.configuration.datetime_format + ) + ) + ) + else: + _query_params.append(('end_date', end_date)) + + if user_id is not None: + + _query_params.append(('user_id', user_id)) + + if api_key_id is not None: + + _query_params.append(('api_key_id', api_key_id)) + + if name is not None: + + _query_params.append(('name', name)) + + # process the header parameters + # process the form parameters + # process the body parameter + + + # set the HTTP header `Accept` + if 'Accept' not in _header_params: + _header_params['Accept'] = self.api_client.select_header_accept( + [ + 'application/json' + ] + ) + + + # authentication setting + _auth_settings: List[str] = [ + 'XApiKeyAuth', + 'ApiKeyAuth' + ] + + return self.api_client.param_serialize( + method='GET', + resource_path='/v1/agent-telemetry/count', + path_params=_path_params, + query_params=_query_params, + header_params=_header_params, + body=_body_params, + post_params=_form_params, + files=_files, + auth_settings=_auth_settings, + collection_formats=_collection_formats, + _host=_host, + _request_auth=_request_auth + ) + + + + @validate_call def delete_agent_telemetry_rows_v1_agent_telemetry_delete( self, diff --git a/src/otari/_client/api/bootstrap_api.py b/src/otari/_client/api/bootstrap_api.py new file mode 100644 index 0000000..c9de74d --- /dev/null +++ b/src/otari/_client/api/bootstrap_api.py @@ -0,0 +1,280 @@ +""" + 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 otari._client.models.deployment_bootstrap import DeploymentBootstrap + +from otari._client.api_client import ApiClient, RequestSerialized +from otari._client.api_response import ApiResponse +from otari._client.rest import RESTResponseType + + +class BootstrapApi: + """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 get_bootstrap_v1_bootstrap_get( + self, + _request_timeout: Union[ + None, + Annotated[StrictFloat, Field(gt=0)], + Tuple[ + Annotated[StrictFloat, Field(gt=0)], + Annotated[StrictFloat, Field(gt=0)] + ] + ] = None, + _request_auth: Optional[Dict[StrictStr, Any]] = None, + _content_type: Optional[StrictStr] = None, + _headers: Optional[Dict[StrictStr, Any]] = None, + _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, + ) -> DeploymentBootstrap: + """Get Bootstrap + + Return the deployment context the dashboard shell renders from. Public: the shell fetches this before it knows whether it can authenticate. + + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :type _request_timeout: int, tuple(int, int), optional + :param _request_auth: set to override the auth_settings for an a single + request; this effectively ignores the + authentication in the spec for a single request. + :type _request_auth: dict, optional + :param _content_type: force content-type for the request. + :type _content_type: str, Optional + :param _headers: set to override the headers for a single + request; this effectively ignores the headers + in the spec for a single request. + :type _headers: dict, optional + :param _host_index: set to override the host_index for a single + request; this effectively ignores the host_index + in the spec for a single request. + :type _host_index: int, optional + :return: Returns the result object. + """ # noqa: E501 + + _param = self._get_bootstrap_v1_bootstrap_get_serialize( + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "DeploymentBootstrap", + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + response_data.read() + return self.api_client.response_deserialize( + response_data=response_data, + response_types_map=_response_types_map, + ).data + + + @validate_call + def get_bootstrap_v1_bootstrap_get_with_http_info( + self, + _request_timeout: Union[ + None, + Annotated[StrictFloat, Field(gt=0)], + Tuple[ + Annotated[StrictFloat, Field(gt=0)], + Annotated[StrictFloat, Field(gt=0)] + ] + ] = None, + _request_auth: Optional[Dict[StrictStr, Any]] = None, + _content_type: Optional[StrictStr] = None, + _headers: Optional[Dict[StrictStr, Any]] = None, + _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, + ) -> ApiResponse[DeploymentBootstrap]: + """Get Bootstrap + + Return the deployment context the dashboard shell renders from. Public: the shell fetches this before it knows whether it can authenticate. + + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :type _request_timeout: int, tuple(int, int), optional + :param _request_auth: set to override the auth_settings for an a single + request; this effectively ignores the + authentication in the spec for a single request. + :type _request_auth: dict, optional + :param _content_type: force content-type for the request. + :type _content_type: str, Optional + :param _headers: set to override the headers for a single + request; this effectively ignores the headers + in the spec for a single request. + :type _headers: dict, optional + :param _host_index: set to override the host_index for a single + request; this effectively ignores the host_index + in the spec for a single request. + :type _host_index: int, optional + :return: Returns the result object. + """ # noqa: E501 + + _param = self._get_bootstrap_v1_bootstrap_get_serialize( + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "DeploymentBootstrap", + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + response_data.read() + return self.api_client.response_deserialize( + response_data=response_data, + response_types_map=_response_types_map, + ) + + + @validate_call + def get_bootstrap_v1_bootstrap_get_without_preload_content( + self, + _request_timeout: Union[ + None, + Annotated[StrictFloat, Field(gt=0)], + Tuple[ + Annotated[StrictFloat, Field(gt=0)], + Annotated[StrictFloat, Field(gt=0)] + ] + ] = None, + _request_auth: Optional[Dict[StrictStr, Any]] = None, + _content_type: Optional[StrictStr] = None, + _headers: Optional[Dict[StrictStr, Any]] = None, + _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, + ) -> RESTResponseType: + """Get Bootstrap + + Return the deployment context the dashboard shell renders from. Public: the shell fetches this before it knows whether it can authenticate. + + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :type _request_timeout: int, tuple(int, int), optional + :param _request_auth: set to override the auth_settings for an a single + request; this effectively ignores the + authentication in the spec for a single request. + :type _request_auth: dict, optional + :param _content_type: force content-type for the request. + :type _content_type: str, Optional + :param _headers: set to override the headers for a single + request; this effectively ignores the headers + in the spec for a single request. + :type _headers: dict, optional + :param _host_index: set to override the host_index for a single + request; this effectively ignores the host_index + in the spec for a single request. + :type _host_index: int, optional + :return: Returns the result object. + """ # noqa: E501 + + _param = self._get_bootstrap_v1_bootstrap_get_serialize( + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "DeploymentBootstrap", + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + return response_data.response + + + def _get_bootstrap_v1_bootstrap_get_serialize( + self, + _request_auth, + _content_type, + _headers, + _host_index, + ) -> RequestSerialized: + + _host = None + + _collection_formats: Dict[str, str] = { + } + + _path_params: Dict[str, str] = {} + _query_params: List[Tuple[str, str]] = [] + _header_params: Dict[str, Optional[str]] = _headers or {} + _form_params: List[Tuple[str, str]] = [] + _files: Dict[ + str, Union[str, bytes, List[str], List[bytes], List[Tuple[str, bytes]]] + ] = {} + _body_params: Optional[bytes] = None + + # process the path parameters + # process the query parameters + # process the header parameters + # process the form parameters + # process the body parameter + + + # 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] = [ + ] + + return self.api_client.param_serialize( + method='GET', + resource_path='/v1/bootstrap', + path_params=_path_params, + query_params=_query_params, + header_params=_header_params, + body=_body_params, + post_params=_form_params, + files=_files, + auth_settings=_auth_settings, + collection_formats=_collection_formats, + _host=_host, + _request_auth=_request_auth + ) + + diff --git a/src/otari/_client/api/otel_api.py b/src/otari/_client/api/otel_api.py index 0c3a1e8..836cf80 100644 --- a/src/otari/_client/api/otel_api.py +++ b/src/otari/_client/api/otel_api.py @@ -282,6 +282,253 @@ def _receive_logs_v1_logs_post_serialize( + @validate_call + def receive_metrics_v1_metrics_post( + self, + _request_timeout: Union[ + None, + Annotated[StrictFloat, Field(gt=0)], + Tuple[ + Annotated[StrictFloat, Field(gt=0)], + Annotated[StrictFloat, Field(gt=0)] + ] + ] = None, + _request_auth: Optional[Dict[StrictStr, Any]] = None, + _content_type: Optional[StrictStr] = None, + _headers: Optional[Dict[StrictStr, Any]] = None, + _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, + ) -> object: + """Receive Metrics + + Ingest content-free coding-agent outcome metrics from OTLP metric points. Records the outcome counters a coding agent reports on the metrics signal and that Otari has no other source for: lines of code changed, commits, pull requests, and active time. Points are stored exactly as reported, with their OTLP series identity, so a cumulative counter is turned into an increment at read time rather than re-counted on every export. Metrics that duplicate an already-recorded signal (token/cost usage, already billed; edit decisions, already captured as behavioral events) are skipped, as is any metric name this gateway does not know, so a newer agent version never breaks reception. Outcome metrics are never billable: they touch no budget and no spend. Capture answers to the same ``capture_agent_telemetry`` toggle as behavioral events; with it off, the export still succeeds and simply stores nothing. + + :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._receive_metrics_v1_metrics_post_serialize( + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "object", + } + 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 receive_metrics_v1_metrics_post_with_http_info( + self, + _request_timeout: Union[ + None, + Annotated[StrictFloat, Field(gt=0)], + Tuple[ + Annotated[StrictFloat, Field(gt=0)], + Annotated[StrictFloat, Field(gt=0)] + ] + ] = None, + _request_auth: Optional[Dict[StrictStr, Any]] = None, + _content_type: Optional[StrictStr] = None, + _headers: Optional[Dict[StrictStr, Any]] = None, + _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, + ) -> ApiResponse[object]: + """Receive Metrics + + Ingest content-free coding-agent outcome metrics from OTLP metric points. Records the outcome counters a coding agent reports on the metrics signal and that Otari has no other source for: lines of code changed, commits, pull requests, and active time. Points are stored exactly as reported, with their OTLP series identity, so a cumulative counter is turned into an increment at read time rather than re-counted on every export. Metrics that duplicate an already-recorded signal (token/cost usage, already billed; edit decisions, already captured as behavioral events) are skipped, as is any metric name this gateway does not know, so a newer agent version never breaks reception. Outcome metrics are never billable: they touch no budget and no spend. Capture answers to the same ``capture_agent_telemetry`` toggle as behavioral events; with it off, the export still succeeds and simply stores nothing. + + :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._receive_metrics_v1_metrics_post_serialize( + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "object", + } + 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 receive_metrics_v1_metrics_post_without_preload_content( + self, + _request_timeout: Union[ + None, + Annotated[StrictFloat, Field(gt=0)], + Tuple[ + Annotated[StrictFloat, Field(gt=0)], + Annotated[StrictFloat, Field(gt=0)] + ] + ] = None, + _request_auth: Optional[Dict[StrictStr, Any]] = None, + _content_type: Optional[StrictStr] = None, + _headers: Optional[Dict[StrictStr, Any]] = None, + _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, + ) -> RESTResponseType: + """Receive Metrics + + Ingest content-free coding-agent outcome metrics from OTLP metric points. Records the outcome counters a coding agent reports on the metrics signal and that Otari has no other source for: lines of code changed, commits, pull requests, and active time. Points are stored exactly as reported, with their OTLP series identity, so a cumulative counter is turned into an increment at read time rather than re-counted on every export. Metrics that duplicate an already-recorded signal (token/cost usage, already billed; edit decisions, already captured as behavioral events) are skipped, as is any metric name this gateway does not know, so a newer agent version never breaks reception. Outcome metrics are never billable: they touch no budget and no spend. Capture answers to the same ``capture_agent_telemetry`` toggle as behavioral events; with it off, the export still succeeds and simply stores nothing. + + :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._receive_metrics_v1_metrics_post_serialize( + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "object", + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + return response_data.response + + + def _receive_metrics_v1_metrics_post_serialize( + self, + _request_auth, + _content_type, + _headers, + _host_index, + ) -> RequestSerialized: + + _host = None + + _collection_formats: Dict[str, str] = { + } + + _path_params: Dict[str, str] = {} + _query_params: List[Tuple[str, str]] = [] + _header_params: Dict[str, Optional[str]] = _headers or {} + _form_params: List[Tuple[str, str]] = [] + _files: Dict[ + str, Union[str, bytes, List[str], List[bytes], List[Tuple[str, bytes]]] + ] = {} + _body_params: Optional[bytes] = None + + # process the path parameters + # process the query parameters + # process the header parameters + # process the form parameters + # process the body parameter + + + # 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='/v1/metrics', + 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 receive_traces_v1_traces_post( self, diff --git a/src/otari/_client/api/pricing_api.py b/src/otari/_client/api/pricing_api.py index b34269c..4a6bf1c 100644 --- a/src/otari/_client/api/pricing_api.py +++ b/src/otari/_client/api/pricing_api.py @@ -1926,7 +1926,7 @@ def set_pricing_v1_pricing_post( ) -> PricingResponse: """Set Pricing - Set or update pricing for a model. Rejects an alias: pricing, budgets, and usage all key on the resolved target, so a row stored under an alias name would never be read. + Set or update pricing for a model. Rejects an alias or a routing policy: pricing, budgets, and usage all key on the model a request resolves to, so a row stored under either name would never be read. :param set_pricing_request: (required) :type set_pricing_request: SetPricingRequest @@ -1994,7 +1994,7 @@ def set_pricing_v1_pricing_post_with_http_info( ) -> ApiResponse[PricingResponse]: """Set Pricing - Set or update pricing for a model. Rejects an alias: pricing, budgets, and usage all key on the resolved target, so a row stored under an alias name would never be read. + Set or update pricing for a model. Rejects an alias or a routing policy: pricing, budgets, and usage all key on the model a request resolves to, so a row stored under either name would never be read. :param set_pricing_request: (required) :type set_pricing_request: SetPricingRequest @@ -2062,7 +2062,7 @@ def set_pricing_v1_pricing_post_without_preload_content( ) -> RESTResponseType: """Set Pricing - Set or update pricing for a model. Rejects an alias: pricing, budgets, and usage all key on the resolved target, so a row stored under an alias name would never be read. + Set or update pricing for a model. Rejects an alias or a routing policy: pricing, budgets, and usage all key on the model a request resolves to, so a row stored under either name would never be read. :param set_pricing_request: (required) :type set_pricing_request: SetPricingRequest diff --git a/src/otari/_client/api/routing_api.py b/src/otari/_client/api/routing_api.py index 0f07130..adccb44 100644 --- a/src/otari/_client/api/routing_api.py +++ b/src/otari/_client/api/routing_api.py @@ -1415,7 +1415,7 @@ def set_policy_v1_routing_policies_post( ) -> PolicyResponse: """Set Policy - Create or update a stored policy, global or scoped to one user. The spec is validated here and stored as given, so a row can never contain a body this build would refuse at load. The cache is refreshed twice: once before validating (so the shadowing checks see other writers' policies) and once after committing (so this worker serves the new policy immediately). + Create or update a stored policy, global or scoped to one user. The spec is validated here and stored as given, so a row can never contain a body this build would refuse at load. The cache is refreshed twice: once before validating (so the shadowing checks see other writers' policies) and once after committing (so this worker serves the new policy immediately). ``rename_from`` renames the row instead of keying on ``name``. It is part of this write rather than an endpoint of its own so that an edit which both renames a policy and re-targets it cannot land half-applied, leaving the old name serving the new spec. The new name is validated exactly as a fresh one is, because a rename can walk a policy into every collision a create can. Sending the field asserts the named policy is stored, so it never falls back to creating one. :param policy_request: (required) :type policy_request: PolicyRequest @@ -1483,7 +1483,7 @@ def set_policy_v1_routing_policies_post_with_http_info( ) -> ApiResponse[PolicyResponse]: """Set Policy - Create or update a stored policy, global or scoped to one user. The spec is validated here and stored as given, so a row can never contain a body this build would refuse at load. The cache is refreshed twice: once before validating (so the shadowing checks see other writers' policies) and once after committing (so this worker serves the new policy immediately). + Create or update a stored policy, global or scoped to one user. The spec is validated here and stored as given, so a row can never contain a body this build would refuse at load. The cache is refreshed twice: once before validating (so the shadowing checks see other writers' policies) and once after committing (so this worker serves the new policy immediately). ``rename_from`` renames the row instead of keying on ``name``. It is part of this write rather than an endpoint of its own so that an edit which both renames a policy and re-targets it cannot land half-applied, leaving the old name serving the new spec. The new name is validated exactly as a fresh one is, because a rename can walk a policy into every collision a create can. Sending the field asserts the named policy is stored, so it never falls back to creating one. :param policy_request: (required) :type policy_request: PolicyRequest @@ -1551,7 +1551,7 @@ def set_policy_v1_routing_policies_post_without_preload_content( ) -> RESTResponseType: """Set Policy - Create or update a stored policy, global or scoped to one user. The spec is validated here and stored as given, so a row can never contain a body this build would refuse at load. The cache is refreshed twice: once before validating (so the shadowing checks see other writers' policies) and once after committing (so this worker serves the new policy immediately). + Create or update a stored policy, global or scoped to one user. The spec is validated here and stored as given, so a row can never contain a body this build would refuse at load. The cache is refreshed twice: once before validating (so the shadowing checks see other writers' policies) and once after committing (so this worker serves the new policy immediately). ``rename_from`` renames the row instead of keying on ``name``. It is part of this write rather than an endpoint of its own so that an edit which both renames a policy and re-targets it cannot land half-applied, leaving the old name serving the new spec. The new name is validated exactly as a fresh one is, because a rename can walk a policy into every collision a create can. Sending the field asserts the named policy is stored, so it never falls back to creating one. :param policy_request: (required) :type policy_request: PolicyRequest diff --git a/src/otari/_client/api/search_tools_api.py b/src/otari/_client/api/search_tools_api.py new file mode 100644 index 0000000..c4cb11c --- /dev/null +++ b/src/otari/_client/api/search_tools_api.py @@ -0,0 +1,1619 @@ +""" + 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 StrictStr +from typing import List +from otari._client.models.create_search_tool_request import CreateSearchToolRequest +from otari._client.models.reencrypt_search_tools_response import ReencryptSearchToolsResponse +from otari._client.models.search_provider_schema import SearchProviderSchema +from otari._client.models.search_tools_response import SearchToolsResponse +from otari._client.models.stored_search_tool_schema import StoredSearchToolSchema +from otari._client.models.update_search_tool_request import UpdateSearchToolRequest + +from otari._client.api_client import ApiClient, RequestSerialized +from otari._client.api_response import ApiResponse +from otari._client.rest import RESTResponseType + + +class SearchToolsApi: + """NOTE: This class is auto generated by OpenAPI Generator + Ref: https://openapi-generator.tech + + Do not edit the class manually. + """ + + def __init__(self, api_client=None) -> None: + if api_client is None: + api_client = ApiClient.get_default() + self.api_client = api_client + + + @validate_call + def create_search_tool_v1_search_tools_post( + self, + create_search_tool_request: CreateSearchToolRequest, + _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, + ) -> StoredSearchToolSchema: + """Create Search Tool + + Add a search tool at runtime. Storing an API key requires OTARI_SECRET_KEY. + + :param create_search_tool_request: (required) + :type create_search_tool_request: CreateSearchToolRequest + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :type _request_timeout: int, tuple(int, int), optional + :param _request_auth: set to override the auth_settings for an a single + request; this effectively ignores the + authentication in the spec for a single request. + :type _request_auth: dict, optional + :param _content_type: force content-type for the request. + :type _content_type: str, Optional + :param _headers: set to override the headers for a single + request; this effectively ignores the headers + in the spec for a single request. + :type _headers: dict, optional + :param _host_index: set to override the host_index for a single + request; this effectively ignores the host_index + in the spec for a single request. + :type _host_index: int, optional + :return: Returns the result object. + """ # noqa: E501 + + _param = self._create_search_tool_v1_search_tools_post_serialize( + create_search_tool_request=create_search_tool_request, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '201': "StoredSearchToolSchema", + '422': "HTTPValidationError", + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + response_data.read() + return self.api_client.response_deserialize( + response_data=response_data, + response_types_map=_response_types_map, + ).data + + + @validate_call + def create_search_tool_v1_search_tools_post_with_http_info( + self, + create_search_tool_request: CreateSearchToolRequest, + _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[StoredSearchToolSchema]: + """Create Search Tool + + Add a search tool at runtime. Storing an API key requires OTARI_SECRET_KEY. + + :param create_search_tool_request: (required) + :type create_search_tool_request: CreateSearchToolRequest + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :type _request_timeout: int, tuple(int, int), optional + :param _request_auth: set to override the auth_settings for an a single + request; this effectively ignores the + authentication in the spec for a single request. + :type _request_auth: dict, optional + :param _content_type: force content-type for the request. + :type _content_type: str, Optional + :param _headers: set to override the headers for a single + request; this effectively ignores the headers + in the spec for a single request. + :type _headers: dict, optional + :param _host_index: set to override the host_index for a single + request; this effectively ignores the host_index + in the spec for a single request. + :type _host_index: int, optional + :return: Returns the result object. + """ # noqa: E501 + + _param = self._create_search_tool_v1_search_tools_post_serialize( + create_search_tool_request=create_search_tool_request, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '201': "StoredSearchToolSchema", + '422': "HTTPValidationError", + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + response_data.read() + return self.api_client.response_deserialize( + response_data=response_data, + response_types_map=_response_types_map, + ) + + + @validate_call + def create_search_tool_v1_search_tools_post_without_preload_content( + self, + create_search_tool_request: CreateSearchToolRequest, + _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 Search Tool + + Add a search tool at runtime. Storing an API key requires OTARI_SECRET_KEY. + + :param create_search_tool_request: (required) + :type create_search_tool_request: CreateSearchToolRequest + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :type _request_timeout: int, tuple(int, int), optional + :param _request_auth: set to override the auth_settings for an a single + request; this effectively ignores the + authentication in the spec for a single request. + :type _request_auth: dict, optional + :param _content_type: force content-type for the request. + :type _content_type: str, Optional + :param _headers: set to override the headers for a single + request; this effectively ignores the headers + in the spec for a single request. + :type _headers: dict, optional + :param _host_index: set to override the host_index for a single + request; this effectively ignores the host_index + in the spec for a single request. + :type _host_index: int, optional + :return: Returns the result object. + """ # noqa: E501 + + _param = self._create_search_tool_v1_search_tools_post_serialize( + create_search_tool_request=create_search_tool_request, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '201': "StoredSearchToolSchema", + '422': "HTTPValidationError", + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + return response_data.response + + + def _create_search_tool_v1_search_tools_post_serialize( + self, + create_search_tool_request, + _request_auth, + _content_type, + _headers, + _host_index, + ) -> RequestSerialized: + + _host = None + + _collection_formats: Dict[str, str] = { + } + + _path_params: Dict[str, str] = {} + _query_params: List[Tuple[str, str]] = [] + _header_params: Dict[str, Optional[str]] = _headers or {} + _form_params: List[Tuple[str, str]] = [] + _files: Dict[ + str, Union[str, bytes, List[str], List[bytes], List[Tuple[str, bytes]]] + ] = {} + _body_params: Optional[bytes] = None + + # process the path parameters + # process the query parameters + # process the header parameters + # process the form parameters + # process the body parameter + if create_search_tool_request is not None: + _body_params = create_search_tool_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='/v1/search-tools', + path_params=_path_params, + query_params=_query_params, + header_params=_header_params, + body=_body_params, + post_params=_form_params, + files=_files, + auth_settings=_auth_settings, + collection_formats=_collection_formats, + _host=_host, + _request_auth=_request_auth + ) + + + + + @validate_call + def delete_stored_search_tool_v1_search_tools_name_delete( + self, + name: 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, + ) -> None: + """Delete Stored Search Tool + + Delete a stored search tool. A config-file search tool cannot be deleted here. + + :param name: (required) + :type name: 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._delete_stored_search_tool_v1_search_tools_name_delete_serialize( + name=name, + _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 delete_stored_search_tool_v1_search_tools_name_delete_with_http_info( + self, + name: 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[None]: + """Delete Stored Search Tool + + Delete a stored search tool. A config-file search tool cannot be deleted here. + + :param name: (required) + :type name: 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._delete_stored_search_tool_v1_search_tools_name_delete_serialize( + name=name, + _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 delete_stored_search_tool_v1_search_tools_name_delete_without_preload_content( + self, + name: 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: + """Delete Stored Search Tool + + Delete a stored search tool. A config-file search tool cannot be deleted here. + + :param name: (required) + :type name: 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._delete_stored_search_tool_v1_search_tools_name_delete_serialize( + name=name, + _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 _delete_stored_search_tool_v1_search_tools_name_delete_serialize( + self, + name, + _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 name is not None: + _path_params['name'] = name + # process the query parameters + # process the header parameters + # process the form parameters + # process the body parameter + + + # set the HTTP header `Accept` + if 'Accept' not in _header_params: + _header_params['Accept'] = self.api_client.select_header_accept( + [ + 'application/json' + ] + ) + + + # authentication setting + _auth_settings: List[str] = [ + 'XApiKeyAuth', + 'ApiKeyAuth' + ] + + return self.api_client.param_serialize( + method='DELETE', + resource_path='/v1/search-tools/{name}', + path_params=_path_params, + query_params=_query_params, + header_params=_header_params, + body=_body_params, + post_params=_form_params, + files=_files, + auth_settings=_auth_settings, + collection_formats=_collection_formats, + _host=_host, + _request_auth=_request_auth + ) + + + + + @validate_call + def list_all_search_tools_v1_search_tools_get( + self, + _request_timeout: Union[ + None, + Annotated[StrictFloat, Field(gt=0)], + Tuple[ + Annotated[StrictFloat, Field(gt=0)], + Annotated[StrictFloat, Field(gt=0)] + ] + ] = None, + _request_auth: Optional[Dict[StrictStr, Any]] = None, + _content_type: Optional[StrictStr] = None, + _headers: Optional[Dict[StrictStr, Any]] = None, + _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, + ) -> SearchToolsResponse: + """List All Search Tools + + List every search tool ``POST /v1/search`` can name. ``stored`` are the editable rows written through this API; ``config`` are the config-file entries, which are still honored and are reported so the operator can see the whole set. Keys are never returned, only ``last4``. + + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :type _request_timeout: int, tuple(int, int), optional + :param _request_auth: set to override the auth_settings for an a single + request; this effectively ignores the + authentication in the spec for a single request. + :type _request_auth: dict, optional + :param _content_type: force content-type for the request. + :type _content_type: str, Optional + :param _headers: set to override the headers for a single + request; this effectively ignores the headers + in the spec for a single request. + :type _headers: dict, optional + :param _host_index: set to override the host_index for a single + request; this effectively ignores the host_index + in the spec for a single request. + :type _host_index: int, optional + :return: Returns the result object. + """ # noqa: E501 + + _param = self._list_all_search_tools_v1_search_tools_get_serialize( + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "SearchToolsResponse", + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + response_data.read() + return self.api_client.response_deserialize( + response_data=response_data, + response_types_map=_response_types_map, + ).data + + + @validate_call + def list_all_search_tools_v1_search_tools_get_with_http_info( + self, + _request_timeout: Union[ + None, + Annotated[StrictFloat, Field(gt=0)], + Tuple[ + Annotated[StrictFloat, Field(gt=0)], + Annotated[StrictFloat, Field(gt=0)] + ] + ] = None, + _request_auth: Optional[Dict[StrictStr, Any]] = None, + _content_type: Optional[StrictStr] = None, + _headers: Optional[Dict[StrictStr, Any]] = None, + _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, + ) -> ApiResponse[SearchToolsResponse]: + """List All Search Tools + + List every search tool ``POST /v1/search`` can name. ``stored`` are the editable rows written through this API; ``config`` are the config-file entries, which are still honored and are reported so the operator can see the whole set. Keys are never returned, only ``last4``. + + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :type _request_timeout: int, tuple(int, int), optional + :param _request_auth: set to override the auth_settings for an a single + request; this effectively ignores the + authentication in the spec for a single request. + :type _request_auth: dict, optional + :param _content_type: force content-type for the request. + :type _content_type: str, Optional + :param _headers: set to override the headers for a single + request; this effectively ignores the headers + in the spec for a single request. + :type _headers: dict, optional + :param _host_index: set to override the host_index for a single + request; this effectively ignores the host_index + in the spec for a single request. + :type _host_index: int, optional + :return: Returns the result object. + """ # noqa: E501 + + _param = self._list_all_search_tools_v1_search_tools_get_serialize( + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "SearchToolsResponse", + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + response_data.read() + return self.api_client.response_deserialize( + response_data=response_data, + response_types_map=_response_types_map, + ) + + + @validate_call + def list_all_search_tools_v1_search_tools_get_without_preload_content( + self, + _request_timeout: Union[ + None, + Annotated[StrictFloat, Field(gt=0)], + Tuple[ + Annotated[StrictFloat, Field(gt=0)], + Annotated[StrictFloat, Field(gt=0)] + ] + ] = None, + _request_auth: Optional[Dict[StrictStr, Any]] = None, + _content_type: Optional[StrictStr] = None, + _headers: Optional[Dict[StrictStr, Any]] = None, + _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, + ) -> RESTResponseType: + """List All Search Tools + + List every search tool ``POST /v1/search`` can name. ``stored`` are the editable rows written through this API; ``config`` are the config-file entries, which are still honored and are reported so the operator can see the whole set. Keys are never returned, only ``last4``. + + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :type _request_timeout: int, tuple(int, int), optional + :param _request_auth: set to override the auth_settings for an a single + request; this effectively ignores the + authentication in the spec for a single request. + :type _request_auth: dict, optional + :param _content_type: force content-type for the request. + :type _content_type: str, Optional + :param _headers: set to override the headers for a single + request; this effectively ignores the headers + in the spec for a single request. + :type _headers: dict, optional + :param _host_index: set to override the host_index for a single + request; this effectively ignores the host_index + in the spec for a single request. + :type _host_index: int, optional + :return: Returns the result object. + """ # noqa: E501 + + _param = self._list_all_search_tools_v1_search_tools_get_serialize( + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "SearchToolsResponse", + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + return response_data.response + + + def _list_all_search_tools_v1_search_tools_get_serialize( + self, + _request_auth, + _content_type, + _headers, + _host_index, + ) -> RequestSerialized: + + _host = None + + _collection_formats: Dict[str, str] = { + } + + _path_params: Dict[str, str] = {} + _query_params: List[Tuple[str, str]] = [] + _header_params: Dict[str, Optional[str]] = _headers or {} + _form_params: List[Tuple[str, str]] = [] + _files: Dict[ + str, Union[str, bytes, List[str], List[bytes], List[Tuple[str, bytes]]] + ] = {} + _body_params: Optional[bytes] = None + + # process the path parameters + # process the query parameters + # process the header parameters + # process the form parameters + # process the body parameter + + + # set the HTTP header `Accept` + if 'Accept' not in _header_params: + _header_params['Accept'] = self.api_client.select_header_accept( + [ + 'application/json' + ] + ) + + + # authentication setting + _auth_settings: List[str] = [ + 'XApiKeyAuth', + 'ApiKeyAuth' + ] + + return self.api_client.param_serialize( + method='GET', + resource_path='/v1/search-tools', + path_params=_path_params, + query_params=_query_params, + header_params=_header_params, + body=_body_params, + post_params=_form_params, + files=_files, + auth_settings=_auth_settings, + collection_formats=_collection_formats, + _host=_host, + _request_auth=_request_auth + ) + + + + + @validate_call + def list_search_providers_v1_search_tools_providers_get( + self, + _request_timeout: Union[ + None, + Annotated[StrictFloat, Field(gt=0)], + Tuple[ + Annotated[StrictFloat, Field(gt=0)], + Annotated[StrictFloat, Field(gt=0)] + ] + ] = None, + _request_auth: Optional[Dict[StrictStr, Any]] = None, + _content_type: Optional[StrictStr] = None, + _headers: Optional[Dict[StrictStr, Any]] = None, + _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, + ) -> List[SearchProviderSchema]: + """List Search Providers + + List the search providers this build can dispatch to, for the add-tool form. Reports per provider whether an API key is required and what endpoint a tool inherits when it declares none, so the form can ask for exactly what the chosen provider needs instead of taking a free-text provider name. + + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :type _request_timeout: int, tuple(int, int), optional + :param _request_auth: set to override the auth_settings for an a single + request; this effectively ignores the + authentication in the spec for a single request. + :type _request_auth: dict, optional + :param _content_type: force content-type for the request. + :type _content_type: str, Optional + :param _headers: set to override the headers for a single + request; this effectively ignores the headers + in the spec for a single request. + :type _headers: dict, optional + :param _host_index: set to override the host_index for a single + request; this effectively ignores the host_index + in the spec for a single request. + :type _host_index: int, optional + :return: Returns the result object. + """ # noqa: E501 + + _param = self._list_search_providers_v1_search_tools_providers_get_serialize( + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "List[SearchProviderSchema]", + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + response_data.read() + return self.api_client.response_deserialize( + response_data=response_data, + response_types_map=_response_types_map, + ).data + + + @validate_call + def list_search_providers_v1_search_tools_providers_get_with_http_info( + self, + _request_timeout: Union[ + None, + Annotated[StrictFloat, Field(gt=0)], + Tuple[ + Annotated[StrictFloat, Field(gt=0)], + Annotated[StrictFloat, Field(gt=0)] + ] + ] = None, + _request_auth: Optional[Dict[StrictStr, Any]] = None, + _content_type: Optional[StrictStr] = None, + _headers: Optional[Dict[StrictStr, Any]] = None, + _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, + ) -> ApiResponse[List[SearchProviderSchema]]: + """List Search Providers + + List the search providers this build can dispatch to, for the add-tool form. Reports per provider whether an API key is required and what endpoint a tool inherits when it declares none, so the form can ask for exactly what the chosen provider needs instead of taking a free-text provider name. + + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :type _request_timeout: int, tuple(int, int), optional + :param _request_auth: set to override the auth_settings for an a single + request; this effectively ignores the + authentication in the spec for a single request. + :type _request_auth: dict, optional + :param _content_type: force content-type for the request. + :type _content_type: str, Optional + :param _headers: set to override the headers for a single + request; this effectively ignores the headers + in the spec for a single request. + :type _headers: dict, optional + :param _host_index: set to override the host_index for a single + request; this effectively ignores the host_index + in the spec for a single request. + :type _host_index: int, optional + :return: Returns the result object. + """ # noqa: E501 + + _param = self._list_search_providers_v1_search_tools_providers_get_serialize( + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "List[SearchProviderSchema]", + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + response_data.read() + return self.api_client.response_deserialize( + response_data=response_data, + response_types_map=_response_types_map, + ) + + + @validate_call + def list_search_providers_v1_search_tools_providers_get_without_preload_content( + self, + _request_timeout: Union[ + None, + Annotated[StrictFloat, Field(gt=0)], + Tuple[ + Annotated[StrictFloat, Field(gt=0)], + Annotated[StrictFloat, Field(gt=0)] + ] + ] = None, + _request_auth: Optional[Dict[StrictStr, Any]] = None, + _content_type: Optional[StrictStr] = None, + _headers: Optional[Dict[StrictStr, Any]] = None, + _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, + ) -> RESTResponseType: + """List Search Providers + + List the search providers this build can dispatch to, for the add-tool form. Reports per provider whether an API key is required and what endpoint a tool inherits when it declares none, so the form can ask for exactly what the chosen provider needs instead of taking a free-text provider name. + + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :type _request_timeout: int, tuple(int, int), optional + :param _request_auth: set to override the auth_settings for an a single + request; this effectively ignores the + authentication in the spec for a single request. + :type _request_auth: dict, optional + :param _content_type: force content-type for the request. + :type _content_type: str, Optional + :param _headers: set to override the headers for a single + request; this effectively ignores the headers + in the spec for a single request. + :type _headers: dict, optional + :param _host_index: set to override the host_index for a single + request; this effectively ignores the host_index + in the spec for a single request. + :type _host_index: int, optional + :return: Returns the result object. + """ # noqa: E501 + + _param = self._list_search_providers_v1_search_tools_providers_get_serialize( + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "List[SearchProviderSchema]", + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + return response_data.response + + + def _list_search_providers_v1_search_tools_providers_get_serialize( + self, + _request_auth, + _content_type, + _headers, + _host_index, + ) -> RequestSerialized: + + _host = None + + _collection_formats: Dict[str, str] = { + } + + _path_params: Dict[str, str] = {} + _query_params: List[Tuple[str, str]] = [] + _header_params: Dict[str, Optional[str]] = _headers or {} + _form_params: List[Tuple[str, str]] = [] + _files: Dict[ + str, Union[str, bytes, List[str], List[bytes], List[Tuple[str, bytes]]] + ] = {} + _body_params: Optional[bytes] = None + + # process the path parameters + # process the query parameters + # process the header parameters + # process the form parameters + # process the body parameter + + + # set the HTTP header `Accept` + if 'Accept' not in _header_params: + _header_params['Accept'] = self.api_client.select_header_accept( + [ + 'application/json' + ] + ) + + + # authentication setting + _auth_settings: List[str] = [ + 'XApiKeyAuth', + 'ApiKeyAuth' + ] + + return self.api_client.param_serialize( + method='GET', + resource_path='/v1/search-tools/providers', + 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 reencrypt_stored_search_tool_keys_v1_search_tools_reencrypt_post( + self, + _request_timeout: Union[ + None, + Annotated[StrictFloat, Field(gt=0)], + Tuple[ + Annotated[StrictFloat, Field(gt=0)], + Annotated[StrictFloat, Field(gt=0)] + ] + ] = None, + _request_auth: Optional[Dict[StrictStr, Any]] = None, + _content_type: Optional[StrictStr] = None, + _headers: Optional[Dict[StrictStr, Any]] = None, + _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, + ) -> ReencryptSearchToolsResponse: + """Reencrypt Stored Search Tool Keys + + Re-encrypt stored search-tool keys with the primary OTARI_SECRET_KEY. The search-tool half of the ``OTARI_SECRET_KEY`` rotation procedure; run it alongside ``POST /v1/provider-credentials/reencrypt``. Rows that cannot be decrypted are left untouched and must be recovered by replacing the affected tool's key. + + :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._reencrypt_stored_search_tool_keys_v1_search_tools_reencrypt_post_serialize( + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "ReencryptSearchToolsResponse", + } + 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 reencrypt_stored_search_tool_keys_v1_search_tools_reencrypt_post_with_http_info( + self, + _request_timeout: Union[ + None, + Annotated[StrictFloat, Field(gt=0)], + Tuple[ + Annotated[StrictFloat, Field(gt=0)], + Annotated[StrictFloat, Field(gt=0)] + ] + ] = None, + _request_auth: Optional[Dict[StrictStr, Any]] = None, + _content_type: Optional[StrictStr] = None, + _headers: Optional[Dict[StrictStr, Any]] = None, + _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, + ) -> ApiResponse[ReencryptSearchToolsResponse]: + """Reencrypt Stored Search Tool Keys + + Re-encrypt stored search-tool keys with the primary OTARI_SECRET_KEY. The search-tool half of the ``OTARI_SECRET_KEY`` rotation procedure; run it alongside ``POST /v1/provider-credentials/reencrypt``. Rows that cannot be decrypted are left untouched and must be recovered by replacing the affected tool's key. + + :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._reencrypt_stored_search_tool_keys_v1_search_tools_reencrypt_post_serialize( + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "ReencryptSearchToolsResponse", + } + 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 reencrypt_stored_search_tool_keys_v1_search_tools_reencrypt_post_without_preload_content( + self, + _request_timeout: Union[ + None, + Annotated[StrictFloat, Field(gt=0)], + Tuple[ + Annotated[StrictFloat, Field(gt=0)], + Annotated[StrictFloat, Field(gt=0)] + ] + ] = None, + _request_auth: Optional[Dict[StrictStr, Any]] = None, + _content_type: Optional[StrictStr] = None, + _headers: Optional[Dict[StrictStr, Any]] = None, + _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, + ) -> RESTResponseType: + """Reencrypt Stored Search Tool Keys + + Re-encrypt stored search-tool keys with the primary OTARI_SECRET_KEY. The search-tool half of the ``OTARI_SECRET_KEY`` rotation procedure; run it alongside ``POST /v1/provider-credentials/reencrypt``. Rows that cannot be decrypted are left untouched and must be recovered by replacing the affected tool's key. + + :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._reencrypt_stored_search_tool_keys_v1_search_tools_reencrypt_post_serialize( + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "ReencryptSearchToolsResponse", + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + return response_data.response + + + def _reencrypt_stored_search_tool_keys_v1_search_tools_reencrypt_post_serialize( + self, + _request_auth, + _content_type, + _headers, + _host_index, + ) -> RequestSerialized: + + _host = None + + _collection_formats: Dict[str, str] = { + } + + _path_params: Dict[str, str] = {} + _query_params: List[Tuple[str, str]] = [] + _header_params: Dict[str, Optional[str]] = _headers or {} + _form_params: List[Tuple[str, str]] = [] + _files: Dict[ + str, Union[str, bytes, List[str], List[bytes], List[Tuple[str, bytes]]] + ] = {} + _body_params: Optional[bytes] = None + + # process the path parameters + # process the query parameters + # process the header parameters + # process the form parameters + # process the body parameter + + + # 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='/v1/search-tools/reencrypt', + path_params=_path_params, + query_params=_query_params, + header_params=_header_params, + body=_body_params, + post_params=_form_params, + files=_files, + auth_settings=_auth_settings, + collection_formats=_collection_formats, + _host=_host, + _request_auth=_request_auth + ) + + + + + @validate_call + def update_search_tool_v1_search_tools_name_patch( + self, + name: StrictStr, + update_search_tool_request: UpdateSearchToolRequest, + _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, + ) -> StoredSearchToolSchema: + """Update Search Tool + + Update a stored search tool. Omitted fields are left as-is; an explicit ``null`` clears them. ``api_key`` follows the same rule: omit it to keep the stored key, send a new one to rotate, or send ``null`` to clear it (a keyless SearXNG backend). The row is locked ``FOR UPDATE`` so the ``expected_updated_at`` check and the write it guards are atomic. The tool as it will be after the update is validated, so a change that would leave it unusable (clearing the key of a provider that needs one) is refused rather than stored. + + :param name: (required) + :type name: str + :param update_search_tool_request: (required) + :type update_search_tool_request: UpdateSearchToolRequest + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :type _request_timeout: int, tuple(int, int), optional + :param _request_auth: set to override the auth_settings for an a single + request; this effectively ignores the + authentication in the spec for a single request. + :type _request_auth: dict, optional + :param _content_type: force content-type for the request. + :type _content_type: str, Optional + :param _headers: set to override the headers for a single + request; this effectively ignores the headers + in the spec for a single request. + :type _headers: dict, optional + :param _host_index: set to override the host_index for a single + request; this effectively ignores the host_index + in the spec for a single request. + :type _host_index: int, optional + :return: Returns the result object. + """ # noqa: E501 + + _param = self._update_search_tool_v1_search_tools_name_patch_serialize( + name=name, + update_search_tool_request=update_search_tool_request, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "StoredSearchToolSchema", + '422': "HTTPValidationError", + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + response_data.read() + return self.api_client.response_deserialize( + response_data=response_data, + response_types_map=_response_types_map, + ).data + + + @validate_call + def update_search_tool_v1_search_tools_name_patch_with_http_info( + self, + name: StrictStr, + update_search_tool_request: UpdateSearchToolRequest, + _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[StoredSearchToolSchema]: + """Update Search Tool + + Update a stored search tool. Omitted fields are left as-is; an explicit ``null`` clears them. ``api_key`` follows the same rule: omit it to keep the stored key, send a new one to rotate, or send ``null`` to clear it (a keyless SearXNG backend). The row is locked ``FOR UPDATE`` so the ``expected_updated_at`` check and the write it guards are atomic. The tool as it will be after the update is validated, so a change that would leave it unusable (clearing the key of a provider that needs one) is refused rather than stored. + + :param name: (required) + :type name: str + :param update_search_tool_request: (required) + :type update_search_tool_request: UpdateSearchToolRequest + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :type _request_timeout: int, tuple(int, int), optional + :param _request_auth: set to override the auth_settings for an a single + request; this effectively ignores the + authentication in the spec for a single request. + :type _request_auth: dict, optional + :param _content_type: force content-type for the request. + :type _content_type: str, Optional + :param _headers: set to override the headers for a single + request; this effectively ignores the headers + in the spec for a single request. + :type _headers: dict, optional + :param _host_index: set to override the host_index for a single + request; this effectively ignores the host_index + in the spec for a single request. + :type _host_index: int, optional + :return: Returns the result object. + """ # noqa: E501 + + _param = self._update_search_tool_v1_search_tools_name_patch_serialize( + name=name, + update_search_tool_request=update_search_tool_request, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "StoredSearchToolSchema", + '422': "HTTPValidationError", + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + response_data.read() + return self.api_client.response_deserialize( + response_data=response_data, + response_types_map=_response_types_map, + ) + + + @validate_call + def update_search_tool_v1_search_tools_name_patch_without_preload_content( + self, + name: StrictStr, + update_search_tool_request: UpdateSearchToolRequest, + _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 Search Tool + + Update a stored search tool. Omitted fields are left as-is; an explicit ``null`` clears them. ``api_key`` follows the same rule: omit it to keep the stored key, send a new one to rotate, or send ``null`` to clear it (a keyless SearXNG backend). The row is locked ``FOR UPDATE`` so the ``expected_updated_at`` check and the write it guards are atomic. The tool as it will be after the update is validated, so a change that would leave it unusable (clearing the key of a provider that needs one) is refused rather than stored. + + :param name: (required) + :type name: str + :param update_search_tool_request: (required) + :type update_search_tool_request: UpdateSearchToolRequest + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :type _request_timeout: int, tuple(int, int), optional + :param _request_auth: set to override the auth_settings for an a single + request; this effectively ignores the + authentication in the spec for a single request. + :type _request_auth: dict, optional + :param _content_type: force content-type for the request. + :type _content_type: str, Optional + :param _headers: set to override the headers for a single + request; this effectively ignores the headers + in the spec for a single request. + :type _headers: dict, optional + :param _host_index: set to override the host_index for a single + request; this effectively ignores the host_index + in the spec for a single request. + :type _host_index: int, optional + :return: Returns the result object. + """ # noqa: E501 + + _param = self._update_search_tool_v1_search_tools_name_patch_serialize( + name=name, + update_search_tool_request=update_search_tool_request, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "StoredSearchToolSchema", + '422': "HTTPValidationError", + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + return response_data.response + + + def _update_search_tool_v1_search_tools_name_patch_serialize( + self, + name, + update_search_tool_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 name is not None: + _path_params['name'] = name + # process the query parameters + # process the header parameters + # process the form parameters + # process the body parameter + if update_search_tool_request is not None: + _body_params = update_search_tool_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='/v1/search-tools/{name}', + 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 6fc6f33..fc432e9 100644 --- a/src/otari/_client/models/__init__.py +++ b/src/otari/_client/models/__init__.py @@ -13,14 +13,26 @@ """ # noqa: E501 # import models into model package +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 from otari._client.models.agent_telemetry_delete_result import AgentTelemetryDeleteResult +from otari._client.models.agent_telemetry_group_row import AgentTelemetryGroupRow +from otari._client.models.agent_telemetry_grouped_series import AgentTelemetryGroupedSeries +from otari._client.models.agent_telemetry_grouped_series_point import AgentTelemetryGroupedSeriesPoint +from otari._client.models.agent_telemetry_measures import AgentTelemetryMeasures +from otari._client.models.agent_telemetry_outcomes import AgentTelemetryOutcomes +from otari._client.models.agent_telemetry_series_point import AgentTelemetrySeriesPoint +from otari._client.models.agent_telemetry_summary import AgentTelemetrySummary +from otari._client.models.agent_telemetry_tool_row import AgentTelemetryToolRow +from otari._client.models.agent_telemetry_usage import AgentTelemetryUsage from otari._client.models.alias_request import AliasRequest from otari._client.models.alias_response import AliasResponse from otari._client.models.api_key_id import ApiKeyId from otari._client.models.applied_edits_inner import AppliedEditsInner from otari._client.models.audio_speech_request import AudioSpeechRequest from otari._client.models.batch_request_item import BatchRequestItem +from otari._client.models.billing_meters import BillingMeters from otari._client.models.budget_reset_log_response import BudgetResetLogResponse from otari._client.models.budget_response import BudgetResponse from otari._client.models.cc_chat_completion_audio import CCChatCompletionAudio @@ -58,6 +70,7 @@ from otari._client.models.chat_completion_request_tools_inner import ChatCompletionRequestToolsInner from otari._client.models.chat_message_input import ChatMessageInput from otari._client.models.config_field import ConfigField +from otari._client.models.config_search_tool_schema import ConfigSearchToolSchema from otari._client.models.content import Content from otari._client.models.content1 import Content1 from otari._client.models.content10 import Content10 @@ -85,9 +98,11 @@ from otari._client.models.create_embedding_response import CreateEmbeddingResponse from otari._client.models.create_key_request import CreateKeyRequest from otari._client.models.create_key_response import CreateKeyResponse +from otari._client.models.create_search_tool_request import CreateSearchToolRequest from otari._client.models.create_session_request import CreateSessionRequest from otari._client.models.create_stored_provider_request import CreateStoredProviderRequest from otari._client.models.create_user_request import CreateUserRequest +from otari._client.models.deployment_bootstrap import DeploymentBootstrap from otari._client.models.discoverable_model import DiscoverableModel from otari._client.models.discoverable_models_response import DiscoverableModelsResponse from otari._client.models.discoverable_provider import DiscoverableProvider @@ -265,7 +280,8 @@ from otari._client.models.pricing_refresh_preview_response import PricingRefreshPreviewResponse from otari._client.models.pricing_response import PricingResponse from otari._client.models.pricing_tier import PricingTier -from otari._client.models.pricing_tiers_inner_value import PricingTiersInnerValue +from otari._client.models.pricing_tiers_inner import PricingTiersInner +from otari._client.models.pricing_tiers_inner_any_of_value import PricingTiersInnerAnyOfValue from otari._client.models.provider_capabilities_schema import ProviderCapabilitiesSchema from otari._client.models.provider_health_response import ProviderHealthResponse from otari._client.models.provider_health_schema import ProviderHealthSchema @@ -278,35 +294,45 @@ from otari._client.models.rank_response import RankResponse from otari._client.models.recorded_pool import RecordedPool from otari._client.models.reencrypt_provider_credentials_response import ReencryptProviderCredentialsResponse +from otari._client.models.reencrypt_search_tools_response import ReencryptSearchToolsResponse from otari._client.models.rerank_request import RerankRequest from otari._client.models.rerank_response import RerankResponse 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.scored_example import ScoredExample +from otari._client.models.search_provider_schema import SearchProviderSchema from otari._client.models.search_request import SearchRequest from otari._client.models.search_response import SearchResponse from otari._client.models.search_result_item import SearchResultItem +from otari._client.models.search_tools_response import SearchToolsResponse from otari._client.models.session_response import SessionResponse from otari._client.models.set_pricing_request import SetPricingRequest from otari._client.models.source import Source from otari._client.models.source1 import Source1 from otari._client.models.stop import Stop from otari._client.models.stored_provider_response import StoredProviderResponse +from otari._client.models.stored_search_tool_schema import StoredSearchToolSchema from otari._client.models.system import System from otari._client.models.task_pool import TaskPool from otari._client.models.test_provider_request import TestProviderRequest from otari._client.models.test_provider_response import TestProviderResponse from otari._client.models.test_service_request import TestServiceRequest from otari._client.models.test_service_response import TestServiceResponse +from otari._client.models.token_charge_line import TokenChargeLine from otari._client.models.tool_calls_inner import ToolCallsInner from otari._client.models.tool_choice import ToolChoice from otari._client.models.tool_choice1 import ToolChoice1 +from otari._client.models.tool_meter import ToolMeter from otari._client.models.tool_setting_field import ToolSettingField from otari._client.models.tool_settings_response import ToolSettingsResponse from otari._client.models.tools_response import ToolsResponse +from otari._client.models.unit_charge_line import UnitChargeLine +from otari._client.models.units import Units +from otari._client.models.units1 import Units1 from otari._client.models.update_budget_request import UpdateBudgetRequest from otari._client.models.update_key_request import UpdateKeyRequest +from otari._client.models.update_search_tool_request import UpdateSearchToolRequest from otari._client.models.update_settings_request import UpdateSettingsRequest from otari._client.models.update_stored_provider_request import UpdateStoredProviderRequest from otari._client.models.update_tool_settings_request import UpdateToolSettingsRequest @@ -315,7 +341,7 @@ from otari._client.models.usage_delete_request import UsageDeleteRequest from otari._client.models.usage_delete_result import UsageDeleteResult from otari._client.models.usage_entry import UsageEntry -from otari._client.models.usage_entry_pricing_breakdown_inner_value import UsageEntryPricingBreakdownInnerValue +from otari._client.models.usage_entry_pricing_breakdown_inner import UsageEntryPricingBreakdownInner from otari._client.models.usage_error_code_row import UsageErrorCodeRow from otari._client.models.usage_group_row import UsageGroupRow from otari._client.models.usage_grouped_series import UsageGroupedSeries diff --git a/src/otari/_client/models/agent_telemetry_behavior.py b/src/otari/_client/models/agent_telemetry_behavior.py new file mode 100644 index 0000000..221e2f7 --- /dev/null +++ b/src/otari/_client/models/agent_telemetry_behavior.py @@ -0,0 +1,108 @@ +# 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, Optional +from otari._client.models.agent_telemetry_tool_row import AgentTelemetryToolRow +from typing import Optional, Set +from typing_extensions import Self +from pydantic_core import to_jsonable_python + +class AgentTelemetryBehavior(BaseModel): + """ + Counts from the behavioral events already captured on the logs signal. + """ # noqa: E501 + api_errors: Optional[StrictInt] = 0 + by_tool: Optional[List[AgentTelemetryToolRow]] = None + sessions: Optional[StrictInt] = 0 + tool_accepts: Optional[StrictInt] = 0 + tool_calls: Optional[StrictInt] = 0 + tool_rejects: Optional[StrictInt] = 0 + turns: Optional[StrictInt] = 0 + __properties: ClassVar[List[str]] = ["api_errors", "by_tool", "sessions", "tool_accepts", "tool_calls", "tool_rejects", "turns"] + + 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 AgentTelemetryBehavior 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 by_tool (list) + _items = [] + if self.by_tool: + for _item_by_tool in self.by_tool: + if _item_by_tool: + _items.append(_item_by_tool.to_dict()) + _dict['by_tool'] = _items + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of AgentTelemetryBehavior from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "api_errors": obj.get("api_errors") if obj.get("api_errors") is not None else 0, + "by_tool": [AgentTelemetryToolRow.from_dict(_item) for _item in obj["by_tool"]] if obj.get("by_tool") is not None else None, + "sessions": obj.get("sessions") if obj.get("sessions") is not None else 0, + "tool_accepts": obj.get("tool_accepts") if obj.get("tool_accepts") is not None else 0, + "tool_calls": obj.get("tool_calls") if obj.get("tool_calls") is not None else 0, + "tool_rejects": obj.get("tool_rejects") if obj.get("tool_rejects") is not None else 0, + "turns": obj.get("turns") if obj.get("turns") is not None else 0 + }) + return _obj + + diff --git a/src/otari/_client/models/agent_telemetry_count.py b/src/otari/_client/models/agent_telemetry_count.py new file mode 100644 index 0000000..b07da91 --- /dev/null +++ b/src/otari/_client/models/agent_telemetry_count.py @@ -0,0 +1,88 @@ +# coding: utf-8 + +""" + otari + + Otari, an OpenAI-compatible LLM gateway with API key management + + The version of the OpenAPI document: 0.0.0-dev + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +from __future__ import annotations +import pprint +import re # noqa: F401 +import json + +from pydantic import BaseModel, ConfigDict, StrictInt +from typing import Any, ClassVar, Dict, List +from typing import Optional, Set +from typing_extensions import Self +from pydantic_core import to_jsonable_python + +class AgentTelemetryCount(BaseModel): + """ + Total number of agent_telemetry rows matching a set of filters. + """ # noqa: E501 + total: StrictInt + __properties: ClassVar[List[str]] = ["total"] + + 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 AgentTelemetryCount 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 AgentTelemetryCount from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "total": obj.get("total") + }) + return _obj + + diff --git a/src/otari/_client/models/agent_telemetry_group_row.py b/src/otari/_client/models/agent_telemetry_group_row.py new file mode 100644 index 0000000..db05bbd --- /dev/null +++ b/src/otari/_client/models/agent_telemetry_group_row.py @@ -0,0 +1,97 @@ +# coding: utf-8 + +""" + otari + + Otari, an OpenAI-compatible LLM gateway with API key management + + The version of the OpenAPI document: 0.0.0-dev + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +from __future__ import annotations +import pprint +import re # noqa: F401 +import json + +from pydantic import BaseModel, ConfigDict, StrictBool, StrictInt, StrictStr +from typing import Any, ClassVar, Dict, List, Optional +from typing import Optional, Set +from typing_extensions import Self +from pydantic_core import to_jsonable_python + +class AgentTelemetryGroupRow(BaseModel): + """ + One group of a grouped series. ``key`` is null for the ``other`` fold and for a real group whose column is NULL (e.g. a since-deleted user); ``is_other`` separates the two. + """ # noqa: E501 + is_other: Optional[StrictBool] = False + key: Optional[StrictStr] + rows: StrictInt + __properties: ClassVar[List[str]] = ["is_other", "key", "rows"] + + 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 AgentTelemetryGroupRow 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 key (nullable) is None + # and model_fields_set contains the field + if self.key is None and "key" in self.model_fields_set: + _dict['key'] = None + + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of AgentTelemetryGroupRow from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "is_other": obj.get("is_other") if obj.get("is_other") is not None else False, + "key": obj.get("key"), + "rows": obj.get("rows") + }) + return _obj + + diff --git a/src/otari/_client/models/agent_telemetry_grouped_series.py b/src/otari/_client/models/agent_telemetry_grouped_series.py new file mode 100644 index 0000000..cfb81e9 --- /dev/null +++ b/src/otari/_client/models/agent_telemetry_grouped_series.py @@ -0,0 +1,128 @@ +# 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, StrictStr, field_validator +from typing import Any, ClassVar, Dict, List +from otari._client.models.agent_telemetry_group_row import AgentTelemetryGroupRow +from otari._client.models.agent_telemetry_grouped_series_point import AgentTelemetryGroupedSeriesPoint +from typing import Optional, Set +from typing_extensions import Self +from pydantic_core import to_jsonable_python + +class AgentTelemetryGroupedSeries(BaseModel): + """ + A per-group row-volume series, for stacked charting. + """ # noqa: E501 + bucket: StrictStr + end_date: StrictStr + group_by: StrictStr + groups: List[AgentTelemetryGroupRow] + points: List[AgentTelemetryGroupedSeriesPoint] + start_date: StrictStr + __properties: ClassVar[List[str]] = ["bucket", "end_date", "group_by", "groups", "points", "start_date"] + + @field_validator('bucket') + def bucket_validate_enum(cls, value): + """Validates the enum""" + if value not in set(['hour', 'day']): + raise ValueError("must be one of enum values ('hour', 'day')") + return value + + @field_validator('group_by') + def group_by_validate_enum(cls, value): + """Validates the enum""" + if value not in set(['user_id', 'api_key_id']): + raise ValueError("must be one of enum values ('user_id', 'api_key_id')") + return value + + 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 AgentTelemetryGroupedSeries 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 groups (list) + _items = [] + if self.groups: + for _item_groups in self.groups: + if _item_groups: + _items.append(_item_groups.to_dict()) + _dict['groups'] = _items + # override the default output from pydantic by calling `to_dict()` of each item in points (list) + _items = [] + if self.points: + for _item_points in self.points: + if _item_points: + _items.append(_item_points.to_dict()) + _dict['points'] = _items + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of AgentTelemetryGroupedSeries from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "bucket": obj.get("bucket"), + "end_date": obj.get("end_date"), + "group_by": obj.get("group_by"), + "groups": [AgentTelemetryGroupRow.from_dict(_item) for _item in obj["groups"]] if obj.get("groups") is not None else None, + "points": [AgentTelemetryGroupedSeriesPoint.from_dict(_item) for _item in obj["points"]] if obj.get("points") is not None else None, + "start_date": obj.get("start_date") + }) + return _obj + + diff --git a/src/otari/_client/models/agent_telemetry_grouped_series_point.py b/src/otari/_client/models/agent_telemetry_grouped_series_point.py new file mode 100644 index 0000000..85c5be7 --- /dev/null +++ b/src/otari/_client/models/agent_telemetry_grouped_series_point.py @@ -0,0 +1,99 @@ +# coding: utf-8 + +""" + otari + + Otari, an OpenAI-compatible LLM gateway with API key management + + The version of the OpenAPI document: 0.0.0-dev + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +from __future__ import annotations +import pprint +import re # noqa: F401 +import json + +from pydantic import BaseModel, ConfigDict, StrictBool, StrictInt, StrictStr +from typing import Any, ClassVar, Dict, List, Optional +from typing import Optional, Set +from typing_extensions import Self +from pydantic_core import to_jsonable_python + +class AgentTelemetryGroupedSeriesPoint(BaseModel): + """ + One (bucket, group) cell: how many rows that group recorded in that bucket. + """ # noqa: E501 + bucket_start: StrictStr + is_other: Optional[StrictBool] = False + key: Optional[StrictStr] + rows: StrictInt + __properties: ClassVar[List[str]] = ["bucket_start", "is_other", "key", "rows"] + + 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 AgentTelemetryGroupedSeriesPoint 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 key (nullable) is None + # and model_fields_set contains the field + if self.key is None and "key" in self.model_fields_set: + _dict['key'] = None + + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of AgentTelemetryGroupedSeriesPoint from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "bucket_start": obj.get("bucket_start"), + "is_other": obj.get("is_other") if obj.get("is_other") is not None else False, + "key": obj.get("key"), + "rows": obj.get("rows") + }) + return _obj + + diff --git a/src/otari/_client/models/agent_telemetry_measures.py b/src/otari/_client/models/agent_telemetry_measures.py new file mode 100644 index 0000000..663e1f9 --- /dev/null +++ b/src/otari/_client/models/agent_telemetry_measures.py @@ -0,0 +1,142 @@ +# 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, StrictFloat, StrictInt +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 AgentTelemetryMeasures(BaseModel): + """ + Cost and quality per unit of work. Each is null when its denominator is zero. ``edit_acceptance_rate`` and ``tool_acceptance_rate`` are the same quantity today, both derived from the ``tool_decision`` event: the agent's own ``code_edit_tool.decision`` metric is deliberately never stored, since ``tool_decision`` already carries that accept/reject signal. Both names are reported so a caller reading either vocabulary gets the right number. + """ # noqa: E501 + cost_per_commit: Optional[Union[StrictFloat, StrictInt]] = None + cost_per_line: Optional[Union[StrictFloat, StrictInt]] = None + cost_per_pull_request: Optional[Union[StrictFloat, StrictInt]] = None + edit_acceptance_rate: Optional[Union[StrictFloat, StrictInt]] = None + error_rate: Optional[Union[StrictFloat, StrictInt]] = None + spend_per_active_hour: Optional[Union[StrictFloat, StrictInt]] = None + tool_acceptance_rate: Optional[Union[StrictFloat, StrictInt]] = None + turns_per_session: Optional[Union[StrictFloat, StrictInt]] = None + __properties: ClassVar[List[str]] = ["cost_per_commit", "cost_per_line", "cost_per_pull_request", "edit_acceptance_rate", "error_rate", "spend_per_active_hour", "tool_acceptance_rate", "turns_per_session"] + + 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 AgentTelemetryMeasures 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 cost_per_commit (nullable) is None + # and model_fields_set contains the field + if self.cost_per_commit is None and "cost_per_commit" in self.model_fields_set: + _dict['cost_per_commit'] = None + + # set to None if cost_per_line (nullable) is None + # and model_fields_set contains the field + if self.cost_per_line is None and "cost_per_line" in self.model_fields_set: + _dict['cost_per_line'] = None + + # set to None if cost_per_pull_request (nullable) is None + # and model_fields_set contains the field + if self.cost_per_pull_request is None and "cost_per_pull_request" in self.model_fields_set: + _dict['cost_per_pull_request'] = None + + # set to None if edit_acceptance_rate (nullable) is None + # and model_fields_set contains the field + if self.edit_acceptance_rate is None and "edit_acceptance_rate" in self.model_fields_set: + _dict['edit_acceptance_rate'] = None + + # set to None if error_rate (nullable) is None + # and model_fields_set contains the field + if self.error_rate is None and "error_rate" in self.model_fields_set: + _dict['error_rate'] = None + + # set to None if spend_per_active_hour (nullable) is None + # and model_fields_set contains the field + if self.spend_per_active_hour is None and "spend_per_active_hour" in self.model_fields_set: + _dict['spend_per_active_hour'] = None + + # set to None if tool_acceptance_rate (nullable) is None + # and model_fields_set contains the field + if self.tool_acceptance_rate is None and "tool_acceptance_rate" in self.model_fields_set: + _dict['tool_acceptance_rate'] = None + + # set to None if turns_per_session (nullable) is None + # and model_fields_set contains the field + if self.turns_per_session is None and "turns_per_session" in self.model_fields_set: + _dict['turns_per_session'] = None + + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of AgentTelemetryMeasures from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "cost_per_commit": obj.get("cost_per_commit"), + "cost_per_line": obj.get("cost_per_line"), + "cost_per_pull_request": obj.get("cost_per_pull_request"), + "edit_acceptance_rate": obj.get("edit_acceptance_rate"), + "error_rate": obj.get("error_rate"), + "spend_per_active_hour": obj.get("spend_per_active_hour"), + "tool_acceptance_rate": obj.get("tool_acceptance_rate"), + "turns_per_session": obj.get("turns_per_session") + }) + return _obj + + diff --git a/src/otari/_client/models/agent_telemetry_outcomes.py b/src/otari/_client/models/agent_telemetry_outcomes.py new file mode 100644 index 0000000..d526d15 --- /dev/null +++ b/src/otari/_client/models/agent_telemetry_outcomes.py @@ -0,0 +1,94 @@ +# 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, StrictFloat, StrictInt +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 AgentTelemetryOutcomes(BaseModel): + """ + How much work the agent produced inside the window. Each value is the read-time increment for its metric: a delta series is summed, a cumulative one is diffed per series generation, so a counter that is re-reported in full on every export is never counted twice. ``lines_of_code`` sums the added and removed series, which are stored separately. ``active_time`` is in seconds, as the agent reports it. + """ # noqa: E501 + active_time: Optional[Union[StrictFloat, StrictInt]] = 0.0 + commits: Optional[Union[StrictFloat, StrictInt]] = 0.0 + lines_of_code: Optional[Union[StrictFloat, StrictInt]] = 0.0 + pull_requests: Optional[Union[StrictFloat, StrictInt]] = 0.0 + __properties: ClassVar[List[str]] = ["active_time", "commits", "lines_of_code", "pull_requests"] + + 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 AgentTelemetryOutcomes 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 AgentTelemetryOutcomes from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "active_time": obj.get("active_time") if obj.get("active_time") is not None else 0.0, + "commits": obj.get("commits") if obj.get("commits") is not None else 0.0, + "lines_of_code": obj.get("lines_of_code") if obj.get("lines_of_code") is not None else 0.0, + "pull_requests": obj.get("pull_requests") if obj.get("pull_requests") is not None else 0.0 + }) + return _obj + + diff --git a/src/otari/_client/models/agent_telemetry_series_point.py b/src/otari/_client/models/agent_telemetry_series_point.py new file mode 100644 index 0000000..8ce6c75 --- /dev/null +++ b/src/otari/_client/models/agent_telemetry_series_point.py @@ -0,0 +1,104 @@ +# 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, 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 AgentTelemetrySeriesPoint(BaseModel): + """ + One UTC time bucket of outcomes, behavior, and the spend beside them. A cumulative series' increment is attributed to the bucket of the later point of each consecutive pair, so a bucket reports the growth observed inside it. + """ # noqa: E501 + active_time: Optional[Union[StrictFloat, StrictInt]] = 0.0 + api_errors: Optional[StrictInt] = 0 + bucket_start: StrictStr + commits: Optional[Union[StrictFloat, StrictInt]] = 0.0 + cost: Optional[Union[StrictFloat, StrictInt]] = 0.0 + lines_of_code: Optional[Union[StrictFloat, StrictInt]] = 0.0 + pull_requests: Optional[Union[StrictFloat, StrictInt]] = 0.0 + tool_calls: Optional[StrictInt] = 0 + turns: Optional[StrictInt] = 0 + __properties: ClassVar[List[str]] = ["active_time", "api_errors", "bucket_start", "commits", "cost", "lines_of_code", "pull_requests", "tool_calls", "turns"] + + 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 AgentTelemetrySeriesPoint 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 AgentTelemetrySeriesPoint from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "active_time": obj.get("active_time") if obj.get("active_time") is not None else 0.0, + "api_errors": obj.get("api_errors") if obj.get("api_errors") is not None else 0, + "bucket_start": obj.get("bucket_start"), + "commits": obj.get("commits") if obj.get("commits") is not None else 0.0, + "cost": obj.get("cost") if obj.get("cost") is not None else 0.0, + "lines_of_code": obj.get("lines_of_code") if obj.get("lines_of_code") is not None else 0.0, + "pull_requests": obj.get("pull_requests") if obj.get("pull_requests") is not None else 0.0, + "tool_calls": obj.get("tool_calls") if obj.get("tool_calls") is not None else 0, + "turns": obj.get("turns") if obj.get("turns") is not None else 0 + }) + return _obj + + diff --git a/src/otari/_client/models/agent_telemetry_summary.py b/src/otari/_client/models/agent_telemetry_summary.py new file mode 100644 index 0000000..4f5f95f --- /dev/null +++ b/src/otari/_client/models/agent_telemetry_summary.py @@ -0,0 +1,133 @@ +# 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, StrictStr, field_validator +from typing import Any, ClassVar, Dict, List +from otari._client.models.agent_telemetry_behavior import AgentTelemetryBehavior +from otari._client.models.agent_telemetry_measures import AgentTelemetryMeasures +from otari._client.models.agent_telemetry_outcomes import AgentTelemetryOutcomes +from otari._client.models.agent_telemetry_series_point import AgentTelemetrySeriesPoint +from otari._client.models.agent_telemetry_usage import AgentTelemetryUsage +from typing import Optional, Set +from typing_extensions import Self +from pydantic_core import to_jsonable_python + +class AgentTelemetrySummary(BaseModel): + """ + Agent outcomes and behavior for the window, joined against recorded spend. + """ # noqa: E501 + behavior: AgentTelemetryBehavior + bucket: StrictStr + end_date: StrictStr + measures: AgentTelemetryMeasures + outcomes: AgentTelemetryOutcomes + series: List[AgentTelemetrySeriesPoint] + start_date: StrictStr + usage: AgentTelemetryUsage + __properties: ClassVar[List[str]] = ["behavior", "bucket", "end_date", "measures", "outcomes", "series", "start_date", "usage"] + + @field_validator('bucket') + def bucket_validate_enum(cls, value): + """Validates the enum""" + if value not in set(['hour', 'day']): + raise ValueError("must be one of enum values ('hour', 'day')") + return value + + 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 AgentTelemetrySummary 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 behavior + if self.behavior: + _dict['behavior'] = self.behavior.to_dict() + # override the default output from pydantic by calling `to_dict()` of measures + if self.measures: + _dict['measures'] = self.measures.to_dict() + # override the default output from pydantic by calling `to_dict()` of outcomes + if self.outcomes: + _dict['outcomes'] = self.outcomes.to_dict() + # override the default output from pydantic by calling `to_dict()` of each item in series (list) + _items = [] + if self.series: + for _item_series in self.series: + if _item_series: + _items.append(_item_series.to_dict()) + _dict['series'] = _items + # override the default output from pydantic by calling `to_dict()` of usage + if self.usage: + _dict['usage'] = self.usage.to_dict() + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of AgentTelemetrySummary from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "behavior": AgentTelemetryBehavior.from_dict(obj["behavior"]) if obj.get("behavior") is not None else None, + "bucket": obj.get("bucket"), + "end_date": obj.get("end_date"), + "measures": AgentTelemetryMeasures.from_dict(obj["measures"]) if obj.get("measures") is not None else None, + "outcomes": AgentTelemetryOutcomes.from_dict(obj["outcomes"]) if obj.get("outcomes") is not None else None, + "series": [AgentTelemetrySeriesPoint.from_dict(_item) for _item in obj["series"]] if obj.get("series") is not None else None, + "start_date": obj.get("start_date"), + "usage": AgentTelemetryUsage.from_dict(obj["usage"]) if obj.get("usage") is not None else None + }) + return _obj + + diff --git a/src/otari/_client/models/agent_telemetry_tool_row.py b/src/otari/_client/models/agent_telemetry_tool_row.py new file mode 100644 index 0000000..a2ff6e8 --- /dev/null +++ b/src/otari/_client/models/agent_telemetry_tool_row.py @@ -0,0 +1,95 @@ +# 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, StrictStr +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 AgentTelemetryToolRow(BaseModel): + """ + Tool call volume for one tool. ``tool`` is null for a call with no name. + """ # noqa: E501 + calls: StrictInt + tool: Optional[StrictStr] + __properties: ClassVar[List[str]] = ["calls", "tool"] + + 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 AgentTelemetryToolRow 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 tool (nullable) is None + # and model_fields_set contains the field + if self.tool is None and "tool" in self.model_fields_set: + _dict['tool'] = None + + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of AgentTelemetryToolRow from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "calls": obj.get("calls"), + "tool": obj.get("tool") + }) + return _obj + + diff --git a/src/otari/_client/models/agent_telemetry_usage.py b/src/otari/_client/models/agent_telemetry_usage.py new file mode 100644 index 0000000..e3ac45f --- /dev/null +++ b/src/otari/_client/models/agent_telemetry_usage.py @@ -0,0 +1,90 @@ +# 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, StrictFloat, StrictInt +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 AgentTelemetryUsage(BaseModel): + """ + The recorded spend the measures below divide, reported so they can be checked. + """ # noqa: E501 + cost: Optional[Union[StrictFloat, StrictInt]] = 0.0 + requests: Optional[StrictInt] = 0 + __properties: ClassVar[List[str]] = ["cost", "requests"] + + 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 AgentTelemetryUsage 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 AgentTelemetryUsage from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "cost": obj.get("cost") if obj.get("cost") is not None else 0.0, + "requests": obj.get("requests") if obj.get("requests") is not None else 0 + }) + return _obj + + diff --git a/src/otari/_client/models/billing_meters.py b/src/otari/_client/models/billing_meters.py new file mode 100644 index 0000000..116ee73 --- /dev/null +++ b/src/otari/_client/models/billing_meters.py @@ -0,0 +1,143 @@ +# 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 +from inspect import getfullargspec +import json +import pprint +import re # noqa: F401 +from pydantic import BaseModel, ConfigDict, Field, StrictStr, ValidationError, field_validator +from typing import Any, Dict, Optional +from typing import Union, Any, List, Set, TYPE_CHECKING, Optional, Dict +from typing_extensions import Literal, Self +from pydantic import Field + +BILLINGMETERS_ANY_OF_SCHEMAS = ["BillingMeters", "Dict[str, object]"] + +class BillingMeters(BaseModel): + """ + BillingMeters + """ + + # 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').") + if TYPE_CHECKING: + actual_instance: Optional[Union[BillingMeters, Dict[str, object]]] = None + else: + actual_instance: Any = None + any_of_schemas: Set[str] = { "BillingMeters", "Dict[str, object]" } + + model_config = { + "validate_assignment": True, + "protected_namespaces": (), + } + + def __init__(self, *args, **kwargs) -> None: + if args: + if len(args) > 1: + raise ValueError("If a position argument is used, only 1 is allowed to set `actual_instance`") + if kwargs: + raise ValueError("If a position argument is used, keyword arguments cannot be used.") + super().__init__(actual_instance=args[0]) + else: + super().__init__(**kwargs) + + @field_validator('actual_instance') + def actual_instance_must_validate_anyof(cls, v): + if v is None: + return v + + instance = BillingMeters.model_construct() + error_messages = [] + # validate data type: BillingMeters + if not isinstance(v, BillingMeters): + error_messages.append(f"Error! Input type `{type(v)}` is not `BillingMeters`") + else: + return v + + # validate data type: Dict[str, object] + try: + instance.anyof_schema_2_validator = v + return v + except (ValidationError, ValueError) as e: + error_messages.append(str(e)) + if error_messages: + # no match + raise ValueError("No match found when setting the actual_instance in BillingMeters with anyOf schemas: BillingMeters, Dict[str, object]. Details: " + ", ".join(error_messages)) + else: + return v + + @classmethod + def from_dict(cls, obj: Dict[str, Any]) -> Self: + return cls.from_json(json.dumps(obj)) + + @classmethod + def from_json(cls, json_str: str) -> Self: + """Returns the object represented by the json string""" + instance = cls.model_construct() + if json_str is None: + return instance + + error_messages = [] + # anyof_schema_1_validator: Optional[BillingMeters] = None + try: + instance.actual_instance = BillingMeters.from_json(json_str) + return instance + except (ValidationError, ValueError) as e: + error_messages.append(str(e)) + # deserialize data into Dict[str, object] + try: + # validation + instance.anyof_schema_2_validator = json.loads(json_str) + # assign value to actual_instance + instance.actual_instance = instance.anyof_schema_2_validator + return instance + except (ValidationError, ValueError) as e: + error_messages.append(str(e)) + + if error_messages: + # no match + raise ValueError("No match found when deserializing the JSON string into BillingMeters with anyOf schemas: BillingMeters, Dict[str, object]. Details: " + ", ".join(error_messages)) + else: + return instance + + def to_json(self) -> str: + """Returns the JSON representation of the actual instance""" + if self.actual_instance is None: + return "null" + + if hasattr(self.actual_instance, "to_json") and callable(self.actual_instance.to_json): + return self.actual_instance.to_json() + else: + return json.dumps(self.actual_instance) + + def to_dict(self) -> Optional[Union[Dict[str, Any], BillingMeters, Dict[str, object]]]: + """Returns the dict representation of the actual instance""" + if self.actual_instance is None: + return None + + if hasattr(self.actual_instance, "to_dict") and callable(self.actual_instance.to_dict): + return self.actual_instance.to_dict() + else: + return self.actual_instance + + def to_str(self) -> str: + """Returns the string representation of the actual instance""" + return pprint.pformat(self.model_dump()) + +# TODO: Rewrite to not use raise_errors +BillingMeters.model_rebuild(raise_errors=False) + diff --git a/src/otari/_client/models/cc_chat_completion_message.py b/src/otari/_client/models/cc_chat_completion_message.py index b63c3ff..877fd26 100644 --- a/src/otari/_client/models/cc_chat_completion_message.py +++ b/src/otari/_client/models/cc_chat_completion_message.py @@ -37,8 +37,8 @@ class CCChatCompletionMessage(BaseModel): audio: Optional[CCChatCompletionAudio] = None function_call: Optional[CCFunctionCall] = None tool_calls: Optional[List[CCChatCompletionMessageToolCallsInner]] = None - reasoning: Optional[StrictStr] = Field(default=None, description="Delete the alias scoped to this user. Omit to delete the global alias of that name.") - extra_content: Optional[Dict[str, Any]] = Field(default=None, description="An unsaved policy body to explain.") + 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').") additional_properties: Dict[str, Any] = {} __properties: ClassVar[List[str]] = ["content", "refusal", "role", "annotations", "audio", "function_call", "tool_calls", "reasoning", "extra_content"] diff --git a/src/otari/_client/models/cck_choice_delta.py b/src/otari/_client/models/cck_choice_delta.py index 7828fd2..c7b8152 100644 --- a/src/otari/_client/models/cck_choice_delta.py +++ b/src/otari/_client/models/cck_choice_delta.py @@ -34,7 +34,7 @@ class CCKChoiceDelta(BaseModel): refusal: Optional[StrictStr] = None role: Optional[StrictStr] = None tool_calls: Optional[List[CCKChoiceDeltaToolCall]] = None - reasoning: Optional[StrictStr] = Field(default=None, description="Delete the alias scoped to this user. Omit to delete the global alias of that name.") + 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]] = None additional_properties: Dict[str, Any] = {} __properties: ClassVar[List[str]] = ["content", "function_call", "refusal", "role", "tool_calls", "reasoning", "extra_content"] diff --git a/src/otari/_client/models/cck_choice_delta_function_call.py b/src/otari/_client/models/cck_choice_delta_function_call.py index 0fe4bc7..6a33735 100644 --- a/src/otari/_client/models/cck_choice_delta_function_call.py +++ b/src/otari/_client/models/cck_choice_delta_function_call.py @@ -27,7 +27,7 @@ class CCKChoiceDeltaFunctionCall(BaseModel): """ Deprecated and replaced by `tool_calls`. The name and arguments of a function that should be called, as generated by the model. """ # noqa: E501 - arguments: Optional[StrictStr] = Field(default=None, description="Delete the alias scoped to this user. Omit to delete the global alias of that name.") + arguments: Optional[StrictStr] = Field(default=None, description="Filter to a single event type or metric name (e.g. 'tool_result', 'claude_code.commit.count')") name: Optional[StrictStr] = None additional_properties: Dict[str, Any] = {} __properties: ClassVar[List[str]] = ["arguments", "name"] diff --git a/src/otari/_client/models/chat_completion.py b/src/otari/_client/models/chat_completion.py index 9769072..7ed29ca 100644 --- a/src/otari/_client/models/chat_completion.py +++ b/src/otari/_client/models/chat_completion.py @@ -35,7 +35,7 @@ class ChatCompletion(BaseModel): model: StrictStr object: StrictStr service_tier: Optional[StrictStr] = None - system_fingerprint: Optional[StrictStr] = Field(default=None, description="Delete the alias scoped to this user. Omit to delete the global alias of that name.") + system_fingerprint: Optional[StrictStr] = Field(default=None, description="Filter to a single event type or metric name (e.g. 'tool_result', 'claude_code.commit.count')") usage: Optional[CCCompletionUsage] = None additional_properties: Dict[str, Any] = {} __properties: ClassVar[List[str]] = ["id", "choices", "created", "model", "object", "service_tier", "system_fingerprint", "usage"] diff --git a/src/otari/_client/models/chat_completion_request.py b/src/otari/_client/models/chat_completion_request.py index 68df619..129522c 100644 --- a/src/otari/_client/models/chat_completion_request.py +++ b/src/otari/_client/models/chat_completion_request.py @@ -33,7 +33,7 @@ class ChatCompletionRequest(BaseModel): """ - OpenAI-compatible chat completion request. The completion-param fields are derived from any-llm's ``CompletionParams`` (see ``_schema_derive``) so the schema cannot silently drop a param any-llm forwards. Fields below either tighten a derived field (``messages``, ``response_format``) or add gateway-internal behavior (``mcp_servers``, ``mcp_server_ids``, ``guardrails``, ``tools_header``, ``max_tool_iterations``) that is stripped before the request is forwarded upstream. + OpenAI-compatible chat completion request. The completion-param fields are derived from any-llm's ``CompletionParams`` (see ``_schema_derive``) so the schema cannot silently drop a param any-llm forwards. Fields below either tighten a derived field (``messages``, ``response_format``), declare an OpenAI wire param ``CompletionParams`` does not model (``service_tier``, forwarded as an any-llm ``**kwargs`` param), or add gateway-internal behavior (``mcp_servers``, ``mcp_server_ids``, ``guardrails``, ``tools_header``, ``max_tool_iterations``) that is stripped before the request is forwarded upstream. """ # noqa: E501 frequency_penalty: Optional[Union[StrictFloat, StrictInt]] = None guardrails: Optional[Annotated[List[GuardrailConfig], Field(max_length=8)]] = None @@ -52,10 +52,11 @@ class ChatCompletionRequest(BaseModel): reasoning_effort: Optional[StrictStr] = None response_format: Optional[Dict[str, Any]] = None 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="An unsaved policy body to explain.") + 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').") temperature: Optional[Union[StrictFloat, StrictInt]] = None tool_choice: Optional[ToolChoice] = None tools: Optional[List[ChatCompletionRequestToolsInner]] = None @@ -63,7 +64,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", "reasoning_effort", "response_format", "seed", "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", "model", "n", "parallel_tool_calls", "presence_penalty", "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): @@ -223,6 +224,11 @@ def to_dict(self) -> Dict[str, Any]: if self.seed is None and "seed" in self.model_fields_set: _dict['seed'] = None + # set to None if service_tier (nullable) is None + # and model_fields_set contains the field + if self.service_tier is None and "service_tier" in self.model_fields_set: + _dict['service_tier'] = None + # set to None if session_label (nullable) is None # and model_fields_set contains the field if self.session_label is None and "session_label" in self.model_fields_set: @@ -302,6 +308,7 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: "reasoning_effort": obj.get("reasoning_effort"), "response_format": obj.get("response_format"), "seed": obj.get("seed"), + "service_tier": obj.get("service_tier"), "session_label": obj.get("session_label"), "stop": Stop.from_dict(obj["stop"]) if obj.get("stop") is not None else None, "stream": obj.get("stream") if obj.get("stream") is not None else False, 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 5d0f211..3068f35 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="An unsaved policy body to explain.") + 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').") # data type: Dict[str, object] anyof_schema_2_validator: Optional[Dict[str, Any]] = None if TYPE_CHECKING: diff --git a/src/otari/_client/models/config_search_tool_schema.py b/src/otari/_client/models/config_search_tool_schema.py new file mode 100644 index 0000000..8db242d --- /dev/null +++ b/src/otari/_client/models/config_search_tool_schema.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, StrictStr +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 ConfigSearchToolSchema(BaseModel): + """ + A search tool declared in the config file. Read-only: it cannot be edited here. + """ # noqa: E501 + api_base: Optional[StrictStr] = None + has_api_key: StrictBool = Field(description="Whether the config entry carries an API key. The key itself is not shown.") + name: StrictStr + provider: StrictStr + shadowed: Optional[StrictBool] = Field(default=False, description="True when a stored search tool of the same name overrides this entry.") + __properties: ClassVar[List[str]] = ["api_base", "has_api_key", "name", "provider", "shadowed"] + + 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 ConfigSearchToolSchema 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_base (nullable) is None + # and model_fields_set contains the field + if self.api_base is None and "api_base" in self.model_fields_set: + _dict['api_base'] = None + + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of ConfigSearchToolSchema from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "api_base": obj.get("api_base"), + "has_api_key": obj.get("has_api_key"), + "name": obj.get("name"), + "provider": obj.get("provider"), + "shadowed": obj.get("shadowed") if obj.get("shadowed") is not None else False + }) + return _obj + + diff --git a/src/otari/_client/models/conversation.py b/src/otari/_client/models/conversation.py index 76dd40b..b4ce930 100644 --- a/src/otari/_client/models/conversation.py +++ b/src/otari/_client/models/conversation.py @@ -31,9 +31,9 @@ class Conversation(BaseModel): """ # data type: str - anyof_schema_1_validator: Optional[StrictStr] = Field(default=None, description="Delete the alias scoped to this user. Omit to delete the global alias of that name.") + 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="An unsaved policy body to explain.") + 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').") 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 c502f82..978a597 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="An unsaved policy body to explain.") - context_management: Optional[Dict[str, Any]] = Field(default=None, description="An unsaved policy body to explain.") + 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').") messages: Annotated[List[Optional[Dict[str, Any]]], Field(min_length=1)] - metadata: Optional[Dict[str, Any]] = Field(default=None, description="An unsaved policy body to explain.") + metadata: Optional[Dict[str, Any]] = Field(default=None, description="Provider-native request fields used as defaults (e.g. exa's 'type', searxng's 'engines').") model: StrictStr system: Optional[System] = None - thinking: Optional[Dict[str, Any]] = Field(default=None, description="An unsaved policy body to explain.") - tool_choice: Optional[Dict[str, Any]] = Field(default=None, description="An unsaved policy body to explain.") + 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').") 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_key_request.py b/src/otari/_client/models/create_key_request.py index 9d80c46..80e1488 100644 --- a/src/otari/_client/models/create_key_request.py +++ b/src/otari/_client/models/create_key_request.py @@ -29,7 +29,7 @@ class CreateKeyRequest(BaseModel): Request model for creating a new API key. """ # 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 behavioral events (tool_result, tool_decision, user_prompt, api_error) from POST /v1/logs, false always discards them. Usage capture and billing are unaffected either way.") + 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 /v1/logs and outcome-metric data points (lines of code, commits, pull requests, active time) from POST /v1/metrics. Usage capture and billing are unaffected either way.") 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") key_name: Optional[StrictStr] = Field(default=None, description="Optional name for the key") diff --git a/src/otari/_client/models/create_search_tool_request.py b/src/otari/_client/models/create_search_tool_request.py new file mode 100644 index 0000000..c544c40 --- /dev/null +++ b/src/otari/_client/models/create_search_tool_request.py @@ -0,0 +1,119 @@ +# 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, Union +from typing_extensions import Annotated +from typing import Optional, Set +from typing_extensions import Self +from pydantic_core import to_jsonable_python + +class CreateSearchToolRequest(BaseModel): + """ + Create a stored search tool. ``api_key`` is write-only and requires OTARI_SECRET_KEY. + """ # noqa: E501 + 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 /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').") + 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"] + + 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 CreateSearchToolRequest 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_base (nullable) is None + # and model_fields_set contains the field + if self.api_base is None and "api_base" in self.model_fields_set: + _dict['api_base'] = None + + # 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 options (nullable) is None + # and model_fields_set contains the field + if self.options is None and "options" in self.model_fields_set: + _dict['options'] = None + + # set to None if timeout (nullable) is None + # and model_fields_set contains the field + if self.timeout is None and "timeout" in self.model_fields_set: + _dict['timeout'] = None + + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of CreateSearchToolRequest from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "api_base": obj.get("api_base"), + "api_key": obj.get("api_key"), + "name": obj.get("name"), + "options": obj.get("options"), + "provider": obj.get("provider"), + "timeout": obj.get("timeout") + }) + return _obj + + diff --git a/src/otari/_client/models/create_stored_provider_request.py b/src/otari/_client/models/create_stored_provider_request.py index 3d78201..5247e36 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="An unsaved policy body to explain.") + 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').") 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/deployment_bootstrap.py b/src/otari/_client/models/deployment_bootstrap.py new file mode 100644 index 0000000..4bce1f1 --- /dev/null +++ b/src/otari/_client/models/deployment_bootstrap.py @@ -0,0 +1,113 @@ +# 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, field_validator +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 DeploymentBootstrap(BaseModel): + """ + What the dashboard shell needs before it can render anything. + """ # noqa: E501 + deployment_type: StrictStr = Field(description="Which deployment serves this URL. 'standalone' owns its own data; 'hosted' is otari.ai; 'hybrid' is a gateway attached to otari.ai, which is data-plane only and holds no management surface of its own.") + management_url: Optional[StrictStr] = Field(description="Where the authoritative control plane lives when it is not this deployment. Set for a hybrid gateway so its landing page can link to otari.ai; null otherwise.") + session_type: StrictStr = Field(description="The kind of session this deployment issues, not whether the caller holds one. 'local_operator' is the standalone master-key sign-in, 'hosted_user' an otari.ai account, and 'none' a deployment that issues no management session at all.") + surfaces: List[StrictStr] = Field(description="Management API groups this deployment serves, sorted, which is what its dashboard pages gate on. Named surfaces, not capabilities: capability is otari.ai's word for the entitlement (licensing) axis, and this is the deployment (topology) axis. Empty for a hybrid gateway.") + __properties: ClassVar[List[str]] = ["deployment_type", "management_url", "session_type", "surfaces"] + + @field_validator('deployment_type') + def deployment_type_validate_enum(cls, value): + """Validates the enum""" + if value not in set(['standalone', 'hosted', 'hybrid']): + raise ValueError("must be one of enum values ('standalone', 'hosted', 'hybrid')") + return value + + @field_validator('session_type') + def session_type_validate_enum(cls, value): + """Validates the enum""" + if value not in set(['local_operator', 'hosted_user', 'none']): + raise ValueError("must be one of enum values ('local_operator', 'hosted_user', 'none')") + return value + + 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 DeploymentBootstrap 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 management_url (nullable) is None + # and model_fields_set contains the field + if self.management_url is None and "management_url" in self.model_fields_set: + _dict['management_url'] = None + + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of DeploymentBootstrap from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "deployment_type": obj.get("deployment_type"), + "management_url": obj.get("management_url"), + "session_type": obj.get("session_type"), + "surfaces": obj.get("surfaces") + }) + return _obj + + diff --git a/src/otari/_client/models/explain_request.py b/src/otari/_client/models/explain_request.py index 187b7e0..2d679f6 100644 --- a/src/otari/_client/models/explain_request.py +++ b/src/otari/_client/models/explain_request.py @@ -32,7 +32,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="An unsaved policy body 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').") user_id: Optional[StrictStr] = Field(default=None, description="Evaluate conditions as this user.") __properties: ClassVar[List[str]] = ["allowed_models", "budget_remaining_usd", "budget_used_pct", "key_id", "name", "spec", "user_id"] diff --git a/src/otari/_client/models/img_image.py b/src/otari/_client/models/img_image.py index 3456f0e..5ab195a 100644 --- a/src/otari/_client/models/img_image.py +++ b/src/otari/_client/models/img_image.py @@ -27,9 +27,9 @@ class IMGImage(BaseModel): """ Represents the content or the URL of an image generated by the OpenAI API. """ # noqa: E501 - b64_json: Optional[StrictStr] = Field(default=None, description="Delete the alias scoped to this user. Omit to delete the global alias of that name.") - revised_prompt: Optional[StrictStr] = Field(default=None, description="Delete the alias scoped to this user. Omit to delete the global alias of that name.") - url: Optional[StrictStr] = Field(default=None, description="Delete the alias scoped to this user. Omit to delete the global alias of that name.") + b64_json: Optional[StrictStr] = Field(default=None, description="Filter to a single event type or metric name (e.g. 'tool_result', 'claude_code.commit.count')") + revised_prompt: Optional[StrictStr] = Field(default=None, description="Filter to a single event type or metric name (e.g. 'tool_result', 'claude_code.commit.count')") + url: Optional[StrictStr] = Field(default=None, description="Filter to a single event type or metric name (e.g. 'tool_result', 'claude_code.commit.count')") additional_properties: Dict[str, Any] = {} __properties: ClassVar[List[str]] = ["b64_json", "revised_prompt", "url"] diff --git a/src/otari/_client/models/message_response.py b/src/otari/_client/models/message_response.py index ce93cfd..216d4e0 100644 --- a/src/otari/_client/models/message_response.py +++ b/src/otari/_client/models/message_response.py @@ -41,7 +41,7 @@ class MessageResponse(BaseModel): role: StrictStr stop_details: Optional[MRRefusalStopDetails] = None stop_reason: Optional[StrictStr] = None - stop_sequence: Optional[StrictStr] = Field(default=None, description="Delete the alias scoped to this user. Omit to delete the global alias of that name.") + stop_sequence: Optional[StrictStr] = Field(default=None, description="Filter to a single event type or metric name (e.g. 'tool_result', 'claude_code.commit.count')") type: StrictStr usage: MRMessageUsage context_management: Optional[MRBetaContextManagementResponse] = None diff --git a/src/otari/_client/models/messages_request.py b/src/otari/_client/models/messages_request.py index 416db2f..b7dd282 100644 --- a/src/otari/_client/models/messages_request.py +++ b/src/otari/_client/models/messages_request.py @@ -43,7 +43,7 @@ class MessagesRequest(BaseModel): messages: Annotated[List[Dict[str, Any]], Field(min_length=1)] metadata: Optional[Dict[str, Any]] = None model: StrictStr - output_format: Optional[Dict[str, Any]] = Field(default=None, description="An unsaved policy body to explain.") + 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').") 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_sequences: Optional[List[StrictStr]] = None stream: Optional[StrictBool] = False diff --git a/src/otari/_client/models/model_pricing_info.py b/src/otari/_client/models/model_pricing_info.py index a1bf7e1..a8f8107 100644 --- a/src/otari/_client/models/model_pricing_info.py +++ b/src/otari/_client/models/model_pricing_info.py @@ -19,7 +19,7 @@ from pydantic import BaseModel, ConfigDict, StrictFloat, StrictInt from typing import Any, ClassVar, Dict, List, Optional, Union -from otari._client.models.pricing_tiers_inner_value import PricingTiersInnerValue +from otari._client.models.pricing_tiers_inner import PricingTiersInner from typing import Optional, Set from typing_extensions import Self from pydantic_core import to_jsonable_python @@ -33,7 +33,7 @@ class ModelPricingInfo(BaseModel): cache_write_price_per_million: Optional[Union[StrictFloat, StrictInt]] = None input_price_per_million: Union[StrictFloat, StrictInt] output_price_per_million: Union[StrictFloat, StrictInt] - pricing_tiers: Optional[List[Dict[str, PricingTiersInnerValue]]] = None + pricing_tiers: Optional[List[PricingTiersInner]] = None __properties: ClassVar[List[str]] = ["cache_read_price_per_million", "cache_write_1h_price_per_million", "cache_write_price_per_million", "input_price_per_million", "output_price_per_million", "pricing_tiers"] model_config = ConfigDict( @@ -75,14 +75,12 @@ def to_dict(self) -> Dict[str, Any]: exclude=excluded_fields, exclude_none=True, ) - # override the default output from pydantic by calling `to_dict()` of each item in pricing_tiers (list of dict) + # override the default output from pydantic by calling `to_dict()` of each item in pricing_tiers (list) _items = [] if self.pricing_tiers: for _item_pricing_tiers in self.pricing_tiers: if _item_pricing_tiers: - _items.append( - {_inner_key: _inner_value.to_dict() for _inner_key, _inner_value in _item_pricing_tiers.items()} - ) + _items.append(_item_pricing_tiers.to_dict()) _dict['pricing_tiers'] = _items # set to None if cache_read_price_per_million (nullable) is None # and model_fields_set contains the field @@ -116,10 +114,7 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: "cache_write_price_per_million": obj.get("cache_write_price_per_million"), "input_price_per_million": obj.get("input_price_per_million"), "output_price_per_million": obj.get("output_price_per_million"), - "pricing_tiers": [ - {_inner_key: PricingTiersInnerValue.from_dict(_inner_value) for _inner_key, _inner_value in _item.items()} - for _item in obj["pricing_tiers"] - ] if obj.get("pricing_tiers") is not None else None + "pricing_tiers": [PricingTiersInner.from_dict(_item) for _item in obj["pricing_tiers"]] if obj.get("pricing_tiers") is not None else None }) return _obj diff --git a/src/otari/_client/models/moderation_result.py b/src/otari/_client/models/moderation_result.py index 6998c44..98893e0 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="An unsaved policy body to explain.") + 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').") __properties: ClassVar[List[str]] = ["categories", "category_applied_input_types", "category_scores", "flagged", "provider_raw"] model_config = ConfigDict( diff --git a/src/otari/_client/models/mr_beta_diagnostics_fallback.py b/src/otari/_client/models/mr_beta_diagnostics_fallback.py index 91684b9..78cd7a3 100644 --- a/src/otari/_client/models/mr_beta_diagnostics_fallback.py +++ b/src/otari/_client/models/mr_beta_diagnostics_fallback.py @@ -27,7 +27,7 @@ class MRBetaDiagnosticsFallback(BaseModel): """ MRBetaDiagnosticsFallback """ # noqa: E501 - cache_miss_reason: Optional[Dict[str, Any]] = Field(default=None, description="An unsaved policy body to explain.") + cache_miss_reason: Optional[Dict[str, Any]] = Field(default=None, description="Provider-native request fields used as defaults (e.g. exa's 'type', searxng's 'engines').") additional_properties: Dict[str, Any] = {} __properties: ClassVar[List[str]] = ["cache_miss_reason"] diff --git a/src/otari/_client/models/mr_message_usage.py b/src/otari/_client/models/mr_message_usage.py index 45b2df4..8ac52c0 100644 --- a/src/otari/_client/models/mr_message_usage.py +++ b/src/otari/_client/models/mr_message_usage.py @@ -33,7 +33,7 @@ class MRMessageUsage(BaseModel): cache_creation: Optional[MRCacheCreation] = None cache_creation_input_tokens: Optional[StrictInt] = Field(default=None, description="Filter to a single failure status code (e.g. 429 for provider rate limits, 402 for missing-pricing rejections). Only error rows carry one, so this filter also restricts to status='error' unless 'status' is given explicitly") cache_read_input_tokens: Optional[StrictInt] = Field(default=None, description="Filter to a single failure status code (e.g. 429 for provider rate limits, 402 for missing-pricing rejections). Only error rows carry one, so this filter also restricts to status='error' unless 'status' is given explicitly") - inference_geo: Optional[StrictStr] = Field(default=None, description="Delete the alias scoped to this user. Omit to delete the global alias of that name.") + inference_geo: Optional[StrictStr] = Field(default=None, description="Filter to a single event type or metric name (e.g. 'tool_result', 'claude_code.commit.count')") input_tokens: StrictInt output_tokens: StrictInt server_tool_use: Optional[MRServerToolUsage] = None diff --git a/src/otari/_client/models/mr_refusal_stop_details.py b/src/otari/_client/models/mr_refusal_stop_details.py index 53755b0..63286b4 100644 --- a/src/otari/_client/models/mr_refusal_stop_details.py +++ b/src/otari/_client/models/mr_refusal_stop_details.py @@ -28,7 +28,7 @@ class MRRefusalStopDetails(BaseModel): Structured information about a refusal. """ # noqa: E501 category: Optional[StrictStr] = None - explanation: Optional[StrictStr] = Field(default=None, description="Delete the alias scoped to this user. Omit to delete the global alias of that name.") + explanation: Optional[StrictStr] = Field(default=None, description="Filter to a single event type or metric name (e.g. 'tool_result', 'claude_code.commit.count')") type: StrictStr additional_properties: Dict[str, Any] = {} __properties: ClassVar[List[str]] = ["category", "explanation", "type"] diff --git a/src/otari/_client/models/policy_request.py b/src/otari/_client/models/policy_request.py index 362e329..f0c4da7 100644 --- a/src/otari/_client/models/policy_request.py +++ b/src/otari/_client/models/policy_request.py @@ -28,9 +28,10 @@ class PolicyRequest(BaseModel): Request to create or update a routing policy. """ # noqa: E501 name: StrictStr = Field(description="Model name callers send, e.g. 'fast'.") + rename_from: Optional[StrictStr] = Field(default=None, description="Current name of the policy to rename, in the same scope. The stored row keeps its id and created_at and takes `name` and `spec`. Sending it asserts that policy exists, so a name with no stored row is a 404 rather than a create, even when it equals `name`. Omit to create or update the policy named `name`. Renaming changes what callers must send as `model`; usage already recorded keeps the old name.") spec: Dict[str, Any] = Field(description="The policy body: select (with exactly one `default` entry, last), optional on_failure and guardrails. Same schema as a `routing.policies` entry in config.yml, and closed to unknown keys, so a typo is a 400 rather than a silently ignored setting.") user_id: Optional[StrictStr] = Field(default=None, description="User this policy belongs to. Omit for a global policy every caller sees. A user-scoped policy resolves only for that user and shadows a global one of the same name.") - __properties: ClassVar[List[str]] = ["name", "spec", "user_id"] + __properties: ClassVar[List[str]] = ["name", "rename_from", "spec", "user_id"] model_config = ConfigDict( validate_by_name=True, @@ -71,6 +72,11 @@ def to_dict(self) -> Dict[str, Any]: exclude=excluded_fields, exclude_none=True, ) + # set to None if rename_from (nullable) is None + # and model_fields_set contains the field + if self.rename_from is None and "rename_from" in self.model_fields_set: + _dict['rename_from'] = None + # set to None if user_id (nullable) is None # and model_fields_set contains the field if self.user_id is None and "user_id" in self.model_fields_set: @@ -89,6 +95,7 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: _obj = cls.model_validate({ "name": obj.get("name"), + "rename_from": obj.get("rename_from"), "spec": obj.get("spec"), "user_id": obj.get("user_id") }) diff --git a/src/otari/_client/models/pricing_tiers_inner.py b/src/otari/_client/models/pricing_tiers_inner.py new file mode 100644 index 0000000..21a983a --- /dev/null +++ b/src/otari/_client/models/pricing_tiers_inner.py @@ -0,0 +1,137 @@ +# 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 +from inspect import getfullargspec +import json +import pprint +import re # noqa: F401 +from pydantic import BaseModel, ConfigDict, Field, StrictStr, ValidationError, field_validator +from typing import Dict, Optional +from otari._client.models.pricing_tier import PricingTier +from otari._client.models.pricing_tiers_inner_any_of_value import PricingTiersInnerAnyOfValue +from typing import Union, Any, List, Set, TYPE_CHECKING, Optional, Dict +from typing_extensions import Literal, Self +from pydantic import Field + +PRICINGTIERSINNER_ANY_OF_SCHEMAS = ["Dict[str, PricingTiersInnerAnyOfValue]", "PricingTier"] + +class PricingTiersInner(BaseModel): + """ + PricingTiersInner + """ + + # data type: PricingTier + anyof_schema_1_validator: Optional[PricingTier] = None + # data type: Dict[str, PricingTiersInnerAnyOfValue] + anyof_schema_2_validator: Optional[Dict[str, PricingTiersInnerAnyOfValue]] = None + if TYPE_CHECKING: + actual_instance: Optional[Union[Dict[str, PricingTiersInnerAnyOfValue], PricingTier]] = None + else: + actual_instance: Any = None + any_of_schemas: Set[str] = { "Dict[str, PricingTiersInnerAnyOfValue]", "PricingTier" } + + model_config = { + "validate_assignment": True, + "protected_namespaces": (), + } + + def __init__(self, *args, **kwargs) -> None: + if args: + if len(args) > 1: + raise ValueError("If a position argument is used, only 1 is allowed to set `actual_instance`") + if kwargs: + raise ValueError("If a position argument is used, keyword arguments cannot be used.") + super().__init__(actual_instance=args[0]) + else: + super().__init__(**kwargs) + + @field_validator('actual_instance') + def actual_instance_must_validate_anyof(cls, v): + instance = PricingTiersInner.model_construct() + error_messages = [] + # validate data type: PricingTier + if not isinstance(v, PricingTier): + error_messages.append(f"Error! Input type `{type(v)}` is not `PricingTier`") + else: + return v + + # validate data type: Dict[str, PricingTiersInnerAnyOfValue] + try: + instance.anyof_schema_2_validator = v + return v + except (ValidationError, ValueError) as e: + error_messages.append(str(e)) + if error_messages: + # no match + raise ValueError("No match found when setting the actual_instance in PricingTiersInner with anyOf schemas: Dict[str, PricingTiersInnerAnyOfValue], PricingTier. Details: " + ", ".join(error_messages)) + else: + return v + + @classmethod + def from_dict(cls, obj: Dict[str, Any]) -> Self: + return cls.from_json(json.dumps(obj)) + + @classmethod + def from_json(cls, json_str: str) -> Self: + """Returns the object represented by the json string""" + instance = cls.model_construct() + error_messages = [] + # anyof_schema_1_validator: Optional[PricingTier] = None + try: + instance.actual_instance = PricingTier.from_json(json_str) + return instance + except (ValidationError, ValueError) as e: + error_messages.append(str(e)) + # deserialize data into Dict[str, PricingTiersInnerAnyOfValue] + try: + # validation + instance.anyof_schema_2_validator = json.loads(json_str) + # assign value to actual_instance + instance.actual_instance = instance.anyof_schema_2_validator + return instance + except (ValidationError, ValueError) as e: + error_messages.append(str(e)) + + if error_messages: + # no match + raise ValueError("No match found when deserializing the JSON string into PricingTiersInner with anyOf schemas: Dict[str, PricingTiersInnerAnyOfValue], PricingTier. Details: " + ", ".join(error_messages)) + else: + return instance + + def to_json(self) -> str: + """Returns the JSON representation of the actual instance""" + if self.actual_instance is None: + return "null" + + if hasattr(self.actual_instance, "to_json") and callable(self.actual_instance.to_json): + return self.actual_instance.to_json() + else: + return json.dumps(self.actual_instance) + + def to_dict(self) -> Optional[Union[Dict[str, Any], Dict[str, PricingTiersInnerAnyOfValue], PricingTier]]: + """Returns the dict representation of the actual instance""" + if self.actual_instance is None: + return None + + if hasattr(self.actual_instance, "to_dict") and callable(self.actual_instance.to_dict): + return self.actual_instance.to_dict() + else: + return self.actual_instance + + def to_str(self) -> str: + """Returns the string representation of the actual instance""" + return pprint.pformat(self.model_dump()) + + diff --git a/src/otari/_client/models/pricing_tiers_inner_value.py b/src/otari/_client/models/pricing_tiers_inner_any_of_value.py similarity index 91% rename from src/otari/_client/models/pricing_tiers_inner_value.py rename to src/otari/_client/models/pricing_tiers_inner_any_of_value.py index 3ef9880..07fd43a 100644 --- a/src/otari/_client/models/pricing_tiers_inner_value.py +++ b/src/otari/_client/models/pricing_tiers_inner_any_of_value.py @@ -23,11 +23,11 @@ from typing_extensions import Literal, Self from pydantic import Field -PRICINGTIERSINNERVALUE_ANY_OF_SCHEMAS = ["float", "int"] +PRICINGTIERSINNERANYOFVALUE_ANY_OF_SCHEMAS = ["float", "int"] -class PricingTiersInnerValue(BaseModel): +class PricingTiersInnerAnyOfValue(BaseModel): """ - PricingTiersInnerValue + PricingTiersInnerAnyOfValue """ # data type: float @@ -57,7 +57,7 @@ def __init__(self, *args, **kwargs) -> None: @field_validator('actual_instance') def actual_instance_must_validate_anyof(cls, v): - instance = PricingTiersInnerValue.model_construct() + instance = PricingTiersInnerAnyOfValue.model_construct() error_messages = [] # validate data type: float try: @@ -73,7 +73,7 @@ def actual_instance_must_validate_anyof(cls, v): error_messages.append(str(e)) if error_messages: # no match - raise ValueError("No match found when setting the actual_instance in PricingTiersInnerValue with anyOf schemas: float, int. Details: " + ", ".join(error_messages)) + raise ValueError("No match found when setting the actual_instance in PricingTiersInnerAnyOfValue with anyOf schemas: float, int. Details: " + ", ".join(error_messages)) else: return v @@ -107,7 +107,7 @@ def from_json(cls, json_str: str) -> Self: if error_messages: # no match - raise ValueError("No match found when deserializing the JSON string into PricingTiersInnerValue with anyOf schemas: float, int. Details: " + ", ".join(error_messages)) + raise ValueError("No match found when deserializing the JSON string into PricingTiersInnerAnyOfValue with anyOf schemas: float, int. Details: " + ", ".join(error_messages)) else: return instance diff --git a/src/otari/_client/models/reencrypt_search_tools_response.py b/src/otari/_client/models/reencrypt_search_tools_response.py new file mode 100644 index 0000000..132307c --- /dev/null +++ b/src/otari/_client/models/reencrypt_search_tools_response.py @@ -0,0 +1,90 @@ +# 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 typing import Optional, Set +from typing_extensions import Self +from pydantic_core import to_jsonable_python + +class ReencryptSearchToolsResponse(BaseModel): + """ + Result of re-encrypting stored search-tool keys with the primary secret key. + """ # noqa: E501 + reencrypted: StrictInt = Field(description="Number of stored search-tool keys re-encrypted.") + unreadable: StrictInt = Field(description="Number of encrypted keys left untouched because they could not be decrypted.") + __properties: ClassVar[List[str]] = ["reencrypted", "unreadable"] + + 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 ReencryptSearchToolsResponse 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 ReencryptSearchToolsResponse from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "reencrypted": obj.get("reencrypted"), + "unreadable": obj.get("unreadable") + }) + return _obj + + diff --git a/src/otari/_client/models/rerank_response.py b/src/otari/_client/models/rerank_response.py index 4d26f3d..f915cb2 100644 --- a/src/otari/_client/models/rerank_response.py +++ b/src/otari/_client/models/rerank_response.py @@ -30,7 +30,7 @@ class RerankResponse(BaseModel): """ Normalized rerank response, provider-agnostic. """ # noqa: E501 - id: Optional[StrictStr] = Field(default=None, description="Delete the alias scoped to this user. Omit to delete the global alias of that name.") + id: Optional[StrictStr] = Field(default=None, description="Filter to a single event type or metric name (e.g. 'tool_result', 'claude_code.commit.count')") results: List[RRRerankResult] = Field(description="Results sorted by relevance_score descending") meta: Optional[RRRerankMeta] = None usage: Optional[RRRerankUsage] = None diff --git a/src/otari/_client/models/responses_request.py b/src/otari/_client/models/responses_request.py index 5dc7374..2c535f8 100644 --- a/src/otari/_client/models/responses_request.py +++ b/src/otari/_client/models/responses_request.py @@ -53,7 +53,7 @@ class ResponsesRequest(BaseModel): 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="An unsaved policy body to explain.") + reasoning: 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]] = None safety_identifier: Optional[StrictStr] = None service_tier: Optional[StrictStr] = None diff --git a/src/otari/_client/models/router_status.py b/src/otari/_client/models/router_status.py index 569d49f..dac3456 100644 --- a/src/otari/_client/models/router_status.py +++ b/src/otari/_client/models/router_status.py @@ -28,7 +28,7 @@ class RouterStatus(BaseModel): """ - How warm this user's routing memory is, and what depends on it. Routing memory has no single warmth: it is a set of independent pools. ``default_pool`` is what a request with no ``Otari-Router-Task`` header votes over (every record the user has, labelled or not) and ``tasks`` lists each partition, which only requests carrying that label use. Each crosses ``seed_count`` on its own. + How warm this user's routing memory is, and what depends on it. Routing memory has no single warmth: it is a set of independent pools. ``default_pool`` is what a request with no ``Otari-Router-Task`` header votes over (every record the user has, labeled or not) and ``tasks`` lists each partition, which only requests carrying that label use. Each crosses ``seed_count`` on its own. """ # noqa: E501 alpha: Union[StrictFloat, StrictInt] confidence_floor: Union[StrictFloat, StrictInt] diff --git a/src/otari/_client/models/search_provider_schema.py b/src/otari/_client/models/search_provider_schema.py new file mode 100644 index 0000000..fa4f222 --- /dev/null +++ b/src/otari/_client/models/search_provider_schema.py @@ -0,0 +1,99 @@ +# 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 typing import Optional, Set +from typing_extensions import Self +from pydantic_core import to_jsonable_python + +class SearchProviderSchema(BaseModel): + """ + One search provider this build can dispatch to, for the add-tool picker. + """ # noqa: E501 + default_api_base: Optional[StrictStr] = Field(default=None, description="The endpoint a tool on this provider uses when it declares no api_base. Null means nothing supplies one, so an api_base is required.") + id: StrictStr = Field(description="Value to send as 'provider'.") + requires_api_base: StrictBool = Field(description="True when this provider has no endpoint of its own, so the tool must say where the backend is.") + requires_api_key: StrictBool = Field(description="True when a tool on this provider must carry an API key.") + __properties: ClassVar[List[str]] = ["default_api_base", "id", "requires_api_base", "requires_api_key"] + + 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 SearchProviderSchema from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self) -> Dict[str, Any]: + """Return the dictionary representation of the model using alias. + + This has the following differences from calling pydantic's + `self.model_dump(by_alias=True)`: + + * `None` is only added to the output dict for nullable fields that + were set at model initialization. Other fields with value `None` + are ignored. + """ + excluded_fields: Set[str] = set([ + ]) + + _dict = self.model_dump( + by_alias=True, + exclude=excluded_fields, + exclude_none=True, + ) + # set to None if default_api_base (nullable) is None + # and model_fields_set contains the field + if self.default_api_base is None and "default_api_base" in self.model_fields_set: + _dict['default_api_base'] = None + + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of SearchProviderSchema from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "default_api_base": obj.get("default_api_base"), + "id": obj.get("id"), + "requires_api_base": obj.get("requires_api_base"), + "requires_api_key": obj.get("requires_api_key") + }) + return _obj + + diff --git a/src/otari/_client/models/search_tools_response.py b/src/otari/_client/models/search_tools_response.py new file mode 100644 index 0000000..129b14b --- /dev/null +++ b/src/otari/_client/models/search_tools_response.py @@ -0,0 +1,106 @@ +# 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 +from typing import Any, ClassVar, Dict, List +from otari._client.models.config_search_tool_schema import ConfigSearchToolSchema +from otari._client.models.stored_search_tool_schema import StoredSearchToolSchema +from typing import Optional, Set +from typing_extensions import Self +from pydantic_core import to_jsonable_python + +class SearchToolsResponse(BaseModel): + """ + Every search tool ``POST /v1/search`` can name, by where it came from. + """ # noqa: E501 + config: List[ConfigSearchToolSchema] + stored: List[StoredSearchToolSchema] + __properties: ClassVar[List[str]] = ["config", "stored"] + + 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 SearchToolsResponse 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 config (list) + _items = [] + if self.config: + for _item_config in self.config: + if _item_config: + _items.append(_item_config.to_dict()) + _dict['config'] = _items + # override the default output from pydantic by calling `to_dict()` of each item in stored (list) + _items = [] + if self.stored: + for _item_stored in self.stored: + if _item_stored: + _items.append(_item_stored.to_dict()) + _dict['stored'] = _items + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of SearchToolsResponse from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "config": [ConfigSearchToolSchema.from_dict(_item) for _item in obj["config"]] if obj.get("config") is not None else None, + "stored": [StoredSearchToolSchema.from_dict(_item) for _item in obj["stored"]] if obj.get("stored") is not None else None + }) + return _obj + + diff --git a/src/otari/_client/models/stored_search_tool_schema.py b/src/otari/_client/models/stored_search_tool_schema.py new file mode 100644 index 0000000..fbfd028 --- /dev/null +++ b/src/otari/_client/models/stored_search_tool_schema.py @@ -0,0 +1,131 @@ +# 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, 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 StoredSearchToolSchema(BaseModel): + """ + A runtime-stored search tool. The API key is never returned, only ``last4``. + """ # noqa: E501 + api_base: Optional[StrictStr] = None + created_at: Optional[StrictStr] = None + decryptable: Optional[StrictBool] = True + last4: Optional[StrictStr] = None + name: StrictStr + options: Optional[Dict[str, Any]] = None + provider: StrictStr + shadows_config: Optional[StrictBool] = Field(default=False, description="True when a config-file search tool of the same name exists; the stored one is in effect.") + timeout: Optional[Union[StrictFloat, StrictInt]] = None + updated_at: Optional[StrictStr] = None + __properties: ClassVar[List[str]] = ["api_base", "created_at", "decryptable", "last4", "name", "options", "provider", "shadows_config", "timeout", "updated_at"] + + 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 StoredSearchToolSchema 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_base (nullable) is None + # and model_fields_set contains the field + if self.api_base is None and "api_base" in self.model_fields_set: + _dict['api_base'] = None + + # set to None if created_at (nullable) is None + # and model_fields_set contains the field + if self.created_at is None and "created_at" in self.model_fields_set: + _dict['created_at'] = None + + # set to None if 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 timeout (nullable) is None + # and model_fields_set contains the field + if self.timeout is None and "timeout" in self.model_fields_set: + _dict['timeout'] = 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 StoredSearchToolSchema from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "api_base": obj.get("api_base"), + "created_at": obj.get("created_at"), + "decryptable": obj.get("decryptable") if obj.get("decryptable") is not None else True, + "last4": obj.get("last4"), + "name": obj.get("name"), + "options": obj.get("options"), + "provider": obj.get("provider"), + "shadows_config": obj.get("shadows_config") if obj.get("shadows_config") is not None else False, + "timeout": obj.get("timeout"), + "updated_at": obj.get("updated_at") + }) + return _obj + + diff --git a/src/otari/_client/models/token_charge_line.py b/src/otari/_client/models/token_charge_line.py new file mode 100644 index 0000000..c5960d5 --- /dev/null +++ b/src/otari/_client/models/token_charge_line.py @@ -0,0 +1,111 @@ +# 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, Union +from otari._client.models.units import Units +from typing import Optional, Set +from typing_extensions import Self +from pydantic_core import to_jsonable_python + +class TokenChargeLine(BaseModel): + """ + A charge line billed per million tokens. ``rate_per_million`` is the discriminator: its presence (rather than ``unit_rate``) is what tells a reader, and a renderer, which unit convention applies. See ``gateway.services.pricing_service``. + """ # noqa: E501 + cost: Union[StrictFloat, StrictInt] = Field(description="USD charged for this line.") + meter: StrictStr = Field(description="What was metered, e.g. 'input' or 'cache_read'.") + rate_per_million: Union[StrictFloat, StrictInt] = Field(description="USD per million units.") + units: Units + additional_properties: Dict[str, Any] = {} + __properties: ClassVar[List[str]] = ["cost", "meter", "rate_per_million", "units"] + + 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 TokenChargeLine 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. + * Fields in `self.additional_properties` are added to the output dict. + """ + excluded_fields: Set[str] = set([ + "additional_properties", + ]) + + _dict = self.model_dump( + by_alias=True, + exclude=excluded_fields, + exclude_none=True, + ) + # override the default output from pydantic by calling `to_dict()` of units + if self.units: + _dict['units'] = self.units.to_dict() + # puts key-value pairs in additional_properties in the top level + if self.additional_properties is not None: + for _key, _value in self.additional_properties.items(): + _dict[_key] = _value + + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of TokenChargeLine from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "cost": obj.get("cost"), + "meter": obj.get("meter"), + "rate_per_million": obj.get("rate_per_million"), + "units": Units.from_dict(obj["units"]) if obj.get("units") is not None else None + }) + # store additional fields in additional_properties + for _key in obj.keys(): + if _key not in cls.__properties: + _obj.additional_properties[_key] = obj.get(_key) + + return _obj + + diff --git a/src/otari/_client/models/tool_choice.py b/src/otari/_client/models/tool_choice.py index d628776..aa12e76 100644 --- a/src/otari/_client/models/tool_choice.py +++ b/src/otari/_client/models/tool_choice.py @@ -31,9 +31,9 @@ class ToolChoice(BaseModel): """ # data type: str - anyof_schema_1_validator: Optional[StrictStr] = Field(default=None, description="Delete the alias scoped to this user. Omit to delete the global alias of that name.") + 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="An unsaved policy body to explain.") + 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').") if TYPE_CHECKING: actual_instance: Optional[Union[Dict[str, object], str]] = None else: diff --git a/src/otari/_client/models/tool_meter.py b/src/otari/_client/models/tool_meter.py new file mode 100644 index 0000000..1f0d223 --- /dev/null +++ b/src/otari/_client/models/tool_meter.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, StrictFloat, StrictInt +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 ToolMeter(BaseModel): + """ + One gateway-run tool's call counts on a request. A TypedDict rather than a model, and every key optional, so a stored entry serializes back as it was written: a model with defaults would put ``\"unit_rate\": null`` on every tool that has never been priced. + """ # noqa: E501 + billed: Optional[StrictInt] = None + errors: Optional[StrictInt] = None + unit_rate: Optional[Union[StrictFloat, StrictInt]] = None + additional_properties: Dict[str, Any] = {} + __properties: ClassVar[List[str]] = ["billed", "errors", "unit_rate"] + + 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 ToolMeter 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. + * Fields in `self.additional_properties` are added to the output dict. + """ + excluded_fields: Set[str] = set([ + "additional_properties", + ]) + + _dict = self.model_dump( + by_alias=True, + exclude=excluded_fields, + exclude_none=True, + ) + # puts key-value pairs in additional_properties in the top level + if self.additional_properties is not None: + for _key, _value in self.additional_properties.items(): + _dict[_key] = _value + + # set to None if unit_rate (nullable) is None + # and model_fields_set contains the field + if self.unit_rate is None and "unit_rate" in self.model_fields_set: + _dict['unit_rate'] = None + + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of ToolMeter from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "billed": obj.get("billed"), + "errors": obj.get("errors"), + "unit_rate": obj.get("unit_rate") + }) + # store additional fields in additional_properties + for _key in obj.keys(): + if _key not in cls.__properties: + _obj.additional_properties[_key] = obj.get(_key) + + return _obj + + diff --git a/src/otari/_client/models/unit_charge_line.py b/src/otari/_client/models/unit_charge_line.py new file mode 100644 index 0000000..9ffb7a3 --- /dev/null +++ b/src/otari/_client/models/unit_charge_line.py @@ -0,0 +1,111 @@ +# 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, Union +from otari._client.models.units1 import Units1 +from typing import Optional, Set +from typing_extensions import Self +from pydantic_core import to_jsonable_python + +class UnitChargeLine(BaseModel): + """ + A charge line billed per call, for gateway-run tools and per-request routes. ``unit_rate`` is the discriminator, in the same sense as :class:`TokenChargeLine`'s ``rate_per_million``. + """ # noqa: E501 + cost: Union[StrictFloat, StrictInt] = Field(description="USD charged for this line.") + meter: StrictStr = Field(description="What was metered, e.g. 'request' or 'web_search_calls'.") + unit_rate: Union[StrictFloat, StrictInt] = Field(description="USD per call.") + units: Units1 + additional_properties: Dict[str, Any] = {} + __properties: ClassVar[List[str]] = ["cost", "meter", "unit_rate", "units"] + + 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 UnitChargeLine 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. + * Fields in `self.additional_properties` are added to the output dict. + """ + excluded_fields: Set[str] = set([ + "additional_properties", + ]) + + _dict = self.model_dump( + by_alias=True, + exclude=excluded_fields, + exclude_none=True, + ) + # override the default output from pydantic by calling `to_dict()` of units + if self.units: + _dict['units'] = self.units.to_dict() + # puts key-value pairs in additional_properties in the top level + if self.additional_properties is not None: + for _key, _value in self.additional_properties.items(): + _dict[_key] = _value + + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of UnitChargeLine from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "cost": obj.get("cost"), + "meter": obj.get("meter"), + "unit_rate": obj.get("unit_rate"), + "units": Units1.from_dict(obj["units"]) if obj.get("units") is not None else None + }) + # store additional fields in additional_properties + for _key in obj.keys(): + if _key not in cls.__properties: + _obj.additional_properties[_key] = obj.get(_key) + + return _obj + + diff --git a/src/otari/_client/models/usage_entry_pricing_breakdown_inner_value.py b/src/otari/_client/models/units.py similarity index 74% rename from src/otari/_client/models/usage_entry_pricing_breakdown_inner_value.py rename to src/otari/_client/models/units.py index 6e3f502..a8d4daf 100644 --- a/src/otari/_client/models/usage_entry_pricing_breakdown_inner_value.py +++ b/src/otari/_client/models/units.py @@ -23,24 +23,22 @@ from typing_extensions import Literal, Self from pydantic import Field -USAGEENTRYPRICINGBREAKDOWNINNERVALUE_ANY_OF_SCHEMAS = ["float", "int", "str"] +UNITS_ANY_OF_SCHEMAS = ["float", "int"] -class UsageEntryPricingBreakdownInnerValue(BaseModel): +class Units(BaseModel): """ - UsageEntryPricingBreakdownInnerValue + Tokens billed on this meter. """ - # data type: float - anyof_schema_1_validator: Optional[Union[StrictFloat, StrictInt]] = None # data type: int - anyof_schema_2_validator: Optional[StrictInt] = None - # data type: str - anyof_schema_3_validator: Optional[StrictStr] = None + anyof_schema_1_validator: Optional[StrictInt] = None + # data type: float + anyof_schema_2_validator: Optional[Union[StrictFloat, StrictInt]] = None if TYPE_CHECKING: - actual_instance: Optional[Union[float, int, str]] = None + actual_instance: Optional[Union[float, int]] = None else: actual_instance: Any = None - any_of_schemas: Set[str] = { "float", "int", "str" } + any_of_schemas: Set[str] = { "float", "int" } model_config = { "validate_assignment": True, @@ -59,29 +57,23 @@ def __init__(self, *args, **kwargs) -> None: @field_validator('actual_instance') def actual_instance_must_validate_anyof(cls, v): - instance = UsageEntryPricingBreakdownInnerValue.model_construct() + instance = Units.model_construct() error_messages = [] - # validate data type: float + # validate data type: int try: instance.anyof_schema_1_validator = v return v except (ValidationError, ValueError) as e: error_messages.append(str(e)) - # validate data type: int + # validate data type: float try: instance.anyof_schema_2_validator = v return v except (ValidationError, ValueError) as e: error_messages.append(str(e)) - # validate data type: str - try: - instance.anyof_schema_3_validator = v - return v - except (ValidationError, ValueError) as e: - error_messages.append(str(e)) if error_messages: # no match - raise ValueError("No match found when setting the actual_instance in UsageEntryPricingBreakdownInnerValue with anyOf schemas: float, int, str. Details: " + ", ".join(error_messages)) + raise ValueError("No match found when setting the actual_instance in Units with anyOf schemas: float, int. Details: " + ", ".join(error_messages)) else: return v @@ -94,7 +86,7 @@ def from_json(cls, json_str: str) -> Self: """Returns the object represented by the json string""" instance = cls.model_construct() error_messages = [] - # deserialize data into float + # deserialize data into int try: # validation instance.anyof_schema_1_validator = json.loads(json_str) @@ -103,7 +95,7 @@ def from_json(cls, json_str: str) -> Self: return instance except (ValidationError, ValueError) as e: error_messages.append(str(e)) - # deserialize data into int + # deserialize data into float try: # validation instance.anyof_schema_2_validator = json.loads(json_str) @@ -112,19 +104,10 @@ def from_json(cls, json_str: str) -> Self: return instance except (ValidationError, ValueError) as e: error_messages.append(str(e)) - # deserialize data into str - try: - # validation - instance.anyof_schema_3_validator = json.loads(json_str) - # assign value to actual_instance - instance.actual_instance = instance.anyof_schema_3_validator - return instance - except (ValidationError, ValueError) as e: - error_messages.append(str(e)) if error_messages: # no match - raise ValueError("No match found when deserializing the JSON string into UsageEntryPricingBreakdownInnerValue with anyOf schemas: float, int, str. Details: " + ", ".join(error_messages)) + raise ValueError("No match found when deserializing the JSON string into Units with anyOf schemas: float, int. Details: " + ", ".join(error_messages)) else: return instance @@ -138,7 +121,7 @@ def to_json(self) -> str: else: return json.dumps(self.actual_instance) - def to_dict(self) -> Optional[Union[Dict[str, Any], float, int, str]]: + def to_dict(self) -> Optional[Union[Dict[str, Any], float, int]]: """Returns the dict representation of the actual instance""" if self.actual_instance is None: return None diff --git a/src/otari/_client/models/units1.py b/src/otari/_client/models/units1.py new file mode 100644 index 0000000..d586672 --- /dev/null +++ b/src/otari/_client/models/units1.py @@ -0,0 +1,138 @@ +# 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 +from inspect import getfullargspec +import json +import pprint +import re # noqa: F401 +from pydantic import BaseModel, ConfigDict, Field, StrictFloat, StrictInt, StrictStr, ValidationError, field_validator +from typing import Optional, Union +from typing import Union, Any, List, Set, TYPE_CHECKING, Optional, Dict +from typing_extensions import Literal, Self +from pydantic import Field + +UNITS1_ANY_OF_SCHEMAS = ["float", "int"] + +class Units1(BaseModel): + """ + Calls billed on this meter. + """ + + # data type: int + anyof_schema_1_validator: Optional[StrictInt] = None + # data type: float + anyof_schema_2_validator: Optional[Union[StrictFloat, StrictInt]] = None + if TYPE_CHECKING: + actual_instance: Optional[Union[float, int]] = None + else: + actual_instance: Any = None + any_of_schemas: Set[str] = { "float", "int" } + + model_config = { + "validate_assignment": True, + "protected_namespaces": (), + } + + def __init__(self, *args, **kwargs) -> None: + if args: + if len(args) > 1: + raise ValueError("If a position argument is used, only 1 is allowed to set `actual_instance`") + if kwargs: + raise ValueError("If a position argument is used, keyword arguments cannot be used.") + super().__init__(actual_instance=args[0]) + else: + super().__init__(**kwargs) + + @field_validator('actual_instance') + def actual_instance_must_validate_anyof(cls, v): + instance = Units1.model_construct() + error_messages = [] + # validate data type: int + try: + instance.anyof_schema_1_validator = v + return v + except (ValidationError, ValueError) as e: + error_messages.append(str(e)) + # validate data type: float + try: + instance.anyof_schema_2_validator = v + return v + except (ValidationError, ValueError) as e: + error_messages.append(str(e)) + if error_messages: + # no match + raise ValueError("No match found when setting the actual_instance in Units1 with anyOf schemas: float, int. Details: " + ", ".join(error_messages)) + else: + return v + + @classmethod + def from_dict(cls, obj: Dict[str, Any]) -> Self: + return cls.from_json(json.dumps(obj)) + + @classmethod + def from_json(cls, json_str: str) -> Self: + """Returns the object represented by the json string""" + instance = cls.model_construct() + error_messages = [] + # deserialize data into int + try: + # validation + instance.anyof_schema_1_validator = json.loads(json_str) + # assign value to actual_instance + instance.actual_instance = instance.anyof_schema_1_validator + return instance + except (ValidationError, ValueError) as e: + error_messages.append(str(e)) + # deserialize data into float + try: + # validation + instance.anyof_schema_2_validator = json.loads(json_str) + # assign value to actual_instance + instance.actual_instance = instance.anyof_schema_2_validator + return instance + except (ValidationError, ValueError) as e: + error_messages.append(str(e)) + + if error_messages: + # no match + raise ValueError("No match found when deserializing the JSON string into Units1 with anyOf schemas: float, int. Details: " + ", ".join(error_messages)) + else: + return instance + + def to_json(self) -> str: + """Returns the JSON representation of the actual instance""" + if self.actual_instance is None: + return "null" + + if hasattr(self.actual_instance, "to_json") and callable(self.actual_instance.to_json): + return self.actual_instance.to_json() + else: + return json.dumps(self.actual_instance) + + def to_dict(self) -> Optional[Union[Dict[str, Any], float, int]]: + """Returns the dict representation of the actual instance""" + if self.actual_instance is None: + return None + + if hasattr(self.actual_instance, "to_dict") and callable(self.actual_instance.to_dict): + return self.actual_instance.to_dict() + else: + return self.actual_instance + + def to_str(self) -> str: + """Returns the string representation of the actual instance""" + return pprint.pformat(self.model_dump()) + + diff --git a/src/otari/_client/models/update_search_tool_request.py b/src/otari/_client/models/update_search_tool_request.py new file mode 100644 index 0000000..ca86a64 --- /dev/null +++ b/src/otari/_client/models/update_search_tool_request.py @@ -0,0 +1,129 @@ +# 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, Union +from typing_extensions import Annotated +from typing import Optional, Set +from typing_extensions import Self +from pydantic_core import to_jsonable_python + +class UpdateSearchToolRequest(BaseModel): + """ + Update a stored search tool. Omitted fields are unchanged; ``api_key`` rotates in place. + """ # noqa: E501 + 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').") + 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"] + + 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 UpdateSearchToolRequest 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_base (nullable) is None + # and model_fields_set contains the field + if self.api_base is None and "api_base" in self.model_fields_set: + _dict['api_base'] = None + + # 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 expected_updated_at (nullable) is None + # and model_fields_set contains the field + if self.expected_updated_at is None and "expected_updated_at" in self.model_fields_set: + _dict['expected_updated_at'] = None + + # set to None if options (nullable) is None + # and model_fields_set contains the field + if self.options is None and "options" in self.model_fields_set: + _dict['options'] = None + + # set to None if provider (nullable) is None + # and model_fields_set contains the field + if self.provider is None and "provider" in self.model_fields_set: + _dict['provider'] = None + + # set to None if timeout (nullable) is None + # and model_fields_set contains the field + if self.timeout is None and "timeout" in self.model_fields_set: + _dict['timeout'] = None + + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of UpdateSearchToolRequest from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "api_base": obj.get("api_base"), + "api_key": obj.get("api_key"), + "expected_updated_at": obj.get("expected_updated_at"), + "options": obj.get("options"), + "provider": obj.get("provider"), + "timeout": obj.get("timeout") + }) + return _obj + + diff --git a/src/otari/_client/models/usage_entry.py b/src/otari/_client/models/usage_entry.py index f5d2779..212d491 100644 --- a/src/otari/_client/models/usage_entry.py +++ b/src/otari/_client/models/usage_entry.py @@ -17,9 +17,10 @@ import re # noqa: F401 import json -from pydantic import BaseModel, ConfigDict, Field, StrictBool, StrictFloat, StrictInt, StrictStr +from pydantic import BaseModel, ConfigDict, StrictBool, StrictFloat, StrictInt, StrictStr from typing import Any, ClassVar, Dict, List, Optional, Union -from otari._client.models.usage_entry_pricing_breakdown_inner_value import UsageEntryPricingBreakdownInnerValue +from otari._client.models.billing_meters import BillingMeters +from otari._client.models.usage_entry_pricing_breakdown_inner import UsageEntryPricingBreakdownInner from typing import Optional, Set from typing_extensions import Self from pydantic_core import to_jsonable_python @@ -32,7 +33,7 @@ class UsageEntry(BaseModel): api_key_name: Optional[StrictStr] = None attempt_count: Optional[StrictInt] = None attempt_position: Optional[StrictInt] = None - billing_meters: Optional[Dict[str, Any]] = Field(description="An unsaved policy body to explain.") + billing_meters: Optional[BillingMeters] cache_read_tokens: Optional[StrictInt] cache_write_1h_tokens: Optional[StrictInt] cache_write_tokens: Optional[StrictInt] @@ -45,7 +46,7 @@ class UsageEntry(BaseModel): latency_ms: Optional[StrictInt] model: StrictStr policy_name: Optional[StrictStr] = None - pricing_breakdown: Optional[List[Dict[str, UsageEntryPricingBreakdownInnerValue]]] + pricing_breakdown: Optional[List[UsageEntryPricingBreakdownInner]] prompt_tokens: Optional[StrictInt] provider: Optional[StrictStr] request_group_id: Optional[StrictStr] = None @@ -99,14 +100,15 @@ def to_dict(self) -> Dict[str, Any]: exclude=excluded_fields, exclude_none=True, ) - # override the default output from pydantic by calling `to_dict()` of each item in pricing_breakdown (list of dict) + # override the default output from pydantic by calling `to_dict()` of billing_meters + if self.billing_meters: + _dict['billing_meters'] = self.billing_meters.to_dict() + # override the default output from pydantic by calling `to_dict()` of each item in pricing_breakdown (list) _items = [] if self.pricing_breakdown: for _item_pricing_breakdown in self.pricing_breakdown: if _item_pricing_breakdown: - _items.append( - {_inner_key: _inner_value.to_dict() for _inner_key, _inner_value in _item_pricing_breakdown.items()} - ) + _items.append(_item_pricing_breakdown.to_dict()) _dict['pricing_breakdown'] = _items # set to None if api_key_id (nullable) is None # and model_fields_set contains the field @@ -239,7 +241,7 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: "api_key_name": obj.get("api_key_name"), "attempt_count": obj.get("attempt_count"), "attempt_position": obj.get("attempt_position"), - "billing_meters": obj.get("billing_meters"), + "billing_meters": BillingMeters.from_dict(obj["billing_meters"]) if obj.get("billing_meters") is not None else None, "cache_read_tokens": obj.get("cache_read_tokens"), "cache_write_1h_tokens": obj.get("cache_write_1h_tokens"), "cache_write_tokens": obj.get("cache_write_tokens"), @@ -252,10 +254,7 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: "latency_ms": obj.get("latency_ms"), "model": obj.get("model"), "policy_name": obj.get("policy_name"), - "pricing_breakdown": [ - {_inner_key: UsageEntryPricingBreakdownInnerValue.from_dict(_inner_value) for _inner_key, _inner_value in _item.items()} - for _item in obj["pricing_breakdown"] - ] if obj.get("pricing_breakdown") is not None else None, + "pricing_breakdown": [UsageEntryPricingBreakdownInner.from_dict(_item) for _item in obj["pricing_breakdown"]] if obj.get("pricing_breakdown") is not None else None, "prompt_tokens": obj.get("prompt_tokens"), "provider": obj.get("provider"), "request_group_id": obj.get("request_group_id"), diff --git a/src/otari/_client/models/usage_entry_pricing_breakdown_inner.py b/src/otari/_client/models/usage_entry_pricing_breakdown_inner.py new file mode 100644 index 0000000..3579dd7 --- /dev/null +++ b/src/otari/_client/models/usage_entry_pricing_breakdown_inner.py @@ -0,0 +1,151 @@ +# 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 +from inspect import getfullargspec +import json +import pprint +import re # noqa: F401 +from pydantic import BaseModel, ConfigDict, Field, StrictStr, ValidationError, field_validator +from typing import Any, Dict, Optional +from otari._client.models.token_charge_line import TokenChargeLine +from otari._client.models.unit_charge_line import UnitChargeLine +from typing import Union, Any, List, Set, TYPE_CHECKING, Optional, Dict +from typing_extensions import Literal, Self +from pydantic import Field + +USAGEENTRYPRICINGBREAKDOWNINNER_ANY_OF_SCHEMAS = ["Dict[str, object]", "TokenChargeLine", "UnitChargeLine"] + +class UsageEntryPricingBreakdownInner(BaseModel): + """ + UsageEntryPricingBreakdownInner + """ + + # data type: TokenChargeLine + anyof_schema_1_validator: Optional[TokenChargeLine] = None + # 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').") + if TYPE_CHECKING: + actual_instance: Optional[Union[Dict[str, object], TokenChargeLine, UnitChargeLine]] = None + else: + actual_instance: Any = None + any_of_schemas: Set[str] = { "Dict[str, object]", "TokenChargeLine", "UnitChargeLine" } + + model_config = { + "validate_assignment": True, + "protected_namespaces": (), + } + + def __init__(self, *args, **kwargs) -> None: + if args: + if len(args) > 1: + raise ValueError("If a position argument is used, only 1 is allowed to set `actual_instance`") + if kwargs: + raise ValueError("If a position argument is used, keyword arguments cannot be used.") + super().__init__(actual_instance=args[0]) + else: + super().__init__(**kwargs) + + @field_validator('actual_instance') + def actual_instance_must_validate_anyof(cls, v): + instance = UsageEntryPricingBreakdownInner.model_construct() + error_messages = [] + # validate data type: TokenChargeLine + if not isinstance(v, TokenChargeLine): + error_messages.append(f"Error! Input type `{type(v)}` is not `TokenChargeLine`") + else: + return v + + # validate data type: UnitChargeLine + if not isinstance(v, UnitChargeLine): + error_messages.append(f"Error! Input type `{type(v)}` is not `UnitChargeLine`") + else: + return v + + # validate data type: Dict[str, object] + try: + instance.anyof_schema_3_validator = v + return v + except (ValidationError, ValueError) as e: + error_messages.append(str(e)) + if error_messages: + # no match + raise ValueError("No match found when setting the actual_instance in UsageEntryPricingBreakdownInner with anyOf schemas: Dict[str, object], TokenChargeLine, UnitChargeLine. Details: " + ", ".join(error_messages)) + else: + return v + + @classmethod + def from_dict(cls, obj: Dict[str, Any]) -> Self: + return cls.from_json(json.dumps(obj)) + + @classmethod + def from_json(cls, json_str: str) -> Self: + """Returns the object represented by the json string""" + instance = cls.model_construct() + error_messages = [] + # anyof_schema_1_validator: Optional[TokenChargeLine] = None + try: + instance.actual_instance = TokenChargeLine.from_json(json_str) + return instance + except (ValidationError, ValueError) as e: + error_messages.append(str(e)) + # anyof_schema_2_validator: Optional[UnitChargeLine] = None + try: + instance.actual_instance = UnitChargeLine.from_json(json_str) + return instance + except (ValidationError, ValueError) as e: + error_messages.append(str(e)) + # deserialize data into Dict[str, object] + try: + # validation + instance.anyof_schema_3_validator = json.loads(json_str) + # assign value to actual_instance + instance.actual_instance = instance.anyof_schema_3_validator + return instance + except (ValidationError, ValueError) as e: + error_messages.append(str(e)) + + if error_messages: + # no match + raise ValueError("No match found when deserializing the JSON string into UsageEntryPricingBreakdownInner with anyOf schemas: Dict[str, object], TokenChargeLine, UnitChargeLine. Details: " + ", ".join(error_messages)) + else: + return instance + + def to_json(self) -> str: + """Returns the JSON representation of the actual instance""" + if self.actual_instance is None: + return "null" + + if hasattr(self.actual_instance, "to_json") and callable(self.actual_instance.to_json): + return self.actual_instance.to_json() + else: + return json.dumps(self.actual_instance) + + def to_dict(self) -> Optional[Union[Dict[str, Any], Dict[str, object], TokenChargeLine, UnitChargeLine]]: + """Returns the dict representation of the actual instance""" + if self.actual_instance is None: + return None + + if hasattr(self.actual_instance, "to_dict") and callable(self.actual_instance.to_dict): + return self.actual_instance.to_dict() + else: + return self.actual_instance + + def to_str(self) -> str: + """Returns the string representation of the actual instance""" + return pprint.pformat(self.model_dump()) + +