From e5333ee2d5feaa13637f4995183985264f0bca79 Mon Sep 17 00:00:00 2001 From: Niklas Semmler Date: Wed, 7 Oct 2026 17:24:57 +0200 Subject: [PATCH] refactor(api): share cursor pagination meta via CursorMetaResponse Regenerated langfuse/api from the upstream Fern definition: baseline langfuse/langfuse 619dbe3 (last sync, #1866) plus langfuse/langfuse#17888. Split out of the bundled API-spec bot PR #1943. Co-Authored-By: Claude Opus 5.5 (1M context) --- langfuse/api/evaluators/types/cursor_meta.py | 7 +++---- .../types/experiments_response_meta.py | 7 +++---- .../observations/types/observations_v2meta.py | 11 +++------- .../api/scores_v3/types/get_scores_v3meta.py | 8 ++----- langfuse/api/utils/__init__.py | 5 +++-- langfuse/api/utils/pagination/__init__.py | 9 +++++--- .../api/utils/pagination/types/__init__.py | 8 +++++-- .../pagination/types/cursor_meta_response.py | 21 +++++++++++++++++++ 8 files changed, 47 insertions(+), 29 deletions(-) create mode 100644 langfuse/api/utils/pagination/types/cursor_meta_response.py diff --git a/langfuse/api/evaluators/types/cursor_meta.py b/langfuse/api/evaluators/types/cursor_meta.py index 3ee6e1a0a..7e4c64a67 100644 --- a/langfuse/api/evaluators/types/cursor_meta.py +++ b/langfuse/api/evaluators/types/cursor_meta.py @@ -3,13 +3,12 @@ import typing import pydantic -from ...core.pydantic_utilities import UniversalBaseModel +from ...utils.pagination.types.cursor_meta_response import CursorMetaResponse -class CursorMeta(UniversalBaseModel): - cursor: typing.Optional[str] = pydantic.Field(default=None) +class CursorMeta(CursorMetaResponse): """ - Opaque cursor for the next page. Omitted when there is no next page. + Cursor pagination metadata. """ model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict( diff --git a/langfuse/api/experiments/types/experiments_response_meta.py b/langfuse/api/experiments/types/experiments_response_meta.py index 038bcc45d..61f2de4ea 100644 --- a/langfuse/api/experiments/types/experiments_response_meta.py +++ b/langfuse/api/experiments/types/experiments_response_meta.py @@ -3,13 +3,12 @@ import typing import pydantic -from ...core.pydantic_utilities import UniversalBaseModel +from ...utils.pagination.types.cursor_meta_response import CursorMetaResponse -class ExperimentsResponseMeta(UniversalBaseModel): - cursor: typing.Optional[str] = pydantic.Field(default=None) +class ExperimentsResponseMeta(CursorMetaResponse): """ - Versioned base64url cursor for retrieving the next page. Absent when there are no more results. + Metadata for cursor-based pagination. """ model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict( diff --git a/langfuse/api/observations/types/observations_v2meta.py b/langfuse/api/observations/types/observations_v2meta.py index 8f86a6512..46d9f42aa 100644 --- a/langfuse/api/observations/types/observations_v2meta.py +++ b/langfuse/api/observations/types/observations_v2meta.py @@ -3,17 +3,12 @@ import typing import pydantic -from ...core.pydantic_utilities import UniversalBaseModel +from ...utils.pagination.types.cursor_meta_response import CursorMetaResponse -class ObservationsV2Meta(UniversalBaseModel): +class ObservationsV2Meta(CursorMetaResponse): """ - Metadata for cursor-based pagination - """ - - cursor: typing.Optional[str] = pydantic.Field(default=None) - """ - Base64-encoded cursor to use for retrieving the next page. If not present, there are no more results. + Metadata for cursor-based pagination. """ model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict( diff --git a/langfuse/api/scores_v3/types/get_scores_v3meta.py b/langfuse/api/scores_v3/types/get_scores_v3meta.py index 7dfcfe0e1..832793364 100644 --- a/langfuse/api/scores_v3/types/get_scores_v3meta.py +++ b/langfuse/api/scores_v3/types/get_scores_v3meta.py @@ -3,15 +3,11 @@ import typing import pydantic -from ...core.pydantic_utilities import UniversalBaseModel +from ...utils.pagination.types.cursor_meta_response import CursorMetaResponse -class GetScoresV3Meta(UniversalBaseModel): +class GetScoresV3Meta(CursorMetaResponse): limit: int - cursor: typing.Optional[str] = pydantic.Field(default=None) - """ - URL-safe base64 (base64url) cursor for the next page. Absent when there are no more results. - """ model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict( extra="allow", frozen=True diff --git a/langfuse/api/utils/__init__.py b/langfuse/api/utils/__init__.py index b272f64b5..1690ee475 100644 --- a/langfuse/api/utils/__init__.py +++ b/langfuse/api/utils/__init__.py @@ -7,8 +7,9 @@ if typing.TYPE_CHECKING: from . import pagination - from .pagination import MetaResponse + from .pagination import CursorMetaResponse, MetaResponse _dynamic_imports: typing.Dict[str, str] = { + "CursorMetaResponse": ".pagination", "MetaResponse": ".pagination", "pagination": ".pagination", } @@ -41,4 +42,4 @@ def __dir__(): return sorted(lazy_attrs) -__all__ = ["MetaResponse", "pagination"] +__all__ = ["CursorMetaResponse", "MetaResponse", "pagination"] diff --git a/langfuse/api/utils/pagination/__init__.py b/langfuse/api/utils/pagination/__init__.py index 50821832d..59cdf0321 100644 --- a/langfuse/api/utils/pagination/__init__.py +++ b/langfuse/api/utils/pagination/__init__.py @@ -6,8 +6,11 @@ from importlib import import_module if typing.TYPE_CHECKING: - from .types import MetaResponse -_dynamic_imports: typing.Dict[str, str] = {"MetaResponse": ".types"} + from .types import CursorMetaResponse, MetaResponse +_dynamic_imports: typing.Dict[str, str] = { + "CursorMetaResponse": ".types", + "MetaResponse": ".types", +} def __getattr__(attr_name: str) -> typing.Any: @@ -37,4 +40,4 @@ def __dir__(): return sorted(lazy_attrs) -__all__ = ["MetaResponse"] +__all__ = ["CursorMetaResponse", "MetaResponse"] diff --git a/langfuse/api/utils/pagination/types/__init__.py b/langfuse/api/utils/pagination/types/__init__.py index 5c0d83028..85d13aee0 100644 --- a/langfuse/api/utils/pagination/types/__init__.py +++ b/langfuse/api/utils/pagination/types/__init__.py @@ -6,8 +6,12 @@ from importlib import import_module if typing.TYPE_CHECKING: + from .cursor_meta_response import CursorMetaResponse from .meta_response import MetaResponse -_dynamic_imports: typing.Dict[str, str] = {"MetaResponse": ".meta_response"} +_dynamic_imports: typing.Dict[str, str] = { + "CursorMetaResponse": ".cursor_meta_response", + "MetaResponse": ".meta_response", +} def __getattr__(attr_name: str) -> typing.Any: @@ -37,4 +41,4 @@ def __dir__(): return sorted(lazy_attrs) -__all__ = ["MetaResponse"] +__all__ = ["CursorMetaResponse", "MetaResponse"] diff --git a/langfuse/api/utils/pagination/types/cursor_meta_response.py b/langfuse/api/utils/pagination/types/cursor_meta_response.py new file mode 100644 index 000000000..eb30740ac --- /dev/null +++ b/langfuse/api/utils/pagination/types/cursor_meta_response.py @@ -0,0 +1,21 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing + +import pydantic +from ....core.pydantic_utilities import UniversalBaseModel + + +class CursorMetaResponse(UniversalBaseModel): + """ + Metadata for cursor-based pagination. + """ + + cursor: typing.Optional[str] = pydantic.Field(default=None) + """ + Opaque cursor for the next page. Omitted when there is no next page. + """ + + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict( + extra="allow", frozen=True + )