Compare commits

...
242 Commits
Author SHA1 Message Date
steffen911 30ca47b667 chore: release v3.70.0 2025-06-16 13:14:22 +02:00
Steffen SchmitzGitHubellipsis-dev[bot] <65095814+ellipsis-dev[bot]@users.noreply.github.com>
ce1c1a5016 feat: allow sharded ingestion queue (#7240)
* feat: create outline for redis cluster mode setup

* chore: fix compilation problems

* chore: add redis-cluster docker compose setup

* chore: make cluster config compile

* chore: remove unused env var declarations

* chore: remove experimental queue length metrics flag

* chore: include queue name into prefix

* chore: lint

* chore: update node config

* chore: lint

* chore: tty to skip model match cache

* chore: execute test flush on all nodes

* chore: add aws specific dns lookup

* chore: add ioredis debug logs for tests

* chore: optimize setup for ci

* chore: update example config

* chore: secret

* chore: cleanup

* chore: remove redis cluster testing script

* feat: allow sharded ingestion queue

* Update packages/shared/src/server/redis/ingestionQueue.ts

Co-authored-by: ellipsis-dev[bot] <65095814+ellipsis-dev[bot]@users.noreply.github.com>

* chore: patch

* chore: remove redundent getQueue

* chore: lint

* chore: skip queue metric collection

* chore: release v3.67.1-0

* chore: linting

* chore: release v3.67.1-1

* chore: release v3.67.1-2

* chore: queue metric collection

* chore: update docs

* chore: add docs

---------

Co-authored-by: ellipsis-dev[bot] <65095814+ellipsis-dev[bot]@users.noreply.github.com>
2025-06-16 10:28:55 +00:00
Steffen SchmitzandGitHub ed01cb7d91 chore: upgrade langchain components (#7320) 2025-06-16 10:18:59 +00:00
marliessophieandGitHub 17364919af fix(observation-ui): enhance badge rendering with text truncation and improved value display (#7321) 2025-06-16 10:03:20 +00:00
Hassieb PakzadandGitHub 0c58edcf5e feat(otel): parse trace attributes from trace metadata (#7314)
* feat(otel): parse trace attributes from trace metadata

* add test
2025-06-16 08:02:37 +00:00
Steffen SchmitzandGitHub 90d7c7df98 feat: add redis cluster mode setup (#7162)
* feat: create outline for redis cluster mode setup

* chore: fix compilation problems

* chore: add redis-cluster docker compose setup

* chore: make cluster config compile

* chore: remove unused env var declarations

* chore: remove experimental queue length metrics flag

* chore: include queue name into prefix

* chore: lint

* chore: update node config

* chore: lint

* chore: tty to skip model match cache

* chore: execute test flush on all nodes

* chore: add aws specific dns lookup

* chore: add ioredis debug logs for tests

* chore: optimize setup for ci

* chore: update example config

* chore: secret

* chore: cleanup

* chore: remove redis cluster testing script
2025-06-16 07:51:08 +00:00
Max DeichmannandGitHub 07fbae3da7 security: upgrade react-syntax-highlighter (#7313) 2025-06-16 07:35:15 +00:00
steffen911 b4bd8208c3 chore: release v3.69.0 2025-06-16 09:35:37 +02:00
Max DeichmannandGitHub c8b282dc82 chore: upgrade react email (#6358)
* chore: upgrade react email

* chore: upgrade react email

* chore: upgrade react email

* chore: upgrade react email

* upgrade

* upgrade
2025-06-15 13:05:52 +00:00
Max DeichmannandGitHub e2922aa787 fix: fix select all UI bug (#7312) 2025-06-15 12:13:25 +00:00
Max DeichmannandGitHub e8690eeb0b chore: clean up scripts (#7306)
chore: clean up
2025-06-13 23:05:34 +00:00
Max DeichmannandGitHub a695d58e8e chore: improve search tooltip (#7305)
push
2025-06-13 22:59:11 +00:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
b097a98444 chore(deps): bump next from 14.2.26 to 14.2.30 (#7301)
Bumps [next](https://github.com/vercel/next.js) from 14.2.26 to 14.2.30.
- [Release notes](https://github.com/vercel/next.js/releases)
- [Changelog](https://github.com/vercel/next.js/blob/canary/release.js)
- [Commits](https://github.com/vercel/next.js/compare/v14.2.26...v14.2.30)

---
updated-dependencies:
- dependency-name: next
  dependency-version: 14.2.30
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-06-13 19:12:39 +00:00
Max DeichmannandGitHub 87c6d45a01 security: upgrade release-it (#7300) 2025-06-13 17:27:23 +00:00
d5a79b1830 chore(ui) Update LLM connection API key message (#7278)
Update API key description based on cloud or self-hosted deployment

Co-authored-by: Cursor Agent <cursoragent@cursor.com>
2025-06-13 16:22:56 +00:00
Steffen SchmitzandGitHub 40b967c258 fix: add auth headers to ctx within middleware, update not found logging (#7295) 2025-06-13 11:56:14 +00:00
marliessophieandGitHub b6b7a7c670 chore(dialog): move close button to DialogHeader for improved accessibility (#7294)
refactor(dialog): move close button to DialogHeader for improved accessibility
2025-06-13 11:08:07 +00:00
Hassieb PakzadandGitHub 346e787784 fix(prompts-api): make updates via API concurrency safe (#7287)
* fix(prompts-api): make updates via API concurrency safe

* push
2025-06-13 10:04:57 +00:00
Steffen SchmitzandGitHub 8e67f851b0 fix: keep zod/v3 schema for langchainjs interactions (#7293)
Patches https://github.com/langchain-ai/langchainjs/issues/8357
2025-06-13 09:33:40 +00:00
marliessophieandGitHub 8b416da2ef fix(PopoverFilterBuilder): ensure filter buttons do not submit forms (#7290) 2025-06-13 09:29:59 +00:00
marliessophieandGitHub 88237dcb30 fix(evals): add missing Dialog Body and Footer components (#7289) 2025-06-13 09:12:35 +00:00
Steffen SchmitzandGitHub 8a0b3962ac chore: upgrade zod to v4 (#7271)
* chore: upgrade zod to v4

* chore: docs

* chore: switch enums to non-deprecated api

* chore: remove unnecessary any

* chore: reverts

* chore: cleanup

* chore: cleanup

* chore: prompts filter tags

* chore: fix sync tests

* chore: patch tests
2025-06-13 08:04:27 +00:00
marliessophieandGitHub 2f6414bbf4 fix(dataset-items): add sorting by id for deterministic ordering (#7280) 2025-06-13 07:34:48 +00:00
c7aa992586 feat: add export functionality to audit log table (#7202)
Co-authored-by: Max Deichmann <m.deichmann@tum.de>
2025-06-12 20:48:58 +02:00
marliessophieandGitHub c2b5923e88 fix(NewDatasetItemForm): add JSON formatting utility for input, output, and metadata field (#7265)
* fix(NewDatasetItemForm): add JSON formatting utility for input, output, and metadata fields

* perf(NewDatasetItemFromExistingObject): conditionally render NewDatasetItemForm based on form state

* fix(NewDatasetItemForm): update JSON value check to handle undefined case
2025-06-12 17:57:22 +00:00
marliessophieandGitHub fc411d0c5c style(CommentList): reduce font size for author username (#7277) 2025-06-12 17:57:08 +00:00
marliessophieandGitHub 3fac8d2608 style(sessions): align header pills (#7282) 2025-06-12 16:38:55 +00:00
marliessophieandGitHub cd413fa887 style(TagButton): reduce size of spinner icon (#7281) 2025-06-12 16:29:11 +00:00
Marc KlingenandGitHub be7cc835be fix(trpcErrorToast): enhance error handling for 5xx server errors wit… (#7279)
fix(trpcErrorToast): enhance error handling for 5xx server errors with user-friendly message
2025-06-12 16:23:43 +00:00
marliessophieandGitHub b68896d14a refactor(DataTableToolbar): reposition PopoverFilterBuilder for improved UX (#7275) 2025-06-12 15:22:58 +00:00
Marc Klingen aae1909466 chore: release v3.68.0 2025-06-12 17:45:04 +02:00
Steffen SchmitzandGitHub 3d7960f43e fix: propagate searchQuery to deleteMany call (#7274)
* fix: propagate searchQuery to deleteMany call

* chore: address feedback

* chore: propagate filters from frontend
2025-06-12 14:16:35 +00:00
Hassieb PakzadandGitHub a121e24b79 feat(otel-ingestion): handle long-running traces (#7241)
* feat(otel-ingestion): handle long-running traces

* rename

* push

* push

* add tests

* add test

* use logger and update cache key

* refactor to OtelIngestionProcessor

* fix

* fix

* fix

* push

* fix graph view
2025-06-12 12:06:17 +00:00
7279a924ed fix: add llm_api_key_update to events, fix linting & call chain (#7160)
* feat: add ability to update llm api keys

* fix: add llm_api_key_update to events, fix linting & call chain

* fix: security issue, deleting last headers, typing

* fix: remove unused variable

* fix: remove unused variable

* refactor: align LlmApiKeys type with shared package across the components

* push fixes

* push fixes

* push fixes

* push fixes

* push fixes

* push fixes

---------

Co-authored-by: Max Deichmann <m.deichmann@tum.de>
2025-06-12 11:57:38 +00:00
Max DeichmannandGitHub a10951b7e5 chore: allow trace deletions on entire history (#7252)
push
2025-06-12 11:57:04 +00:00
marliessophieandGitHub e456b08f92 fix(trace-graph): validate node existence before selection and handle errors gracefully (#7272) 2025-06-12 11:46:02 +00:00
85130cecb3 feat(cloud): 2-step sign in to make enterprise sso easier (#7250)
* chore: update `pnpm dx-f` to require no confirmation

* chore: setup cursor background agent

* Implement two-step login flow with SSO domain detection

* Simplify SSO fallback logic in sign-in page

* Conditionally render credentials form based on auth provider config

* Reorder SSO buttons and error display in sign-in page layout

* Checkpoint before follow-up message

* add focus password

* skip two step if no sso configured

---------

Co-authored-by: Cursor Agent <cursoragent@cursor.com>
2025-06-12 09:52:29 +00:00
marliessophieandGitHub fbb15e26ec fix(dialog): adjust dialog component styling to prevent overflow issues (#7264)
* fix(dialog): adjust dialog component styling to prevent overflow issues

* refactor(dialog): simplify dialog footer styling across multiple components
2025-06-12 08:36:33 +00:00
Marc KlingenandGitHub dd203a1f18 chore: setup cursor background agent (#7251)
* chore: update `pnpm dx-f` to require no confirmation

* chore: setup cursor background agent

* push
2025-06-11 22:06:15 +00:00
Marc KlingenandGitHub 06c25f9ec3 chore: update pnpm dx-f to require no confirmation (#7249) 2025-06-11 21:23:07 +00:00
marliessophieandGitHub 7072ca2786 fix(popover): update max-width calculation for popover component to use fit-content (#7248) 2025-06-11 20:30:12 +00:00
marliessophieandGitHub cb1e5f4c19 fix(TracesTable): stabilize control column definition (#7247)
* fix(TracesTable): stabilize control column definition

- Ensured conditional rendering of the bookmarked column remains intact while simplifying the structure.

* refactor(TracesTable): enhance column visibility and order identifiers for control states
2025-06-11 19:36:46 +00:00
Steffen SchmitzandGitHub d4a28aa164 chore: upgrade clickhouse client dependency (#7246) 2025-06-11 18:40:43 +00:00
marliessophieandGitHub fda5fcdd0c refactor(dialog): improve dialog component layout and styling for billing settings (#7245)
- Updated dialog header to use a title component and improved button layout for clarity.
- Adjusted positioning of the close button for better alignment.
- Enhanced header and footer with rounded corners for a more polished look.
2025-06-11 16:39:42 +00:00
Marc KlingenandGitHub 24131e0791 feat(cloud): add stripe productid of cloud enterprise plan (#7244) 2025-06-11 16:14:16 +00:00
Marc KlingenandGitHub ffe132403e chore(cloud): increase user limit on core plan (#7243) 2025-06-11 15:51:39 +00:00
marliessophieandGitHub cce3bf35e1 fix(CreateExperimentsForm): clear modelConfig errors when valid model parameters are set and adjust layout spacing (#7233) 2025-06-11 10:34:06 +00:00
marliessophieandGitHub eccfec36e8 feat(MarkdownViewer): add URL sanitization using DOMPurify for safe link rendering (#7232) 2025-06-11 09:31:29 +00:00
Hassieb PakzadandGitHub a71faa4e60 feat(model-prices): add o1-pro (#7229) 2025-06-11 08:41:26 +00:00
b7362258c6 fix(ui): enable clipboard copying for self-hosted instances (#7227)
* fix(ui): Enable clipboard copying in insecure browser contexts

* Fixes #5541

* Adds clipboard utility file to manage copy interactions

* Implements fallback method for scenarios lacking Clipboard API
  support in insecure contexts (e.g., HTTP resources not delivered locally)

* Suggested review comments addressed

* chore: eslint

* chore: apply copy functionality to new occurrences

---------

Co-authored-by: akshitvijay <akshitthevijay@gmail.com>
2025-06-11 08:35:08 +00:00
Hassieb PakzadandGitHub 5eb1d98985 fix(graph-view): do not JSON parse node names (#7228) 2025-06-11 10:13:06 +02:00
Marlies Mayerhofer 1c574b2a5d chore: release v3.67.0 2025-06-11 01:39:36 +02:00
marliessophieandGitHub 6db9b87b6a chore(models): adjust price of o3 to reflected updated openai pricing (#7223) 2025-06-10 22:30:07 +00:00
marliessophieandGitHub 3e3ccb65ff feat(models): add o3-pro for cost tracking (#7222)
* feat(models): add o3-pro for playground and costs

* chore: remove from playground as langchain does not support o3 model for completions
2025-06-10 22:23:28 +00:00
marliessophieandGitHub 0d53b443e5 style(CreateScoreConfigButton): add padding to confirmation message for improved readability (#7220) 2025-06-10 16:26:16 +00:00
marliessophieandGitHub 1b795a3dcf chore(evals): show warning if API key was deleted (#7053)
* chore(evals): show warning if API key was deleted

* chore: fix typo
2025-06-10 15:44:36 +00:00
Hassieb PakzadandGitHub 2e94bc9e09 fix(graph-view): handle missing __start__ node for langgraph>=0.4 (#7215) 2025-06-10 15:44:12 +00:00
marliessophieandGitHub 8b94e8a3bd fix(annotation): handle deletes gracefully and protect against race conditions (#6848) 2025-06-10 15:00:43 +00:00
marliessophieandGitHub 91730a2eaf refactor(dialogs): dialog components with improved structure and styling (#7218) 2025-06-10 14:40:26 +00:00
marliessophieandGitHub 4f1a2337be fix(datasets): prevent delete modal from closing on mouse navigation event (#7163) 2025-06-10 14:30:05 +00:00
Hassieb PakzadandGitHub 4cf5aa03ec fix(trpc-prompts-api): handle prompt not found case on setLabels (#7216) 2025-06-10 13:00:23 +00:00
Steffen SchmitzandGitHub 922eafd4f6 chore: refactor chart display names into single util (#7209) 2025-06-10 07:29:06 +00:00
Hassieb PakzadandGitHub 9067f80206 fix(evals): do not throw errors if eval model does not consistently return JSON (#7187) 2025-06-08 14:05:51 +00:00
Steffen SchmitzandGitHub a7ca1fb269 chore: show frontend name for histogram chart type (#7181) 2025-06-06 15:09:54 +00:00
Hassieb PakzadandGitHub b51f321d22 feat(quickstart+readme): add python SDK v3 examples (#7157) 2025-06-06 16:36:16 +02:00
Hassieb PakzadandGitHub dd048a64a0 chore: upgrade langchain (#7178)
* chore: upgrade langchain

* push
2025-06-06 11:41:08 +00:00
ClemoandGitHub c6c19de0e8 docs: update readme, add terraform templates 2025-06-06 11:25:16 +02:00
marliessophieandGitHub 5491f176e1 chore(datasets): simplify DatasetAnalytics component interaction and integrate local storage for chart metrics (#7161)
* chore(datasets): simplify DatasetAnalytics component interaction and integrate local storage for chart metrics

* chore: eslint
2025-06-05 16:10:06 +00:00
marliessophieandGitHub 7a28473ebb perf(traces-table): improve performance (#7126)
* fixup: limit render duration of traces table

* fixup: reduce render cycles through data flows and memoization

* refactor: enhance performance and structure of table components

- Removed unnecessary console logs in `data-table.tsx`.
- Refactored `TablePeekView` to use a more structured props type and memoization for improved performance.
- Updated `usePeekData` to reduce stale time from 5 minutes to 1 minute.
- Replaced `IOTableCell` with `MemoizedIOTableCell` in various components to optimize rendering.
- Adjusted `peekView` configurations in `observations.tsx` and `traces.tsx` for consistency and clarity.

* chore: eslint
2025-06-05 14:16:10 +00:00
Steffen SchmitzandGitHub 005ce7318c chore: allow bullmq-api for non-cloud deployments (#7156) 2025-06-05 12:22:18 +00:00
marliessophieandGitHub 448c56e114 feat(dialog): add sticky header and footer (#7154)
* chore(ui-components): add dialog body

* style(popover): update width styling to use CSS variable for dynamic sizing

* feat(dialog): add DialogBody and DialogFooter components to enhance dialog structure

* chore: eslint

* chore: adjust modal height
2025-06-05 12:05:31 +00:00
Hassieb PakzadandGitHub 1d6e498e2b fix(otel): read resourceAttributes for release attribute (#7155) 2025-06-05 11:38:13 +00:00
Steffen SchmitzandGitHub 33ab717ae0 chore: include LANGFUSE_USE_AZURE_BLOB in docker-compose options (#7153) 2025-06-05 08:29:05 +00:00
Steffen SchmitzandGitHub ec563b775b feat(dashboards): add histogram chart type (#7140)
* feat(dashboards): add histogram chart type

* chore: update querybuilder behaviour

* chore: lint

* chore: push

* chore: format numbers nicely

* chore: store histogram bins in chartConfig

* chore: change order

* chore: add histogram function to metrics api

* chore: docs

* chore: generate docs
2025-06-05 07:43:35 +00:00
marliessophieandGitHub de427b5572 chore(evals): implement update confirmation for default evaluation model (#7137)
* chore(evals): implement update confirmation for default evaluation model

* chore: adjust alert to confirm

* chore: adjust alert to confirm
2025-06-04 17:08:44 +00:00
Marc Klingen 95921fa5da chore: release v3.66.1 2025-06-04 11:09:25 +02:00
Marc KlingenandGitHub 9e4d352366 fix(ee): pro plan label (#7136)
fix(ee): self-hosted pro plan label
2025-06-04 08:57:50 +00:00
steffen911 02449cbe0a chore: release v3.66.0 2025-06-04 09:24:50 +02:00
Steffen SchmitzandGitHub 616c68a87b feat: add support for new OTEL semantic event types (#7135) 2025-06-04 07:06:07 +00:00
Steffen SchmitzandGitHub 319b22ae78 chore: disentangle batch actions from batch exports (#7092)
* chore: disentangle batch actions from batch exports

* chore: revert

* chore: revert

* chore: revert
2025-06-04 06:53:52 +00:00
Max Deichmann b919562eed chore: release v3.65.3 2025-06-04 01:17:23 +02:00
Max DeichmannandGitHub 91c01e7363 chore: allow annotation queues on FOSS (#7130)
chore: move features
2025-06-03 22:17:02 +00:00
Max DeichmannandGitHub 48ec1bccae fix: fix full text search selector (#7129)
* push

* fix: annotation queue count

* chore: move features

* chore: move features

* chore: move features
2025-06-03 22:04:49 +00:00
steffen911 66aa2fd48e chore: release v3.65.2 2025-06-03 22:02:11 +02:00
Steffen SchmitzandGitHub f822bf1049 chore: add opt-out flag from queue length metric checks (#7123) 2025-06-03 19:21:35 +00:00
Hassieb PakzadGitHubellipsis-dev[bot] <65095814+ellipsis-dev[bot]@users.noreply.github.com>
96ec24aad8 fix(otel): set trace io from root span (#7127)
* fix(otel): set trace io from root span

* Update web/src/features/otel/server/index.ts

Co-authored-by: ellipsis-dev[bot] <65095814+ellipsis-dev[bot]@users.noreply.github.com>

---------

Co-authored-by: ellipsis-dev[bot] <65095814+ellipsis-dev[bot]@users.noreply.github.com>
2025-06-03 16:48:58 +00:00
steffen911 068fbd0cc6 chore: release v3.65.1 2025-06-03 11:33:30 +02:00
Steffen SchmitzandGitHub 7c8b76d573 security: bump tar-fs, rollup version (#7116)
* security: bump tar-fs version

* chore: bump rollup version
2025-06-03 08:13:54 +00:00
Max Deichmann e4e93d64bb chore: release v3.65.0 2025-06-03 10:09:46 +02:00
Max DeichmannandGitHub f5cf8693e9 chore: move core features to OSS (#7091)
* chore: move features

* chore: move features

* chore: move features

* chore: move features

* chore: move features

* chore: move features

* chore: move features

* chore: move features

* chore: move features

* chore: move features

* chore: move features

* chore: move features

* chore: move features

* chore: move features

* chore: move features

* changes to pro plan

* chore: move features
2025-06-03 08:07:45 +00:00
marliessophieandGitHub 5beef28214 style(scores): limit height of grouped scores hovercard (#7106) 2025-06-02 10:59:46 +00:00
marliessophieandGitHub d93712c6ab chore: sort dataset (run) items by created_at and id (#7105)
* `created_at` is not unique, we require a deterministic order of items to ensure data consistency
2025-06-02 10:46:46 +00:00
Hassieb PakzadandGitHub b1b0a966be fix(projects-api-docs): retentionDays to optional (#7103) 2025-06-02 11:49:25 +02:00
b5edadb203 fix: update Google AI Studio model name to preview version (#7086) (#7102)
Co-authored-by: Faris Ibrahim <faris@traba.work>
2025-06-02 11:23:51 +02:00
marliessophieandGitHub 3090882590 fix(default-model): allow set up flow to add LLM API key (#7101) 2025-06-02 07:58:37 +00:00
Max DeichmannandGitHub 787f5d8d10 chore: remove popup from count for historic eval elements (#7098)
* chore: move features

* chore: move features

* chore: move features
2025-05-30 21:25:50 +00:00
Jannik MaierhöferandGitHub 5fa142eda4 chore(ui): changed wording on checkout page (#7045) 2025-05-30 10:05:15 +00:00
steffen911 d96865b019 chore: release v3.64.0 2025-05-30 11:25:55 +02:00
Steffen SchmitzandGitHub 8d808923a1 feat: allow host credentials for blob storage S3 integration (#7072)
* feat: allow host credentials for blob storage S3 integration

* chore: compilation errors
2025-05-30 09:07:52 +00:00
Max DeichmannandGitHub 0f056c1c2d fix: add error message for missing encryption key for self-hosters (#7090)
push
2025-05-30 08:40:50 +00:00
Max DeichmannandGitHub 094a523795 perf: use trace identifier stream to batch delete traces (#7081) 2025-05-29 20:08:27 +02:00
Marc KlingenandGitHub c60e58a568 feat(ui): misc improvements to dashboards including mobile view, big number chart, truncate title/description, enforce min height/width of widgets (#7082)
* truncate title and description to prevent wraps

* remove unnecessary padding from charts

* improve bignumber chart

* add min h/w

* mobile resizing

* fix
2025-05-29 15:58:38 +00:00
Max DeichmannGitHubellipsis-dev[bot] <65095814+ellipsis-dev[bot]@users.noreply.github.com>
6147e9c518 perf: only read trace identifiers for historic eval read stream (#7080)
* push

* Update packages/shared/src/server/services/traces-ui-table-service.ts

Co-authored-by: ellipsis-dev[bot] <65095814+ellipsis-dev[bot]@users.noreply.github.com>

* perf: add exact timestamp match for eval batch actions

---------

Co-authored-by: ellipsis-dev[bot] <65095814+ellipsis-dev[bot]@users.noreply.github.com>
2025-05-29 14:35:39 +00:00
Max DeichmannandGitHub f0408b208e perf: add exact timestamp match for eval batch actions (#7077)
* perf: add exact timestamp match for eval batch actions

* perf: add exact timestamp match for eval batch actions

* perf: add exact timestamp match for eval batch actions
2025-05-29 10:54:13 +00:00
Steffen SchmitzandGitHub 55e0bdcac0 feat: allow validation and run now for blob storage integrations (#7064)
* feat: allow validation and run now for blob storage integrations

* chore: error handling and formatting

* lint

* chore: linting
2025-05-28 16:47:23 +00:00
Hassieb PakzadandGitHub 05e15c9f53 fix(otel): update trace name only for root spans (#7061)
* fix(otel): update trace name only for root spans

* push
2025-05-28 15:30:37 +00:00
Max DeichmannandGitHub ce6249b266 perf: data retention concurrency (#7065) 2025-05-28 17:36:20 +02:00
Max DeichmannandGitHub 83e91e5bf5 chore: add logging to retry queue (#7062)
fix: do not wrap traces toolbar
2025-05-28 13:58:46 +00:00
Hassieb PakzadandGitHub edf073cc18 feat(api-models): return model prices on public API (#7046)
* feat(api-models): return model prices on public API

* add tests

* add openapi spec

* return map instead of list
2025-05-28 13:24:20 +00:00
Hassieb Pakzad 65343a8e9b chore: release v3.63.1 2025-05-28 14:17:40 +02:00
Max DeichmannandGitHub 0978055bdc chore: rename dead letter retry queue (#7058)
* push

* push

* push
2025-05-28 11:54:11 +00:00
Max DeichmannandGitHub 76aaf2a3d0 chore: upgrade clickhouse node client (#6806)
* push

* fix: do not wrap traces toolbar

* fix: do not wrap traces toolbar

* fix: do not wrap traces toolbar
2025-05-28 07:57:14 +00:00
Max DeichmannandGitHub 8ed61bf705 perf: increase retry batch action queue (#7049)
push
2025-05-27 19:59:47 +00:00
Steffen SchmitzandGitHub 45436530b4 chore: add analytic views in ClickHouse (#7034)
* chore: add analytic views in ClickHouse

* chore: add additional properties

* chore: add filtering and order changes
2025-05-27 15:59:12 +00:00
Hassieb PakzadandGitHub 7a3f01fc0a fix(playground): resolve prompts when jumping to playground (#7041)
* fix(playground): resolve prompts when jumping to playground

* push
2025-05-27 14:36:40 +00:00
marliessophieandGitHub 468fc4d079 chore(evals): display default model on peek (#7042) 2025-05-27 14:19:11 +00:00
Hassieb PakzadandGitHub 945d13dac0 fix(playground): update tools and schemas if name already exists (#7039)
* fix(playground): update tools and schemas if name already exists

* push
2025-05-27 13:38:59 +00:00
Marc KlingenandGitHub 3646eaa5a8 feat(model): add regex for claude-sonnet-4@20250514 (#7035) 2025-05-27 00:50:10 +00:00
marliessophieandGitHub feb5af11b8 style: default evaluation model management components (#7028) 2025-05-26 16:57:08 +00:00
marliessophieandGitHub 3711af5663 fix: prompt variables of SQL Semantic Equivalence evaluator (#7029) 2025-05-26 14:56:35 +00:00
marliessophieandGitHub 9ec798f393 feat(evaluation): allow filtering by log status (#7018) 2025-05-26 14:43:57 +00:00
Hassieb PakzadandGitHub f71fd43d91 fix(llm-tool-dialog): do not propagate textarea keystrokes up (#7023)
* fix(llm-tool-dialog): do not propagate textarea keystrokes up

* push
2025-05-26 13:51:51 +00:00
marliessophieandGitHub 0303596420 fix(scores): conditionally render metadata in score badges (#7020) 2025-05-26 11:31:50 +00:00
marliessophieandGitHub cfaccc46d3 chore: ensure eval config modal closes after successful delete (#7015)
* chore: ensure eval config modal closes after successful delete

* chore: eslint
2025-05-26 10:21:47 +00:00
Max DeichmannandGitHub 907f764adc fix: do not wrap traces toolbar (#7019)
* fix: do not wrap traces toolbar

* fix: do not wrap traces toolbar
2025-05-26 10:18:23 +00:00
Hassieb PakzadandGitHub 652e9e3fe5 fix(otel): set trace name only if root span or attr provided (#7017) 2025-05-26 09:59:59 +00:00
Steffen SchmitzGitHubellipsis-dev[bot] <65095814+ellipsis-dev[bot]@users.noreply.github.com>
48673e43d7 feat: allow propagation of request headers through logs (#6979)
* feat: allow propagation of request headers through logs

* chore: propagate under correct name

* chore: take all header values

* chore: allow more properties in context propagation

* chore: update trpc propagation

* Update packages/shared/src/env.ts

Co-authored-by: ellipsis-dev[bot] <65095814+ellipsis-dev[bot]@users.noreply.github.com>

* chore: trace header props for ingestion api

* chore: rename env variable

* chore: remove unused comments

* chore: remove outdated addUserToSpan method

---------

Co-authored-by: ellipsis-dev[bot] <65095814+ellipsis-dev[bot]@users.noreply.github.com>
2025-05-26 07:33:02 +00:00
Marlies Mayerhofer a136ac8184 chore: release v3.63.0 2025-05-24 14:05:07 +02:00
marliessophieandGitHub 9ebf62fc9c chore: do not alert on missing API keys or model (#7007)
* chore: change error string for LLM API key not found

* chore: push

* chore: do not alert on missing default model
2025-05-24 07:16:17 +00:00
Max DeichmannGitHubellipsis-dev[bot] <65095814+ellipsis-dev[bot]@users.noreply.github.com>
cf52dce773 chore: fix dataset eval executions for historic evals (#7001)
* push

* fix

* push

* fix

* fix

* fix

* fix

* fix

* fix

* Update worker/src/ee/evaluation/evalService.ts

Co-authored-by: ellipsis-dev[bot] <65095814+ellipsis-dev[bot]@users.noreply.github.com>

* fix

* fix

---------

Co-authored-by: ellipsis-dev[bot] <65095814+ellipsis-dev[bot]@users.noreply.github.com>
2025-05-23 17:44:21 +00:00
marliessophieandGitHub 0a6ecf1cba feat: evaluator library (#6956)
* chore: make `project_id` nullable on `eval_templates`

* feat: add script for managed langfuse evaluators

* feat: restyle running evaluator configs table

* feat: add peek view for running evals

* fixup: add peek view for evaluator library

* fixup: add configure button to table

* feat: rework eval creation flow

* feat: add option to edit eval from table

* fixup: configure evaluator flow with traces data preview

* style: eval configuration UI elements

* chore: add support for current langfuse templates

* chore: reference templateId on jobExecution

* style: add maintainer icon across

* chore: extract WorkerEvaluationVariableService

* fixup: support live data mapping interface

* fixup: revamp datasets eval ui

* fixup: add clone functionality

* chore: rename online evaluation -> llm-as-a-judge

* feat: add evaluator selection in experiment creation flow

* chore: refactor into hooks in experiment form

* feat: add ragas evaluator prompt templates

* chore: show evaluator prompt preview by default

* fix: eval table filtering

* feat: add input box to slider

* fix: clean up running eval peek view and logs

* fix: ensure preview variables are not wrapped in quotes in evaluation prompt preview

* feat: support navigating through traces table

* feat: support default model workflow

* fix: typos in managed evaluators

* fix: do not allow selection of evaluators requiring default to run

* fix: type and build errors

* chore: rename table to default_llm_model

* chore: rm empty file

* fixup: complete rename

* chore: push

* style: eval set up form

* style: separate new evaluator form out into two steps

* chore: ensure we only run evals if default model is set

* chore: add `partner` col to `eval_templates`

* style: new eval template creation

* chore: add proper mapping for dataset evals

* feat: also put evaluation selection on datasets page

* feat: datasets also run on historic experiments after creating mapping

* revert: 09ab242dc12c8647bc716c84d180bc8e631d4919

* chore: fix eslint and ts

* chore: fix warnings

* fix: ensure we inactivate all job configs that rely on default eval model

* fix: tests

* chore: fix eslint

* chore: wrap in tx

* chore: fix default model checkbox logic

* chore: improve wording on delete model

* fix: eslint

* chore: adjust migration order

* style: push ui improvements

* style: sort templates by partner

* fix: eslint
2025-05-23 17:10:47 +00:00
Steffen SchmitzandGitHub c359900b59 perf: skip S3 list calls for OTEL observations (#6995)
* perf: skip S3 list calls for OTEL observations

* chore: reuse prefix definition
2025-05-23 14:04:40 +00:00
Steffen SchmitzandGitHub 720ed7a36f feat: add new /api/public/organizations/projects route to list projects (#6997)
* feat: add new /api/public/organizations/projects route to list projects

* chore: address typos
2025-05-23 13:56:07 +00:00
Marc KlingenandGitHub 1dbefb0994 feat(cloud): push orgs as tenants to plain (#6986)
* fix: plain initialization issues via updatequeue

* apply to the show cb

* chore

* catch errors

* feat(cloud): push orgs as tenants to plain

* add PLAIN_CARDS_API_TOKEN

* fix

* fix

* limit to cloud

* fix
2025-05-23 13:17:45 +00:00
Jannik MaierhöferandGitHub abfdd2366a chore: lw3-5 notification (#6992) 2025-05-23 10:06:02 +00:00
Marc KlingenandGitHub 1f9bb37f3b fix(cloud): plain.com initialization issues via update queue (#6866)
* fix: plain initialization issues via updatequeue

* apply to the show cb

* chore

* catch errors
2025-05-22 23:00:52 +00:00
Marc Klingen 00afab9725 chore: release v3.62.1 2025-05-22 20:24:52 +02:00
Hassieb PakzadandGitHub d04e808515 feat(cost-tracking+llm-keys): add claude 4 sonnet and opus (#6982) 2025-05-22 17:56:45 +00:00
Jannik MaierhöferandGitHub ee04912f0e chore: lw3-4 notification (#6977) 2025-05-22 14:34:55 +00:00
steffen911 7f04a54c0c chore: release v3.62.0 2025-05-22 16:31:39 +02:00
Steffen SchmitzandGitHub cce11ef6b5 perf: drop unused observation_media index (#6978) 2025-05-22 14:27:21 +00:00
Steffen SchmitzGitHubellipsis-dev[bot] <65095814+ellipsis-dev[bot]@users.noreply.github.com>
1b03f537e2 feat: allow AWS S3 SSE configuration for S3 interactions (#6965)
* feat: allow AWS S3 SSE configuration for S3 interactions

* Update packages/shared/src/env.ts

Co-authored-by: ellipsis-dev[bot] <65095814+ellipsis-dev[bot]@users.noreply.github.com>

* chore: whitelist allowed SSE settings

* dummy

---------

Co-authored-by: ellipsis-dev[bot] <65095814+ellipsis-dev[bot]@users.noreply.github.com>
2025-05-22 12:32:12 +00:00
Hassieb PakzadandGitHub dba114e4a3 feat(otel): add support for observations of type 'event' (#6972) 2025-05-22 12:27:14 +00:00
Steffen SchmitzandGitHub fefe3bc3bd fix: dynamically calc max value for home line charts (#6966)
* fix: dynamically calc max value for home line charts

* chore: wrap in useMemo

* dummy
2025-05-22 12:21:18 +00:00
Steffen SchmitzandGitHub 800cc299cb fix: use quorum writes for temporary dataset tables (#6958) 2025-05-21 15:21:58 +00:00
Hassieb PakzadandGitHub 1bdaed4314 fix(ui-jump-to-playground): look up llm api keys when model parsing (#6957)
* fix(ui-jump-to-playground): look up llm api keys when model parsing

* push

* push
2025-05-21 14:18:37 +00:00
Hassieb PakzadandGitHub 71dde233c5 fix(ui-jump-to-playground): allow response format in modelParams (#6955) 2025-05-21 14:13:05 +02:00
Steffen SchmitzGitHubellipsis-dev[bot] <65095814+ellipsis-dev[bot]@users.noreply.github.com>
3b80afdf2d chore: reduce minimum project retention to 3 days (#6954)
* chore: reduce minimum project retention to 3 days

* Update web/src/features/projects/components/ConfigureRetention.tsx

Co-authored-by: ellipsis-dev[bot] <65095814+ellipsis-dev[bot]@users.noreply.github.com>

* chore: update test cases

---------

Co-authored-by: ellipsis-dev[bot] <65095814+ellipsis-dev[bot]@users.noreply.github.com>
2025-05-21 12:08:52 +00:00
Steffen SchmitzandGitHub b69f0bda9d chore: bump metrics-api rate limits and deprecate daily metrics (#6950)
* chore: bump metrics-api rate limits

* chore: remove docs for metrics/daily

* chore: remove flaky assertion
2025-05-21 10:26:36 +00:00
Hassieb PakzadandGitHub 9b9a58ae45 fix(prompt-experiments): use resolved prompts (#6940)
* fix(prompt-experiments): use resolved prompts

* fix test
2025-05-21 09:39:37 +00:00
Marc Klingen 775e6a8bfc chore: release v3.61.0 2025-05-21 11:12:29 +02:00
5253014fa6 chore: lw3-3 product hunt notification (#6942)
* chore: lw3-3 product hunt notification

* reverse order

* add created date

---------

Co-authored-by: Marc Klingen <git@marcklingen.com>
2025-05-21 09:37:55 +02:00
Marc KlingenandGitHub 1571de133b chore: update pipcat otel attribute mapping (#6944)
based on this change: https://github.com/pipecat-ai/pipecat/pull/1859
2025-05-20 23:50:45 +00:00
Marc KlingenandGitHub 9202f4ec79 docs: add note that docker ENTRYPOINT is covered by semver (#6941) 2025-05-20 23:27:18 +00:00
Steffen SchmitzandGitHub 949e3d1181 chore(dashboards): add more langfuse managed templates (#6939)
* chore(dashboards): add more langfuse managed templates

* chore: update descriptions

* chore: dashboards

* chore: remove wrong dashboard

* chore: commit

* chore: push

* chore: typo

* chore: drop projectId etc from default

* chore: remove beta label

* chore: fix number chart type naming
2025-05-20 17:32:08 +00:00
Jannik MaierhöferGitHubMarc Klingenellipsis-dev[bot] <65095814+ellipsis-dev[bot]@users.noreply.github.com>
2d280329c5 chore: update product notification - lw3-2 (#6929)
* chore: update product notification: launch week day 2

* update

* Update web/src/components/nav/sidebar-notifications.tsx

Co-authored-by: ellipsis-dev[bot] <65095814+ellipsis-dev[bot]@users.noreply.github.com>

* update

* push

---------

Co-authored-by: Marc Klingen <git@marcklingen.com>
Co-authored-by: ellipsis-dev[bot] <65095814+ellipsis-dev[bot]@users.noreply.github.com>
2025-05-20 17:24:29 +00:00
Steffen SchmitzandGitHub 6e1886055a feat(dashboards): add langfuse managed dashboards (#6877)
* feat(dashboards): add langfuse managed dashboard templates

* chore: typing

* chore: update dashboards
2025-05-20 14:49:21 +00:00
Marc KlingenandGitHub 39e4a7533a feat(dashboards): add big number chart type (#6933) 2025-05-20 15:46:20 +02:00
Steffen SchmitzandGitHub e8787e3f38 chore(dashboards): expand measures for dashboards (#6932)
* chore(dashboards): expand measures for dashboards

* chore: add testcase

* chore: define inputTokens and outputTokens

* chore: add timePerOutputToken and costs

* chore: fix definition and handling of tag based breakdowns
2025-05-20 13:43:20 +00:00
Max DeichmannandGitHub 59055cd311 chore: add metrics to measure by-id recency (#6930)
push
2025-05-20 14:59:55 +02:00
Marc KlingenandGitHub 7712b63b95 fix(auth): only apply login domain enforcement to multi-tenant sso (#6928) 2025-05-20 10:33:35 +02:00
marliessophieandGitHub f25d466388 fix(tables-ui): truncate name columns in traces and observations table (#6925) 2025-05-20 07:55:46 +00:00
Max DeichmannandGitHub b9e18f59d8 chore: upgrade zod (#6921)
push
2025-05-19 20:59:03 +00:00
Steffen SchmitzandGitHub 09f3343db2 fix(dashboards): update resize migration to handle empty widget list correctly (#6918)
fix(dashboards): update migration to handle empty widget list correctly
2025-05-19 15:15:32 +00:00
Steffen SchmitzandGitHub 5ab8e4219f feat(dashboard): make dashboard widgets draggable (#6891)
* feat(dashboard): make dashboard widgets draggable

* chore: do not update on layout change

* chore: fix size

* chore: remove the preventCollision flag

* chore: linting

* chore: get row height dynamically

* chore: make chart resizable

* chore: styling for resizes

* chore: add migration to align y values
2025-05-19 14:48:39 +00:00
Steffen SchmitzandGitHub 40359f0e3f chore(dashboards): order metrics and dimensions in widgetform (#6917)
* chore(dashboards): make metrics and dimensions in widgetform searchable

* chore: only sort without search
2025-05-19 14:18:48 +00:00
Marc KlingenandGitHub 817b6d37bc feat(ui): implement optional sidebar notification expiry (#6916)
* feat(web): add expiry for sidebar notifications

* Update web/src/components/nav/sidebar-notifications.tsx

* Update web/src/components/nav/sidebar-notifications.tsx
2025-05-19 13:57:04 +00:00
Hassieb Pakzad 8bb73822d3 chore: release v3.60.1 2025-05-19 14:50:33 +02:00
Jannik MaierhöferGitHubMarc Klingenellipsis-dev[bot] <65095814+ellipsis-dev[bot]@users.noreply.github.com>
fa53ba3c1a chore: add lw3-1 notification (#6912)
* chore: add lw3-1 notification

* Update web/src/components/nav/sidebar-notifications.tsx

Co-authored-by: ellipsis-dev[bot] <65095814+ellipsis-dev[bot]@users.noreply.github.com>

---------

Co-authored-by: Marc Klingen <git@marcklingen.com>
Co-authored-by: ellipsis-dev[bot] <65095814+ellipsis-dev[bot]@users.noreply.github.com>
2025-05-19 09:56:02 +00:00
Hassieb PakzadandGitHub 086a764083 chore(media): make ID generation fully deterministic based on hash (#6900) 2025-05-19 11:52:55 +02:00
Steffen SchmitzandGitHub 79a9f3c3e3 perf: add mediaId index to efficiently delete media items (#6909)
* perf: add mediaId index to efficiently delete media items

* chore: only add index if they do not exist yet
2025-05-19 09:30:16 +00:00
Max Deichmann abd46f2d4d chore: release v3.60.0 2025-05-19 11:16:27 +02:00
marliessophieandGitHub dfd9565a3f chore(experiments): improve delete experiment confirm message (#6908) 2025-05-19 07:41:27 +00:00
Marc KlingenandGitHub ebb8a5a13f chore(ui): trim password reset otp (#6905) 2025-05-18 20:01:26 +00:00
Marc KlingenandGitHub 44104596f6 fix(auth): add domain check for multi-tenant sso providers (#6904) 2025-05-18 19:54:40 +00:00
Marc KlingenandGitHub 17f6260671 feat: otel span mapping for pipecat traces (#6903) 2025-05-18 17:41:49 +00:00
Marc KlingenandGitHub 0a2bfe5ab5 fix(ui): peek view header should stay single line on mobile screens (#6902) 2025-05-18 17:23:32 +00:00
Marc KlingenandGitHub 8bd1a4da3e chore(ui): hide thread refs in support chat (#6901)
feat(web): hide thread refs in support chat
2025-05-18 13:28:49 +00:00
Marc KlingenGitHubellipsis-dev[bot] <65095814+ellipsis-dev[bot]@users.noreply.github.com>
31b230d3e0 feat(auth): switch to OTP based password reset instead of magic link (#6898)
* feat(auth): add otp-based password reset

* fix

* fix lint and margins

* Update web/src/features/auth-credentials/components/ResetPasswordButton.tsx

Co-authored-by: ellipsis-dev[bot] <65095814+ellipsis-dev[bot]@users.noreply.github.com>

* Update web/src/server/auth.ts

Co-authored-by: ellipsis-dev[bot] <65095814+ellipsis-dev[bot]@users.noreply.github.com>

* simplify

---------

Co-authored-by: ellipsis-dev[bot] <65095814+ellipsis-dev[bot]@users.noreply.github.com>
2025-05-18 13:04:40 +00:00
Marc KlingenandGitHub dbe71249e7 chore: ignore HEAD request for auth api endpoints (#6899) 2025-05-18 12:04:20 +00:00
Marc KlingenandGitHub a9d0486edd chore: Update AGENTS guide (#6897)
docs: mention conventional commits
2025-05-18 13:45:29 +02:00
Marc KlingenandGitHub 2bf506a436 fix(ui): hover state color of chat message types (#6895) 2025-05-18 10:38:17 +00:00
Steffen SchmitzandGitHub edca91c12a chore(dashboard): auto-generate widget name from selected props (#6890)
* chore(dashboard): auto-generate widget name from selected props

* chore: lint
2025-05-17 13:52:52 +00:00
Steffen SchmitzandGitHub a11e7ddfee feat(dashboard): include dashboards in cmdk menu (#6889) 2025-05-17 12:28:26 +00:00
Steffen SchmitzandGitHub cb9eb23f36 chore(dashboard): show description on hover in selection tables (#6888) 2025-05-17 12:25:43 +00:00
Steffen SchmitzandGitHub 5e942f0208 feat(dashboards): add langfuse managed read-only dashboard support (#6873)
* chore: add owner to project and return langfuse dashboards

* chore: show owner for dashborads in table

* chore: snapshot

* chore: snapshot

* chore: allow widget clone

* chore: snapshot

* chore: linting

* chore: use project instead of user

* chore: show error message on clone failure

* chore: indicate existing dashboard widget relationship

* chore: show only project dashboards in selection for adding widgets

* chore: make full dashboard row clickable

* chore: add clone button to langfuse dashboards
2025-05-17 12:02:50 +00:00
Max DeichmannandGitHub 8e0e139848 chore: remove clickhouse session id (#6849)
* push

* push
2025-05-16 15:09:08 +00:00
Hassieb Pakzad acc1227962 chore: release v3.59.1 2025-05-16 16:57:30 +02:00
Hassieb PakzadandGitHub d9682511c1 perf(otel): do not pass deep parsed metadata (#6878)
* revert previous commit

* perf(otel): do not pass deep parsed metadata
2025-05-16 14:55:16 +00:00
Hassieb Pakzad 00e0b51bc4 chore: release v3.59.0 2025-05-16 14:06:50 +02:00
Hassieb PakzadGitHubellipsis-dev[bot] <65095814+ellipsis-dev[bot]@users.noreply.github.com>
e63cf84e4f feat(otel): add Langfuse attribute parsing (#6692)
* feat(otel): add Langfuse attribute parsing

* fix

* push

* add safeguard for cross project spans

* fix test

* add extract completionStartTime

* fix type issues

* handle trace io

* fix

* Update web/src/features/otel/server/index.ts

Co-authored-by: ellipsis-dev[bot] <65095814+ellipsis-dev[bot]@users.noreply.github.com>

---------

Co-authored-by: ellipsis-dev[bot] <65095814+ellipsis-dev[bot]@users.noreply.github.com>
2025-05-16 12:03:01 +00:00
Steffen SchmitzandGitHub 63d1051ac2 perf: increase socket lifetime and connections for clickhouse client (#6870) 2025-05-16 08:54:38 +00:00
Steffen SchmitzandGitHub 0e056eb072 chore: increase default timeframe in custom dashboards to 7d (#6871) 2025-05-16 05:45:37 +00:00
Steffen SchmitzandGitHub 87f7095966 chore: reduce title size in widget item doc hover (#6869) 2025-05-16 05:26:57 +00:00
steffen911 5eefe997ae chore: release v3.58.0 2025-05-16 06:39:23 +02:00
Marc KlingenandGitHub e251e60b53 fix: plain chat availability check should not rely on window.Plain but only on env (#6867) 2025-05-16 05:36:07 +02:00
Marc KlingenandGitHub adc05eeef4 feat(ui-ee): show/hide product modules in main menu via LANGFUSE_UI_VISIBLE/HIDDEN_PRODUCT_MODULES (#6841)
* feat(ui): show/hide product modules in main menu

* prod example

* add dashboards

* improve comment
2025-05-16 00:20:17 +00:00
Steffen SchmitzandGitHub 702143fbe2 perf: skip zod validation for otel event batches (#6861)
* perf: skip zod validation for otel event batches

* chore: remove unnecessary casting
2025-05-15 16:47:30 +00:00
Steffen SchmitzandGitHub 06643f30e5 feat(dashboard): add documentation hovers onto widget properties (#6856)
* feat(dashboard): add documentation hovers onto widget properties

* chore: fix typing

* chore: remove open and close delays of hovercards
2025-05-15 14:31:20 +00:00
Steffen SchmitzandGitHub 2e496d5429 chore(dashboard): make hovers in dark mode more readable (#6858) 2025-05-15 13:54:44 +00:00
Steffen SchmitzandGitHub 5b62df9122 feat(dashboard): add new widget to dashboard on save (#6854)
* feat(dashboard): add new widget to dashboard on save

* chore: linting
2025-05-15 13:15:08 +00:00
Steffen SchmitzandGitHub fd189dc66b fix(dashboard): map traceRelease and traceVersion correctly on breakdown (#6853) 2025-05-15 11:39:51 +00:00
Steffen SchmitzandGitHub 10a3644dcf chore(dashboard): auto-save dashboard on any changes (#6820)
* chore(dashboard): auto-save dashboard on any changes

* chore: linting

* chore: switch timeouts to useDebounce

* chore: linting
2025-05-15 09:48:02 +00:00
Max DeichmannandGitHub 8ca000b225 chore: reduce worker logs (#6851) 2025-05-15 11:33:33 +02:00
Steffen SchmitzandGitHub 47d41b6a42 chore: change logging pattern around redis retries (#6843) 2025-05-15 07:34:00 +00:00
Steffen SchmitzandGitHub 1d66408c18 fix(dashboard): avoid invalid filter name on view switches (#6829)
* fix(dashboard): avoid invalid filter name on view switches

* chore: add test case
2025-05-15 07:18:41 +00:00
Max DeichmannandGitHub 44d1727dd0 chore: reduce error logs for llm 429 errors (#6836) 2025-05-15 00:37:58 +02:00
Max DeichmannandGitHub bfb2878719 chore: reduce log level for prompt service (#6835)
fix
2025-05-14 22:19:00 +00:00
Marc KlingenandGitHub 67e6b4ce87 chore(cloud): increases api rate limits (#6783) 2025-05-14 23:03:49 +02:00
Max DeichmannandGitHub dcc5bf9c6e fix: fix traceid filter for observations by id clickhouse query (#6828) 2025-05-14 16:10:23 +02:00
Steffen SchmitzandGitHub db357101b7 feat(dashboards): add support for cloning existing dashboards (#6824)
* feat(dashboards): add support for cloning existing dashboards

* chore: move buttons into a dedicated dropdown menu

* chore: allow updates to dashboard name and description

* chore: lint

* chore: removal double capturing of dashboard delete

* chore: track deletions
2025-05-14 12:50:26 +00:00
Steffen SchmitzandGitHub afbd45b9c3 chore(metrics-api): return bad request errors for invalid query (#6826) 2025-05-14 11:01:10 +00:00
Max DeichmannGitHubellipsis-dev[bot] <65095814+ellipsis-dev[bot]@users.noreply.github.com>
b6b37212ce perf: reduce project deletion concurrency (#6823)
* push

* Update worker/src/app.ts

Co-authored-by: ellipsis-dev[bot] <65095814+ellipsis-dev[bot]@users.noreply.github.com>

---------

Co-authored-by: ellipsis-dev[bot] <65095814+ellipsis-dev[bot]@users.noreply.github.com>
2025-05-14 10:30:46 +00:00
Steffen SchmitzandGitHub 76a090241e feat(dashboard): add newly created widget to dashboard on save (#6819)
* feat(dashboard): add newly created widget to dashboard on save

* chore: linting
2025-05-14 09:25:23 +00:00
Max DeichmannandGitHub c53abf6aeb perf: also add trace_id to observations search (#6822)
push
2025-05-14 09:16:49 +00:00
Hassieb Pakzad 5cbfd922f9 chore: release v3.57.2 2025-05-14 09:55:07 +02:00
Hassieb PakzadandGitHub 0be269d519 fix(ui-tool-calls): handle parsing errors gracefully (#6817) 2025-05-14 07:52:47 +00:00
Max DeichmannandGitHub d0eeb44b90 fix: fail gracefully for batch actions in case eval config does not exist (#6809)
* push

* fix
2025-05-13 15:03:57 +00:00
Marlies Mayerhofer 30ced3ab42 chore: release v3.57.1 2025-05-13 16:52:57 +02:00
Max DeichmannandGitHub 2ed6b5a40f chore: parameterize clickhouse deletion timeouts (#6801) 2025-05-13 16:20:13 +02:00
Steffen SchmitzandGitHub 6eaef75f20 fix(dashboard): render localized time strings for LineCharts (#6799)
* fix(dashboard): render localized time strings for LineCharts

* chore: use memo
2025-05-13 13:57:07 +00:00
Max DeichmannandGitHub 31c36565c3 chore: fix clickhouse timeout settings (#6798) 2025-05-13 15:30:04 +02:00
Steffen SchmitzandGitHub d1a1ca7744 fix(dashboard): increase precision of numbers on hover cards (#6797) 2025-05-13 12:54:52 +00:00
Steffen SchmitzandGitHub 2dac75d203 chore(dashboard): use more granular time buckets on home dashboard (#6795) 2025-05-13 12:25:39 +00:00
Steffen SchmitzandGitHub fab90b36a6 chore: remove queryPlayground page (#6796) 2025-05-13 12:20:12 +00:00
Steffen SchmitzandGitHub 597bd6c96b fix(dashboard): warn on slow chart render and ask users to confirm (#6794) 2025-05-13 12:03:02 +00:00
Max DeichmannandGitHub ba3bcc9295 fix: Increase memory usage for deploy (#6793)
Increase memory usage for deploy
2025-05-13 10:32:29 +00:00
marliessophieandGitHub 5f65929a5e fix(session-ui): handling mine type as enum string equivalent (#6792) 2025-05-13 09:40:01 +00:00
Steffen SchmitzandGitHub f1344a4c1a chore: remove unused env variable (#6789) 2025-05-13 08:44:02 +00:00
Steffen SchmitzandGitHub 4e3b9a82f7 fix: do not refresh blobstorage form on browser navigation (#6788) 2025-05-13 08:12:28 +00:00
Max DeichmannandGitHub 7b803619fd fix: fix metadata json selector (#6784) 2025-05-12 21:11:21 +02:00
marliessophieandGitHub 1ef51b1644 feat(datasets): support GET dataset-run-items (#6780)
* feat(datasets): support `GET` dataset run items

* chore: add fern api types

* chore: eslint
2025-05-12 17:55:26 +00:00
Hassieb PakzadandGitHub fee9e34b7e chore(ui-graph-view): allow graph view in impersonation mode (#6782) 2025-05-12 17:37:32 +00:00
Hassieb PakzadandGitHub 1354db489f fix(ui-graph-view): fetch graph data separately (#6781)
* fix(ui-graph-view): fetch graph data separately

* fix

* push

* refactor

* fix

* fix lint
2025-05-12 16:33:33 +00:00
steffen911 740a25150c chore: release v3.57.0 2025-05-12 17:49:49 +02:00
Marc KlingenandGitHub 47c2d65d12 chore(ui): improve ux of full-text search input (#6772)
* width

* change to dropdown

* fix
2025-05-12 15:08:12 +00:00
Steffen SchmitzandGitHub d94e7c1c06 feat: add new metrics api endpoint (#6778)
* feat: add metric api endpoint

* feat: add implementation and documentation

* chore: add defaults for timeDimension and ordering
2025-05-12 14:17:40 +00:00
Steffen SchmitzandGitHub 38ed98a76d feat: add org API keys to organization settings (#6729)
* feat: add org API keys to organization settings

* chore: linting suggestions

* chore: fix typing

* feedback: do not call hooks conditionally
2025-05-12 11:25:01 +00:00
Max DeichmannandGitHub 92567b765b chore: reduce amount of ingested dd spans (#6775)
* push

* fix
2025-05-12 09:47:37 +00:00
Marc KlingenandGitHub b37396893a chore: improve auth error message (#6773) 2025-05-12 04:02:11 +00:00
Steffen SchmitzandGitHub 0fd1eebbff fix: align signed download URL with hostname (#6764) 2025-05-11 12:24:49 +00:00
Max DeichmannandGitHub f478bb5763 refactor: refactor observations by id repo function (#6768)
fix
2025-05-10 20:12:13 +00:00
646 changed files with 29986 additions and 13703 deletions
+47
View File
@@ -0,0 +1,47 @@
FROM node:20
# ---------- System packages --------------------------------------------------
# The buildpack-deps base already ships git, build-essential, python, etc.
# Add a few extra tools handy during Langfuse development.
RUN apt-get update && \
DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \
openssl \
wget \
curl \
ca-certificates \
postgresql-client \
redis-tools \
less nano \
&& rm -rf /var/lib/apt/lists/*
# ---------- pnpm -------------------------------------------------------------
# Langfuse monorepo relies on pnpm 9.5.0 (see CONTRIBUTING.md)
ENV PNPM_HOME="/pnpm"
ENV PATH="$PNPM_HOME:$PATH"
RUN corepack enable && \
corepack prepare pnpm@9.5.0 --activate
# ---------- golang-migrate ----------------------------------------------------
# CLI used for database migrations during development.
ENV MIGRATE_VERSION=4.18.2
RUN wget -qO- "https://github.com/golang-migrate/migrate/releases/download/v${MIGRATE_VERSION}/migrate.linux-amd64.tar.gz" \
| tar -xz -C /usr/local/bin && \
chmod +x /usr/local/bin/migrate
# ---------- Non-root user -----------------------------------------------------
# Use root for convenience in development containers
WORKDIR /workspace
# Create non-root user
RUN useradd -ms /bin/bash ubuntu
# Pre-create pnpm store and set correct ownership to avoid first-run cost & permission issues
RUN pnpm store path > /dev/null && \
chown -R ubuntu:ubuntu /pnpm
USER ubuntu
WORKDIR /home/ubuntu
ENV HOME=/home/ubuntu
# Container starts with a bash shell ready for hacking.
CMD ["bash"]
+8
View File
@@ -0,0 +1,8 @@
{
"install": "cp .env.dev.example .env && pnpm i",
"build": {
"context": ".",
"dockerfile": "Dockerfile"
},
"start": "pnpm dx-f"
}
+8
View File
@@ -0,0 +1,8 @@
---
description:
globs:
alwaysApply: true
---
# General rules
- Linting in this repo only works if the development server is running
+84
View File
@@ -0,0 +1,84 @@
# When adding additional environment variables, the schema in "/src/env.mjs"
# should be updated accordingly.
# Prisma
# https://www.prisma.io/docs/reference/database-reference/connection-urls#env
DIRECT_URL="postgresql://postgres:postgres@localhost:5432/postgres"
DATABASE_URL="postgresql://postgres:postgres@localhost:5432/postgres"
# Clickhouse
CLICKHOUSE_MIGRATION_URL="clickhouse://localhost:9000"
CLICKHOUSE_URL="http://localhost:8123"
CLICKHOUSE_USER="clickhouse"
CLICKHOUSE_PASSWORD="clickhouse"
CLICKHOUSE_CLUSTER_ENABLED="false"
# Next Auth
# You can generate a new secret on the command line with:
# openssl rand -base64 32
# https://next-auth.js.org/configuration/options#secret
# NEXTAUTH_SECRET=""
NEXTAUTH_URL="http://localhost:3000"
NEXTAUTH_SECRET="secret"
# Langfuse Cloud Environment
NEXT_PUBLIC_LANGFUSE_CLOUD_REGION="DEV"
# Langfuse experimental features
LANGFUSE_ENABLE_EXPERIMENTAL_FEATURES="true"
# Salt for API key hashing
SALT="salt"
# Email
EMAIL_FROM_ADDRESS="" # Defines the email address to use as the from address.
SMTP_CONNECTION_URL="" # Defines the connection url for smtp server.
# S3 Batch Exports
LANGFUSE_S3_BATCH_EXPORT_ENABLED=true
LANGFUSE_S3_BATCH_EXPORT_BUCKET=langfuse
LANGFUSE_S3_BATCH_EXPORT_ACCESS_KEY_ID=minio
LANGFUSE_S3_BATCH_EXPORT_SECRET_ACCESS_KEY=miniosecret
LANGFUSE_S3_BATCH_EXPORT_REGION=us-east-1
LANGFUSE_S3_BATCH_EXPORT_ENDPOINT=http://localhost:9090
## Necessary for minio compatibility
LANGFUSE_S3_BATCH_EXPORT_FORCE_PATH_STYLE=true
LANGFUSE_S3_BATCH_EXPORT_PREFIX=exports/
# S3 Media Upload LOCAL
LANGFUSE_S3_MEDIA_UPLOAD_BUCKET=langfuse
LANGFUSE_S3_MEDIA_UPLOAD_ACCESS_KEY_ID=minio
LANGFUSE_S3_MEDIA_UPLOAD_SECRET_ACCESS_KEY=miniosecret
LANGFUSE_S3_MEDIA_UPLOAD_REGION=us-east-1
LANGFUSE_S3_MEDIA_UPLOAD_ENDPOINT=http://localhost:9090
## Necessary for minio compatibility
LANGFUSE_S3_MEDIA_UPLOAD_FORCE_PATH_STYLE=true
LANGFUSE_S3_MEDIA_UPLOAD_PREFIX=media/
# S3 Event Bucket Upload
## Set to true to test uploading all events to S3
LANGFUSE_S3_EVENT_UPLOAD_BUCKET=langfuse
LANGFUSE_S3_EVENT_UPLOAD_ACCESS_KEY_ID=minio
LANGFUSE_S3_EVENT_UPLOAD_SECRET_ACCESS_KEY=miniosecret
LANGFUSE_S3_EVENT_UPLOAD_REGION=us-east-1
LANGFUSE_S3_EVENT_UPLOAD_ENDPOINT=http://localhost:9090
## Necessary for minio compatibility
LANGFUSE_S3_EVENT_UPLOAD_FORCE_PATH_STYLE=true
LANGFUSE_S3_EVENT_UPLOAD_PREFIX=events/
# Set during docker build of application
# Used to disable environment verification at build time
# DOCKER_BUILD=1
REDIS_HOST="127.0.0.1"
REDIS_PORT=6379
REDIS_AUTH="bitnami"
REDIS_CLUSTER_ENABLED="true"
REDIS_CLUSTER_NODES="127.0.0.1:6370,127.0.0.1:6371,127.0.0.1:6372,127.0.0.1:6373,127.0.0.1:6374,127.0.0.1:6375"
LANGFUSE_INGESTION_QUEUE_SHARD_COUNT=8
# openssl rand -hex 32 used only here
ENCRYPTION_KEY=0000000000000000000000000000000000000000000000000000000000000000
# speeds up local development by not executing init scripts on server startup
NEXT_PUBLIC_LANGFUSE_RUN_NEXT_INIT="false"
+8 -4
View File
@@ -157,10 +157,6 @@ OTEL_SERVICE_NAME="langfuse"
# LANGFUSE_S3_EVENT_UPLOAD_ACCESS_KEY_ID=
# LANGFUSE_S3_EVENT_UPLOAD_SECRET_ACCESS_KEY=
# Exports are streamed to S3 in pages to avoid memory issues
# The page size can be adjusted if needed to optimize performance
# DB_EXPORT_PAGE_SIZE=1000
# Automated provisioning of default resources
# LANGFUSE_INIT_ORG_ID=org-id
# LANGFUSE_INIT_ORG_NAME=org-name
@@ -179,6 +175,10 @@ OTEL_SERVICE_NAME="langfuse"
# REDIS_CONNECTION_STRING=
# REDIS_ENABLE_AUTO_PIPELINING=
# Redis Cluster configuration (optional)
# REDIS_CLUSTER_ENABLED=false
# REDIS_CLUSTER_NODES=redis-node1:6379,redis-node2:6379,redis-node3:6379
# Cache configuration
# LANGFUSE_CACHE_API_KEY_ENABLED=
# LANGFUSE_CACHE_API_KEY_TTL_SECONDS=
@@ -215,6 +215,8 @@ OTEL_SERVICE_NAME="langfuse"
# LANGFUSE_UI_DEFAULT_BASE_URL_OPENAI=https://api.openai.com/v1
# LANGFUSE_UI_DEFAULT_BASE_URL_ANTHROPIC=https://api.anthropic.com
# LANGFUSE_UI_DEFAULT_BASE_URL_AZURE_OPENAI=https://{instanceName}.openai.azure.com/openai/deployments
# LANGFUSE_UI_VISIBLE_PRODUCT_MODULES=
# LANGFUSE_UI_HIDDEN_PRODUCT_MODULES=
### END Enterprise Edition Configuration
@@ -253,6 +255,8 @@ OTEL_SERVICE_NAME="langfuse"
# Plain Chat
# NEXT_PUBLIC_PLAIN_APP_ID=
# PLAIN_AUTHENTICATION_SECRET=
# PLAIN_API_KEY=
# PLAIN_CARDS_API_TOKEN=
# Admin API
# ADMIN_API_KEY=
@@ -15,6 +15,10 @@ jobs:
runs-on: ubuntu-latest
environment: ${{ inputs.environment }}
steps:
- name: Set Swap Space
uses: pierotofy/set-swap-space@master
with:
swap-size-gb: 10
- name: Get app name
uses: winterjung/split@v2
id: split
+11 -11
View File
@@ -171,12 +171,12 @@ jobs:
needs:
- pre-job
if: needs.pre-job.outputs.should_skip != 'true'
name: tests-web-async (node${{ matrix.node-version }}, pg${{ matrix.postgres-version }}, mode${{ matrix.blob-provider }})
name: tests-web-async (node${{ matrix.node-version }}, pg${{ matrix.postgres-version }}, mode${{ matrix.deploy-mode }})
strategy:
matrix:
node-version: [20]
postgres-version: [12, 15]
blob-provider: ["", "-azure"]
deploy-mode: ["", "-azure", "-redis-cluster"]
steps:
- name: Set Swap Space
uses: pierotofy/set-swap-space@master
@@ -208,8 +208,8 @@ jobs:
pnpm install
- name: Load default env
run: |
cp .env.dev${{ matrix.blob-provider }}.example .env
grep -v -e '^LANGFUSE_S3_BATCH_EXPORT_ENABLED=' -e '^NEXT_PUBLIC_LANGFUSE_RUN_NEXT_INIT=' .env.dev${{ matrix.blob-provider }}.example > .env
cp .env.dev${{ matrix.deploy-mode }}.example .env
grep -v -e '^LANGFUSE_S3_BATCH_EXPORT_ENABLED=' -e '^NEXT_PUBLIC_LANGFUSE_RUN_NEXT_INIT=' .env.dev${{ matrix.deploy-mode }}.example > .env
echo "LANGFUSE_INGESTION_QUEUE_DELAY_MS=1" >> .env
echo "LANGFUSE_INGESTION_CLICKHOUSE_WRITE_INTERVAL_MS=1" >> .env
echo "LANGFUSE_TRACE_DELETE_CONCURRENCY=100" >> .env
@@ -217,7 +217,7 @@ jobs:
echo "LANGFUSE_EE_LICENSE_KEY=langfuse_ee_test" >> .env
- name: Run dev containers
run: |
docker compose -f docker-compose.dev${{ matrix.blob-provider }}.yml up -d
docker compose -f docker-compose.dev${{ matrix.deploy-mode }}.yml up -d
sleep 5 # Wait for PostgreSQL to accept connections
docker compose ps
env:
@@ -250,12 +250,12 @@ jobs:
needs:
- pre-job
if: needs.pre-job.outputs.should_skip != 'true'
name: tests-worker (node${{ matrix.node-version }}, pg${{ matrix.postgres-version }}, mode${{ matrix.blob-provider }})
name: tests-worker (node${{ matrix.node-version }}, pg${{ matrix.postgres-version }}, mode${{ matrix.deploy-mode }})
strategy:
matrix:
node-version: [20]
postgres-version: [12, 15]
blob-provider: ["", "-azure"]
deploy-mode: ["", "-azure", "-redis-cluster"]
steps:
- name: Set Swap Space
uses: pierotofy/set-swap-space@master
@@ -287,12 +287,12 @@ jobs:
which migrate
- name: Load default env
run: |
cp .env.dev${{ matrix.blob-provider }}.example .env
cp .env.dev${{ matrix.blob-provider }}.example web/.env
cp .env.dev${{ matrix.blob-provider }}.example worker/.env
cp .env.dev${{ matrix.deploy-mode }}.example .env
cp .env.dev${{ matrix.deploy-mode }}.example web/.env
cp .env.dev${{ matrix.deploy-mode }}.example worker/.env
- name: Run + migrate
run: |
docker compose -f docker-compose.dev${{ matrix.blob-provider }}.yml up -d
docker compose -f docker-compose.dev${{ matrix.deploy-mode }}.yml up -d
sleep 5 # Wait for PostgreSQL to accept connections
docker compose ps
- name: Ensure no unhealthy status
+1
View File
@@ -39,6 +39,7 @@ yarn-error.log*
.env*
!.env.dev.example
!.env.dev-azure.example
!.env.dev-redis-cluster.example
!.env.prod.example
# vercel
+16
View File
@@ -0,0 +1,16 @@
# Codex Guidelines for Langfuse
Langfuse is an **open source LLM engineering** platform for developing, monitoring, evaluating and debugging AI applications. See the README for more details.
## Linting
- Run `pnpm run lint` to lint all packages.
- Fix issues automatically with `pnpm run lint:fix`.
## Tests
- Codex cannot run the test suite because it depends on Docker-based infrastructure that is unavailable in this environment.
## Cursor Rules
- Additional folder-specific rules live in `.cursor/rules/`.
## Commits
- Follow [Conventional Commits](https://www.conventionalcommits.org/en/v1.0.0/) when crafting commit messages.
+2 -2
View File
@@ -213,8 +213,8 @@ LANGFUSE_HOST="https://cloud.langfuse.com" # 🇪🇺 欧盟区域
创建示例代码(文件名:**main.py**):
````python:main.py
from langfuse.decorators import observe
```python:main.py
from langfuse import observe
from langfuse.openai import openai # OpenAI 集成
@observe()
+1 -1
View File
@@ -219,7 +219,7 @@ LANGFUSE_HOST="https://cloud.langfuse.com" # 🇪🇺 EUリージョン
```
```python:/@observe()/ /from langfuse.openai import openai/ filename="main.py"
from langfuse.decorators import observe
from langfuse import observe
from langfuse.openai import openai # OpenAI統合
@observe()
+1 -1
View File
@@ -201,7 +201,7 @@ LANGFUSE_HOST="https://cloud.langfuse.com" # 🇪🇺 EU region
```
```python:main.py
from langfuse.decorators import observe
from langfuse import observe
from langfuse.openai import openai # OpenAI integration
@observe()
+5 -6
View File
@@ -93,7 +93,7 @@ Langfuse is an **open source LLM engineering** platform. It helps teams collabor
### Langfuse Cloud
Managed deployment by the Langfuse team, generous free-tier (hobby plan), no credit card required.
Managed deployment by the Langfuse team, generous free-tier, no credit card required.
<div align="center">
<a href="https://cloud.langfuse.com" target="_blank">
@@ -115,12 +115,11 @@ Run Langfuse on your own infrastructure:
# Run the langfuse docker compose
docker compose up
```
- [Kubernetes (Helm)](https://langfuse.com/self-hosting/kubernetes-helm): Run Langfuse on a Kubernetes cluster using Helm. This is the preferred production deployment.
- [VM](https://langfuse.com/self-hosting/docker-compose): Run Langfuse on a single Virtual Machine using Docker Compose.
- Planned: Cloud-specific deployment guides, please upvote and comment on the following threads: [AWS](https://github.com/orgs/langfuse/discussions/4645), [Google Cloud](https://github.com/orgs/langfuse/discussions/4646), [Azure](https://github.com/orgs/langfuse/discussions/4647).
- [Kubernetes (Helm)](https://langfuse.com/self-hosting/kubernetes-helm): Run Langfuse on a Kubernetes cluster using Helm. This is the preferred production deployment.
- Terraform Templates: [AWS](https://langfuse.com/self-hosting/aws), [Azure](https://langfuse.com/self-hosting/azure), [GCP](https://langfuse.com/self-hosting/gcp)
See [self-hosting documentation](https://langfuse.com/self-hosting) to learn more about the architecture and configuration options.
See [self-hosting documentation](https://langfuse.com/self-hosting) to learn more about architecture and configuration options.
## 🔌 Integrations
@@ -191,7 +190,7 @@ LANGFUSE_HOST="https://cloud.langfuse.com" # 🇪🇺 EU region
```
```python /@observe()/ /from langfuse.openai import openai/ filename="main.py"
from langfuse.decorators import observe
from langfuse import observe
from langfuse.openai import openai # OpenAI integration
@observe()
+146
View File
@@ -0,0 +1,146 @@
services:
clickhouse:
image: clickhouse/clickhouse-server:24.3
user: "101:101"
environment:
CLICKHOUSE_DB: default
CLICKHOUSE_USER: clickhouse
CLICKHOUSE_PASSWORD: clickhouse
volumes:
- langfuse_clickhouse_data:/var/lib/clickhouse
- langfuse_clickhouse_logs:/var/log/clickhouse-server
ports:
- 127.0.0.1:8123:8123
- 127.0.0.1:9000:9000
depends_on:
- postgres
minio:
image: minio/minio
entrypoint: sh
# create the 'langfuse' bucket before starting the service
command: -c 'mkdir -p /data/langfuse && minio server --address ":9000" --console-address ":9001" /data'
environment:
MINIO_ACCESS_KEY: minio
MINIO_SECRET_KEY: miniosecret
ports:
- 127.0.0.1:9090:9000
- 127.0.0.1:9091:9001
volumes:
- langfuse_minio_data:/data
healthcheck:
test: ["CMD", "mc", "ready", "local"]
interval: 1s
timeout: 5s
retries: 5
start_period: 1s
postgres:
image: postgres:${POSTGRES_VERSION:-latest}
restart: always
healthcheck:
test: ["CMD-SHELL", "pg_isready -U postgres"]
interval: 3s
timeout: 3s
retries: 10
command: ["postgres", "-c", "log_statement=all"]
environment:
- POSTGRES_USER=postgres
- POSTGRES_PASSWORD=postgres
- POSTGRES_DB=postgres
ports:
- 127.0.0.1:5432:5432
volumes:
- langfuse_postgres_data:/var/lib/postgresql/data
# Redis Cluster. Requires a Unix host to work for network_mode: host. I.e. tests will fail on windows and mac with this setup.
redis-node-0:
image: docker.io/bitnami/redis-cluster:8.0
network_mode: host
volumes:
- redis-cluster_data-0:/bitnami/redis/data
environment:
REDIS_PASSWORD: bitnami
REDIS_PORT_NUMBER: 6370
REDIS_NODES: 127.0.0.1:6370 127.0.0.1:6371 127.0.0.1:6372 127.0.0.1:6373 127.0.0.1:6374 127.0.0.1:6375
redis-node-1:
image: docker.io/bitnami/redis-cluster:8.0
network_mode: host
volumes:
- redis-cluster_data-1:/bitnami/redis/data
environment:
REDIS_PASSWORD: bitnami
REDIS_PORT_NUMBER: 6371
REDIS_NODES: 127.0.0.1:6370 127.0.0.1:6371 127.0.0.1:6372 127.0.0.1:6373 127.0.0.1:6374 127.0.0.1:6375
redis-node-2:
image: docker.io/bitnami/redis-cluster:8.0
network_mode: host
volumes:
- redis-cluster_data-2:/bitnami/redis/data
environment:
REDIS_PASSWORD: bitnami
REDIS_PORT_NUMBER: 6372
REDIS_NODES: 127.0.0.1:6370 127.0.0.1:6371 127.0.0.1:6372 127.0.0.1:6373 127.0.0.1:6374 127.0.0.1:6375
redis-node-3:
image: docker.io/bitnami/redis-cluster:8.0
network_mode: host
volumes:
- redis-cluster_data-3:/bitnami/redis/data
environment:
REDIS_PASSWORD: bitnami
REDIS_PORT_NUMBER: 6373
REDIS_NODES: 127.0.0.1:6370 127.0.0.1:6371 127.0.0.1:6372 127.0.0.1:6373 127.0.0.1:6374 127.0.0.1:6375
redis-node-4:
image: docker.io/bitnami/redis-cluster:8.0
network_mode: host
volumes:
- redis-cluster_data-4:/bitnami/redis/data
environment:
REDIS_PASSWORD: bitnami
REDIS_PORT_NUMBER: 6374
REDIS_NODES: 127.0.0.1:6370 127.0.0.1:6371 127.0.0.1:6372 127.0.0.1:6373 127.0.0.1:6374 127.0.0.1:6375
redis-node-5:
image: docker.io/bitnami/redis-cluster:8.0
network_mode: host
volumes:
- redis-cluster_data-5:/bitnami/redis/data
depends_on:
- redis-node-0
- redis-node-1
- redis-node-2
- redis-node-3
- redis-node-4
environment:
REDISCLI_AUTH: bitnami
REDIS_CLUSTER_REPLICAS: 1
REDIS_PASSWORD: bitnami
REDIS_PORT_NUMBER: 6375
REDIS_NODES: 127.0.0.1:6370 127.0.0.1:6371 127.0.0.1:6372 127.0.0.1:6373 127.0.0.1:6374 127.0.0.1:6375
REDIS_CLUSTER_CREATOR: yes
volumes:
langfuse_postgres_data:
driver: local
langfuse_clickhouse_data:
driver: local
langfuse_clickhouse_logs:
driver: local
langfuse_minio_data:
driver: local
redis-cluster_data-0:
driver: local
redis-cluster_data-1:
driver: local
redis-cluster_data-2:
driver: local
redis-cluster_data-3:
driver: local
redis-cluster_data-4:
driver: local
redis-cluster_data-5:
driver: local
+1
View File
@@ -29,6 +29,7 @@ services:
CLICKHOUSE_USER: ${CLICKHOUSE_USER:-clickhouse}
CLICKHOUSE_PASSWORD: ${CLICKHOUSE_PASSWORD:-clickhouse} # CHANGEME
CLICKHOUSE_CLUSTER_ENABLED: ${CLICKHOUSE_CLUSTER_ENABLED:-false}
LANGFUSE_USE_AZURE_BLOB: ${LANGFUSE_USE_AZURE_BLOB:-false}
LANGFUSE_S3_EVENT_UPLOAD_BUCKET: ${LANGFUSE_S3_EVENT_UPLOAD_BUCKET:-langfuse}
LANGFUSE_S3_EVENT_UPLOAD_REGION: ${LANGFUSE_S3_EVENT_UPLOAD_REGION:-auto}
LANGFUSE_S3_EVENT_UPLOAD_ACCESS_KEY_ID: ${LANGFUSE_S3_EVENT_UPLOAD_ACCESS_KEY_ID:-minio}
+2 -2
View File
@@ -28,9 +28,9 @@
"@opentelemetry/api": ">=1.0.0 <1.10.0",
"axios": "^1.8.2",
"https-proxy-agent": "^7.0.6",
"next": "^14.2.26",
"next": "^14.2.30",
"next-auth": "^4.24.11",
"zod": "^3.23.8"
"zod": "^3.25.62"
},
"devDependencies": {
"@repo/eslint-config": "workspace:*",
+1 -1
View File
@@ -1,4 +1,4 @@
import { z } from "zod";
import { z } from "zod/v4";
import { removeEmptyEnvVariables } from "@langfuse/shared";
const EnvSchema = z.object({
+10 -3
View File
@@ -457,13 +457,13 @@ types:
docs: Unit used by this model.
type: optional<ModelUsageUnit>
inputPrice:
docs: Price (USD) per input unit
docs: Deprecated. See 'prices' instead. Price (USD) per input unit
type: optional<double>
outputPrice:
docs: Price (USD) per output unit
docs: Deprecated. See 'prices' instead. Price (USD) per output unit
type: optional<double>
totalPrice:
docs: Price (USD) per total unit. Cannot be set if input or output price is set.
docs: Deprecated. See 'prices' instead. Price (USD) per total unit. Cannot be set if input or output price is set.
type: optional<double>
tokenizerId:
docs: Optional. Tokenizer to be applied to observations which match to this model. See docs for more details.
@@ -473,6 +473,13 @@ types:
type: optional<unknown>
isLangfuseManaged:
type: boolean
prices:
docs: Price (USD) by usage type
type: map<string, ModelPrice>
ModelPrice:
properties:
price: double
# Utilities
ModelUsageUnit:
@@ -1,6 +1,7 @@
# yaml-language-server: $schema=https://raw.githubusercontent.com/fern-api/fern/main/fern.schema.json
imports:
commons: ./commons.yml
pagination: ./utils/pagination.yml
service:
auth: true
base-path: /api/public
@@ -11,6 +12,23 @@ service:
path: /dataset-run-items
request: CreateDatasetRunItemRequest
response: commons.DatasetRunItem
list:
method: GET
docs: List dataset run items
path: /dataset-run-items
request:
name: ListDatasetRunItemsRequest
query-parameters:
datasetId: string
runName: string
page:
type: optional<integer>
docs: page number, starts at 1
limit:
type: optional<integer>
docs: limit of items per page
response: PaginatedDatasetRunItems
types:
CreateDatasetRunItemRequest:
properties:
@@ -26,3 +44,7 @@ types:
traceId:
type: optional<string>
docs: traceId should always be provided. For compatibility with older SDK versions it can also be inferred from the provided observationId.
PaginatedDatasetRunItems:
properties:
data: list<commons.DatasetRunItem>
meta: pagination.MetaResponse
+55 -62
View File
@@ -6,71 +6,64 @@ service:
auth: true
base-path: /api/public
endpoints:
daily:
docs: Get daily metrics of the Langfuse project
metrics:
docs: Get metrics from the Langfuse project using a query object
method: GET
path: /metrics/daily
path: /metrics
request:
name: GetDailyMetricsRequest
name: GetMetricsRequest
query-parameters:
page:
type: optional<integer>
docs: page number, starts at 1
limit:
type: optional<integer>
docs: limit of items per page
traceName:
type: optional<string>
docs: Optional filter by the name of the trace
userId:
type: optional<string>
docs: Optional filter by the userId associated with the trace
tags:
type: optional<string>
allow-multiple: true
docs: Optional filter for metrics where traces include all of these tags
environment:
type: optional<string>
allow-multiple: true
docs: Optional filter for metrics where events include any of these environments
fromTimestamp:
type: optional<datetime>
docs: Optional filter to only include traces and observations on or after a certain datetime (ISO 8601)
toTimestamp:
type: optional<datetime>
docs: Optional filter to only include traces and observations before a certain datetime (ISO 8601)
response: DailyMetrics
query:
type: string
docs: |
JSON string containing the query parameters with the following structure:
```json
{
"view": string, // Required. One of "traces", "observations", "scores-numeric", "scores-categorical"
"dimensions": [ // Optional. Default: []
{
"field": string // Field to group by, e.g. "name", "userId", "sessionId"
}
],
"metrics": [ // Required. At least one metric must be provided
{
"measure": string, // What to measure, e.g. "count", "latency", "value"
"aggregation": string // How to aggregate, e.g. "count", "sum", "avg", "p95", "histogram"
}
],
"filters": [ // Optional. Default: []
{
"column": string, // Column to filter on
"operator": string, // Operator, e.g. "=", ">", "<", "contains"
"value": any, // Value to compare against
"type": string, // Data type, e.g. "string", "number", "stringObject"
"key": string // Required only when filtering on metadata
}
],
"timeDimension": { // Optional. Default: null. If provided, results will be grouped by time
"granularity": string // One of "minute", "hour", "day", "week", "month", "auto"
},
"fromTimestamp": string, // Required. ISO datetime string for start of time range
"toTimestamp": string, // Required. ISO datetime string for end of time range
"orderBy": [ // Optional. Default: null
{
"field": string, // Field to order by
"direction": string // "asc" or "desc"
}
],
"config": { // Optional. Query-specific configuration
"bins": number, // Optional. Number of bins for histogram (1-100), default: 10
"row_limit": number // Optional. Row limit for results (1-1000)
}
}
```
response: MetricsResponse
types:
DailyMetrics:
MetricsResponse:
properties:
data:
type: list<DailyMetricsDetails>
docs: A list of daily metrics, only days with ingested data are included.
meta: pagination.MetaResponse
DailyMetricsDetails:
properties:
date: date
countTraces: integer
countObservations: integer
totalCost:
type: double
docs: Total model cost in USD
usage: list<UsageByModel>
UsageByModel:
docs: Daily usage of a given model. Usage corresponds to the unit set for the specific model (e.g. tokens).
properties:
model: optional<string>
inputUsage:
type: integer
docs: Total number of generation input units (e.g. tokens)
outputUsage:
type: integer
docs: Total number of generation output units (e.g. tokens)
totalUsage:
type: integer
docs: Total number of generation total units (e.g. tokens)
countTraces: integer
countObservations: integer
totalCost:
type: double
docs: Total model cost in USD
type: list<map<string, unknown>>
docs: |
The metrics data. Each item in the list contains the metric values and dimensions requested in the query.
Format varies based on the query parameters.
Histograms will return an array with [lower, upper, height] tuples.
+1 -1
View File
@@ -39,7 +39,7 @@ service:
docs: Optional filter for observations where the environment is one of the provided values.
fromStartTime:
type: optional<datetime>
docs: Retrieve only observations with a start_time or or after this datetime (ISO 8601).
docs: Retrieve only observations with a start_time on or after this datetime (ISO 8601).
toStartTime:
type: optional<datetime>
docs: Retrieve only observations with a start_time before this datetime (ISO 8601).
@@ -37,6 +37,12 @@ service:
request: MembershipRequest
response: MembershipResponse
getOrganizationProjects:
docs: Get all projects for the organization associated with the API key (requires organization-scoped API key)
method: GET
path: /organizations/projects
response: OrganizationProjectsResponse
types:
MembershipRole:
enum:
@@ -59,4 +65,16 @@ types:
MembershipsResponse:
properties:
memberships: list<MembershipResponse>
memberships: list<MembershipResponse>
OrganizationProject:
properties:
id: string
name: string
metadata: optional<map<string, unknown>>
createdAt: datetime
updatedAt: datetime
OrganizationProjectsResponse:
properties:
projects: list<OrganizationProject>
+9 -9
View File
@@ -11,7 +11,7 @@ service:
method: GET
path: /projects
response: Projects
create:
docs: Create a new project (requires organization-scoped API key)
method: POST
@@ -26,9 +26,9 @@ service:
docs: Optional metadata for the project
retention:
type: integer
docs: Number of days to retain data. Must be 0 or at least 7 days. Requires data-retention entitlement for non-zero values. Optional.
docs: Number of days to retain data. Must be 0 or at least 3 days. Requires data-retention entitlement for non-zero values. Optional.
response: Project
update:
docs: Update a project by ID (requires organization-scoped API key).
method: PUT
@@ -45,9 +45,9 @@ service:
docs: Optional metadata for the project
retention:
type: integer
docs: Number of days to retain data. Must be 0 or at least 7 days. Requires data-retention entitlement for non-zero values. Optional.
docs: Number of days to retain data. Must be 0 or at least 3 days. Requires data-retention entitlement for non-zero values. Optional.
response: Project
delete:
docs: Delete a project by ID (requires organization-scoped API key). Project deletion is processed asynchronously.
method: DELETE
@@ -57,7 +57,7 @@ service:
response:
status-code: 202
type: ProjectDeletionResponse
# API Key endpoints
getApiKeys:
docs: Get all API keys for a project (requires organization-scoped API key)
@@ -104,14 +104,14 @@ types:
type: map<string, unknown>
docs: Metadata for the project
retentionDays:
type: integer
type: optional<integer>
docs: Number of days to retain data. Null or 0 means no retention. Omitted if no retention is configured.
ProjectDeletionResponse:
properties:
success: boolean
message: string
ApiKeyList:
docs: List of API keys for a project
properties:
@@ -137,7 +137,7 @@ types:
secretKey: string
displaySecretKey: string
note: optional<string>
ApiKeyDeletionResponse:
docs: Response for API key deletion
properties:
+7 -5
View File
@@ -1,6 +1,6 @@
{
"name": "langfuse",
"version": "3.56.0",
"version": "3.70.0",
"author": "engineering@langfuse.com",
"license": "MIT",
"private": true,
@@ -18,7 +18,7 @@
"db:seed:examples": "turbo run db:seed:examples",
"nuke": "bash ./scripts/nuke.sh",
"dx": "pnpm i && pnpm run infra:dev:prune && pnpm run infra:dev:up --pull always && pnpm --filter=shared run db:reset && pnpm --filter=shared run ch:reset && pnpm --filter=shared run db:seed:examples && pnpm run dev",
"dx-f": "pnpm i && pnpm run infra:dev:prune && pnpm run infra:dev:up --pull always && pnpm --filter=shared run db:reset -f && pnpm --filter=shared run ch:reset && pnpm --filter=shared run db:seed:examples && pnpm run dev",
"dx-f": "pnpm i && pnpm run infra:dev:prune && pnpm run infra:dev:up --pull always && pnpm --filter=shared run db:reset -f && SKIP_CONFIRM=1 pnpm --filter=shared run ch:reset && pnpm --filter=shared run db:seed:examples && pnpm run dev",
"dx:skip-infra": "pnpm i && pnpm --filter=shared run db:reset && pnpm --filter=shared run ch:reset && pnpm --filter=shared run db:seed:examples && pnpm run dev",
"build": "turbo run build",
"start": "turbo run start",
@@ -31,12 +31,12 @@
"prepare": "husky"
},
"devDependencies": {
"@release-it/bumper": "^7.0.1",
"@release-it/bumper": "^7.0.5",
"braces": "3.0.3",
"dotenv-cli": "^7.4.2",
"husky": "^9.0.11",
"prettier": "^3.3.3",
"release-it": "^18.1.2",
"release-it": "^19.0.3",
"turbo": "^1.13.4"
},
"release-it": {
@@ -86,7 +86,9 @@
"pnpm": {
"overrides": {
"nanoid": "^3.3.8",
"katex": "^0.16.21"
"katex": "^0.16.21",
"tar-fs": "^2.1.2",
"rollup@^4.0.0": "^4.22.4"
},
"patchedDependencies": {
"next-auth@4.24.11": "patches/next-auth@4.24.11.patch"
@@ -0,0 +1 @@
DROP VIEW IF EXISTS analytics_traces ON CLUSTER default;
@@ -0,0 +1,15 @@
CREATE VIEW analytics_traces ON CLUSTER default AS
SELECT
project_id,
toStartOfHour(timestamp) AS hour,
uniq(id) AS countTraces,
max(user_id IS NOT NULL) AS hasUsers,
max(session_id IS NOT NULL) AS hasSessions,
max(if(environment != 'default', 1, 0)) AS hasEnvironments,
max(length(tags) > 0) AS hasTags
FROM
traces
WHERE toStartOfHour(timestamp) <= toStartOfHour(subtractHours(now(), 1))
GROUP BY
project_id,
hour;
@@ -0,0 +1 @@
DROP VIEW IF EXISTS analytics_observations ON CLUSTER default;
@@ -0,0 +1,18 @@
CREATE VIEW analytics_observations ON CLUSTER default AS
SELECT
project_id,
type,
toStartOfHour(start_time) AS hour,
uniq(id) AS countObservations,
max(level != 'DEFAULT') AS hasLevel,
max(provided_model_name IS NOT NULL) AS hasProvidedModelName,
max(length(provided_usage_details) > 0) AS hasProvidedUsageDetails,
max(length(provided_cost_details) > 0) AS hasProvidedCostDetails,
max(prompt_name IS NOT NULL) AS hasPromptName
FROM
observations
WHERE toStartOfHour(start_time) <= toStartOfHour(subtractHours(now(), 1))
GROUP BY
project_id,
type,
hour;
@@ -0,0 +1 @@
DROP VIEW IF EXISTS analytics_scores ON CLUSTER default;
@@ -0,0 +1,21 @@
CREATE VIEW analytics_scores ON CLUSTER default AS
SELECT
project_id,
toStartOfHour(timestamp) AS hour,
uniq(id) AS countScores,
max(source = 'ANNOTATION') AS hasAnnotation,
max(source = 'API') AS hasApi,
max(source = 'EVAL') AS hasEval,
max(observation_id IS NOT NULL) AS hasObservationScore,
max(session_id IS NOT NULL) AS hasSessionScore,
max(dataset_run_id IS NOT NULL) AS hasDatasetRunScore,
max(data_type = 'BOOLEAN') AS hasBoolScore,
max(data_type = 'NUMERIC') AS hasNumericScore,
max(data_type = 'CATEGORICAL') AS hasCategoricalScore,
max(comment IS NOT NULL) AS hasComment
FROM
scores
WHERE toStartOfHour(timestamp) <= toStartOfHour(subtractHours(now(), 1))
GROUP BY
project_id,
hour;
@@ -0,0 +1 @@
DROP VIEW IF EXISTS analytics_traces;
@@ -0,0 +1,15 @@
CREATE VIEW analytics_traces AS
SELECT
project_id,
toStartOfHour(timestamp) AS hour,
uniq(id) AS countTraces,
max(user_id IS NOT NULL) AS hasUsers,
max(session_id IS NOT NULL) AS hasSessions,
max(if(environment != 'default', 1, 0)) AS hasEnvironments,
max(length(tags) > 0) AS hasTags
FROM
traces
WHERE toStartOfHour(timestamp) <= toStartOfHour(subtractHours(now(), 1))
GROUP BY
project_id,
hour;
@@ -0,0 +1 @@
DROP VIEW IF EXISTS analytics_observations;
@@ -0,0 +1,18 @@
CREATE VIEW analytics_observations AS
SELECT
project_id,
type,
toStartOfHour(start_time) AS hour,
uniq(id) AS countObservations,
max(level != 'DEFAULT') AS hasLevel,
max(provided_model_name IS NOT NULL) AS hasProvidedModelName,
max(length(provided_usage_details) > 0) AS hasProvidedUsageDetails,
max(length(provided_cost_details) > 0) AS hasProvidedCostDetails,
max(prompt_name IS NOT NULL) AS hasPromptName
FROM
observations
WHERE toStartOfHour(start_time) <= toStartOfHour(subtractHours(now(), 1))
GROUP BY
project_id,
type,
hour;
@@ -0,0 +1 @@
DROP VIEW IF EXISTS analytics_scores;
@@ -0,0 +1,21 @@
CREATE VIEW analytics_scores AS
SELECT
project_id,
toStartOfHour(timestamp) AS hour,
uniq(id) AS countScores,
max(source = 'ANNOTATION') AS hasAnnotation,
max(source = 'API') AS hasApi,
max(source = 'EVAL') AS hasEval,
max(observation_id IS NOT NULL) AS hasObservationScore,
max(session_id IS NOT NULL) AS hasSessionScore,
max(dataset_run_id IS NOT NULL) AS hasDatasetRunScore,
max(data_type = 'BOOLEAN') AS hasBoolScore,
max(data_type = 'NUMERIC') AS hasNumericScore,
max(data_type = 'CATEGORICAL') AS hasCategoricalScore,
max(comment IS NOT NULL) AS hasComment
FROM
scores
WHERE toStartOfHour(timestamp) <= toStartOfHour(subtractHours(now(), 1))
GROUP BY
project_id,
hour;
+12 -4
View File
@@ -36,8 +36,12 @@ if [ "$CLICKHOUSE_CLUSTER_ENABLED" == "false" ] ; then
DATABASE_URL="${CLICKHOUSE_MIGRATION_URL}?username=${CLICKHOUSE_USER}&password=${CLICKHOUSE_PASSWORD}&database=${CLICKHOUSE_DB}&x-multi-statement=true&x-migrations-table-engine=MergeTree"
fi
# Execute the up command
migrate -source file://clickhouse/migrations/unclustered -database "$DATABASE_URL" down
# If SKIP_CONFIRM is set, automatically answer the confirmation prompt. Otherwise run interactively.
if [ "$SKIP_CONFIRM" = "1" ] || [ "$SKIP_CONFIRM" = "true" ]; then
printf 'y\n' | migrate -source file://clickhouse/migrations/unclustered -database "$DATABASE_URL" down
else
migrate -source file://clickhouse/migrations/unclustered -database "$DATABASE_URL" down
fi
else
if [ "$CLICKHOUSE_MIGRATION_SSL" = true ] ; then
DATABASE_URL="${CLICKHOUSE_MIGRATION_URL}?username=${CLICKHOUSE_USER}&password=${CLICKHOUSE_PASSWORD}&database=${CLICKHOUSE_DB}&x-multi-statement=true&secure=true&skip_verify=true&x-cluster-name=${CLICKHOUSE_CLUSTER_NAME}&x-migrations-table-engine=ReplicatedMergeTree"
@@ -45,6 +49,10 @@ else
DATABASE_URL="${CLICKHOUSE_MIGRATION_URL}?username=${CLICKHOUSE_USER}&password=${CLICKHOUSE_PASSWORD}&database=${CLICKHOUSE_DB}&x-multi-statement=true&x-cluster-name=${CLICKHOUSE_CLUSTER_NAME}&x-migrations-table-engine=ReplicatedMergeTree"
fi
# Execute the up command
migrate -source file://clickhouse/migrations/clustered -database "$DATABASE_URL" down
# If SKIP_CONFIRM is set, automatically answer the confirmation prompt. Otherwise run interactively.
if [ "$SKIP_CONFIRM" = "1" ] || [ "$SKIP_CONFIRM" = "true" ]; then
printf 'y\n' | migrate -source file://clickhouse/migrations/clustered -database "$DATABASE_URL" down
else
migrate -source file://clickhouse/migrations/clustered -database "$DATABASE_URL" down
fi
fi
+14 -13
View File
@@ -33,7 +33,7 @@
"scripts": {
"build": "tsc",
"dev": "tsc --watch",
"lint": "eslint . --ext .js,.jsx,.ts,.tsx --max-warnings 65",
"lint": "eslint . --ext .js,.jsx,.ts,.tsx --max-warnings 70",
"lint:fix": "eslint . --ext .js,.jsx,.ts,.tsx --fix",
"db:migrate": "DISABLE_ERD=false dotenv -e ../../.env -- npx prisma migrate dev",
"db:push": "DISABLE_ERD=false dotenv -e ../../.env -- npx prisma db push",
@@ -60,18 +60,18 @@
"@aws-sdk/lib-storage": "^3.675.0",
"@aws-sdk/s3-request-presigner": "^3.679.0",
"@azure/storage-blob": "^12.26.0",
"@clickhouse/client": "^1.4.0",
"@clickhouse/client": "^1.11.2",
"@google-cloud/storage": "^7.15.2",
"@langchain/anthropic": "^0.3.12",
"@langchain/aws": "^0.1.3",
"@langchain/core": "^0.3.37",
"@langchain/google-genai": "^0.1.9",
"@langchain/google-vertexai": "^0.1.8",
"@langchain/openai": "^0.3.17",
"@langchain/anthropic": "^0.3.22",
"@langchain/aws": "^0.1.11",
"@langchain/core": "^0.3.58",
"@langchain/google-genai": "^0.2.12",
"@langchain/google-vertexai": "^0.2.12",
"@langchain/openai": "^0.5.13",
"@opentelemetry/api": ">=1.0.0 <1.10.0",
"@prisma/client": "^6.3.0",
"@react-email/components": "^0.0.19",
"@react-email/render": "^0.0.15",
"@react-email/components": "^0.0.42",
"@react-email/render": "^1.1.2",
"@types/bcryptjs": "^2.4.6",
"axios": "^1.8.2",
"bcryptjs": "^2.4.3",
@@ -82,8 +82,8 @@
"https-proxy-agent": "^7.0.6",
"ioredis": "^5.4.1",
"kysely": "^0.27.4",
"langchain": "^0.3.15",
"langfuse-langchain": "3.30.3",
"langchain": "^0.3.28",
"langfuse-langchain": "3.37.4",
"lodash": "^4.17.21",
"lossless-json": "^4.0.2",
"next-auth": "^4.24.11",
@@ -91,7 +91,7 @@
"prisma-extension-kysely": "^2.1.0",
"uuid": "^9.0.1",
"winston": "^3.15.0",
"zod": "^3.23.8",
"zod": "^3.25.62",
"zod-to-json-schema": "^3.23.5"
},
"devDependencies": {
@@ -101,6 +101,7 @@
"@types/node": "^20.11.29",
"@types/nodemailer": "^6.4.16",
"@types/pg": "^8.11.10",
"@types/react": "18.2.79",
"@types/uuid": "^9.0.8",
"@typescript-eslint/parser": "^7.12.0",
"eslint": "^8.57.0",
+23 -7
View File
@@ -109,7 +109,9 @@ export const DashboardWidgetChartType = {
BAR_TIME_SERIES: "BAR_TIME_SERIES",
HORIZONTAL_BAR: "HORIZONTAL_BAR",
VERTICAL_BAR: "VERTICAL_BAR",
PIE: "PIE"
PIE: "PIE",
NUMBER: "NUMBER",
HISTOGRAM: "HISTOGRAM"
} as const;
export type DashboardWidgetChartType = (typeof DashboardWidgetChartType)[keyof typeof DashboardWidgetChartType];
export type Account = {
@@ -227,8 +229,8 @@ export type BlobStorageIntegration = {
type: BlobStorageIntegrationType;
bucket_name: string;
prefix: string;
access_key_id: string;
secret_access_key: string;
access_key_id: string | null;
secret_access_key: string | null;
region: string;
endpoint: string | null;
force_path_style: boolean;
@@ -325,17 +327,29 @@ export type DatasetRuns = {
created_at: Generated<Timestamp>;
updated_at: Generated<Timestamp>;
};
export type EvalTemplate = {
export type DefaultLlmModel = {
id: string;
created_at: Generated<Timestamp>;
updated_at: Generated<Timestamp>;
project_id: string;
llm_api_key_id: string;
provider: string;
adapter: string;
model: string;
model_params: unknown | null;
};
export type EvalTemplate = {
id: string;
created_at: Generated<Timestamp>;
updated_at: Generated<Timestamp>;
project_id: string | null;
name: string;
version: number;
prompt: string;
model: string;
provider: string;
model_params: unknown;
partner: string | null;
model: string | null;
provider: string | null;
model_params: unknown | null;
vars: Generated<string[]>;
output_schema: unknown;
};
@@ -361,6 +375,7 @@ export type JobExecution = {
updated_at: Generated<Timestamp>;
project_id: string;
job_configuration_id: string;
job_template_id: string | null;
status: JobExecutionStatus;
start_time: Timestamp | null;
end_time: Timestamp | null;
@@ -702,6 +717,7 @@ export type DB = {
dataset_run_items: DatasetRunItems;
dataset_runs: DatasetRuns;
datasets: Dataset;
default_llm_models: DefaultLlmModel;
eval_templates: EvalTemplate;
job_configurations: JobConfiguration;
job_executions: JobExecution;
@@ -0,0 +1,2 @@
-- CreateIndex
CREATE INDEX CONCURRENTLY IF NOT EXISTS "trace_media_project_id_media_id_idx" ON "trace_media"("project_id", "media_id");
@@ -0,0 +1,2 @@
-- CreateIndex
CREATE INDEX CONCURRENTLY IF NOT EXISTS "observation_media_project_id_media_id_idx" ON "observation_media"("project_id", "media_id");
@@ -0,0 +1,3 @@
-- Index cannot be created concurrently in a transaction, so we need to create it separately
-- Prerequisite for migration 20250518075613_media_relax_id_uniqueness_to_project_only
CREATE UNIQUE INDEX CONCURRENTLY IF NOT EXISTS "media_project_id_id_key" ON "media"("project_id", "id");
@@ -0,0 +1,21 @@
/*
Warnings:
- The primary key for the `media` table will be changed. If it partially fails, the table could be left without primary key constraint.
- A unique constraint covering the columns `[project_id,id]` on the table `media` will be added. If there are existing duplicate values, this will fail.
*/
-- DropForeignKey
ALTER TABLE "observation_media" DROP CONSTRAINT "observation_media_media_id_fkey";
-- DropForeignKey
ALTER TABLE "trace_media" DROP CONSTRAINT "trace_media_media_id_fkey";
-- AlterTable
ALTER TABLE "media" DROP CONSTRAINT "media_pkey";
-- AddForeignKey
ALTER TABLE "trace_media" ADD CONSTRAINT "trace_media_media_id_project_id_fkey" FOREIGN KEY ("media_id", "project_id") REFERENCES "media"("id", "project_id") ON DELETE CASCADE ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "observation_media" ADD CONSTRAINT "observation_media_media_id_project_id_fkey" FOREIGN KEY ("media_id", "project_id") REFERENCES "media"("id", "project_id") ON DELETE CASCADE ON UPDATE CASCADE;
@@ -0,0 +1,33 @@
/* Triple y and y_size in dashboards.definition->'widgets' */
WITH updated AS (
SELECT
id,
CASE
WHEN jsonb_array_length(definition->'widgets') = 0 THEN definition
ELSE jsonb_set(
definition, -- original JSON
'{widgets}', -- path to replace
(
SELECT jsonb_agg( -- rebuild widgets array
/* 1) y * 3 2) y_size * 3 */
jsonb_set(
jsonb_set(widget, '{y}',
to_jsonb( ((widget->>'y')::int * 3) ), /* y */
true
),
'{y_size}',
to_jsonb( ((widget->>'y_size')::int * 3) ),/* y_size */
true
)
)
FROM jsonb_array_elements(definition->'widgets') AS widget
),
true -- create path if absent
)
END AS new_def
FROM dashboards
)
UPDATE dashboards d
SET definition = u.new_def
FROM updated u
WHERE d.id = u.id;
@@ -0,0 +1,2 @@
-- AlterEnum
ALTER TYPE "DashboardWidgetChartType" ADD VALUE 'NUMBER';
@@ -0,0 +1,2 @@
-- DropIndex
DROP INDEX CONCURRENTLY IF EXISTS "observation_media_project_id_observation_id_idx";
@@ -0,0 +1,23 @@
-- CreateTable
CREATE TABLE "default_llm_models" (
"id" TEXT NOT NULL,
"created_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updated_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"project_id" TEXT NOT NULL,
"llm_api_key_id" TEXT NOT NULL,
"provider" TEXT NOT NULL,
"adapter" TEXT NOT NULL,
"model" TEXT NOT NULL,
"model_params" JSONB,
CONSTRAINT "default_llm_models_pkey" PRIMARY KEY ("id")
);
-- AddForeignKey
ALTER TABLE "default_llm_models" ADD CONSTRAINT "default_llm_models_project_id_fkey" FOREIGN KEY ("project_id") REFERENCES "projects"("id") ON DELETE CASCADE ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "default_llm_models" ADD CONSTRAINT "default_llm_models_llm_api_key_id_fkey" FOREIGN KEY ("llm_api_key_id") REFERENCES "llm_api_keys"("id") ON DELETE CASCADE ON UPDATE CASCADE;
-- AddUniqueConstraint
ALTER TABLE "default_llm_models" ADD CONSTRAINT "default_llm_models_project_id_key" UNIQUE ("project_id");
@@ -0,0 +1,6 @@
-- AlterTable
ALTER TABLE "eval_templates" ALTER COLUMN "project_id" DROP NOT NULL;
ALTER TABLE "eval_templates" ALTER COLUMN "model" DROP NOT NULL;
ALTER TABLE "eval_templates" ALTER COLUMN "provider" DROP NOT NULL;
ALTER TABLE "eval_templates" ALTER COLUMN "model_params" DROP NOT NULL;
ALTER TABLE "eval_templates" ADD COLUMN "partner" TEXT;
@@ -0,0 +1,3 @@
-- AlterTable
ALTER TABLE "job_executions" ADD COLUMN "job_template_id" TEXT;
ALTER TABLE "job_executions" ADD CONSTRAINT "job_executions_job_template_id_fkey" FOREIGN KEY ("job_template_id") REFERENCES "eval_templates"("id") ON DELETE SET NULL;
@@ -0,0 +1,3 @@
-- AlterTable
ALTER TABLE "blob_storage_integrations" ALTER COLUMN "access_key_id" DROP NOT NULL,
ALTER COLUMN "secret_access_key" DROP NOT NULL;
@@ -0,0 +1,2 @@
-- AlterEnum
ALTER TYPE "DashboardWidgetChartType" ADD VALUE 'HISTOGRAM';
+49 -16
View File
@@ -157,6 +157,7 @@ model Project {
Dashboard Dashboard[]
DashboardWidget DashboardWidget[]
TableViewPreset TableViewPreset[]
DefaultLlmModel DefaultLlmModel[]
@@index([orgId])
@@map("projects")
@@ -222,8 +223,9 @@ model LlmApiKeys {
extraHeaderKeys String[] @default([]) @map("extra_header_keys")
config Json?
projectId String @map("project_id")
project Project @relation(fields: [projectId], references: [id], onDelete: Cascade)
projectId String @map("project_id")
project Project @relation(fields: [projectId], references: [id], onDelete: Cascade)
DefaultLlmModel DefaultLlmModel[] @relation("LlmApiKeyId")
@@unique([projectId, provider])
@@map("llm_api_keys")
@@ -793,18 +795,22 @@ model EvalTemplate {
createdAt DateTime @default(now()) @map("created_at")
updatedAt DateTime @default(now()) @updatedAt @map("updated_at")
projectId String @map("project_id")
project Project @relation(fields: [projectId], references: [id], onDelete: Cascade)
projectId String? @map("project_id")
project Project? @relation(fields: [projectId], references: [id], onDelete: Cascade)
name String
version Int
prompt String
model String
provider String
modelParams Json @map("model_params")
name String
version Int
prompt String
partner String? // e.g. "ragas", describes the partner that created the template
model String?
provider String?
modelParams Json? @map("model_params")
vars String[] @default([])
outputSchema Json @map("output_schema")
JobConfiguration JobConfiguration[]
JobExecution JobExecution[]
@@unique([projectId, name, version])
@@index([projectId, id])
@@ -864,6 +870,9 @@ model JobExecution {
jobConfigurationId String @map("job_configuration_id")
jobConfiguration JobConfiguration @relation(fields: [jobConfigurationId], references: [id], onDelete: Cascade)
jobTemplateId String? @map("job_template_id")
jobTemplate EvalTemplate? @relation(fields: [jobTemplateId], references: [id], onDelete: SetNull)
status JobExecutionStatus
startTime DateTime? @map("start_time")
endTime DateTime? @map("end_time")
@@ -887,6 +896,26 @@ model JobExecution {
@@map("job_executions")
}
model DefaultLlmModel {
id String @id @default(cuid())
createdAt DateTime @default(now()) @map("created_at")
updatedAt DateTime @default(now()) @updatedAt @map("updated_at")
projectId String @map("project_id")
Project Project @relation(fields: [projectId], references: [id])
llmApiKeyId String @map("llm_api_key_id")
LlmApiKey LlmApiKeys @relation("LlmApiKeyId", fields: [llmApiKeyId], references: [id], onDelete: Cascade)
provider String
adapter String // This controls the interface that is used to connect with the LLM, e.g. 'openai' or 'anthropic'
model String
modelParams Json? @map("model_params")
@@unique([projectId])
@@map("default_llm_models")
}
// Single Sign-On configuration for a domain
// This feature is part of the Enterprise Edition
model SsoConfig {
@@ -922,8 +951,8 @@ model BlobStorageIntegration {
type BlobStorageIntegrationType @map("type")
bucketName String @map("bucket_name")
prefix String @map("prefix")
accessKeyId String @map("access_key_id")
secretAccessKey String @map("secret_access_key")
accessKeyId String? @map("access_key_id")
secretAccessKey String? @map("secret_access_key")
region String @map("region")
endpoint String? @map("endpoint")
forcePathStyle Boolean @map("force_path_style")
@@ -982,7 +1011,7 @@ model BatchExport {
}
model Media {
id String @id @default(cuid())
id String
sha256Hash String @map("sha_256_hash") @db.Char(44)
projectId String @map("project_id")
project Project @relation(fields: [projectId], references: [id], onDelete: Cascade)
@@ -998,6 +1027,7 @@ model Media {
TraceMedia TraceMedia[]
ObservationMedia ObservationMedia[]
@@unique([projectId, id])
@@unique([projectId, sha256Hash])
@@map("media")
}
@@ -1009,11 +1039,12 @@ model TraceMedia {
createdAt DateTime @default(now()) @map("created_at")
updatedAt DateTime @default(now()) @updatedAt @map("updated_at")
mediaId String @map("media_id")
media Media @relation(fields: [mediaId], references: [id], onDelete: Cascade)
media Media @relation(fields: [mediaId, projectId], references: [id, projectId], onDelete: Cascade)
traceId String @map("trace_id")
field String @map("field")
@@unique([projectId, traceId, mediaId, field])
@@index([projectId, mediaId])
@@map("trace_media")
}
@@ -1024,13 +1055,13 @@ model ObservationMedia {
createdAt DateTime @default(now()) @map("created_at")
updatedAt DateTime @default(now()) @updatedAt @map("updated_at")
mediaId String @map("media_id")
media Media @relation(fields: [mediaId], references: [id], onDelete: Cascade)
media Media @relation(fields: [mediaId, projectId], references: [id, projectId], onDelete: Cascade)
traceId String @map("trace_id")
observationId String @map("observation_id")
field String @map("field")
@@unique([projectId, traceId, observationId, mediaId, field])
@@index([projectId, observationId])
@@index([projectId, mediaId])
@@map("observation_media")
}
@@ -1124,6 +1155,8 @@ enum DashboardWidgetChartType {
HORIZONTAL_BAR
VERTICAL_BAR
PIE
NUMBER
HISTOGRAM
}
model DashboardWidget {
+2 -2
View File
@@ -496,7 +496,7 @@ async function createDashboardsAndWidgets(projects: Project[]) {
x: 0,
y: 0,
x_size: 6,
y_size: 2,
y_size: 6,
},
{
type: "widget",
@@ -505,7 +505,7 @@ async function createDashboardsAndWidgets(projects: Project[]) {
x: 6,
y: 0,
x_size: 6,
y_size: 2,
y_size: 6,
},
],
},
+1 -1
View File
@@ -1,4 +1,4 @@
import z from "zod";
import z from "zod/v4";
import { jsonSchema } from "../utils/zod";
import { MetadataDomain } from "./traces";
+2 -2
View File
@@ -1,5 +1,5 @@
import { ScoreDataType } from "@prisma/client";
import z from "zod";
import z from "zod/v4";
import { MetadataDomain } from "./traces";
export const ScoreSource = {
@@ -31,7 +31,7 @@ export const ScoreSchema = z.object({
queueId: z.string().nullable(),
createdAt: z.date(),
updatedAt: z.date(),
dataType: z.nativeEnum(ScoreDataType),
dataType: z.enum(ScoreDataType),
});
export type ScoreDomain = z.infer<typeof ScoreSchema>;
@@ -1,6 +1,6 @@
import { singleFilter } from "../interfaces/filters";
import { orderBy } from "../interfaces/orderBy";
import z from "zod";
import z from "zod/v4";
export enum TableViewPresetTableName {
Traces = "traces",
@@ -17,7 +17,7 @@ const TableViewPresetDomainSchema = z.object({
updatedAt: z.date(),
createdBy: z.string().nullable(),
name: z.string(),
tableName: z.nativeEnum(TableViewPresetTableName),
tableName: z.enum(TableViewPresetTableName),
filters: z.array(singleFilter),
columnOrder: z.array(z.string()),
columnVisibility: z.record(z.string(), z.boolean()),
+1 -1
View File
@@ -1,4 +1,4 @@
import z from "zod";
import z from "zod/v4";
import { jsonSchema, jsonSchemaNullable } from "../utils/zod";
export const MetadataDomain = z.record(
+25 -8
View File
@@ -1,4 +1,4 @@
import { z } from "zod";
import { z } from "zod/v4";
import { removeEmptyEnvVariables } from "./utils/environment";
const EnvSchema = z.object({
@@ -9,10 +9,7 @@ const EnvSchema = z.object({
NEXTAUTH_URL: z.string().url().optional(),
REDIS_HOST: z.string().nullish(),
REDIS_PORT: z.coerce
.number({
description:
".env files convert numbers to strings, therefore we have to enforce them to be numbers",
})
.number() // .env files convert numbers to strings, therefore we have to enforce them to be numbers
.positive()
.max(65536, `options.port should be >= 0 and < 65536`)
.default(6379)
@@ -24,6 +21,9 @@ const EnvSchema = z.object({
REDIS_TLS_CERT_PATH: z.string().optional(),
REDIS_TLS_KEY_PATH: z.string().optional(),
REDIS_ENABLE_AUTO_PIPELINING: z.enum(["true", "false"]).default("true"),
// Redis Cluster Configuration
REDIS_CLUSTER_ENABLED: z.enum(["true", "false"]).default("false"),
REDIS_CLUSTER_NODES: z.string().optional(),
ENCRYPTION_KEY: z
.string()
.length(
@@ -38,23 +38,33 @@ const EnvSchema = z.object({
CLICKHOUSE_DB: z.string().default("default"),
CLICKHOUSE_USER: z.string(),
CLICKHOUSE_PASSWORD: z.string(),
CLICKHOUSE_KEEP_ALIVE_IDLE_SOCKET_TTL: z.coerce.number().int().default(9000),
CLICKHOUSE_MAX_OPEN_CONNECTIONS: z.coerce.number().int().default(25),
LANGFUSE_INGESTION_QUEUE_DELAY_MS: z.coerce
.number()
.nonnegative()
.default(15_000),
LANGFUSE_INGESTION_QUEUE_SHARD_COUNT: z.coerce
.number()
.positive()
.default(1),
SALT: z.string().optional(), // used by components imported by web package
LANGFUSE_LOG_LEVEL: z
.enum(["trace", "debug", "info", "warn", "error", "fatal"])
.optional(),
LANGFUSE_LOG_FORMAT: z.enum(["text", "json"]).default("text"),
LANGFUSE_LOG_PROPAGATED_HEADERS: z
.string()
.optional()
.transform((s) =>
s ? s.split(",").map((s) => s.toLowerCase().trim()) : [],
),
ENABLE_AWS_CLOUDWATCH_METRIC_PUBLISHING: z
.enum(["true", "false"])
.default("false"),
LANGFUSE_S3_CONCURRENT_WRITES: z.coerce.number().positive().default(50),
LANGFUSE_S3_EVENT_UPLOAD_BUCKET: z.string({
required_error: "Langfuse requires a bucket name for S3 Event Uploads.",
}),
LANGFUSE_S3_EVENT_UPLOAD_BUCKET: z.string(), // Langfuse requires a bucket name for S3 Event Uploads.
LANGFUSE_S3_EVENT_UPLOAD_PREFIX: z.string().default(""),
LANGFUSE_S3_EVENT_UPLOAD_REGION: z.string().optional(),
LANGFUSE_S3_EVENT_UPLOAD_ENDPOINT: z.string().optional(),
@@ -63,6 +73,8 @@ const EnvSchema = z.object({
LANGFUSE_S3_EVENT_UPLOAD_FORCE_PATH_STYLE: z
.enum(["true", "false"])
.default("false"),
LANGFUSE_S3_EVENT_UPLOAD_SSE: z.enum(["AES256", "aws:kms"]).optional(),
LANGFUSE_S3_EVENT_UPLOAD_SSE_KMS_KEY_ID: z.string().optional(),
LANGFUSE_S3_MEDIA_UPLOAD_BUCKET: z.string().optional(),
LANGFUSE_S3_MEDIA_UPLOAD_PREFIX: z.string().default(""),
LANGFUSE_S3_MEDIA_UPLOAD_REGION: z.string().optional(),
@@ -72,6 +84,8 @@ const EnvSchema = z.object({
LANGFUSE_S3_MEDIA_UPLOAD_FORCE_PATH_STYLE: z
.enum(["true", "false"])
.default("false"),
LANGFUSE_S3_MEDIA_UPLOAD_SSE: z.enum(["AES256", "aws:kms"]).optional(),
LANGFUSE_S3_MEDIA_UPLOAD_SSE_KMS_KEY_ID: z.string().optional(),
LANGFUSE_USE_AZURE_BLOB: z.enum(["true", "false"]).default("false"),
LANGFUSE_USE_GOOGLE_CLOUD_STORAGE: z.enum(["true", "false"]).default("false"),
LANGFUSE_GOOGLE_CLOUD_STORAGE_CREDENTIALS: z.string().optional(),
@@ -80,6 +94,8 @@ const EnvSchema = z.object({
LANGFUSE_S3_CORE_DATA_EXPORT_IS_ENABLED: z
.enum(["true", "false"])
.default("false"),
LANGFUSE_S3_CORE_DATA_EXPORT_SSE: z.enum(["AES256", "aws:kms"]).optional(),
LANGFUSE_S3_CORE_DATA_EXPORT_SSE_KMS_KEY_ID: z.string().optional(),
LANGFUSE_POSTGRES_METERING_DATA_EXPORT_IS_ENABLED: z
.enum(["true", "false"])
.default("false"),
@@ -90,6 +106,7 @@ const EnvSchema = z.object({
LANGFUSE_API_TRACE_OBSERVATIONS_SIZE_LIMIT_BYTES: z.coerce
.number()
.default(80e6), // 80MB
LANGFUSE_CLICKHOUSE_DELETION_TIMEOUT_MS: z.coerce.number().default(240_000), // 4 minutes
});
export const env: z.infer<typeof EnvSchema> =
@@ -1,4 +1,4 @@
import z from "zod";
import z from "zod/v4";
import { type ScoreDataType } from "../../db";
const NUMERIC: ScoreDataType = "NUMERIC";
@@ -1,7 +1,8 @@
import z from "zod";
import z from "zod/v4";
import { singleFilter } from "../../interfaces/filters";
import { orderBy } from "../../interfaces/orderBy";
import { BatchExportTableName } from "../batchExport/types";
import { BatchTableNames } from "../../interfaces/tableNames";
import { TracingSearchType } from "../../interfaces/search";
/* eslint-disable no-unused-vars */
export enum BatchActionType {
@@ -20,6 +21,8 @@ export type ActionId = z.infer<typeof ActionIdSchema>;
export const BatchActionQuerySchema = z.object({
filter: z.array(singleFilter).nullable(),
orderBy,
searchQuery: z.string().optional(),
searchType: z.array(TracingSearchType).optional(),
});
export type BatchActionQuery = z.infer<typeof BatchActionQuerySchema>;
@@ -29,11 +32,11 @@ export const CreateBatchActionSchema = z.object({
actionId: ActionIdSchema,
targetId: z.string().optional(),
query: BatchActionQuerySchema,
tableName: z.nativeEnum(BatchExportTableName),
tableName: z.enum(BatchTableNames),
});
export const GetIsBatchActionInProgressSchema = z.object({
projectId: z.string(),
actionId: ActionIdSchema,
tableName: z.nativeEnum(BatchExportTableName),
tableName: z.enum(BatchTableNames),
});
@@ -1,9 +1,10 @@
import z from "zod";
import z from "zod/v4";
import { BatchExport } from "@prisma/client";
import { singleFilter } from "../../interfaces/filters";
import { orderBy } from "../../interfaces/orderBy";
import { BatchTableNames } from "../../interfaces/tableNames";
export enum BatchExportStatus {
QUEUED = "QUEUED",
@@ -18,13 +19,9 @@ export enum BatchExportFileFormat {
JSONL = "JSONL",
}
export enum BatchExportTableName {
Scores = "scores",
Sessions = "sessions",
Traces = "traces",
Observations = "observations",
DatasetRunItems = "dataset_run_items",
}
// Use shared BatchTableNames enum for consistency across batch operations
// Keep BatchExportTableName as alias for backward compatibility
export { BatchTableNames as BatchExportTableName };
export const exportOptions: Record<
BatchExportFileFormat,
@@ -44,7 +41,7 @@ export const exportOptions: Record<
} as const;
export const BatchExportQuerySchema = z.object({
tableName: z.nativeEnum(BatchExportTableName),
tableName: z.enum(BatchTableNames),
filter: z.array(singleFilter).nullable(),
orderBy,
limit: z.number().optional(),
@@ -57,7 +54,7 @@ export const CreateBatchExportSchema = z.object({
projectId: z.string(),
name: z.string(),
query: BatchExportQuerySchema,
format: z.nativeEnum(BatchExportFileFormat),
format: z.enum(BatchExportFileFormat),
});
export const BatchExportSchema = z.object({
@@ -69,9 +66,9 @@ export const BatchExportSchema = z.object({
finishedAt: z.date().nullable(),
expiresAt: z.date().nullable(),
name: z.string(),
status: z.nativeEnum(BatchExportStatus),
status: z.enum(BatchExportStatus),
query: BatchExportQuerySchema,
format: z.nativeEnum(BatchExportFileFormat),
format: z.enum(BatchExportFileFormat),
url: z.string().nullable(),
log: z.string().nullable(),
});
@@ -1,4 +1,4 @@
import { z } from "zod";
import { z } from "zod/v4";
const MAX_COMMENT_LENGTH = 3000;
+6 -3
View File
@@ -1,4 +1,4 @@
import z from "zod";
import z from "zod/v4";
export const langfuseObjects = [
"trace",
@@ -8,6 +8,9 @@ export const langfuseObjects = [
"dataset_item",
] as const;
const langfuseObject = z.enum(langfuseObjects);
export type LangfuseEvaluationObject = z.infer<typeof langfuseObject>;
// variable mapping stored in the db for eval templates
export const variableMapping = z
.object({
@@ -15,7 +18,7 @@ export const variableMapping = z
// name of the observation to extract the variable from
// not required for trace, as we only have one.
objectName: z.string().nullish(),
langfuseObject: z.enum(langfuseObjects),
langfuseObject: langfuseObject,
selectedColumnId: z.string(),
jsonSelector: z.string().nullish(),
})
@@ -31,7 +34,7 @@ export const variableMappingList = z.array(variableMapping);
export const wipVariableMapping = z.object({
templateVariable: z.string(),
objectName: z.string().nullish(),
langfuseObject: z.enum(langfuseObjects),
langfuseObject: langfuseObject,
selectedColumnId: z.string().nullish(),
jsonSelector: z.string().nullish(),
});
@@ -0,0 +1,66 @@
import z from "zod/v4";
import { variableMapping } from "./types";
/**
* Parses an unknown value to a string representation
* This is used for any evaluation variable that needs string conversion
*/
export const parseUnknownToString = (value: unknown): string => {
if (value === null || value === undefined) {
return "";
}
if (
typeof value === "string" ||
typeof value === "number" ||
typeof value === "boolean"
) {
return value.toString();
}
if (typeof value === "object") {
return JSON.stringify(value);
}
if (typeof value === "symbol") {
return value.toString();
}
return String(value);
};
function parseJsonDefault(selectedColumn: unknown, jsonSelector: string) {
// Front-end friendly JSON path extraction
const parsedJson =
typeof selectedColumn === "string"
? JSON.parse(selectedColumn)
: selectedColumn;
// Simple path extraction (could use a library)
return jsonSelector
.split(".")
.reduce((o, key) => (o as any)?.[key], parsedJson);
}
export function extractValueFromObject(
obj: Record<string, unknown>,
mapping: z.infer<typeof variableMapping>,
parseJson?: (selectedColumn: unknown, jsonSelector: string) => unknown,
): string {
const selectedColumn = obj[mapping.selectedColumnId];
const jsonParser = parseJson || parseJsonDefault;
let jsonSelectedColumn;
if (mapping.jsonSelector && selectedColumn) {
try {
jsonSelectedColumn = jsonParser(selectedColumn, mapping.jsonSelector);
} catch (error) {
console.error(
`Error parsing JSON selector: ${mapping.jsonSelector}`,
error,
);
jsonSelectedColumn = selectedColumn;
}
} else {
jsonSelectedColumn = selectedColumn;
}
return parseUnknownToString(jsonSelectedColumn);
}
@@ -1,4 +1,4 @@
import { z } from "zod";
import { z } from "zod/v4";
export const PromptDependencyRegex = /@@@langfusePrompt:(.*?)@@@/g;
@@ -1,4 +1,4 @@
import { z } from "zod";
import { z } from "zod/v4";
import { jsonSchema, publicApiPaginationZod } from "../../../../utils/zod";
import { stringDateTime } from "../../../../utils/typeChecks";
import { applyScoreValidation } from "../../../../utils/scores";
@@ -1,4 +1,4 @@
import { z } from "zod";
import { z } from "zod/v4";
import { paginationMetaResponseZod } from "../../../../../utils/zod";
import {
DeleteScoreQuery,
@@ -1,4 +1,4 @@
import { z } from "zod";
import { z } from "zod/v4";
import {
CategoricalData,
NumericData,
@@ -1,4 +1,4 @@
import z from "zod";
import z from "zod/v4";
import { GetScoreResponseDataV1 } from "./endpoints";
/**
@@ -1,4 +1,4 @@
import z from "zod";
import z from "zod/v4";
import { paginationMetaResponseZod } from "../../../../../utils/zod";
import { GetScoreQuery, GetScoresQuery } from "../shared";
import { APIScoreSchemaV2 } from "./schemas";
@@ -1,4 +1,4 @@
import { z } from "zod";
import { z } from "zod/v4";
import {
CategoricalData,
NumericData,
@@ -1,4 +1,4 @@
import z from "zod";
import z from "zod/v4";
import { GetScoreResponseDataV2 } from "./endpoints";
/**
@@ -1,4 +1,4 @@
import z from "zod";
import z from "zod/v4";
import { APIScoreSchemaV2, APIScoreV2 } from "../api/v2/schemas";
import { APIScoreSchemaV1, APIScoreV1 } from "../api/v1/schemas";
import { ScoreDomain } from "../../../../domain";
@@ -1,4 +1,4 @@
import z from "zod";
import z from "zod/v4";
import { applyScoreValidation } from "../../../../utils/scores";
import { PostScoreBodyFoundationSchema } from "../shared";
import { isPresent } from "../../../../utils/typeChecks";
@@ -1,5 +1,5 @@
import { jsonSchema } from "../../../utils/zod";
import z from "zod";
import z from "zod/v4";
import { NonEmptyString } from "../../../utils/zod";
/**
@@ -1,4 +1,4 @@
import { z } from "zod";
import { z } from "zod/v4";
import { ScoreConfig as ScoreConfigDbType } from "@prisma/client";
@@ -68,10 +68,10 @@ const CategoricalScoreConfig = z.object({
const parseResult = Categories.safeParse(categories);
if (!parseResult.success) {
ctx.addIssue({
code: z.ZodIssueCode.custom,
code: "custom",
message:
"Category must be an array of objects with label value pairs, where labels and values are unique.",
});
} as z.core.$ZodIssueCustom);
return;
}
@@ -198,7 +198,7 @@ export const GetScoreConfigResponse = ValidatedScoreConfigSchema;
// POST /score-configs
export const PostScoreConfigBody = z
.union([
.discriminatedUnion("dataType", [
ScoreConfigPostBase.merge(CategoricalScoreConfig),
ScoreConfigPostBase.merge(NumericScoreConfig),
ScoreConfigPostBase.merge(
+2 -1
View File
@@ -22,10 +22,11 @@ export * from "./server/llm/types";
// evals
export * from "./features/evals/types";
export * from "./features/evals/utilities";
// table actions
export * from "./features/batchExport/types";
export * from "./features/batchAction/types";
export { BatchTableNames } from "./interfaces/tableNames";
// annotation
export * from "./features/annotation/types";
@@ -1,4 +1,4 @@
import { z } from "zod";
import { z } from "zod/v4";
import { CloudConfigRateLimit } from "./rate-limits";
import { cloudConfigPlans } from "../features/entitlements/plans";
@@ -1,4 +1,4 @@
import { z } from "zod";
import { z } from "zod/v4";
export const BedrockConfigSchema = z.object({ region: z.string() });
export type BedrockConfig = z.infer<typeof BedrockConfigSchema>;
+1 -1
View File
@@ -1,4 +1,4 @@
import { z } from "zod";
import { z } from "zod/v4";
export const filterOperators = {
datetime: [">", "<", ">=", "<="],
+1 -1
View File
@@ -1,4 +1,4 @@
import { z } from "zod";
import { z } from "zod/v4";
export const orderBy = z
.object({
@@ -1,12 +1,14 @@
import z from "zod";
import z from "zod/v4";
import { ApiAccessScope } from "../server";
export const RateLimitResource = z.enum([
"ingestion",
"public-api",
"public-api-metrics",
"public-api-daily-metrics-legacy",
"prompts",
"legacy-ingestion",
"datasets",
]);
// result of the rate limit check.
+1 -1
View File
@@ -1,4 +1,4 @@
import { z } from "zod";
import { z } from "zod/v4";
export const TracingSearchType = z.enum(["id", "content"]);
// id: for searching smaller columns like IDs, types, and other metadata
@@ -0,0 +1,13 @@
/**
* Shared table names used across batch operations (exports, actions, etc.)
* This enum provides a centralized definition of database table names
* to avoid coupling between different batch operation types.
*/
export enum BatchTableNames {
Scores = "scores",
Sessions = "sessions",
Traces = "traces",
Observations = "observations",
DatasetRunItems = "dataset_run_items",
AuditLogs = "audit_logs",
}
+2 -1
View File
@@ -1,4 +1,4 @@
import z from "zod";
import z from "zod/v4";
import { Plan, plans } from "../../features/entitlements/plans";
import { CloudConfigRateLimit } from "../../interfaces/rate-limits";
import { ApiKeyScope } from "../../";
@@ -55,4 +55,5 @@ export type ApiAccessScope = {
plan: Plan;
rateLimitOverrides: z.infer<typeof CloudConfigRateLimit>;
apiKeyId: string;
publicKey: string;
};
@@ -45,9 +45,9 @@ export class ClickHouseClientManager {
database: env.CLICKHOUSE_DB,
http_headers: opts?.http_headers,
settings: opts?.clickhouse_settings,
request_timeout: opts?.request_timeout ?? 30000,
// Include any other relevant config options
};
return JSON.stringify(keyParams);
}
@@ -60,7 +60,6 @@ export class ClickHouseClientManager {
opts: NodeClickHouseClientConfigOptions,
): ClickhouseClientType {
const key = this.generateClientSettingsKey(opts);
if (!this.clientMap.has(key)) {
const headers = opts?.http_headers ?? {};
const activeSpan = getCurrentSpan();
@@ -84,12 +83,25 @@ export class ClickHouseClientManager {
password: env.CLICKHOUSE_PASSWORD,
database: env.CLICKHOUSE_DB,
http_headers: headers,
keep_alive: {
idle_socket_ttl: env.CLICKHOUSE_KEEP_ALIVE_IDLE_SOCKET_TTL,
},
max_open_connections: env.CLICKHOUSE_MAX_OPEN_CONNECTIONS,
clickhouse_settings: {
...cloudOptions,
...opts.clickhouse_settings,
async_insert: 1,
wait_for_async_insert: 1, // if disabled, we won't get errors from clickhouse
...(opts.request_timeout && opts.request_timeout > 30000
? {
send_progress_in_http_headers: 1,
http_headers_progress_interval_ms: "25000", // UInt64, should be passed as a string
}
: {}),
},
...(opts.request_timeout
? { request_timeout: opts.request_timeout }
: {}),
});
this.clientMap.set(key, client);
+1 -1
View File
@@ -2,7 +2,7 @@ import { Prisma } from "@prisma/client";
import { ColumnDefinition, type TableNames } from "../tableDefinitions";
import { FilterState } from "../types";
import { filterOperators, timeFilter } from "../interfaces/filters";
import { z } from "zod";
import { z } from "zod/v4";
import { logger } from "./index";
const operatorReplacements = {
@@ -0,0 +1,44 @@
import * as opentelemetry from "@opentelemetry/api";
import type { IncomingHttpHeaders } from "http";
import { env } from "../env";
export type LangfuseContextProps = {
headers?: IncomingHttpHeaders;
userId?: string;
projectId?: string;
};
/**
* Returns a new context containing baggage entries composed from
* the supplied props (headers, userId, projectId). Existing baggage
* entries are preserved.
*/
export const contextWithLangfuseProps = (
props: LangfuseContextProps,
): opentelemetry.Context => {
const ctx = opentelemetry.context.active();
let baggage =
opentelemetry.propagation.getBaggage(ctx) ??
opentelemetry.propagation.createBaggage();
if (props.headers) {
(env.LANGFUSE_LOG_PROPAGATED_HEADERS as string[]).forEach((name) => {
const value = props.headers![name];
if (!value) return;
const strValue = Array.isArray(value) ? JSON.stringify(value) : value;
baggage = baggage.setEntry(`langfuse.header.${name}`, {
value: strValue,
});
});
}
if (props.userId) {
baggage = baggage.setEntry("langfuse.user.id", { value: props.userId });
}
if (props.projectId) {
baggage = baggage.setEntry("langfuse.project.id", {
value: props.projectId,
});
}
return opentelemetry.propagation.setBaggage(ctx, baggage);
};
+3 -1
View File
@@ -41,13 +41,14 @@ export * from "./redis/dataRetentionProcessingQueue";
export * from "./redis/coreDataS3ExportQueue";
export * from "./redis/meteringDataPostgresExportQueue";
export * from "./redis/experimentCreateQueue";
export * from "./redis/dlxRetryQueue";
export * from "./redis/dlqRetryQueue";
export * from "./auth/types";
export * from "./queues";
export * from "./orderByToPrisma";
export * from "./filterToPrisma";
export * from "./instrumentation";
export * from "./logger";
export * from "./headerPropagation";
export * from "./queries";
export * from "./repositories";
export * from "./redis/evalExecutionQueue";
@@ -55,6 +56,7 @@ export * from "./services/sessions-ui-table-service";
export * from "./services/datasets-ui-table-service";
export * from "./services/DashboardService";
export * from "./services/TableViewService";
export * from "./services/DefaultEvaluationModelService";
export * from "./data-deletion/ingestionFileDeletion";
export * from "./s3";
@@ -1,5 +1,5 @@
import { randomUUID } from "crypto";
import { z } from "zod";
import { z } from "zod/v4";
import { type Model } from "../../db";
import { env } from "../../env";
@@ -13,7 +13,6 @@ import { getClickhouseEntityType } from "../clickhouse/schemaUtils";
import {
getCurrentSpan,
instrumentAsync,
instrumentSync,
recordDistribution,
recordIncrement,
traceException,
@@ -39,6 +38,8 @@ const getS3StorageServiceClient = (bucketName: string): StorageService => {
endpoint: env.LANGFUSE_S3_EVENT_UPLOAD_ENDPOINT,
region: env.LANGFUSE_S3_EVENT_UPLOAD_REGION,
forcePathStyle: env.LANGFUSE_S3_EVENT_UPLOAD_FORCE_PATH_STYLE === "true",
awsSse: env.LANGFUSE_S3_EVENT_UPLOAD_SSE,
awsSseKmsKeyId: env.LANGFUSE_S3_EVENT_UPLOAD_SSE_KMS_KEY_ID,
});
}
return s3StorageServiceClient;
@@ -78,11 +79,13 @@ const getDelay = (delay: number | null) => {
* @param input - Batch of IngestionEventType. Will validate the types first thing and return errors if they are invalid.
* @param authCheck - AuthHeaderValidVerificationResult
* @param delay - (Optional) Delay in ms to wait before processing events in the batch.
* @param source - (Optional) Source of the events for metrics tracking (e.g., "otel", "api").
*/
export const processEventBatch = async (
input: unknown[],
authCheck: AuthHeaderValidVerificationResult,
delay: number | null = null,
source: "api" | "otel" = "api",
): Promise<{
successes: { id: string; status: number }[];
errors: {
@@ -94,8 +97,10 @@ export const processEventBatch = async (
}> => {
// add context of api call to the span
const currentSpan = getCurrentSpan();
recordIncrement("langfuse.ingestion.event", input.length);
recordDistribution("langfuse.ingestion.event_distribution", input.length);
recordIncrement("langfuse.ingestion.event", input.length, { source });
recordDistribution("langfuse.ingestion.event_distribution", input.length, {
source,
});
currentSpan?.setAttribute("langfuse.ingestion.batch_size", input.length);
currentSpan?.setAttribute(
@@ -117,19 +122,7 @@ export const processEventBatch = async (
const batch: z.infer<typeof ingestionEvent>[] = input
.flatMap((event) => {
const parsed = instrumentSync(
{ name: "ingestion-zod-parse-individual-event" },
(span) => {
const parsedBody = ingestionEvent.safeParse(event);
if (parsedBody.data?.id !== undefined) {
span.setAttribute(
"langfuse.ingestion.entity.id",
parsedBody.data.id,
);
}
return parsedBody;
},
);
const parsed = ingestionEvent.safeParse(event);
if (!parsed.success) {
validationErrors.push({
id:
@@ -236,10 +229,13 @@ export const processEventBatch = async (
throw new Error("Redis not initialized, aborting event processing");
}
const queue = IngestionQueue.getInstance();
await Promise.all(
Object.keys(sortedBatchByEventBodyId).map(async (id) =>
queue
Object.keys(sortedBatchByEventBodyId).map(async (id) => {
const eventData = sortedBatchByEventBodyId[id];
const shardingKey = `${authCheck.scope.projectId}-${eventData.eventBodyId}`;
const queue = IngestionQueue.getInstance({ shardingKey });
return queue
? queue.add(
QueueJobs.IngestionJob,
{
@@ -248,9 +244,12 @@ export const processEventBatch = async (
name: QueueJobs.IngestionJob as const,
payload: {
data: {
type: sortedBatchByEventBodyId[id].type,
eventBodyId: sortedBatchByEventBodyId[id].eventBodyId,
fileKey: sortedBatchByEventBodyId[id].key,
type: eventData.type,
eventBodyId: eventData.eventBodyId,
fileKey: eventData.key,
skipS3List:
source === "otel" &&
getClickhouseEntityType(eventData.type) === "observation",
},
authCheck: authCheck as {
validKey: true;
@@ -263,8 +262,8 @@ export const processEventBatch = async (
},
{ delay: getDelay(delay) },
)
: Promise.reject("Failed to instantiate queue"),
),
: Promise.reject("Failed to instantiate queue");
}),
);
return aggregateBatchResult(
@@ -1,5 +1,5 @@
import lodash from "lodash";
import { z } from "zod";
import { z } from "zod/v4";
import { NonEmptyString, jsonSchema } from "../../utils/zod";
import { ModelUsageUnit } from "../../constants";
@@ -20,7 +20,7 @@ export const Usage = z.object({
input: z.number().int().nullish(),
output: z.number().int().nullish(),
total: z.number().int().nullish(),
unit: z.nativeEnum(ModelUsageUnit).nullish(),
unit: z.enum(ModelUsageUnit).nullish(),
inputCost: z.number().nullish(),
outputCost: z.number().nullish(),
totalCost: z.number().nullish(),
@@ -30,7 +30,7 @@ const MixedUsage = z.object({
input: z.number().int().nullish(),
output: z.number().int().nullish(),
total: z.number().int().nullish(),
unit: z.nativeEnum(ModelUsageUnit).nullish(),
unit: z.enum(ModelUsageUnit).nullish(),
promptTokens: z.number().int().nullish(),
completionTokens: z.number().int().nullish(),
totalTokens: z.number().int().nullish(),
@@ -128,8 +128,7 @@ const OpenAICompletionUsageSchema = z
}
return result;
})
.pipe(RawUsageDetails);
});
// The new OpenAI Response API uses a new Usage schema that departs from the Completion API Usage schema
const OpenAIResponseUsageSchema = z
@@ -184,8 +183,7 @@ const OpenAIResponseUsageSchema = z
}
return result;
})
.pipe(RawUsageDetails);
});
export const UsageDetails = z
.union([
@@ -266,7 +264,7 @@ export const CreateGenerationBody = CreateSpanBody.extend({
z.number(),
z.boolean(),
z.array(z.string()),
z.record(z.string()),
z.record(z.string(), z.string()),
])
.nullish(),
)
@@ -296,7 +294,7 @@ export const UpdateGenerationBody = UpdateSpanBody.extend({
z.number(),
z.boolean(),
z.array(z.string()),
z.record(z.string()),
z.record(z.string(), z.string()),
])
.nullish(),
)
@@ -162,7 +162,7 @@ function validateConfigAgainstBody(
});
if (!rangeValidation.success) {
const errorDetails = rangeValidation.error.errors
const errorDetails = rangeValidation.error.issues
.map((error) => `${error.path.join(".")} - ${error.message}`)
.join(", ");
@@ -43,6 +43,14 @@ export async function instrumentAsync<T>(
},
activeContext,
async (span) => {
const baggage = opentelemetry.propagation.getBaggage(
opentelemetry.context.active(),
);
if (baggage) {
baggage
.getAllEntries()
.forEach(([k, v]) => span.setAttribute(k, v.value));
}
try {
const result = await callback(span);
span.end();
@@ -77,6 +85,14 @@ export function instrumentSync<T>(
},
activeContext,
(span) => {
const baggage = opentelemetry.propagation.getBaggage(
opentelemetry.context.active(),
);
if (baggage) {
baggage
.getAllEntries()
.forEach(([k, v]) => span.setAttribute(k, v.value));
}
try {
const result = callback(span);
span.end();
@@ -141,30 +157,6 @@ export const traceException = (
});
};
export const addUserToSpan = (
attributes: {
userId?: string;
projectId?: string;
email?: string;
orgId?: string;
plan?: string;
},
span?: opentelemetry.Span,
) => {
const activeSpan = span ?? getCurrentSpan();
if (!activeSpan) {
return;
}
attributes.userId && activeSpan.setAttribute("user.id", attributes.userId);
attributes.email && activeSpan.setAttribute("user.email", attributes.email);
attributes.projectId &&
activeSpan.setAttribute("project.id", attributes.projectId);
attributes.orgId && activeSpan.setAttribute("org.id", attributes.orgId);
attributes.plan && activeSpan.setAttribute("org.plan", attributes.plan);
};
export const getTracer = (name: string) => opentelemetry.trace.getTracer(name);
const cloudWatchClient = new CloudWatchClient();
@@ -1,4 +1,4 @@
import { type ZodSchema } from "zod";
import { type ZodSchema } from "zod/v4";
import { ChatAnthropic } from "@langchain/anthropic";
import { ChatVertexAI } from "@langchain/google-vertexai";
@@ -16,7 +16,7 @@ import {
StringOutputParser,
} from "@langchain/core/output_parsers";
import { IterableReadableStream } from "@langchain/core/utils/stream";
import { ChatOpenAI } from "@langchain/openai";
import { ChatOpenAI, AzureChatOpenAI } from "@langchain/openai";
import GCPServiceAccountKeySchema, {
BedrockConfigSchema,
BedrockCredentialSchema,
@@ -219,7 +219,7 @@ export async function fetchLLMCompletion(
timeout: 1000 * 60 * 2, // 2 minutes timeout
});
} else if (modelParams.adapter === LLMAdapter.Azure) {
chatModel = new ChatOpenAI({
chatModel = new AzureChatOpenAI({
azureOpenAIApiKey: apiKey,
azureOpenAIBasePath: baseURL,
azureOpenAIApiDeploymentName: modelParams.model,
+17 -7
View File
@@ -1,5 +1,5 @@
import { LlmApiKeys } from "@prisma/client";
import z from "zod";
import z from "zod/v4";
import { BedrockConfigSchema } from "../../interfaces/customLLMProviderConfigSchemas";
import { TokenCountDelegate } from "../ingestion/processEventBatch";
import { AuthHeaderValidVerificationResult } from "../auth/types";
@@ -28,7 +28,7 @@ export const JSONSchemaFormSchema = z
z
.object({
type: z.literal("object"),
properties: z.record(z.any()),
properties: z.record(z.string(), z.any()),
required: z.array(z.string()).optional(),
additionalProperties: z.boolean().optional(),
})
@@ -71,7 +71,13 @@ export const OpenAIToolCallSchema = z.object({
z.record(z.string(), z.unknown()),
z
.string()
.transform((v) => JSON.parse(v))
.transform((v) => {
try {
return JSON.parse(v);
} catch {
return v;
}
})
.pipe(z.record(z.string(), z.unknown())),
]),
}),
@@ -162,7 +168,7 @@ export const ToolResultMessageSchema = z.object({
});
export type ToolResultMessage = z.infer<typeof ToolResultMessageSchema>;
export const ChatMessageDefaultRoleSchema = z.nativeEnum(ChatMessageRole);
export const ChatMessageDefaultRoleSchema = z.enum(ChatMessageRole);
export const ChatMessageSchema = z.union([
SystemMessageSchema,
DeveloperMessageSchema,
@@ -297,6 +303,8 @@ export type OpenAIModel = (typeof openAIModels)[number];
// NOTE: Update docs page when changing this! https://langfuse.com/docs/playground#openai-playground--anthropic-playground
// WARNING: The first entry in the array is chosen as the default model to add LLM API keys
export const anthropicModels = [
"claude-sonnet-4-20250514",
"claude-opus-4-20250514",
"claude-3-7-sonnet-20250219",
"claude-3-5-sonnet-20241022",
"claude-3-5-sonnet-20240620",
@@ -311,7 +319,8 @@ export const anthropicModels = [
// WARNING: The first entry in the array is chosen as the default model to add LLM API keys
export const vertexAIModels = [
"gemini-2.5-pro-exp-03-25",
"gemini-2.5-pro-preview-05-06",
"gemini-2.5-flash-preview-05-20",
"gemini-2.0-pro-exp-02-05",
"gemini-2.0-flash",
"gemini-2.0-flash-001",
@@ -324,7 +333,8 @@ export const vertexAIModels = [
// WARNING: The first entry in the array is chosen as the default model to add LLM API keys. Make sure it supports top_p, max_tokens and temperature.
export const googleAIStudioModels = [
"gemini-2.5-pro-exp-03-25",
"gemini-2.5-pro-preview-05-06",
"gemini-2.5-flash-preview-05-20",
"gemini-2.0-flash",
"gemini-2.0-flash-lite-preview",
"gemini-2.0-flash-lite-preview-02-05",
@@ -360,7 +370,7 @@ export const LLMApiKeySchema = z
projectId: z.string(),
createdAt: z.date(),
updatedAt: z.date(),
adapter: z.nativeEnum(LLMAdapter),
adapter: z.enum(LLMAdapter),
provider: z.string(),
displaySecretKey: z.string(),
secretKey: z.string(),
+1 -1
View File
@@ -1,4 +1,4 @@
import { z } from "zod";
import { z } from "zod/v4";
import { decrypt } from "../../encryption";
+7
View File
@@ -1,6 +1,7 @@
import { env } from "../env";
import winston from "winston";
import { getCurrentSpan } from "./instrumentation";
import { propagation, context } from "@opentelemetry/api";
const tracingFormat = function () {
return winston.format((info) => {
@@ -13,6 +14,12 @@ const tracingFormat = function () {
info["trace_id"] = traceId;
info["span_id"] = spanId;
}
const baggage = propagation.getBaggage(context.active());
if (baggage) {
const headerObj: Record<string, string> = {};
baggage.getAllEntries().forEach(([k, v]) => (headerObj[k] = v.value));
if (Object.keys(headerObj).length) info = { ...headerObj, ...info };
}
return info;
})();
};
@@ -1,4 +1,4 @@
import { z } from "zod";
import { z } from "zod/v4";
import { Prisma } from "@prisma/client";
@@ -1,4 +1,4 @@
import z from "zod";
import z from "zod/v4";
import { singleFilter } from "../../../interfaces/filters";
import { FilterCondition } from "../../../types";
import { isValidTableName } from "../../clickhouse/schemaUtils";
@@ -1,4 +1,4 @@
import z from "zod";
import z from "zod/v4";
import { OrderByState } from "../../../interfaces/orderBy";
import { UiColumnMappings } from "../../../tableDefinitions";
import { logger } from "../../logger";

Some files were not shown because too many files have changed in this diff Show More