Skip to content

feat(api): update API spec from langfuse/langfuse e5c1a45#823

Closed
langfuse-bot wants to merge 1 commit into
mainfrom
api-spec-bot-e5c1a45
Closed

feat(api): update API spec from langfuse/langfuse e5c1a45#823
langfuse-bot wants to merge 1 commit into
mainfrom
api-spec-bot-e5c1a45

Conversation

@langfuse-bot

@langfuse-bot langfuse-bot commented Jun 10, 2026

Copy link
Copy Markdown
Collaborator

Greptile Summary

This auto-generated PR (from Fern/API spec commit e5c1a45) promotes the v3 scores API to the default scores client and moves the v2 scores API under legacy.scoresV2, while renaming all V3-suffixed types (e.g. ScoreSubjectV3ScoreSubject, GetScoresV3MetaGetScoresMeta).

  • client.scoresV3 is removed; existing callers of scoresV3.getManyV3() must migrate to client.scores.getMany(), which uses cursor-based pagination and changed parameter types.
  • client.scores.getById() is removed and only survives as client.legacy.scoresV2.getById() — which the JSDoc marks unavailable on Langfuse v4+ — leaving no documented v3 single-score fetch path.
  • GetScoresRequest.value changed from number to string and GetScoresResponse.meta changed from page-based (totalItems, totalPages) to cursor-based (cursor) — consumers reading those fields will silently get undefined at runtime.

Confidence Score: 3/5

The generated code is internally consistent, but three concurrent breaking changes touch the public SDK surface: the pagination model for the main scores list endpoint, the type of the value filter parameter, and the removal of a previously-available single-score fetch method with no v3 replacement. Any consumer upgrading without reading the diff will hit runtime errors or silent wrong-data conditions.

The restructuring correctly reflects the API spec and the internal wiring is coherent. However, GetScoresRequest.value flipped from number to string, meta.totalItems/meta.totalPages silently disappear at runtime, and getById is gone from the v3 client with the only surviving fallback already marked deprecated and unavailable on v4+. These compound to meaningful migration risk for existing SDK consumers.

packages/core/src/api/api/resources/scores/client/requests/GetScoresRequest.ts (value type change), packages/core/src/api/api/resources/scores/types/GetScoresResponse.ts (meta shape change), packages/core/src/api/Client.ts (scoresV3 removal)

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    subgraph Before["Before (old API shape)"]
        A1["client.scoresV3.getManyV3()\n→ GET /api/public/v3/scores\nPagination: cursor-based"]
        A2["client.scores.getMany()\n→ GET /api/public/v2/scores\nPagination: page-based"]
        A3["client.scores.getById(scoreId)\n→ GET /api/public/v2/scores/{id}"]
    end

    subgraph After["After (new API shape)"]
        B1["client.scores.getMany()\n→ GET /api/public/v3/scores\nPagination: cursor-based\n(was scoresV3.getManyV3)"]
        B2["client.legacy.scoresV2.getMany()\n→ GET /api/public/v2/scores\nPagination: page-based\n⚠️ deprecated, unavailable on v4+"]
        B3["client.legacy.scoresV2.getById(scoreId)\n→ GET /api/public/v2/scores/{id}\n⚠️ deprecated, unavailable on v4+"]
        B4["No v3 getById\nWorkaround: getMany with id filter"]
    end

    A1 -->|"promoted & renamed"| B1
    A2 -->|"moved to legacy"| B2
    A3 -->|"moved to legacy"| B3
    A3 -.->|"v3 gap"| B4

    style A1 fill:#d4edda
    style A2 fill:#fff3cd
    style A3 fill:#fff3cd
    style B1 fill:#d4edda
    style B2 fill:#f8d7da
    style B3 fill:#f8d7da
    style B4 fill:#f8d7da
Loading
Prompt To Fix All With AI
Fix the following 4 code review issues. Work through them one at a time, proposing concise fixes.

---

### Issue 1 of 4
packages/core/src/api/api/resources/scores/client/requests/GetScoresRequest.ts:33
**`value` type changed from `number` to `string` — silent runtime mismatch for numeric callers**

Any existing TypeScript code that passes `value: 1.0` (a number literal) to `getMany()` will produce a compile error after upgrading, or — if consumers are silently casting — will send the number to the server verbatim where the API now expects a comma-separated string, likely returning HTTP 400. The old `GetScoresRequest.value` was `number` and the client serialized it with `.toString()`; the new spec expects a string for comma-separated exact-value matching. Callers who rely on numeric value filtering need to update to `value: "1.0"` (or `value: "true"/"false"` for boolean scores).

### Issue 2 of 4
packages/core/src/api/Client.ts:201-204
**`client.scoresV3` removed with no runtime-safe fallback**

The public `scoresV3` getter is deleted. Any SDK consumer calling `client.scoresV3.getManyV3(...)` will receive a `TypeError: Cannot read properties of undefined` at runtime (not compile-time, if consuming plain JS or an older type declaration). The replacement is `client.scores.getMany(...)`, but the method name and all request parameters changed as well (`cursor`-based vs `page`-based pagination, `value: string` vs `value: number`, etc.). This warrants an explicit migration note in the changelog or release notes.

