feat(api): update API spec from langfuse/langfuse e5c1a45#1699
feat(api): update API spec from langfuse/langfuse e5c1a45#1699langfuse-bot wants to merge 1 commit into
Conversation
|
@claude review |
| @@ -30,96 +27,109 @@ def with_raw_response(self) -> RawScoresClient: | |||
| def get_many( | |||
There was a problem hiding this comment.
Breaking removal of
get_by_id without a v3 equivalent
The get_by_id(score_id) method has been removed from ScoresClient and AsyncScoresClient. The v3 API has no GET /api/public/v3/scores/:id endpoint, so the nearest workaround is get_many(id=score_id) — but that returns a GetScoresResponse (a list) rather than a single Score. Any caller that previously used client.scores.get_by_id() must be updated; there is no drop-in replacement. The old v2 equivalent is preserved under client.legacy.scores_v2.get_by_id(), but callers still need to be migrated manually.
Prompt To Fix With AI
This is a comment left during a code review.
Path: langfuse/api/scores/client.py
Line: 27
Comment:
**Breaking removal of `get_by_id` without a v3 equivalent**
The `get_by_id(score_id)` method has been removed from `ScoresClient` and `AsyncScoresClient`. The v3 API has no `GET /api/public/v3/scores/:id` endpoint, so the nearest workaround is `get_many(id=score_id)` — but that returns a `GetScoresResponse` (a list) rather than a single `Score`. Any caller that previously used `client.scores.get_by_id()` must be updated; there is no drop-in replacement. The old v2 equivalent is preserved under `client.legacy.scores_v2.get_by_id()`, but callers still need to be migrated manually.
How can I resolve this? If you propose a fix, please make it concise.| def get_many( | ||
| self, | ||
| *, | ||
| page: typing.Optional[int] = None, | ||
| limit: typing.Optional[int] = None, |
There was a problem hiding this comment.
🔴 The autogenerated scores.get_by_id method is removed by this regen (only get_many remains on the new v3 ScoresClient), but tests/e2e/test_core_sdk.py:158 (test_create_session_score) still calls get_api().scores.get_by_id(score_id). Once merged the e2e CI shard will fail immediately with AttributeError: 'ScoresClient' object has no attribute 'get_by_id' — please migrate that one call to get_api().legacy.scores_v2.get_by_id(score_id) (which this same PR adds and which still returns the v2 Score with the flat session_id the test asserts on) in this PR.
Extended reasoning...
What the bug is
This PR is an auto-generated regen of the Fern client that swaps ScoresClient.get_many to the new v3 /api/public/v3/scores endpoint and drops the old ScoresClient.get_by_id method entirely. The replacement is moved to client.legacy.scores_v2.get_by_id (hitting /api/public/v2/scores/{score_id}). The PR does not touch the in-repo test suite.
The triggering code path
tests/e2e/test_core_sdk.py:158 in test_create_session_score does:
score = get_api().scores.get_by_id(score_id)
assert score.value == 1
assert score.data_type == "NUMERIC"
assert score.session_id == session_idget_api() in tests/support/utils.py:68 returns a LangfuseAPI (the generated client) wrapped in a thin retry proxy that forwards attribute access via getattr(self._target, name). So get_api().scores is the new ScoresClient, whose only public method is now get_many. Attribute access for get_by_id therefore raises AttributeError before any HTTP call is ever made.
Why existing code doesn't prevent it
There is no shim or backward-compat alias re-exporting get_by_id on the new ScoresClient. grep -n get_by_id langfuse/api/scores/client.py returns nothing after this PR; the only sibling get_by_id lives at langfuse/api/legacy/scores_v2/client.py:207, which the test does not reference. The synthesis description and all four verifiers independently confirmed both halves (call site exists, method removed).
Impact
tests/e2e/test_core_sdk.py is included in the e2e shards (it is explicitly weighted in scripts/select_e2e_shard.py, and the e2e job in .github/workflows/ci.yml runs pytest against tests/e2e/* on every PR). The failure is deterministic — AttributeError on the first call — so the shard that picks up test_create_session_score will go red the moment this PR is merged, blocking subsequent merges.
Step-by-step proof
- Pytest loads
tests/e2e/test_core_sdk.pyand dispatchestest_create_session_score. - The test calls
get_api()→ returns a_RetryingApiProxyaround aLangfuseAPIinstance (tests/support/utils.py:68). .scores→ proxy forwards toLangfuseAPI.scores→ lazy-instantiatesScoresClient(langfuse/api/client.py, post-PR)..get_by_id(score_id)→ScoresClientonly definesget_many(seelangfuse/api/scores/client.py:27). Python raisesAttributeError: 'ScoresClient' object has no attribute 'get_by_id'.- Test fails before flush/assert; e2e shard fails.
How to fix
One-line change in the same PR:
score = get_api().legacy.scores_v2.get_by_id(score_id)The new ScoresV2Client.get_by_id (added by this PR at langfuse/api/legacy/scores_v2/client.py:166) returns the v2 Score type from commons.types.score, which still has the flat session_id, value, and data_type fields that the test's assertions read — so no other test changes are needed. Migrating to v3 get_many(id=score_id) would work for fetching but the assertion on score.session_id would need updating because v3 ScoreV3 puts session_id on a nested optional subject object that is only populated when fields=subject is requested. The legacy route is the cheaper, safer fix.
Greptile Summary
This PR is a Fern-generated API spec update that restructures the scores API modules: the v3 scores types and client (previously under
scores_v3) are merged into thescoresmodule, the old v2 scores endpoint is moved into a newlegacy/scores_v2sub-client, andscores.get_many()now callsGET /api/public/v3/scoreswith cursor-based pagination and a revised filter set.scores_v3module is deleted and its types/clients are folded intoscores, with renames dropping theV3suffix from subject and meta types (e.g.ScoreSubjectV3→ScoreSubject,GetScoresV3Meta→GetScoresMeta).scores.get_many()gains new filters (cursor,id,author_user_id,value_min,value_max,experiment_id) and drops v2-only params (page,user_id,score_ids,dataset_run_id,operator,trace_tags,filter);scores.get_by_id()is removed with no v3 equivalent.client.legacy.scores_v2, which introduces a newScoresV2Client/AsyncScoresV2ClientwrappingGET /api/public/v2/scores.Confidence Score: 3/5
The migration from
scoresto the v3 endpoint is intentional, but the silent removal ofget_by_idand the incompatibleget_manysignature are breaking changes for any caller that hasn't been updated alongside this PR.The
scores.get_by_id()method is deleted with no v3 drop-in: callers must switch toget_many(id=...)which returns a list, not a single object. Simultaneously,get_manyloses several parameters (page,user_id,score_ids,trace_tags,filter) that existing callers may depend on. If all call-sites have been audited and updated, this is safe; if not, runtime errors or silently wrong behavior will occur.langfuse/api/scores/client.py and langfuse/api/scores/raw_client.py — the removed
get_by_idand the changedget_manyparameter set are the most likely source of breakage for downstream code.Sequence Diagram
sequenceDiagram participant Caller participant ScoresClient as scores.get_many() (v3) participant LegacyScoresV2 as legacy.scores_v2.get_many() (v2) participant API_v3 as GET /api/public/v3/scores participant API_v2 as GET /api/public/v2/scores Caller->>ScoresClient: get_many(cursor, id, value_min, ...) ScoresClient->>API_v3: HTTP GET with cursor pagination API_v3-->>ScoresClient: GetScoresResponse (ScoreV3 list + GetScoresMeta) ScoresClient-->>Caller: GetScoresResponse Caller->>LegacyScoresV2: get_many(page, user_id, score_ids, ...) LegacyScoresV2->>API_v2: HTTP GET with page pagination API_v2-->>LegacyScoresV2: GetScoresResponse (v2 data + MetaResponse) LegacyScoresV2-->>Caller: GetScoresResponse (v2)Prompt To Fix All With AI
Reviews (1): Last reviewed commit: "feat(api): update API spec from langfuse..." | Re-trigger Greptile
Context used:
Learned From
langfuse/langfuse-python#1387