diff --git a/docs/components/costdetails.md b/docs/components/costdetails.md index ada009c..7e29616 100644 --- a/docs/components/costdetails.md +++ b/docs/components/costdetails.md @@ -3,8 +3,8 @@ ## Fields -| Field | Type | Required | Description | -| -------------------------------- | -------------------------------- | -------------------------------- | -------------------------------- | -| `upstream_inference_cost` | *OptionalNullable[float]* | :heavy_minus_sign: | N/A | -| `upstream_inference_input_cost` | *float* | :heavy_check_mark: | N/A | -| `upstream_inference_output_cost` | *float* | :heavy_check_mark: | N/A | \ No newline at end of file +| Field | Type | Required | Description | +| ---------------------------------------- | ------------------------- | ------------------ | ----------- | +| `upstream_inference_completions_cost` | *float* | :heavy_check_mark: | N/A | +| `upstream_inference_prompt_cost` | *float* | :heavy_check_mark: | N/A | +| `upstream_inference_cost` | *OptionalNullable[float]* | :heavy_minus_sign: | N/A | \ No newline at end of file diff --git a/src/openrouter/components/__init__.py b/src/openrouter/components/__init__.py index e41de29..24fabfb 100644 --- a/src/openrouter/components/__init__.py +++ b/src/openrouter/components/__init__.py @@ -1263,9 +1263,8 @@ UpdateGuardrailResponseTypedDict, ) from .urlcitation import URLCitation, URLCitationType, URLCitationTypedDict + from .costdetails import CostDetails, CostDetailsTypedDict from .usage import ( - CostDetails, - CostDetailsTypedDict, InputTokensDetails, InputTokensDetailsTypedDict, OutputTokensDetails, @@ -3319,8 +3318,8 @@ "URLCitation": ".urlcitation", "URLCitationType": ".urlcitation", "URLCitationTypedDict": ".urlcitation", - "CostDetails": ".usage", - "CostDetailsTypedDict": ".usage", + "CostDetails": ".costdetails", + "CostDetailsTypedDict": ".costdetails", "InputTokensDetails": ".usage", "InputTokensDetailsTypedDict": ".usage", "OutputTokensDetails": ".usage", diff --git a/src/openrouter/components/chatusage.py b/src/openrouter/components/chatusage.py index 12b58ec..c915860 100644 --- a/src/openrouter/components/chatusage.py +++ b/src/openrouter/components/chatusage.py @@ -12,6 +12,8 @@ from typing import Optional from typing_extensions import NotRequired, TypedDict +from .costdetails import CostDetails, CostDetailsTypedDict + class CompletionTokensDetailsTypedDict(TypedDict): r"""Detailed completion token usage""" @@ -124,6 +126,11 @@ class ChatUsageTypedDict(TypedDict): r"""Detailed completion token usage""" prompt_tokens_details: NotRequired[Nullable[PromptTokensDetailsTypedDict]] r"""Detailed prompt token usage""" + cost: NotRequired[Nullable[float]] + r"""Cost of the completion""" + cost_details: NotRequired[CostDetailsTypedDict] + is_byok: NotRequired[bool] + r"""Whether a request was made using a Bring Your Own Key configuration""" class ChatUsage(BaseModel): @@ -144,10 +151,24 @@ class ChatUsage(BaseModel): prompt_tokens_details: OptionalNullable[PromptTokensDetails] = UNSET r"""Detailed prompt token usage""" + cost: OptionalNullable[float] = UNSET + r"""Cost of the completion""" + + cost_details: Optional[CostDetails] = None + + is_byok: Optional[bool] = None + r"""Whether a request was made using a Bring Your Own Key configuration""" + @model_serializer(mode="wrap") def serialize_model(self, handler): - optional_fields = ["completion_tokens_details", "prompt_tokens_details"] - nullable_fields = ["completion_tokens_details", "prompt_tokens_details"] + optional_fields = [ + "completion_tokens_details", + "prompt_tokens_details", + "cost", + "cost_details", + "is_byok", + ] + nullable_fields = ["completion_tokens_details", "prompt_tokens_details", "cost"] null_default_fields = [] serialized = handler(self) diff --git a/src/openrouter/components/costdetails.py b/src/openrouter/components/costdetails.py new file mode 100644 index 0000000..7880cdc --- /dev/null +++ b/src/openrouter/components/costdetails.py @@ -0,0 +1,60 @@ +"""Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT.""" + +from __future__ import annotations +from openrouter.types import ( + BaseModel, + Nullable, + OptionalNullable, + UNSET, + UNSET_SENTINEL, +) +from pydantic import model_serializer +from typing_extensions import NotRequired, TypedDict + + +class CostDetailsTypedDict(TypedDict): + r"""Breakdown of upstream inference costs""" + + upstream_inference_completions_cost: float + upstream_inference_prompt_cost: float + upstream_inference_cost: NotRequired[Nullable[float]] + + +class CostDetails(BaseModel): + r"""Breakdown of upstream inference costs""" + + upstream_inference_completions_cost: float + + upstream_inference_prompt_cost: float + + upstream_inference_cost: OptionalNullable[float] = UNSET + + @model_serializer(mode="wrap") + def serialize_model(self, handler): + optional_fields = ["upstream_inference_cost"] + nullable_fields = ["upstream_inference_cost"] + null_default_fields = [] + + serialized = handler(self) + + m = {} + + for n, f in type(self).model_fields.items(): + k = f.alias or n + val = serialized.get(k) + serialized.pop(k, None) + + optional_nullable = k in optional_fields and k in nullable_fields + is_set = ( + self.__pydantic_fields_set__.intersection({n}) + or k in null_default_fields + ) # pylint: disable=no-member + + if val is not None and val != UNSET_SENTINEL: + m[k] = val + elif val != UNSET_SENTINEL and ( + not k in optional_fields or (optional_nullable and is_set) + ): + m[k] = val + + return m