### Issue 3 of 4
packages/core/src/api/api/resources/legacy/resources/scoresV2/client/Client.ts:467-474
**Single-score fetch via v3 API has no equivalent — users on Langfuse v4+ are stranded**

`client.scores.getById()` was removed and now only lives in `client.legacy.scoresV2.getById()`, which hits `/api/public/v2/scores/{scoreId}`. The JSDoc on `ScoresV2` explicitly states "This endpoint is no longer available on Langfuse v4 and later." The v3 `scores` client exposes only `getMany()`, so fetching a single score by ID on v4+ requires calling `getMany({ id: scoreId })` and taking the first element — but this is undocumented and there is no `getById` convenience wrapper on the v3 client. Users upgrading a Langfuse v4 deployment will silently hit 404 / 405 if they migrate to `legacy.scoresV2.getById()` without reading the deprecation notice.

### Issue 4 of 4
packages/core/src/api/api/resources/scores/types/GetScoresResponse.ts:8-11
**`GetScoresResponse.meta` shape changed — page-based fields silently disappear at runtime**

`meta` changed from `LangfuseAPI.utils.MetaResponse` (which had `page`, `limit`, `totalItems`, `totalPages`) to `GetScoresMeta` (which has only `limit` and `cursor`). TypeScript consumers who destructure `meta.totalItems` or `meta.totalPages` will compile successfully if their types haven't been updated, but those fields will be `undefined` at runtime, breaking any pagination logic that reads total page count or item count. Any downstream code iterating all pages via `for page in range(1, meta.totalPages + 1)` will silently loop only once or behave incorrectly.

Reviews (1): Last reviewed commit: "feat(api): update API spec from langfuse..." | Re-trigger Greptile

Greptile also left 2 inline comments on this PR.

@vercel

vercel Bot commented Jun 10, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
langfuse-js Ready Ready Preview Jun 10, 2026 1:00pm

Request Review

@github-actions

Copy link
Copy Markdown

@claude review

/** Comma-separated list of author user IDs to filter by. */
authorUserId?: string;
/** Comma-separated list of exact values to filter by. Requires a single dataType from NUMERIC, BOOLEAN, or CATEGORICAL; any other dataType, multiple dataTypes, or omitting dataType returns HTTP 400. For BOOLEAN, each value must be "true" or "false"; for NUMERIC, each value must be a finite number. Otherwise the request returns HTTP 400. */
value?: string;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 value type changed from number to string — silent runtime mismatch for numeric callers

Any existing TypeScript code that passes value: 1.0 (a number literal) to getMany() will produce a compile error after upgrading, or — if consumers are silently casting — will send the number to the server verbatim where the API now expects a comma-separated string, likely returning HTTP 400. The old GetScoresRequest.value was number and the client serialized it with .toString(); the new spec expects a string for comma-separated exact-value matching. Callers who rely on numeric value filtering need to update to value: "1.0" (or value: "true"/"false" for boolean scores).

Prompt To Fix With AI
This is a comment left during a code review.
Path: packages/core/src/api/api/resources/scores/client/requests/GetScoresRequest.ts
Line: 33

Comment:
**`value` type changed from `number` to `string` — silent runtime mismatch for numeric callers**

Any existing TypeScript code that passes `value: 1.0` (a number literal) to `getMany()` will produce a compile error after upgrading, or — if consumers are silently casting — will send the number to the server verbatim where the API now expects a comma-separated string, likely returning HTTP 400. The old `GetScoresRequest.value` was `number` and the client serialized it with `.toString()`; the new spec expects a string for comma-separated exact-value matching. Callers who rely on numeric value filtering need to update to `value: "1.0"` (or `value: "true"/"false"` for boolean scores).

How can I resolve this? If you propose a fix, please make it concise.

Comment on lines 201 to 204
return (this._scoreConfigs ??= new ScoreConfigs(this._options));
}

public get scoresV3(): ScoresV3 {
return (this._scoresV3 ??= new ScoresV3(this._options));
}

public get scores(): Scores {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 client.scoresV3 removed with no runtime-safe fallback

The public scoresV3 getter is deleted. Any SDK consumer calling client.scoresV3.getManyV3(...) will receive a TypeError: Cannot read properties of undefined at runtime (not compile-time, if consuming plain JS or an older type declaration). The replacement is client.scores.getMany(...), but the method name and all request parameters changed as well (cursor-based vs page-based pagination, value: string vs value: number, etc.). This warrants an explicit migration note in the changelog or release notes.

Prompt To Fix With AI
This is a comment left during a code review.
Path: packages/core/src/api/Client.ts
Line: 201-204

Comment:
**`client.scoresV3` removed with no runtime-safe fallback**

The public `scoresV3` getter is deleted. Any SDK consumer calling `client.scoresV3.getManyV3(...)` will receive a `TypeError: Cannot read properties of undefined` at runtime (not compile-time, if consuming plain JS or an older type declaration). The replacement is `client.scores.getMany(...)`, but the method name and all request parameters changed as well (`cursor`-based vs `page`-based pagination, `value: string` vs `value: number`, etc.). This warrants an explicit migration note in the changelog or release notes.

How can I resolve this? If you propose a fix, please make it concise.

Comment on lines 61 to 84
}

/**
* Get a list of scores (supports both trace and session scores)
* Get a list of scores with a polymorphic `value` field (v3).
*
* The `value` field type depends on `dataType`:
* - `NUMERIC` → number
* - `BOOLEAN` → boolean
* - `CATEGORICAL`, `TEXT`, `CORRECTION` → string
*
* The response always includes the core fields: id, projectId, name,
* value, dataType, source, timestamp, environment, createdAt, updatedAt.
*
* Additional field groups can be requested via the `fields` parameter:
* - `details` — adds comment, configId, metadata
* - `subject` — adds the subject object describing the entity the score
* is attached to: kind (trace, observation, session, or experiment),
* id, and traceId for observation-level scores
* - `annotation` — adds authorUserId, queueId
*
* Unknown group names return HTTP 400.
*
* @param {LangfuseAPI.GetScoresRequest} request
* @param {Scores.RequestOptions} requestOptions - Request-specific configuration.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔴 The Scores client class loses its getById(scoreId) method in this PR (relocated to legacy.scoresV2.getById), but tests/e2e/scores.e2e.test.ts still calls assertions.api.scores.getById(...) in 26 places (lines 69, 115, 148, 184, 243-244, 316-317, 391, 437, 488, 531, 596, 691-694, 742, 788, 832, 882, 944, 982, 1029, 1086, 1137). Vitest does not type-check and tsc -b --noEmit excludes tests/, so this surfaces only at runtime as TypeError: assertions.api.scores.getById is not a function, failing pnpm test:e2e and blocking the all-tests-passed merge gate. Fix: update the e2e test call sites (or the helpers/serverAssertions.ts wrapper) to use assertions.api.legacy.scoresV2.getById(scoreId).

Extended reasoning...

What is broken

This PR replaces the v2 Scores client with a new v3-backed client and removes the getById(scoreId, requestOptions) method entirely. The old method (previously at packages/core/src/api/api/resources/scores/client/Client.ts, around lines 230-411 pre-PR) has been relocated to packages/core/src/api/api/resources/legacy/resources/scoresV2/client/Client.ts and is now reachable only as client.legacy.scoresV2.getById(...). The new Scores class exposes only getMany() (Client.ts:95).

How it breaks CI

The in-repo e2e suite at tests/e2e/scores.e2e.test.ts still calls assertions.api.scores.getById(...) in 26 places. assertions.api is a LangfuseAPIClient (see tests/e2e/helpers/serverAssertions.ts:12, 26), so its .scores getter returns the new Scores instance with no getById method.

Why type checking does not catch this

  • The root tsconfig.json references only the packages/* projects; tests/ is not part of the tsc -b --noEmit build graph, so pnpm typecheck will not flag the missing method.
  • The vitest e2e project aliases @langfuse/core to packages/core/dist/index.mjs (built JS). Vitest does not enable typecheck mode (no typecheck.enabled: true, no --typecheck flag in CI), so the TypeScript compiler is never invoked over tests/.
  • Net effect: the only signal is a runtime TypeError: scores.getById is not a function once vitest executes the first call site.

Impact

.github/workflows/ci.yml runs pnpm test:e2e at line 146, and the all-tests-passed job at line 173 has needs: [test-e2e, test-integration, lint]. With every call site throwing, every test in scores.e2e.test.ts fails, the test-e2e job fails, and the merge gate blocks.

Step-by-step proof

  1. pnpm test:e2e runs pnpm run build && vitest run --project=e2e.
  2. Build produces packages/core/dist/index.mjs which re-exports the new Scores class. grep -n "getById" packages/core/src/api/api/resources/scores/client/Client.ts returns zero matches after this PR.
  3. Vitest starts the e2e project, loads tests/e2e/scores.e2e.test.ts, and runs the first describe block.
  4. The first call site, tests/e2e/scores.e2e.test.ts:69await assertions.api.scores.getById(scoreId), resolves assertions.api.scores to the new Scores instance.
  5. Scores.prototype.getById === undefined → Node throws TypeError: assertions.api.scores.getById is not a function.
  6. The test fails. The remaining 25 call sites fail identically. test-e2e job reports failure. all-tests-passed cannot succeed.

How to fix

Update tests/e2e/scores.e2e.test.ts (26 call sites) to call assertions.api.legacy.scoresV2.getById(scoreId) — the new location of the v2 endpoint — or migrate to the v3 pattern assertions.api.scores.getMany({ id: scoreId }) if the tests should target the new endpoint. A small helper on ServerAssertions (e.g. getScoreById(scoreId)) would centralize the change. Since this PR is auto-generated codegen, the maintainer may prefer to land the test migration as a follow-up commit, but it must land before merge to keep CI green.

@wochinge wochinge deleted the api-spec-bot-e5c1a45 branch June 11, 2026 13:09
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant